Skip to content

Commit 393727e

Browse files
authored
GH-3632: Fix record-level notIn evaluation (#3631)
1 parent aaff5db commit 393727e

2 files changed

Lines changed: 67 additions & 33 deletions

File tree

parquet-generator/src/main/java/org/apache/parquet/filter2/IncrementallyUpdatedFilterPredicateGenerator.java

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -281,51 +281,50 @@ private void addInequalityCase(TypeInfo info, String op, boolean expectMultipleR
281281
}
282282

283283
private void addInNotInCase(TypeInfo info, boolean isEq, boolean expectMultipleResults) throws IOException {
284-
add(" if (clazz.equals(" + info.className + ".class)) {\n" + " if (pred.getValues().contains(null)) {\n"
285-
+ " valueInspector = new ValueInspector() {\n"
286-
+ " @Override\n"
287-
+ " public void updateNull() {\n"
288-
+ " setResult("
289-
+ isEq + ");\n" + " }\n"
290-
+ "\n"
291-
+ " @Override\n"
292-
+ " public void update("
293-
+ info.primitiveName + " value) {\n" + " setResult("
294-
+ !isEq + ");\n" + " }\n"
295-
+ " };\n"
296-
+ " } else {\n"
297-
+ " final Set<"
284+
String nullResult = isEq ? "containsNull" : "!containsNull";
285+
add(" if (clazz.equals(" + info.className + ".class)) {\n" + " final Set<"
298286
+ info.className + "> target = (Set<" + info.className + ">) pred.getValues();\n"
299-
+ " final PrimitiveComparator<"
287+
+ " final boolean containsNull = target.contains(null);\n"
288+
+ " final PrimitiveComparator<"
300289
+ info.className + "> comparator = getComparator(columnPath);\n" + "\n"
301-
+ " valueInspector = new ValueInspector() {\n"
302-
+ " @Override\n"
303-
+ " public void updateNull() {\n"
304-
+ " setResult("
305-
+ !isEq + ");\n" + " }\n"
290+
+ " valueInspector = new ValueInspector() {\n"
291+
+ " @Override\n"
292+
+ " public void updateNull() {\n");
293+
if (!expectMultipleResults) {
294+
add(" setResult(" + nullResult + ");\n");
295+
} else {
296+
add(" if (" + nullResult + ") { setResult(true); }\n");
297+
}
298+
add(" }\n"
306299
+ "\n"
307-
+ " @Override\n"
308-
+ " public void update("
300+
+ " @Override\n"
301+
+ " public void update("
309302
+ info.primitiveName + " value) {\n");
310303

311304
if (expectMultipleResults) {
312-
add(" if (isKnown()) return;\n");
305+
add(" if (isKnown()) return;\n");
313306
}
314-
add(" for (" + info.primitiveName + " i : target) {\n");
315-
316-
add(" if(" + compareEquality("value", "i", isEq) + ") {\n");
307+
add(" for (" + info.className + " i : target) {\n"
308+
+ " if (i == null) { continue; }\n"
309+
+ " "
310+
+ info.primitiveName + " targetValue = i;\n");
317311

318-
add(" setResult(true);\n return;\n");
312+
add(" if(" + compareEquality("value", "targetValue", true) + ") {\n");
319313

320-
add(" }\n");
314+
if (!expectMultipleResults || isEq) {
315+
add(" setResult(" + isEq + ");\n");
316+
}
317+
add(" return;\n");
321318

322319
add(" }\n");
323-
if (!expectMultipleResults) {
324-
add(" setResult(false);\n");
325-
}
320+
326321
add(" }\n");
322+
if (!expectMultipleResults || !isEq) {
323+
add(" setResult(" + !isEq + ");\n");
324+
}
325+
add(" }\n");
327326

328-
add(" };\n" + " }\n" + " }\n\n");
327+
add(" };\n" + " }\n\n");
329328
}
330329

331330
private void addUdpBegin() throws IOException {

parquet-hadoop/src/test/java/org/apache/parquet/filter2/recordlevel/TestRecordLevelFilters.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@
4444
import java.util.ArrayList;
4545
import java.util.HashSet;
4646
import java.util.Iterator;
47+
import java.util.LinkedHashSet;
4748
import java.util.List;
49+
import java.util.Set;
4850
import java.util.stream.LongStream;
4951
import org.apache.parquet.example.data.Group;
5052
import org.apache.parquet.filter2.compat.FilterCompat;
@@ -156,7 +158,11 @@ private static void assertFilter(List<Group> found, UserFilter f) {
156158
}
157159

158160
private static void assertPredicate(FilterPredicate predicate, long... expectedIds) throws IOException {
159-
List<Group> found = PhoneBookWriter.readFile(phonebookFile, FilterCompat.get(predicate));
161+
assertPredicate(phonebookFile, predicate, expectedIds);
162+
}
163+
164+
private static void assertPredicate(File file, FilterPredicate predicate, long... expectedIds) throws IOException {
165+
List<Group> found = PhoneBookWriter.readFile(file, FilterCompat.get(predicate));
160166

161167
assertEquals(expectedIds.length, found.size());
162168
for (int i = 0; i < expectedIds.length; i++) {
@@ -175,6 +181,35 @@ public boolean keep(User u) {
175181
});
176182
}
177183

184+
@Test
185+
public void testNotInChecksAllValues() throws Exception {
186+
File file = PhoneBookWriter.writeToFile(List.of(
187+
new User(300, "lon-1", null, new Location(1.0, null)),
188+
new User(301, "lon-2", null, new Location(2.0, null)),
189+
new User(302, "lon-3", null, new Location(3.0, null))));
190+
DoubleColumn lon = doubleColumn("location.lon");
191+
192+
Set<Double> values = new LinkedHashSet<>();
193+
values.add(1.0);
194+
values.add(3.0);
195+
assertPredicate(file, notIn(lon, values), 301L);
196+
}
197+
198+
@Test
199+
public void testInAndNotInCheckNullAndNonNullValues() throws Exception {
200+
File file = PhoneBookWriter.writeToFile(List.of(
201+
new User(300, "lon-null", null, new Location(null, null)),
202+
new User(301, "lon-2", null, new Location(2.0, null)),
203+
new User(302, "lon-3", null, new Location(3.0, null))));
204+
DoubleColumn lon = doubleColumn("location.lon");
205+
206+
Set<Double> values = new LinkedHashSet<>();
207+
values.add(null);
208+
values.add(3.0);
209+
assertPredicate(file, in(lon, values), 300L, 302L);
210+
assertPredicate(file, notIn(lon, values), 301L);
211+
}
212+
178213
@Test
179214
public void testAllFilter() throws Exception {
180215
BinaryColumn name = binaryColumn("name");

0 commit comments

Comments
 (0)