|
42 | 42 | import org.apache.doris.nereids.rules.expression.ExpressionRewriteContext;
|
43 | 43 | import org.apache.doris.nereids.trees.expressions.Alias;
|
44 | 44 | import org.apache.doris.nereids.trees.expressions.BoundStar;
|
| 45 | +import org.apache.doris.nereids.trees.expressions.Cast; |
45 | 46 | import org.apache.doris.nereids.trees.expressions.DefaultValueSlot;
|
46 | 47 | import org.apache.doris.nereids.trees.expressions.EqualTo;
|
47 | 48 | import org.apache.doris.nereids.trees.expressions.ExprId;
|
|
89 | 90 | import org.apache.doris.nereids.trees.plans.logical.UsingJoin;
|
90 | 91 | import org.apache.doris.nereids.trees.plans.visitor.InferPlanOutputAlias;
|
91 | 92 | import org.apache.doris.nereids.types.BooleanType;
|
| 93 | +import org.apache.doris.nereids.types.DataType; |
| 94 | +import org.apache.doris.nereids.types.NullType; |
92 | 95 | import org.apache.doris.nereids.types.StructField;
|
93 | 96 | import org.apache.doris.nereids.types.StructType;
|
| 97 | +import org.apache.doris.nereids.types.TinyIntType; |
94 | 98 | import org.apache.doris.nereids.util.ExpressionUtils;
|
95 | 99 | import org.apache.doris.nereids.util.PlanUtils;
|
96 | 100 | import org.apache.doris.nereids.util.TypeCoercionUtils;
|
@@ -208,22 +212,38 @@ protected boolean condition(Rule rule, Plan plan) {
|
208 | 212 |
|
209 | 213 | private LogicalResultSink<Plan> bindResultSink(MatchingContext<UnboundResultSink<Plan>> ctx) {
|
210 | 214 | LogicalSink<Plan> sink = ctx.root;
|
| 215 | + Plan child = sink.child(); |
| 216 | + List<Slot> output = child.getOutput(); |
| 217 | + List<NamedExpression> castNullToTinyInt = Lists.newArrayListWithCapacity(output.size()); |
| 218 | + boolean needProject = false; |
| 219 | + for (Slot slot : output) { |
| 220 | + DataType newType = TypeCoercionUtils.replaceSpecifiedType( |
| 221 | + slot.getDataType(), NullType.class, TinyIntType.INSTANCE); |
| 222 | + if (!newType.equals(slot.getDataType())) { |
| 223 | + needProject = true; |
| 224 | + castNullToTinyInt.add(new Alias(new Cast(slot, newType))); |
| 225 | + } else { |
| 226 | + castNullToTinyInt.add(slot); |
| 227 | + } |
| 228 | + } |
| 229 | + if (needProject) { |
| 230 | + child = new LogicalProject<>(castNullToTinyInt, child); |
| 231 | + } |
211 | 232 | if (ctx.connectContext.getState().isQuery()) {
|
212 |
| - List<NamedExpression> outputExprs = sink.child().getOutput().stream() |
| 233 | + List<NamedExpression> outputExprs = child.getOutput().stream() |
213 | 234 | .map(NamedExpression.class::cast)
|
214 | 235 | .collect(ImmutableList.toImmutableList());
|
215 |
| - return new LogicalResultSink<>(outputExprs, sink.child()); |
| 236 | + return new LogicalResultSink<>(outputExprs, child); |
216 | 237 | }
|
217 | 238 | // Should infer column name for expression when query command
|
218 |
| - final ImmutableListMultimap.Builder<ExprId, Integer> exprIdToIndexMapBuilder = |
219 |
| - ImmutableListMultimap.builder(); |
220 |
| - List<Slot> childOutput = sink.child().getOutput(); |
| 239 | + final ImmutableListMultimap.Builder<ExprId, Integer> exprIdToIndexMapBuilder = ImmutableListMultimap.builder(); |
| 240 | + List<Slot> childOutput = child.getOutput(); |
221 | 241 | for (int index = 0; index < childOutput.size(); index++) {
|
222 | 242 | exprIdToIndexMapBuilder.put(childOutput.get(index).getExprId(), index);
|
223 | 243 | }
|
224 | 244 | InferPlanOutputAlias aliasInfer = new InferPlanOutputAlias(childOutput);
|
225 |
| - List<NamedExpression> output = aliasInfer.infer(sink.child(), exprIdToIndexMapBuilder.build()); |
226 |
| - return new LogicalResultSink<>(output, sink.child()); |
| 245 | + List<NamedExpression> sinkExpr = aliasInfer.infer(child, exprIdToIndexMapBuilder.build()); |
| 246 | + return new LogicalResultSink<>(sinkExpr, child); |
227 | 247 | }
|
228 | 248 |
|
229 | 249 | private LogicalSubQueryAlias<Plan> bindSubqueryAlias(MatchingContext<LogicalSubQueryAlias<Plan>> ctx) {
|
|
0 commit comments