This is an automated email from the ASF dual-hosted git repository. yiguolei pushed a commit to branch branch-2.1 in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-2.1 by this push: new 301ff6af22c [Fix](nereids) add backquote and qualifier to udf, column, column alias and table alias when create view (#37237) (#37984) 301ff6af22c is described below commit 301ff6af22c28b18810f0ef2d76224004017f513 Author: feiniaofeiafei <53502832+feiniaofeia...@users.noreply.github.com> AuthorDate: Fri Jul 19 00:56:26 2024 +0800 [Fix](nereids) add backquote and qualifier to udf, column, column alias and table alias when create view (#37237) (#37984) cherry-pick #37237 to branch-2.1 --------- Co-authored-by: feiniaofeiafei <moail...@selectdb.com> --- .../apache/doris/nereids/analyzer/MappingSlot.java | 8 + .../doris/nereids/analyzer/UnboundFunction.java | 25 ++- .../doris/nereids/analyzer/UnboundRelation.java | 6 + .../apache/doris/nereids/analyzer/UnboundSlot.java | 16 +- .../apache/doris/nereids/analyzer/UnboundStar.java | 4 + .../doris/nereids/parser/LogicalPlanBuilder.java | 48 ++--- .../parser/LogicalPlanBuilderForCreateView.java | 209 +++++++++++++++++++++ .../apache/doris/nereids/parser/NereidsParser.java | 12 +- .../nereids/rules/analysis/BindExpression.java | 6 +- .../nereids/rules/analysis/ExpressionAnalyzer.java | 38 +++- .../doris/nereids/trees/expressions/Alias.java | 2 +- .../trees/expressions/ArrayItemReference.java | 6 + .../trees/expressions/DefaultValueSlot.java | 9 +- .../trees/expressions/MarkJoinSlotReference.java | 6 + .../doris/nereids/trees/expressions/Slot.java | 16 +- .../nereids/trees/expressions/SlotReference.java | 29 ++- .../trees/expressions/VirtualSlotReference.java | 6 + .../trees/plans/commands/info/AlterViewInfo.java | 10 +- .../trees/plans/commands/info/BaseViewInfo.java | 148 ++++++++++++++- .../trees/plans/commands/info/CreateViewInfo.java | 10 +- .../data/ddl_p0/test_alter_view_nereids.out | 2 +- regression-test/data/ddl_p0/test_create_view.out | 2 +- .../data/ddl_p0/test_create_view_nereids.out | 149 ++++++++++++++- .../test_show_create_table_and_views_nereids.out | 2 +- .../suites/ddl_p0/test_create_view.groovy | 1 + .../suites/ddl_p0/test_create_view_nereids.groovy | 113 +++++++++++ .../suites/javaudf_p0/test_javaudf_date.groovy | 22 +-- .../test_show_create_table_and_views.groovy | 1 + 28 files changed, 793 insertions(+), 113 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/MappingSlot.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/MappingSlot.java index 7e5b92e5a27..8acfb03762d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/MappingSlot.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/MappingSlot.java @@ -17,6 +17,7 @@ package org.apache.doris.nereids.analyzer; +import org.apache.doris.common.Pair; import org.apache.doris.nereids.exceptions.UnboundException; import org.apache.doris.nereids.trees.expressions.ExprId; import org.apache.doris.nereids.trees.expressions.Expression; @@ -25,6 +26,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DataType; import java.util.List; +import java.util.Optional; /** * MappingSlot. @@ -36,6 +38,7 @@ public class MappingSlot extends Slot { private final Expression mappingExpression; public MappingSlot(Slot slot, Expression mappingExpression) { + super(Optional.empty()); this.slot = slot; this.mappingExpression = mappingExpression; } @@ -112,4 +115,9 @@ public class MappingSlot extends Slot { public Slot withQualifier(List<String> qualifier) { return this; } + + @Override + public Slot withIndexInSql(Pair<Integer, Integer> index) { + return this; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundFunction.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundFunction.java index 4f9a69146b3..4e959284302 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundFunction.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundFunction.java @@ -17,6 +17,7 @@ package org.apache.doris.nereids.analyzer; +import org.apache.doris.common.Pair; import org.apache.doris.nereids.exceptions.UnboundException; import org.apache.doris.nereids.trees.expressions.Expression; import org.apache.doris.nereids.trees.expressions.functions.Function; @@ -37,23 +38,31 @@ import java.util.stream.Collectors; public class UnboundFunction extends Function implements Unbound, PropagateNullable { private final String dbName; private final boolean isDistinct; + // for create view stmt, the start and end position of the function string in original sql + private final Optional<Pair<Integer, Integer>> indexInSqlString; public UnboundFunction(String name, List<Expression> arguments) { - this(null, name, false, arguments); + this(null, name, false, arguments, Optional.empty()); } public UnboundFunction(String dbName, String name, List<Expression> arguments) { - this(dbName, name, false, arguments); + this(dbName, name, false, arguments, Optional.empty()); } public UnboundFunction(String name, boolean isDistinct, List<Expression> arguments) { - this(null, name, isDistinct, arguments); + this(null, name, isDistinct, arguments, Optional.empty()); } public UnboundFunction(String dbName, String name, boolean isDistinct, List<Expression> arguments) { + this(dbName, name, isDistinct, arguments, Optional.empty()); + } + + public UnboundFunction(String dbName, String name, boolean isDistinct, + List<Expression> arguments, Optional<Pair<Integer, Integer>> indexInSqlString) { super(name, arguments); this.dbName = dbName; this.isDistinct = isDistinct; + this.indexInSqlString = indexInSqlString; } @Override @@ -97,7 +106,7 @@ public class UnboundFunction extends Function implements Unbound, PropagateNulla @Override public UnboundFunction withChildren(List<Expression> children) { - return new UnboundFunction(dbName, getName(), isDistinct, children); + return new UnboundFunction(dbName, getName(), isDistinct, children, indexInSqlString); } @Override @@ -119,4 +128,12 @@ public class UnboundFunction extends Function implements Unbound, PropagateNulla public int hashCode() { return Objects.hash(getName(), isDistinct); } + + public UnboundFunction withIndexInSql(Pair<Integer, Integer> index) { + return new UnboundFunction(dbName, getName(), isDistinct, children, Optional.ofNullable(index)); + } + + public Optional<Pair<Integer, Integer>> getIndexInSqlString() { + return indexInSqlString; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundRelation.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundRelation.java index 8180fd8518e..b8d821e1548 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundRelation.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundRelation.java @@ -152,6 +152,12 @@ public class UnboundRelation extends LogicalRelation implements Unbound, BlockFu isTempPart, tabletIds, hints, tableSample, indexName, null, indexInSqlString, tableSnapshot); } + public UnboundRelation withIndexInSql(Pair<Integer, Integer> index) { + return new UnboundRelation(relationId, nameParts, groupExpression, Optional.of(getLogicalProperties()), + partNames, isTempPart, tabletIds, hints, tableSample, indexName, null, + Optional.of(index), tableSnapshot); + } + @Override public UnboundRelation withRelationId(RelationId relationId) { throw new UnboundException("should not call UnboundRelation's withRelationId method"); 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 8fa85966dc0..f8581256980 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 @@ -17,6 +17,7 @@ package org.apache.doris.nereids.analyzer; +import org.apache.doris.common.Pair; import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; @@ -27,6 +28,7 @@ import com.google.common.collect.Lists; import java.util.List; import java.util.Objects; +import java.util.Optional; /** * Slot has not been bound. @@ -36,13 +38,23 @@ public class UnboundSlot extends Slot implements Unbound, PropagateNullable { private final List<String> nameParts; public UnboundSlot(String... nameParts) { - this(ImmutableList.copyOf(nameParts)); + this(ImmutableList.copyOf(nameParts), Optional.empty()); } public UnboundSlot(List<String> nameParts) { + this(ImmutableList.copyOf(nameParts), Optional.empty()); + } + + public UnboundSlot(List<String> nameParts, Optional<Pair<Integer, Integer>> indexInSqlString) { + super(indexInSqlString); this.nameParts = ImmutableList.copyOf(Objects.requireNonNull(nameParts, "nameParts can not be null")); } + @Override + public Slot withIndexInSql(Pair<Integer, Integer> index) { + return new UnboundSlot(nameParts, Optional.ofNullable(index)); + } + public List<String> getNameParts() { return nameParts; } @@ -74,7 +86,7 @@ public class UnboundSlot extends Slot implements Unbound, PropagateNullable { } public static UnboundSlot quoted(String name) { - return new UnboundSlot(Lists.newArrayList(name)); + return new UnboundSlot(Lists.newArrayList(name), Optional.empty()); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundStar.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundStar.java index cf73f877d60..2875036eb07 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundStar.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/analyzer/UnboundStar.java @@ -94,4 +94,8 @@ public class UnboundStar extends NamedExpression implements LeafExpression, Unbo public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) { return visitor.visitUnboundStar(this, context); } + + public UnboundStar withIndexInSql(Pair<Integer, Integer> index) { + return new UnboundStar(qualifier, Optional.ofNullable(index)); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java index 4b430c2dac1..9ffe16d0f81 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java @@ -490,8 +490,6 @@ import java.util.stream.Collectors; */ @SuppressWarnings({"OptionalUsedAsFieldOrParameterType", "OptionalGetWithoutIsPresent"}) public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { - private final boolean forCreateView; - // Sort the parameters with token position to keep the order with original placeholders // in prepared statement.Otherwise, the order maybe broken private final Map<Token, Placeholder> tokenPosToParameters = Maps.newTreeMap((pos1, pos2) -> { @@ -502,14 +500,6 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { return pos1.getCharPositionInLine() - pos2.getCharPositionInLine(); }); - public LogicalPlanBuilder() { - forCreateView = false; - } - - public LogicalPlanBuilder(boolean forCreateView) { - this.forCreateView = forCreateView; - } - @SuppressWarnings("unchecked") protected <T> T typedVisit(ParseTree ctx) { return (T) ctx.accept(this); @@ -854,9 +844,8 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { @Override public LogicalPlan visitAlterView(AlterViewContext ctx) { List<String> nameParts = visitMultipartIdentifier(ctx.name); - LogicalPlan logicalPlan = visitQuery(ctx.query()); String querySql = getOriginSql(ctx.query()); - AlterViewInfo info = new AlterViewInfo(new TableNameInfo(nameParts), logicalPlan, querySql, + AlterViewInfo info = new AlterViewInfo(new TableNameInfo(nameParts), querySql, ctx.cols == null ? Lists.newArrayList() : visitSimpleColumnDefs(ctx.cols)); return new AlterViewCommand(info); } @@ -1356,7 +1345,7 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { /** * Create an aliased table reference. This is typically used in FROM clauses. */ - private LogicalPlan withTableAlias(LogicalPlan plan, TableAliasContext ctx) { + protected LogicalPlan withTableAlias(LogicalPlan plan, TableAliasContext ctx) { if (ctx.strictIdentifier() == null) { return plan; } @@ -1418,14 +1407,8 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { } } - MultipartIdentifierContext identifier = ctx.multipartIdentifier(); TableSample tableSample = ctx.sample() == null ? null : (TableSample) visit(ctx.sample()); - UnboundRelation relation = forCreateView ? new UnboundRelation(StatementScopeIdGenerator.newRelationId(), - tableId, partitionNames, isTempPart, tabletIdLists, relationHints, - Optional.ofNullable(tableSample), indexName, scanParams, - Optional.of(Pair.of(identifier.start.getStartIndex(), identifier.stop.getStopIndex())), - Optional.ofNullable(tableSnapshot)) : - new UnboundRelation(StatementScopeIdGenerator.newRelationId(), + UnboundRelation relation = new UnboundRelation(StatementScopeIdGenerator.newRelationId(), tableId, partitionNames, isTempPart, tabletIdLists, relationHints, Optional.ofNullable(tableSample), indexName, scanParams, Optional.ofNullable(tableSnapshot)); LogicalPlan checkedRelation = LogicalPlanBuilderAssistant.withCheckPolicy(relation); @@ -1485,9 +1468,7 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { } else { target = ImmutableList.of(); } - return forCreateView - ? new UnboundStar(target, Optional.of(Pair.of(ctx.start.getStartIndex(), ctx.stop.getStopIndex()))) - : new UnboundStar(target); + return new UnboundStar(target); }); } @@ -2272,7 +2253,8 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { UnboundSlot unboundAttribute = (UnboundSlot) e; List<String> nameParts = Lists.newArrayList(unboundAttribute.getNameParts()); nameParts.add(ctx.fieldName.getText()); - return new UnboundSlot(nameParts); + UnboundSlot slot = new UnboundSlot(nameParts, Optional.empty()); + return slot; } else { // todo: base is an expression, may be not a table name. throw new ParseException("Unsupported dereference expression: " + ctx.getText(), ctx); @@ -2484,7 +2466,7 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { @Override public EqualTo visitUpdateAssignment(UpdateAssignmentContext ctx) { - return new EqualTo(new UnboundSlot(visitMultipartIdentifier(ctx.multipartIdentifier())), + return new EqualTo(new UnboundSlot(visitMultipartIdentifier(ctx.multipartIdentifier()), Optional.empty()), getExpression(ctx.expression())); } @@ -2531,10 +2513,9 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { List<String> nameParts = visitMultipartIdentifier(ctx.name); String comment = ctx.STRING_LITERAL() == null ? "" : LogicalPlanBuilderAssistant.escapeBackSlash( ctx.STRING_LITERAL().getText().substring(1, ctx.STRING_LITERAL().getText().length() - 1)); - LogicalPlan logicalPlan = visitQuery(ctx.query()); String querySql = getOriginSql(ctx.query()); CreateViewInfo info = new CreateViewInfo(ctx.EXISTS() != null, new TableNameInfo(nameParts), - comment, logicalPlan, querySql, + comment, querySql, ctx.cols == null ? Lists.newArrayList() : visitSimpleColumnDefs(ctx.cols)); return new CreateViewCommand(info); } @@ -2962,7 +2943,7 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { * * <p>Note that query hints are ignored (both by the parser and the builder). */ - private LogicalPlan withSelectQuerySpecification( + protected LogicalPlan withSelectQuerySpecification( ParserRuleContext ctx, LogicalPlan inputRelation, SelectClauseContext selectClause, @@ -2984,10 +2965,7 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { if (!expressions.stream().allMatch(UnboundSlot.class::isInstance)) { throw new ParseException("only column name is supported in except clause", selectColumnCtx); } - UnboundStar star = forCreateView ? new UnboundStar(ImmutableList.of(), - Optional.of(Pair.of(selectColumnCtx.start.getStartIndex(), - selectColumnCtx.stop.getStopIndex()))) - : new UnboundStar(ImmutableList.of()); + UnboundStar star = new UnboundStar(ImmutableList.of()); project = new LogicalProject<>(ImmutableList.of(star), expressions, isDistinct, aggregate); } else { List<NamedExpression> projects = getNamedExpressions(selectColumnCtx.namedExpressionSeq()); @@ -3160,7 +3138,7 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { .collect(ImmutableList.toImmutableList()); } - private LogicalPlan withProjection(LogicalPlan input, SelectColumnClauseContext selectCtx, + protected LogicalPlan withProjection(LogicalPlan input, SelectColumnClauseContext selectCtx, Optional<AggClauseContext> aggCtx, boolean isDistinct) { return ParserUtils.withOrigin(selectCtx, () -> { if (aggCtx.isPresent()) { @@ -3176,9 +3154,7 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> { if (!expressions.stream().allMatch(UnboundSlot.class::isInstance)) { throw new ParseException("only column name is supported in except clause", selectCtx); } - UnboundStar star = forCreateView ? new UnboundStar(ImmutableList.of(), - Optional.of(Pair.of(selectCtx.start.getStartIndex(), selectCtx.stop.getStopIndex()))) : - new UnboundStar(ImmutableList.of()); + UnboundStar star = new UnboundStar(ImmutableList.of()); return new LogicalProject<>(ImmutableList.of(star), expressions, isDistinct, input); } else { List<NamedExpression> projects = getNamedExpressions(selectCtx.namedExpressionSeq()); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilderForCreateView.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilderForCreateView.java new file mode 100644 index 00000000000..3989a8f8988 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilderForCreateView.java @@ -0,0 +1,209 @@ +// 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. + +package org.apache.doris.nereids.parser; + +import org.apache.doris.common.Pair; +import org.apache.doris.nereids.DorisParser; +import org.apache.doris.nereids.DorisParser.AggClauseContext; +import org.apache.doris.nereids.DorisParser.AliasQueryContext; +import org.apache.doris.nereids.DorisParser.ColumnReferenceContext; +import org.apache.doris.nereids.DorisParser.DereferenceContext; +import org.apache.doris.nereids.DorisParser.GroupingElementContext; +import org.apache.doris.nereids.DorisParser.HavingClauseContext; +import org.apache.doris.nereids.DorisParser.IdentifierContext; +import org.apache.doris.nereids.DorisParser.LateralViewContext; +import org.apache.doris.nereids.DorisParser.MultipartIdentifierContext; +import org.apache.doris.nereids.DorisParser.NamedExpressionContext; +import org.apache.doris.nereids.DorisParser.SelectClauseContext; +import org.apache.doris.nereids.DorisParser.SelectColumnClauseContext; +import org.apache.doris.nereids.DorisParser.StarContext; +import org.apache.doris.nereids.DorisParser.TableAliasContext; +import org.apache.doris.nereids.DorisParser.TableNameContext; +import org.apache.doris.nereids.DorisParser.WhereClauseContext; +import org.apache.doris.nereids.analyzer.UnboundFunction; +import org.apache.doris.nereids.analyzer.UnboundRelation; +import org.apache.doris.nereids.analyzer.UnboundSlot; +import org.apache.doris.nereids.analyzer.UnboundStar; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.NamedExpression; +import org.apache.doris.nereids.trees.plans.Plan; +import org.apache.doris.nereids.trees.plans.logical.LogicalHaving; +import org.apache.doris.nereids.trees.plans.logical.LogicalPlan; +import org.apache.doris.nereids.trees.plans.logical.LogicalProject; +import org.apache.doris.nereids.trees.plans.logical.LogicalSubQueryAlias; +import org.apache.doris.nereids.util.Utils; +import org.apache.doris.qe.ConnectContext; + +import com.google.common.collect.ImmutableList; +import org.antlr.v4.runtime.ParserRuleContext; + +import java.util.Optional; + +/**LogicalPlanBuilderForCreateView*/ +public class LogicalPlanBuilderForCreateView extends LogicalPlanBuilder { + @Override + protected LogicalPlan withGenerate(LogicalPlan plan, LateralViewContext ctx) { + ConnectContext.get().getStatementContext().addIndexInSqlToString( + Pair.of(ctx.tableName.start.getStartIndex(), + ctx.tableName.stop.getStopIndex()), + Utils.qualifiedNameWithBackquote(ImmutableList.of(ctx.tableName.getText()))); + for (IdentifierContext colCtx : ctx.columnNames) { + ConnectContext.get().getStatementContext().addIndexInSqlToString( + Pair.of(colCtx.start.getStartIndex(), + colCtx.stop.getStopIndex()), + Utils.qualifiedNameWithBackquote(ImmutableList.of(colCtx.getText()))); + } + return super.withGenerate(plan, ctx); + } + + @Override + public LogicalSubQueryAlias<Plan> visitAliasQuery(AliasQueryContext ctx) { + ConnectContext.get().getStatementContext().addIndexInSqlToString( + Pair.of(ctx.identifier().start.getStartIndex(), + ctx.identifier().stop.getStopIndex()), + Utils.qualifiedNameWithBackquote(ImmutableList.of(ctx.identifier().getText()))); + if (ctx.columnAliases() != null) { + for (IdentifierContext colCtx : ctx.columnAliases().identifier()) { + ConnectContext.get().getStatementContext().addIndexInSqlToString( + Pair.of(colCtx.start.getStartIndex(), + colCtx.stop.getStopIndex()), + Utils.qualifiedNameWithBackquote(ImmutableList.of(colCtx.getText()))); + } + } + return super.visitAliasQuery(ctx); + } + + @Override + protected LogicalPlan withSelectQuerySpecification( + ParserRuleContext ctx, + LogicalPlan inputRelation, + SelectClauseContext selectClause, + Optional<WhereClauseContext> whereClause, + Optional<AggClauseContext> aggClause, + Optional<HavingClauseContext> havingClause) { + LogicalPlan plan = super.withSelectQuerySpecification(ctx, inputRelation, selectClause, whereClause, + aggClause, havingClause); + SelectColumnClauseContext selectColumnCtx = selectClause.selectColumnClause(); + if ((!aggClause.isPresent() || isRepeat(aggClause.get())) && havingClause.isPresent() + && selectColumnCtx.EXCEPT() != null + && plan instanceof LogicalHaving && plan.child(0) instanceof LogicalProject) { + LogicalHaving<LogicalProject<Plan>> having = (LogicalHaving) plan; + LogicalProject<Plan> project = having.child(); + UnboundStar star = (UnboundStar) project.getProjects().get(0); + star = star.withIndexInSql(Pair.of(selectColumnCtx.start.getStartIndex(), + selectColumnCtx.stop.getStopIndex())); + project = project.withProjects(ImmutableList.of(star)); + return (LogicalPlan) plan.withChildren(project); + } else { + return plan; + } + } + + @Override + protected LogicalPlan withProjection(LogicalPlan input, SelectColumnClauseContext selectCtx, + Optional<AggClauseContext> aggCtx, boolean isDistinct) { + LogicalPlan plan = super.withProjection(input, selectCtx, aggCtx, isDistinct); + if (!aggCtx.isPresent() && selectCtx.EXCEPT() != null && plan instanceof LogicalProject) { + LogicalProject<Plan> project = (LogicalProject) plan; + UnboundStar star = (UnboundStar) project.getProjects().get(0); + star = star.withIndexInSql(Pair.of(selectCtx.start.getStartIndex(), selectCtx.stop.getStopIndex())); + return project.withProjects(ImmutableList.of(star)); + } else { + return plan; + } + } + + @Override + protected LogicalPlan withTableAlias(LogicalPlan plan, TableAliasContext ctx) { + if (ctx.strictIdentifier() == null) { + return plan; + } + String alias = ctx.strictIdentifier().getText(); + ConnectContext.get().getStatementContext().addIndexInSqlToString( + Pair.of(ctx.strictIdentifier().start.getStartIndex(), + ctx.strictIdentifier().stop.getStopIndex()), + Utils.qualifiedNameWithBackquote(ImmutableList.of(alias))); + return super.withTableAlias(plan, ctx); + } + + @Override + public LogicalPlan visitTableName(TableNameContext ctx) { + LogicalPlan plan = super.visitTableName(ctx); + MultipartIdentifierContext identifier = ctx.multipartIdentifier(); + return (LogicalPlan) plan.rewriteDownShortCircuit(node -> { + if (node instanceof UnboundRelation) { + UnboundRelation relation = (UnboundRelation) node; + return relation.withIndexInSql(Pair.of(identifier.start.getStartIndex(), + identifier.stop.getStopIndex())); + } + return node; + }); + } + + @Override + public Expression visitStar(StarContext ctx) { + Expression expr = super.visitStar(ctx); + UnboundStar star = (UnboundStar) expr; + return star.withIndexInSql(Pair.of(ctx.start.getStartIndex(), ctx.stop.getStopIndex())); + } + + @Override + public NamedExpression visitNamedExpression(NamedExpressionContext ctx) { + if (ctx.identifierOrText() != null) { + String alias = visitIdentifierOrText(ctx.identifierOrText()); + ConnectContext.get().getStatementContext().addIndexInSqlToString( + Pair.of(ctx.identifierOrText().start.getStartIndex(), + ctx.identifierOrText().stop.getStopIndex()), + Utils.qualifiedNameWithBackquote(ImmutableList.of(alias))); + } + return super.visitNamedExpression(ctx); + } + + @Override + public Expression visitFunctionCallExpression(DorisParser.FunctionCallExpressionContext ctx) { + Expression expr = super.visitFunctionCallExpression(ctx); + if (expr instanceof UnboundFunction) { + UnboundFunction function = (UnboundFunction) expr; + function = function.withIndexInSql(Pair.of( + ctx.functionIdentifier().start.getStartIndex(), + ctx.functionIdentifier().stop.getStopIndex())); + return function; + } else { + return expr; + } + } + + @Override + public Expression visitDereference(DereferenceContext ctx) { + UnboundSlot slot = (UnboundSlot) super.visitDereference(ctx); + return slot.withIndexInSql(Pair.of(ctx.start.getStartIndex(), ctx.stop.getStopIndex())); + } + + @Override + public Expression visitColumnReference(ColumnReferenceContext ctx) { + Expression expr = super.visitColumnReference(ctx); + UnboundSlot slot = (UnboundSlot) expr; + return slot.withIndexInSql(Pair.of(ctx.start.getStartIndex(), ctx.stop.getStopIndex())); + } + + private boolean isRepeat(AggClauseContext ctx) { + GroupingElementContext groupingElementContext = ctx.groupingElement(); + return groupingElementContext.GROUPING() != null || groupingElementContext.CUBE() != null + || groupingElementContext.ROLLUP() != null; + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/NereidsParser.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/NereidsParser.java index 35e1a6a354b..58854b1a293 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/NereidsParser.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/NereidsParser.java @@ -278,15 +278,9 @@ public class NereidsParser { } public LogicalPlan parseForCreateView(String sql) { - return parseForCreateViewInternal(sql, null, DorisParser::singleStatement); - } - - private <T> T parseForCreateViewInternal(String sql, @Nullable LogicalPlanBuilder logicalPlanBuilder, - Function<DorisParser, ParserRuleContext> parseFunction) { - ParserRuleContext tree = toAst(sql, parseFunction); - LogicalPlanBuilder realLogicalPlanBuilder = logicalPlanBuilder == null - ? new LogicalPlanBuilder(true) : logicalPlanBuilder; - return (T) realLogicalPlanBuilder.visit(tree); + ParserRuleContext tree = toAst(sql, DorisParser::singleStatement); + LogicalPlanBuilder realLogicalPlanBuilder = new LogicalPlanBuilderForCreateView(); + return (LogicalPlan) realLogicalPlanBuilder.visit(tree); } /** toAst */ 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 c1080adf3b7..8a74d71917c 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 @@ -591,9 +591,9 @@ public class BindExpression implements AnalysisRuleFactory { // for create view stmt expand star List<Slot> slotsForLambda = slots; UnboundStar unboundStar = (UnboundStar) expression; - unboundStar.getIndexInSqlString().ifPresent(pair -> - statementContext.addIndexInSqlToString(pair, toSqlWithBackquote(slotsForLambda)) - ); + unboundStar.getIndexInSqlString().ifPresent(pair -> { + statementContext.addIndexInSqlToString(pair, toSqlWithBackquote(slotsForLambda)); + }); } } return project.withProjects(boundProjections.build()); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ExpressionAnalyzer.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ExpressionAnalyzer.java index b9f34b91bf0..fc9e1385b59 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ExpressionAnalyzer.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ExpressionAnalyzer.java @@ -73,6 +73,7 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.Nvl; import org.apache.doris.nereids.trees.expressions.functions.udf.AliasUdfBuilder; import org.apache.doris.nereids.trees.expressions.functions.udf.JavaUdaf; import org.apache.doris.nereids.trees.expressions.functions.udf.JavaUdf; +import org.apache.doris.nereids.trees.expressions.functions.udf.UdfBuilder; import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral; import org.apache.doris.nereids.trees.expressions.literal.IntegerLikeLiteral; import org.apache.doris.nereids.trees.expressions.literal.Literal; @@ -378,7 +379,8 @@ public class ExpressionAnalyzer extends SubExprAnalyzer<ExpressionRewriteContext .build() : (List) unboundFunction.getArguments(); - if (StringUtils.isEmpty(unboundFunction.getDbName())) { + String dbName = unboundFunction.getDbName(); + if (StringUtils.isEmpty(dbName)) { // we will change arithmetic function like add(), subtract(), bitnot() // to the corresponding objects rather than BoundFunction. ArithmeticFunctionBinder functionBinder = new ArithmeticFunctionBinder(); @@ -390,7 +392,16 @@ public class ExpressionAnalyzer extends SubExprAnalyzer<ExpressionRewriteContext String functionName = unboundFunction.getName(); FunctionBuilder builder = functionRegistry.findFunctionBuilder( - unboundFunction.getDbName(), functionName, arguments); + dbName, functionName, arguments); + // for create view stmt + if (builder instanceof UdfBuilder) { + unboundFunction.getIndexInSqlString().ifPresent(index -> { + ConnectContext.get().getStatementContext().addIndexInSqlToString(index, + Utils.qualifiedNameWithBackquote(ImmutableList.of(null == dbName + ? ConnectContext.get().getDatabase() : dbName, functionName))); + }); + } + Pair<? extends Expression, ? extends BoundFunction> buildResult = builder.build(functionName, arguments); Optional<SqlCacheContext> sqlCacheContext = Optional.empty(); if (wantToParseSqlFromSqlCache) { @@ -716,27 +727,40 @@ public class ExpressionAnalyzer extends SubExprAnalyzer<ExpressionRewriteContext return !extractSlots.isEmpty() ? extractSlots : candidates; } + private List<Slot> addSqlIndexInfo(List<Slot> slots, Optional<Pair<Integer, Integer>> indexInSql) { + if (!indexInSql.isPresent()) { + return slots; + } + List<Slot> newSlots = new ArrayList<>(); + for (Slot slot : slots) { + newSlots.add(slot.withIndexInSql(indexInSql.get())); + } + return newSlots; + } + /** bindSlotByScope */ public List<Slot> bindSlotByScope(UnboundSlot unboundSlot, Scope scope) { List<String> nameParts = unboundSlot.getNameParts(); + Optional<Pair<Integer, Integer>> idxInSql = unboundSlot.getIndexInSqlString(); int namePartSize = nameParts.size(); switch (namePartSize) { // column case 1: { - return bindSingleSlotByName(nameParts.get(0), scope); + return addSqlIndexInfo(bindSingleSlotByName(nameParts.get(0), scope), idxInSql); } // table.column case 2: { - return bindSingleSlotByTable(nameParts.get(0), nameParts.get(1), scope); + return addSqlIndexInfo(bindSingleSlotByTable(nameParts.get(0), nameParts.get(1), scope), idxInSql); } // db.table.column case 3: { - return bindSingleSlotByDb(nameParts.get(0), nameParts.get(1), nameParts.get(2), scope); + return addSqlIndexInfo(bindSingleSlotByDb(nameParts.get(0), nameParts.get(1), nameParts.get(2), scope), + idxInSql); } // catalog.db.table.column case 4: { - return bindSingleSlotByCatalog( - nameParts.get(0), nameParts.get(1), nameParts.get(2), nameParts.get(3), scope); + return addSqlIndexInfo(bindSingleSlotByCatalog( + nameParts.get(0), nameParts.get(1), nameParts.get(2), nameParts.get(3), scope), idxInSql); } default: { throw new AnalysisException("Not supported name: " + StringUtils.join(nameParts, ".")); 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 af9347a169b..6b31fc60f27 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 @@ -95,7 +95,7 @@ public class Alias extends NamedExpression implements UnaryExpression { internalName, slotReference != null ? slotReference.getSubPath() - : ImmutableList.of() + : ImmutableList.of(), Optional.empty() ); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ArrayItemReference.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ArrayItemReference.java index 62137a4d30c..1a853207cc6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ArrayItemReference.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/ArrayItemReference.java @@ -17,6 +17,7 @@ package org.apache.doris.nereids.trees.expressions; +import org.apache.doris.common.Pair; import org.apache.doris.nereids.trees.expressions.typecoercion.ExpectsInputTypes; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.ArrayType; @@ -161,6 +162,11 @@ public class ArrayItemReference extends NamedExpression implements ExpectsInputT return new ArrayItemSlot(exprId, name.get(), dataType, nullable); } + @Override + public Slot withIndexInSql(Pair<Integer, Integer> index) { + return this; + } + @Override public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) { return visitor.visitArrayItemSlot(this, context); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/DefaultValueSlot.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/DefaultValueSlot.java index 6c65692dd5f..a66428dc982 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/DefaultValueSlot.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/DefaultValueSlot.java @@ -17,18 +17,21 @@ package org.apache.doris.nereids.trees.expressions; +import org.apache.doris.common.Pair; import org.apache.doris.nereids.exceptions.UnboundException; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DataType; import org.apache.doris.nereids.types.NullType; +import java.util.Optional; + /** * only use for insert into t values(DEFAULT, ...) */ public class DefaultValueSlot extends Slot { public DefaultValueSlot() { - super(); + super(Optional.empty()); } @Override @@ -60,4 +63,8 @@ public class DefaultValueSlot extends Slot { public String toString() { return "DEFAULT_VALUE"; } + + public Slot withIndexInSql(Pair<Integer, Integer> index) { + return this; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/MarkJoinSlotReference.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/MarkJoinSlotReference.java index bfbd24647e7..e840a32b7c6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/MarkJoinSlotReference.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/MarkJoinSlotReference.java @@ -17,6 +17,7 @@ package org.apache.doris.nereids.trees.expressions; +import org.apache.doris.common.Pair; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.BooleanType; @@ -78,4 +79,9 @@ public class MarkJoinSlotReference extends SlotReference { public SlotReference withName(String name) { return new MarkJoinSlotReference(exprId, name, existsHasAgg); } + + @Override + public Slot withIndexInSql(Pair<Integer, Integer> index) { + return this; + } } 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 b587a26864e..2460c964463 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 @@ -17,19 +17,25 @@ package org.apache.doris.nereids.trees.expressions; +import org.apache.doris.common.Pair; import org.apache.doris.nereids.trees.expressions.shape.LeafExpression; import com.google.common.collect.ImmutableList; import java.util.List; +import java.util.Optional; /** * Abstract class for all slot in expression. */ public abstract class Slot extends NamedExpression implements LeafExpression { + // for create view, the start and end position of the sql substring + // (e.g. "col1", "t1.col1", "db1.t1.col1", "ctl1.db1.t1.col1") + protected final Optional<Pair<Integer, Integer>> indexInSqlString; - protected Slot() { + protected Slot(Optional<Pair<Integer, Integer>> indexInSqlString) { super(ImmutableList.of()); + this.indexInSqlString = indexInSqlString; } @Override @@ -56,4 +62,12 @@ public abstract class Slot extends NamedExpression implements LeafExpression { public String getInternalName() { throw new RuntimeException("Do not implement"); } + + public Slot withIndexInSql(Pair<Integer, Integer> index) { + throw new RuntimeException("Do not implement"); + } + + public Optional<Pair<Integer, Integer>> getIndexInSqlString() { + return indexInSqlString; + } } 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 b5fb57abf3c..920bb791b5b 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 @@ -19,6 +19,7 @@ package org.apache.doris.nereids.trees.expressions; import org.apache.doris.catalog.Column; import org.apache.doris.catalog.TableIf; +import org.apache.doris.common.Pair; import org.apache.doris.nereids.exceptions.UnboundException; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.types.DataType; @@ -89,7 +90,7 @@ public class SlotReference extends Slot { List<String> qualifier, @Nullable TableIf table, @Nullable Column column, Optional<String> internalName, List<String> subColLabels) { this(exprId, () -> name, dataType, nullable, qualifier, table, column, - buildInternalName(() -> name, subColLabels, internalName), subColLabels); + buildInternalName(() -> name, subColLabels, internalName), subColLabels, Optional.empty()); } /** @@ -106,7 +107,9 @@ public class SlotReference extends Slot { */ public SlotReference(ExprId exprId, Supplier<String> name, DataType dataType, boolean nullable, List<String> qualifier, @Nullable TableIf table, @Nullable Column column, - Supplier<Optional<String>> internalName, List<String> subPath) { + Supplier<Optional<String>> internalName, List<String> subPath, + Optional<Pair<Integer, Integer>> indexInSql) { + super(indexInSql); this.exprId = exprId; this.name = name; this.dataType = dataType; @@ -132,7 +135,7 @@ public class SlotReference extends Slot { DataType dataType = DataType.fromCatalogType(column.getType()); return new SlotReference(StatementScopeIdGenerator.newExprId(), column::getName, dataType, column.isAllowNull(), qualifier, table, column, - () -> Optional.of(column.getName()), ImmutableList.of()); + () -> Optional.of(column.getName()), ImmutableList.of(), Optional.empty()); } public static SlotReference fromColumn(TableIf table, Column column, String name, List<String> qualifier) { @@ -250,13 +253,15 @@ public class SlotReference extends Slot { if (this.nullable == newNullable) { return this; } + return new SlotReference(exprId, name, dataType, newNullable, - qualifier, table, column, internalName, subPath); + qualifier, table, column, internalName, subPath, indexInSqlString); } @Override public SlotReference withQualifier(List<String> qualifier) { - return new SlotReference(exprId, name, dataType, nullable, qualifier, table, column, internalName, subPath); + return new SlotReference(exprId, name, dataType, nullable, qualifier, table, column, internalName, subPath, + indexInSqlString); } @Override @@ -265,17 +270,25 @@ public class SlotReference extends Slot { return this; } return new SlotReference( - exprId, () -> name, dataType, nullable, qualifier, table, column, internalName, subPath); + exprId, () -> name, dataType, nullable, qualifier, table, column, internalName, subPath, + indexInSqlString); } @Override public SlotReference withExprId(ExprId exprId) { - return new SlotReference(exprId, name, dataType, nullable, qualifier, table, column, internalName, subPath); + return new SlotReference(exprId, name, dataType, nullable, qualifier, table, column, internalName, subPath, + indexInSqlString); } public SlotReference withSubPath(List<String> subPath) { return new SlotReference(exprId, name, dataType, !subPath.isEmpty() || nullable, - qualifier, table, column, internalName, subPath); + qualifier, table, column, internalName, subPath, indexInSqlString); + } + + @Override + public Slot withIndexInSql(Pair<Integer, Integer> index) { + return new SlotReference(exprId, name, dataType, nullable, qualifier, table, column, internalName, subPath, + Optional.ofNullable(index)); } public boolean isVisible() { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/VirtualSlotReference.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/VirtualSlotReference.java index b9b9eeb9b2f..326bd202cd5 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/VirtualSlotReference.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/VirtualSlotReference.java @@ -17,6 +17,7 @@ package org.apache.doris.nereids.trees.expressions; +import org.apache.doris.common.Pair; import org.apache.doris.nereids.trees.expressions.functions.scalar.GroupingScalarFunction; import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; import org.apache.doris.nereids.trees.plans.algebra.Repeat.GroupingSetShapes; @@ -145,4 +146,9 @@ public class VirtualSlotReference extends SlotReference implements SlotNotFromCh return new VirtualSlotReference(exprId, name.get(), dataType, nullable, qualifier, originExpression, computeLongValueMethod); } + + @Override + public Slot withIndexInSql(Pair<Integer, Integer> index) { + return this; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AlterViewInfo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AlterViewInfo.java index 55798377145..7627f89d75d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AlterViewInfo.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/AlterViewInfo.java @@ -33,12 +33,9 @@ import org.apache.doris.common.util.Util; import org.apache.doris.mysql.privilege.PrivPredicate; import org.apache.doris.nereids.NereidsPlanner; import org.apache.doris.nereids.analyzer.UnboundResultSink; -import org.apache.doris.nereids.exceptions.AnalysisException; import org.apache.doris.nereids.properties.PhysicalProperties; import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.plans.commands.ExplainCommand.ExplainLevel; -import org.apache.doris.nereids.trees.plans.logical.LogicalFileSink; -import org.apache.doris.nereids.trees.plans.logical.LogicalPlan; import org.apache.doris.qe.ConnectContext; import com.google.common.collect.Lists; @@ -50,12 +47,9 @@ import java.util.Set; /** AlterViewInfo */ public class AlterViewInfo extends BaseViewInfo { /** constructor*/ - public AlterViewInfo(TableNameInfo viewName, LogicalPlan logicalQuery, + public AlterViewInfo(TableNameInfo viewName, String querySql, List<SimpleColumnDefinition> simpleColumnDefinitions) { - super(viewName, logicalQuery, querySql, simpleColumnDefinitions); - if (logicalQuery instanceof LogicalFileSink) { - throw new AnalysisException("Not support OUTFILE clause in ALTER VIEW statement"); - } + super(viewName, querySql, simpleColumnDefinitions); } /** init */ diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/BaseViewInfo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/BaseViewInfo.java index e0b00edf7fe..0cbaa167fdf 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/BaseViewInfo.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/BaseViewInfo.java @@ -18,6 +18,7 @@ package org.apache.doris.nereids.trees.plans.commands.info; import org.apache.doris.catalog.Column; +import org.apache.doris.common.AnalysisException; import org.apache.doris.common.ErrorCode; import org.apache.doris.common.ErrorReport; import org.apache.doris.common.Pair; @@ -31,18 +32,35 @@ import org.apache.doris.nereids.analyzer.UnboundResultSink; import org.apache.doris.nereids.jobs.executor.AbstractBatchJobExecutor; import org.apache.doris.nereids.jobs.rewrite.RewriteJob; import org.apache.doris.nereids.parser.NereidsParser; +import org.apache.doris.nereids.properties.OrderKey; import org.apache.doris.nereids.properties.PhysicalProperties; import org.apache.doris.nereids.rules.analysis.AnalyzeCTE; import org.apache.doris.nereids.rules.analysis.BindExpression; import org.apache.doris.nereids.rules.analysis.BindRelation; import org.apache.doris.nereids.rules.analysis.CheckPolicy; import org.apache.doris.nereids.rules.analysis.EliminateLogicalSelectHint; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.NamedExpression; import org.apache.doris.nereids.trees.expressions.Slot; +import org.apache.doris.nereids.trees.expressions.visitor.DefaultExpressionVisitor; import org.apache.doris.nereids.trees.plans.Plan; +import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate; import org.apache.doris.nereids.trees.plans.logical.LogicalCTEAnchor; import org.apache.doris.nereids.trees.plans.logical.LogicalCTEProducer; +import org.apache.doris.nereids.trees.plans.logical.LogicalFileSink; +import org.apache.doris.nereids.trees.plans.logical.LogicalFilter; +import org.apache.doris.nereids.trees.plans.logical.LogicalGenerate; +import org.apache.doris.nereids.trees.plans.logical.LogicalHaving; +import org.apache.doris.nereids.trees.plans.logical.LogicalJoin; import org.apache.doris.nereids.trees.plans.logical.LogicalPlan; +import org.apache.doris.nereids.trees.plans.logical.LogicalProject; +import org.apache.doris.nereids.trees.plans.logical.LogicalRepeat; +import org.apache.doris.nereids.trees.plans.logical.LogicalSort; +import org.apache.doris.nereids.trees.plans.logical.LogicalTopN; +import org.apache.doris.nereids.trees.plans.logical.LogicalView; +import org.apache.doris.nereids.trees.plans.logical.LogicalWindow; import org.apache.doris.nereids.trees.plans.visitor.DefaultPlanVisitor; +import org.apache.doris.nereids.util.Utils; import org.apache.doris.qe.ConnectContext; import com.google.common.collect.Lists; @@ -53,27 +71,31 @@ import org.apache.commons.lang3.StringUtils; import java.util.List; import java.util.Map; +import java.util.TreeMap; /** BaseViewInfo */ public class BaseViewInfo { protected final TableNameInfo viewName; - protected final LogicalPlan logicalQuery; + protected LogicalPlan logicalQuery; protected final String querySql; protected final List<SimpleColumnDefinition> simpleColumnDefinitions; protected final List<Column> finalCols = Lists.newArrayList(); protected Plan analyzedPlan; - public BaseViewInfo(TableNameInfo viewName, LogicalPlan logicalQuery, + public BaseViewInfo(TableNameInfo viewName, String querySql, List<SimpleColumnDefinition> simpleColumnDefinitions) { this.viewName = viewName; - this.logicalQuery = logicalQuery; this.querySql = querySql; this.simpleColumnDefinitions = simpleColumnDefinitions; } - protected void analyzeAndFillRewriteSqlMap(String sql, ConnectContext ctx) { + protected void analyzeAndFillRewriteSqlMap(String sql, ConnectContext ctx) throws AnalysisException { StatementContext stmtCtx = ctx.getStatementContext(); LogicalPlan parsedViewPlan = new NereidsParser().parseForCreateView(sql); + logicalQuery = parsedViewPlan; + if (logicalQuery instanceof LogicalFileSink) { + throw new AnalysisException("Not support OUTFILE clause in CREATE VIEW statement"); + } if (parsedViewPlan instanceof UnboundResultSink) { parsedViewPlan = (LogicalPlan) ((UnboundResultSink<?>) parsedViewPlan).child(); } @@ -82,9 +104,12 @@ public class BaseViewInfo { AnalyzerForCreateView analyzerForStar = new AnalyzerForCreateView(viewContextForStar); analyzerForStar.analyze(); analyzedPlan = viewContextForStar.getRewritePlan(); + // Traverse all slots in the plan, and add the slot's location information + // and the fully qualified replacement string to the indexInSqlToString of the StatementContext. + analyzedPlan.accept(PlanSlotFinder.INSTANCE, ctx.getStatementContext()); } - protected String rewriteSql(Map<Pair<Integer, Integer>, String> indexStringSqlMap) { + protected String rewriteSql(TreeMap<Pair<Integer, Integer>, String> indexStringSqlMap) { StringBuilder builder = new StringBuilder(); int beg = 0; for (Map.Entry<Pair<Integer, Integer>, String> entry : indexStringSqlMap.entrySet()) { @@ -258,4 +283,117 @@ public class BaseViewInfo { ); } } + + private static class PlanSlotFinder extends DefaultPlanVisitor<Void, StatementContext> { + private static PlanSlotFinder INSTANCE = new PlanSlotFinder(); + + @Override + public Void visitLogicalView(LogicalView<? extends Plan> alias, StatementContext context) { + return null; + } + + @Override + public Void visitLogicalAggregate(LogicalAggregate<? extends Plan> aggregate, StatementContext context) { + for (Expression expr : aggregate.getGroupByExpressions()) { + expr.accept(SlotDealer.INSTANCE, context); + } + for (NamedExpression expr : aggregate.getOutputExpressions()) { + expr.accept(SlotDealer.INSTANCE, context); + } + return aggregate.child().accept(this, context); + } + + @Override + public Void visitLogicalFilter(LogicalFilter<? extends Plan> filter, StatementContext context) { + for (Expression expr : filter.getConjuncts()) { + expr.accept(SlotDealer.INSTANCE, context); + } + return filter.child().accept(this, context); + } + + public Void visitLogicalGenerate(LogicalGenerate<? extends Plan> generate, StatementContext context) { + for (Expression expr : generate.getGenerators()) { + expr.accept(SlotDealer.INSTANCE, context); + } + return generate.child().accept(this, context); + } + + @Override + public Void visitLogicalHaving(LogicalHaving<? extends Plan> having, StatementContext context) { + for (Expression expr : having.getConjuncts()) { + expr.accept(SlotDealer.INSTANCE, context); + } + return having.child().accept(this, context); + } + + @Override + public Void visitLogicalJoin(LogicalJoin<? extends Plan, ? extends Plan> join, StatementContext context) { + for (Expression expr : join.getOtherJoinConjuncts()) { + expr.accept(SlotDealer.INSTANCE, context); + } + for (Expression expr : join.getHashJoinConjuncts()) { + expr.accept(SlotDealer.INSTANCE, context); + } + join.child(0).accept(this, context); + return join.child(1).accept(this, context); + } + + @Override + public Void visitLogicalProject(LogicalProject<? extends Plan> project, StatementContext context) { + for (Expression expr : project.getProjects()) { + expr.accept(SlotDealer.INSTANCE, context); + } + return project.child().accept(this, context); + } + + @Override + public Void visitLogicalRepeat(LogicalRepeat<? extends Plan> repeat, StatementContext context) { + for (Expression expr : repeat.getOutputExpressions()) { + expr.accept(SlotDealer.INSTANCE, context); + } + for (List<Expression> exprs : repeat.getGroupingSets()) { + for (Expression expr : exprs) { + expr.accept(SlotDealer.INSTANCE, context); + } + } + return repeat.child().accept(this, context); + } + + @Override + public Void visitLogicalSort(LogicalSort<? extends Plan> sort, StatementContext context) { + for (OrderKey key : sort.getOrderKeys()) { + key.getExpr().accept(SlotDealer.INSTANCE, context); + } + return sort.child().accept(this, context); + } + + @Override + public Void visitLogicalTopN(LogicalTopN<? extends Plan> topN, StatementContext context) { + for (OrderKey key : topN.getOrderKeys()) { + key.getExpr().accept(SlotDealer.INSTANCE, context); + } + return topN.child().accept(this, context); + } + + @Override + public Void visitLogicalWindow(LogicalWindow<? extends Plan> window, StatementContext context) { + for (Expression expr : window.getWindowExpressions()) { + expr.accept(SlotDealer.INSTANCE, context); + } + return window.child().accept(this, context); + } + } + + private static class SlotDealer extends DefaultExpressionVisitor<Void, StatementContext> { + private static final SlotDealer INSTANCE = new SlotDealer(); + + @Override + public Void visitSlot(Slot slot, StatementContext ctx) { + slot.getIndexInSqlString().ifPresent(index -> + ctx.addIndexInSqlToString(index, + Utils.qualifiedNameWithBackquote(slot.getQualifier(), slot.getName())) + ); + return null; + } + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateViewInfo.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateViewInfo.java index e52f69954ba..17931f9e628 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateViewInfo.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateViewInfo.java @@ -30,12 +30,9 @@ import org.apache.doris.common.util.Util; import org.apache.doris.mysql.privilege.PrivPredicate; import org.apache.doris.nereids.NereidsPlanner; import org.apache.doris.nereids.analyzer.UnboundResultSink; -import org.apache.doris.nereids.exceptions.AnalysisException; import org.apache.doris.nereids.properties.PhysicalProperties; import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.plans.commands.ExplainCommand.ExplainLevel; -import org.apache.doris.nereids.trees.plans.logical.LogicalFileSink; -import org.apache.doris.nereids.trees.plans.logical.LogicalPlan; import org.apache.doris.qe.ConnectContext; import com.google.common.collect.Lists; @@ -52,14 +49,11 @@ public class CreateViewInfo extends BaseViewInfo { private final String comment; /** constructor*/ - public CreateViewInfo(boolean ifNotExists, TableNameInfo viewName, String comment, LogicalPlan logicalQuery, + public CreateViewInfo(boolean ifNotExists, TableNameInfo viewName, String comment, String querySql, List<SimpleColumnDefinition> simpleColumnDefinitions) { - super(viewName, logicalQuery, querySql, simpleColumnDefinitions); + super(viewName, querySql, simpleColumnDefinitions); this.ifNotExists = ifNotExists; this.comment = comment; - if (logicalQuery instanceof LogicalFileSink) { - throw new AnalysisException("Not support OUTFILE clause in CREATE VIEW statement"); - } } /** init */ diff --git a/regression-test/data/ddl_p0/test_alter_view_nereids.out b/regression-test/data/ddl_p0/test_alter_view_nereids.out index ef50a9c8801..a31a13f107a 100644 --- a/regression-test/data/ddl_p0/test_alter_view_nereids.out +++ b/regression-test/data/ddl_p0/test_alter_view_nereids.out @@ -10,7 +10,7 @@ 2 70 -- !sql -- -test_alter_view_view_nereids CREATE VIEW `test_alter_view_view_nereids` COMMENT 'test_view' AS SELECT c1 AS `k1`, sum(c3) AS `k2` FROM `internal`.`regression_test_ddl_p0`.`test_alter_view_table_nereids` GROUP BY c1; utf8mb4 utf8mb4_0900_bin +test_alter_view_view_nereids CREATE VIEW `test_alter_view_view_nereids` COMMENT 'test_view' AS SELECT `internal`.`regression_test_ddl_p0`.`test_alter_view_table_nereids`.`c1` AS `k1`, sum(`internal`.`regression_test_ddl_p0`.`test_alter_view_table_nereids`.`c3`) AS `k2` FROM `internal`.`regression_test_ddl_p0`.`test_alter_view_table_nereids` GROUP BY `internal`.`regression_test_ddl_p0`.`test_alter_view_table_nereids`.`c1`; utf8mb4 utf8mb4_0900_bin -- !sql -- test_alter_view_view_nereids CREATE VIEW `test_alter_view_view_nereids` COMMENT 'test_view' AS (select `internal`.`regression_test_ddl_p0`.`test_alter_view_table_nereids`.`c1`, `internal`.`regression_test_ddl_p0`.`test_alter_view_table_nereids`.`c2`, `internal`.`regression_test_ddl_p0`.`test_alter_view_table_nereids`.`c3` from `internal`.`regression_test_ddl_p0`.`test_alter_view_table_nereids`); utf8mb4 utf8mb4_0900_bin diff --git a/regression-test/data/ddl_p0/test_create_view.out b/regression-test/data/ddl_p0/test_create_view.out index 7f2a6e44d4a..4ba274b5347 100644 --- a/regression-test/data/ddl_p0/test_create_view.out +++ b/regression-test/data/ddl_p0/test_create_view.out @@ -25,5 +25,5 @@ 3 [-1, 20, 0] [0, 1, 0] -- !test_view_6 -- -v1 CREATE VIEW `v1` AS SELECT\n error_code, \n 1, \n 'string', \n now(), \n dayofyear(op_time), \n cast (source AS BIGINT), \n min(`timestamp`) OVER (\n ORDER BY \n op_time DESC ROWS BETWEEN UNBOUNDED PRECEDING\n AND 1 FOLLOWING\n ), \n 1 > 2,\n 2 + 3,\n 1 IN (1, 2, 3, 4), \n remark LIKE '%like', \n CASE WHEN remark = 's' THEN 1 ELSE 2 END,\n TRUE | FALSE \n FROM \n `internal`.`regressi [...] +v1 CREATE VIEW `v1` AS SELECT `error_code` AS `error_code`, 1 AS `__literal_1`, 'string' AS `__literal_2`, now() AS `__now_3`, dayofyear(`op_time`) AS `__dayofyear_4`, CAST(`source` AS BIGINT) AS `__cast_expr_5`, min(`timestamp`) OVER (ORDER BY `op_time` DESC NULLS LAST ROWS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING) AS `__min_6`, (1 > 2) AS `__binary_predicate_7`, (2 + 3) AS `__arithmetic_expr_8`, 1 IN (1, 2, 3, 4) AS `__in_predicate_9`, `remark` LIKE '%like' AS `__like_predicate_10`, [...] diff --git a/regression-test/data/ddl_p0/test_create_view_nereids.out b/regression-test/data/ddl_p0/test_create_view_nereids.out index efdc1553ca1..b6db86eaf62 100644 --- a/regression-test/data/ddl_p0/test_create_view_nereids.out +++ b/regression-test/data/ddl_p0/test_create_view_nereids.out @@ -25,7 +25,7 @@ 3 [-1, 20, 0] [0, 1, 0] -- !test_view_6 -- -v1 CREATE VIEW `v1` AS SELECT\n error_code, \n 1, \n 'string', \n now(), \n dayofyear(op_time), \n cast (source AS BIGINT), \n min(`timestamp`) OVER (\n ORDER BY \n op_time DESC ROWS BETWEEN UNBOUNDED PRECEDING\n AND 1 FOLLOWING\n ), \n 1 > 2,\n 2 + 3,\n 1 IN (1, 2, 3, 4), \n remark LIKE '%like', \n CASE WHEN remark = 's' THEN 1 ELSE 2 END,\n TRUE | FALSE \n FROM \n `internal`.`regressi [...] +v1 CREATE VIEW `v1` AS SELECT\n `internal`.`regression_test_ddl_p0`.`view_column_name_test_nereids`.`error_code`, \n 1, \n 'string', \n now(), \n dayofyear(`internal`.`regression_test_ddl_p0`.`view_column_name_test_nereids`.`op_time`), \n cast (`internal`.`regression_test_ddl_p0`.`view_column_name_test_nereids`.`source` AS BIGINT), \n min(`internal`.`regression_test_ddl_p0`.`view_column_name_test_nereids`.`timestamp`) OVER (\n ORDER BY \n [...] -- !test_with_as -- 1 1 2 @@ -47,7 +47,7 @@ v1 CREATE VIEW `v1` AS SELECT\n error_code, \n 1, \n 'string', \n 6 7 1 -- !test_with_as_sql -- -test_view_with_as CREATE VIEW `test_view_with_as` AS (\n with t1 as (select `internal`.`regression_test_ddl_p0`.`mal_test_view`.`pk`, `internal`.`regression_test_ddl_p0`.`mal_test_view`.`a`, `internal`.`regression_test_ddl_p0`.`mal_test_view`.`b` from `internal`.`regression_test_ddl_p0`.`mal_test_view`), t2 as (select `internal`.`regression_test_ddl_p0`.`mal_test_view`.`pk`, `internal`.`regression_test_ddl_p0`.`mal_test_view`.`a`, `internal`.`regression_test_ddl_p0`.`mal_test [...] +test_view_with_as CREATE VIEW `test_view_with_as` AS (\n with `t1` as (select `internal`.`regression_test_ddl_p0`.`mal_test_view`.`pk`, `internal`.`regression_test_ddl_p0`.`mal_test_view`.`a`, `internal`.`regression_test_ddl_p0`.`mal_test_view`.`b` from `internal`.`regression_test_ddl_p0`.`mal_test_view`), `t2` as (select `internal`.`regression_test_ddl_p0`.`mal_test_view`.`pk`, `internal`.`regression_test_ddl_p0`.`mal_test_view`.`a`, `internal`.`regression_test_ddl_p0`.`mal_ [...] -- !test_union -- 1 1 2 @@ -114,7 +114,7 @@ test_view_count_star CREATE VIEW `test_view_count_star` AS (select count(*) AS ` 8 10 1 -- !test_expression_sql -- -test_view_expression CREATE VIEW `test_view_expression` AS (select a+1 AS `c1`, abs(a)+2+1 AS `c2`, cast(b as varchar(10)) AS `c3` from `internal`.`regression_test_ddl_p0`.`mal_test_view`); utf8mb4 utf8mb4_0900_bin +test_view_expression CREATE VIEW `test_view_expression` AS (select `internal`.`regression_test_ddl_p0`.`mal_test_view`.`a`+1 AS `c1`, abs(`internal`.`regression_test_ddl_p0`.`mal_test_view`.`a`)+2+1 AS `c2`, cast(`internal`.`regression_test_ddl_p0`.`mal_test_view`.`b` as varchar(10)) AS `c3` from `internal`.`regression_test_ddl_p0`.`mal_test_view`); utf8mb4 utf8mb4_0900_bin -- !test_alias -- \N \N 6 @@ -136,7 +136,7 @@ test_view_expression CREATE VIEW `test_view_expression` AS (select a+1 AS `c1`, 8 10 1 -- !test_alias_sql -- -test_view_alias CREATE VIEW `test_view_alias` AS (\n select c8 AS `c1`, c2 AS `c2`, c1 AS `c3` from (select a+1 c8,abs(a)+2+1 as c2, cast(b as varchar(10)) as c1 from `internal`.`regression_test_ddl_p0`.`mal_test_view`) t); utf8mb4 utf8mb4_0900_bin +test_view_alias CREATE VIEW `test_view_alias` AS (\n select `t`.`c8` AS `c1`, `t`.`c2` AS `c2`, `t`.`c1` AS `c3` from (select `internal`.`regression_test_ddl_p0`.`mal_test_view`.`a`+1 `c8`,abs(`internal`.`regression_test_ddl_p0`.`mal_test_view`.`a`)+2+1 as `c2`, cast(`internal`.`regression_test_ddl_p0`.`mal_test_view`.`b` as varchar(10)) as `c1` from `internal`.`regression_test_ddl_p0`.`mal_test_view`) `t`); utf8mb4 utf8mb4_0900_bin -- !test_star_except -- \N 6 @@ -202,7 +202,7 @@ test_view_from_view CREATE VIEW `test_view_from_view` AS select `internal`.`regr 7 1 -- !test_backquote_in_view_define_sql -- -test_backquote_in_view_define CREATE VIEW `test_backquote_in_view_define` AS select a AS `ab``c`, b AS `c2` from `internal`.`regression_test_ddl_p0`.`mal_test_view`; utf8mb4 utf8mb4_0900_bin +test_backquote_in_view_define CREATE VIEW `test_backquote_in_view_define` AS select `internal`.`regression_test_ddl_p0`.`mal_test_view`.`a` AS `ab``c`, `internal`.`regression_test_ddl_p0`.`mal_test_view`.`b` AS `c2` from `internal`.`regression_test_ddl_p0`.`mal_test_view`; utf8mb4 utf8mb4_0900_bin -- !test_backquote_in_table_alias -- \N 6 @@ -224,5 +224,142 @@ test_backquote_in_view_define CREATE VIEW `test_backquote_in_view_define` AS sel 7 1 -- !test_backquote_in_table_alias_sql -- -test_backquote_in_table_alias CREATE VIEW `test_backquote_in_table_alias` AS select `ab``c`.`a` AS `c1`, `ab``c`.`b` AS `c2` from (select a,b from `internal`.`regression_test_ddl_p0`.`mal_test_view`) `ab``c`; utf8mb4 utf8mb4_0900_bin +test_backquote_in_table_alias CREATE VIEW `test_backquote_in_table_alias` AS select `ab``c`.`a` AS `c1`, `ab``c`.`b` AS `c2` from (select `internal`.`regression_test_ddl_p0`.`mal_test_view`.`a`,`internal`.`regression_test_ddl_p0`.`mal_test_view`.`b` from `internal`.`regression_test_ddl_p0`.`mal_test_view`) `ab``c`; utf8mb4 utf8mb4_0900_bin + +-- !test_generate -- +1 10 A 30 +1 10 A 60 +2 20 B 30 +2 20 B 60 +3 30 C 30 +3 30 C 60 +4 40 D 30 +4 40 D 60 + +-- !test_generate_sql -- +test_view_generate CREATE VIEW `test_view_generate` AS select `internal`.`regression_test_ddl_p0`.`create_view_table1`.`id`, `internal`.`regression_test_ddl_p0`.`create_view_table1`.`value1`, `internal`.`regression_test_ddl_p0`.`create_view_table1`.`value2`, `t1`.`age` from `internal`.`regression_test_ddl_p0`.`create_view_table1` lateral view EXPLODE(ARRAY(30,60)) `t1` as `age`; utf8mb4 utf8mb4_0900_bin + +-- !test_generate_with_column -- +1 10 A 0 +2 20 B 0 +2 20 B 1 +3 30 C 0 +3 30 C 1 +3 30 C 2 +4 40 D 0 +4 40 D 1 +4 40 D 2 +4 40 D 3 + +-- !test_generate_with_column_sql -- +test_view_generate_with_column CREATE VIEW `test_view_generate_with_column` AS select `internal`.`regression_test_ddl_p0`.`create_view_table1`.`id`, `internal`.`regression_test_ddl_p0`.`create_view_table1`.`value1`, `internal`.`regression_test_ddl_p0`.`create_view_table1`.`value2`, `t1`.`age` from `internal`.`regression_test_ddl_p0`.`create_view_table1` lateral view EXPLODE_numbers(`internal`.`regression_test_ddl_p0`.`create_view_table1`.`id`) `t1` as `age`; utf8mb4 utf8mb4_0900_bin + +-- !test_col_alias -- +1 10 +2 20 +3 30 +4 40 + +-- !test_col_alias_sql -- +test_view_col_alias CREATE VIEW `test_view_col_alias` AS select `internal`.`regression_test_ddl_p0`.`create_view_table1`.`id` as `c1`, `internal`.`regression_test_ddl_p0`.`create_view_table1`.`value1` as `c2` from `internal`.`regression_test_ddl_p0`.`create_view_table1`; utf8mb4 utf8mb4_0900_bin + +-- !test_col_alias_with_specific_name -- +1 10 +2 20 +3 30 +4 40 + +-- !test_col_alias_with_specific_name_sql -- +test_view_col_alias_specific_name CREATE VIEW `test_view_col_alias_specific_name` AS select `internal`.`regression_test_ddl_p0`.`create_view_table1`.`id` AS `col1`, `internal`.`regression_test_ddl_p0`.`create_view_table1`.`value1` AS `col2` from `internal`.`regression_test_ddl_p0`.`create_view_table1`; utf8mb4 utf8mb4_0900_bin + +-- !test_table_alias -- +1 10 +2 20 +3 30 +4 40 + +-- !test_table_alias_sql -- +test_view_table_alias CREATE VIEW `test_view_table_alias` AS select `t`.`c1`, `t`.`c2` from (\n select `internal`.`regression_test_ddl_p0`.`create_view_table1`.`id` as `c1`, `internal`.`regression_test_ddl_p0`.`create_view_table1`.`value1` as `c2` from `internal`.`regression_test_ddl_p0`.`create_view_table1` limit 10) as `t`; utf8mb4 utf8mb4_0900_bin + +-- !test_join_table_alias -- +1 10 +2 20 +3 30 +4 40 + +-- !test_join_table_alias_sql -- +test_view_join_table_alias CREATE VIEW `test_view_join_table_alias` AS select `t`.`c1`, `t`.`c2` from (\n select `t1`.`id` as `c1`, `t1`.`value1` as `c2` from `internal`.`regression_test_ddl_p0`.`create_view_table1` `t1` inner join `internal`.`regression_test_ddl_p0`.`create_view_table2` `t2` on `t1`.`id`=`t2`.`id` limit 10) as `t`; utf8mb4 utf8mb4_0900_bin + +-- !test_alias_udf -- +1****1 1 +2****2 2 +3****3 3 +4****4 4 + +-- !test_alias_udf_sql -- +test_view_alias_udf CREATE VIEW `test_view_alias_udf` AS (select `regression_test_ddl_p0`.`alias_function_create_view_test`(`internal`.`regression_test_ddl_p0`.`create_view_table1`.`id`) as `c1`,abs(`internal`.`regression_test_ddl_p0`.`create_view_table1`.`id`) from `internal`.`regression_test_ddl_p0`.`create_view_table1`); utf8mb4 utf8mb4_0900_bin + +-- !test_alias_with_db_udf -- +1****1 1 +2****2 2 +3****3 3 +4****4 4 + +-- !test_alias_with_db_udf_sql -- +test_view_alias_udf_with_db CREATE VIEW `test_view_alias_udf_with_db` AS (select `regression_test_ddl_p0`.`alias_function_create_view_test`(`internal`.`regression_test_ddl_p0`.`create_view_table1`.`id`) as `c1`,abs(`internal`.`regression_test_ddl_p0`.`create_view_table1`.`id`) from `internal`.`regression_test_ddl_p0`.`create_view_table1`); utf8mb4 utf8mb4_0900_bin + +-- !test_udf_sql -- +test_view_udf CREATE VIEW `test_view_udf` AS (select `regression_test_ddl_p0`.`alias_function_create_view_test`(`internal`.`regression_test_ddl_p0`.`create_view_table1`.`id`) as `c1`, `regression_test_ddl_p0`.`java_udf_create_view_test`('2011-01-01','2011-01-02'),\n `regression_test_ddl_p0`.`java_udf_create_view_test`('2011-01-01','2011-01-03') from `internal`.`regression_test_ddl_p0`.`create_view_table1`); utf8mb4 utf8mb4_0900_bin + +-- !test_udf -- +1****1 false false +2****2 false false +3****3 false false +4****4 false false + +-- !test_with_as_with_columns -- +1 1 2 +1 1 4 +1 3 6 +2 1 3 +2 1 4 +2 1 7 +2 3 5 +2 3 9 +2 4 2 +3 2 8 +3 5 \N +3 5 6 +3 5 6 +3 5 8 +4 5 6 +6 \N 6 +6 7 1 + +-- !test_with_as_with_columns_sql -- +test_view_with_as_with_columns CREATE VIEW `test_view_with_as_with_columns` AS (\n with `t1`(`c1`,`c2`,`c3`) as (select `internal`.`regression_test_ddl_p0`.`mal_test_view`.`pk`, `internal`.`regression_test_ddl_p0`.`mal_test_view`.`a`, `internal`.`regression_test_ddl_p0`.`mal_test_view`.`b` from `internal`.`regression_test_ddl_p0`.`mal_test_view`), `t2` as (select `internal`.`regression_test_ddl_p0`.`mal_test_view`.`pk`, `internal`.`regression_test_ddl_p0`.`mal_test_view`.`a`, [...] + +-- !test_having -- +2 2 +3 3 +4 2 +4 4 +5 5 +6 3 +7 7 +8 4 +9 3 +10 5 +14 7 +15 5 + +-- !test_having_sql -- +test_having CREATE VIEW `test_having` AS select sum(`internal`.`regression_test_ddl_p0`.`mal_test_view`.`a`) over(partition by `internal`.`regression_test_ddl_p0`.`mal_test_view`.`a` order by `internal`.`regression_test_ddl_p0`.`mal_test_view`.`pk`) as `c1` , `internal`.`regression_test_ddl_p0`.`mal_test_view`.`a` from `internal`.`regression_test_ddl_p0`.`mal_test_view` group by grouping sets((`internal`.`regression_test_ddl_p0`.`mal_test_view`.`a`),(`internal`.`regression_test_ddl_p0`.` [...] + +-- !complicated_view1 -- +1 100 1 +2 200 1 + +-- !complicated_view1_sql -- +test_view_complicated CREATE VIEW `test_view_complicated` AS SELECT `t`.`id`, `t`.`value3`, `t`.`row_num` FROM (\n SELECT `t1`.`id`, `tt`.`value3`, ROW_NUMBER() OVER (PARTITION BY `t1`.`id` ORDER BY `tt`.`value3` DESC) as `row_num`\n FROM (SELECT `internal`.`regression_test_ddl_p0`.`create_view_table1`.`id` FROM `internal`.`regression_test_ddl_p0`.`create_view_table1` GROUP BY `internal`.`regression_test_ddl_p0`.`create_view_table1`.`id`) `t1`\n FULL OUTER JOIN (SELECT `inte [...] diff --git a/regression-test/data/show_p0/test_show_create_table_and_views_nereids.out b/regression-test/data/show_p0/test_show_create_table_and_views_nereids.out index 9b1f6d3e4a0..5e4a1fd3643 100644 --- a/regression-test/data/show_p0/test_show_create_table_and_views_nereids.out +++ b/regression-test/data/show_p0/test_show_create_table_and_views_nereids.out @@ -24,7 +24,7 @@ show_create_table_and_views_nereids_table CREATE TABLE `show_create_table_and_vi 3 1 -- !show -- -show_create_table_and_views_nereids_view CREATE VIEW `show_create_table_and_views_nereids_view` AS SELECT user_id AS `user_id`, cost AS `cost` FROM `internal`.`show_create_table_and_views_nereids_db`.`show_create_table_and_views_nereids_table`\n WHERE good_id = 2; utf8mb4 utf8mb4_0900_bin +show_create_table_and_views_nereids_view CREATE VIEW `show_create_table_and_views_nereids_view` AS SELECT `internal`.`show_create_table_and_views_nereids_db`.`show_create_table_and_views_nereids_table`.`user_id` AS `user_id`, `internal`.`show_create_table_and_views_nereids_db`.`show_create_table_and_views_nereids_table`.`cost` AS `cost` FROM `internal`.`show_create_table_and_views_nereids_db`.`show_create_table_and_views_nereids_table`\n WHERE `internal`.`show_create_table_and_vie [...] -- !select -- 1 47 diff --git a/regression-test/suites/ddl_p0/test_create_view.groovy b/regression-test/suites/ddl_p0/test_create_view.groovy index b4bd9848545..0cc42f8fcc1 100644 --- a/regression-test/suites/ddl_p0/test_create_view.groovy +++ b/regression-test/suites/ddl_p0/test_create_view.groovy @@ -16,6 +16,7 @@ // under the License. suite("test_create_view") { + sql "SET enable_nereids_planner=false" sql """DROP TABLE IF EXISTS count_distinct""" sql """ CREATE TABLE IF NOT EXISTS count_distinct diff --git a/regression-test/suites/ddl_p0/test_create_view_nereids.groovy b/regression-test/suites/ddl_p0/test_create_view_nereids.groovy index 48885a47fd1..ad3c84f25ec 100644 --- a/regression-test/suites/ddl_p0/test_create_view_nereids.groovy +++ b/regression-test/suites/ddl_p0/test_create_view_nereids.groovy @@ -277,4 +277,117 @@ suite("test_create_view_nereids") { sql "create view test_backquote_in_table_alias(c1, c2) as select * from (select a,b from mal_test_view) `ab``c`;" qt_test_backquote_in_table_alias "select * from test_backquote_in_table_alias order by c1, c2;" qt_test_backquote_in_table_alias_sql "show create view test_backquote_in_table_alias;" + + sql "drop table if exists create_view_table1" + sql """CREATE TABLE create_view_table1 ( + id INT, + value1 INT, + value2 VARCHAR(50) + ) distributed by hash(id) buckets 10 properties("replication_num"="1");""" + sql """INSERT INTO create_view_table1 (id, value1, value2) VALUES + (1, 10, 'A'), + (2, 20, 'B'), + (3, 30, 'C'), + (4, 40, 'D');""" + sql "drop table if exists create_view_table2" + sql """CREATE TABLE create_view_table2 ( + id INT, + table1_id INT, + value3 INT, + value4 VARCHAR(50) + ) distributed by hash(id) buckets 10 properties("replication_num"="1");""" + sql """INSERT INTO create_view_table2 (id, table1_id, value3, value4) VALUES + (1, 1, 100, 'X'), + (2, 2, 200, 'Y'), + (3, 2, 300, 'Z'), + (4, 3, 400, 'W');""" + + sql "drop view if exists test_view_generate" + sql """create view test_view_generate as select * from create_view_table1 lateral view EXPLODE(ARRAY(30,60)) t1 as age""" + qt_test_generate "select * from test_view_generate order by 1,2,3,4;" + qt_test_generate_sql "show create view test_view_generate;" + + sql "drop view if exists test_view_generate_with_column" + sql """create view test_view_generate_with_column as select * from create_view_table1 lateral view EXPLODE_numbers(id) t1 as age""" + qt_test_generate_with_column "select * from test_view_generate_with_column order by 1,2,3,4" + qt_test_generate_with_column_sql "show create view test_view_generate_with_column;" + + sql "drop view if exists test_view_col_alias" + sql """create view test_view_col_alias as select id as `c1`, value1 as c2 from create_view_table1;""" + qt_test_col_alias "select * from test_view_col_alias order by 1,2" + qt_test_col_alias_sql "show create view test_view_col_alias;" + + sql "drop view if exists test_view_col_alias_specific_name" + sql """create view test_view_col_alias_specific_name(col1,col2) as select id as `c1`, value1 as c2 from create_view_table1;""" + qt_test_col_alias_with_specific_name "select * from test_view_col_alias_specific_name order by 1,2" + qt_test_col_alias_with_specific_name_sql "show create view test_view_col_alias_specific_name;" + + sql "drop view if exists test_view_table_alias" + sql """create view test_view_table_alias as select * from ( + select id as `c1`, value1 as c2 from create_view_table1 limit 10) as t ;""" + qt_test_table_alias "select * from test_view_table_alias order by 1,2" + qt_test_table_alias_sql "show create view test_view_table_alias;" + + sql "drop view if exists test_view_join_table_alias" + sql """create view test_view_join_table_alias as select * from ( + select t1.id as `c1`, value1 as c2 from create_view_table1 t1 inner join create_view_table2 t2 on t1.id=t2.id limit 10) as t ;""" + qt_test_join_table_alias "select * from test_view_join_table_alias order by 1,2" + qt_test_join_table_alias_sql "show create view test_view_join_table_alias;" + + sql "drop function if exists alias_function_create_view_test(INT)" + sql "CREATE ALIAS FUNCTION alias_function_create_view_test(INT) WITH PARAMETER(id) AS CONCAT(LEFT(id, 3), '****', RIGHT(id, 4));" + sql "drop view if exists test_view_alias_udf;" + sql "CREATE VIEW if not exists test_view_alias_udf AS (select alias_function_create_view_test(id) as c1,abs(id) from create_view_table1);" + qt_test_alias_udf "select * from test_view_alias_udf order by 1,2" + qt_test_alias_udf_sql "show create view test_view_alias_udf;" + + String db = context.config.getDbNameByFile(context.file) + log.info("db:${db}") + sql "drop view if exists test_view_alias_udf_with_db;" + sql "CREATE VIEW if not exists test_view_alias_udf_with_db AS (select ${db}.alias_function_create_view_test(id) as c1,abs(id) from create_view_table1);" + qt_test_alias_with_db_udf "select * from test_view_alias_udf_with_db order by 1,2" + qt_test_alias_with_db_udf_sql "show create view test_view_alias_udf_with_db;" + + def jarPath = """${context.config.suitePath}/javaudf_p0/jars/java-udf-case-jar-with-dependencies.jar""" + scp_udf_file_to_all_be(jarPath) + log.info("jarPath:${jarPath}") + + sql "drop function if exists java_udf_create_view_test(date, date)" + sql """ CREATE FUNCTION java_udf_create_view_test(date, date) RETURNS boolean PROPERTIES ( + "file"="file://${jarPath}", + "symbol"="org.apache.doris.udf.DateTest1", + "type"="JAVA_UDF" + ); """ + + sql "drop view if exists test_view_udf;" + sql """CREATE VIEW if not exists test_view_udf AS (select ${db}.alias_function_create_view_test(id) as c1, java_udf_create_view_test('2011-01-01','2011-01-02'), + ${db}.java_udf_create_view_test('2011-01-01','2011-01-03') from create_view_table1);""" + qt_test_udf_sql "show create view test_view_udf;" + qt_test_udf "select * from test_view_udf order by 1,2,3" + + sql "DROP VIEW if exists test_view_with_as_with_columns" + sql """CREATE VIEW if not exists test_view_with_as_with_columns AS ( + with t1(c1,c2,c3) as (select * from mal_test_view), t2 as (select * from mal_test_view), + t3 as (select * from mal_test_view) SELECT * FROM t1);""" + qt_test_with_as_with_columns "select * from test_view_with_as_with_columns order by c1,c2,c3" + qt_test_with_as_with_columns_sql "show create view test_view_with_as_with_columns" + + sql "drop view if exists test_having" + sql """create view test_having as + select sum(a) over(partition by a order by pk) as c1 , a from mal_test_view group by grouping sets((a),(b),(pk,a)) having a>1""" + qt_test_having "select * from test_having order by 1,2" + qt_test_having_sql "show create view test_having" + + sql "drop view if exists test_view_complicated;" + sql """create view test_view_complicated as + SELECT * FROM ( + SELECT t1.id, tt.value3, ROW_NUMBER() OVER (PARTITION BY t1.id ORDER BY tt.value3 DESC) as row_num + FROM (SELECT id FROM create_view_table1 GROUP BY id) t1 + FULL OUTER JOIN (SELECT value3, id, MAX(value4) FROM create_view_table2 GROUP BY value3, id) tt + ON tt.id = t1.id + ORDER BY t1.id + ) t + WHERE value3 < 280 AND (id < 3 or id >8);""" + qt_complicated_view1 "select * from test_view_complicated order by 1,2,3" + qt_complicated_view1_sql "show create view test_view_complicated;" } diff --git a/regression-test/suites/javaudf_p0/test_javaudf_date.groovy b/regression-test/suites/javaudf_p0/test_javaudf_date.groovy index 91f7c771968..76d287e9c6d 100644 --- a/regression-test/suites/javaudf_p0/test_javaudf_date.groovy +++ b/regression-test/suites/javaudf_p0/test_javaudf_date.groovy @@ -80,7 +80,7 @@ suite("test_javaudf_date") { qt_select """ SELECT java_udf_date_test2('2011-01-01', '2011-01-01') result FROM ${tableName} ORDER BY result; """ qt_select """ SELECT java_udf_date_test2(null, '2011-01-01') result FROM ${tableName} ORDER BY result; """ - + sql """ CREATE FUNCTION java_udf_date_test3(date, date) RETURNS boolean PROPERTIES ( "file"="file://${jarPath}", @@ -92,7 +92,7 @@ suite("test_javaudf_date") { qt_select """ SELECT java_udf_date_test3('2011-01-01', '2011-01-01') result FROM ${tableName} ORDER BY result; """ qt_select """ SELECT java_udf_date_test3(null, '2011-01-01') result FROM ${tableName} ORDER BY result; """ - + sql """ CREATE FUNCTION java_udf_datetime_test1(datetime, datetime) RETURNS boolean PROPERTIES ( "file"="file://${jarPath}", @@ -104,7 +104,7 @@ suite("test_javaudf_date") { qt_select """ SELECT java_udf_datetime_test1('2011-01-01', '2011-01-01') result FROM ${tableName} ORDER BY result; """ qt_select """ SELECT java_udf_datetime_test1(null, '2011-01-01') result FROM ${tableName} ORDER BY result; """ - + sql """ CREATE FUNCTION java_udf_datetime_test2(datetime, datetime) RETURNS boolean PROPERTIES ( "file"="file://${jarPath}", @@ -116,7 +116,7 @@ suite("test_javaudf_date") { qt_select """ SELECT java_udf_datetime_test2('2011-01-01', '2011-01-01') result FROM ${tableName} ORDER BY result; """ qt_select """ SELECT java_udf_datetime_test2(null, '2011-01-01') result FROM ${tableName} ORDER BY result; """ - + sql """ CREATE FUNCTION java_udf_datetime_test3(datetime, datetime) RETURNS boolean PROPERTIES ( "file"="file://${jarPath}", @@ -128,7 +128,7 @@ suite("test_javaudf_date") { qt_select """ SELECT java_udf_datetime_test3('2011-01-01', '2011-01-01') result FROM ${tableName} ORDER BY result; """ qt_select """ SELECT java_udf_datetime_test3(null, '2011-01-01') result FROM ${tableName} ORDER BY result; """ - + sql """ CREATE FUNCTION java_udf_datev2_test1(datev2, datev2) RETURNS boolean PROPERTIES ( @@ -139,7 +139,7 @@ suite("test_javaudf_date") { qt_select """ SELECT java_udf_datev2_test1(datev2_col, '2011-01-01') result FROM ${tableName} ORDER BY result; """ - + sql """ CREATE FUNCTION java_udf_datev2_test2(datev2, datev2) RETURNS boolean PROPERTIES ( "file"="file://${jarPath}", @@ -149,7 +149,7 @@ suite("test_javaudf_date") { qt_select """ SELECT java_udf_datev2_test2(datev2_col, '2011-01-01') result FROM ${tableName} ORDER BY result; """ - + sql """ CREATE FUNCTION java_udf_datev2_test3(datev2, datev2) RETURNS boolean PROPERTIES ( "file"="file://${jarPath}", @@ -159,7 +159,7 @@ suite("test_javaudf_date") { qt_select """ SELECT java_udf_datev2_test3(datev2_col, '2011-01-01') result FROM ${tableName} ORDER BY result; """ - + sql """ CREATE FUNCTION java_udf_datetimev2_test1(datetimev2, datetimev2) RETURNS boolean PROPERTIES ( "file"="file://${jarPath}", @@ -169,7 +169,7 @@ suite("test_javaudf_date") { qt_select """ SELECT java_udf_datetimev2_test1(datetimev2_col, '2011-01-01') result FROM ${tableName} ORDER BY result; """ - + sql """ CREATE FUNCTION java_udf_datetimev2_test2(datetimev2, datetimev2) RETURNS boolean PROPERTIES ( "file"="file://${jarPath}", @@ -179,7 +179,7 @@ suite("test_javaudf_date") { qt_select """ SELECT java_udf_datetimev2_test2(datetimev2_col, '2011-01-01') result FROM ${tableName} ORDER BY result; """ - + sql """ CREATE FUNCTION java_udf_datetimev2_test3(datetimev2, datetimev2) RETURNS boolean PROPERTIES ( "file"="file://${jarPath}", @@ -189,7 +189,7 @@ suite("test_javaudf_date") { qt_select """ SELECT java_udf_datetimev2_test3(datetimev2_col, '2011-01-01') result FROM ${tableName} ORDER BY result; """ - + } finally { try_sql("DROP FUNCTION IF EXISTS java_udf_date_test3(date, date);") try_sql("DROP FUNCTION IF EXISTS java_udf_datetime_test1(datetime, datetime);") diff --git a/regression-test/suites/show_p0/test_show_create_table_and_views.groovy b/regression-test/suites/show_p0/test_show_create_table_and_views.groovy index 2fd5f09d307..f7497f9ee51 100644 --- a/regression-test/suites/show_p0/test_show_create_table_and_views.groovy +++ b/regression-test/suites/show_p0/test_show_create_table_and_views.groovy @@ -16,6 +16,7 @@ // under the License. suite("test_show_create_table_and_views", "show") { + sql "SET enable_nereids_planner=false;" def ret = sql "SHOW FRONTEND CONFIG like '%enable_feature_binlog%';" logger.info("${ret}") if (ret.size() != 0 && ret[0].size() > 1 && ret[0][1] == 'false') { --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org