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

singhpk234 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg.git


The following commit(s) were added to refs/heads/main by this push:
     new be03c998d9 Core: Use safeContainsKey to avoid NPE for CountNonNull 
(#13980)
be03c998d9 is described below

commit be03c998d96d0d1fae13aa8c53d6c7c87e2d60ba
Author: jackylee <qcsd2...@gmail.com>
AuthorDate: Thu Sep 4 08:50:03 2025 +0800

    Core: Use safeContainsKey to avoid NPE for CountNonNull (#13980)
---
 .../apache/iceberg/expressions/CountNonNull.java   |  2 +-
 .../expressions/TestAggregateEvaluator.java        | 34 ++++++++++++++++++++++
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/api/src/main/java/org/apache/iceberg/expressions/CountNonNull.java 
b/api/src/main/java/org/apache/iceberg/expressions/CountNonNull.java
index ecc83c9ef6..2b8708b10b 100644
--- a/api/src/main/java/org/apache/iceberg/expressions/CountNonNull.java
+++ b/api/src/main/java/org/apache/iceberg/expressions/CountNonNull.java
@@ -40,7 +40,7 @@ public class CountNonNull<T> extends CountAggregate<T> {
   @Override
   protected boolean hasValue(DataFile file) {
     return safeContainsKey(file.valueCounts(), fieldId)
-        && file.nullValueCounts().containsKey(fieldId);
+        && safeContainsKey(file.nullValueCounts(), fieldId);
   }
 
   @Override
diff --git 
a/api/src/test/java/org/apache/iceberg/expressions/TestAggregateEvaluator.java 
b/api/src/test/java/org/apache/iceberg/expressions/TestAggregateEvaluator.java
index aa15d36de3..384836ec30 100644
--- 
a/api/src/test/java/org/apache/iceberg/expressions/TestAggregateEvaluator.java
+++ 
b/api/src/test/java/org/apache/iceberg/expressions/TestAggregateEvaluator.java
@@ -91,6 +91,22 @@ public class TestAggregateEvaluator {
           // upper bounds
           ImmutableMap.of(1, toByteBuffer(IntegerType.get(), 3333)));
 
+  private static final DataFile MISSING_SOME_STATS =
+      new TestDataFile(
+          "file_missing_stats.avro",
+          Row.of(),
+          20,
+          // any value counts, including nulls
+          ImmutableMap.of(1, 20L, 4, 10L),
+          // null value counts
+          null,
+          // nan value counts
+          null,
+          // lower bounds
+          ImmutableMap.of(1, toByteBuffer(IntegerType.get(), -3)),
+          // upper bounds
+          ImmutableMap.of(1, toByteBuffer(IntegerType.get(), 1333)));
+
   private static final DataFile[] DATA_FILES = {
     FILE, MISSING_SOME_NULLS_STATS_1, MISSING_SOME_NULLS_STATS_2
   };
@@ -225,6 +241,24 @@ public class TestAggregateEvaluator {
     assertEvaluatorResult(result, expected);
   }
 
+  @Test
+  public void testMissingSomeStats() {
+    List<Expression> list =
+        ImmutableList.of(
+            Expressions.countStar(),
+            Expressions.count("some_nulls"),
+            Expressions.max("some_nulls"),
+            Expressions.min("some_nulls"));
+    AggregateEvaluator aggregateEvaluator = AggregateEvaluator.create(SCHEMA, 
list);
+
+    aggregateEvaluator.update(MISSING_SOME_STATS);
+
+    assertThat(aggregateEvaluator.allAggregatorsValid()).isFalse();
+    StructLike result = aggregateEvaluator.result();
+    Object[] expected = {20L, null, null, null};
+    assertEvaluatorResult(result, expected);
+  }
+
   private void assertEvaluatorResult(StructLike result, Object[] expected) {
     Object[] actual = new Object[result.size()];
     for (int i = 0; i < result.size(); i++) {

Reply via email to