This is an automated email from the ASF dual-hosted git repository.

starocean999 pushed a commit to branch dev_rec
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/dev_rec by this push:
     new d5188baad94 add ut
d5188baad94 is described below

commit d5188baad9440f90fc69fd38bae727df336de870
Author: lichi <[email protected]>
AuthorDate: Fri Oct 24 14:47:41 2025 +0800

    add ut
---
 .../doris/nereids/rules/analysis/AnalyzeCTE.java   |  4 +-
 .../nereids/rules/analysis/AnalyzeCTETest.java     | 71 ++++++++++++++++++++++
 2 files changed, 73 insertions(+), 2 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/AnalyzeCTE.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/AnalyzeCTE.java
index 62612422e08..b734292d321 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/AnalyzeCTE.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/AnalyzeCTE.java
@@ -174,8 +174,8 @@ public class AnalyzeCTE extends OneAnalysisRuleFactory {
         List<LogicalRecursiveCteScan> recursiveCteScanList = 
analyzedRecursiveChild
                 .collectToList(LogicalRecursiveCteScan.class::isInstance);
         if (recursiveCteScanList.size() > 1) {
-            throw new AnalysisException(String.format("can have only 1 
recursive cte instance, but there is %d",
-                    recursiveCteScanList.size()));
+            throw new AnalysisException(String.format("recursive reference to 
query %s must not appear more than once",
+                    aliasQuery.getAlias()));
         }
         List<Slot> anchorChildOutputs = analyzedAnchorChild.getOutput();
         List<DataType> anchorChildOutputTypes = new 
ArrayList<>(anchorChildOutputs.size());
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/AnalyzeCTETest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/AnalyzeCTETest.java
index 56cea284188..1921ae9025d 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/AnalyzeCTETest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/AnalyzeCTETest.java
@@ -481,4 +481,75 @@ public class AnalyzeCTETest extends TestWithFeService 
implements MemoPatternMatc
         Assertions.assertTrue(exception.getMessage()
                 .contains("recursive reference to query xx must not appear 
within its non-recursive term"));
     }
+
+    @Test
+    public void testRecCteNoUnionException() {
+        String sql = new StringBuilder().append("with recursive t1 as 
(\n").append("    select 1 \n")
+                .append("        intersect\n").append("    select 2 from 
t1\n").append(")\n").append("select\n")
+                .append("    *\n").append("from\n").append("    
t1").toString();
+        LogicalPlan unboundPlan = new NereidsParser().parseSingle(sql);
+        StatementContext statementContext = new 
StatementContext(connectContext,
+                new OriginStatement(sql, 0));
+        NereidsPlanner planner = new NereidsPlanner(statementContext);
+        AnalysisException exception = 
Assertions.assertThrows(AnalysisException.class,
+                () -> planner.planWithLock(unboundPlan, PhysicalProperties.ANY,
+                        ExplainCommand.ExplainLevel.ANALYZED_PLAN),
+                "Not throw expected exception.");
+        Assertions.assertTrue(exception.getMessage().contains("recursive cte 
must be union"));
+    }
+
+    @Test
+    public void testRecCteAnchorException() {
+        String sql = new StringBuilder().append("with recursive t1 as 
(\n").append("    select 1 from t1\n")
+                .append("        union\n").append("    select 2 from 
t1\n").append(")\n").append("select\n")
+                .append("    *\n").append("from\n").append("    
t1;").toString();
+        LogicalPlan unboundPlan = new NereidsParser().parseSingle(sql);
+        StatementContext statementContext = new 
StatementContext(connectContext,
+                new OriginStatement(sql, 0));
+        NereidsPlanner planner = new NereidsPlanner(statementContext);
+        AnalysisException exception = 
Assertions.assertThrows(AnalysisException.class,
+                () -> planner.planWithLock(unboundPlan, PhysicalProperties.ANY,
+                        ExplainCommand.ExplainLevel.ANALYZED_PLAN),
+                "Not throw expected exception.");
+        Assertions.assertTrue(exception.getMessage()
+                .contains("recursive reference to query t1 must not appear 
within its non-recursive term"));
+    }
+
+    @Test
+    public void testRecCteMoreThanOnceException() {
+        String sql = new StringBuilder().append("with recursive t1 as 
(\n").append("    select 1\n")
+                .append("        union\n").append("    select 2 from t1 x, t1 
y\n").append(")\n").append("select\n")
+                .append("    *\n").append("from\n").append("    
t1").toString();
+        LogicalPlan unboundPlan = new NereidsParser().parseSingle(sql);
+        StatementContext statementContext = new 
StatementContext(connectContext,
+                new OriginStatement(sql, 0));
+        NereidsPlanner planner = new NereidsPlanner(statementContext);
+        AnalysisException exception = 
Assertions.assertThrows(AnalysisException.class,
+                () -> planner.planWithLock(unboundPlan, PhysicalProperties.ANY,
+                        ExplainCommand.ExplainLevel.ANALYZED_PLAN),
+                "Not throw expected exception.");
+        Assertions.assertTrue(
+                exception.getMessage().contains("recursive reference to query 
t1 must not appear more than once"));
+    }
+
+    @Test
+    public void testRecCteInSubqueryException() {
+        String sql = new StringBuilder().append("with recursive t1 as 
(\n").append("    select\n")
+                .append("        1 as c1,\n").append("        1 as 
c2\n").append("),\n").append("xx as (\n")
+                .append("    select\n").append("        2 as c1,\n").append("  
      2 as c2\n").append("    from\n")
+                .append("        t1\n").append("    union\n").append("    
select\n").append("        3 as c1,\n")
+                .append("        3 as c2\n").append("    from\n")
+                .append("        t1 where t1.c1 in (select c1 from 
xx)\n").append(")\n").append("select\n")
+                .append("    *\n").append("from\n").append("    
xx").toString();
+        LogicalPlan unboundPlan = new NereidsParser().parseSingle(sql);
+        StatementContext statementContext = new 
StatementContext(connectContext,
+                new OriginStatement(sql, 0));
+        NereidsPlanner planner = new NereidsPlanner(statementContext);
+        AnalysisException exception = 
Assertions.assertThrows(AnalysisException.class,
+                () -> planner.planWithLock(unboundPlan, PhysicalProperties.ANY,
+                        ExplainCommand.ExplainLevel.ANALYZED_PLAN),
+                "Not throw expected exception.");
+        Assertions.assertTrue(
+                exception.getMessage().contains("Table [xx] does not exist in 
database"));
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to