diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/process/FilterAndProjectOperator.java b/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/process/FilterAndProjectOperator.java index 0b6bf595fc2813751516442e99069e61c03c69f5..60dc07b2f2ab88e8abab7b15dd280c644cf64f09 100644 --- a/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/process/FilterAndProjectOperator.java +++ b/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/process/FilterAndProjectOperator.java @@ -56,6 +56,9 @@ public class FilterAndProjectOperator implements ProcessOperator { private final OperatorContext operatorContext; + // false when we only need to do projection + private final boolean hasFilter; + public FilterAndProjectOperator( OperatorContext operatorContext, Operator inputOperator, @@ -65,7 +68,8 @@ public class FilterAndProjectOperator implements ProcessOperator { List commonTransformerList, List projectLeafColumnTransformerList, List projectOutputTransformerList, - boolean hasNonMappableUDF) { + boolean hasNonMappableUDF, + boolean hasFilter) { this.operatorContext = operatorContext; this.inputOperator = inputOperator; this.filterLeafColumnTransformerList = filterLeafColumnTransformerList; @@ -75,6 +79,7 @@ public class FilterAndProjectOperator implements ProcessOperator { this.projectOutputTransformerList = projectOutputTransformerList; this.hasNonMappableUDF = hasNonMappableUDF; this.filterTsBlockBuilder = new TsBlockBuilder(8, filterOutputDataTypes); + this.hasFilter = hasFilter; } @Override @@ -89,6 +94,10 @@ public class FilterAndProjectOperator implements ProcessOperator { return null; } + if (!hasFilter) { + return getTransformedTsBlock(input); + } + TsBlock filterResult = getFilterTsBlock(input); // contains non-mappable udf, we leave calculation for TransformOperator diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/FunctionExpression.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/FunctionExpression.java index 049381ede720aa1ce89413e794d79f47523f04bb..2371300cff7c17a8df8692cda6df24588cf9a3f2 100644 --- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/FunctionExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/expression/multi/FunctionExpression.java @@ -431,6 +431,9 @@ public class FunctionExpression extends Expression { @Override public boolean isMappable(TypeProvider typeProvider) { + if (isBuiltInAggregationFunctionExpression) { + return false; + } return new UDTFInformationInferrer(functionName) .getAccessStrategy( expressions.stream().map(Expression::toString).collect(Collectors.toList()), diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/OperatorTreeGenerator.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/OperatorTreeGenerator.java index c67c3bfd6ddca6aa54e8b222a9ca4c5ac819306d..5c4570a1fefb35570d1bbe00e29967521d04682d 100644 --- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/OperatorTreeGenerator.java +++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/OperatorTreeGenerator.java @@ -796,9 +796,62 @@ public class OperatorTreeGenerator extends PlanVisitor inputDataTypes = getInputColumnTypes(node, context.getTypeProvider()); final Map> inputLocations = makeLayout(node); + final Expression[] projectExpressions = node.getOutputExpressions(); + final TypeProvider typeProvider = context.getTypeProvider(); context.getTimeSliceAllocator().recordExecutionWeight(operatorContext, 1); + boolean hasNonMappableUDF = false; + for (Expression expression : projectExpressions) { + if (!expression.isMappable(typeProvider)) { + hasNonMappableUDF = true; + break; + } + } + + // Use FilterAndProject Operator when project expressions are all mappable + if (!hasNonMappableUDF) { + // init project UDTFContext + UDTFContext projectContext = new UDTFContext(node.getZoneId()); + projectContext.constructUdfExecutors(projectExpressions); + + List projectOutputTransformerList = new ArrayList<>(); + Map projectExpressionColumnTransformerMap = new HashMap<>(); + + // records LeafColumnTransformer of project expressions + List projectLeafColumnTransformerList = new ArrayList<>(); + + ColumnTransformerVisitor visitor = new ColumnTransformerVisitor(); + ColumnTransformerVisitor.ColumnTransformerVisitorContext projectColumnTransformerContext = + new ColumnTransformerVisitor.ColumnTransformerVisitorContext( + projectContext, + typeProvider, + projectLeafColumnTransformerList, + inputLocations, + projectExpressionColumnTransformerMap, + ImmutableMap.of(), + ImmutableList.of(), + inputDataTypes, + inputLocations.size()); + + for (Expression expression : projectExpressions) { + projectOutputTransformerList.add( + visitor.process(expression, projectColumnTransformerContext)); + } + + return new FilterAndProjectOperator( + operatorContext, + inputOperator, + inputDataTypes, + ImmutableList.of(), + null, + ImmutableList.of(), + projectLeafColumnTransformerList, + projectOutputTransformerList, + false, + false); + } + try { return new TransformOperator( operatorContext, @@ -918,7 +971,8 @@ public class OperatorTreeGenerator extends PlanVisitor