This is an automated email from the ASF dual-hosted git repository.

szehon-ho pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg.git


The following commit(s) were added to refs/heads/main by this push:
     new 25cc463c0d Core: Preserve manifest content pruning when ignoring 
residuals (#17443)
25cc463c0d is described below

commit 25cc463c0d2108db6a9427b7f8e2b191f7913061
Author: yangshangqing <[email protected]>
AuthorDate: Fri Jul 31 13:44:19 2026 -0400

    Core: Preserve manifest content pruning when ignoring residuals (#17443)
---
 .../java/org/apache/iceberg/BaseEntriesTable.java  |  7 +++--
 .../apache/iceberg/TestEntriesMetadataTable.java   | 35 ++++++++++++++++++++++
 2 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/core/src/main/java/org/apache/iceberg/BaseEntriesTable.java 
b/core/src/main/java/org/apache/iceberg/BaseEntriesTable.java
index 1d125a9119..a4ee6eec32 100644
--- a/core/src/main/java/org/apache/iceberg/BaseEntriesTable.java
+++ b/core/src/main/java/org/apache/iceberg/BaseEntriesTable.java
@@ -71,7 +71,6 @@ abstract class BaseEntriesTable extends BaseMetadataTable {
     Expression rowFilter = context.rowFilter();
     boolean caseSensitive = context.caseSensitive();
     boolean ignoreResiduals = context.ignoreResiduals();
-    Expression filter = ignoreResiduals ? Expressions.alwaysTrue() : rowFilter;
 
     LoadingCache<Integer, ManifestEvaluator> evalCache =
         Caffeine.newBuilder()
@@ -82,7 +81,7 @@ abstract class BaseEntriesTable extends BaseMetadataTable {
                   return ManifestEvaluator.forRowFilter(rowFilter, 
transformedSpec, caseSensitive);
                 });
     ManifestContentEvaluator manifestContentEvaluator =
-        new ManifestContentEvaluator(filter, tableSchema.asStruct(), 
caseSensitive);
+        new ManifestContentEvaluator(rowFilter, tableSchema.asStruct(), 
caseSensitive);
 
     CloseableIterable<ManifestFile> filteredManifests =
         CloseableIterable.filter(
@@ -91,9 +90,11 @@ abstract class BaseEntriesTable extends BaseMetadataTable {
                 evalCache.get(manifest.partitionSpecId()).eval(manifest)
                     && manifestContentEvaluator.eval(manifest));
 
+    Expression residual = ignoreResiduals ? Expressions.alwaysTrue() : 
rowFilter;
+
     return CloseableIterable.transform(
         filteredManifests,
-        manifest -> new ManifestReadTask(table, manifest, projectedSchema, 
filter));
+        manifest -> new ManifestReadTask(table, manifest, projectedSchema, 
residual));
   }
 
   /**
diff --git 
a/core/src/test/java/org/apache/iceberg/TestEntriesMetadataTable.java 
b/core/src/test/java/org/apache/iceberg/TestEntriesMetadataTable.java
index 25e138f962..f80f29256d 100644
--- a/core/src/test/java/org/apache/iceberg/TestEntriesMetadataTable.java
+++ b/core/src/test/java/org/apache/iceberg/TestEntriesMetadataTable.java
@@ -22,6 +22,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assumptions.assumeThat;
 
 import java.util.List;
+import org.apache.iceberg.expressions.Expressions;
 import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
 import org.apache.iceberg.relocated.com.google.common.collect.Iterables;
 import org.apache.iceberg.types.TypeUtil;
@@ -152,4 +153,38 @@ public class TestEntriesMetadataTable extends TestBase {
         .as("Should contain 1 delete file record")
         .isEqualTo(1);
   }
+
+  @TestTemplate
+  public void testIgnoreResidualsPreservesManifestContentPruning() {
+    assumeThat(formatVersion).as("Only V2 Tables Support 
Deletes").isGreaterThanOrEqualTo(2);
+
+    table.newAppend().appendFile(FILE_A).appendFile(FILE_B).commit();
+    table.newRowDelta().addDeletes(fileADeletes()).commit();
+
+    String dataManifestPath = 
table.currentSnapshot().dataManifests(table.io()).get(0).path();
+    String deleteManifestPath = 
table.currentSnapshot().deleteManifests(table.io()).get(0).path();
+
+    List<Table> entriesTables =
+        ImmutableList.of(new ManifestEntriesTable(table), new 
AllEntriesTable(table));
+
+    for (Table entriesTable : entriesTables) {
+      TableScan scan =
+          entriesTable
+              .newScan()
+              .filter(Expressions.equal("data_file.content", 
FileContent.POSITION_DELETES.id()))
+              .ignoreResiduals();
+
+      List<FileScanTask> tasks = ImmutableList.copyOf(scan.planFiles());
+
+      assertThat(tasks)
+          .as("Should retain manifest content pruning for %s", 
entriesTable.name())
+          .extracting(task -> task.file().location())
+          .contains(deleteManifestPath)
+          .doesNotContain(dataManifestPath);
+
+      assertThat(tasks)
+          .as("Should ignore residuals for %s", entriesTable.name())
+          .allSatisfy(task -> 
assertThat(task.residual()).isEqualTo(Expressions.alwaysTrue()));
+    }
+  }
 }

Reply via email to