mzzz-zzm commented on issue #977:
URL: https://github.com/apache/iceberg-go/issues/977#issuecomment-4369969986
## Suggested fix
When `newConflictContext` is called with a `base` that has no snapshot on
the target branch (`base.SnapshotByName(branch) == nil`), the function returned
an empty `concurrent` list. The fix below uses `AncestorsOf` to populate
`concurrent` with all snapshots currently on the branch — those are all commits
that happened after the writer loaded the (then-empty) table, and they must be
inspected by validators.
This change touches **one function in one file** and is independent of the
manifest list rebuild fix and the RowDelta partition filter fix.
## File changed
`table/conflict_validation.go` — `newConflictContext()`
## Diff
```diff
baseHead := base.SnapshotByName(branch)
if baseHead == nil {
- // Writer has no view of this branch yet (e.g. creating it) —
- // by definition there are no concurrent commits to validate
- // against.
- return &conflictContext{current: current, branch: branch, fs: fs,
caseSensitive: caseSensitive}, nil
+ // Writer started from a table that had no snapshot on this branch
+ // (empty table, or branch not yet created by the writer). All
+ // snapshots now present on the branch were committed concurrently
+ // and must be examined by validators that care about concurrent
+ // writes (e.g. RowDelta with equality deletes under SERIALIZABLE).
+ // Fast-append validators safely short-circuit on non-empty
+ // concurrent lists, so this does not regress the common path.
+ allConcurrent := AncestorsOf(currentHead.SnapshotID,
current.SnapshotByID)
+ return &conflictContext{
+ current: current,
+ branch: branch,
+ fs: fs,
+ caseSensitive: caseSensitive,
+ concurrent: allConcurrent,
+ }, nil
}
```
## Why this is safe for fast-append
Fast-append and merge-append producers do not register a validator (their
`producerImpl.validate` is a no-op). A non-empty `concurrent` list is walked
only when a validator calls `forEachAddedEntry` or
`validateNoConflictingDataFiles`. Writers that do not register validators pay
only the cost of the `AncestorsOf` walk (proportional to the number of
snapshots on the branch) with no change in commit acceptance behaviour.
## Existing test that encodes the old (wrong) behaviour
`TestNewConflictContext_WriterHasNoBranchView` in
`table/conflict_validation_test.go` currently asserts `assert.Empty(t,
ctx.concurrent)`. That assertion must be updated to reflect the correct
behaviour:
```diff
-assert.Empty(t, ctx.concurrent)
+assert.Len(t, ctx.concurrent, 1)
+assert.Equal(t, int64(7), ctx.concurrent[0].SnapshotID)
```
## Test
Run the reproducer from the bug report:
```
go test ./table/ -run TestBugRepro_EmptyTableConflictDetectionBypassed -v
```
Expected after this fix:
```
--- PASS: TestBugRepro_EmptyTableConflictDetectionBypassed (0.00s)
```
--
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]