HHH-16768 - Move type compatibility validation to the comparison/between node constructors
Signed-off-by: Jan Schatteman <jschatte@redhat.com>
This commit is contained in:
parent
dd9a51a53a
commit
935ac494dd
|
@ -256,7 +256,6 @@ import static org.hibernate.query.sqm.TemporalUnit.TIMEZONE_HOUR;
|
|||
import static org.hibernate.query.sqm.TemporalUnit.TIMEZONE_MINUTE;
|
||||
import static org.hibernate.query.sqm.TemporalUnit.WEEK_OF_MONTH;
|
||||
import static org.hibernate.query.sqm.TemporalUnit.WEEK_OF_YEAR;
|
||||
import static org.hibernate.query.sqm.internal.TypecheckUtil.assertComparable;
|
||||
import static org.hibernate.type.descriptor.DateTimeUtils.DATE_TIME;
|
||||
import static org.hibernate.type.spi.TypeConfiguration.isJdbcTemporalType;
|
||||
|
||||
|
@ -2441,7 +2440,6 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
right = r;
|
||||
}
|
||||
}
|
||||
assertComparable( left, right, creationContext.getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
left,
|
||||
comparisonOperator,
|
||||
|
@ -2556,10 +2554,10 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
public SqmPredicate visitMemberOfPredicate(HqlParser.MemberOfPredicateContext ctx) {
|
||||
final boolean negated = ctx.NOT() != null;
|
||||
final SqmPath<?> sqmPluralPath = consumeDomainPath( ctx.path() );
|
||||
if ( sqmPluralPath.getReferencedPathSource() instanceof PluralPersistentAttribute ) {
|
||||
if ( sqmPluralPath instanceof SqmPluralValuedSimplePath ) {
|
||||
return new SqmMemberOfPredicate(
|
||||
(SqmExpression<?>) ctx.expression().accept( this ),
|
||||
sqmPluralPath,
|
||||
(SqmPluralValuedSimplePath<?>) sqmPluralPath,
|
||||
negated,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
|
@ -2636,7 +2634,6 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
else if ( inListContext instanceof HqlParser.SubqueryInListContext ) {
|
||||
final HqlParser.SubqueryInListContext subQueryOrParamInListContext = (HqlParser.SubqueryInListContext) inListContext;
|
||||
final SqmSubQuery<?> subquery = visitSubquery( subQueryOrParamInListContext.subquery() );
|
||||
assertComparable( testExpression, subquery, creationContext.getNodeBuilder().getSessionFactory() );
|
||||
return new SqmInSubQueryPredicate(
|
||||
testExpression,
|
||||
subquery,
|
||||
|
|
|
@ -43,12 +43,14 @@ import org.hibernate.internal.util.collections.CollectionHelper;
|
|||
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||
import org.hibernate.metamodel.model.domain.DomainType;
|
||||
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
||||
import org.hibernate.metamodel.model.domain.SimpleDomainType;
|
||||
import org.hibernate.metamodel.model.domain.internal.BasicTypeImpl;
|
||||
import org.hibernate.metamodel.model.domain.spi.JpaMetamodelImplementor;
|
||||
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
|
||||
import org.hibernate.query.BindableType;
|
||||
import org.hibernate.query.NullPrecedence;
|
||||
import org.hibernate.query.ReturnableType;
|
||||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.SortDirection;
|
||||
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
|
||||
import org.hibernate.query.criteria.JpaCoalesce;
|
||||
|
@ -2040,8 +2042,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate between(Expression<? extends Y> value, Expression<? extends Y> lower, Expression<? extends Y> upper) {
|
||||
assertComparable( value, lower, getNodeBuilder().getSessionFactory() );
|
||||
assertComparable( value, upper, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmBetweenPredicate(
|
||||
(SqmExpression<? extends Y>) value,
|
||||
(SqmExpression<? extends Y>) lower,
|
||||
|
@ -2056,8 +2056,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
final SqmExpression<? extends Y> valueExpression = (SqmExpression<? extends Y>) value;
|
||||
final SqmExpression<?> lowerExpr = value( lower, valueExpression );
|
||||
final SqmExpression<?> upperExpr = value( upper, valueExpression );
|
||||
assertComparable( valueExpression, lowerExpr, getNodeBuilder().getSessionFactory() );
|
||||
assertComparable( valueExpression, upperExpr, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmBetweenPredicate(
|
||||
valueExpression,
|
||||
lowerExpr,
|
||||
|
@ -2069,7 +2067,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public SqmPredicate equal(Expression<?> x, Expression<?> y) {
|
||||
assertComparable( x, y, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.EQUAL,
|
||||
|
@ -2081,7 +2078,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
@Override
|
||||
public SqmPredicate equal(Expression<?> x, Object y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.EQUAL,
|
||||
|
@ -2092,7 +2088,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public SqmPredicate notEqual(Expression<?> x, Expression<?> y) {
|
||||
assertComparable( x, y, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.NOT_EQUAL,
|
||||
|
@ -2104,7 +2099,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
@Override
|
||||
public SqmPredicate notEqual(Expression<?> x, Object y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.NOT_EQUAL,
|
||||
|
@ -2115,7 +2109,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public SqmPredicate distinctFrom(Expression<?> x, Expression<?> y) {
|
||||
assertComparable( x, y, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.DISTINCT_FROM,
|
||||
|
@ -2127,7 +2120,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
@Override
|
||||
public SqmPredicate distinctFrom(Expression<?> x, Object y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.DISTINCT_FROM,
|
||||
|
@ -2138,7 +2130,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public SqmPredicate notDistinctFrom(Expression<?> x, Expression<?> y) {
|
||||
assertComparable( x, y, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.NOT_DISTINCT_FROM,
|
||||
|
@ -2150,7 +2141,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
@Override
|
||||
public SqmPredicate notDistinctFrom(Expression<?> x, Object y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.NOT_DISTINCT_FROM,
|
||||
|
@ -2161,7 +2151,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate greaterThan(Expression<? extends Y> x, Expression<? extends Y> y) {
|
||||
assertComparable( x, y, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.GREATER_THAN,
|
||||
|
@ -2173,7 +2162,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
@Override
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate greaterThan(Expression<? extends Y> x, Y y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.GREATER_THAN,
|
||||
|
@ -2184,7 +2172,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate greaterThanOrEqualTo(Expression<? extends Y> x, Expression<? extends Y> y) {
|
||||
assertComparable( x, y, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.GREATER_THAN_OR_EQUAL,
|
||||
|
@ -2196,7 +2183,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
@Override
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate greaterThanOrEqualTo(Expression<? extends Y> x, Y y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.GREATER_THAN_OR_EQUAL,
|
||||
|
@ -2207,7 +2193,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate lessThan(Expression<? extends Y> x, Expression<? extends Y> y) {
|
||||
assertComparable( x, y, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.LESS_THAN,
|
||||
|
@ -2219,7 +2204,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
@Override
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate lessThan(Expression<? extends Y> x, Y y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.LESS_THAN,
|
||||
|
@ -2241,7 +2225,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
@Override
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate lessThanOrEqualTo(Expression<? extends Y> x, Y y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.LESS_THAN_OR_EQUAL,
|
||||
|
@ -2252,7 +2235,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public SqmPredicate gt(Expression<? extends Number> x, Expression<? extends Number> y) {
|
||||
assertComparable( x, y, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.GREATER_THAN,
|
||||
|
@ -2264,7 +2246,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
@Override
|
||||
public SqmPredicate gt(Expression<? extends Number> x, Number y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.GREATER_THAN,
|
||||
|
@ -2275,7 +2256,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public SqmPredicate ge(Expression<? extends Number> x, Expression<? extends Number> y) {
|
||||
assertComparable( x, y, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.GREATER_THAN_OR_EQUAL,
|
||||
|
@ -2287,7 +2267,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
@Override
|
||||
public SqmPredicate ge(Expression<? extends Number> x, Number y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.GREATER_THAN_OR_EQUAL,
|
||||
|
@ -2298,7 +2277,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public SqmPredicate lt(Expression<? extends Number> x, Expression<? extends Number> y) {
|
||||
assertComparable( x, y, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.LESS_THAN,
|
||||
|
@ -2310,7 +2288,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
@Override
|
||||
public SqmPredicate lt(Expression<? extends Number> x, Number y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.LESS_THAN,
|
||||
|
@ -2321,7 +2298,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public SqmPredicate le(Expression<? extends Number> x, Expression<? extends Number> y) {
|
||||
assertComparable( x, y, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.LESS_THAN_OR_EQUAL,
|
||||
|
@ -2333,7 +2309,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
@Override
|
||||
public SqmPredicate le(Expression<? extends Number> x, Number y) {
|
||||
final SqmExpression<?> yExpr = value( y, (SqmExpression<?>) x );
|
||||
assertComparable( x, yExpr, getNodeBuilder().getSessionFactory() );
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.LESS_THAN_OR_EQUAL,
|
||||
|
@ -2354,22 +2329,31 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
public <E, C extends Collection<E>> SqmPredicate isMember(Expression<E> elem, Expression<C> collection) {
|
||||
return new SqmMemberOfPredicate( (SqmExpression<?>) elem, (SqmPath<?>) collection, false, this );
|
||||
return createSqmMemberOfPredicate( (SqmExpression<?>) elem, (SqmPath<?>) collection, false, this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E, C extends Collection<E>> SqmPredicate isMember(E elem, Expression<C> collection) {
|
||||
return new SqmMemberOfPredicate( value( elem ), (SqmPath<?>) collection, false, this );
|
||||
return createSqmMemberOfPredicate( value( elem ), (SqmPath<?>) collection, false, this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E, C extends Collection<E>> SqmPredicate isNotMember(Expression<E> elem, Expression<C> collection) {
|
||||
return new SqmMemberOfPredicate( (SqmExpression<?>) elem, (SqmPath<?>) collection, true, this );
|
||||
return createSqmMemberOfPredicate( (SqmExpression<?>) elem, (SqmPath<?>) collection, true, this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E, C extends Collection<E>> SqmPredicate isNotMember(E elem, Expression<C> collection) {
|
||||
return new SqmMemberOfPredicate( value( elem ), (SqmPath<?>) collection, true, this );
|
||||
return createSqmMemberOfPredicate( value( elem ), (SqmPath<?>) collection, true, this );
|
||||
}
|
||||
|
||||
private SqmMemberOfPredicate createSqmMemberOfPredicate(SqmExpression<?> elem, SqmPath<?> collection, boolean negated, NodeBuilder nodeBuilder) {
|
||||
if ( collection instanceof SqmPluralValuedSimplePath ) {
|
||||
return new SqmMemberOfPredicate( elem, (SqmPluralValuedSimplePath) collection, negated, this );
|
||||
}
|
||||
else {
|
||||
throw new SemanticException( "Operand of 'member of' operator must be a plural path" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,6 +22,7 @@ import org.hibernate.query.sqm.SqmPathSource;
|
|||
import org.hibernate.query.sqm.UnaryArithmeticOperator;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteralNull;
|
||||
import org.hibernate.type.BasicType;
|
||||
|
@ -89,7 +90,7 @@ public class TypecheckUtil {
|
|||
* be done within the framework laid out below, not by adding ad-hoc special
|
||||
* rules and holes which undermine the type system. It's much more important
|
||||
* that HQL has simple, predictable, and understandable rules than it is that
|
||||
* every single user be able to do every single little wierd thing that used
|
||||
* every single user be able to do every single little weird thing that used
|
||||
* to work in Hibernate 5.
|
||||
*
|
||||
* @param lhsType the type of the expression on the LHS of the comparison operator
|
||||
|
@ -97,7 +98,7 @@ public class TypecheckUtil {
|
|||
*
|
||||
* @see #isTypeAssignable(SqmPathSource, SqmExpressible, SessionFactoryImplementor)
|
||||
*/
|
||||
private static boolean areTypesComparable(
|
||||
public static boolean areTypesComparable(
|
||||
SqmExpressible<?> lhsType, SqmExpressible<?> rhsType,
|
||||
SessionFactoryImplementor factory) {
|
||||
|
||||
|
@ -321,6 +322,13 @@ public class TypecheckUtil {
|
|||
&& left.getTupleLength().intValue() != right.getTupleLength().intValue() ) {
|
||||
throw new SemanticException( "Cannot compare tuples of different lengths" );
|
||||
}
|
||||
|
||||
// SqmMemerOfPredicate is the only one allowing multi-valued paths, its comparability is now evaluated in areTypesComparable
|
||||
// i.e. without calling this method, so we can check this here for other Predicates that do call this
|
||||
if ( left instanceof SqmPluralValuedSimplePath || right instanceof SqmPluralValuedSimplePath ) {
|
||||
throw new SemanticException( "Multi valued paths are only allowed for the member of operator" );
|
||||
}
|
||||
|
||||
// allow comparing literal null to things
|
||||
if ( !(left instanceof SqmLiteralNull) && !(right instanceof SqmLiteralNull) ) {
|
||||
final SqmExpressible<?> leftType = left.getNodeType();
|
||||
|
@ -448,6 +456,17 @@ public class TypecheckUtil {
|
|||
}
|
||||
}
|
||||
|
||||
public static void assertString(SqmExpression<?> expression) {
|
||||
final SqmExpressible<?> nodeType = expression.getNodeType();
|
||||
if ( nodeType != null ) {
|
||||
final Class<?> javaType = nodeType.getExpressibleJavaType().getJavaTypeClass();
|
||||
if ( javaType != String.class && javaType != char[].class ) {
|
||||
throw new SemanticException( "Operand of 'like' is of type '" + nodeType.getTypeName() + "' which is not a string"
|
||||
+ " (it is not an instance of 'java.lang.String' or 'char[]')" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// public static void assertNumeric(SqmExpression<?> expression, BinaryArithmeticOperator op) {
|
||||
// final SqmExpressible<?> nodeType = expression.getNodeType();
|
||||
// if ( nodeType != null ) {
|
||||
|
|
|
@ -13,6 +13,8 @@ import org.hibernate.query.sqm.SqmExpressible;
|
|||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
|
||||
import static org.hibernate.query.sqm.internal.TypecheckUtil.assertComparable;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -32,6 +34,9 @@ public class SqmBetweenPredicate extends AbstractNegatableSqmPredicate {
|
|||
this.lowerBound = lowerBound;
|
||||
this.upperBound = upperBound;
|
||||
|
||||
assertComparable( expression, lowerBound, nodeBuilder.getSessionFactory() );
|
||||
assertComparable( expression, upperBound, nodeBuilder.getSessionFactory() );
|
||||
|
||||
final SqmExpressible<?> expressibleType = QueryHelper.highestPrecedenceType(
|
||||
expression.getExpressible(),
|
||||
lowerBound.getExpressible(),
|
||||
|
|
|
@ -6,14 +6,18 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.tree.predicate;
|
||||
|
||||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.sqm.ComparisonOperator;
|
||||
import org.hibernate.query.internal.QueryHelper;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
|
||||
import static org.hibernate.query.sqm.internal.TypecheckUtil.assertComparable;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -41,6 +45,8 @@ public class SqmComparisonPredicate extends AbstractNegatableSqmPredicate {
|
|||
this.rightHandExpression = rightHandExpression;
|
||||
this.operator = operator;
|
||||
|
||||
assertComparable( leftHandExpression, rightHandExpression, nodeBuilder.getSessionFactory() );
|
||||
|
||||
final SqmExpressible<?> expressibleType = QueryHelper.highestPrecedenceType(
|
||||
leftHandExpression.getExpressible(),
|
||||
rightHandExpression.getExpressible()
|
||||
|
@ -55,6 +61,7 @@ public class SqmComparisonPredicate extends AbstractNegatableSqmPredicate {
|
|||
this.leftHandExpression = affirmativeForm.leftHandExpression;
|
||||
this.rightHandExpression = affirmativeForm.rightHandExpression;
|
||||
this.operator = affirmativeForm.operator;
|
||||
assertComparable( leftHandExpression, rightHandExpression, nodeBuilder().getSessionFactory() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,6 +17,8 @@ import org.hibernate.query.sqm.tree.select.SqmSubQuery;
|
|||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
|
||||
import static org.hibernate.query.sqm.internal.TypecheckUtil.assertComparable;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -40,6 +42,8 @@ public class SqmInSubQueryPredicate<T> extends AbstractNegatableSqmPredicate imp
|
|||
this.testExpression = testExpression;
|
||||
this.subQueryExpression = subQueryExpression;
|
||||
|
||||
assertComparable( testExpression, subQueryExpression, nodeBuilder.getSessionFactory() );
|
||||
|
||||
final SqmExpressible<?> expressibleType = QueryHelper.highestPrecedenceType2(
|
||||
testExpression.getExpressible(),
|
||||
subQueryExpression.getExpressible()
|
||||
|
|
|
@ -13,6 +13,8 @@ import org.hibernate.query.sqm.SqmExpressible;
|
|||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
|
||||
import static org.hibernate.query.sqm.internal.TypecheckUtil.assertString;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -55,8 +57,13 @@ public class SqmLikePredicate extends AbstractNegatableSqmPredicate {
|
|||
matchExpression.getExpressible(),
|
||||
pattern.getExpressible()
|
||||
);
|
||||
|
||||
assertString( matchExpression );
|
||||
assertString( pattern );
|
||||
|
||||
matchExpression.applyInferableType( expressibleType );
|
||||
pattern.applyInferableType( expressibleType );
|
||||
|
||||
if ( escapeCharacter != null ) {
|
||||
escapeCharacter.applyInferableType( nodeBuilder.getCharacterType() );
|
||||
}
|
||||
|
|
|
@ -6,27 +6,30 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.tree.predicate;
|
||||
|
||||
import org.hibernate.metamodel.model.domain.SimpleDomainType;
|
||||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||
|
||||
import static org.hibernate.query.sqm.internal.TypecheckUtil.areTypesComparable;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmMemberOfPredicate extends AbstractNegatableSqmPredicate {
|
||||
private final SqmExpression<?> leftHandExpression;
|
||||
private final SqmPath<?> pluralPath;
|
||||
private final SqmPluralValuedSimplePath<?> pluralPath;
|
||||
|
||||
public SqmMemberOfPredicate(SqmExpression<?> leftHandExpression, SqmPath<?> pluralPath, NodeBuilder nodeBuilder) {
|
||||
public SqmMemberOfPredicate(SqmExpression<?> leftHandExpression, SqmPluralValuedSimplePath<?> pluralPath, NodeBuilder nodeBuilder) {
|
||||
this( leftHandExpression, pluralPath, false, nodeBuilder );
|
||||
}
|
||||
|
||||
public SqmMemberOfPredicate(
|
||||
SqmExpression<?> leftHandExpression,
|
||||
SqmPath<?> pluralPath,
|
||||
SqmPluralValuedSimplePath<?> pluralPath,
|
||||
boolean negated,
|
||||
NodeBuilder nodeBuilder) {
|
||||
super( negated, nodeBuilder );
|
||||
|
@ -34,11 +37,21 @@ public class SqmMemberOfPredicate extends AbstractNegatableSqmPredicate {
|
|||
this.pluralPath = pluralPath;
|
||||
this.leftHandExpression = leftHandExpression;
|
||||
|
||||
leftHandExpression.applyInferableType(
|
||||
( (SqmPluralValuedSimplePath<?>) pluralPath ).getReferencedPathSource().getElementType()
|
||||
final SimpleDomainType<?> simpleDomainType = pluralPath.getReferencedPathSource().getElementType();
|
||||
|
||||
if ( !areTypesComparable(leftHandExpression.getNodeType(), simpleDomainType, nodeBuilder.getSessionFactory()) ) {
|
||||
throw new SemanticException(
|
||||
String.format(
|
||||
"Cannot compare left expression of type '%s' with right expression of type '%s'",
|
||||
leftHandExpression.getNodeType().getTypeName(),
|
||||
pluralPath.getNodeType().getTypeName()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
leftHandExpression.applyInferableType( simpleDomainType );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmMemberOfPredicate copy(SqmCopyContext context) {
|
||||
final SqmMemberOfPredicate existing = context.getCopy( this );
|
||||
|
@ -62,7 +75,7 @@ public class SqmMemberOfPredicate extends AbstractNegatableSqmPredicate {
|
|||
return leftHandExpression;
|
||||
}
|
||||
|
||||
public SqmPath<?> getPluralPath() {
|
||||
public SqmPluralValuedSimplePath<?> getPluralPath() {
|
||||
return pluralPath;
|
||||
}
|
||||
|
||||
|
|
|
@ -2646,7 +2646,7 @@ public class HQLTest extends BaseEntityManagerFunctionalTestCase {
|
|||
List<Person> persons = entityManager.createQuery(
|
||||
"select p " +
|
||||
"from Person p " +
|
||||
"where p.createdOn between '1999-01-01' and '2001-01-02'",
|
||||
"where p.createdOn between date 1999-01-01 and date 2001-01-02",
|
||||
Person.class)
|
||||
.getResultList();
|
||||
//end::hql-between-predicate-example[]
|
||||
|
|
Loading…
Reference in New Issue