HHH-14148 fix issue mapping order SQL fragment could produce incorrect SQL

This commit is contained in:
Nathan Xu 2020-08-31 05:58:42 -04:00 committed by Christian Beikov
parent f91ed82757
commit cf94259248
2 changed files with 33 additions and 4 deletions

View File

@ -146,7 +146,7 @@ selectStatement
from from
( #(WHERE { out(" where "); } whereExpr ) )? ( #(WHERE { out(" where "); } whereExpr ) )?
( #(GROUP { out(" group by "); } groupExprs ( #(HAVING { out(" having "); } booleanExpr[false]) )? ) )? ( #(GROUP { out(" group by "); } groupExprs ( #(HAVING { out(" having "); } booleanExpr[false]) )? ) )?
( #(ORDER { out(" order by "); } orderExprs ) )? ( #(ORDER { out(" order by "); } orderBySqlFragmentOrExprs ) )?
) )
; ;
@ -191,6 +191,11 @@ whereClauseExpr
| booleanExpr[ false ] | booleanExpr[ false ]
; ;
orderBySqlFragmentOrExprs
: sqlToken // for the purpose of mapping-defined orderBy SQL fragment
| orderExprs
;
orderExprs { String ordExp = null; String ordDir = null; String ordNul = null; } orderExprs { String ordExp = null; String ordDir = null; String ordNul = null; }
// TODO: remove goofy space before the comma when we don't have to regression test anymore. // TODO: remove goofy space before the comma when we don't have to regression test anymore.
// Dialect is provided a hook to render each ORDER BY element, so the expression is being captured instead of // Dialect is provided a hook to render each ORDER BY element, so the expression is being captured instead of
@ -277,7 +282,7 @@ distinctOrAll
; ;
countExpr countExpr
// Syntacitic predicate resolves star all by itself, avoiding a conflict with STAR in expr. // Syntactic predicate resolves star all by itself, avoiding a conflict with STAR in expr.
: ROW_STAR { out("*"); } : ROW_STAR { out("*"); }
| simpleExpr | simpleExpr
; ;

View File

@ -24,15 +24,17 @@ import org.hibernate.Criteria;
import org.hibernate.Hibernate; import org.hibernate.Hibernate;
import org.hibernate.NullPrecedence; import org.hibernate.NullPrecedence;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.dialect.H2Dialect; import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.MySQLDialect; import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.Oracle8iDialect; import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.dialect.SQLServer2008Dialect; import org.hibernate.dialect.SQLServer2008Dialect;
import org.hibernate.dialect.SQLServer2012Dialect;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.graph.RootGraph;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.QueryableCollection; import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.query.Query;
import org.hibernate.sql.SimpleSelect; import org.hibernate.sql.SimpleSelect;
import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
@ -515,6 +517,28 @@ public class OrderByTest extends BaseCoreFunctionalTestCase {
s.close(); s.close();
} }
@Test
@TestForIssue( jiraKey = "HHH-14148" )
@RequiresDialect(value = { H2Dialect.class, MySQLDialect.class, SQLServer2008Dialect.class },
comment = "By default H2 places NULL values first, so testing 'NULLS LAST' expression. " +
"For MySQL and SQL Server 2008 testing overridden Dialect#renderOrderByElement(String, String, String, NullPrecedence) method. " +
"MySQL and SQL Server 2008 does not support NULLS FIRST / LAST syntax at the moment, so transforming the expression to 'CASE WHEN ...'.")
public void testNullPrecedenceWithOrderBySqlFragment() {
inTransaction( session -> {
final RootGraph<Order> graph = session.createEntityGraph( Order.class );
graph.addAttributeNodes( "itemList" );
Query<Order> query = session.createQuery( "from Order", Order.class );
query.applyFetchGraph( graph );
query.getResultList(); // before HHH-14148 is fixed, incorrect SQL would be generated ending with " nulls last nulls last"
} );
}
@Override
protected void configure(Configuration configuration) {
configuration.setProperty( AvailableSettings.DEFAULT_NULL_ORDERING, "last" );
}
@Override @Override
protected Class[] getAnnotatedClasses() { protected Class[] getAnnotatedClasses() {
return new Class[] { return new Class[] {