Search in sources :

Example 6 with SqmFromClause

use of org.hibernate.query.sqm.tree.from.SqmFromClause in project hibernate-orm by hibernate.

the class FromClauseTests method simpleJoinAssertions.

private void simpleJoinAssertions(SqmSelectStatement<?> selectStatement, SqmJoinType joinType, String rootAlias, String joinAlias) {
    final SqmFromClause fromClause = selectStatement.getQuerySpec().getFromClause();
    assertThat(fromClause, notNullValue());
    assertThat(fromClause.getRoots(), hasSize(1));
    final SqmRoot<?> sqmRoot = fromClause.getRoots().get(0);
    assertThat(sqmRoot, notNullValue());
    assertThat(sqmRoot.getExplicitAlias(), is(rootAlias));
    assertThat(sqmRoot.getJoins(), hasSize(1));
    assertThat(sqmRoot.getSqmJoins().get(0).getExplicitAlias(), is(joinAlias));
    assertThat(sqmRoot.getSqmJoins().get(0).getSqmJoinType(), is(joinType));
}
Also used : SqmFromClause(org.hibernate.query.sqm.tree.from.SqmFromClause)

Example 7 with SqmFromClause

use of org.hibernate.query.sqm.tree.from.SqmFromClause in project hibernate-orm by hibernate.

the class SemanticQueryBuilder method visitFromClause.

@Override
public SqmFromClause visitFromClause(HqlParser.FromClauseContext parserFromClause) {
    final SqmFromClause fromClause;
    if (parserFromClause == null) {
        fromClause = new SqmFromClause();
        currentQuerySpec().setFromClause(fromClause);
    } else {
        final int size = parserFromClause.getChildCount();
        // Shift 1 bit instead of division by 2
        final int estimatedSize = size >> 1;
        fromClause = new SqmFromClause(estimatedSize);
        currentQuerySpec().setFromClause(fromClause);
        for (int i = 0; i < size; i++) {
            final ParseTree parseTree = parserFromClause.getChild(i);
            if (parseTree instanceof HqlParser.EntityWithJoinsContext) {
                visitEntityWithJoins((HqlParser.EntityWithJoinsContext) parseTree);
            }
        }
    }
    return fromClause;
}
Also used : HqlParser(org.hibernate.grammars.hql.HqlParser) SqmFromClause(org.hibernate.query.sqm.tree.from.SqmFromClause) ParseTree(org.antlr.v4.runtime.tree.ParseTree)

Example 8 with SqmFromClause

use of org.hibernate.query.sqm.tree.from.SqmFromClause in project hibernate-orm by hibernate.

the class SemanticQueryBuilder method visitEntityWithJoins.

@Override
public SqmRoot<?> visitEntityWithJoins(HqlParser.EntityWithJoinsContext parserSpace) {
    final SqmRoot<?> sqmRoot = visitRootEntity((HqlParser.RootEntityContext) parserSpace.getChild(0));
    final SqmFromClause fromClause = currentQuerySpec().getFromClause();
    // Correlations are implicitly added to the from clause
    if (!(sqmRoot instanceof SqmCorrelation<?, ?>)) {
        fromClause.addRoot(sqmRoot);
    }
    final int size = parserSpace.getChildCount();
    for (int i = 1; i < size; i++) {
        final ParseTree parseTree = parserSpace.getChild(i);
        if (parseTree instanceof HqlParser.CrossJoinContext) {
            consumeCrossJoin((HqlParser.CrossJoinContext) parseTree, sqmRoot);
        } else if (parseTree instanceof HqlParser.JoinContext) {
            consumeJoin((HqlParser.JoinContext) parseTree, sqmRoot);
        } else if (parseTree instanceof HqlParser.JpaCollectionJoinContext) {
            consumeJpaCollectionJoin((HqlParser.JpaCollectionJoinContext) parseTree, sqmRoot);
        }
    }
    return sqmRoot;
}
Also used : SqmCorrelation(org.hibernate.query.sqm.tree.domain.SqmCorrelation) HqlParser(org.hibernate.grammars.hql.HqlParser) SqmFromClause(org.hibernate.query.sqm.tree.from.SqmFromClause) ParseTree(org.antlr.v4.runtime.tree.ParseTree)

Example 9 with SqmFromClause

use of org.hibernate.query.sqm.tree.from.SqmFromClause in project hibernate-orm by hibernate.

the class QualifiedJoinPredicatePathConsumer method createBasePart.

@Override
protected SemanticPathPart createBasePart() {
    return new BaseLocalSequencePart() {

        @Override
        protected void validateAsRoot(SqmFrom<?, ?> pathRoot) {
            final SqmRoot<?> root = pathRoot.findRoot();
            final SqmRoot<?> joinRoot = sqmJoin.findRoot();
            if (root != joinRoot) {
                // The root of a path within a join condition doesn't have the same root as the current join we are processing.
                // The aim of this check is to prevent uses of different "spaces" i.e. `from A a, B b join b.id = a.id` would be illegal
                SqmCreationProcessingState processingState = getCreationState().getCurrentProcessingState();
                // First, we need to find out if the current join is part of current processing query
                final SqmQuery<?> currentProcessingQuery = processingState.getProcessingQuery();
                if (currentProcessingQuery instanceof SqmSelectQuery<?>) {
                    final SqmQuerySpec<?> querySpec = ((SqmSelectQuery<?>) currentProcessingQuery).getQuerySpec();
                    final SqmFromClause fromClause = querySpec.getFromClause();
                    // then the root of the processing path must be a root of one of the parent queries
                    if (fromClause != null && fromClause.getRoots().contains(joinRoot)) {
                        // It is allowed to use correlations from the same query
                        if (!(root instanceof SqmCorrelation<?, ?>) || !fromClause.getRoots().contains(root)) {
                            validateAsRootOnParentQueryClosure(pathRoot, root, processingState.getParentProcessingState());
                        }
                        return;
                    }
                }
                // in which case the path root is allowed to occur in the current processing query as root
                if (currentProcessingQuery instanceof SqmSubQuery<?>) {
                    validateAsRootOnParentQueryClosure(pathRoot, root, processingState);
                    return;
                }
                throw new SemanticException(String.format(Locale.ROOT, "SqmQualifiedJoin predicate referred to SqmRoot [`%s`] other than the join's root [`%s`]", pathRoot.getNavigablePath().getFullPath(), sqmJoin.getNavigablePath().getFullPath()));
            }
            super.validateAsRoot(pathRoot);
        }

        private void validateAsRootOnParentQueryClosure(SqmFrom<?, ?> pathRoot, SqmRoot<?> root, SqmCreationProcessingState processingState) {
            while (processingState != null) {
                final SqmQuery<?> processingQuery = processingState.getProcessingQuery();
                if (processingQuery instanceof SqmSelectQuery<?>) {
                    final SqmQuerySpec<?> querySpec = ((SqmSelectQuery<?>) processingQuery).getQuerySpec();
                    final SqmFromClause fromClause = querySpec.getFromClause();
                    // i.e. `from A a, B b join b.id = a.id` would be illegal
                    if (fromClause != null && fromClause.getRoots().contains(root)) {
                        super.validateAsRoot(pathRoot);
                        return;
                    }
                }
                processingState = processingState.getParentProcessingState();
            }
            throw new SemanticException(String.format(Locale.ROOT, "SqmQualifiedJoin predicate referred to SqmRoot [`%s`] other than the join's root [`%s`]", pathRoot.getNavigablePath().getFullPath(), sqmJoin.getNavigablePath().getFullPath()));
        }
    };
}
Also used : SqmSelectQuery(org.hibernate.query.sqm.tree.select.SqmSelectQuery) SqmSubQuery(org.hibernate.query.sqm.tree.select.SqmSubQuery) SqmFrom(org.hibernate.query.sqm.tree.from.SqmFrom) SqmCreationProcessingState(org.hibernate.query.hql.spi.SqmCreationProcessingState) SqmFromClause(org.hibernate.query.sqm.tree.from.SqmFromClause) SqmRoot(org.hibernate.query.sqm.tree.from.SqmRoot) SemanticException(org.hibernate.query.SemanticException)

Example 10 with SqmFromClause

use of org.hibernate.query.sqm.tree.from.SqmFromClause in project hibernate-orm by hibernate.

the class SemanticQueryBuilder method createCollectionReferenceSubQuery.

private <X> SqmSubQuery<X> createCollectionReferenceSubQuery(HqlParser.SimplePathContext pathCtx, TerminalNode collectionReferenceCtx) {
    final SqmPath<?> pluralAttributePath = consumeDomainPath(pathCtx);
    final SqmPathSource<?> referencedPathSource = pluralAttributePath.getReferencedPathSource();
    if (!(referencedPathSource instanceof PluralPersistentAttribute)) {
        throw new PathException("Path is not a plural path '" + pluralAttributePath.getNavigablePath() + "'");
    }
    final SqmSubQuery<?> subQuery = new SqmSubQuery<>(processingStateStack.getCurrent().getProcessingQuery(), creationContext.getNodeBuilder());
    final SqmSelectClause selectClause = new SqmSelectClause(false, 1, creationContext.getNodeBuilder());
    final SqmFromClause fromClause = new SqmFromClause(1);
    SqmPath<?> lhs = pluralAttributePath.getLhs();
    final List<String> implicitJoinPaths = new ArrayList<>();
    while (!(lhs instanceof AbstractSqmFrom<?, ?>)) {
        implicitJoinPaths.add(lhs.getNavigablePath().getUnaliasedLocalName());
        lhs = lhs.getLhs();
    }
    final AbstractSqmFrom<?, ?> correlationBase = (AbstractSqmFrom<?, ?>) lhs;
    final SqmCorrelation<?, ?> correlation = correlationBase.createCorrelation();
    SqmFrom<?, ?> joinBase = correlation;
    for (int i = implicitJoinPaths.size() - 1; i >= 0; i--) {
        joinBase = joinBase.join(implicitJoinPaths.get(i));
    }
    final SqmAttributeJoin<?, ?> collectionJoin = joinBase.join(pluralAttributePath.getNavigablePath().getUnaliasedLocalName());
    fromClause.addRoot(correlation.getCorrelatedRoot());
    if (collectionReferenceCtx == null) {
        final SqmLiteral<Integer> literal = new SqmLiteral<>(1, creationContext.getNodeBuilder().getIntegerType(), creationContext.getNodeBuilder());
        subQuery.applyInferableType(literal.getNodeType());
        selectClause.setSelection(literal);
    } else {
        final String partName;
        switch(collectionReferenceCtx.getSymbol().getType()) {
            case HqlParser.ELEMENTS:
                partName = CollectionPart.Nature.ELEMENT.getName();
                break;
            case HqlParser.INDICES:
                partName = CollectionPart.Nature.INDEX.getName();
                break;
            default:
                throw new ParsingException("Unexpected collection reference : " + collectionReferenceCtx.getText());
        }
        final SqmPath<?> path = collectionJoin.resolvePathPart(partName, true, this);
        subQuery.applyInferableType(path.getNodeType());
        selectClause.setSelection(path);
    }
    final SqmQuerySpec<?> querySpec = subQuery.getQuerySpec();
    querySpec.setFromClause(fromClause);
    querySpec.setSelectClause(selectClause);
    // noinspection unchecked
    return (SqmSubQuery<X>) subQuery;
}
Also used : SqmSubQuery(org.hibernate.query.sqm.tree.select.SqmSubQuery) PluralPersistentAttribute(org.hibernate.metamodel.model.domain.PluralPersistentAttribute) SqmSelectClause(org.hibernate.query.sqm.tree.select.SqmSelectClause) ArrayList(java.util.ArrayList) AbstractSqmFrom(org.hibernate.query.sqm.tree.domain.AbstractSqmFrom) PathException(org.hibernate.query.PathException) BigInteger(java.math.BigInteger) ParsingException(org.hibernate.query.sqm.ParsingException) SqmFromClause(org.hibernate.query.sqm.tree.from.SqmFromClause) SqmLiteral(org.hibernate.query.sqm.tree.expression.SqmLiteral)

Aggregations

SqmFromClause (org.hibernate.query.sqm.tree.from.SqmFromClause)13 BaseSqmUnitTest (org.hibernate.orm.test.query.sqm.BaseSqmUnitTest)7 Test (org.junit.jupiter.api.Test)7 CoreMatchers.containsString (org.hamcrest.CoreMatchers.containsString)3 SqmRoot (org.hibernate.query.sqm.tree.from.SqmRoot)3 ParseTree (org.antlr.v4.runtime.tree.ParseTree)2 HqlParser (org.hibernate.grammars.hql.HqlParser)2 SqmCorrelation (org.hibernate.query.sqm.tree.domain.SqmCorrelation)2 SqmSubQuery (org.hibernate.query.sqm.tree.select.SqmSubQuery)2 CollectionJoin (jakarta.persistence.criteria.CollectionJoin)1 Join (jakarta.persistence.criteria.Join)1 ListJoin (jakarta.persistence.criteria.ListJoin)1 MapJoin (jakarta.persistence.criteria.MapJoin)1 PluralJoin (jakarta.persistence.criteria.PluralJoin)1 SetJoin (jakarta.persistence.criteria.SetJoin)1 BigInteger (java.math.BigInteger)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 PluralPersistentAttribute (org.hibernate.metamodel.model.domain.PluralPersistentAttribute)1 PathException (org.hibernate.query.PathException)1