From 3f8a8cd413b0d1e4c66e01a05014e32e9de8466a Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 16 Sep 2025 15:50:33 +0200 Subject: [PATCH] Fix HQL rendering of CTE with CYCLE clause. Ensure SET identifier is an expression. Closes #4012 --- .../repository/query/HqlQueryRenderer.java | 8 +++--- .../query/HqlQueryRendererTests.java | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryRenderer.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryRenderer.java index a6936ddbb..366b6f3e1 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryRenderer.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryRenderer.java @@ -195,22 +195,22 @@ class HqlQueryRenderer extends HqlBaseVisitor { QueryRendererBuilder builder = QueryRenderer.builder(); builder.append(QueryTokens.expression(ctx.CYCLE().getText())); - builder.append(visit(ctx.cteAttributes())); + builder.appendExpression(visit(ctx.cteAttributes())); builder.append(QueryTokens.expression(ctx.SET().getText())); - builder.append(visit(ctx.identifier(0))); + builder.appendExpression(visit(ctx.identifier(0))); if (ctx.TO() != null) { builder.append(QueryTokens.expression(ctx.TO().getText())); builder.append(visit(ctx.literal(0))); builder.append(QueryTokens.expression(ctx.DEFAULT().getText())); - builder.append(visit(ctx.literal(1))); + builder.appendExpression(visit(ctx.literal(1))); } if (ctx.USING() != null) { builder.append(QueryTokens.expression(ctx.USING().getText())); - builder.append(visit(ctx.identifier(1))); + builder.appendExpression(visit(ctx.identifier(1))); } return builder; diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java index f9d56fdf7..d064fd4d3 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java @@ -1730,6 +1730,31 @@ class HqlQueryRendererTests { """); } + @Test // GH-4012 + void cteWithSearch() { + + assertQuery(""" + WITH Tree AS (SELECT o.uuid AS test_uuid FROM DemoEntity o) + SEARCH BREADTH FIRST BY foo ASC NULLS FIRST, bar DESC NULLS LAST SET baz + SELECT test_uuid FROM Tree + """); + } + + @Test // GH-4012 + void cteWithCycle() { + + assertQuery(""" + WITH Tree AS (SELECT o.uuid AS test_uuid FROM DemoEntity o) CYCLE test_uuid SET circular TO true DEFAULT false + SELECT test_uuid FROM Tree + """); + + assertQuery( + """ + WITH Tree AS (SELECT o.uuid AS test_uuid FROM DemoEntity o) CYCLE test_uuid SET circular TO true DEFAULT false USING bar + SELECT test_uuid FROM Tree + """); + } + @Test // GH-2982 void floorShouldBeValidEntityName() {