Search in sources :

Example 1 with JoinOnBuilder

use of com.blazebit.persistence.JoinOnBuilder in project blaze-persistence by Blazebit.

the class BlazeCriteriaBuilderRenderer method renderJoins.

private <X extends FromBuilder<X>> X renderJoins(QueryMetadata metadata, FromBaseBuilder<X> fromBuilder) {
    X criteriaBuilder = null;
    for (final JoinExpression joinExpression : metadata.getJoins()) {
        boolean fetch = joinExpression.hasFlag(JPAQueryMixin.FETCH);
        boolean hasCondition = joinExpression.getCondition() != null;
        Expression<?> target = joinExpression.getTarget();
        String alias = null;
        if (target instanceof Operation<?>) {
            Operation<?> operation = (Operation<?>) target;
            if (operation.getOperator() == Ops.ALIAS) {
                target = operation.getArg(0);
                alias = ((Path<?>) operation.getArg(1)).getMetadata().getName();
            }
        }
        if (target instanceof ValuesExpression<?>) {
            ValuesExpression<?> valuesExpression = (ValuesExpression<?>) target;
            Class type = valuesExpression.getRoot().getType();
            String name = valuesExpression.getAlias().getMetadata().getName();
            Collection<?> elements = valuesExpression.getElements();
            if (!valuesExpression.getMetadata().isRoot()) {
                String attribute = relativePathString(valuesExpression.getRoot(), valuesExpression);
                if (valuesExpression.isIdentifiable()) {
                    criteriaBuilder = (X) fromBuilder.fromIdentifiableValues(type, attribute, name, elements);
                } else {
                    criteriaBuilder = (X) fromBuilder.fromValues(type, attribute, name, elements);
                }
            } else if (valuesExpression.isIdentifiable()) {
                criteriaBuilder = (X) fromBuilder.fromIdentifiableValues(type, name, elements);
            } else {
                criteriaBuilder = (X) fromBuilder.fromValues(type, name, elements);
            }
        } else if (target instanceof Path<?>) {
            Path<?> entityPath = (Path<?>) target;
            boolean entityJoin = entityPath.getMetadata().isRoot();
            String renderedExpression = renderExpression(entityPath);
            // While this looks suspicious, this is actually in line with Querydsl's default behaviour in JPQLSerializer.handleJoinTarget
            if (alias == null && entityJoin) {
                alias = renderedExpression;
            }
            switch(joinExpression.getType()) {
                case DEFAULT:
                    if (fromBuilder instanceof FromBuilder) {
                        criteriaBuilder = (X) fromBuilder;
                        From from = criteriaBuilder.getFrom(alias);
                        // TODO find a clean way to detect FROM clauses that are already set by fromEntitySubquery...
                        if (from != null) {
                            if (entityPath instanceof CollectionExpressionBase<?, ?> && ((CollectionExpressionBase<?, ?>) entityPath).getElementType().equals(from.getJavaType()) || from.getJavaType().equals(entityPath.getType())) {
                                break;
                            }
                        }
                    }
                    if (entityJoin) {
                        criteriaBuilder = fromBuilder.from(entityPath.getType(), alias);
                    } else {
                        if (fromBuilder instanceof BaseSubqueryBuilder) {
                            criteriaBuilder = (X) ((BaseSubqueryBuilder<?>) fromBuilder).from(renderedExpression, alias);
                        } else if (fromBuilder instanceof SubqueryInitiator<?>) {
                            criteriaBuilder = (X) ((SubqueryInitiator<?>) fromBuilder).from(renderedExpression, alias);
                        } else {
                            throw new IllegalArgumentException(renderedExpression + "  join not supported here");
                        }
                    }
                    break;
                default:
                    JoinType joinType = getJoinType(joinExpression);
                    if (hasCondition && fetch) {
                        LOG.warning("Fetch is ignored due to on-clause");
                    }
                    if (entityJoin) {
                        if (!hasCondition) {
                            throw new IllegalStateException("No on-clause for entity join!");
                        }
                        final JoinOnBuilder<X> xJoinOnBuilder = criteriaBuilder.joinOn(entityPath.getType(), alias, joinType);
                        setExpressionSubqueries(joinExpression.getCondition(), null, xJoinOnBuilder, JoinOnBuilderExpressionSetter.INSTANCE);
                    } else if (!hasCondition) {
                        // If there is no alias, assume a default join
                        boolean defaultJoin = alias == null || joinExpression.hasFlag(AbstractBlazeJPAQuery.DEFAULT);
                        if (fetch) {
                            if (defaultJoin) {
                                ((FullQueryBuilder<?, ?>) criteriaBuilder).joinDefault(renderedExpression, alias, joinType, fetch);
                            } else {
                                ((FullQueryBuilder<?, ?>) criteriaBuilder).join(renderedExpression, alias, joinType, fetch);
                            }
                        } else {
                            if (defaultJoin) {
                                criteriaBuilder.joinDefault(renderedExpression, alias, joinType);
                            } else {
                                criteriaBuilder.join(renderedExpression, alias, joinType);
                            }
                        }
                    } else {
                        if (alias == null) {
                            throw new IllegalArgumentException("This association join requires an alias, like so: .join(" + renderedExpression + ", " + entityPath.getClass().getSimpleName() + "." + entityPath.getMetadata().getName() + ")");
                        }
                        final JoinOnBuilder<X> xJoinOnBuilder = criteriaBuilder.joinOn(renderedExpression, alias, joinType);
                        setExpressionSubqueries(joinExpression.getCondition(), null, xJoinOnBuilder, JoinOnBuilderExpressionSetter.INSTANCE);
                    }
                    break;
            }
        } else if (target instanceof SubQueryExpression) {
            switch(joinExpression.getType()) {
                case DEFAULT:
                    {
                        FullSelectCTECriteriaBuilder<X> xFullSelectCTECriteriaBuilder = fromBuilder.fromSubquery(target.getType(), alias);
                        Object o = serializeSubQuery(xFullSelectCTECriteriaBuilder, target);
                        criteriaBuilder = o instanceof FinalSetOperationCTECriteriaBuilder ? ((FinalSetOperationCTECriteriaBuilder<X>) o).end() : ((FullSelectCTECriteriaBuilder<X>) o).end();
                        break;
                    }
                default:
                    {
                        JoinType joinType = getJoinType(joinExpression);
                        boolean isLateral = joinExpression.hasFlag(AbstractBlazeJPAQuery.LATERAL);
                        if (fetch) {
                            LOG.warning("Fetch is ignored due to subquery entity join!");
                        }
                        SubQueryExpression<?> subQueryExpression = target.accept(new FirstSubqueryResolver(), null);
                        Path<?> fromPath = subQueryExpression.getMetadata().getJoins().get(0).getTarget().accept(new FirstSubqueryTargetPathResolver(), null);
                        boolean entityJoin = fromPath.getMetadata().isRoot();
                        if (hasCondition) {
                            FullSelectCTECriteriaBuilder<JoinOnBuilder<X>> joinOnBuilderFullSelectCTECriteriaBuilder;
                            if (isLateral) {
                                String subqueryAlias = subQueryExpression.getMetadata().getJoins().get(0).getTarget().accept(new JoinTargetAliasPathResolver(), null).getMetadata().getName();
                                if (entityJoin) {
                                    joinOnBuilderFullSelectCTECriteriaBuilder = criteriaBuilder.joinLateralOnSubquery(target.getType(), alias, joinType);
                                } else {
                                    joinOnBuilderFullSelectCTECriteriaBuilder = criteriaBuilder.joinLateralOnSubquery(renderExpression(fromPath), alias, subqueryAlias, joinType);
                                }
                            } else {
                                if (!entityJoin) {
                                    throw new IllegalStateException("Entity join to association");
                                }
                                joinOnBuilderFullSelectCTECriteriaBuilder = criteriaBuilder.joinOnSubquery(target.getType(), alias, joinType);
                            }
                            Object o = serializeSubQuery(joinOnBuilderFullSelectCTECriteriaBuilder, target);
                            final JoinOnBuilder<X> joinOnBuilder = o instanceof FinalSetOperationCTECriteriaBuilder ? ((FinalSetOperationCTECriteriaBuilder<JoinOnBuilder<X>>) o).end() : ((FullSelectCTECriteriaBuilder<JoinOnBuilder<X>>) o).end();
                            criteriaBuilder = (X) setExpressionSubqueries(joinExpression.getCondition(), null, joinOnBuilder, JoinOnBuilderExpressionSetter.INSTANCE);
                        } else {
                            if (isLateral) {
                                FullSelectCTECriteriaBuilder<X> xFullSelectCTECriteriaBuilder;
                                String subqueryAlias = subQueryExpression.getMetadata().getJoins().get(0).getTarget().accept(new JoinTargetAliasPathResolver(), null).getMetadata().getName();
                                if (entityJoin) {
                                    xFullSelectCTECriteriaBuilder = criteriaBuilder.joinLateralSubquery(target.getType(), alias, joinType);
                                } else {
                                    xFullSelectCTECriteriaBuilder = criteriaBuilder.joinLateralSubquery(renderExpression(fromPath), alias, subqueryAlias, joinType);
                                }
                                Object o = serializeSubQuery(xFullSelectCTECriteriaBuilder, target);
                                criteriaBuilder = o instanceof FinalSetOperationCTECriteriaBuilder ? ((FinalSetOperationCTECriteriaBuilder<X>) o).end() : ((FullSelectCTECriteriaBuilder<X>) o).end();
                            } else {
                                throw new IllegalStateException("No on-clause for subquery entity join!");
                            }
                        }
                        break;
                    }
            }
        } else {
            throw new UnsupportedOperationException("Joins for " + target + " is not yet implemented");
        }
    }
    return criteriaBuilder;
}
Also used : SubQueryExpression(com.querydsl.core.types.SubQueryExpression) FinalSetOperationCTECriteriaBuilder(com.blazebit.persistence.FinalSetOperationCTECriteriaBuilder) BaseSubqueryBuilder(com.blazebit.persistence.BaseSubqueryBuilder) Operation(com.querydsl.core.types.Operation) JoinOnBuilder(com.blazebit.persistence.JoinOnBuilder) FullQueryBuilder(com.blazebit.persistence.FullQueryBuilder) JoinExpression(com.querydsl.core.JoinExpression) Path(com.querydsl.core.types.Path) BeanPath(com.querydsl.core.types.dsl.BeanPath) SubqueryInitiator(com.blazebit.persistence.SubqueryInitiator) MultipleSubqueryInitiator(com.blazebit.persistence.MultipleSubqueryInitiator) JoinType(com.blazebit.persistence.JoinType) CollectionExpressionBase(com.querydsl.core.types.dsl.CollectionExpressionBase) From(com.blazebit.persistence.From) FullSelectCTECriteriaBuilder(com.blazebit.persistence.FullSelectCTECriteriaBuilder) FromBuilder(com.blazebit.persistence.FromBuilder)

Example 2 with JoinOnBuilder

use of com.blazebit.persistence.JoinOnBuilder in project blaze-persistence by Blazebit.

the class JoinOnBuilderImpl method onExpressionSubqueries.

@Override
public MultipleSubqueryInitiator<JoinOnBuilder<T>> onExpressionSubqueries(String expression) {
    Predicate predicate = expressionFactory.createBooleanExpression(expression, true);
    // We don't need a listener or marker here, because the resulting restriction builder can only be ended, when the initiator is ended
    MultipleSubqueryInitiator<JoinOnBuilder<T>> initiator = new MultipleSubqueryInitiatorImpl<JoinOnBuilder<T>>(this, predicate, new ExpressionBuilderEndedListener() {

        @Override
        public void onBuilderEnded(ExpressionBuilder builder) {
            rootPredicate.getPredicate().getChildren().add((Predicate) builder.getExpression());
            currentMultipleSubqueryInitiator = null;
        }
    }, subqueryInitFactory, ClauseType.JOIN);
    currentMultipleSubqueryInitiator = initiator;
    return initiator;
}
Also used : ExpressionBuilderEndedListener(com.blazebit.persistence.impl.builder.expression.ExpressionBuilderEndedListener) MultipleSubqueryInitiatorImpl(com.blazebit.persistence.impl.MultipleSubqueryInitiatorImpl) JoinOnBuilder(com.blazebit.persistence.JoinOnBuilder) ExpressionBuilder(com.blazebit.persistence.impl.builder.expression.ExpressionBuilder) Predicate(com.blazebit.persistence.parser.predicate.Predicate) CompoundPredicate(com.blazebit.persistence.parser.predicate.CompoundPredicate) ExistsPredicate(com.blazebit.persistence.parser.predicate.ExistsPredicate)

Example 3 with JoinOnBuilder

use of com.blazebit.persistence.JoinOnBuilder in project blaze-persistence by Blazebit.

the class JoinOnBuilderImpl method onSubqueries.

@Override
public MultipleSubqueryInitiator<RestrictionBuilder<JoinOnBuilder<T>>> onSubqueries(String expression) {
    Expression expr = expressionFactory.createSimpleExpression(expression, true);
    RestrictionBuilderImpl<JoinOnBuilder<T>> restrictionBuilder = startBuilder(new RestrictionBuilderImpl<JoinOnBuilder<T>>(this, this, subqueryInitFactory, expressionFactory, parameterManager, ClauseType.JOIN));
    // We don't need a listener or marker here, because the resulting restriction builder can only be ended, when the initiator is ended
    MultipleSubqueryInitiator<RestrictionBuilder<JoinOnBuilder<T>>> initiator = new MultipleSubqueryInitiatorImpl<RestrictionBuilder<JoinOnBuilder<T>>>(restrictionBuilder, expr, new RestrictionBuilderExpressionBuilderListener(restrictionBuilder), subqueryInitFactory, ClauseType.JOIN);
    return initiator;
}
Also used : Expression(com.blazebit.persistence.parser.expression.Expression) MultipleSubqueryInitiatorImpl(com.blazebit.persistence.impl.MultipleSubqueryInitiatorImpl) JoinOnBuilder(com.blazebit.persistence.JoinOnBuilder) RestrictionBuilderExpressionBuilderListener(com.blazebit.persistence.impl.RestrictionBuilderExpressionBuilderListener) RestrictionBuilder(com.blazebit.persistence.RestrictionBuilder)

Aggregations

JoinOnBuilder (com.blazebit.persistence.JoinOnBuilder)3 MultipleSubqueryInitiatorImpl (com.blazebit.persistence.impl.MultipleSubqueryInitiatorImpl)2 BaseSubqueryBuilder (com.blazebit.persistence.BaseSubqueryBuilder)1 FinalSetOperationCTECriteriaBuilder (com.blazebit.persistence.FinalSetOperationCTECriteriaBuilder)1 From (com.blazebit.persistence.From)1 FromBuilder (com.blazebit.persistence.FromBuilder)1 FullQueryBuilder (com.blazebit.persistence.FullQueryBuilder)1 FullSelectCTECriteriaBuilder (com.blazebit.persistence.FullSelectCTECriteriaBuilder)1 JoinType (com.blazebit.persistence.JoinType)1 MultipleSubqueryInitiator (com.blazebit.persistence.MultipleSubqueryInitiator)1 RestrictionBuilder (com.blazebit.persistence.RestrictionBuilder)1 SubqueryInitiator (com.blazebit.persistence.SubqueryInitiator)1 RestrictionBuilderExpressionBuilderListener (com.blazebit.persistence.impl.RestrictionBuilderExpressionBuilderListener)1 ExpressionBuilder (com.blazebit.persistence.impl.builder.expression.ExpressionBuilder)1 ExpressionBuilderEndedListener (com.blazebit.persistence.impl.builder.expression.ExpressionBuilderEndedListener)1 Expression (com.blazebit.persistence.parser.expression.Expression)1 CompoundPredicate (com.blazebit.persistence.parser.predicate.CompoundPredicate)1 ExistsPredicate (com.blazebit.persistence.parser.predicate.ExistsPredicate)1 Predicate (com.blazebit.persistence.parser.predicate.Predicate)1 JoinExpression (com.querydsl.core.JoinExpression)1