HHH-17804 roll back change to semantics of 'null in ()'

It turns out that SQL databases (IMO wrongly) treat the expression
'null in (select 1 where false)' as false instead of null. And as
of JPA 3.2, we're free to interpret 'null in ()' consistently with
that, which we should do.

So my change made things worse rather than better.

Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
Gavin King 2024-06-06 14:19:37 +02:00
parent 15cbebbbf9
commit de3a4c0af9
4 changed files with 7 additions and 29 deletions

View File

@ -3206,7 +3206,7 @@ public abstract class AbstractEntityPersister
Map<String, EntityNameUse> entityNameUses, Map<String, EntityNameUse> entityNameUses,
MappingMetamodelImplementor mappingMetamodel, MappingMetamodelImplementor mappingMetamodel,
String alias) { String alias) {
final InFragment frag = new InFragment( false ); final InFragment frag = new InFragment();
if ( isDiscriminatorFormula() ) { if ( isDiscriminatorFormula() ) {
frag.setFormula( alias, getDiscriminatorFormulaTemplate() ); frag.setFormula( alias, getDiscriminatorFormulaTemplate() );
} }

View File

@ -21,15 +21,10 @@ import org.hibernate.internal.util.StringHelper;
@Internal @Internal
public class InFragment { public class InFragment {
public InFragment(boolean columnCanBeNull) {
this.columnCanBeNull = columnCanBeNull;
}
public static final String NULL = "null"; public static final String NULL = "null";
public static final String NOT_NULL = "not null"; public static final String NOT_NULL = "not null";
protected String columnName; protected String columnName;
protected boolean columnCanBeNull;
protected List<Object> values = new ArrayList<>(); protected List<Object> values = new ArrayList<>();
/** /**
@ -71,15 +66,7 @@ public class InFragment {
switch ( values.size() ) { switch ( values.size() ) {
case 0: { case 0: {
if ( columnCanBeNull ) { return "0=1";
return buf.append( "(1 = case when " )
.append( columnName )
.append(" is not null then 0 end)")
.toString();
}
else {
return "0=1";
}
} }
case 1: { case 1: {
Object value = values.get( 0 ); Object value = values.get( 0 );

View File

@ -7641,7 +7641,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
public void visitInListPredicate(InListPredicate inListPredicate) { public void visitInListPredicate(InListPredicate inListPredicate) {
final List<Expression> listExpressions = inListPredicate.getListExpressions(); final List<Expression> listExpressions = inListPredicate.getListExpressions();
if ( listExpressions.isEmpty() ) { if ( listExpressions.isEmpty() ) {
emptyInList( inListPredicate ); appendSql( "1=" + ( inListPredicate.isNegated() ? "1" : "0" ) );
return; return;
} }
Function<Expression, Expression> itemAccessor = Function.identity(); Function<Expression, Expression> itemAccessor = Function.identity();
@ -7748,16 +7748,6 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
} }
} }
protected void emptyInList(InListPredicate inListPredicate) {
appendSql("(");
appendSql( inListPredicate.isNegated() ? "0" : "1" );
appendSql(" = case when ");
inListPredicate.getTestExpression().accept( this );
appendSql( " is not null then 0");
// dialect.appendBooleanValueString( this, inListPredicate.isNegated() );
appendSql(" end)");
}
private void appendInClauseSeparator(InListPredicate inListPredicate) { private void appendInClauseSeparator(InListPredicate inListPredicate) {
appendSql( CLOSE_PARENTHESIS ); appendSql( CLOSE_PARENTHESIS );
appendSql( inListPredicate.isNegated() ? " and " : " or " ); appendSql( inListPredicate.isNegated() ? " and " : " or " );

View File

@ -31,6 +31,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
/** /**
@ -334,7 +335,7 @@ public class PredicateTest extends AbstractMetamodelSpecificTest {
CriteriaQuery<Order> orderCriteria = builder.createQuery( Order.class ); CriteriaQuery<Order> orderCriteria = builder.createQuery( Order.class );
Root<Order> orderRoot = orderCriteria.from( Order.class ); Root<Order> orderRoot = orderCriteria.from( Order.class );
orderCriteria.select( orderRoot ); orderCriteria.select( orderRoot );
orderCriteria.where( builder.in( orderRoot.get("creditCard") ) ); orderCriteria.where( builder.in( orderRoot.get("id") ) );
List<Order> orders = em.createQuery( orderCriteria ).getResultList(); List<Order> orders = em.createQuery( orderCriteria ).getResultList();
assertTrue( orders.isEmpty() ); assertTrue( orders.isEmpty() );
@ -350,10 +351,10 @@ public class PredicateTest extends AbstractMetamodelSpecificTest {
CriteriaQuery<Order> orderCriteria = builder.createQuery( Order.class ); CriteriaQuery<Order> orderCriteria = builder.createQuery( Order.class );
Root<Order> orderRoot = orderCriteria.from( Order.class ); Root<Order> orderRoot = orderCriteria.from( Order.class );
orderCriteria.select( orderRoot ); orderCriteria.select( orderRoot );
orderCriteria.where( builder.in( orderRoot.get("creditCard") ).not() ); orderCriteria.where( builder.in( orderRoot.get("id") ).not() );
List<Order> orders = em.createQuery( orderCriteria ).getResultList(); List<Order> orders = em.createQuery( orderCriteria ).getResultList();
assertTrue( orders.isEmpty() ); assertFalse( orders.isEmpty() );
em.getTransaction().commit(); em.getTransaction().commit();
em.close(); em.close();
} }