This is an automated email from the ASF dual-hosted git repository.

gortiz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new 4588d0b15d Modify AggregationPlanNode to consider not nullable columns 
that do not contain nulls (#14342)
4588d0b15d is described below

commit 4588d0b15db53553f25615d9ec2d552173143b8a
Author: Gonzalo Ortiz Jaureguizar <gor...@users.noreply.github.com>
AuthorDate: Fri Nov 8 15:39:18 2024 +0100

    Modify AggregationPlanNode to consider not nullable columns that do not 
contain nulls (#14342)
---
 .../pinot/core/plan/AggregationPlanNode.java       | 40 ++++++++++++++++++++--
 1 file changed, 37 insertions(+), 3 deletions(-)

diff --git 
a/pinot-core/src/main/java/org/apache/pinot/core/plan/AggregationPlanNode.java 
b/pinot-core/src/main/java/org/apache/pinot/core/plan/AggregationPlanNode.java
index 2a1321f1b9..6202f0890d 100644
--- 
a/pinot-core/src/main/java/org/apache/pinot/core/plan/AggregationPlanNode.java
+++ 
b/pinot-core/src/main/java/org/apache/pinot/core/plan/AggregationPlanNode.java
@@ -36,6 +36,7 @@ import org.apache.pinot.segment.spi.AggregationFunctionType;
 import org.apache.pinot.segment.spi.IndexSegment;
 import org.apache.pinot.segment.spi.SegmentContext;
 import org.apache.pinot.segment.spi.datasource.DataSource;
+import org.apache.pinot.segment.spi.index.reader.NullValueVectorReader;
 
 import static org.apache.pinot.segment.spi.AggregationFunctionType.*;
 
@@ -94,7 +95,8 @@ public class AggregationPlanNode implements PlanNode {
     FilterPlanNode filterPlanNode = new FilterPlanNode(_segmentContext, 
_queryContext);
     BaseFilterOperator filterOperator = filterPlanNode.run();
 
-    if (!_queryContext.isNullHandlingEnabled()) {
+    boolean hasNullValues = _queryContext.isNullHandlingEnabled() && 
hasNullValues(aggregationFunctions);
+    if (!hasNullValues) {
       if (canOptimizeFilteredCount(filterOperator, aggregationFunctions)) {
         return new FastFilteredCountOperator(_queryContext, filterOperator, 
_indexSegment.getSegmentMetadata());
       }
@@ -118,17 +120,49 @@ public class AggregationPlanNode implements PlanNode {
     return new AggregationOperator(_queryContext, aggregationInfo, 
numTotalDocs);
   }
 
+  /**
+   * Returns {@code true} if any of the aggregation functions have null 
values, {@code false} otherwise.
+   *
+   * The current implementation is pessimistic and returns {@code true} if any 
of the arguments to the aggregation
+   * functions is of function type. This is because we do not have a way to 
determine if the function will return null
+   * values without actually evaluating it.
+   */
+  private boolean hasNullValues(AggregationFunction[] aggregationFunctions) {
+    for (AggregationFunction<?, ?> aggregationFunction : aggregationFunctions) 
{
+      for (ExpressionContext argument : 
aggregationFunction.getInputExpressions()) {
+        switch (argument.getType()) {
+          case IDENTIFIER:
+            DataSource dataSource = 
_indexSegment.getDataSource(argument.getIdentifier());
+            NullValueVectorReader nullValueVector = 
dataSource.getNullValueVector();
+            if (nullValueVector != null && 
!nullValueVector.getNullBitmap().isEmpty()) {
+              return true;
+            }
+            break;
+          case LITERAL:
+            if (argument.getLiteral().isNull()) {
+              return true;
+            }
+            break;
+          case FUNCTION:
+          default:
+            return true;
+        }
+      }
+    }
+    return false;
+  }
+
   /**
    * Returns {@code true} if the given aggregations can be solved with 
dictionary or column metadata, {@code false}
    * otherwise.
    */
   private static boolean isFitForNonScanBasedPlan(AggregationFunction[] 
aggregationFunctions,
       IndexSegment indexSegment) {
-    for (AggregationFunction aggregationFunction : aggregationFunctions) {
+    for (AggregationFunction<?, ?> aggregationFunction : aggregationFunctions) 
{
       if (aggregationFunction.getType() == COUNT) {
         continue;
       }
-      ExpressionContext argument = (ExpressionContext) 
aggregationFunction.getInputExpressions().get(0);
+      ExpressionContext argument = 
aggregationFunction.getInputExpressions().get(0);
       if (argument.getType() != ExpressionContext.Type.IDENTIFIER) {
         return false;
       }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@pinot.apache.org
For additional commands, e-mail: commits-h...@pinot.apache.org

Reply via email to