From 18db5faf26cd5ea273fcbe33c8b4fd0742b7eb73 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 16 Sep 2025 15:50:33 +0200 Subject: [PATCH] Refine HQL rendering of CTE with SEARCH clause. Add tests for CYCLE, ensure no space between search order items. Closes #4012 --- .../repository/query/HqlQueryRenderer.java | 5 ++++ .../query/HqlQueryRendererTests.java | 25 +++++++++++++++++++ 2 files changed, 30 insertions(+) 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 58b5a3cb3..15522f026 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 @@ -131,6 +131,11 @@ class HqlQueryRenderer extends HqlBaseVisitor { return QueryTokenStream.concat(ctx.identifier(), this::visit, TOKEN_COMMA); } + @Override + public QueryTokenStream visitSearchSpecifications(HqlParser.SearchSpecificationsContext ctx) { + return QueryTokenStream.concat(ctx.searchSpecification(), this::visit, TOKEN_COMMA); + } + @Override public QueryTokenStream visitOrderedQuery(HqlParser.OrderedQueryContext ctx) { 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 f130b6cea..022983f79 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 @@ -2097,6 +2097,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() {