This is an automated email from the ASF dual-hosted git repository. huajianlan pushed a commit to branch opt_insert_into_values in repository https://gitbox.apache.org/repos/asf/doris.git
commit a5880cf6c41c4df06d41d415652b865032aa005c Author: 924060929 <lanhuaj...@selectdb.com> AuthorDate: Fri Aug 30 21:05:10 2024 +0800 optimize insert into values --- .../org/apache/doris/nereids/NereidsPlanner.java | 14 +- .../expression/rules/FoldConstantRuleOnFE.java | 9 ++ .../commands/insert/InsertIntoTableCommand.java | 153 ++++++++++++++++++++- .../trees/plans/commands/insert/InsertUtils.java | 57 +++++--- .../insert/OlapGroupCommitInsertExecutor.java | 8 +- .../trees/plans/logical/LogicalInlineTable.java | 13 +- .../nereids/trees/plans/logical/LogicalUnion.java | 18 +++ .../plans/physical/PhysicalOlapTableSink.java | 2 +- 8 files changed, 242 insertions(+), 32 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/NereidsPlanner.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/NereidsPlanner.java index 58af5cd3e92..0e6d8ebf8de 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/NereidsPlanner.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/NereidsPlanner.java @@ -99,17 +99,19 @@ import java.util.function.Function; */ public class NereidsPlanner extends Planner { public static final Logger LOG = LogManager.getLogger(NereidsPlanner.class); + + protected Plan parsedPlan; + protected Plan analyzedPlan; + protected Plan rewrittenPlan; + protected Plan optimizedPlan; + protected PhysicalPlan physicalPlan; + private CascadesContext cascadesContext; private final StatementContext statementContext; private final List<ScanNode> scanNodeList = Lists.newArrayList(); private final List<PhysicalRelation> physicalRelations = Lists.newArrayList(); private DescriptorTable descTable; - private Plan parsedPlan; - private Plan analyzedPlan; - private Plan rewrittenPlan; - private Plan optimizedPlan; - private PhysicalPlan physicalPlan; private FragmentIdMapping<DistributedPlan> distributedPlans; // The cost of optimized plan private double cost = 0; @@ -540,7 +542,7 @@ public class NereidsPlanner extends Planner { return cascadesContext.getMemo().getRoot(); } - private PhysicalPlan chooseNthPlan(Group rootGroup, PhysicalProperties physicalProperties, int nthPlan) { + protected PhysicalPlan chooseNthPlan(Group rootGroup, PhysicalProperties physicalProperties, int nthPlan) { if (nthPlan <= 1) { cost = rootGroup.getLowestCostPlan(physicalProperties).orElseThrow( () -> new AnalysisException("lowestCostPlans with physicalProperties(" diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java index d1c385ec621..c439458ff4c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/FoldConstantRuleOnFE.java @@ -24,7 +24,9 @@ import org.apache.doris.common.ErrorCode; import org.apache.doris.common.util.DebugUtil; import org.apache.doris.datasource.InternalCatalog; import org.apache.doris.mysql.privilege.PrivPredicate; +import org.apache.doris.nereids.analyzer.UnboundVariable; import org.apache.doris.nereids.exceptions.AnalysisException; +import org.apache.doris.nereids.rules.analysis.ExpressionAnalyzer; import org.apache.doris.nereids.rules.expression.AbstractExpressionRewriteRule; import org.apache.doris.nereids.rules.expression.ExpressionListenerMatcher; import org.apache.doris.nereids.rules.expression.ExpressionMatchingContext; @@ -53,6 +55,7 @@ import org.apache.doris.nereids.trees.expressions.NullSafeEqual; import org.apache.doris.nereids.trees.expressions.Or; import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.expressions.TimestampArithmetic; +import org.apache.doris.nereids.trees.expressions.Variable; import org.apache.doris.nereids.trees.expressions.WhenClause; import org.apache.doris.nereids.trees.expressions.functions.BoundFunction; import org.apache.doris.nereids.trees.expressions.functions.PropagateNullLiteral; @@ -220,6 +223,12 @@ public class FoldConstantRuleOnFE extends AbstractExpressionRewriteRule return super.visitMatch(match, context); } + @Override + public Expression visitUnboundVariable(UnboundVariable unboundVariable, ExpressionRewriteContext context) { + Variable variable = ExpressionAnalyzer.resolveUnboundVariable(unboundVariable); + return variable.getRealExpression(); + } + @Override public Expression visitEncryptKeyRef(EncryptKeyRef encryptKeyRef, ExpressionRewriteContext context) { String dbName = encryptKeyRef.getDbName(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertIntoTableCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertIntoTableCommand.java index 0999c4baa79..a147a900f02 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertIntoTableCommand.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertIntoTableCommand.java @@ -35,21 +35,35 @@ import org.apache.doris.nereids.StatementContext; import org.apache.doris.nereids.analyzer.UnboundTableSink; import org.apache.doris.nereids.exceptions.AnalysisException; import org.apache.doris.nereids.glue.LogicalPlanAdapter; +import org.apache.doris.nereids.memo.Group; +import org.apache.doris.nereids.memo.GroupId; +import org.apache.doris.nereids.properties.PhysicalProperties; +import org.apache.doris.nereids.rules.RuleType; +import org.apache.doris.nereids.rules.analysis.BindSink; +import org.apache.doris.nereids.rules.rewrite.MergeProjects; import org.apache.doris.nereids.trees.expressions.Slot; import org.apache.doris.nereids.trees.plans.Explainable; import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.trees.plans.PlanType; +import org.apache.doris.nereids.trees.plans.algebra.SetOperation.Qualifier; import org.apache.doris.nereids.trees.plans.commands.Command; import org.apache.doris.nereids.trees.plans.commands.ForwardWithSync; +import org.apache.doris.nereids.trees.plans.logical.LogicalInlineTable; +import org.apache.doris.nereids.trees.plans.logical.LogicalOlapTableSink; 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.LogicalUnion; import org.apache.doris.nereids.trees.plans.physical.PhysicalEmptyRelation; import org.apache.doris.nereids.trees.plans.physical.PhysicalHiveTableSink; import org.apache.doris.nereids.trees.plans.physical.PhysicalIcebergTableSink; import org.apache.doris.nereids.trees.plans.physical.PhysicalJdbcTableSink; import org.apache.doris.nereids.trees.plans.physical.PhysicalOlapTableSink; import org.apache.doris.nereids.trees.plans.physical.PhysicalOneRowRelation; +import org.apache.doris.nereids.trees.plans.physical.PhysicalPlan; +import org.apache.doris.nereids.trees.plans.physical.PhysicalProject; import org.apache.doris.nereids.trees.plans.physical.PhysicalSink; import org.apache.doris.nereids.trees.plans.physical.PhysicalUnion; +import org.apache.doris.nereids.trees.plans.visitor.DefaultPlanRewriter; import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor; import org.apache.doris.planner.DataSink; import org.apache.doris.qe.ConnectContext; @@ -60,6 +74,7 @@ import org.apache.doris.system.Backend; import com.google.common.base.Preconditions; import com.google.common.base.Throwables; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -338,7 +353,7 @@ public class InsertIntoTableCommand extends Command implements ForwardWithSync, StatementContext statementContext = ctx.getStatementContext(); AtomicReference<ExecutorFactory> executorFactoryRef = new AtomicReference<>(); - NereidsPlanner planner = new NereidsPlanner(statementContext) { + InsertByInlineTablePlanner planner = new InsertByInlineTablePlanner(ctx.getStatementContext()) { @Override protected void doDistribute(boolean canUseNereidsDistributePlanner) { // when enter this method, the step 1 already executed @@ -449,4 +464,140 @@ public class InsertIntoTableCommand extends Command implements ForwardWithSync, this.physicalSink = physicalSink; } } + + private static class InsertByInlineTablePlanner extends NereidsPlanner { + private AtomicReference<Group> rootGroupRef = new AtomicReference<>(); + + public InsertByInlineTablePlanner(StatementContext statementContext) { + super(statementContext); + } + + @Override + protected void analyze(boolean showPlanProcess) { + DefaultPlanRewriter<Void> analyzer = new DefaultPlanRewriter<Void>() { + @Override + public Plan visitUnboundTableSink( + UnboundTableSink<? extends Plan> olapTableSink, Void context) { + olapTableSink = + (UnboundTableSink<? extends Plan>) super.visitUnboundTableSink(olapTableSink, context); + return new BindSink() + .buildRules() + .stream() + .filter(rule -> rule.getRuleType() == RuleType.BINDING_INSERT_TARGET_TABLE) + .findFirst() + .get() + .transform(olapTableSink, getCascadesContext()) + .get(0); + } + + @Override + public Plan visitLogicalInlineTable(LogicalInlineTable logicalInlineTable, Void context) { + logicalInlineTable = + (LogicalInlineTable) super.visitLogicalInlineTable(logicalInlineTable, context); + return new LogicalUnion( + Qualifier.ALL, logicalInlineTable.getConstantExprsList(), ImmutableList.of() + ); + } + }; + + Plan boundPlan = getCascadesContext().getRewritePlan().accept(analyzer, null); + getCascadesContext().setRewritePlan(boundPlan); + } + + @Override + protected void rewrite(boolean showPlanProcess) { + DefaultPlanRewriter<Void> rewriter = new DefaultPlanRewriter<Void>() { + @Override + public Plan visitLogicalProject(LogicalProject<? extends Plan> project, Void context) { + project = (LogicalProject<? extends Plan>) super.visitLogicalProject(project, context); + if (project.child() instanceof LogicalProject) { + return new MergeProjects() + .build() + .transform(project, getCascadesContext()) + .get(0); + } + return project; + } + }; + getCascadesContext().setRewritePlan( + getCascadesContext().getRewritePlan().accept(rewriter, null) + ); + } + + @Override + protected void optimize() { + DefaultPlanRewriter<Void> optimizer = new DefaultPlanRewriter<Void>() { + @Override + public Plan visitLogicalUnion(LogicalUnion logicalUnion, Void context) { + logicalUnion = (LogicalUnion) super.visitLogicalUnion(logicalUnion, context); + + return new PhysicalUnion(logicalUnion.getQualifier(), + logicalUnion.getOutputs(), + logicalUnion.getRegularChildrenOutputs(), + logicalUnion.getConstantExprsList(), + logicalUnion.getLogicalProperties(), + logicalUnion.children() + ); + } + + @Override + public Plan visitLogicalProject(LogicalProject<? extends Plan> logicalProject, Void context) { + logicalProject = + (LogicalProject<? extends Plan>) super.visitLogicalProject(logicalProject, context); + + return new PhysicalProject<>( + logicalProject.getProjects(), + logicalProject.getLogicalProperties(), + logicalProject.child() + ); + } + + @Override + public Plan visitLogicalOlapTableSink(LogicalOlapTableSink<? extends Plan> olapTableSink, + Void context) { + olapTableSink = + (LogicalOlapTableSink) super.visitLogicalOlapTableSink(olapTableSink, context); + + return new PhysicalOlapTableSink<>( + olapTableSink.getDatabase(), + olapTableSink.getTargetTable(), + olapTableSink.getCols(), + olapTableSink.getPartitionIds(), + olapTableSink.getOutputExprs(), + getCascadesContext().getConnectContext().getSessionVariable().isEnableSingleReplicaInsert(), + olapTableSink.isPartialUpdate(), + olapTableSink.getDmlCommandType(), + Optional.empty(), + olapTableSink.getLogicalProperties(), + olapTableSink.child() + ); + } + }; + + PhysicalPlan physicalPlan = + (PhysicalPlan) getCascadesContext().getRewritePlan().accept(optimizer, null); + + super.physicalPlan = physicalPlan; + + GroupId rootGroupId = GroupId.createGenerator().getNextId(); + Group rootGroup = new Group(rootGroupId, physicalPlan.getLogicalProperties()); + rootGroupRef.set(rootGroup); + } + + @Override + public Group getRoot() { + return rootGroupRef.get(); + } + + @Override + protected PhysicalPlan chooseNthPlan( + Group rootGroup, PhysicalProperties physicalProperties, int nthPlan) { + return super.physicalPlan; + } + + @Override + protected PhysicalPlan postProcess(PhysicalPlan physicalPlan) { + return physicalPlan; + } + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertUtils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertUtils.java index 60e7e5bf805..ba67d7d5ac4 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertUtils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertUtils.java @@ -29,6 +29,7 @@ import org.apache.doris.common.Config; import org.apache.doris.common.FormatOptions; import org.apache.doris.datasource.hive.HMSExternalTable; import org.apache.doris.datasource.jdbc.JdbcExternalTable; +import org.apache.doris.nereids.CascadesContext; import org.apache.doris.nereids.analyzer.UnboundAlias; import org.apache.doris.nereids.analyzer.UnboundHiveTableSink; import org.apache.doris.nereids.analyzer.UnboundIcebergTableSink; @@ -36,19 +37,19 @@ import org.apache.doris.nereids.analyzer.UnboundJdbcTableSink; import org.apache.doris.nereids.analyzer.UnboundOneRowRelation; import org.apache.doris.nereids.analyzer.UnboundTableSink; import org.apache.doris.nereids.exceptions.AnalysisException; -import org.apache.doris.nereids.parser.LogicalPlanBuilder; import org.apache.doris.nereids.parser.NereidsParser; +import org.apache.doris.nereids.properties.PhysicalProperties; +import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext; +import org.apache.doris.nereids.rules.expression.rules.FoldConstantRuleOnFE; import org.apache.doris.nereids.trees.expressions.Alias; import org.apache.doris.nereids.trees.expressions.Cast; import org.apache.doris.nereids.trees.expressions.DefaultValueSlot; import org.apache.doris.nereids.trees.expressions.Expression; import org.apache.doris.nereids.trees.expressions.NamedExpression; -import org.apache.doris.nereids.trees.expressions.StatementScopeIdGenerator; import org.apache.doris.nereids.trees.expressions.literal.ArrayLiteral; import org.apache.doris.nereids.trees.expressions.literal.Literal; import org.apache.doris.nereids.trees.expressions.literal.NullLiteral; import org.apache.doris.nereids.trees.plans.Plan; -import org.apache.doris.nereids.trees.plans.algebra.SetOperation.Qualifier; import org.apache.doris.nereids.trees.plans.commands.info.DMLCommandType; import org.apache.doris.nereids.trees.plans.logical.LogicalInlineTable; import org.apache.doris.nereids.trees.plans.logical.LogicalPlan; @@ -337,18 +338,30 @@ public class InsertUtils { if (!(query instanceof LogicalInlineTable)) { return plan; } + LogicalInlineTable logicalInlineTable = (LogicalInlineTable) query; - ImmutableList.Builder<LogicalPlan> oneRowRelationBuilder = ImmutableList.builder(); + ImmutableList.Builder<List<NamedExpression>> optimizedRowConstructors + = ImmutableList.builderWithExpectedSize(logicalInlineTable.getConstantExprsList().size()); List<Column> columns = table.getBaseSchema(false); + ConnectContext context = ConnectContext.get(); + ExpressionRewriteContext rewriteContext = null; + if (context != null && context.getStatementContext() != null) { + rewriteContext = new ExpressionRewriteContext( + CascadesContext.initContext( + context.getStatementContext(), logicalInlineTable, PhysicalProperties.ANY + ) + ); + } + for (List<NamedExpression> values : logicalInlineTable.getConstantExprsList()) { - ImmutableList.Builder<NamedExpression> constantExprs = ImmutableList.builder(); + ImmutableList.Builder<NamedExpression> optimizedRowConstructor = ImmutableList.builder(); if (values.isEmpty()) { if (CollectionUtils.isNotEmpty(unboundLogicalSink.getColNames())) { throw new AnalysisException("value list should not be empty if columns are specified"); } for (Column column : columns) { - constantExprs.add(generateDefaultExpression(column)); + optimizedRowConstructor.add(generateDefaultExpression(column)); } } else { if (CollectionUtils.isNotEmpty(unboundLogicalSink.getColNames())) { @@ -374,10 +387,14 @@ public class InsertUtils { + "' in table '" + table.getName() + "' is not allowed."); } if (values.get(i) instanceof DefaultValueSlot) { - constantExprs.add(generateDefaultExpression(sameNameColumn)); + optimizedRowConstructor.add(generateDefaultExpression(sameNameColumn)); } else { DataType targetType = DataType.fromCatalogType(sameNameColumn.getType()); - constantExprs.add((NamedExpression) castValue(values.get(i), targetType)); + Expression castValue = castValue(values.get(i), targetType); + castValue = rewriteContext == null + ? castValue + : FoldConstantRuleOnFE.evaluate(castValue, rewriteContext); + optimizedRowConstructor.add((NamedExpression) castValue); } } } else { @@ -392,30 +409,28 @@ public class InsertUtils { + "' in table '" + table.getName() + "' is not allowed."); } if (values.get(i) instanceof DefaultValueSlot) { - constantExprs.add(generateDefaultExpression(columns.get(i))); + optimizedRowConstructor.add(generateDefaultExpression(columns.get(i))); } else { DataType targetType = DataType.fromCatalogType(columns.get(i).getType()); - constantExprs.add((NamedExpression) castValue(values.get(i), targetType)); + Expression castValue = castValue(values.get(i), targetType); + castValue = rewriteContext == null + ? castValue + : FoldConstantRuleOnFE.evaluate(castValue, rewriteContext); + optimizedRowConstructor.add((NamedExpression) castValue); } } } } - oneRowRelationBuilder.add(new UnboundOneRowRelation( - StatementScopeIdGenerator.newRelationId(), constantExprs.build())); - } - List<LogicalPlan> oneRowRelations = oneRowRelationBuilder.build(); - if (oneRowRelations.size() == 1) { - return plan.withChildren(oneRowRelations.get(0)); - } else { - return plan.withChildren( - LogicalPlanBuilder.reduceToLogicalPlanTree(0, oneRowRelations.size() - 1, - oneRowRelations, Qualifier.ALL)); + optimizedRowConstructors.add(optimizedRowConstructor.build()); } + + return plan.withChildren(new LogicalInlineTable(optimizedRowConstructors.build())); } private static Expression castValue(Expression value, DataType targetType) { if (value instanceof UnboundAlias) { - return value.withChildren(TypeCoercionUtils.castUnbound(((UnboundAlias) value).child(), targetType)); + UnboundAlias unboundAlias = (UnboundAlias) value; + return new Alias(TypeCoercionUtils.castUnbound(unboundAlias.child(), targetType)); } else { return TypeCoercionUtils.castUnbound(value, targetType); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/OlapGroupCommitInsertExecutor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/OlapGroupCommitInsertExecutor.java index e7b1f4d5818..5a6736873d2 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/OlapGroupCommitInsertExecutor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/OlapGroupCommitInsertExecutor.java @@ -31,6 +31,7 @@ import org.apache.doris.nereids.NereidsPlanner; import org.apache.doris.nereids.analyzer.UnboundTableSink; import org.apache.doris.nereids.exceptions.AnalysisException; import org.apache.doris.nereids.trees.plans.algebra.OneRowRelation; +import org.apache.doris.nereids.trees.plans.logical.LogicalInlineTable; import org.apache.doris.nereids.trees.plans.logical.LogicalPlan; import org.apache.doris.nereids.trees.plans.logical.LogicalUnion; import org.apache.doris.planner.GroupCommitPlanner; @@ -93,8 +94,11 @@ public class OlapGroupCommitInsertExecutor extends OlapInsertExecutor { conditions.add(Pair.of(() -> !(insertCtx.isPresent() && insertCtx.get() instanceof OlapInsertCommandContext && ((OlapInsertCommandContext) insertCtx.get()).isOverwrite()), () -> "is overwrite command")); conditions.add(Pair.of( - () -> tableSink.child() instanceof OneRowRelation || tableSink.child() instanceof LogicalUnion, - () -> "not one row relation or union, class: " + tableSink.child().getClass().getName())); + () -> tableSink.child() instanceof OneRowRelation + || tableSink.child() instanceof LogicalUnion + || tableSink.child() instanceof LogicalInlineTable, + () -> "not one row relation or union or inline table, class: " + + tableSink.child().getClass().getName())); ctx.setGroupCommit(conditions.stream().allMatch(p -> p.first.getAsBoolean())); if (!ctx.isGroupCommit() && LOG.isDebugEnabled()) { for (Pair<BooleanSupplier, Supplier<String>> pair : conditions) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalInlineTable.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalInlineTable.java index b2a2a1d83ca..57eb7be4c6e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalInlineTable.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalInlineTable.java @@ -26,12 +26,14 @@ import org.apache.doris.nereids.trees.plans.BlockFuncDepsPropagation; import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.trees.plans.PlanType; import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor; +import org.apache.doris.nereids.util.Utils; import com.google.common.collect.ImmutableList; import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.stream.Collectors; /** * represent value list such as values(1), (2), (3) will generate LogicalInlineTable((1), (2), (3)). @@ -79,7 +81,10 @@ public class LogicalInlineTable extends LogicalLeaf implements BlockFuncDepsProp @Override public List<Slot> computeOutput() { - return ImmutableList.of(); + return constantExprsList.get(0) + .stream() + .map(NamedExpression::toSlot) + .collect(Collectors.toList()); } @Override @@ -98,4 +103,10 @@ public class LogicalInlineTable extends LogicalLeaf implements BlockFuncDepsProp public int hashCode() { return Objects.hash(constantExprsList); } + + @Override + public String toString() { + return Utils.toSqlString("LogicalInlineTable[" + id.asInt() + "] (rowNum=" + + constantExprsList.size() + ")"); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalUnion.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalUnion.java index 459044100b6..acd07536983 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalUnion.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalUnion.java @@ -42,6 +42,7 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; /** * Logical Union. @@ -205,6 +206,23 @@ public class LogicalUnion extends LogicalSetOperation implements Union, OutputPr // don't propagate uniform slots } + @Override + public boolean hasUnboundExpression() { + if (!constantExprsList.isEmpty() && children.isEmpty()) { + return false; + } + return super.hasUnboundExpression(); + } + + @Override + public List<Slot> computeOutput() { + if (children.isEmpty()) { + return constantExprsList.get(0).stream().map(NamedExpression::toSlot).collect(Collectors.toList()); + } else { + return super.computeOutput(); + } + } + private List<BitSet> mapSlotToIndex(Plan plan, List<Set<Slot>> equalSlotsList) { Map<Slot, Integer> slotToIndex = new HashMap<>(); for (int i = 0; i < plan.getOutput().size(); i++) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalOlapTableSink.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalOlapTableSink.java index efe0a03e370..90e92ca1ae2 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalOlapTableSink.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalOlapTableSink.java @@ -178,7 +178,7 @@ public class PhysicalOlapTableSink<CHILD_TYPE extends Plan> extends PhysicalTabl @Override public String toString() { - return Utils.toSqlString("LogicalOlapTableSink[" + id.asInt() + "]", + return Utils.toSqlString("PhysicalOlapTableSink[" + id.asInt() + "]", "outputExprs", outputExprs, "database", database.getFullName(), "targetTable", targetTable.getName(), --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org