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

Reply via email to