From dadfd85c40cbdf9f5a6316cdab3cd91b63e725e8 Mon Sep 17 00:00:00 2001 From: Kikyou1997 <33112463+Kikyou1997@users.noreply.github.com> Date: Mon, 5 Sep 2022 19:09:00 +0800 Subject: [PATCH] prune for agg with constant expr (#12274) Currently, nereids doesn't support aggregate function with no slot reference in query, since all the column would be pruned, e.g. SELECT COUNT(1) FROM t; This PR reserve the column with the smallest amount of data when doing column prune under this situation. To be noticed, this PR ONLY handle aggregate functions. So projection with no slot reference need to be handled in future. --- .../apache/doris/analysis/SlotDescriptor.java | 4 - .../translator/PhysicalPlanTranslator.java | 26 +++--- .../doris/nereids/jobs/batch/RewriteJob.java | 3 +- .../nereids/rules/analysis/BindFunction.java | 2 +- .../rewrite/logical/PruneAggChildColumns.java | 41 ++++++++- .../logical/PruneFilterChildColumns.java | 1 + .../doris/nereids/types/BigIntType.java | 8 ++ .../doris/nereids/types/BooleanType.java | 7 ++ .../apache/doris/nereids/types/DataType.java | 2 + .../doris/nereids/types/DateTimeType.java | 7 ++ .../apache/doris/nereids/types/DateType.java | 7 ++ .../doris/nereids/types/DecimalType.java | 8 ++ .../doris/nereids/types/DoubleType.java | 7 ++ .../apache/doris/nereids/types/FloatType.java | 7 ++ .../doris/nereids/types/IntegerType.java | 7 ++ .../doris/nereids/types/LargeIntType.java | 7 ++ .../apache/doris/nereids/types/NullType.java | 7 ++ .../doris/nereids/types/SmallIntType.java | 7 ++ .../doris/nereids/types/TinyIntType.java | 7 ++ .../nereids/types/coercion/CharacterType.java | 7 ++ .../types/coercion/FractionalType.java | 5 + .../nereids/types/coercion/PrimitiveType.java | 5 + .../rewrite/logical/ColumnPruningTest.java | 92 +++++++++++++++++++ .../data/nereids_syntax_p0/agg_with_const.out | 10 ++ .../nereids_syntax_p0/agg_with_const.groovy | 48 ++++++++++ 25 files changed, 314 insertions(+), 18 deletions(-) create mode 100644 regression-test/data/nereids_syntax_p0/agg_with_const.out create mode 100644 regression-test/suites/nereids_syntax_p0/agg_with_const.groovy diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java index a3fb63f0e1..330bcea5e2 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java @@ -347,8 +347,4 @@ public class SlotDescriptor { return parent.getTable() instanceof OlapTable; } - public void setMaterialized(boolean materialized) { - isMaterialized = materialized; - } - } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/PhysicalPlanTranslator.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/PhysicalPlanTranslator.java index 50632182ae..26da00175f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/PhysicalPlanTranslator.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/PhysicalPlanTranslator.java @@ -21,6 +21,7 @@ import org.apache.doris.analysis.AggregateInfo; import org.apache.doris.analysis.BaseTableRef; import org.apache.doris.analysis.Expr; import org.apache.doris.analysis.FunctionCallExpr; +import org.apache.doris.analysis.SlotDescriptor; import org.apache.doris.analysis.SlotId; import org.apache.doris.analysis.SlotRef; import org.apache.doris.analysis.SortInfo; @@ -31,7 +32,6 @@ import org.apache.doris.catalog.OlapTable; import org.apache.doris.catalog.Table; import org.apache.doris.nereids.exceptions.AnalysisException; import org.apache.doris.nereids.properties.OrderKey; -import org.apache.doris.nereids.trees.expressions.Alias; import org.apache.doris.nereids.trees.expressions.EqualTo; import org.apache.doris.nereids.trees.expressions.ExprId; import org.apache.doris.nereids.trees.expressions.Expression; @@ -354,8 +354,12 @@ public class PhysicalPlanTranslator extends DefaultPlanVisitor ExpressionTranslator.translate(e, context)) .collect(Collectors.toList()); - TupleDescriptor leftTuple = context.getTupleDesc(leftPlanRoot); - TupleDescriptor rightTuple = context.getTupleDesc(rightPlanRoot); + TupleDescriptor leftChildOutputTupleDesc = leftPlanRoot.getOutputTupleDesc(); + TupleDescriptor leftTuple = + leftChildOutputTupleDesc != null ? leftChildOutputTupleDesc : context.getTupleDesc(leftPlanRoot); + TupleDescriptor rightChildOutputTupleDesc = rightPlanRoot.getOutputTupleDesc(); + TupleDescriptor rightTuple = + rightChildOutputTupleDesc != null ? rightChildOutputTupleDesc : context.getTupleDesc(rightPlanRoot); // Nereids does not care about output order of join, // but BE need left child's output must be before right child's output. @@ -414,12 +418,6 @@ public class PhysicalPlanTranslator extends DefaultPlanVisitor project, PlanTranslatorContext context) { PlanFragment inputFragment = project.child(0).accept(this, context); - // TODO: handle p.child(0) is not NamedExpression. - project.getProjects().stream().filter(Alias.class::isInstance).forEach(p -> { - SlotRef ref = context.findSlotRef(((NamedExpression) p.child(0)).getExprId()); - context.addExprIdSlotRefPair(p.getExprId(), ref); - }); - List execExprList = project.getProjects() .stream() .map(e -> ExpressionTranslator.translate(e, context)) @@ -464,11 +462,17 @@ public class PhysicalPlanTranslator extends DefaultPlanVisitor slotIdSet = slotRefSet.stream() .map(SlotRef::getSlotId).map(SlotId::asInt).collect(Collectors.toSet()); slotIdSet.addAll(requiredSlotIdList); - execPlan.getTupleIds().stream() + boolean noneMaterialized = execPlan.getTupleIds().stream() .map(context::getTupleDesc) .map(TupleDescriptor::getSlots) .flatMap(List::stream) - .forEach(s -> s.setIsMaterialized(slotIdSet.contains(s.getId().asInt()))); + .peek(s -> s.setIsMaterialized(slotIdSet.contains(s.getId().asInt()))) + .filter(SlotDescriptor::isMaterialized) + .count() == 0; + if (noneMaterialized) { + context.getDescTable() + .getTupleDesc(execPlan.getTupleIds().get(0)).getSlots().get(0).setIsMaterialized(true); + } } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/RewriteJob.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/RewriteJob.java index ed145d1179..a8d59aeb02 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/RewriteJob.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/batch/RewriteJob.java @@ -60,8 +60,9 @@ public class RewriteJob extends BatchRulesJob { .add(topDownBatch(ImmutableList.of(new ReorderJoin()))) .add(topDownBatch(ImmutableList.of(new FindHashConditionForJoin()))) .add(topDownBatch(ImmutableList.of(new PushPredicateThroughJoin()))) - .add(topDownBatch(ImmutableList.of(new AggregateDisassemble()))) + .add(topDownBatch(ImmutableList.of(new NormalizeAggregate()))) .add(topDownBatch(ImmutableList.of(new ColumnPruning()))) + .add(topDownBatch(ImmutableList.of(new AggregateDisassemble()))) .add(topDownBatch(ImmutableList.of(new SwapFilterAndProject()))) .add(bottomUpBatch(ImmutableList.of(new MergeConsecutiveProjects()))) .add(topDownBatch(ImmutableList.of(new MergeConsecutiveFilters()))) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindFunction.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindFunction.java index 9c24d0b1ec..2e45e4c4cb 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindFunction.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindFunction.java @@ -101,7 +101,7 @@ public class BindFunction implements AnalysisRuleFactory { if (arguments.size() > 1 || (arguments.size() == 0 && !unboundFunction.isStar())) { return unboundFunction; } - if (unboundFunction.isStar()) { + if (unboundFunction.isStar() || arguments.stream().allMatch(Expression::isConstant)) { return new Count(); } return new Count(unboundFunction.getArguments().get(0)); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/PruneAggChildColumns.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/PruneAggChildColumns.java index 78951bbf05..0175f909ab 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/PruneAggChildColumns.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/PruneAggChildColumns.java @@ -23,6 +23,9 @@ import org.apache.doris.nereids.rules.rewrite.OneRewriteRuleFactory; 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.GroupPlan; +import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate; import org.apache.doris.nereids.trees.plans.logical.LogicalProject; import org.apache.doris.nereids.util.SlotExtractor; @@ -54,10 +57,18 @@ public class PruneAggChildColumns extends OneRewriteRuleFactory { @Override public Rule build() { return RuleType.COLUMN_PRUNE_AGGREGATION_CHILD.build(logicalAggregate().then(agg -> { + List childOutput = agg.child().getOutput(); + if (isAggregateWithConstant(agg)) { + Slot slot = selectMinimumColumn(childOutput); + if (childOutput.size() == 1 && childOutput.get(0).equals(slot)) { + return agg; + } + return agg.withChildren(ImmutableList.of(new LogicalProject<>(ImmutableList.of(slot), agg.child()))); + } List slots = Lists.newArrayList(); slots.addAll(agg.getExpressions()); Set outputs = SlotExtractor.extractSlot(slots); - List prunedOutputs = agg.child().getOutput().stream().filter(outputs::contains) + List prunedOutputs = childOutput.stream().filter(outputs::contains) .collect(Collectors.toList()); if (prunedOutputs.size() == agg.child().getOutput().size()) { return agg; @@ -65,4 +76,32 @@ public class PruneAggChildColumns extends OneRewriteRuleFactory { return agg.withChildren(ImmutableList.of(new LogicalProject<>(prunedOutputs, agg.child()))); })); } + + /** + * For these aggregate function with constant param. Such as: + * count(*), count(1), sum(1)..etc. + * @return null, if there exists an aggregation function that its parameters contains non-constant expr. + * else return a slot with min data type. + */ + private boolean isAggregateWithConstant(LogicalAggregate agg) { + for (NamedExpression output : agg.getOutputExpressions()) { + if (output.anyMatch(SlotReference.class::isInstance)) { + return false; + } + } + return true; + } + + private Slot selectMinimumColumn(List outputList) { + Slot minSlot = null; + for (Slot slot : outputList) { + if (minSlot == null) { + minSlot = slot; + } else { + int slotDataTypeWidth = slot.getDataType().width(); + minSlot = minSlot.getDataType().width() > slotDataTypeWidth ? slot : minSlot; + } + } + return minSlot; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/PruneFilterChildColumns.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/PruneFilterChildColumns.java index 1721234d0d..391f6f894f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/PruneFilterChildColumns.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/logical/PruneFilterChildColumns.java @@ -44,6 +44,7 @@ import java.util.stream.Stream; * | * scan(k1,k2,k3,v1) * transformed: + *  project(k1) * | * filter(k2 > 3) * | diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/BigIntType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/BigIntType.java index fa1d0ada50..75b55cf5bc 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/BigIntType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/BigIntType.java @@ -24,8 +24,11 @@ import org.apache.doris.nereids.types.coercion.IntegralType; * BigInt data type in Nereids. */ public class BigIntType extends IntegralType { + public static BigIntType INSTANCE = new BigIntType(); + private static final int WIDTH = 8; + private BigIntType() { } @@ -48,4 +51,9 @@ public class BigIntType extends IntegralType { public DataType defaultConcreteType() { return this; } + + @Override + public int width() { + return WIDTH; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/BooleanType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/BooleanType.java index 80670edf7e..7f225b856c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/BooleanType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/BooleanType.java @@ -26,6 +26,8 @@ import org.apache.doris.nereids.types.coercion.PrimitiveType; public class BooleanType extends PrimitiveType { public static BooleanType INSTANCE = new BooleanType(); + private static int WIDTH = 1; + private BooleanType() { } @@ -38,4 +40,9 @@ public class BooleanType extends PrimitiveType { public String simpleString() { return "boolean"; } + + @Override + public int width() { + return WIDTH; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java index 74f26bdd70..1b1060f0af 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DataType.java @@ -227,4 +227,6 @@ public abstract class DataType implements AbstractDataType { return this; } } + + public abstract int width(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeType.java index b7ae478dda..2731a3cc49 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateTimeType.java @@ -27,6 +27,8 @@ public class DateTimeType extends PrimitiveType { public static DateTimeType INSTANCE = new DateTimeType(); + private static final int WIDTH = 16; + private DateTimeType() { } @@ -39,4 +41,9 @@ public class DateTimeType extends PrimitiveType { public boolean equals(Object o) { return o instanceof DateTimeType; } + + @Override + public int width() { + return WIDTH; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateType.java index 9de50bf1cf..76daccb62c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DateType.java @@ -27,6 +27,8 @@ public class DateType extends PrimitiveType { public static DateType INSTANCE = new DateType(); + private static final int WIDTH = 16; + private DateType() { } @@ -34,5 +36,10 @@ public class DateType extends PrimitiveType { public Type toCatalogDataType() { return Type.DATE; } + + @Override + public int width() { + return WIDTH; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DecimalType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DecimalType.java index 29c93083de..3c583df3eb 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DecimalType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DecimalType.java @@ -46,6 +46,8 @@ public class DecimalType extends FractionalType { private static final DecimalType FLOAT_DECIMAL = new DecimalType(14, 7); private static final DecimalType DOUBLE_DECIMAL = new DecimalType(30, 15); + private static final int WIDTH = 16; + private static final Map FOR_TYPE_MAP = ImmutableMap.builder() .put(TinyIntType.INSTANCE, TINYINT_DECIMAL) .put(SmallIntType.INSTANCE, SMALLINT_DECIMAL) @@ -160,5 +162,11 @@ public class DecimalType extends FractionalType { public int hashCode() { return Objects.hash(super.hashCode(), precision, scale); } + + @Override + public int width() { + return WIDTH; + } + } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DoubleType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DoubleType.java index 1bf28dc35c..1e754cb6ea 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DoubleType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/DoubleType.java @@ -26,6 +26,8 @@ import org.apache.doris.nereids.types.coercion.FractionalType; public class DoubleType extends FractionalType { public static DoubleType INSTANCE = new DoubleType(); + private static final int WIDTH = 8; + private DoubleType() { } @@ -53,4 +55,9 @@ public class DoubleType extends FractionalType { public DataType defaultConcreteType() { return this; } + + @Override + public int width() { + return WIDTH; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/FloatType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/FloatType.java index 77836cc6a2..3a8a03e0e9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/FloatType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/FloatType.java @@ -26,6 +26,8 @@ import org.apache.doris.nereids.types.coercion.FractionalType; public class FloatType extends FractionalType { public static FloatType INSTANCE = new FloatType(); + private static final int WIDTH = 4; + private FloatType() { } @@ -53,4 +55,9 @@ public class FloatType extends FractionalType { public String simpleString() { return "float"; } + + @Override + public int width() { + return WIDTH; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/IntegerType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/IntegerType.java index 1c354f9f39..3aad2cf8dd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/IntegerType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/IntegerType.java @@ -26,6 +26,8 @@ import org.apache.doris.nereids.types.coercion.IntegralType; public class IntegerType extends IntegralType { public static IntegerType INSTANCE = new IntegerType(); + private static final int WIDTH = 4; + private IntegerType() { } @@ -53,4 +55,9 @@ public class IntegerType extends IntegralType { public DataType defaultConcreteType() { return this; } + + @Override + public int width() { + return WIDTH; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/LargeIntType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/LargeIntType.java index b835b4788b..d380d92492 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/LargeIntType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/LargeIntType.java @@ -26,6 +26,8 @@ import org.apache.doris.nereids.types.coercion.IntegralType; public class LargeIntType extends IntegralType { public static LargeIntType INSTANCE = new LargeIntType(); + private static final int WIDTH = 16; + private LargeIntType() { } @@ -53,4 +55,9 @@ public class LargeIntType extends IntegralType { public DataType defaultConcreteType() { return this; } + + @Override + public int width() { + return WIDTH; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/NullType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/NullType.java index 5015b5e250..a3d278456a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/NullType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/NullType.java @@ -26,6 +26,8 @@ import org.apache.doris.nereids.types.coercion.PrimitiveType; public class NullType extends PrimitiveType { public static NullType INSTANCE = new NullType(); + private static final int WIDTH = 1; + private NullType() { } @@ -33,4 +35,9 @@ public class NullType extends PrimitiveType { public Type toCatalogDataType() { return Type.NULL; } + + @Override + public int width() { + return WIDTH; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/SmallIntType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/SmallIntType.java index a4dea4c247..a14e5d8640 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/SmallIntType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/SmallIntType.java @@ -26,6 +26,8 @@ import org.apache.doris.nereids.types.coercion.IntegralType; public class SmallIntType extends IntegralType { public static SmallIntType INSTANCE = new SmallIntType(); + private static final int WIDTH = 2; + private SmallIntType() { } @@ -53,4 +55,9 @@ public class SmallIntType extends IntegralType { public DataType defaultConcreteType() { return this; } + + @Override + public int width() { + return WIDTH; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/TinyIntType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/TinyIntType.java index 7632b61ed7..e0bbfe9cb3 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/TinyIntType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/TinyIntType.java @@ -26,6 +26,8 @@ import org.apache.doris.nereids.types.coercion.IntegralType; public class TinyIntType extends IntegralType { public static TinyIntType INSTANCE = new TinyIntType(); + private static final int WIDTH = 1; + private TinyIntType() { } @@ -53,4 +55,9 @@ public class TinyIntType extends IntegralType { public DataType defaultConcreteType() { return this; } + + @Override + public int width() { + return WIDTH; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/coercion/CharacterType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/coercion/CharacterType.java index 361c30c158..95cc67249d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/coercion/CharacterType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/coercion/CharacterType.java @@ -28,6 +28,8 @@ public class CharacterType extends PrimitiveType { public static final CharacterType INSTANCE = new CharacterType(-1); + private static final int WIDTH = 16; + protected final int len; public CharacterType(int len) { @@ -52,4 +54,9 @@ public class CharacterType extends PrimitiveType { public DataType defaultConcreteType() { return StringType.INSTANCE; } + + @Override + public int width() { + return WIDTH; + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/coercion/FractionalType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/coercion/FractionalType.java index 6ba9e89d4b..bb3a30e228 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/coercion/FractionalType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/coercion/FractionalType.java @@ -40,4 +40,9 @@ public class FractionalType extends NumericType { public String simpleString() { return "fractional"; } + + @Override + public int width() { + throw new RuntimeException("Unimplemented exception"); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/coercion/PrimitiveType.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/coercion/PrimitiveType.java index 6ced44bf6b..938dab267c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/coercion/PrimitiveType.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/coercion/PrimitiveType.java @@ -29,4 +29,9 @@ public abstract class PrimitiveType extends DataType { public String toSql() { return simpleString().toUpperCase(Locale.ROOT); } + + @Override + public int width() { + throw new RuntimeException("Unimplemented exception"); + } } diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/logical/ColumnPruningTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/logical/ColumnPruningTest.java index eb7777b368..c26fa86462 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/logical/ColumnPruningTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/logical/ColumnPruningTest.java @@ -20,6 +20,8 @@ package org.apache.doris.nereids.rules.rewrite.logical; import org.apache.doris.nereids.trees.expressions.NamedExpression; import org.apache.doris.nereids.trees.plans.Plan; import org.apache.doris.nereids.trees.plans.logical.LogicalProject; +import org.apache.doris.nereids.types.DoubleType; +import org.apache.doris.nereids.types.IntegerType; import org.apache.doris.nereids.util.PatternMatchSupported; import org.apache.doris.nereids.util.PlanChecker; import org.apache.doris.utframe.TestWithFeService; @@ -177,6 +179,96 @@ public class ColumnPruningTest extends TestWithFeService implements PatternMatch ); } + @Test + public void pruneCountStarStmt() { + PlanChecker.from(connectContext) + .analyze("SELECT COUNT(*) FROM test.course") + .applyTopDown(new ColumnPruning()) + .matchesFromRoot( + logicalAggregate( + logicalProject( + logicalOlapScan() + ).when(p -> p.getProjects().get(0).getDataType().equals(IntegerType.INSTANCE) + && p.getProjects().size() == 1) + ) + ); + } + + @Test + public void pruneCountConstantStmt() { + PlanChecker.from(connectContext) + .analyze("SELECT COUNT(1) FROM test.course") + .applyTopDown(new ColumnPruning()) + .matchesFromRoot( + logicalAggregate( + logicalProject( + logicalOlapScan() + ).when(p -> p.getProjects().get(0).getDataType().equals(IntegerType.INSTANCE) + && p.getProjects().size() == 1) + ) + ); + } + + @Test + public void pruneCountConstantAndSumConstantStmt() { + PlanChecker.from(connectContext) + .analyze("SELECT COUNT(1), SUM(2) FROM test.course") + .applyTopDown(new ColumnPruning()) + .matchesFromRoot( + logicalAggregate( + logicalProject( + logicalOlapScan() + ).when(p -> p.getProjects().get(0).getDataType().equals(IntegerType.INSTANCE) + && p.getProjects().size() == 1) + ) + ); + } + + @Test + public void pruneCountStarAndSumConstantStmt() { + PlanChecker.from(connectContext) + .analyze("SELECT COUNT(*), SUM(2) FROM test.course") + .applyTopDown(new ColumnPruning()) + .matchesFromRoot( + logicalAggregate( + logicalProject( + logicalOlapScan() + ).when(p -> p.getProjects().get(0).getDataType().equals(IntegerType.INSTANCE) + && p.getProjects().size() == 1) + ) + ); + } + + @Test + public void pruneCountStarAndSumColumnStmt() { + PlanChecker.from(connectContext) + .analyze("SELECT COUNT(*), SUM(grade) FROM test.score") + .applyTopDown(new ColumnPruning()) + .matchesFromRoot( + logicalAggregate( + logicalProject( + logicalOlapScan() + ).when(p -> p.getProjects().get(0).getDataType().equals(DoubleType.INSTANCE) + && p.getProjects().size() == 1) + ) + ); + } + + @Test + public void pruneCountStarAndSumColumnAndSumConstantStmt() { + PlanChecker.from(connectContext) + .analyze("SELECT COUNT(*), SUM(grade) + SUM(2) FROM test.score") + .applyTopDown(new ColumnPruning()) + .matchesFromRoot( + logicalAggregate( + logicalProject( + logicalOlapScan() + ).when(p -> p.getProjects().get(0).getDataType().equals(DoubleType.INSTANCE) + && p.getProjects().size() == 1) + ) + ); + } + private List getOutputQualifiedNames(LogicalProject p) { return p.getProjects().stream().map(NamedExpression::getQualifiedName).collect(Collectors.toList()); } diff --git a/regression-test/data/nereids_syntax_p0/agg_with_const.out b/regression-test/data/nereids_syntax_p0/agg_with_const.out new file mode 100644 index 0000000000..3dc5fdcfd6 --- /dev/null +++ b/regression-test/data/nereids_syntax_p0/agg_with_const.out @@ -0,0 +1,10 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !select -- +2 1996 + +-- !select -- +1 + +-- !select -- +2 4 + diff --git a/regression-test/suites/nereids_syntax_p0/agg_with_const.groovy b/regression-test/suites/nereids_syntax_p0/agg_with_const.groovy new file mode 100644 index 0000000000..ed2e5b60f1 --- /dev/null +++ b/regression-test/suites/nereids_syntax_p0/agg_with_const.groovy @@ -0,0 +1,48 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +suite("agg_with_const") { + + sql """ + DROP TABLE IF EXISTS t1 + """ + + sql """CREATE TABLE t1 (col1 int not null, col2 int not null, col3 int not null) + DISTRIBUTED BY HASH(col3) + BUCKETS 1 + PROPERTIES( + "replication_num"="1" + ) + """ + + sql """ + insert into t1 values(1994, 1994, 1995) + """ + + qt_select """ + select count(2) + 1, sum(2) + sum(col1) from t1 + """ + + qt_select """ + select count(*) from t1 + """ + + qt_select """ + select count(2) + 1, sum(2) + sum(2) from t1 + """ + +} \ No newline at end of file