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

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


The following commit(s) were added to refs/heads/master by this push:
     new 01d5901356c [fix](Nereids) cte should support nested name reuse 
(#25858)
01d5901356c is described below

commit 01d5901356ce5306841e752d21387779605bb44d
Author: morrySnow <[email protected]>
AuthorDate: Wed Oct 25 18:52:14 2023 +0800

    [fix](Nereids) cte should support nested name reuse (#25858)
    
    for example:
    ```sql
    with a as (with a as (select * from t) select * from a) select * from a;
    
    with a as (select * from t1), b as (with a as (select * from a) select * 
from a) select * from b;
    ```
---
 .../java/org/apache/doris/nereids/CTEContext.java  | 10 +---
 .../doris/nereids/rules/analysis/AnalyzeCTE.java   | 23 ++++++---
 .../data/nereids_p0/cte/test_cte_name_reuse.out    | 10 ++++
 .../nereids_p0/cte/test_cte_name_reuse.groovy      | 60 ++++++++++++++++++++++
 4 files changed, 87 insertions(+), 16 deletions(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/CTEContext.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/CTEContext.java
index 6bc67870708..9653811492e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/CTEContext.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/CTEContext.java
@@ -60,7 +60,8 @@ public class CTEContext {
                 : ImmutableMap.<String, CTEContext>builder()
                         .putAll(previousCteContext.cteContextMap)
                         .put(name, this)
-                        .build();
+                        // if inner name same with outer name, use inner name 
in this scope.
+                        .buildKeepingLast();
         this.cteId = cteId;
     }
 
@@ -68,13 +69,6 @@ public class CTEContext {
         this.analyzedPlan = analyzedPlan;
     }
 
-    /**
-     * check if cteName can be found in current order
-     */
-    public boolean containsCTE(String cteName) {
-        return findCTEContext(cteName).isPresent();
-    }
-
     /**
      * Get for CTE reuse.
      */
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 a465df6da13..0fe083c1e93 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
@@ -34,11 +34,13 @@ import 
org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
 import org.apache.doris.nereids.trees.plans.logical.LogicalSubQueryAlias;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Sets;
 
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * Register CTE, includes checking columnAliases, checking CTE name, analyzing 
each CTE and store the
@@ -53,6 +55,18 @@ public class AnalyzeCTE extends OneAnalysisRuleFactory {
         return logicalCTE().thenApply(ctx -> {
             LogicalCTE<Plan> logicalCTE = ctx.root;
 
+            // step 0. check duplicate cte name
+            Set<String> uniqueAlias = Sets.newHashSet();
+            List<String> aliases = logicalCTE.getAliasQueries().stream()
+                    .map(LogicalSubQueryAlias::getAlias)
+                    .collect(Collectors.toList());
+            for (String alias : aliases) {
+                if (uniqueAlias.contains(alias)) {
+                    throw new AnalysisException("CTE name [" + alias + "] 
cannot be used more than once.");
+                }
+                uniqueAlias.add(alias);
+            }
+
             // step 1. analyzed all cte plan
             Pair<CTEContext, List<LogicalCTEProducer<Plan>>> result = 
analyzeCte(logicalCTE, ctx.cascadesContext);
             CascadesContext outerCascadesCtx = 
CascadesContext.newContextWithCteContext(
@@ -76,17 +90,10 @@ public class AnalyzeCTE extends OneAnalysisRuleFactory {
         List<LogicalSubQueryAlias<Plan>> aliasQueries = 
logicalCTE.getAliasQueries();
         List<LogicalCTEProducer<Plan>> cteProducerPlans = new ArrayList<>();
         for (LogicalSubQueryAlias<Plan> aliasQuery : aliasQueries) {
-            String cteName = aliasQuery.getAlias();
-            if (outerCteCtx.containsCTE(cteName)) {
-                throw new AnalysisException("CTE name [" + cteName + "] cannot 
be used more than once.");
-            }
-
             // we should use a chain to ensure visible of cte
-            CTEContext innerCteCtx = outerCteCtx;
-
             LogicalPlan parsedCtePlan = (LogicalPlan) aliasQuery.child();
             CascadesContext innerCascadesCtx = 
CascadesContext.newContextWithCteContext(
-                    cascadesContext, parsedCtePlan, innerCteCtx);
+                    cascadesContext, parsedCtePlan, outerCteCtx);
             innerCascadesCtx.newAnalyzer().analyze();
             LogicalPlan analyzedCtePlan = (LogicalPlan) 
innerCascadesCtx.getRewritePlan();
             checkColumnAlias(aliasQuery, analyzedCtePlan.getOutput());
diff --git a/regression-test/data/nereids_p0/cte/test_cte_name_reuse.out 
b/regression-test/data/nereids_p0/cte/test_cte_name_reuse.out
new file mode 100644
index 00000000000..52966eaa688
--- /dev/null
+++ b/regression-test/data/nereids_p0/cte/test_cte_name_reuse.out
@@ -0,0 +1,10 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !reuse_name_with_other_outer_cte --
+1      1       1       1
+
+-- !reuse_name_with_other_outer_cte_and_use_outer_same_name_cte --
+1      1
+
+-- !reuse_name_with_self_outer_cte --
+1      1
+
diff --git a/regression-test/suites/nereids_p0/cte/test_cte_name_reuse.groovy 
b/regression-test/suites/nereids_p0/cte/test_cte_name_reuse.groovy
new file mode 100644
index 00000000000..5d472716f00
--- /dev/null
+++ b/regression-test/suites/nereids_p0/cte/test_cte_name_reuse.groovy
@@ -0,0 +1,60 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+suite("test_cte_name_reuse)") {
+    sql "SET enable_nereids_planner=true"
+    sql "SET enable_pipeline_engine=true"
+    sql "SET enable_fallback_to_original_planner=false"
+
+    sql """
+        drop table if exists test_cte_name_reuse;
+    """
+
+    sql """
+        CREATE TABLE `test_cte_name_reuse` (
+          `id` int(11) NULL,
+          `msg` text NULL
+        ) ENGINE=OLAP
+        DUPLICATE KEY(`id`)
+        COMMENT 'OLAP'
+        DISTRIBUTED BY HASH(`id`) BUCKETS 10
+        PROPERTIES (
+        "replication_allocation" = "tag.location.default: 1",
+        "min_load_replica_num" = "-1",
+        "is_being_synced" = "false",
+        "storage_format" = "V2",
+        "light_schema_change" = "true",
+        "disable_auto_compaction" = "false",
+        "enable_single_replica_compaction" = "false"
+        );
+    """
+
+    sql """
+        insert into test_cte_name_reuse values(1, "1");
+    """
+
+    qt_reuse_name_with_other_outer_cte """
+        with a as (select * from test_cte_name_reuse), b as (with a as (select 
* from test_cte_name_reuse) select * from a) select * from a, b;
+    """
+
+    qt_reuse_name_with_other_outer_cte_and_use_outer_same_name_cte """
+        with a as (select * from test_cte_name_reuse), b as (with a as (select 
* from a) select * from a) select * from b;
+    """
+
+    qt_reuse_name_with_self_outer_cte """
+        with a as (with a as (select * from test_cte_name_reuse) select * from 
a) select * from a;
+    """
+}


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

Reply via email to