|  | 
| 21 | 21 | import org.hibernate.sql.ast.tree.from.ValuesTableReference; | 
| 22 | 22 | import org.hibernate.sql.ast.tree.insert.ConflictClause; | 
| 23 | 23 | import org.hibernate.sql.ast.tree.insert.InsertSelectStatement; | 
|  | 24 | +import org.hibernate.sql.ast.tree.select.QueryGroup; | 
| 24 | 25 | import org.hibernate.sql.ast.tree.select.QueryPart; | 
| 25 | 26 | import org.hibernate.sql.ast.tree.select.QuerySpec; | 
| 26 | 27 | import org.hibernate.sql.ast.tree.select.SelectClause; | 
| @@ -60,11 +61,14 @@ protected void renderSelectExpression(Expression expression) { | 
| 60 | 61 | 
 | 
| 61 | 62 | 	@Override | 
| 62 | 63 | 	protected void visitSqlSelections(SelectClause selectClause) { | 
| 63 |  | -		if ( supportsSkipFirstClause() ) { | 
| 64 |  | -			renderSkipFirstClause( (QuerySpec) getQueryPartStack().getCurrent() ); | 
| 65 |  | -		} | 
| 66 |  | -		else { | 
| 67 |  | -			renderFirstClause( (QuerySpec) getQueryPartStack().getCurrent() ); | 
|  | 64 | +		final QuerySpec querySpec = (QuerySpec) getQueryPartStack().getCurrent(); | 
|  | 65 | +		if ( isRowsOnlyFetchClauseType( querySpec ) ) { | 
|  | 66 | +			if ( supportsSkipFirstClause() ) { | 
|  | 67 | +				renderSkipFirstClause( querySpec ); | 
|  | 68 | +			} | 
|  | 69 | +			else { | 
|  | 70 | +				renderFirstClause( querySpec ); | 
|  | 71 | +			} | 
| 68 | 72 | 		} | 
| 69 | 73 | 		if ( selectClause.isDistinct() ) { | 
| 70 | 74 | 			appendSql( "distinct " ); | 
| @@ -195,4 +199,30 @@ protected void visitInsertStatementOnly(InsertSelectStatement statement) { | 
| 195 | 199 | 	public void visitValuesTableReference(ValuesTableReference tableReference) { | 
| 196 | 200 | 		emulateValuesTableReferenceColumnAliasing( tableReference ); | 
| 197 | 201 | 	} | 
|  | 202 | + | 
|  | 203 | +	protected boolean shouldEmulateFetchClause(QueryPart queryPart) { | 
|  | 204 | +		// Check if current query part is already row numbering to avoid infinite recursion | 
|  | 205 | +		return useOffsetFetchClause( queryPart ) && getQueryPartForRowNumbering() != queryPart | 
|  | 206 | +			&& getDialect().supportsWindowFunctions() && !isRowsOnlyFetchClauseType( queryPart ); | 
|  | 207 | +	} | 
|  | 208 | + | 
|  | 209 | +	@Override | 
|  | 210 | +	public void visitQueryGroup(QueryGroup queryGroup) { | 
|  | 211 | +		if ( shouldEmulateFetchClause( queryGroup ) ) { | 
|  | 212 | +			emulateFetchOffsetWithWindowFunctions( queryGroup, true ); | 
|  | 213 | +		} | 
|  | 214 | +		else { | 
|  | 215 | +			super.visitQueryGroup( queryGroup ); | 
|  | 216 | +		} | 
|  | 217 | +	} | 
|  | 218 | + | 
|  | 219 | +	@Override | 
|  | 220 | +	public void visitQuerySpec(QuerySpec querySpec) { | 
|  | 221 | +		if ( shouldEmulateFetchClause( querySpec ) ) { | 
|  | 222 | +			emulateFetchOffsetWithWindowFunctions( querySpec, true ); | 
|  | 223 | +		} | 
|  | 224 | +		else { | 
|  | 225 | +			super.visitQuerySpec( querySpec ); | 
|  | 226 | +		} | 
|  | 227 | +	} | 
| 198 | 228 | } | 
0 commit comments