diff --git a/paimon-common/src/main/java/org/apache/paimon/predicate/LeafPredicate.java b/paimon-common/src/main/java/org/apache/paimon/predicate/LeafPredicate.java index 85a04855391e..913c76f7414b 100644 --- a/paimon-common/src/main/java/org/apache/paimon/predicate/LeafPredicate.java +++ b/paimon-common/src/main/java/org/apache/paimon/predicate/LeafPredicate.java @@ -157,8 +157,12 @@ public boolean test( Object min = get(minValues, index, type); Object max = get(maxValues, index, type); - Long nullCount = nullCounts.isNullAt(index) ? null : nullCounts.getLong(index); + Long nullCount = + nullCounts.size() == 0 || nullCounts.isNullAt(index) + ? null + : nullCounts.getLong(index); if (nullCount == null || rowCount != nullCount) { + // missing null counts // not all null // min or max is null // unknown stats diff --git a/paimon-common/src/test/java/org/apache/paimon/predicate/LeafPredicateTest.java b/paimon-common/src/test/java/org/apache/paimon/predicate/LeafPredicateTest.java index a179753b0faf..594e33ba79ed 100644 --- a/paimon-common/src/test/java/org/apache/paimon/predicate/LeafPredicateTest.java +++ b/paimon-common/src/test/java/org/apache/paimon/predicate/LeafPredicateTest.java @@ -18,9 +18,12 @@ package org.apache.paimon.predicate; +import org.apache.paimon.data.BinaryArray; +import org.apache.paimon.data.BinaryRow; import org.apache.paimon.data.BinaryString; import org.apache.paimon.data.GenericArray; import org.apache.paimon.data.GenericRow; +import org.apache.paimon.data.serializer.InternalRowSerializer; import org.apache.paimon.types.DataTypes; import org.apache.paimon.types.RowType; import org.apache.paimon.utils.InstantiationUtil; @@ -123,6 +126,31 @@ public void testArraySetPredicateSerializationUsesElementSerializer() assertThat(InstantiationUtil.clone(containsAll).test(row)).isTrue(); } + @Test + public void testEmptyNullCountsWithCompleteBounds() { + RowType type = RowType.of(DataTypes.STRING(), DataTypes.STRING()); + PredicateBuilder builder = new PredicateBuilder(type); + InternalRowSerializer serializer = new InternalRowSerializer(type); + BinaryRow bounds = + serializer + .toBinaryRow( + GenericRow.of( + BinaryString.fromString("sample"), + BinaryString.fromString("1"))) + .copy(); + BinaryArray nullCounts = BinaryArray.fromLongArray(new Long[0]); + Predicate first = builder.equal(0, BinaryString.fromString("other")); + Predicate second = builder.equal(1, BinaryString.fromString("1")); + + assertThat(first.test(1, bounds, bounds, nullCounts)).isFalse(); + assertThat(second.test(1, bounds, bounds, nullCounts)).isTrue(); + assertThat(builder.isNull(0).test(1, bounds, bounds, nullCounts)).isTrue(); + assertThat(builder.isNotNull(1).test(1, bounds, bounds, nullCounts)).isTrue(); + assertThat(PredicateBuilder.and(first, second).test(1, bounds, bounds, nullCounts)) + .isFalse(); + assertThat(PredicateBuilder.or(first, second).test(1, bounds, bounds, nullCounts)).isTrue(); + } + private LeafPredicate create() { List inputs = new ArrayList<>(); inputs.add(new FieldRef(0, "f0", DataTypes.STRING()));