From d672e321ccbf4ff96716fbb06feb9a779e786baf Mon Sep 17 00:00:00 2001 From: morrySnow <101034200+morrySnow@users.noreply.github.com> Date: Tue, 26 Dec 2023 15:51:08 +0800 Subject: [PATCH] [feature](Nereids) support values inline table in query (#28972) --- .../org/apache/doris/nereids/DorisParser.g4 | 3 +- .../nereids/parser/LogicalPlanBuilder.java | 2 +- .../rules/analysis/BindExpression.java | 35 +++++++++++++------ 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 index dc202fef74..98260c77db 100644 --- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 +++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 @@ -57,7 +57,7 @@ statement partitionSpec? // partition define (WITH LABEL labelName=identifier)? cols=identifierList? // label and columns define (LEFT_BRACKET hints=identifierSeq RIGHT_BRACKET)? // hint define - (query | inlineTable) #insertTable + query #insertTable | explain? cte? UPDATE tableName=multipartIdentifier tableAlias SET updateAssignmentSeq fromClause? @@ -287,6 +287,7 @@ setQuantifier queryPrimary : querySpecification #queryPrimaryDefault | LEFT_PAREN query RIGHT_PAREN #subquery + | inlineTable #valuesTable ; querySpecification 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 95ae97192c..cf670fe1aa 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 @@ -488,7 +488,7 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor { List colNames = ctx.cols == null ? ImmutableList.of() : visitIdentifierList(ctx.cols); // TODO visit partitionSpecCtx Pair> partitionSpec = visitPartitionSpec(ctx.partitionSpec()); - LogicalPlan plan = ctx.query() != null ? visitQuery(ctx.query()) : visitInlineTable(ctx.inlineTable()); + LogicalPlan plan = visitQuery(ctx.query()); UnboundTableSink sink = new UnboundTableSink<>( tableName.build(), colNames, 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 83b0eb1ea7..e1b2167e79 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 @@ -27,6 +27,7 @@ import org.apache.doris.nereids.analyzer.UnboundOneRowRelation; import org.apache.doris.nereids.analyzer.UnboundSlot; import org.apache.doris.nereids.analyzer.UnboundTVFRelation; import org.apache.doris.nereids.exceptions.AnalysisException; +import org.apache.doris.nereids.parser.LogicalPlanBuilder; import org.apache.doris.nereids.properties.OrderKey; import org.apache.doris.nereids.rules.AppliedAwareRule.AppliedAwareRuleCondition; import org.apache.doris.nereids.rules.Rule; @@ -36,6 +37,7 @@ import org.apache.doris.nereids.rules.expression.rules.FunctionBinder; import org.apache.doris.nereids.trees.UnaryNode; import org.apache.doris.nereids.trees.expressions.Alias; import org.apache.doris.nereids.trees.expressions.BoundStar; +import org.apache.doris.nereids.trees.expressions.DefaultValueSlot; import org.apache.doris.nereids.trees.expressions.EqualTo; import org.apache.doris.nereids.trees.expressions.ExprId; import org.apache.doris.nereids.trees.expressions.Expression; @@ -43,6 +45,7 @@ import org.apache.doris.nereids.trees.expressions.NamedExpression; import org.apache.doris.nereids.trees.expressions.Properties; import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.expressions.SlotReference; +import org.apache.doris.nereids.trees.expressions.StatementScopeIdGenerator; import org.apache.doris.nereids.trees.expressions.functions.BoundFunction; import org.apache.doris.nereids.trees.expressions.functions.Function; import org.apache.doris.nereids.trees.expressions.functions.FunctionBuilder; @@ -67,6 +70,7 @@ import org.apache.doris.nereids.trees.plans.logical.LogicalInlineTable; import org.apache.doris.nereids.trees.plans.logical.LogicalIntersect; import org.apache.doris.nereids.trees.plans.logical.LogicalJoin; import org.apache.doris.nereids.trees.plans.logical.LogicalOneRowRelation; +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.LogicalResultSink; @@ -87,6 +91,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList.Builder; import com.google.common.collect.ImmutableListMultimap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; import com.google.common.collect.Sets; import org.apache.commons.lang3.StringUtils; @@ -528,6 +533,26 @@ public class BindExpression implements AnalysisRuleFactory { return new LogicalHaving<>(boundConjuncts, having.child()); }) ), + RuleType.BINDING_INLINE_TABLE_SLOT.build( + logicalInlineTable().thenApply(ctx -> { + LogicalInlineTable logicalInlineTable = ctx.root; + // ensure all expressions are valid. + List relations + = Lists.newArrayListWithCapacity(logicalInlineTable.getConstantExprsList().size()); + for (int i = 0; i < logicalInlineTable.getConstantExprsList().size(); i++) { + if (logicalInlineTable.getConstantExprsList().get(i).stream() + .anyMatch(DefaultValueSlot.class::isInstance)) { + throw new AnalysisException("Default expression" + + " can't exist in SELECT statement at row " + (i + 1)); + } + relations.add(new UnboundOneRowRelation(StatementScopeIdGenerator.newRelationId(), + logicalInlineTable.getConstantExprsList().get(i))); + } + // construct union all tree + return LogicalPlanBuilder.reduceToLogicalPlanTree(0, relations.size() - 1, + relations, Qualifier.ALL); + }) + ), RuleType.BINDING_ONE_ROW_RELATION_SLOT.build( // we should bind UnboundAlias in the UnboundOneRowRelation unboundOneRowRelation().thenApply(ctx -> { @@ -540,16 +565,6 @@ public class BindExpression implements AnalysisRuleFactory { return new LogicalOneRowRelation(oneRowRelation.getRelationId(), projects); }) ), - RuleType.BINDING_INLINE_TABLE_SLOT.build( - logicalInlineTable().thenApply(ctx -> { - LogicalInlineTable logicalInlineTable = ctx.root; - // ensure all expressions are valid. - logicalInlineTable.getExpressions().forEach(expr -> - bindSlot(expr, ImmutableList.of(), ctx.cascadesContext, false) - ); - return null; - }) - ), RuleType.BINDING_SET_OPERATION_SLOT.build( // LogicalSetOperation don't bind again if LogicalSetOperation.outputs is not empty, this is special // we should not remove LogicalSetOperation::canBind, because in default case, the plan can run into