HHH-16843 fix interpretation of 'value = null' in HQL

the previous implementation was not compliant with the
JPA spec and defied logic
This commit is contained in:
Gavin King 2023-06-25 18:29:50 +02:00
parent e15bee589f
commit f77067b1b3
5 changed files with 21 additions and 43 deletions

View File

@ -2443,12 +2443,10 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
return ComparisonOperator.GREATER_THAN;
case HqlLexer.GREATER_EQUAL:
return ComparisonOperator.GREATER_THAN_OR_EQUAL;
case HqlLexer.IS: {
final TerminalNode secondToken = (TerminalNode) ctx.getChild( 1 );
return secondToken.getSymbol().getType() == HqlLexer.NOT
? ComparisonOperator.NOT_DISTINCT_FROM
: ComparisonOperator.DISTINCT_FROM;
}
case HqlLexer.IS:
return ctx.NOT() == null
? ComparisonOperator.DISTINCT_FROM
: ComparisonOperator.NOT_DISTINCT_FROM;
default:
throw new ParsingException("Unrecognized comparison operator");
}
@ -2456,11 +2454,11 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
@Override
public SqmPredicate visitComparisonPredicate(HqlParser.ComparisonPredicateContext ctx) {
final ComparisonOperator comparisonOperator = (ComparisonOperator) ctx.getChild( 1 ).accept( this );
final ComparisonOperator comparisonOperator = (ComparisonOperator) ctx.comparisonOperator().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 );
final HqlParser.ExpressionContext leftExpressionContext = ctx.expression( 0 );
final HqlParser.ExpressionContext rightExpressionContext = ctx.expression( 1 );
switch (comparisonOperator) {
case EQUAL:
case NOT_EQUAL:
@ -2499,24 +2497,6 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
left = l;
right = r;
}
// 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: {
@ -2582,15 +2562,12 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
@Override
public SqmPredicate visitLikePredicate(HqlParser.LikePredicateContext ctx) {
final boolean negated = ( (TerminalNode) ctx.getChild( 1 ) ).getSymbol().getType() == HqlParser.NOT;
final int startIndex = negated ? 3 : 2;
final boolean caseSensitive = ( (TerminalNode) ctx.getChild( negated ? 2 : 1 ) ).getSymbol()
.getType() == HqlParser.LIKE;
if ( ctx.getChildCount() == startIndex + 2 ) {
final boolean negated = ctx.NOT() != null;
final boolean caseSensitive = ctx.LIKE() != null;
if ( ctx.likeEscape() == null ) {
return new SqmLikePredicate(
(SqmExpression<?>) ctx.getChild( 0 ).accept( this ),
(SqmExpression<?>) ctx.getChild( startIndex ).accept( this ),
(SqmExpression<?>) ctx.getChild( startIndex + 1 ).accept( this ),
(SqmExpression<?>) ctx.expression(0).accept( this ),
(SqmExpression<?>) ctx.expression(1).accept( this ),
negated,
caseSensitive,
creationContext.getNodeBuilder()
@ -2598,8 +2575,9 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
}
else {
return new SqmLikePredicate(
(SqmExpression<?>) ctx.getChild( 0 ).accept( this ),
(SqmExpression<?>) ctx.getChild( startIndex ).accept( this ),
(SqmExpression<?>) ctx.expression(0).accept( this ),
(SqmExpression<?>) ctx.expression(1).accept( this ),
(SqmExpression<?>) ctx.likeEscape().accept( this ),
negated,
caseSensitive,
creationContext.getNodeBuilder()

View File

@ -34,6 +34,7 @@ public class JavaTypeHelper {
}
public static boolean isUnknown(JavaType<?> javaType) {
return javaType.getClass() == UnknownBasicJavaType.class;
return javaType == null
|| javaType.getClass() == UnknownBasicJavaType.class;
}
}

View File

@ -24,7 +24,6 @@ import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.sql.ast.spi.StringBuilderSqlAppender;
import org.hibernate.type.descriptor.java.JavaTypeHelper;
import org.hibernate.type.descriptor.java.spi.UnknownBasicJavaType;
import org.hibernate.type.format.FormatMapper;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.BasicPluralJavaType;

View File

@ -1158,7 +1158,7 @@ public class BulkManipulationTest extends BaseCoreFunctionalTestCase {
int count = s.createQuery( "update Mammal set bodyWeight = null" ).executeUpdate();
assertEquals( "Incorrect deletion count on joined subclass", 2, count );
count = s.createQuery( "delete Animal where bodyWeight = null" ).executeUpdate();
count = s.createQuery( "delete Animal where bodyWeight is null" ).executeUpdate();
assertEquals( "Incorrect deletion count on joined subclass", 2, count );
t.commit();

View File

@ -47,13 +47,13 @@ public class DistinctSelectTest extends BaseCoreFunctionalTestCase {
Transaction t = s.beginTransaction();
for (int i = 0; i < 5; i++) {
Tag tag = new Tag("Tag: " + UUID.randomUUID().toString());
Tag tag = new Tag("Tag: " + UUID.randomUUID());
tags.add(tag);
s.save(tag);
}
for (int i = 0; i < NUM_OF_USERS; i++) {
Entry e = new Entry("Entry: " + UUID.randomUUID().toString());
Entry e = new Entry("Entry: " + UUID.randomUUID());
e.getTags().addAll(tags);
s.save(e);
}
@ -68,7 +68,7 @@ public class DistinctSelectTest extends BaseCoreFunctionalTestCase {
Session s = openSession();
List<Entry> entries = s.createQuery("select distinct e from Entry e join e.tags t where t.surrogate != null order by e.name").setFirstResult(10).setMaxResults(5).list();
List<Entry> entries = s.createQuery("select distinct e from Entry e join e.tags t where t.surrogate is not null order by e.name").setFirstResult(10).setMaxResults(5).list();
// System.out.println(entries);
Entry firstEntry = entries.remove(0);