Search in sources :

Example 1 with ComparisonOperator

use of org.hibernate.query.sqm.ComparisonOperator in project hibernate-orm by hibernate.

the class AbstractSqlAstTranslator method visitRelationalPredicate.

@Override
public void visitRelationalPredicate(ComparisonPredicate comparisonPredicate) {
    // todo (6.0) : do we want to allow multi-valued parameters in a relational predicate?
    // yes means we'd have to support dynamically converting this predicate into
    // an IN predicate or an OR predicate
    // 
    // NOTE: JPA does not define support for multi-valued parameters here.
    // 
    // If we decide to support that ^^  we should validate that *both* sides of the
    // predicate are multi-valued parameters.  because...
    // well... its stupid :)
    final SqlTuple lhsTuple;
    final SqlTuple rhsTuple;
    if ((lhsTuple = SqlTupleContainer.getSqlTuple(comparisonPredicate.getLeftHandExpression())) != null) {
        final Expression rhsExpression = comparisonPredicate.getRightHandExpression();
        final boolean all;
        final QueryPart subquery;
        // Handle emulation of quantified comparison
        if (rhsExpression instanceof QueryPart) {
            subquery = (QueryPart) rhsExpression;
            all = true;
        } else if (rhsExpression instanceof Every) {
            subquery = ((Every) rhsExpression).getSubquery();
            all = true;
        } else if (rhsExpression instanceof Any) {
            subquery = ((Any) rhsExpression).getSubquery();
            all = false;
        } else {
            subquery = null;
            all = false;
        }
        final ComparisonOperator operator = comparisonPredicate.getOperator();
        if (lhsTuple.getExpressions().size() == 1) {
            // Special case for tuples with arity 1 as any DBMS supports scalar IN predicates
            if (subquery == null) {
                renderComparison(lhsTuple.getExpressions().get(0), operator, SqlTupleContainer.getSqlTuple(comparisonPredicate.getRightHandExpression()).getExpressions().get(0));
            } else {
                renderComparison(lhsTuple.getExpressions().get(0), operator, rhsExpression);
            }
        } else if (subquery != null && !supportsRowValueConstructorSyntaxInQuantifiedPredicates()) {
            // For quantified relational comparisons, we can do an optimized emulation
            if (supportsRowValueConstructorSyntax() && all) {
                switch(operator) {
                    case LESS_THAN:
                    case LESS_THAN_OR_EQUAL:
                    case GREATER_THAN:
                    case GREATER_THAN_OR_EQUAL:
                        {
                            emulateQuantifiedTupleSubQueryPredicate(comparisonPredicate, subquery, lhsTuple, operator);
                            return;
                        }
                }
            }
            emulateSubQueryRelationalRestrictionPredicate(comparisonPredicate, all, subquery, lhsTuple, this::renderSelectTupleComparison, all ? operator.negated() : operator);
        } else if (!supportsRowValueConstructorSyntax()) {
            rhsTuple = SqlTupleContainer.getSqlTuple(rhsExpression);
            assert rhsTuple != null;
            // Some DBs like Oracle support tuples only for the IN subquery predicate
            if ((operator == ComparisonOperator.EQUAL || operator == ComparisonOperator.NOT_EQUAL) && supportsRowValueConstructorSyntaxInInSubQuery()) {
                comparisonPredicate.getLeftHandExpression().accept(this);
                if (operator == ComparisonOperator.NOT_EQUAL) {
                    appendSql(" not");
                }
                appendSql(" in(");
                renderExpressionsAsSubquery(rhsTuple.getExpressions());
                appendSql(CLOSE_PARENTHESIS);
            } else {
                emulateTupleComparison(lhsTuple.getExpressions(), rhsTuple.getExpressions(), operator, true);
            }
        } else {
            renderComparison(comparisonPredicate.getLeftHandExpression(), operator, rhsExpression);
        }
    } else if ((rhsTuple = SqlTupleContainer.getSqlTuple(comparisonPredicate.getRightHandExpression())) != null) {
        final Expression lhsExpression = comparisonPredicate.getLeftHandExpression();
        if (lhsExpression instanceof QueryGroup) {
            if (rhsTuple.getExpressions().size() == 1) {
                // Special case for tuples with arity 1 as any DBMS supports scalar IN predicates
                renderComparison(lhsExpression, comparisonPredicate.getOperator(), rhsTuple.getExpressions().get(0));
            } else if (supportsRowValueConstructorSyntax()) {
                renderComparison(lhsExpression, comparisonPredicate.getOperator(), comparisonPredicate.getRightHandExpression());
            } else {
                emulateSubQueryRelationalRestrictionPredicate(comparisonPredicate, false, (QueryGroup) lhsExpression, rhsTuple, this::renderSelectTupleComparison, // Since we switch the order of operands, we have to invert the operator
                comparisonPredicate.getOperator().invert());
            }
        } else {
            throw new IllegalStateException("Unsupported tuple comparison combination. LHS is neither a tuple nor a tuple subquery but RHS is a tuple: " + comparisonPredicate);
        }
    } else {
        renderComparison(comparisonPredicate.getLeftHandExpression(), comparisonPredicate.getOperator(), comparisonPredicate.getRightHandExpression());
    }
}
Also used : ComparisonOperator(org.hibernate.query.sqm.ComparisonOperator) Expression(org.hibernate.sql.ast.tree.expression.Expression) BinaryArithmeticExpression(org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression) SelfRenderingExpression(org.hibernate.sql.ast.tree.expression.SelfRenderingExpression) OrderedSetAggregateFunctionExpression(org.hibernate.sql.ast.tree.expression.OrderedSetAggregateFunctionExpression) CaseSimpleExpression(org.hibernate.sql.ast.tree.expression.CaseSimpleExpression) SqlSelectionExpression(org.hibernate.sql.ast.tree.expression.SqlSelectionExpression) CaseSearchedExpression(org.hibernate.sql.ast.tree.expression.CaseSearchedExpression) ModifiedSubQueryExpression(org.hibernate.sql.ast.tree.expression.ModifiedSubQueryExpression) QueryPart(org.hibernate.sql.ast.tree.select.QueryPart) Every(org.hibernate.sql.ast.tree.expression.Every) SqlTuple(org.hibernate.sql.ast.tree.expression.SqlTuple) Any(org.hibernate.sql.ast.tree.expression.Any) QueryGroup(org.hibernate.sql.ast.tree.select.QueryGroup)

Example 2 with ComparisonOperator

use of org.hibernate.query.sqm.ComparisonOperator in project hibernate-orm by hibernate.

the class SemanticQueryBuilder method visitComparisonPredicate.

@Override
public SqmPredicate visitComparisonPredicate(HqlParser.ComparisonPredicateContext ctx) {
    final ComparisonOperator comparisonOperator = (ComparisonOperator) ctx.getChild(1).accept(this);
    final SqmExpression<?> left;
    final SqmExpression<?> right;
    final HqlParser.ExpressionContext leftExpressionContext = (HqlParser.ExpressionContext) ctx.getChild(0);
    final HqlParser.ExpressionContext rightExpressionContext = (HqlParser.ExpressionContext) ctx.getChild(2);
    switch(comparisonOperator) {
        case EQUAL:
        case NOT_EQUAL:
        case DISTINCT_FROM:
        case NOT_DISTINCT_FROM:
            {
                Map<Class<?>, Enum<?>> possibleEnumValues;
                if ((possibleEnumValues = getPossibleEnumValues(leftExpressionContext)) != null) {
                    right = (SqmExpression<?>) rightExpressionContext.accept(this);
                    left = resolveEnumShorthandLiteral(leftExpressionContext, possibleEnumValues, right.getJavaType());
                    break;
                } else if ((possibleEnumValues = getPossibleEnumValues(rightExpressionContext)) != null) {
                    left = (SqmExpression<?>) leftExpressionContext.accept(this);
                    right = resolveEnumShorthandLiteral(rightExpressionContext, possibleEnumValues, left.getJavaType());
                    break;
                }
                left = (SqmExpression<?>) leftExpressionContext.accept(this);
                right = (SqmExpression<?>) rightExpressionContext.accept(this);
                // This is something that we used to support before 6 which is also used in our testsuite
                if (left instanceof SqmLiteralNull<?>) {
                    return new SqmNullnessPredicate(right, comparisonOperator == ComparisonOperator.NOT_EQUAL || comparisonOperator == ComparisonOperator.DISTINCT_FROM, creationContext.getNodeBuilder());
                } else if (right instanceof SqmLiteralNull<?>) {
                    return new SqmNullnessPredicate(left, comparisonOperator == ComparisonOperator.NOT_EQUAL || comparisonOperator == ComparisonOperator.DISTINCT_FROM, creationContext.getNodeBuilder());
                }
                break;
            }
        default:
            {
                left = (SqmExpression<?>) leftExpressionContext.accept(this);
                right = (SqmExpression<?>) rightExpressionContext.accept(this);
                break;
            }
    }
    return new SqmComparisonPredicate(left, comparisonOperator, right, creationContext.getNodeBuilder());
}
Also used : ComparisonOperator(org.hibernate.query.sqm.ComparisonOperator) SqmNullnessPredicate(org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate) SqmExpression(org.hibernate.query.sqm.tree.expression.SqmExpression) SqmLiteralNull(org.hibernate.query.sqm.tree.expression.SqmLiteralNull) HqlParser(org.hibernate.grammars.hql.HqlParser) SqmComparisonPredicate(org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate) Map(java.util.Map)

Example 3 with ComparisonOperator

use of org.hibernate.query.sqm.ComparisonOperator in project hibernate-orm by hibernate.

the class BaseSqmToSqlAstConverter method visitComparisonPredicate.

@Override
public ComparisonPredicate visitComparisonPredicate(SqmComparisonPredicate predicate) {
    final FromClauseIndex fromClauseIndex = fromClauseIndexStack.getCurrent();
    inferrableTypeAccessStack.push(() -> determineValueMapping(predicate.getRightHandExpression(), fromClauseIndex));
    final Expression lhs;
    try {
        lhs = (Expression) predicate.getLeftHandExpression().accept(this);
    } finally {
        inferrableTypeAccessStack.pop();
    }
    inferrableTypeAccessStack.push(() -> determineValueMapping(predicate.getLeftHandExpression(), fromClauseIndex));
    final Expression rhs;
    try {
        rhs = (Expression) predicate.getRightHandExpression().accept(this);
    } finally {
        inferrableTypeAccessStack.pop();
    }
    ComparisonOperator sqmOperator = predicate.getSqmOperator();
    if (predicate.isNegated()) {
        sqmOperator = sqmOperator.negated();
    }
    return new ComparisonPredicate(lhs, sqmOperator, rhs, getBooleanType());
}
Also used : ComparisonOperator(org.hibernate.query.sqm.ComparisonOperator) BinaryArithmeticExpression(org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression) SqmModifiedSubQueryExpression(org.hibernate.query.sqm.tree.expression.SqmModifiedSubQueryExpression) SelfRenderingFunctionSqlAstExpression(org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression) SelfRenderingAggregateFunctionSqlAstExpression(org.hibernate.query.sqm.function.SelfRenderingAggregateFunctionSqlAstExpression) CaseSearchedExpression(org.hibernate.sql.ast.tree.expression.CaseSearchedExpression) SelfRenderingSqlFragmentExpression(org.hibernate.sql.ast.tree.expression.SelfRenderingSqlFragmentExpression) Expression(org.hibernate.sql.ast.tree.expression.Expression) SelfRenderingExpression(org.hibernate.sql.ast.tree.expression.SelfRenderingExpression) SqmExpression(org.hibernate.query.sqm.tree.expression.SqmExpression) CaseSimpleExpression(org.hibernate.sql.ast.tree.expression.CaseSimpleExpression) SqlSelectionExpression(org.hibernate.sql.ast.tree.expression.SqlSelectionExpression) ModifiedSubQueryExpression(org.hibernate.sql.ast.tree.expression.ModifiedSubQueryExpression) SqmComparisonPredicate(org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate) ComparisonPredicate(org.hibernate.sql.ast.tree.predicate.ComparisonPredicate)

Example 4 with ComparisonOperator

use of org.hibernate.query.sqm.ComparisonOperator in project hibernate-orm by hibernate.

the class AbstractSqlAstTranslator method visitInListPredicate.

@Override
public void visitInListPredicate(InListPredicate inListPredicate) {
    final List<Expression> listExpressions = inListPredicate.getListExpressions();
    if (listExpressions.isEmpty()) {
        appendSql("1=0");
        return;
    }
    Function<Expression, Expression> itemAccessor = Function.identity();
    final SqlTuple lhsTuple;
    if ((lhsTuple = SqlTupleContainer.getSqlTuple(inListPredicate.getTestExpression())) != null) {
        if (lhsTuple.getExpressions().size() == 1) {
            // Special case for tuples with arity 1 as any DBMS supports scalar IN predicates
            itemAccessor = listExpression -> SqlTupleContainer.getSqlTuple(listExpression).getExpressions().get(0);
        } else if (!supportsRowValueConstructorSyntaxInInList()) {
            final ComparisonOperator comparisonOperator = inListPredicate.isNegated() ? ComparisonOperator.NOT_EQUAL : ComparisonOperator.EQUAL;
            // Some DBs like Oracle support tuples only for the IN subquery predicate
            if (supportsRowValueConstructorSyntaxInInSubQuery() && getDialect().supportsUnionAll()) {
                inListPredicate.getTestExpression().accept(this);
                if (inListPredicate.isNegated()) {
                    appendSql(" not");
                }
                appendSql(" in(");
                String separator = NO_SEPARATOR;
                for (Expression expression : listExpressions) {
                    appendSql(separator);
                    renderExpressionsAsSubquery(SqlTupleContainer.getSqlTuple(expression).getExpressions());
                    separator = " union all ";
                }
                appendSql(CLOSE_PARENTHESIS);
            } else {
                String separator = NO_SEPARATOR;
                for (Expression expression : listExpressions) {
                    appendSql(separator);
                    emulateTupleComparison(lhsTuple.getExpressions(), SqlTupleContainer.getSqlTuple(expression).getExpressions(), comparisonOperator, true);
                    separator = " or ";
                }
            }
            return;
        }
    }
    inListPredicate.getTestExpression().accept(this);
    if (inListPredicate.isNegated()) {
        appendSql(" not");
    }
    appendSql(" in(");
    String separator = NO_SEPARATOR;
    int bindValueCount = listExpressions.size();
    int bindValueMaxCount = bindValueCount;
    final Dialect dialect = getSessionFactory().getJdbcServices().getDialect();
    int inExprLimit = dialect.getInExpressionCountLimit();
    final boolean inClauseParameterPaddingEnabled = getSessionFactory().getSessionFactoryOptions().inClauseParameterPaddingEnabled() && bindValueCount > 2;
    if (inClauseParameterPaddingEnabled) {
        // bindValueCount: 1005
        // bindValuePaddingCount: 1024
        int bindValuePaddingCount = MathHelper.ceilingPowerOfTwo(bindValueCount);
        // inExprLimit: 1000
        if (inExprLimit > 0) {
            if (bindValuePaddingCount > inExprLimit) {
                // bindValuePaddingCount: 8
                if (bindValueCount < inExprLimit) {
                    bindValueMaxCount = inExprLimit;
                } else {
                    bindValueMaxCount = MathHelper.ceilingPowerOfTwo(bindValueCount % inExprLimit);
                }
            } else if (bindValueCount < bindValuePaddingCount) {
                bindValueMaxCount = bindValuePaddingCount;
            }
        } else if (bindValueCount < bindValuePaddingCount) {
            bindValueMaxCount = bindValuePaddingCount;
        }
    }
    final Iterator<Expression> iterator = listExpressions.iterator();
    int itemNumber = 0;
    while (iterator.hasNext() && (inExprLimit == 0 || itemNumber < inExprLimit)) {
        final Expression listExpression = itemAccessor.apply(iterator.next());
        appendSql(separator);
        listExpression.accept(this);
        separator = COMA_SEPARATOR;
        itemNumber++;
        // and just render through the in list expressions as they are without padding/splitting
        if (!(listExpression instanceof JdbcParameter || listExpression instanceof SqmParameterInterpretation)) {
            inExprLimit = 0;
            bindValueMaxCount = bindValueCount;
        }
    }
    if (itemNumber != inExprLimit && bindValueCount == bindValueMaxCount) {
        appendSql(CLOSE_PARENTHESIS);
        return;
    }
    if (inExprLimit > 0 && bindValueCount > inExprLimit) {
        do {
            append(") and ");
            inListPredicate.getTestExpression().accept(this);
            if (inListPredicate.isNegated()) {
                appendSql(" not");
            }
            appendSql(" in(");
            separator = NO_SEPARATOR;
            itemNumber = 0;
            while (iterator.hasNext() && itemNumber < inExprLimit) {
                final Expression listExpression = iterator.next();
                appendSql(separator);
                itemAccessor.apply(listExpression).accept(this);
                separator = COMA_SEPARATOR;
                itemNumber++;
            }
        } while (iterator.hasNext());
    }
    int i;
    if (inExprLimit > 0 && bindValueCount > inExprLimit) {
        i = bindValueCount % inExprLimit;
    } else {
        i = bindValueCount;
    }
    final Expression lastExpression = itemAccessor.apply(listExpressions.get(listExpressions.size() - 1));
    for (; i < bindValueMaxCount; i++) {
        appendSql(separator);
        lastExpression.accept(this);
        separator = COMA_SEPARATOR;
    }
    appendSql(CLOSE_PARENTHESIS);
}
Also used : ComparisonOperator(org.hibernate.query.sqm.ComparisonOperator) Expression(org.hibernate.sql.ast.tree.expression.Expression) BinaryArithmeticExpression(org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression) SelfRenderingExpression(org.hibernate.sql.ast.tree.expression.SelfRenderingExpression) OrderedSetAggregateFunctionExpression(org.hibernate.sql.ast.tree.expression.OrderedSetAggregateFunctionExpression) CaseSimpleExpression(org.hibernate.sql.ast.tree.expression.CaseSimpleExpression) SqlSelectionExpression(org.hibernate.sql.ast.tree.expression.SqlSelectionExpression) CaseSearchedExpression(org.hibernate.sql.ast.tree.expression.CaseSearchedExpression) ModifiedSubQueryExpression(org.hibernate.sql.ast.tree.expression.ModifiedSubQueryExpression) FilterJdbcParameter(org.hibernate.internal.FilterJdbcParameter) AbstractJdbcParameter(org.hibernate.sql.exec.internal.AbstractJdbcParameter) JdbcParameter(org.hibernate.sql.ast.tree.expression.JdbcParameter) SqlTypedMappingJdbcParameter(org.hibernate.sql.exec.internal.SqlTypedMappingJdbcParameter) SqmParameterInterpretation(org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation) Dialect(org.hibernate.dialect.Dialect) SqlTuple(org.hibernate.sql.ast.tree.expression.SqlTuple)

Aggregations

ComparisonOperator (org.hibernate.query.sqm.ComparisonOperator)4 BinaryArithmeticExpression (org.hibernate.sql.ast.tree.expression.BinaryArithmeticExpression)3 CaseSearchedExpression (org.hibernate.sql.ast.tree.expression.CaseSearchedExpression)3 CaseSimpleExpression (org.hibernate.sql.ast.tree.expression.CaseSimpleExpression)3 Expression (org.hibernate.sql.ast.tree.expression.Expression)3 ModifiedSubQueryExpression (org.hibernate.sql.ast.tree.expression.ModifiedSubQueryExpression)3 SelfRenderingExpression (org.hibernate.sql.ast.tree.expression.SelfRenderingExpression)3 SqlSelectionExpression (org.hibernate.sql.ast.tree.expression.SqlSelectionExpression)3 SqmExpression (org.hibernate.query.sqm.tree.expression.SqmExpression)2 SqmComparisonPredicate (org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate)2 OrderedSetAggregateFunctionExpression (org.hibernate.sql.ast.tree.expression.OrderedSetAggregateFunctionExpression)2 SqlTuple (org.hibernate.sql.ast.tree.expression.SqlTuple)2 Map (java.util.Map)1 Dialect (org.hibernate.dialect.Dialect)1 HqlParser (org.hibernate.grammars.hql.HqlParser)1 FilterJdbcParameter (org.hibernate.internal.FilterJdbcParameter)1 SelfRenderingAggregateFunctionSqlAstExpression (org.hibernate.query.sqm.function.SelfRenderingAggregateFunctionSqlAstExpression)1 SelfRenderingFunctionSqlAstExpression (org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression)1 SqmParameterInterpretation (org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation)1 SqmLiteralNull (org.hibernate.query.sqm.tree.expression.SqmLiteralNull)1