This is an automated email from the ASF dual-hosted git repository.
lzljs3620320 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git
The following commit(s) were added to refs/heads/master by this push:
new e1eeec5695 [core] Introduce NullTransform for AlwaysTrue and
AlwaysFalse
e1eeec5695 is described below
commit e1eeec56954c19ed78fd0bd4a46e0a332443397d
Author: JingsongLi <[email protected]>
AuthorDate: Thu Feb 26 11:34:24 2026 +0800
[core] Introduce NullTransform for AlwaysTrue and AlwaysFalse
---
.../{FalseFunction.java => AlwaysFalse.java} | 10 ++---
.../{TrueFunction.java => AlwaysTrue.java} | 10 ++---
.../org/apache/paimon/predicate/LeafFunction.java | 4 +-
.../org/apache/paimon/predicate/LeafPredicate.java | 23 +---------
.../{TrueTransform.java => NullTransform.java} | 12 +++---
.../apache/paimon/predicate/PredicateBuilder.java | 9 ++++
.../org/apache/paimon/predicate/Transform.java | 2 +-
.../apache/paimon/predicate/LeafPredicateTest.java | 50 +++++++++-------------
.../paimon/predicate/PredicateJsonSerdeTest.java | 20 +++------
.../paimon/spark/SparkV2FilterConverter.scala | 12 ++----
.../spark/sql/SparkV2FilterConverterTestBase.scala | 14 ++----
11 files changed, 63 insertions(+), 103 deletions(-)
diff --git
a/paimon-common/src/main/java/org/apache/paimon/predicate/FalseFunction.java
b/paimon-common/src/main/java/org/apache/paimon/predicate/AlwaysFalse.java
similarity index 87%
rename from
paimon-common/src/main/java/org/apache/paimon/predicate/FalseFunction.java
rename to
paimon-common/src/main/java/org/apache/paimon/predicate/AlwaysFalse.java
index 36b9300961..71e1d26a80 100644
--- a/paimon-common/src/main/java/org/apache/paimon/predicate/FalseFunction.java
+++ b/paimon-common/src/main/java/org/apache/paimon/predicate/AlwaysFalse.java
@@ -26,16 +26,16 @@ import java.util.List;
import java.util.Optional;
/** A {@link LeafFunction} that always returns {@code false}. Used for
AlwaysFalse predicates. */
-public class FalseFunction extends LeafFunction {
+public class AlwaysFalse extends LeafFunction {
private static final long serialVersionUID = 1L;
public static final String NAME = "FALSE";
- public static final FalseFunction INSTANCE = new FalseFunction();
+ public static final AlwaysFalse INSTANCE = new AlwaysFalse();
@JsonCreator
- private FalseFunction() {}
+ private AlwaysFalse() {}
@Override
public boolean test(DataType type, Object field, List<Object> literals) {
@@ -55,13 +55,13 @@ public class FalseFunction extends LeafFunction {
@Override
public Optional<LeafFunction> negate() {
- return Optional.of(TrueFunction.INSTANCE);
+ return Optional.of(AlwaysTrue.INSTANCE);
}
@Override
public <T> T visit(FunctionVisitor<T> visitor, FieldRef fieldRef,
List<Object> literals) {
throw new UnsupportedOperationException(
- "FalseFunction does not support field-based visitation.");
+ "AlwaysFalse does not support field-based visitation.");
}
@Override
diff --git
a/paimon-common/src/main/java/org/apache/paimon/predicate/TrueFunction.java
b/paimon-common/src/main/java/org/apache/paimon/predicate/AlwaysTrue.java
similarity index 87%
rename from
paimon-common/src/main/java/org/apache/paimon/predicate/TrueFunction.java
rename to
paimon-common/src/main/java/org/apache/paimon/predicate/AlwaysTrue.java
index 6ca9d057f0..398e8a341b 100644
--- a/paimon-common/src/main/java/org/apache/paimon/predicate/TrueFunction.java
+++ b/paimon-common/src/main/java/org/apache/paimon/predicate/AlwaysTrue.java
@@ -26,16 +26,16 @@ import java.util.List;
import java.util.Optional;
/** A {@link LeafFunction} that always returns {@code true}. Used for
AlwaysTrue predicates. */
-public class TrueFunction extends LeafFunction {
+public class AlwaysTrue extends LeafFunction {
private static final long serialVersionUID = 1L;
public static final String NAME = "TRUE";
- public static final TrueFunction INSTANCE = new TrueFunction();
+ public static final AlwaysTrue INSTANCE = new AlwaysTrue();
@JsonCreator
- private TrueFunction() {}
+ private AlwaysTrue() {}
@Override
public boolean test(DataType type, Object field, List<Object> literals) {
@@ -55,13 +55,13 @@ public class TrueFunction extends LeafFunction {
@Override
public Optional<LeafFunction> negate() {
- return Optional.of(FalseFunction.INSTANCE);
+ return Optional.of(AlwaysFalse.INSTANCE);
}
@Override
public <T> T visit(FunctionVisitor<T> visitor, FieldRef fieldRef,
List<Object> literals) {
throw new UnsupportedOperationException(
- "TrueFunction does not support field-based visitation.");
+ "AlwaysTrue does not support field-based visitation.");
}
@Override
diff --git
a/paimon-common/src/main/java/org/apache/paimon/predicate/LeafFunction.java
b/paimon-common/src/main/java/org/apache/paimon/predicate/LeafFunction.java
index 0f45e8e920..9ed1ba4338 100644
--- a/paimon-common/src/main/java/org/apache/paimon/predicate/LeafFunction.java
+++ b/paimon-common/src/main/java/org/apache/paimon/predicate/LeafFunction.java
@@ -68,8 +68,8 @@ public abstract class LeafFunction implements Serializable {
registry.put(NotIn.NAME, NotIn.INSTANCE);
registry.put(Between.NAME, Between.INSTANCE);
registry.put(NotBetween.NAME, NotBetween.INSTANCE);
- registry.put(TrueFunction.NAME, TrueFunction.INSTANCE);
- registry.put(FalseFunction.NAME, FalseFunction.INSTANCE);
+ registry.put(AlwaysTrue.NAME, AlwaysTrue.INSTANCE);
+ registry.put(AlwaysFalse.NAME, AlwaysFalse.INSTANCE);
return Collections.unmodifiableMap(registry);
}
}
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 e10b5deb5e..f68771bb7e 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
@@ -143,10 +143,7 @@ public class LeafPredicate implements Predicate {
long rowCount, InternalRow minValues, InternalRow maxValues,
InternalArray nullCounts) {
Optional<FieldRef> fieldRefOptional = fieldRefOptional();
if (!fieldRefOptional.isPresent()) {
- if (transform instanceof TrueTransform) {
- return function.test(transform.outputType(), 0, null, null,
null, literals);
- }
- return true;
+ return !(function instanceof AlwaysFalse);
}
FieldRef fieldRef = fieldRefOptional.get();
int index = fieldRef.index();
@@ -168,23 +165,7 @@ public class LeafPredicate implements Predicate {
@Override
public Optional<Predicate> negate() {
- if (transform instanceof TrueTransform) {
- return function.negate().map(neg -> new LeafPredicate(transform,
neg, literals));
- }
- Optional<FieldRef> fieldRefOptional = fieldRefOptional();
- if (!fieldRefOptional.isPresent()) {
- return Optional.empty();
- }
- FieldRef fieldRef = fieldRefOptional.get();
- return function.negate()
- .map(
- negate ->
- new LeafPredicate(
- negate,
- fieldRef.type(),
- fieldRef.index(),
- fieldRef.name(),
- literals));
+ return function.negate().map(neg -> new LeafPredicate(transform, neg,
literals));
}
@Override
diff --git
a/paimon-common/src/main/java/org/apache/paimon/predicate/TrueTransform.java
b/paimon-common/src/main/java/org/apache/paimon/predicate/NullTransform.java
similarity index 86%
rename from
paimon-common/src/main/java/org/apache/paimon/predicate/TrueTransform.java
rename to
paimon-common/src/main/java/org/apache/paimon/predicate/NullTransform.java
index 2017d2e8d2..da764c048f 100644
--- a/paimon-common/src/main/java/org/apache/paimon/predicate/TrueTransform.java
+++ b/paimon-common/src/main/java/org/apache/paimon/predicate/NullTransform.java
@@ -27,17 +27,17 @@ import
org.apache.paimon.shade.jackson2.com.fasterxml.jackson.annotation.JsonCre
import java.util.Collections;
import java.util.List;
-/** A {@link Transform} that always returns {@code true}. Used for constant
predicates. */
-public class TrueTransform implements Transform {
+/** A {@link Transform} that always returns null. */
+public class NullTransform implements Transform {
private static final long serialVersionUID = 1L;
- public static final String NAME = "TRUE";
+ public static final String NAME = "NULL";
- public static final TrueTransform INSTANCE = new TrueTransform();
+ public static final NullTransform INSTANCE = new NullTransform();
@JsonCreator
- private TrueTransform() {}
+ private NullTransform() {}
@Override
public String name() {
@@ -56,7 +56,7 @@ public class TrueTransform implements Transform {
@Override
public Object transform(InternalRow row) {
- return true;
+ return null;
}
@Override
diff --git
a/paimon-common/src/main/java/org/apache/paimon/predicate/PredicateBuilder.java
b/paimon-common/src/main/java/org/apache/paimon/predicate/PredicateBuilder.java
index b0d52357ac..e73ac84320 100644
---
a/paimon-common/src/main/java/org/apache/paimon/predicate/PredicateBuilder.java
+++
b/paimon-common/src/main/java/org/apache/paimon/predicate/PredicateBuilder.java
@@ -50,6 +50,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
+import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static
org.apache.paimon.utils.InternalRowPartitionComputer.convertSpecToInternal;
@@ -243,6 +244,14 @@ public class PredicateBuilder {
transform, Between.INSTANCE, Arrays.asList(includedLowerBound,
includedUpperBound));
}
+ public Predicate alwaysFalse() {
+ return new LeafPredicate(NullTransform.INSTANCE, AlwaysFalse.INSTANCE,
emptyList());
+ }
+
+ public Predicate alwaysTrue() {
+ return new LeafPredicate(NullTransform.INSTANCE, AlwaysTrue.INSTANCE,
emptyList());
+ }
+
public static Predicate and(Predicate... predicates) {
return and(Arrays.asList(predicates));
}
diff --git
a/paimon-common/src/main/java/org/apache/paimon/predicate/Transform.java
b/paimon-common/src/main/java/org/apache/paimon/predicate/Transform.java
index 6d7b9ba699..826cfd8002 100644
--- a/paimon-common/src/main/java/org/apache/paimon/predicate/Transform.java
+++ b/paimon-common/src/main/java/org/apache/paimon/predicate/Transform.java
@@ -39,7 +39,7 @@ import java.util.List;
@JsonSubTypes.Type(value = ConcatWsTransform.class, name =
ConcatWsTransform.NAME),
@JsonSubTypes.Type(value = UpperTransform.class, name =
UpperTransform.NAME),
@JsonSubTypes.Type(value = LowerTransform.class, name =
LowerTransform.NAME),
- @JsonSubTypes.Type(value = TrueTransform.class, name = TrueTransform.NAME)
+ @JsonSubTypes.Type(value = NullTransform.class, name = NullTransform.NAME)
})
public interface Transform extends Serializable {
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 0af7cf3806..d38703f7be 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
@@ -22,13 +22,13 @@ import org.apache.paimon.data.BinaryString;
import org.apache.paimon.data.GenericArray;
import org.apache.paimon.data.GenericRow;
import org.apache.paimon.types.DataTypes;
+import org.apache.paimon.types.RowType;
import org.apache.paimon.utils.InstantiationUtil;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@@ -83,27 +83,21 @@ class LeafPredicateTest {
@Test
public void testAlwaysTrueRow() {
- LeafPredicate predicate =
- LeafPredicate.of(
- TrueTransform.INSTANCE, TrueFunction.INSTANCE,
Collections.emptyList());
+ LeafPredicate predicate = alwaysTrue();
assertThat(predicate.test(GenericRow.of(1))).isTrue();
assertThat(predicate.test(GenericRow.of((Object) null))).isTrue();
}
@Test
public void testAlwaysFalseRow() {
- LeafPredicate predicate =
- LeafPredicate.of(
- TrueTransform.INSTANCE, FalseFunction.INSTANCE,
Collections.emptyList());
+ LeafPredicate predicate = alwaysFalse();
assertThat(predicate.test(GenericRow.of(1))).isFalse();
assertThat(predicate.test(GenericRow.of((Object) null))).isFalse();
}
@Test
public void testAlwaysTrueMinMax() {
- LeafPredicate predicate =
- LeafPredicate.of(
- TrueTransform.INSTANCE, TrueFunction.INSTANCE,
Collections.emptyList());
+ LeafPredicate predicate = alwaysTrue();
assertThat(
predicate.test(
10,
@@ -116,9 +110,7 @@ class LeafPredicateTest {
@Test
public void testAlwaysFalseMinMax() {
- LeafPredicate predicate =
- LeafPredicate.of(
- TrueTransform.INSTANCE, FalseFunction.INSTANCE,
Collections.emptyList());
+ LeafPredicate predicate = alwaysFalse();
assertThat(
predicate.test(
10,
@@ -131,35 +123,27 @@ class LeafPredicateTest {
@Test
public void testAlwaysTrueNegate() {
- LeafPredicate predicate =
- LeafPredicate.of(
- TrueTransform.INSTANCE, TrueFunction.INSTANCE,
Collections.emptyList());
+ LeafPredicate predicate = alwaysTrue();
Predicate negated = predicate.negate().get();
assertThat(negated).isInstanceOf(LeafPredicate.class);
LeafPredicate negatedLeaf = (LeafPredicate) negated;
- assertThat(negatedLeaf.function()).isEqualTo(FalseFunction.INSTANCE);
- assertThat(negatedLeaf.transform()).isInstanceOf(TrueTransform.class);
+ assertThat(negatedLeaf.function()).isEqualTo(AlwaysFalse.INSTANCE);
assertThat(negatedLeaf.test(GenericRow.of(1))).isFalse();
}
@Test
public void testAlwaysFalseNegate() {
- LeafPredicate predicate =
- LeafPredicate.of(
- TrueTransform.INSTANCE, FalseFunction.INSTANCE,
Collections.emptyList());
+ LeafPredicate predicate = alwaysFalse();
Predicate negated = predicate.negate().get();
assertThat(negated).isInstanceOf(LeafPredicate.class);
LeafPredicate negatedLeaf = (LeafPredicate) negated;
- assertThat(negatedLeaf.function()).isEqualTo(TrueFunction.INSTANCE);
- assertThat(negatedLeaf.transform()).isInstanceOf(TrueTransform.class);
+ assertThat(negatedLeaf.function()).isEqualTo(AlwaysTrue.INSTANCE);
assertThat(negatedLeaf.test(GenericRow.of(1))).isTrue();
}
@Test
public void testAlwaysTrueSerialization() throws IOException,
ClassNotFoundException {
- LeafPredicate predicate =
- LeafPredicate.of(
- TrueTransform.INSTANCE, TrueFunction.INSTANCE,
Collections.emptyList());
+ LeafPredicate predicate = alwaysTrue();
LeafPredicate clone = InstantiationUtil.clone(predicate);
assertThat(clone).isEqualTo(predicate);
assertThat(clone.hashCode()).isEqualTo(predicate.hashCode());
@@ -167,11 +151,19 @@ class LeafPredicateTest {
@Test
public void testAlwaysFalseSerialization() throws IOException,
ClassNotFoundException {
- LeafPredicate predicate =
- LeafPredicate.of(
- TrueTransform.INSTANCE, FalseFunction.INSTANCE,
Collections.emptyList());
+ LeafPredicate predicate = alwaysFalse();
LeafPredicate clone = InstantiationUtil.clone(predicate);
assertThat(clone).isEqualTo(predicate);
assertThat(clone.hashCode()).isEqualTo(predicate.hashCode());
}
+
+ private LeafPredicate alwaysTrue() {
+ PredicateBuilder builder = new PredicateBuilder(RowType.of());
+ return (LeafPredicate) builder.alwaysTrue();
+ }
+
+ private LeafPredicate alwaysFalse() {
+ PredicateBuilder builder = new PredicateBuilder(RowType.of());
+ return (LeafPredicate) builder.alwaysFalse();
+ }
}
diff --git
a/paimon-common/src/test/java/org/apache/paimon/predicate/PredicateJsonSerdeTest.java
b/paimon-common/src/test/java/org/apache/paimon/predicate/PredicateJsonSerdeTest.java
index 3093b83eff..1b18a05b2d 100644
---
a/paimon-common/src/test/java/org/apache/paimon/predicate/PredicateJsonSerdeTest.java
+++
b/paimon-common/src/test/java/org/apache/paimon/predicate/PredicateJsonSerdeTest.java
@@ -156,23 +156,15 @@ class PredicateJsonSerdeTest {
.expectJson(
"{\"kind\":\"LEAF\",\"transform\":{\"name\":\"FIELD_REF\",\"fieldRef\":{\"index\":2,\"name\":\"f2\",\"type\":\"STRING\"}},\"function\":\"LIKE\",\"literals\":[\"%a%b%\"]}"),
- // LeafPredicate - TrueTransform + TrueFunction (AlwaysTrue)
- TestSpec.forPredicate(
- LeafPredicate.of(
- TrueTransform.INSTANCE,
- TrueFunction.INSTANCE,
- Collections.emptyList()))
+ // LeafPredicate - AlwaysTrue
+ TestSpec.forPredicate(builder.alwaysTrue())
.expectJson(
-
"{\"kind\":\"LEAF\",\"transform\":{\"name\":\"TRUE\"},\"function\":\"TRUE\",\"literals\":[]}"),
+
"{\"kind\":\"LEAF\",\"transform\":{\"name\":\"NULL\"},\"function\":\"TRUE\",\"literals\":[]}"),
- // LeafPredicate - TrueTransform + FalseFunction (AlwaysFalse)
- TestSpec.forPredicate(
- LeafPredicate.of(
- TrueTransform.INSTANCE,
- FalseFunction.INSTANCE,
- Collections.emptyList()))
+ // LeafPredicate - AlwaysFalse
+ TestSpec.forPredicate(builder.alwaysFalse())
.expectJson(
-
"{\"kind\":\"LEAF\",\"transform\":{\"name\":\"TRUE\"},\"function\":\"FALSE\",\"literals\":[]}"),
+
"{\"kind\":\"LEAF\",\"transform\":{\"name\":\"NULL\"},\"function\":\"FALSE\",\"literals\":[]}"),
// LeafPredicate - In with many values including nulls
TestSpec.forPredicate(
diff --git
a/paimon-spark/paimon-spark-common/src/main/scala/org/apache/paimon/spark/SparkV2FilterConverter.scala
b/paimon-spark/paimon-spark-common/src/main/scala/org/apache/paimon/spark/SparkV2FilterConverter.scala
index 970d619792..ed87464832 100644
---
a/paimon-spark/paimon-spark-common/src/main/scala/org/apache/paimon/spark/SparkV2FilterConverter.scala
+++
b/paimon-spark/paimon-spark-common/src/main/scala/org/apache/paimon/spark/SparkV2FilterConverter.scala
@@ -18,7 +18,7 @@
package org.apache.paimon.spark
-import org.apache.paimon.predicate.{FalseFunction, LeafPredicate, Predicate,
PredicateBuilder, Transform, TrueFunction, TrueTransform}
+import org.apache.paimon.predicate.{Predicate, PredicateBuilder, Transform}
import org.apache.paimon.spark.util.SparkExpressionConverter.{toPaimonLiteral,
toPaimonTransform}
import org.apache.paimon.types.RowType
@@ -165,16 +165,10 @@ case class SparkV2FilterConverter(rowType: RowType)
extends Logging {
}
case ALWAYS_TRUE =>
- LeafPredicate.of(
- TrueTransform.INSTANCE,
- TrueFunction.INSTANCE,
- java.util.Collections.emptyList())
+ builder.alwaysTrue()
case ALWAYS_FALSE =>
- LeafPredicate.of(
- TrueTransform.INSTANCE,
- FalseFunction.INSTANCE,
- java.util.Collections.emptyList())
+ builder.alwaysFalse()
case _ => throw new UnsupportedOperationException(s"Convert
$sparkPredicate is unsupported.")
}
diff --git
a/paimon-spark/paimon-spark-ut/src/test/scala/org/apache/paimon/spark/sql/SparkV2FilterConverterTestBase.scala
b/paimon-spark/paimon-spark-ut/src/test/scala/org/apache/paimon/spark/sql/SparkV2FilterConverterTestBase.scala
index 430f0785eb..92cba77a3f 100644
---
a/paimon-spark/paimon-spark-ut/src/test/scala/org/apache/paimon/spark/sql/SparkV2FilterConverterTestBase.scala
+++
b/paimon-spark/paimon-spark-ut/src/test/scala/org/apache/paimon/spark/sql/SparkV2FilterConverterTestBase.scala
@@ -19,7 +19,7 @@
package org.apache.paimon.spark.sql
import org.apache.paimon.data.{BinaryString, Decimal, Timestamp}
-import org.apache.paimon.predicate.{FalseFunction, LeafPredicate,
PredicateBuilder, TrueFunction, TrueTransform}
+import org.apache.paimon.predicate.PredicateBuilder
import org.apache.paimon.spark.{PaimonSparkTestBase, SparkV2FilterConverter}
import
org.apache.paimon.spark.util.shim.TypeUtils.treatPaimonTimestampTypeAsSparkTimestampType
import org.apache.paimon.table.source.DataSplit
@@ -355,17 +355,9 @@ abstract class SparkV2FilterConverterTestBase extends
PaimonSparkTestBase {
assert(scanFilesCount(filter) == 4)
}
- private def paimonAlwaysTrue: org.apache.paimon.predicate.Predicate =
- LeafPredicate.of(
- TrueTransform.INSTANCE,
- TrueFunction.INSTANCE,
- java.util.Collections.emptyList())
+ private def paimonAlwaysTrue: org.apache.paimon.predicate.Predicate =
builder.alwaysTrue()
- private def paimonAlwaysFalse: org.apache.paimon.predicate.Predicate =
- LeafPredicate.of(
- TrueTransform.INSTANCE,
- FalseFunction.INSTANCE,
- java.util.Collections.emptyList())
+ private def paimonAlwaysFalse: org.apache.paimon.predicate.Predicate =
builder.alwaysFalse()
test("V2Filter: AlwaysTrue") {
val sparkAlwaysTrue =