From de1de9f6299c32944da320ca16c17f8827b857fd Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Tue, 4 Jan 2022 15:09:09 +0100 Subject: [PATCH] Fix issues with Oracle rownum pagination on Oracle before version 12.2 --- .../dialect/OracleSqlAstTranslator.java | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/OracleSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/dialect/OracleSqlAstTranslator.java index 79327c54dc..5a7e676218 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/OracleSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/OracleSqlAstTranslator.java @@ -126,6 +126,25 @@ public class OracleSqlAstTranslator extends AbstractSql return true; } + @Override + protected FetchClauseType getFetchClauseTypeForRowNumbering(QueryPart queryPart) { + final FetchClauseType fetchClauseType = super.getFetchClauseTypeForRowNumbering( queryPart ); + final boolean hasOffset; + if ( queryPart.isRoot() && hasLimit() ) { + hasOffset = getLimit().getFirstRow() != null; + } + else { + hasOffset = queryPart.getOffsetClauseExpression() != null; + } + if ( queryPart instanceof QuerySpec && !hasOffset && fetchClauseType == FetchClauseType.ROWS_ONLY ) { + // We return null here, because in this particular case, we render a special rownum query + // which can be seen in #emulateFetchOffsetWithWindowFunctions + // Note that we also build upon this in #visitOrderBy + return null; + } + return fetchClauseType; + } + @Override protected void emulateFetchOffsetWithWindowFunctions( QueryPart queryPart, @@ -138,7 +157,7 @@ public class OracleSqlAstTranslator extends AbstractSql final QuerySpec querySpec = (QuerySpec) queryPart; withRowNumbering( querySpec, - false, + true, // we need select aliases to avoid ORA-00918: column ambiguously defined () -> { final QueryPart currentQueryPart = getQueryPartStack().getCurrent(); final boolean needsParenthesis; @@ -210,10 +229,9 @@ public class OracleSqlAstTranslator extends AbstractSql renderOrderBy( true, sortSpecifications ); } else { - // This logic is tightly coupled to emulateFetchOffsetWithWindowFunctions + // This logic is tightly coupled to #emulateFetchOffsetWithWindowFunctions and #getFetchClauseTypeForRowNumbering // so that this is rendered when we end up in the special case for Oracle that renders a rownum filter - final FetchClauseType fetchClauseType = getFetchClauseTypeForRowNumbering( queryPartForRowNumbering ); - if ( fetchClauseType == FetchClauseType.ROWS_ONLY && queryPartForRowNumbering instanceof QuerySpec ) { + if ( getFetchClauseTypeForRowNumbering( queryPartForRowNumbering ) == null ) { final QuerySpec querySpec = (QuerySpec) queryPartForRowNumbering; if ( querySpec.getOffsetClauseExpression() == null && ( !querySpec.isRoot() || getOffsetParameter() == null ) ) {