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 d8327d9b7f3b8f4b4a2fdb0a6ebecdc470816e2d Author: 924060929 <lanhuaj...@selectdb.com> AuthorDate: Fri Dec 6 12:03:46 2024 +0800 fix --- .../trees/plans/commands/insert/InsertUtils.java | 42 ++++++++++++--- .../trees/plans/logical/LogicalInlineTable.java | 59 ++++++++++++++++++---- 2 files changed, 85 insertions(+), 16 deletions(-) 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 570011d3b7c..b09b2429941 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 @@ -56,6 +56,7 @@ import org.apache.doris.nereids.trees.plans.logical.UnboundLogicalSink; import org.apache.doris.nereids.types.DataType; import org.apache.doris.nereids.util.RelationUtil; import org.apache.doris.nereids.util.TypeCoercionUtils; +import org.apache.doris.nereids.util.Utils; import org.apache.doris.proto.InternalService; import org.apache.doris.qe.ConnectContext; import org.apache.doris.qe.InsertStreamTxnExecutor; @@ -80,6 +81,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.Sets; import org.apache.commons.collections.CollectionUtils; +import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.Set; @@ -353,14 +355,21 @@ public class InsertUtils { ); } + Boolean[] outputSlotNullables = new Boolean[logicalInlineTable.getConstantExprsList().get(0).size()]; + Arrays.fill(outputSlotNullables, false); + for (List<NamedExpression> values : logicalInlineTable.getConstantExprsList()) { 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) { - optimizedRowConstructor.add(generateDefaultExpression(column)); + for (int i = 0; i < columns.size(); i++) { + Column column = columns.get(i); + NamedExpression defaultExpression = generateDefaultExpression(column); + addColumnValue( + optimizedRowConstructor, outputSlotNullables, i, defaultExpression + ); } } else { if (CollectionUtils.isNotEmpty(unboundLogicalSink.getColNames())) { @@ -386,14 +395,19 @@ public class InsertUtils { + "' in table '" + table.getName() + "' is not allowed."); } if (values.get(i) instanceof DefaultValueSlot) { - optimizedRowConstructor.add(generateDefaultExpression(sameNameColumn)); + NamedExpression defaultExpression = generateDefaultExpression(sameNameColumn); + addColumnValue( + optimizedRowConstructor, outputSlotNullables, i, defaultExpression + ); } else { DataType targetType = DataType.fromCatalogType(sameNameColumn.getType()); Expression castValue = castValue(values.get(i), targetType); castValue = rewriteContext == null ? castValue : FoldConstantRuleOnFE.evaluate(castValue, rewriteContext); - optimizedRowConstructor.add((NamedExpression) castValue); + addColumnValue( + optimizedRowConstructor, outputSlotNullables, i, (NamedExpression) castValue + ); } } } else { @@ -408,14 +422,19 @@ public class InsertUtils { + "' in table '" + table.getName() + "' is not allowed."); } if (values.get(i) instanceof DefaultValueSlot) { - optimizedRowConstructor.add(generateDefaultExpression(columns.get(i))); + NamedExpression defaultExpression = generateDefaultExpression(columns.get(i)); + addColumnValue( + optimizedRowConstructor, outputSlotNullables, i, defaultExpression + ); } else { DataType targetType = DataType.fromCatalogType(columns.get(i).getType()); Expression castValue = castValue(values.get(i), targetType); castValue = rewriteContext == null ? castValue : FoldConstantRuleOnFE.evaluate(castValue, rewriteContext); - optimizedRowConstructor.add((NamedExpression) castValue); + addColumnValue( + optimizedRowConstructor, outputSlotNullables, i, (NamedExpression) castValue + ); } } } @@ -423,7 +442,16 @@ public class InsertUtils { optimizedRowConstructors.add(optimizedRowConstructor.build()); } - return plan.withChildren(new LogicalInlineTable(optimizedRowConstructors.build())); + return plan.withChildren(new LogicalInlineTable(optimizedRowConstructors.build(), Optional.of( + Utils.fastToImmutableList(outputSlotNullables) + ))); + } + + private static void addColumnValue( + ImmutableList.Builder<NamedExpression> optimizedRowConstructor, + Boolean[] nullable, int index, NamedExpression value) { + optimizedRowConstructor.add(value); + nullable[index] |= value.nullable(); } private static Expression castValue(Expression value, DataType targetType) { 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 a229c8780ad..762ac6351d2 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 @@ -17,11 +17,13 @@ package org.apache.doris.nereids.trees.plans.logical; +import org.apache.doris.nereids.exceptions.AnalysisException; import org.apache.doris.nereids.memo.GroupExpression; import org.apache.doris.nereids.properties.LogicalProperties; 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.SlotReference; import org.apache.doris.nereids.trees.plans.BlockFuncDepsPropagation; import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.trees.plans.PlanType; @@ -33,7 +35,6 @@ 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)). @@ -42,15 +43,27 @@ public class LogicalInlineTable extends LogicalLeaf implements BlockFuncDepsProp private final List<List<NamedExpression>> constantExprsList; + private final Optional<List<Boolean>> outputNullables; + public LogicalInlineTable(List<List<NamedExpression>> constantExprsList) { - this(constantExprsList, Optional.empty(), Optional.empty()); + this(constantExprsList, Optional.empty(), Optional.empty(), Optional.empty()); + } + + public LogicalInlineTable(List<List<NamedExpression>> constantExprsList, Optional<List<Boolean>> outputNullables) { + this(constantExprsList, outputNullables, Optional.empty(), Optional.empty()); } public LogicalInlineTable(List<List<NamedExpression>> constantExprsList, + Optional<List<Boolean>> outputNullables, Optional<GroupExpression> groupExpression, Optional<LogicalProperties> logicalProperties) { super(PlanType.LOGICAL_INLINE_TABLE, groupExpression, logicalProperties); - this.constantExprsList = ImmutableList.copyOf( + + if (constantExprsList.isEmpty()) { + throw new AnalysisException("constantExprsList should now be empty"); + } + this.outputNullables = Objects.requireNonNull(outputNullables, "outputNullables should not be null"); + this.constantExprsList = Utils.fastToImmutableList( Objects.requireNonNull(constantExprsList, "constantExprsList should not be null")); } @@ -70,21 +83,49 @@ public class LogicalInlineTable extends LogicalLeaf implements BlockFuncDepsProp @Override public Plan withGroupExpression(Optional<GroupExpression> groupExpression) { - return new LogicalInlineTable(constantExprsList, groupExpression, Optional.of(getLogicalProperties())); + return new LogicalInlineTable( + constantExprsList, outputNullables, groupExpression, Optional.of(getLogicalProperties()) + ); } @Override public Plan withGroupExprLogicalPropChildren(Optional<GroupExpression> groupExpression, Optional<LogicalProperties> logicalProperties, List<Plan> children) { - return new LogicalInlineTable(constantExprsList, groupExpression, logicalProperties); + if (!children.isEmpty()) { + throw new AnalysisException("children should not be empty"); + } + return new LogicalInlineTable(constantExprsList, outputNullables, groupExpression, logicalProperties); } @Override public List<Slot> computeOutput() { - return constantExprsList.get(0) - .stream() - .map(NamedExpression::toSlot) - .collect(Collectors.toList()); + if (outputNullables.isPresent()) { + List<Boolean> nullables = outputNullables.get(); + int columnNum = constantExprsList.get(0).size(); + List<NamedExpression> firstRow = constantExprsList.get(0); + ImmutableList.Builder<Slot> output = ImmutableList.builderWithExpectedSize(constantExprsList.size()); + for (int i = 0; i < columnNum; i++) { + NamedExpression firstRowColumn = firstRow.get(i); + output.add(new SlotReference(firstRowColumn.getName(), firstRowColumn.getDataType(), nullables.get(i))); + } + return output.build(); + } else { + int columnNum = constantExprsList.get(0).size(); + List<NamedExpression> firstRow = constantExprsList.get(0); + ImmutableList.Builder<Slot> output = ImmutableList.builderWithExpectedSize(constantExprsList.size()); + for (int i = 0; i < columnNum; i++) { + NamedExpression firstRowColumn = firstRow.get(i); + boolean nullable = false; + for (List<NamedExpression> row : constantExprsList) { + if (row.get(i).nullable()) { + nullable = true; + break; + } + } + output.add(new SlotReference(firstRowColumn.getName(), firstRowColumn.getDataType(), nullable)); + } + return output.build(); + } } @Override --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org