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 3be9fbe1590 Guard against NPE for MSE filtered aggregations (#17386)
3be9fbe1590 is described below
commit 3be9fbe159060e504f0258a57b1e49c7b7b6e65e
Author: Yash Mayya <[email protected]>
AuthorDate: Wed Dec 17 02:55:38 2025 -0800
Guard against NPE for MSE filtered aggregations (#17386)
* Guard against NPE for MSE filtered aggregations
* Add unit test
---
.../query/runtime/operator/AggregateOperator.java | 4 +++-
.../runtime/operator/AggregateOperatorTest.java | 28 ++++++++++++++++++++++
2 files changed, 31 insertions(+), 1 deletion(-)
diff --git
a/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/AggregateOperator.java
b/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/AggregateOperator.java
index e0268362766..dfc1cc3600a 100644
---
a/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/AggregateOperator.java
+++
b/pinot-query-runtime/src/main/java/org/apache/pinot/query/runtime/operator/AggregateOperator.java
@@ -351,7 +351,9 @@ public class AggregateOperator extends MultiStageOperator {
List<Object[]> rows = block.asRowHeap().getRows();
int numRows = rows.size();
for (int rowId = 0; rowId < numRows; rowId++) {
- if ((int) rows.get(rowId)[filterArgId] == 1) {
+ // Treat NULL filter values as non-matching (SQL WHERE clause
semantics).
+ Object filterValue = rows.get(rowId)[filterArgId];
+ if (filterValue != null && (int) filterValue == 1) {
matchedBitmap.add(rowId);
}
}
diff --git
a/pinot-query-runtime/src/test/java/org/apache/pinot/query/runtime/operator/AggregateOperatorTest.java
b/pinot-query-runtime/src/test/java/org/apache/pinot/query/runtime/operator/AggregateOperatorTest.java
index 4e12c3d20f2..c96805a1a15 100644
---
a/pinot-query-runtime/src/test/java/org/apache/pinot/query/runtime/operator/AggregateOperatorTest.java
+++
b/pinot-query-runtime/src/test/java/org/apache/pinot/query/runtime/operator/AggregateOperatorTest.java
@@ -185,6 +185,34 @@ public class AggregateOperatorTest {
assertTrue(operator.nextBlock().isSuccess(), "Second block is EOS (done
processing)");
}
+ @Test
+ public void testFilteredAggregateWithNullValues() {
+ // Given:
+ List<RexExpression.FunctionCall> aggCalls =
+ List.of(getSum(new RexExpression.InputRef(1)), getSum(new
RexExpression.InputRef(1)));
+ List<Integer> filterArgs = List.of(-1, 2);
+ List<Integer> groupKeys = List.of(0);
+ DataSchema inSchema =
+ new DataSchema(new String[]{"group", "arg", "filterArg"}, new
ColumnDataType[]{INT, DOUBLE, BOOLEAN});
+ // null for the filterArg should be treated as false
+ when(_input.nextBlock()).thenReturn(
+ OperatorTestUtil.block(inSchema, new Object[]{2, 1.0, null}, new
Object[]{2, 2.0, 1}))
+ .thenReturn(OperatorTestUtil.block(inSchema, new Object[]{2, 3.0, 1}))
+ .thenReturn(SuccessMseBlock.INSTANCE);
+ DataSchema resultSchema =
+ new DataSchema(new String[]{"group", "sum", "sumWithFilter"}, new
ColumnDataType[]{INT, DOUBLE, DOUBLE});
+ AggregateOperator operator = getOperator(resultSchema, aggCalls,
filterArgs, groupKeys);
+
+ // When:
+ List<Object[]> resultRows = ((MseBlock.Data)
operator.nextBlock()).asRowHeap().getRows();
+
+ // Then:
+ assertEquals(resultRows.size(), 1);
+ assertEquals(resultRows.get(0), new Object[]{2, 6.0, 5.0},
+ "Expected three columns (group by key, agg value, agg value with
filter), agg value is final result");
+ assertTrue(operator.nextBlock().isSuccess(), "Second block is EOS (done
processing)");
+ }
+
@Test
public void testGroupByAggregateWithHashCollision() {
_input = OperatorTestUtil.getOperator(OperatorTestUtil.OP_1);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]