Skip to content

Commit 101b5e4

Browse files
committed
[spark] Support AlwaysTrue and AlwaysFalse predicates in SparkV2FilterConverter
1 parent 8703b95 commit 101b5e4

15 files changed

Lines changed: 316 additions & 4 deletions

File tree

paimon-common/src/main/java/org/apache/paimon/fileindex/FileIndexPredicate.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.apache.paimon.fs.Path;
2525
import org.apache.paimon.fs.SeekableInputStream;
2626
import org.apache.paimon.predicate.CompoundPredicate;
27+
import org.apache.paimon.predicate.ConstantPredicate;
2728
import org.apache.paimon.predicate.FieldRef;
2829
import org.apache.paimon.predicate.LeafPredicate;
2930
import org.apache.paimon.predicate.Or;
@@ -132,6 +133,12 @@ public Set<String> visit(CompoundPredicate predicate) {
132133
}
133134
return result;
134135
}
136+
137+
@Override
138+
public Set<String> visit(ConstantPredicate predicate) {
139+
// ConstantPredicate doesn't reference any fields
140+
return new HashSet<>();
141+
}
135142
});
136143
}
137144

@@ -202,5 +209,11 @@ public FileIndexResult visit(CompoundPredicate predicate) {
202209
return compoundResult == null ? REMAIN : compoundResult;
203210
}
204211
}
212+
213+
@Override
214+
public FileIndexResult visit(ConstantPredicate predicate) {
215+
// ConstantPredicate doesn't have field index, return REMAIN
216+
return REMAIN;
217+
}
205218
}
206219
}

paimon-common/src/main/java/org/apache/paimon/globalindex/GlobalIndexEvaluator.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package org.apache.paimon.globalindex;
2020

2121
import org.apache.paimon.predicate.CompoundPredicate;
22+
import org.apache.paimon.predicate.ConstantPredicate;
2223
import org.apache.paimon.predicate.FieldRef;
2324
import org.apache.paimon.predicate.LeafPredicate;
2425
import org.apache.paimon.predicate.Or;
@@ -160,6 +161,12 @@ public Optional<GlobalIndexResult> visit(CompoundPredicate predicate) {
160161
}
161162
}
162163

164+
@Override
165+
public Optional<GlobalIndexResult> visit(ConstantPredicate predicate) {
166+
// ConstantPredicate doesn't have global index support
167+
return Optional.empty();
168+
}
169+
163170
public void close() {
164171
IOUtils.closeAllQuietly(
165172
indexReadersCache.values().stream()
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
package org.apache.paimon.predicate;
20+
21+
import org.apache.paimon.data.InternalArray;
22+
import org.apache.paimon.data.InternalRow;
23+
24+
import org.apache.paimon.shade.jackson2.com.fasterxml.jackson.annotation.JsonCreator;
25+
import org.apache.paimon.shade.jackson2.com.fasterxml.jackson.annotation.JsonGetter;
26+
import org.apache.paimon.shade.jackson2.com.fasterxml.jackson.annotation.JsonProperty;
27+
28+
import java.util.Optional;
29+
30+
/** A constant predicate that always returns true or false. */
31+
public class ConstantPredicate implements Predicate {
32+
33+
private static final long serialVersionUID = 1L;
34+
35+
public static final String NAME = "CONSTANT";
36+
37+
public static final String FIELD_VALUE = "value";
38+
39+
/** A predicate that always returns true. */
40+
public static final ConstantPredicate ALWAYS_TRUE = new ConstantPredicate(true);
41+
42+
/** A predicate that always returns false. */
43+
public static final ConstantPredicate ALWAYS_FALSE = new ConstantPredicate(false);
44+
45+
@JsonProperty(FIELD_VALUE)
46+
private final boolean value;
47+
48+
@JsonCreator
49+
public ConstantPredicate(@JsonProperty(FIELD_VALUE) boolean value) {
50+
this.value = value;
51+
}
52+
53+
@JsonGetter(FIELD_VALUE)
54+
public boolean value() {
55+
return value;
56+
}
57+
58+
@Override
59+
public boolean test(InternalRow row) {
60+
return value;
61+
}
62+
63+
@Override
64+
public boolean test(
65+
long rowCount, InternalRow minValues, InternalRow maxValues, InternalArray nullCounts) {
66+
return value;
67+
}
68+
69+
@Override
70+
public Optional<Predicate> negate() {
71+
return Optional.of(value ? ALWAYS_FALSE : ALWAYS_TRUE);
72+
}
73+
74+
@Override
75+
public <T> T visit(PredicateVisitor<T> visitor) {
76+
return visitor.visit(this);
77+
}
78+
79+
@Override
80+
public boolean equals(Object o) {
81+
if (this == o) {
82+
return true;
83+
}
84+
if (!(o instanceof ConstantPredicate)) {
85+
return false;
86+
}
87+
ConstantPredicate that = (ConstantPredicate) o;
88+
return value == that.value;
89+
}
90+
91+
@Override
92+
public int hashCode() {
93+
return Boolean.hashCode(value);
94+
}
95+
96+
@Override
97+
public String toString() {
98+
return value ? "ALWAYS_TRUE" : "ALWAYS_FALSE";
99+
}
100+
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,10 @@ public Map<String, LeafPredicate> visit(CompoundPredicate predicate) {
4646
}
4747
return Collections.emptyMap();
4848
}
49+
50+
@Override
51+
public Map<String, LeafPredicate> visit(ConstantPredicate predicate) {
52+
// ConstantPredicate has no leaf predicates
53+
return Collections.emptyMap();
54+
}
4955
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,9 @@ public Boolean visit(CompoundPredicate predicate) {
5353
}
5454
return true;
5555
}
56+
57+
@Override
58+
public Boolean visit(ConstantPredicate predicate) {
59+
return false;
60+
}
5661
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@
4141
property = Predicate.FIELD_KIND)
4242
@JsonSubTypes({
4343
@JsonSubTypes.Type(value = LeafPredicate.class, name = LeafPredicate.NAME),
44-
@JsonSubTypes.Type(value = CompoundPredicate.class, name = CompoundPredicate.NAME)
44+
@JsonSubTypes.Type(value = CompoundPredicate.class, name = CompoundPredicate.NAME),
45+
@JsonSubTypes.Type(value = ConstantPredicate.class, name = ConstantPredicate.NAME)
4546
})
4647
public interface Predicate extends Serializable {
4748

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,10 @@ public static Optional<Predicate> transformFieldMapping(
497497
}
498498
}
499499
return Optional.of(leafPredicate.copyWithNewInputs(newInputs));
500+
} else if (predicate instanceof ConstantPredicate) {
501+
// ConstantPredicate (AlwaysTrue/AlwaysFalse) doesn't reference any fields,
502+
// so it can be returned as-is
503+
return Optional.of(predicate);
500504
} else {
501505
return Optional.empty();
502506
}
@@ -510,6 +514,9 @@ public static boolean containsFields(Predicate predicate, Set<String> fields) {
510514
}
511515
}
512516
return false;
517+
} else if (predicate instanceof ConstantPredicate) {
518+
// ConstantPredicate doesn't reference any fields
519+
return true;
513520
} else {
514521
LeafPredicate leafPredicate = (LeafPredicate) predicate;
515522
return fields.containsAll(leafPredicate.fieldNames());

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,10 @@ public Optional<Predicate> visit(CompoundPredicate predicate) {
7676
}
7777
return Optional.of(new CompoundPredicate(predicate.function(), converted));
7878
}
79+
80+
@Override
81+
public Optional<Predicate> visit(ConstantPredicate predicate) {
82+
// ConstantPredicate doesn't need projection conversion
83+
return Optional.of(predicate);
84+
}
7985
}

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ public interface PredicateVisitor<T> {
3131

3232
T visit(CompoundPredicate predicate);
3333

34+
/**
35+
* Visit a constant predicate. Default implementation throws UnsupportedOperationException.
36+
* Override this method if you need to handle constant predicates.
37+
*/
38+
default T visit(ConstantPredicate predicate) {
39+
throw new UnsupportedOperationException(
40+
"ConstantPredicate is not supported by " + this.getClass().getName());
41+
}
42+
3443
static Set<String> collectFieldNames(@Nullable Predicate predicate) {
3544
if (predicate == null) {
3645
return Collections.emptySet();
@@ -60,5 +69,11 @@ public Set<String> visit(CompoundPredicate predicate) {
6069
}
6170
return fieldNames;
6271
}
72+
73+
@Override
74+
public Set<String> visit(ConstantPredicate predicate) {
75+
// Constant predicates don't reference any fields
76+
return Collections.emptySet();
77+
}
6378
}
6479
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,10 @@ public Optional<List<Range>> visit(CompoundPredicate predicate) {
104104
}
105105
return rowIds;
106106
}
107+
108+
@Override
109+
public Optional<List<Range>> visit(ConstantPredicate predicate) {
110+
// ConstantPredicate doesn't reference ROW_ID field
111+
return Optional.empty();
112+
}
107113
}

0 commit comments

Comments
 (0)