[fix](agg_state) adjust nullable should apply on agg_state inner type too (#37489) (#38281)

pick from master #37489

after adjust nullable, some children nullable has changed. so, we need
to update agg_state type inner type nullable too.
This commit is contained in:
morrySnow
2024-07-24 13:55:09 +08:00
committed by GitHub
parent 792bd7c74a
commit 17c33665e5
12 changed files with 111 additions and 19 deletions

View File

@ -102,7 +102,12 @@ public class MappingSlot extends Slot {
}
@Override
public Slot withNullable(boolean newNullable) {
public Slot withNullable(boolean nullable) {
return this;
}
@Override
public Slot withNullableAndDataType(boolean nullable, DataType dataType) {
return this;
}

View File

@ -293,20 +293,20 @@ public class AdjustNullable extends DefaultPlanRewriter<Map<ExprId, Slot>> imple
return result.build();
}
private Map<ExprId, Slot> collectChildrenOutputMap(LogicalPlan plan) {
return plan.children().stream()
.map(Plan::getOutputSet)
.flatMap(Set::stream)
.collect(Collectors.toMap(NamedExpression::getExprId, s -> s));
}
private static class SlotReferenceReplacer extends DefaultExpressionRewriter<Map<ExprId, Slot>> {
public static SlotReferenceReplacer INSTANCE = new SlotReferenceReplacer();
@Override
public Expression visitSlotReference(SlotReference slotReference, Map<ExprId, Slot> context) {
if (context.containsKey(slotReference.getExprId())) {
return slotReference.withNullable(context.get(slotReference.getExprId()).nullable());
Slot slot = context.get(slotReference.getExprId());
if (slot.getDataType().isAggStateType()) {
// we must replace data type, because nested type and agg state contains nullable of their children.
// TODO: remove if statement after we ensure be constant folding do not change expr type at all.
return slotReference.withNullableAndDataType(slot.nullable(), slot.getDataType());
} else {
return slotReference.withNullable(slot.nullable());
}
} else {
return slotReference;
}

View File

@ -158,7 +158,12 @@ public class ArrayItemReference extends NamedExpression implements ExpectsInputT
}
@Override
public SlotReference withNullable(boolean newNullable) {
public SlotReference withNullable(boolean nullable) {
return new ArrayItemSlot(exprId, name.get(), dataType, this.nullable);
}
@Override
public Slot withNullableAndDataType(boolean nullable, DataType dataType) {
return new ArrayItemSlot(exprId, name.get(), dataType, nullable);
}

View File

@ -19,6 +19,7 @@ package org.apache.doris.nereids.trees.expressions;
import org.apache.doris.common.Pair;
import org.apache.doris.nereids.trees.expressions.shape.LeafExpression;
import org.apache.doris.nereids.types.DataType;
import com.google.common.collect.ImmutableList;
@ -43,7 +44,11 @@ public abstract class Slot extends NamedExpression implements LeafExpression {
return this;
}
public Slot withNullable(boolean newNullable) {
public Slot withNullable(boolean nullable) {
throw new RuntimeException("Do not implement");
}
public Slot withNullableAndDataType(boolean nullable, DataType dataType) {
throw new RuntimeException("Do not implement");
}

View File

@ -249,12 +249,20 @@ public class SlotReference extends Slot {
}
@Override
public SlotReference withNullable(boolean newNullable) {
if (this.nullable == newNullable) {
public SlotReference withNullable(boolean nullable) {
if (this.nullable == nullable) {
return this;
}
return new SlotReference(exprId, name, dataType, nullable,
qualifier, table, column, internalName, subPath, indexInSqlString);
}
return new SlotReference(exprId, name, dataType, newNullable,
@Override
public Slot withNullableAndDataType(boolean nullable, DataType dataType) {
if (this.nullable == nullable && this.dataType.equals(dataType)) {
return this;
}
return new SlotReference(exprId, name, dataType, nullable,
qualifier, table, column, internalName, subPath, indexInSqlString);
}

View File

@ -121,11 +121,20 @@ public class VirtualSlotReference extends SlotReference implements SlotNotFromCh
return false;
}
public VirtualSlotReference withNullable(boolean newNullable) {
if (this.nullable == newNullable) {
public VirtualSlotReference withNullable(boolean nullable) {
if (this.nullable == nullable) {
return this;
}
return new VirtualSlotReference(exprId, name.get(), dataType, newNullable, qualifier,
return new VirtualSlotReference(exprId, name.get(), dataType, nullable, qualifier,
originExpression, computeLongValueMethod);
}
@Override
public Slot withNullableAndDataType(boolean nullable, DataType dataType) {
if (this.nullable == nullable && this.dataType.equals(dataType)) {
return this;
}
return new VirtualSlotReference(exprId, name.get(), dataType, nullable, qualifier,
originExpression, computeLongValueMethod);
}

View File

@ -107,6 +107,8 @@ public class CreateTableCommand extends Command implements ForwardWithSync {
LogicalPlan query = ctasQuery.get();
List<String> ctasCols = createTableInfo.getCtasColumns();
NereidsPlanner planner = new NereidsPlanner(ctx.getStatementContext());
// must disable constant folding by be, because be constant folding may return wrong type
ctx.getSessionVariable().disableConstantFoldingByBEOnce();
Plan plan = planner.plan(new UnboundResultSink<>(query), PhysicalProperties.ANY, ExplainLevel.NONE);
if (ctasCols == null) {
// we should analyze the plan firstly to get the columns' name.

View File

@ -141,7 +141,7 @@ public class CreateMTMVInfo {
/**
* analyze create table info
*/
public void analyze(ConnectContext ctx) {
public void analyze(ConnectContext ctx) throws Exception {
// analyze table name
mvName.analyze(ctx);
try {
@ -201,12 +201,14 @@ public class CreateMTMVInfo {
/**
* analyzeQuery
*/
public void analyzeQuery(ConnectContext ctx, Map<String, String> mvProperties) {
public void analyzeQuery(ConnectContext ctx, Map<String, String> mvProperties) throws Exception {
// create table as select
StatementContext statementContext = ctx.getStatementContext();
NereidsPlanner planner = new NereidsPlanner(statementContext);
// this is for expression column name infer when not use alias
LogicalSink<Plan> logicalSink = new UnboundResultSink<>(logicalQuery);
// must disable constant folding by be, because be constant folding may return wrong type
ctx.getSessionVariable().disableConstantFoldingByBEOnce();
Plan plan = planner.plan(logicalSink, PhysicalProperties.ANY, ExplainLevel.ALL_PLAN);
if (plan.anyMatch(node -> node instanceof OneRowRelation)) {
throw new AnalysisException("at least contain one table");

View File

@ -3702,6 +3702,15 @@ public class SessionVariable implements Serializable, Writable {
new SetVar(SessionVariable.ENABLE_FALLBACK_TO_ORIGINAL_PLANNER, new StringLiteral("true")));
}
public void disableConstantFoldingByBEOnce() throws DdlException {
if (!enableFoldConstantByBe) {
return;
}
setIsSingleSetVar(true);
VariableMgr.setVar(this,
new SetVar(SessionVariable.ENABLE_FOLD_CONSTANT_BY_BE, new StringLiteral("false")));
}
public void disableNereidsPlannerOnce() throws DdlException {
if (!enableNereidsPlanner) {
return;