add ut
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 6261242..b734292 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 @@
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 56cea28..1921ae9 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 @@
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"));
+ }
}