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]