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());
}
}
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());
}
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());
}
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);
}
Aggregations