HHH-15766 Add query spec parenthesis also when order by is used within query group
This commit is contained in:
parent
59f57b6811
commit
2c666c3835
|
@ -335,8 +335,17 @@ public class OracleLegacySqlAstTranslator<T extends JdbcOperation> extends Abstr
|
|||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
if ( !isRowNumberingCurrentQueryPart() ) {
|
||||
if ( supportsOffsetFetchClause() ) {
|
||||
if ( getQueryPartStack().depth() > 1 && queryPart.hasSortSpecifications()
|
||||
&& getQueryPartStack().peek( 1 ) instanceof QueryGroup
|
||||
&& ( queryPart.isRoot() && !hasLimit() || !queryPart.hasOffsetOrFetchClause() ) ) {
|
||||
// If the current query part has a query group parent, no offset/fetch clause, but an order by clause,
|
||||
// then we must render "offset 0 rows" as that is needed for the SQL to be valid
|
||||
appendSql( " offset 0 rows" );
|
||||
}
|
||||
else {
|
||||
renderOffsetFetchClause( queryPart, true );
|
||||
}
|
||||
}
|
||||
else {
|
||||
assertRowsOnlyFetchClauseType( queryPart );
|
||||
}
|
||||
|
|
|
@ -323,6 +323,12 @@ public class SQLServerLegacySqlAstTranslator<T extends JdbcOperation> extends Ab
|
|||
else if ( offsetFetchClauseMode == OffsetFetchClauseMode.EMULATED ) {
|
||||
renderTopClause( querySpec, isRowsOnlyFetchClauseType( querySpec ), true );
|
||||
}
|
||||
else if ( getQueryPartStack().depth() > 1 && querySpec.hasSortSpecifications()
|
||||
&& getQueryPartStack().peek( 1 ) instanceof QueryGroup ) {
|
||||
// If the current query spec has a query group parent, no offset/fetch clause, but an order by clause,
|
||||
// then we must render "top 100 percent" as that is needed for the SQL to be valid
|
||||
appendSql( "top 100 percent " );
|
||||
}
|
||||
super.visitSqlSelections( selectClause );
|
||||
}
|
||||
|
||||
|
|
|
@ -339,8 +339,17 @@ public class OracleSqlAstTranslator<T extends JdbcOperation> extends SqlAstTrans
|
|||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
if ( !isRowNumberingCurrentQueryPart() ) {
|
||||
if ( supportsOffsetFetchClause() ) {
|
||||
if ( getQueryPartStack().depth() > 1 && queryPart.hasSortSpecifications()
|
||||
&& getQueryPartStack().peek( 1 ) instanceof QueryGroup
|
||||
&& ( queryPart.isRoot() && !hasLimit() || !queryPart.hasOffsetOrFetchClause() ) ) {
|
||||
// If the current query part has a query group parent, no offset/fetch clause, but an order by clause,
|
||||
// then we must render "offset 0 rows" as that is needed for the SQL to be valid
|
||||
appendSql( " offset 0 rows" );
|
||||
}
|
||||
else {
|
||||
renderOffsetFetchClause( queryPart, true );
|
||||
}
|
||||
}
|
||||
else {
|
||||
assertRowsOnlyFetchClauseType( queryPart );
|
||||
}
|
||||
|
|
|
@ -302,6 +302,12 @@ public class SQLServerSqlAstTranslator<T extends JdbcOperation> extends SqlAstTr
|
|||
else if ( offsetFetchClauseMode == OffsetFetchClauseMode.EMULATED ) {
|
||||
renderTopClause( querySpec, isRowsOnlyFetchClauseType( querySpec ), true );
|
||||
}
|
||||
else if ( getQueryPartStack().depth() > 1 && querySpec.hasSortSpecifications()
|
||||
&& getQueryPartStack().peek( 1 ) instanceof QueryGroup ) {
|
||||
// If the current query spec has a query group parent, no offset/fetch clause, but an order by clause,
|
||||
// then we must render "top 100 percent" as that is needed for the SQL to be valid
|
||||
appendSql( "top 100 percent " );
|
||||
}
|
||||
super.visitSqlSelections( selectClause );
|
||||
}
|
||||
|
||||
|
|
|
@ -146,9 +146,7 @@ public class SybaseASESqlAstTranslator<T extends JdbcOperation> extends Abstract
|
|||
|
||||
@Override
|
||||
protected void visitSqlSelections(SelectClause selectClause) {
|
||||
if ( supportsTopClause() ) {
|
||||
renderTopClause( (QuerySpec) getQueryPartStack().getCurrent(), true, false );
|
||||
}
|
||||
super.visitSqlSelections( selectClause );
|
||||
}
|
||||
|
||||
|
@ -192,7 +190,7 @@ public class SybaseASESqlAstTranslator<T extends JdbcOperation> extends Abstract
|
|||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
assertRowsOnlyFetchClauseType( queryPart );
|
||||
if ( !queryPart.isRoot() && queryPart.hasOffsetOrFetchClause() ) {
|
||||
if ( queryPart.getFetchClauseExpression() != null && !supportsTopClause() || queryPart.getOffsetClauseExpression() != null ) {
|
||||
if ( queryPart.getFetchClauseExpression() != null && queryPart.getOffsetClauseExpression() != null ) {
|
||||
throw new IllegalArgumentException( "Can't emulate offset fetch clause in subquery" );
|
||||
}
|
||||
}
|
||||
|
@ -387,11 +385,6 @@ public class SybaseASESqlAstTranslator<T extends JdbcOperation> extends Abstract
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needsMaxRows() {
|
||||
return !supportsTopClause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
|
@ -412,10 +405,6 @@ public class SybaseASESqlAstTranslator<T extends JdbcOperation> extends Abstract
|
|||
return " from (select 1) dual(c1)";
|
||||
}
|
||||
|
||||
private boolean supportsTopClause() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean supportsParameterOffsetFetchExpression() {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,11 @@ public interface Stack<T> {
|
|||
*/
|
||||
T getCurrent();
|
||||
|
||||
/**
|
||||
* The element at the given offset, relative to the top of the stack
|
||||
*/
|
||||
T peek(int offsetFromTop);
|
||||
|
||||
/**
|
||||
* The element currently at the bottom of the stack
|
||||
*/
|
||||
|
|
|
@ -72,6 +72,14 @@ public final class StandardStack<T> implements Stack<T> {
|
|||
return elements[top - 1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public T peek(int offsetFromTop) {
|
||||
if ( isEmpty() ) {
|
||||
return null;
|
||||
}
|
||||
return elements[top - offsetFromTop - 1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getRoot() {
|
||||
if ( isEmpty() ) {
|
||||
|
|
|
@ -2992,9 +2992,9 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
}
|
||||
String queryGroupAlias = null;
|
||||
if ( currentQueryPart instanceof QueryGroup ) {
|
||||
// We always need query wrapping if we are in a query group and this query spec has a fetch clause
|
||||
// because of order by precedence in SQL
|
||||
if ( querySpec.hasOffsetOrFetchClause() ) {
|
||||
// We always need query wrapping if we are in a query group and this query spec has a fetch or order by
|
||||
// clause, because of order by precedence in SQL
|
||||
if ( querySpec.hasOffsetOrFetchClause() || querySpec.hasSortSpecifications() ) {
|
||||
queryGroupAlias = "";
|
||||
// If the parent is a query group with a fetch clause we must use a select wrapper,
|
||||
// or if the database does not support simple query grouping, we must use a select wrapper
|
||||
|
|
|
@ -2,10 +2,13 @@ package org.hibernate.orm.test.query.hql;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.dialect.SybaseASEDialect;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.hibernate.testing.orm.junit.SkipForDialect;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -22,6 +25,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
|||
)
|
||||
@SessionFactory
|
||||
@TestForIssue(jiraKey = "HHH-15766")
|
||||
@SkipForDialect(dialectClass = SybaseASEDialect.class, reason = "Sybase ASE does not support order by in subqueries")
|
||||
public class HqlUnionTest {
|
||||
|
||||
@BeforeAll
|
||||
|
|
Loading…
Reference in New Issue