Search in sources :

Example 1 with SqmAttributeJoin

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

the class SemanticQueryBuilder method consumeJoin.

protected <X> void consumeJoin(HqlParser.JoinContext parserJoin, SqmRoot<X> sqmRoot) {
    final SqmJoinType joinType;
    final int firstJoinTypeSymbolType;
    if (parserJoin.getChild(0) instanceof HqlParser.JoinTypeContext && parserJoin.getChild(0).getChildCount() != 0) {
        firstJoinTypeSymbolType = ((TerminalNode) parserJoin.getChild(0).getChild(0)).getSymbol().getType();
    } else {
        firstJoinTypeSymbolType = HqlParser.INNER;
    }
    switch(firstJoinTypeSymbolType) {
        case HqlParser.FULL:
            joinType = SqmJoinType.FULL;
            break;
        case HqlParser.RIGHT:
            joinType = SqmJoinType.RIGHT;
            break;
        // For some reason, we also support `outer join` syntax..
        case HqlParser.OUTER:
        case HqlParser.LEFT:
            joinType = SqmJoinType.LEFT;
            break;
        default:
            joinType = SqmJoinType.INNER;
            break;
    }
    final HqlParser.JoinPathContext qualifiedJoinPathContext = parserJoin.joinPath();
    final HqlParser.VariableContext identificationVariableDefContext;
    if (qualifiedJoinPathContext.getChildCount() > 1) {
        identificationVariableDefContext = (HqlParser.VariableContext) qualifiedJoinPathContext.getChild(1);
    } else {
        identificationVariableDefContext = null;
    }
    final String alias = visitVariable(identificationVariableDefContext);
    final boolean fetch = parserJoin.getChild(2) instanceof TerminalNode;
    if (fetch && processingStateStack.depth() > 1) {
        throw new SemanticException("fetch not allowed in subquery from-elements");
    }
    dotIdentifierConsumerStack.push(new QualifiedJoinPathConsumer(sqmRoot, joinType, fetch, alias, this));
    try {
        // noinspection unchecked
        final SqmQualifiedJoin<X, ?> join = (SqmQualifiedJoin<X, ?>) qualifiedJoinPathContext.getChild(0).accept(this);
        final HqlParser.JoinRestrictionContext qualifiedJoinRestrictionContext = parserJoin.joinRestriction();
        if (join instanceof SqmEntityJoin<?>) {
            sqmRoot.addSqmJoin(join);
        } else if (join instanceof SqmAttributeJoin<?, ?>) {
            final SqmAttributeJoin<?, ?> attributeJoin = (SqmAttributeJoin<?, ?>) join;
            if (getCreationOptions().useStrictJpaCompliance()) {
                if (join.getExplicitAlias() != null) {
                    if (attributeJoin.isFetched()) {
                        throw new StrictJpaComplianceViolation("Encountered aliased fetch join, but strict JPQL compliance was requested", StrictJpaComplianceViolation.Type.ALIASED_FETCH_JOIN);
                    }
                }
            }
            if (qualifiedJoinRestrictionContext != null && attributeJoin.isFetched()) {
                throw new SemanticException("with-clause not allowed on fetched associations; use filters");
            }
        }
        if (qualifiedJoinRestrictionContext != null) {
            dotIdentifierConsumerStack.push(new QualifiedJoinPredicatePathConsumer(join, this));
            try {
                join.setJoinPredicate((SqmPredicate) qualifiedJoinRestrictionContext.getChild(1).accept(this));
            } finally {
                dotIdentifierConsumerStack.pop();
            }
        }
    } finally {
        dotIdentifierConsumerStack.pop();
    }
}
Also used : SqmQualifiedJoin(org.hibernate.query.sqm.tree.from.SqmQualifiedJoin) SqmEntityJoin(org.hibernate.query.sqm.tree.from.SqmEntityJoin) SqmJoinType(org.hibernate.query.sqm.tree.SqmJoinType) HqlParser(org.hibernate.grammars.hql.HqlParser) SqmAttributeJoin(org.hibernate.query.sqm.tree.from.SqmAttributeJoin) StrictJpaComplianceViolation(org.hibernate.query.sqm.StrictJpaComplianceViolation) TerminalNode(org.antlr.v4.runtime.tree.TerminalNode) SemanticException(org.hibernate.query.SemanticException)

Example 2 with SqmAttributeJoin

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

the class AbstractSqmFrom method resolvePathPart.

@Override
public SqmPath<?> resolvePathPart(String name, boolean isTerminal, SqmCreationState creationState) {
    // Try to resolve an existing attribute join without ON clause
    SqmPath<?> resolvedPath = null;
    ModelPartContainer modelPartContainer = null;
    for (SqmJoin<?, ?> sqmJoin : getSqmJoins()) {
        // We can only match singular joins here, as plural path parts are interpreted like sub-queries
        if (sqmJoin instanceof SqmSingularJoin<?, ?> && name.equals(sqmJoin.getReferencedPathSource().getPathName())) {
            final SqmAttributeJoin<?, ?> attributeJoin = (SqmAttributeJoin<?, ?>) sqmJoin;
            if (attributeJoin.getOn() == null) {
                // todo (6.0): to match the expectation of the JPA spec I think we also have to check
                // that the join type is INNER or the default join type for the attribute,
                // but as far as I understand, in 5.x we expect to ignore this behavior
                // if ( attributeJoin.getSqmJoinType() != SqmJoinType.INNER ) {
                // if ( attributeJoin.getAttribute().isCollection() ) {
                // continue;
                // }
                // if ( modelPartContainer == null ) {
                // modelPartContainer = findModelPartContainer( attributeJoin, creationState );
                // }
                // final TableGroupJoinProducer joinProducer = (TableGroupJoinProducer) modelPartContainer.findSubPart(
                // name,
                // null
                // );
                // if ( attributeJoin.getSqmJoinType().getCorrespondingSqlJoinType() != joinProducer.getDefaultSqlAstJoinType( null ) ) {
                // continue;
                // }
                // }
                resolvedPath = sqmJoin;
                if (attributeJoin.isFetched()) {
                    break;
                }
            }
        }
    }
    if (resolvedPath != null) {
        return resolvedPath;
    }
    final SqmPath<?> sqmPath = get(name);
    creationState.getProcessingStateStack().getCurrent().getPathRegistry().register(sqmPath);
    return sqmPath;
}
Also used : SqmAttributeJoin(org.hibernate.query.sqm.tree.from.SqmAttributeJoin) ModelPartContainer(org.hibernate.metamodel.mapping.ModelPartContainer)

Aggregations

SqmAttributeJoin (org.hibernate.query.sqm.tree.from.SqmAttributeJoin)2 TerminalNode (org.antlr.v4.runtime.tree.TerminalNode)1 HqlParser (org.hibernate.grammars.hql.HqlParser)1 ModelPartContainer (org.hibernate.metamodel.mapping.ModelPartContainer)1 SemanticException (org.hibernate.query.SemanticException)1 StrictJpaComplianceViolation (org.hibernate.query.sqm.StrictJpaComplianceViolation)1 SqmJoinType (org.hibernate.query.sqm.tree.SqmJoinType)1 SqmEntityJoin (org.hibernate.query.sqm.tree.from.SqmEntityJoin)1 SqmQualifiedJoin (org.hibernate.query.sqm.tree.from.SqmQualifiedJoin)1