HHH-8901 replace "in ()" SQL with "in (null)" in QueryParameterBindingsImpl

This commit is contained in:
Nathan Xu 2019-11-26 22:28:34 -05:00 committed by Sanne Grinovero
parent 4e449dfafa
commit ab9ae43185
7 changed files with 118 additions and 38 deletions

View File

@ -46,13 +46,17 @@ public class InExpression implements Criterion {
if ( columns.length > 1 ) {
singleValueParam = '(' + singleValueParam + ')';
}
final String params = values.length > 0
String params = values.length > 0
? StringHelper.repeat( singleValueParam + ", ", values.length - 1 ) + singleValueParam
: "";
String cols = String.join( ", ", columns );
if ( columns.length > 1 ) {
cols = '(' + cols + ')';
}
// HHH-8901
if ( ! criteriaQuery.getFactory().getDialect().supportsEmptyInList() && params.isEmpty() ) {
params = "null";
}
return cols + " in (" + params + ')';
}
else {

View File

@ -194,6 +194,10 @@ public class InPredicate<T>
.append( ( (Renderable) value ).render( renderingContext ) );
sep = ", ";
}
// HHH-8901
if ( ! renderingContext.getDialect().supportsEmptyInList() && getValues().isEmpty() ) {
buffer.append( "null" );
}
buffer.append( ')' );
}
return buffer.toString();

View File

@ -637,6 +637,11 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
parameterBindingMap.put( syntheticParam, syntheticBinding );
}
// HHH-8901
if ( ! dialect.supportsEmptyInList() && expansionList.length() == 0 ) {
expansionList.append( "null" );
}
queryString = StringHelper.replace(
beforePlaceholder,
afterPlaceholder,

View File

@ -8,26 +8,22 @@ package org.hibernate.jpa.test.criteria.basic;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.hibernate.dialect.Oracle12cDialect;
import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.dialect.Oracle9Dialect;
import org.hibernate.dialect.OracleDialect;
import org.hibernate.jpa.test.metamodel.AbstractMetamodelSpecificTest;
import org.hibernate.jpa.test.metamodel.CreditCard;
import org.hibernate.jpa.test.metamodel.CreditCard_;
import org.hibernate.jpa.test.metamodel.Customer_;
import org.hibernate.jpa.test.metamodel.Order;
import org.hibernate.jpa.test.metamodel.Order_;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.TestForIssue;
import org.junit.Before;
@ -297,4 +293,21 @@ public class PredicateTest extends AbstractMetamodelSpecificTest {
em.getTransaction().commit();
em.close();
}
@Test
@TestForIssue( jiraKey = "HHH-8901" )
@RequiresDialectFeature( DialectChecks.NotSupportsEmptyInListCheck.class )
public void testEmptyInPredicate() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
CriteriaQuery<Order> orderCriteria = builder.createQuery( Order.class );
Root<Order> orderRoot = orderCriteria.from( Order.class );
orderCriteria.select( orderRoot );
orderCriteria.where( builder.in( orderRoot.get("totalPrice") ) );
List<Order> orders = em.createQuery( orderCriteria ).getResultList();
assertTrue( orders.isEmpty() );
em.getTransaction().commit();
em.close();
}
}

View File

@ -8,11 +8,15 @@ package org.hibernate.test.criteria;
import static org.junit.Assert.assertEquals;
import java.util.Collections;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
@ -42,4 +46,24 @@ public class InTest extends BaseCoreFunctionalTestCase {
tx.rollback();
session.close();
}
@Test
@TestForIssue( jiraKey = "HHH-8901" )
@RequiresDialectFeature(DialectChecks.NotSupportsEmptyInListCheck.class)
public void testEmptyInListForDialectNotSupportsEmptyInList() {
Session session = openSession();
Transaction tx = session.beginTransaction();
session.save( new Woman() );
session.save( new Man() );
session.flush();
tx.commit();
session.close();
session = openSession();
tx = session.beginTransaction();
List persons = session.createCriteria( Person.class ).add(
Restrictions.in( "name", Collections.emptySet() ) ).list();
assertEquals( 0, persons.size() );
tx.rollback();
session.close();
}
}

View File

@ -6,6 +6,18 @@
*/
package org.hibernate.test.hql;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hibernate.testing.junit4.ExtraAssertions.assertClassAssignability;
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Date;
@ -13,11 +25,11 @@ import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
@ -53,19 +65,6 @@ import org.hibernate.internal.util.StringHelper;
import org.hibernate.loader.MultipleBagFetchException;
import org.hibernate.persister.entity.DiscriminatorType;
import org.hibernate.stat.QueryStatistics;
import org.hibernate.transform.DistinctRootEntityResultTransformer;
import org.hibernate.transform.Transformers;
import org.hibernate.type.ComponentType;
import org.hibernate.type.ManyToOneType;
import org.hibernate.type.Type;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.test.any.IntegerPropertyValue;
import org.hibernate.test.any.PropertySet;
import org.hibernate.test.any.PropertyValue;
@ -75,24 +74,20 @@ import org.hibernate.test.cid.LineItem;
import org.hibernate.test.cid.LineItem.Id;
import org.hibernate.test.cid.Order;
import org.hibernate.test.cid.Product;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.transform.DistinctRootEntityResultTransformer;
import org.hibernate.transform.Transformers;
import org.hibernate.type.ComponentType;
import org.hibernate.type.ManyToOneType;
import org.hibernate.type.Type;
import org.junit.Test;
import org.jboss.logging.Logger;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hibernate.testing.junit4.ExtraAssertions.assertClassAssignability;
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.hibernate.testing.transaction.TransactionUtil2.inTransaction;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* Tests the integration of the new AST parser into the loading of query results using
* the Hibernate persisters and loaders.
@ -663,6 +658,35 @@ public class ASTParserLoadingTest extends BaseCoreFunctionalTestCase {
session.close();
}
@Test
@TestForIssue( jiraKey = "HHH-8901" )
@RequiresDialectFeature(DialectChecks.NotSupportsEmptyInListCheck.class)
public void testEmptyInListForDialectsNotSupportsEmptyInList() {
Session session = openSession();
session.beginTransaction();
Human human = new Human();
human.setName( new Name( "Lukasz", null, "Antoniak" ) );
human.setNickName( "NONE" );
session.save( human );
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
List results = session.createQuery( "from Human h where h.nickName in (:nickNames)" )
.setParameter("nickNames", Collections.emptySet() )
.list();
assertEquals( 0, results.size() );
session.getTransaction().commit();
session.close();
session = openSession();
session.beginTransaction();
session.delete( human );
session.getTransaction().commit();
session.close();
}
@Test
@TestForIssue( jiraKey = "HHH-2851")
public void testMultipleRefsToSameParam() {
@ -982,7 +1006,7 @@ public class ASTParserLoadingTest extends BaseCoreFunctionalTestCase {
else {
s.createQuery( "from Animal where lower(upper('foo') || upper(:bar)) like 'f%'" ).setString( "bar", "xyz" ).list();
}
if ( getDialect() instanceof AbstractHANADialect ) {
s.createQuery( "from Animal where abs(cast(1 as double) - cast(:param as double)) = 1.0" )
.setLong( "param", 1 ).list();

View File

@ -55,6 +55,12 @@ abstract public class DialectChecks {
}
}
public static class NotSupportsEmptyInListCheck implements DialectCheck {
public boolean isMatch(Dialect dialect) {
return !dialect.supportsEmptyInList();
}
}
public static class CaseSensitiveCheck implements DialectCheck {
public boolean isMatch(Dialect dialect) {
return dialect.areStringComparisonsCaseInsensitive();