diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/WithClauseTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/WithClauseTest.java index 19c05d79e5..921debadf8 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/WithClauseTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/WithClauseTest.java @@ -245,7 +245,7 @@ public class WithClauseTest extends BaseCoreFunctionalTestCase { @Test @TestForIssue(jiraKey = "HHH-11157") public void testWithClauseAsNonSubqueryWithKey() { - rebuildSessionFactory( Collections.singletonMap( AvailableSettings.COLLECTION_JOIN_SUBQUERY, "false" ) ); + rebuildSessionFactory( c -> c.setProperty( AvailableSettings.COLLECTION_JOIN_SUBQUERY, "false" ) ); try { TestData data = new TestData(); diff --git a/hibernate-core/src/test/java/org/hibernate/test/subquery/EntityA.java b/hibernate-core/src/test/java/org/hibernate/test/subquery/EntityA.java new file mode 100644 index 0000000000..79b30b6271 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/subquery/EntityA.java @@ -0,0 +1,44 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ + +//$Id$ + +package org.hibernate.test.subquery; + +import javax.persistence.*; + +@Entity +public class EntityA { + @Id + @Column(name = "id", nullable = false) + private int id; + private String name; + + public EntityA() { + } + + public EntityA(int id, String name) { + this.id = id; + this.name = name; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} \ No newline at end of file diff --git a/hibernate-core/src/test/java/org/hibernate/test/subquery/SubqueryTest.java b/hibernate-core/src/test/java/org/hibernate/test/subquery/SubqueryTest.java new file mode 100644 index 0000000000..fb9e3f0241 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/subquery/SubqueryTest.java @@ -0,0 +1,95 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ + +//$Id$ + +package org.hibernate.test.subquery; + +import org.hibernate.QueryException; +import org.hibernate.Session; +import org.hibernate.dialect.function.SQLFunction; +import org.hibernate.engine.spi.Mapping; +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.type.Type; +import org.junit.Test; + +import javax.persistence.Query; +import java.util.List; +import java.util.function.Consumer; + +/** + * Test some subquery scenarios. + * + * @author Christian Beikov + */ +public class SubqueryTest extends BaseCoreFunctionalTestCase { + + private static final SQLFunction LIMIT_FUNCTION = new SQLFunction() { + public boolean hasArguments() { + return true; + } + + public boolean hasParenthesesIfNoArguments() { + return true; + } + + public Type getReturnType(Type type, Mapping mpng) throws QueryException { + return type; + } + + public String render(Type type, List list, SessionFactoryImplementor sfi) throws QueryException { + String subquery = list.get(0).toString(); + return subquery.substring(0, subquery.length() - 1) + " limit " + list.get(1) + ")"; + } + }; + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[]{ + EntityA.class + }; + } + + @Test + public void testNestedOrderBySubqueryInFunction() { + withLimit(s -> { + Query q = s.createQuery( + "SELECT a.id FROM EntityA a " + + "ORDER BY CASE WHEN (" + + "SELECT 1 FROM EntityA s1 " + + "WHERE s1.id IN(" + + "LIMIT(" + + "(" + + "SELECT 1 FROM EntityA sub " + + "ORDER BY " + + "CASE WHEN sub.name IS NULL THEN 1 ELSE 0 END, " + + "sub.name DESC, " + + "CASE WHEN sub.id IS NULL THEN 1 ELSE 0 END, " + + "sub.id DESC" + + ")," + + "1)" + + ")" + + ") = 1 THEN 1 ELSE 0 END" + ); + q.getResultList(); + }); + } + + private void withLimit(Consumer consumer) { + rebuildSessionFactory( c -> c.addSqlFunction( "limit", LIMIT_FUNCTION ) ); + + try { + Session s = openSession(); + consumer.accept( s ); + } finally { + // Rebuild to remove the function + rebuildSessionFactory(); + } + } + +} diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseCoreFunctionalTestCase.java b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseCoreFunctionalTestCase.java index 64ec85f26c..c69572391a 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseCoreFunctionalTestCase.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/junit4/BaseCoreFunctionalTestCase.java @@ -10,6 +10,7 @@ import java.io.InputStream; import java.sql.Connection; import java.sql.SQLException; import java.util.*; +import java.util.function.Consumer; import javax.persistence.SharedCacheMode; import org.hibernate.HibernateException; @@ -95,16 +96,14 @@ public abstract class BaseCoreFunctionalTestCase extends BaseUnitTestCase { @BeforeClassOnce @SuppressWarnings( {"UnusedDeclaration"}) protected void buildSessionFactory() { - buildSessionFactory( Collections.emptyMap() ); + buildSessionFactory( null ); } - protected void buildSessionFactory(Map properties) { + protected void buildSessionFactory(Consumer configurationAdapter) { // for now, build the configuration to get all the property settings configuration = constructAndConfigureConfiguration(); - if ( properties != null && !properties.isEmpty() ) { - for ( Map.Entry entry : properties.entrySet() ) { - configuration.setProperty( entry.getKey(), entry.getValue() ); - } + if ( configurationAdapter != null ) { + configurationAdapter.accept(configuration); } BootstrapServiceRegistry bootRegistry = buildBootstrapServiceRegistry(); serviceRegistry = buildServiceRegistry( bootRegistry, configuration ); @@ -115,10 +114,10 @@ public abstract class BaseCoreFunctionalTestCase extends BaseUnitTestCase { } protected void rebuildSessionFactory() { - rebuildSessionFactory( Collections.emptyMap() ); + rebuildSessionFactory( null ); } - protected void rebuildSessionFactory(Map properties) { + protected void rebuildSessionFactory(Consumer configurationAdapter) { if ( sessionFactory == null ) { return; } @@ -132,7 +131,7 @@ public abstract class BaseCoreFunctionalTestCase extends BaseUnitTestCase { catch (Exception ignore) { } - buildSessionFactory( properties ); + buildSessionFactory( configurationAdapter ); } protected Configuration buildConfiguration() {