Skip to content

Commit 689df5e

Browse files
committed
[core] Introduce NullTransform for AlwaysTrue and AlwaysFalse
1 parent dbc4198 commit 689df5e

File tree

11 files changed

+63
-103
lines changed

11 files changed

+63
-103
lines changed

paimon-common/src/main/java/org/apache/paimon/predicate/FalseFunction.java renamed to paimon-common/src/main/java/org/apache/paimon/predicate/AlwaysFalse.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,16 @@
2626
import java.util.Optional;
2727

2828
/** A {@link LeafFunction} that always returns {@code false}. Used for AlwaysFalse predicates. */
29-
public class FalseFunction extends LeafFunction {
29+
public class AlwaysFalse extends LeafFunction {
3030

3131
private static final long serialVersionUID = 1L;
3232

3333
public static final String NAME = "FALSE";
3434

35-
public static final FalseFunction INSTANCE = new FalseFunction();
35+
public static final AlwaysFalse INSTANCE = new AlwaysFalse();
3636

3737
@JsonCreator
38-
private FalseFunction() {}
38+
private AlwaysFalse() {}
3939

4040
@Override
4141
public boolean test(DataType type, Object field, List<Object> literals) {
@@ -55,13 +55,13 @@ public boolean test(
5555

5656
@Override
5757
public Optional<LeafFunction> negate() {
58-
return Optional.of(TrueFunction.INSTANCE);
58+
return Optional.of(AlwaysTrue.INSTANCE);
5959
}
6060

6161
@Override
6262
public <T> T visit(FunctionVisitor<T> visitor, FieldRef fieldRef, List<Object> literals) {
6363
throw new UnsupportedOperationException(
64-
"FalseFunction does not support field-based visitation.");
64+
"AlwaysFalse does not support field-based visitation.");
6565
}
6666

6767
@Override

paimon-common/src/main/java/org/apache/paimon/predicate/TrueFunction.java renamed to paimon-common/src/main/java/org/apache/paimon/predicate/AlwaysTrue.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,16 @@
2626
import java.util.Optional;
2727

2828
/** A {@link LeafFunction} that always returns {@code true}. Used for AlwaysTrue predicates. */
29-
public class TrueFunction extends LeafFunction {
29+
public class AlwaysTrue extends LeafFunction {
3030

3131
private static final long serialVersionUID = 1L;
3232

3333
public static final String NAME = "TRUE";
3434

35-
public static final TrueFunction INSTANCE = new TrueFunction();
35+
public static final AlwaysTrue INSTANCE = new AlwaysTrue();
3636

3737
@JsonCreator
38-
private TrueFunction() {}
38+
private AlwaysTrue() {}
3939

4040
@Override
4141
public boolean test(DataType type, Object field, List<Object> literals) {
@@ -55,13 +55,13 @@ public boolean test(
5555

5656
@Override
5757
public Optional<LeafFunction> negate() {
58-
return Optional.of(FalseFunction.INSTANCE);
58+
return Optional.of(AlwaysFalse.INSTANCE);
5959
}
6060

6161
@Override
6262
public <T> T visit(FunctionVisitor<T> visitor, FieldRef fieldRef, List<Object> literals) {
6363
throw new UnsupportedOperationException(
64-
"TrueFunction does not support field-based visitation.");
64+
"AlwaysTrue does not support field-based visitation.");
6565
}
6666

6767
@Override

paimon-common/src/main/java/org/apache/paimon/predicate/LeafFunction.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ private static Map<String, LeafFunction> createRegistry() {
6868
registry.put(NotIn.NAME, NotIn.INSTANCE);
6969
registry.put(Between.NAME, Between.INSTANCE);
7070
registry.put(NotBetween.NAME, NotBetween.INSTANCE);
71-
registry.put(TrueFunction.NAME, TrueFunction.INSTANCE);
72-
registry.put(FalseFunction.NAME, FalseFunction.INSTANCE);
71+
registry.put(AlwaysTrue.NAME, AlwaysTrue.INSTANCE);
72+
registry.put(AlwaysFalse.NAME, AlwaysFalse.INSTANCE);
7373
return Collections.unmodifiableMap(registry);
7474
}
7575
}

paimon-common/src/main/java/org/apache/paimon/predicate/LeafPredicate.java

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,7 @@ public boolean test(
143143
long rowCount, InternalRow minValues, InternalRow maxValues, InternalArray nullCounts) {
144144
Optional<FieldRef> fieldRefOptional = fieldRefOptional();
145145
if (!fieldRefOptional.isPresent()) {
146-
if (transform instanceof TrueTransform) {
147-
return function.test(transform.outputType(), 0, null, null, null, literals);
148-
}
149-
return true;
146+
return !(function instanceof AlwaysFalse);
150147
}
151148
FieldRef fieldRef = fieldRefOptional.get();
152149
int index = fieldRef.index();
@@ -168,23 +165,7 @@ public boolean test(
168165

169166
@Override
170167
public Optional<Predicate> negate() {
171-
if (transform instanceof TrueTransform) {
172-
return function.negate().map(neg -> new LeafPredicate(transform, neg, literals));
173-
}
174-
Optional<FieldRef> fieldRefOptional = fieldRefOptional();
175-
if (!fieldRefOptional.isPresent()) {
176-
return Optional.empty();
177-
}
178-
FieldRef fieldRef = fieldRefOptional.get();
179-
return function.negate()
180-
.map(
181-
negate ->
182-
new LeafPredicate(
183-
negate,
184-
fieldRef.type(),
185-
fieldRef.index(),
186-
fieldRef.name(),
187-
literals));
168+
return function.negate().map(neg -> new LeafPredicate(transform, neg, literals));
188169
}
189170

190171
@Override

paimon-common/src/main/java/org/apache/paimon/predicate/TrueTransform.java renamed to paimon-common/src/main/java/org/apache/paimon/predicate/NullTransform.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,17 @@
2727
import java.util.Collections;
2828
import java.util.List;
2929

30-
/** A {@link Transform} that always returns {@code true}. Used for constant predicates. */
31-
public class TrueTransform implements Transform {
30+
/** A {@link Transform} that always returns null. */
31+
public class NullTransform implements Transform {
3232

3333
private static final long serialVersionUID = 1L;
3434

35-
public static final String NAME = "TRUE";
35+
public static final String NAME = "NULL";
3636

37-
public static final TrueTransform INSTANCE = new TrueTransform();
37+
public static final NullTransform INSTANCE = new NullTransform();
3838

3939
@JsonCreator
40-
private TrueTransform() {}
40+
private NullTransform() {}
4141

4242
@Override
4343
public String name() {
@@ -56,7 +56,7 @@ public DataType outputType() {
5656

5757
@Override
5858
public Object transform(InternalRow row) {
59-
return true;
59+
return null;
6060
}
6161

6262
@Override

paimon-common/src/main/java/org/apache/paimon/predicate/PredicateBuilder.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import java.util.Set;
5151
import java.util.stream.Collectors;
5252

53+
import static java.util.Collections.emptyList;
5354
import static java.util.Collections.singletonList;
5455
import static org.apache.paimon.utils.InternalRowPartitionComputer.convertSpecToInternal;
5556

@@ -243,6 +244,14 @@ public Predicate between(
243244
transform, Between.INSTANCE, Arrays.asList(includedLowerBound, includedUpperBound));
244245
}
245246

247+
public Predicate alwaysFalse() {
248+
return new LeafPredicate(NullTransform.INSTANCE, AlwaysFalse.INSTANCE, emptyList());
249+
}
250+
251+
public Predicate alwaysTrue() {
252+
return new LeafPredicate(NullTransform.INSTANCE, AlwaysTrue.INSTANCE, emptyList());
253+
}
254+
246255
public static Predicate and(Predicate... predicates) {
247256
return and(Arrays.asList(predicates));
248257
}

paimon-common/src/main/java/org/apache/paimon/predicate/Transform.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
@JsonSubTypes.Type(value = ConcatWsTransform.class, name = ConcatWsTransform.NAME),
4040
@JsonSubTypes.Type(value = UpperTransform.class, name = UpperTransform.NAME),
4141
@JsonSubTypes.Type(value = LowerTransform.class, name = LowerTransform.NAME),
42-
@JsonSubTypes.Type(value = TrueTransform.class, name = TrueTransform.NAME)
42+
@JsonSubTypes.Type(value = NullTransform.class, name = NullTransform.NAME)
4343
})
4444
public interface Transform extends Serializable {
4545

paimon-common/src/test/java/org/apache/paimon/predicate/LeafPredicateTest.java

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@
2222
import org.apache.paimon.data.GenericArray;
2323
import org.apache.paimon.data.GenericRow;
2424
import org.apache.paimon.types.DataTypes;
25+
import org.apache.paimon.types.RowType;
2526
import org.apache.paimon.utils.InstantiationUtil;
2627

2728
import org.junit.jupiter.api.Test;
2829

2930
import java.io.IOException;
3031
import java.util.ArrayList;
31-
import java.util.Collections;
3232
import java.util.List;
3333

3434
import static org.assertj.core.api.Assertions.assertThat;
@@ -83,27 +83,21 @@ private LeafPredicate create() {
8383

8484
@Test
8585
public void testAlwaysTrueRow() {
86-
LeafPredicate predicate =
87-
LeafPredicate.of(
88-
TrueTransform.INSTANCE, TrueFunction.INSTANCE, Collections.emptyList());
86+
LeafPredicate predicate = alwaysTrue();
8987
assertThat(predicate.test(GenericRow.of(1))).isTrue();
9088
assertThat(predicate.test(GenericRow.of((Object) null))).isTrue();
9189
}
9290

9391
@Test
9492
public void testAlwaysFalseRow() {
95-
LeafPredicate predicate =
96-
LeafPredicate.of(
97-
TrueTransform.INSTANCE, FalseFunction.INSTANCE, Collections.emptyList());
93+
LeafPredicate predicate = alwaysFalse();
9894
assertThat(predicate.test(GenericRow.of(1))).isFalse();
9995
assertThat(predicate.test(GenericRow.of((Object) null))).isFalse();
10096
}
10197

10298
@Test
10399
public void testAlwaysTrueMinMax() {
104-
LeafPredicate predicate =
105-
LeafPredicate.of(
106-
TrueTransform.INSTANCE, TrueFunction.INSTANCE, Collections.emptyList());
100+
LeafPredicate predicate = alwaysTrue();
107101
assertThat(
108102
predicate.test(
109103
10,
@@ -116,9 +110,7 @@ public void testAlwaysTrueMinMax() {
116110

117111
@Test
118112
public void testAlwaysFalseMinMax() {
119-
LeafPredicate predicate =
120-
LeafPredicate.of(
121-
TrueTransform.INSTANCE, FalseFunction.INSTANCE, Collections.emptyList());
113+
LeafPredicate predicate = alwaysFalse();
122114
assertThat(
123115
predicate.test(
124116
10,
@@ -131,47 +123,47 @@ public void testAlwaysFalseMinMax() {
131123

132124
@Test
133125
public void testAlwaysTrueNegate() {
134-
LeafPredicate predicate =
135-
LeafPredicate.of(
136-
TrueTransform.INSTANCE, TrueFunction.INSTANCE, Collections.emptyList());
126+
LeafPredicate predicate = alwaysTrue();
137127
Predicate negated = predicate.negate().get();
138128
assertThat(negated).isInstanceOf(LeafPredicate.class);
139129
LeafPredicate negatedLeaf = (LeafPredicate) negated;
140-
assertThat(negatedLeaf.function()).isEqualTo(FalseFunction.INSTANCE);
141-
assertThat(negatedLeaf.transform()).isInstanceOf(TrueTransform.class);
130+
assertThat(negatedLeaf.function()).isEqualTo(AlwaysFalse.INSTANCE);
142131
assertThat(negatedLeaf.test(GenericRow.of(1))).isFalse();
143132
}
144133

145134
@Test
146135
public void testAlwaysFalseNegate() {
147-
LeafPredicate predicate =
148-
LeafPredicate.of(
149-
TrueTransform.INSTANCE, FalseFunction.INSTANCE, Collections.emptyList());
136+
LeafPredicate predicate = alwaysFalse();
150137
Predicate negated = predicate.negate().get();
151138
assertThat(negated).isInstanceOf(LeafPredicate.class);
152139
LeafPredicate negatedLeaf = (LeafPredicate) negated;
153-
assertThat(negatedLeaf.function()).isEqualTo(TrueFunction.INSTANCE);
154-
assertThat(negatedLeaf.transform()).isInstanceOf(TrueTransform.class);
140+
assertThat(negatedLeaf.function()).isEqualTo(AlwaysTrue.INSTANCE);
155141
assertThat(negatedLeaf.test(GenericRow.of(1))).isTrue();
156142
}
157143

158144
@Test
159145
public void testAlwaysTrueSerialization() throws IOException, ClassNotFoundException {
160-
LeafPredicate predicate =
161-
LeafPredicate.of(
162-
TrueTransform.INSTANCE, TrueFunction.INSTANCE, Collections.emptyList());
146+
LeafPredicate predicate = alwaysTrue();
163147
LeafPredicate clone = InstantiationUtil.clone(predicate);
164148
assertThat(clone).isEqualTo(predicate);
165149
assertThat(clone.hashCode()).isEqualTo(predicate.hashCode());
166150
}
167151

168152
@Test
169153
public void testAlwaysFalseSerialization() throws IOException, ClassNotFoundException {
170-
LeafPredicate predicate =
171-
LeafPredicate.of(
172-
TrueTransform.INSTANCE, FalseFunction.INSTANCE, Collections.emptyList());
154+
LeafPredicate predicate = alwaysFalse();
173155
LeafPredicate clone = InstantiationUtil.clone(predicate);
174156
assertThat(clone).isEqualTo(predicate);
175157
assertThat(clone.hashCode()).isEqualTo(predicate.hashCode());
176158
}
159+
160+
private LeafPredicate alwaysTrue() {
161+
PredicateBuilder builder = new PredicateBuilder(RowType.of());
162+
return (LeafPredicate) builder.alwaysTrue();
163+
}
164+
165+
private LeafPredicate alwaysFalse() {
166+
PredicateBuilder builder = new PredicateBuilder(RowType.of());
167+
return (LeafPredicate) builder.alwaysFalse();
168+
}
177169
}

paimon-common/src/test/java/org/apache/paimon/predicate/PredicateJsonSerdeTest.java

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -156,23 +156,15 @@ private static Stream<TestSpec> testData() {
156156
.expectJson(
157157
"{\"kind\":\"LEAF\",\"transform\":{\"name\":\"FIELD_REF\",\"fieldRef\":{\"index\":2,\"name\":\"f2\",\"type\":\"STRING\"}},\"function\":\"LIKE\",\"literals\":[\"%a%b%\"]}"),
158158

159-
// LeafPredicate - TrueTransform + TrueFunction (AlwaysTrue)
160-
TestSpec.forPredicate(
161-
LeafPredicate.of(
162-
TrueTransform.INSTANCE,
163-
TrueFunction.INSTANCE,
164-
Collections.emptyList()))
159+
// LeafPredicate - AlwaysTrue
160+
TestSpec.forPredicate(builder.alwaysTrue())
165161
.expectJson(
166-
"{\"kind\":\"LEAF\",\"transform\":{\"name\":\"TRUE\"},\"function\":\"TRUE\",\"literals\":[]}"),
162+
"{\"kind\":\"LEAF\",\"transform\":{\"name\":\"NULL\"},\"function\":\"TRUE\",\"literals\":[]}"),
167163

168-
// LeafPredicate - TrueTransform + FalseFunction (AlwaysFalse)
169-
TestSpec.forPredicate(
170-
LeafPredicate.of(
171-
TrueTransform.INSTANCE,
172-
FalseFunction.INSTANCE,
173-
Collections.emptyList()))
164+
// LeafPredicate - AlwaysFalse
165+
TestSpec.forPredicate(builder.alwaysFalse())
174166
.expectJson(
175-
"{\"kind\":\"LEAF\",\"transform\":{\"name\":\"TRUE\"},\"function\":\"FALSE\",\"literals\":[]}"),
167+
"{\"kind\":\"LEAF\",\"transform\":{\"name\":\"NULL\"},\"function\":\"FALSE\",\"literals\":[]}"),
176168

177169
// LeafPredicate - In with many values including nulls
178170
TestSpec.forPredicate(

paimon-spark/paimon-spark-common/src/main/scala/org/apache/paimon/spark/SparkV2FilterConverter.scala

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
package org.apache.paimon.spark
2020

21-
import org.apache.paimon.predicate.{FalseFunction, LeafPredicate, Predicate, PredicateBuilder, Transform, TrueFunction, TrueTransform}
21+
import org.apache.paimon.predicate.{Predicate, PredicateBuilder, Transform}
2222
import org.apache.paimon.spark.util.SparkExpressionConverter.{toPaimonLiteral, toPaimonTransform}
2323
import org.apache.paimon.types.RowType
2424

@@ -165,16 +165,10 @@ case class SparkV2FilterConverter(rowType: RowType) extends Logging {
165165
}
166166

167167
case ALWAYS_TRUE =>
168-
LeafPredicate.of(
169-
TrueTransform.INSTANCE,
170-
TrueFunction.INSTANCE,
171-
java.util.Collections.emptyList())
168+
builder.alwaysTrue()
172169

173170
case ALWAYS_FALSE =>
174-
LeafPredicate.of(
175-
TrueTransform.INSTANCE,
176-
FalseFunction.INSTANCE,
177-
java.util.Collections.emptyList())
171+
builder.alwaysFalse()
178172

179173
case _ => throw new UnsupportedOperationException(s"Convert $sparkPredicate is unsupported.")
180174
}

0 commit comments

Comments
 (0)