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 129b0860a74ee4..36a0459375b840 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 @@ -101,6 +101,8 @@ private Pair>> analyzeCte( CTEId cteId = StatementScopeIdGenerator.newCTEId(); LogicalSubQueryAlias logicalSubQueryAlias = aliasQuery.withChildren(ImmutableList.of(analyzedCtePlan)); + BindExpression.checkSameNameSlot(logicalSubQueryAlias.child(0).getOutput(), + logicalSubQueryAlias.getAlias()); outerCteCtx = new CTEContext(cteId, logicalSubQueryAlias, outerCteCtx); outerCteCtx.setAnalyzedPlan(logicalSubQueryAlias); cteProducerPlans.add(new LogicalCTEProducer<>(cteId, logicalSubQueryAlias)); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java index ea1d923f83a3f9..6f784d877dfa42 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindExpression.java @@ -951,7 +951,11 @@ private LogicalTVFRelation bindTableValuedFunction(MatchingContext childOutputs, String subQueryAlias) { + /** + * Check the slot in childOutputs is duplicated or not + * If childOutputs has duplicated column name, would throw analysis exception + */ + public static void checkSameNameSlot(List childOutputs, String subQueryAlias) { Set nameSlots = new HashSet<>(childOutputs.size() * 2); for (Slot s : childOutputs) { if (!nameSlots.add(s.getInternalName())) { diff --git a/regression-test/suites/nereids_p0/cte/test_cte_with_duplicate_consumer.groovy b/regression-test/suites/nereids_p0/cte/test_cte_with_duplicate_consumer.groovy index 4064efcfc6e2e9..b5cb03ea174405 100644 --- a/regression-test/suites/nereids_p0/cte/test_cte_with_duplicate_consumer.groovy +++ b/regression-test/suites/nereids_p0/cte/test_cte_with_duplicate_consumer.groovy @@ -14,12 +14,22 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. +import org.junit.Assert; suite("test_cte_with_duplicate_consumer") { - test { + try { sql """ WITH cte1(col1) AS (SELECT 1), cte2(col2_1, col2_2) AS (SELECT col1, col1 FROM cte1) SELECT * FROM cte2 """ + } catch (Exception e) { + // Duplicated inline view column alias: 'col1' in inline view: 'cte2'' + assertTrue(e.message.contains(" Duplicated inline view column alias")) + } + + test { + sql """ + WITH cte1(col1) AS (SELECT 1), cte2(col2_1) AS (SELECT col1 FROM cte1) SELECT * FROM cte2 + """ - result([[1, 1]]) + result([[1]]) } } diff --git a/regression-test/suites/query_p0/cte/query_with_dup_column.groovy b/regression-test/suites/query_p0/cte/query_with_dup_column.groovy new file mode 100644 index 00000000000000..be88cb44bab196 --- /dev/null +++ b/regression-test/suites/query_p0/cte/query_with_dup_column.groovy @@ -0,0 +1,112 @@ +// 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. + +import org.junit.Assert; + +suite("query_with_dup_column") { + String db = context.config.getDbNameByFile(context.file) + sql "use ${db}" + sql "set runtime_filter_mode=OFF"; + sql "SET ignore_shape_nodes='PhysicalDistribute,PhysicalProject'" + + sql """ + drop table if exists test_table; + """ + + sql """ + CREATE TABLE `test_table` ( + `unique_id` varchar(256) NULL, + `name` varchar(256) NULL + ) + PROPERTIES ( + "replication_num" = "1" + ); + """ + + sql """ + insert into test_table values ("yyyxxxzzz", "abc000000") + """ + + // should fail + try { + sql """ + with tmp1 as ( + select unique_id, unique_id from test_table + ) + select * from tmp1; + """ + } catch (Exception e) { + assertTrue(e.message.contains("Duplicated inline view column alias")) + } + + // should fail + try { + sql """ + with tmp1 as ( + select unique_id, unique_id from test_table + ) + select * from tmp1 t; + """ + } catch (Exception e) { + assertTrue(e.message.contains("Duplicated inline view column alias")) + } + + + try { + sql """ + with tmp1 as ( + select *, unique_id from test_table + ) + select * from tmp1; + """ + } catch (Exception e) { + assertTrue(e.message.contains("Duplicated inline view column alias")) + } + + // should fail + try { + sql """ + with tmp1 as ( + select *, unique_id from test_table + ) + select * from tmp1 t; + """ + } catch (Exception e) { + assertTrue(e.message.contains("Duplicated inline view column alias")) + } + + // should success + sql """ + select *, unique_id from test_table; + """ + + // should success + sql """ + select *, unique_id from test_table t; + """ + + // should success + sql """ + select unique_id, unique_id from test_table + """ + + // should success + sql """ + select unique_id, unique_id from test_table t + """ +} +