[fix](nereids) LogicalProject should always has non-empty project list (#18863)

This commit is contained in:
starocean999
2023-04-21 14:28:07 +08:00
committed by GitHub
parent 0c26f8df4d
commit c41b486e7e
6 changed files with 117 additions and 7 deletions

View File

@ -251,9 +251,6 @@ public class ColumnPruning extends DefaultPlanRewriter<PruneContext> implements
for (Plan child : plan.children()) {
Set<Slot> childOutputSet = child.getOutputSet();
Set<Slot> childRequiredSlots = Sets.intersection(childrenRequiredSlots, childOutputSet);
if (childRequiredSlots.isEmpty()) {
childRequiredSlots = ImmutableSet.of(ExpressionUtils.selectMinimumColumn(childOutputSet));
}
Plan prunedChild = doPruneChild(plan, child, childRequiredSlots);
if (prunedChild != child) {
hasNewChildren = true;

View File

@ -17,6 +17,7 @@
package org.apache.doris.nereids.trees.plans.logical;
import org.apache.doris.nereids.analyzer.Unbound;
import org.apache.doris.nereids.analyzer.UnboundStar;
import org.apache.doris.nereids.memo.GroupExpression;
import org.apache.doris.nereids.properties.LogicalProperties;
@ -28,6 +29,7 @@ import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.PlanType;
import org.apache.doris.nereids.trees.plans.algebra.Project;
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
import org.apache.doris.nereids.util.ExpressionUtils;
import org.apache.doris.nereids.util.Utils;
import com.google.common.base.Preconditions;
@ -82,7 +84,14 @@ public class LogicalProject<CHILD_TYPE extends Plan> extends LogicalUnary<CHILD_
Optional<GroupExpression> groupExpression, Optional<LogicalProperties> logicalProperties,
CHILD_TYPE child, boolean isDistinct) {
super(PlanType.LOGICAL_PROJECT, groupExpression, logicalProperties, child);
this.projects = ImmutableList.copyOf(Objects.requireNonNull(projects, "projects can not be null"));
Preconditions.checkArgument(projects != null, "projects can not be null");
// only ColumnPrune rule may produce empty projects, this happens in rewrite phase
// so if projects is empty, all plans have been bound already.
Preconditions.checkArgument(!projects.isEmpty() || !(child instanceof Unbound),
"projects can not be empty when child plan is unbound");
this.projects = projects.isEmpty()
? ImmutableList.of(ExpressionUtils.selectMinimumColumn(child.getOutput()))
: projects;
this.excepts = ImmutableList.copyOf(excepts);
this.canEliminate = canEliminate;
this.isDistinct = isDistinct;

View File

@ -212,6 +212,9 @@ public class ExpressionUtils {
minSlot = slot;
} else {
int slotDataTypeWidth = slot.getDataType().width();
if (slotDataTypeWidth < 0) {
continue;
}
minSlot = minSlot.getDataType().width() > slotDataTypeWidth ? slot : minSlot;
}
}