This is an automated email from the ASF dual-hosted git repository. kxiao pushed a commit to branch branch-2.0 in repository https://gitbox.apache.org/repos/asf/doris.git
commit cbb353edc8bb9ae82d6712606386e71a09e1be3f Author: starocean999 <40539150+starocean...@users.noreply.github.com> AuthorDate: Fri Oct 20 15:37:44 2023 +0800 [fix](nereids)fix bug of duplicate name of inline view (#25627) --- .../apache/doris/nereids/analyzer/UnboundSlot.java | 5 + .../nereids/rules/analysis/BindExpression.java | 4 +- .../doris/nereids/trees/expressions/Alias.java | 4 +- .../doris/nereids/trees/expressions/Slot.java | 4 + .../nereids/trees/expressions/SlotReference.java | 41 +++++--- .../subquery/test_duplicate_name_in_view.groovy | 108 ++++++++++++++++++++- 6 files changed, 151 insertions(+), 15 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundSlot.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundSlot.java index 47bad57f58c..b8eccbff8fb 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundSlot.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundSlot.java @@ -63,6 +63,11 @@ public class UnboundSlot extends Slot implements Unbound, PropagateNullable { return nameParts.subList(0, nameParts.size() - 1); } + @Override + public String getInternalName() { + return getName(); + } + @Override public String toSql() { return nameParts.stream().map(Utils::quoteIfNeeded).reduce((left, right) -> left + "." + right).orElse(""); 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 ecd8ce93cab..6f21d621964 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 @@ -708,11 +708,11 @@ public class BindExpression implements AnalysisRuleFactory { private void checkSameNameSlot(List<Slot> childOutputs, String subQueryAlias) { Set<String> nameSlots = new HashSet<>(); for (Slot s : childOutputs) { - if (nameSlots.contains(s.getName())) { + if (nameSlots.contains(s.getInternalName())) { throw new AnalysisException("Duplicated inline view column alias: '" + s.getName() + "'" + " in inline view: '" + subQueryAlias + "'"); } else { - nameSlots.add(s.getName()); + nameSlots.add(s.getInternalName()); } } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Alias.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Alias.java index 0e91dec26c3..b02c968baba 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Alias.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Alias.java @@ -27,6 +27,7 @@ import com.google.common.collect.ImmutableList; import java.util.List; import java.util.Objects; +import java.util.Optional; /** * Expression for alias, such as col1 as c1. @@ -73,7 +74,8 @@ public class Alias extends NamedExpression implements UnaryExpression { return new SlotReference(exprId, name, child().getDataType(), child().nullable(), qualifier, child() instanceof SlotReference ? ((SlotReference) child()).getColumn().orElse(null) - : null); + : null, + nameFromChild ? Optional.of(child().toString()) : Optional.of(name)); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Slot.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Slot.java index 8b1f7628bf5..b587a26864e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Slot.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Slot.java @@ -52,4 +52,8 @@ public abstract class Slot extends NamedExpression implements LeafExpression { public Slot withExprId(ExprId exprId) { throw new RuntimeException("Do not implement"); } + + public String getInternalName() { + throw new RuntimeException("Do not implement"); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/SlotReference.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/SlotReference.java index b76cc77a51c..db0f4e66359 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/SlotReference.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/SlotReference.java @@ -38,22 +38,34 @@ public class SlotReference extends Slot { protected final DataType dataType; protected final boolean nullable; protected final List<String> qualifier; + + // the unique string representation of a SlotReference + // different SlotReference will have different internalName + // TODO: remove this member variable after mv selection is refactored + protected final Optional<String> internalName; + private final Column column; public SlotReference(String name, DataType dataType) { - this(StatementScopeIdGenerator.newExprId(), name, dataType, true, ImmutableList.of(), null); + this(StatementScopeIdGenerator.newExprId(), name, dataType, true, ImmutableList.of(), null, Optional.empty()); } public SlotReference(String name, DataType dataType, boolean nullable) { - this(StatementScopeIdGenerator.newExprId(), name, dataType, nullable, ImmutableList.of(), null); + this(StatementScopeIdGenerator.newExprId(), name, dataType, nullable, ImmutableList.of(), + null, Optional.empty()); } public SlotReference(String name, DataType dataType, boolean nullable, List<String> qualifier) { - this(StatementScopeIdGenerator.newExprId(), name, dataType, nullable, qualifier, null); + this(StatementScopeIdGenerator.newExprId(), name, dataType, nullable, qualifier, null, Optional.empty()); } public SlotReference(ExprId exprId, String name, DataType dataType, boolean nullable, List<String> qualifier) { - this(exprId, name, dataType, nullable, qualifier, null); + this(exprId, name, dataType, nullable, qualifier, null, Optional.empty()); + } + + public SlotReference(ExprId exprId, String name, DataType dataType, boolean nullable, + List<String> qualifier, @Nullable Column column) { + this(exprId, name, dataType, nullable, qualifier, column, Optional.empty()); } /** @@ -65,15 +77,17 @@ public class SlotReference extends Slot { * @param nullable true if nullable * @param qualifier slot reference qualifier * @param column the column which this slot come from + * @param internalName the internalName of this slot */ public SlotReference(ExprId exprId, String name, DataType dataType, boolean nullable, - List<String> qualifier, @Nullable Column column) { + List<String> qualifier, @Nullable Column column, Optional<String> internalName) { this.exprId = exprId; this.name = name; this.dataType = dataType; this.qualifier = ImmutableList.copyOf(Objects.requireNonNull(qualifier, "qualifier can not be null")); this.nullable = nullable; this.column = column; + this.internalName = internalName.isPresent() ? internalName : Optional.of(name); } public static SlotReference of(String name, DataType type) { @@ -83,13 +97,13 @@ public class SlotReference extends Slot { public static SlotReference fromColumn(Column column, List<String> qualifier) { DataType dataType = DataType.fromCatalogType(column.getType()); return new SlotReference(StatementScopeIdGenerator.newExprId(), column.getName(), dataType, - column.isAllowNull(), qualifier, column); + column.isAllowNull(), qualifier, column, Optional.empty()); } public static SlotReference fromColumn(Column column, String name, List<String> qualifier) { DataType dataType = DataType.fromCatalogType(column.getType()); return new SlotReference(StatementScopeIdGenerator.newExprId(), name, dataType, - column.isAllowNull(), qualifier, column); + column.isAllowNull(), qualifier, column, Optional.empty()); } @Override @@ -117,6 +131,11 @@ public class SlotReference extends Slot { return nullable; } + @Override + public String getInternalName() { + return internalName.get(); + } + @Override public String toSql() { return name; @@ -185,22 +204,22 @@ public class SlotReference extends Slot { if (this.nullable == newNullable) { return this; } - return new SlotReference(exprId, name, dataType, newNullable, qualifier, column); + return new SlotReference(exprId, name, dataType, newNullable, qualifier, column, internalName); } @Override public SlotReference withQualifier(List<String> qualifier) { - return new SlotReference(exprId, name, dataType, nullable, qualifier, column); + return new SlotReference(exprId, name, dataType, nullable, qualifier, column, internalName); } @Override public SlotReference withName(String name) { - return new SlotReference(exprId, name, dataType, nullable, qualifier, column); + return new SlotReference(exprId, name, dataType, nullable, qualifier, column, internalName); } @Override public SlotReference withExprId(ExprId exprId) { - return new SlotReference(exprId, name, dataType, nullable, qualifier, column); + return new SlotReference(exprId, name, dataType, nullable, qualifier, column, internalName); } public boolean isVisible() { diff --git a/regression-test/suites/nereids_p0/subquery/test_duplicate_name_in_view.groovy b/regression-test/suites/nereids_p0/subquery/test_duplicate_name_in_view.groovy index fd5f093a3e8..636548c399f 100644 --- a/regression-test/suites/nereids_p0/subquery/test_duplicate_name_in_view.groovy +++ b/regression-test/suites/nereids_p0/subquery/test_duplicate_name_in_view.groovy @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -suite("inlineview_with_project") { +suite("test_duplicate_name_in_view") { sql "SET enable_nereids_planner=true" sql "SET enable_fallback_to_original_planner=false" sql """ @@ -58,6 +58,112 @@ suite("inlineview_with_project") { } + test { + sql """ + SELECT * + FROM + (SELECT issue_19611_t1.c0 , + issue_19611_t1.c0 + FROM issue_19611_t1 ) tmp; + """ + exception "Duplicated inline view column alias: 'c0' in inline view: 'tmp'" + } + + test { + sql """ + SELECT * + FROM + (SELECT issue_19611_t1.c0 + 1, + issue_19611_t1.c0 + 1 + FROM issue_19611_t1 ) tmp; + """ + exception "Duplicated inline view column alias: '(c0 + 1)' in inline view: 'tmp'" + } + + test { + sql """ + SELECT * + FROM + (SELECT issue_19611_t1.c0 , + issue_19611_t0.c0 + FROM issue_19611_t1, issue_19611_t0 ) tmp; + """ + exception "Duplicated inline view column alias: 'c0' in inline view: 'tmp'" + } + + test { + sql """ + SELECT * + FROM + (SELECT issue_19611_t1.c0 a, + issue_19611_t1.c0 a + FROM issue_19611_t1 ) tmp; + """ + exception "Duplicated inline view column alias: 'a' in inline view: 'tmp'" + } + + test { + sql """ + SELECT * + FROM + (SELECT issue_19611_t0.c0 + 1 a, + issue_19611_t1.c0 + 1 a + FROM issue_19611_t1, issue_19611_t0 ) tmp; + """ + exception "Duplicated inline view column alias: 'a' in inline view: 'tmp'" + } + + test { + sql """ + SELECT * + FROM + (SELECT '2023-10-07', '2023-10-07' + FROM issue_19611_t1 ) tmp; + """ + exception "Duplicated inline view column alias: ''2023-10-07'' in inline view: 'tmp'" + } + + test { + sql """ + SELECT * + FROM + (SELECT '2023-10-07' a, '2023-10-07' a + FROM issue_19611_t1 ) tmp; + """ + exception "Duplicated inline view column alias: 'a' in inline view: 'tmp'" + } + + sql """SELECT * + FROM + (SELECT issue_19611_t1.c0 + 1, + issue_19611_t0.c0 + 1 + FROM issue_19611_t1, issue_19611_t0 ) tmp; + """ + + sql """SELECT * + FROM + (SELECT issue_19611_t1.c0 a, + issue_19611_t1.c0 b + FROM issue_19611_t1 ) tmp;""" + + sql """SELECT * + FROM + (SELECT issue_19611_t1.c0 a, + issue_19611_t1.c0 + FROM issue_19611_t1 ) tmp;""" + + sql """SELECT * + FROM + (SELECT '2023-10-07' a, '2023-10-07' b + FROM issue_19611_t1 ) tmp; + """ + + sql """SELECT * + FROM + (SELECT '2023-10-07' a, '2023-10-07' + FROM issue_19611_t1 ) tmp; + """ + sql """ drop table if exists issue_19611_t0; --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org