bvolpato opened a new pull request, #15966:
URL: https://github.com/apache/iceberg/pull/15966

   ## Summary
   
   Adds a failing test that documents a correctness bug introduced by partition 
pruning in the DV validation path added in #15653 (79d4fc82c).
   
   `MergingSnapshotProducer.validateAddedDVs()` now projects the user-supplied 
`conflictDetectionFilter` onto each concurrent delete manifest's partition spec 
and drops manifests whose partition range doesn't match. The filter is 
caller-supplied (for Spark, `SparkPositionDeltaWrite.conflictDetectionFilter` 
derives it from `queryScan.filterExpressions()`, i.e. the query's WHERE clause) 
and is not required to cover every partition the current commit writes DVs into.
   
   When a commit writes DVs across multiple partitions but supplies a filter 
that only names a subset of them, a concurrent delete manifest holding a DV for 
one of the un-filtered partitions can be pruned out before the per-manifest 
conflict scan ever runs. `dvsByReferencedFile.containsKey(...)` is never 
checked against that manifest's entries, no conflict is raised, and the commit 
goes through.
   
   The resulting table state has two DVs that reference the same data file. Any 
subsequent scan then fails in `DeleteFileIndex.Builder.add`:
   
   ```java
   // core/src/main/java/org/apache/iceberg/DeleteFileIndex.java:528-536
   private void add(Map<String, DeleteFile> dvByPath, DeleteFile dv) {
     String path = dv.referencedDataFile();
     DeleteFile existingDV = dvByPath.putIfAbsent(path, dv);
     if (existingDV != null) {
       throw new ValidationException(
           \"Can't index multiple DVs for %s: %s and %s\",
           path, ContentFileUtil.dvDesc(dv), 
ContentFileUtil.dvDesc(existingDV));
     }
   }
   ```
   
   Every read, DML, and maintenance task on the affected file blows up, so the 
table is effectively bricked until the duplicate DVs are manually resolved.
   
   ## Reproducer
   
   The added test \`testConcurrentDVsMultiPartitionNarrowFilter\` sets up:
   
   1. Table partitioned by \`bucket[16](data)\`, seeded with two data files: 
\`F_P0\` in bucket 0, \`F_P2\` in bucket 2.
   2. Writer A builds a \`RowDelta\` that adds DVs for both \`F_P0\` and 
\`F_P2\`, with \`conflictDetectionFilter = data = 'u'\` (projects to 
\`bucket(data) = 0\`).
   3. Writer B concurrently commits a DV for \`F_P2\`.
   4. Writer A calls \`commit()\` and must throw \`Found concurrently added DV 
for ...F_P2...\`.
   
   On current main this commit returns normally, so \`assertThatThrownBy\` 
fails with \`Expecting code to raise a throwable\`. Ran locally against 
\`56092bc8c\` with JDK 21:
   
   \`\`\`
   TestRowDelta > testConcurrentDVsMultiPartitionNarrowFilter() > formatVersion 
= 3, branch = main FAILED
   TestRowDelta > testConcurrentDVsMultiPartitionNarrowFilter() > formatVersion 
= 3, branch = testBranch FAILED
   TestRowDelta > testConcurrentDVsMultiPartitionNarrowFilter() > formatVersion 
= 4, branch = main FAILED
   TestRowDelta > testConcurrentDVsMultiPartitionNarrowFilter() > formatVersion 
= 4, branch = testBranch FAILED
   6 tests completed, 4 failed, 2 skipped
   \`\`\`
   
   Also verified the corruption consequence locally with a follow-on assertion 
(not included in this PR to keep the test direction clean): after the buggy 
commit returns, \`table.newBatchScan().useRef(branch).planFiles()\` throws 
\`ValidationException: Can't index multiple DVs for ...F_P2...\`, confirming 
the state is unreadable.
   
   ## Test gap in #15653
   
   The three DV validation tests added in #15653 all treat the conflict filter 
and the current commit's DV set as partition-aligned:
   
   - \`testConcurrentDVsInDifferentPartitionsWithFilter\` — Writer A's DV is 
entirely in bucket 0; concurrent DV is in bucket 2. Correct outcome: A wins.
   - \`testConcurrentDVsInSamePartitionWithFilter\` — Writer A's DV and 
concurrent DV both in bucket 0. Correct outcome: A fails.
   - \`testDVValidationPartitionPruningManifestCount\` — micro-test of the 
pruning arithmetic.
   
   None of them cross the current commit's \`dvsByReferencedFile\` partition 
set against the pruning filter, which is where the bug lives.
   
   ## Scope
   
   This PR contains **only** the failing reproducer. It is intentionally draft 
and CI is expected to fail on \`:iceberg-core:test\` until a fix lands. A 
separate PR will propose the fix — probable direction is to widen the pruning 
filter so it covers both the user filter and the union of partitions referenced 
by \`dvsByReferencedFile\`, or to drop the pruning entirely (the pre-#15653 
behavior). Happy to take direction from maintainers on which approach they 
prefer before the fix PR.
   
   ## Test plan
   
   - [x] Reproducer test fails deterministically on current \`main\` 
(\`56092bc8c\`) for format versions 3 and 4, on both \`main\` and non-main 
branches.
   - [ ] Fix to be proposed in a follow-up PR; same test must pass after the 
fix.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to