This is an automated email from the ASF dual-hosted git repository.
JingsongLi 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 c44b9e7df0 [common] Fix duplicate file index predicate traversal
(#8338)
c44b9e7df0 is described below
commit c44b9e7df0c7e4e6669087caedd8609b16f7d8a4
Author: hutiefang76 <[email protected]>
AuthorDate: Wed Jun 24 09:13:21 2026 +0800
[common] Fix duplicate file index predicate traversal (#8338)
---
.../paimon/fileindex/FileIndexPredicate.java | 20 +----
.../paimon/fileindex/FileIndexPredicateTest.java | 92 ++++++++++++++++++++++
2 files changed, 93 insertions(+), 19 deletions(-)
diff --git
a/paimon-common/src/main/java/org/apache/paimon/fileindex/FileIndexPredicate.java
b/paimon-common/src/main/java/org/apache/paimon/fileindex/FileIndexPredicate.java
index 0ad3238a4c..1cd4a8b01c 100644
---
a/paimon-common/src/main/java/org/apache/paimon/fileindex/FileIndexPredicate.java
+++
b/paimon-common/src/main/java/org/apache/paimon/fileindex/FileIndexPredicate.java
@@ -42,7 +42,6 @@ import java.io.Closeable;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -115,24 +114,7 @@ public class FileIndexPredicate implements Closeable {
}
private Set<String> getRequiredNames(Predicate filePredicate) {
- return filePredicate.visit(
- new PredicateVisitor<Set<String>>() {
-
- @Override
- public Set<String> visit(LeafPredicate predicate) {
- return new HashSet<>(predicate.fieldNames());
- }
-
- @Override
- public Set<String> visit(CompoundPredicate predicate) {
- Set<String> result = new HashSet<>();
- for (Predicate child : predicate.children()) {
- child.visit(this);
- result.addAll(child.visit(this));
- }
- return result;
- }
- });
+ return PredicateVisitor.collectFieldNames(filePredicate);
}
@Override
diff --git
a/paimon-common/src/test/java/org/apache/paimon/fileindex/FileIndexPredicateTest.java
b/paimon-common/src/test/java/org/apache/paimon/fileindex/FileIndexPredicateTest.java
new file mode 100644
index 0000000000..e2d4d7b578
--- /dev/null
+++
b/paimon-common/src/test/java/org/apache/paimon/fileindex/FileIndexPredicateTest.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.paimon.fileindex;
+
+import org.apache.paimon.predicate.CompoundPredicate;
+import org.apache.paimon.predicate.Equal;
+import org.apache.paimon.predicate.LeafPredicate;
+import org.apache.paimon.predicate.Or;
+import org.apache.paimon.predicate.Predicate;
+import org.apache.paimon.predicate.PredicateVisitor;
+import org.apache.paimon.types.DataTypes;
+import org.apache.paimon.types.RowType;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Set;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/** Test for {@link FileIndexPredicate}. */
+public class FileIndexPredicateTest {
+
+ @Test
+ public void testGetRequiredNamesVisitsEachChildOnce() throws Exception {
+ CountingLeafPredicate left = new CountingLeafPredicate(0, "a");
+ CountingLeafPredicate right = new CountingLeafPredicate(1, "b");
+ Predicate predicate = new CompoundPredicate(Or.INSTANCE,
Arrays.asList(left, right));
+
+ Set<String> requiredNames = getRequiredNames(predicate);
+
+ assertThat(requiredNames).containsExactlyInAnyOrder("a", "b");
+ assertThat(left.visitCount).isEqualTo(1);
+ assertThat(right.visitCount).isEqualTo(1);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Set<String> getRequiredNames(Predicate predicate) throws
Exception {
+ Method method =
+ FileIndexPredicate.class.getDeclaredMethod("getRequiredNames",
Predicate.class);
+ method.setAccessible(true);
+ return (Set<String>) method.invoke(emptyFileIndexPredicate(),
predicate);
+ }
+
+ private static FileIndexPredicate emptyFileIndexPredicate() throws
Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ FileIndexFormat.Writer writer = FileIndexFormat.createWriter(baos);
+ writer.writeColumnIndexes(new HashMap<String, java.util.Map<String,
byte[]>>());
+ writer.close();
+ return new FileIndexPredicate(baos.toByteArray(),
RowType.builder().build());
+ }
+
+ private static class CountingLeafPredicate extends LeafPredicate {
+
+ private int visitCount;
+
+ private CountingLeafPredicate(int fieldIndex, String fieldName) {
+ super(
+ Equal.INSTANCE,
+ DataTypes.INT(),
+ fieldIndex,
+ fieldName,
+ Collections.singletonList(1));
+ }
+
+ @Override
+ public <T> T visit(PredicateVisitor<T> visitor) {
+ visitCount++;
+ return super.visit(visitor);
+ }
+ }
+}