zeroshade commented on PR #1648:
URL: https://github.com/apache/iceberg-go/pull/1648#issuecomment-5219738561

   Re-reviewed after `95a0d56` and `1efe8e2`. These pick up six of the seven 
notes from my last pass, and several of them go further than I asked — seeding 
the fixture with the previously-absent optional fields is a better fix for the 
vacuous-v1 problem than the guard assertions I suggested, and overriding 
`last-partition-id` to 1001 rather than deleting it tests replacement instead 
of just absence. Thanks for working through all of them.
   
   For the record, what landed:
   
   - `ParseMetadataBytes` now builds `&metadataV1{}` / `&metadataV2{}` / 
`&metadataV3{}` (`table/metadata.go:1514-1518`).
   - The three dead `aux.LastColumnId = -1` assignments are gone, with the 
explanation moved to `initCommonMetadataForDeserialization` 
(`table/metadata.go:1662`) where the value originates.
   - The delete-list gained `statistics`, `partition-statistics`, 
`encryption-keys`, and `last-sequence-number`.
   - Failure-path coverage is table-driven across all three versions.
   - The failure-path assertion is now a `json.Marshal` before/after byte 
comparison.
   
   Two things I found this round, both cheap, and then one wording item that is 
still outstanding.
   
   **1. `TestMetadataUnmarshalPreservesStateOnError/v1` does not currently 
guard anything.**
   
   I checked this by reverting all three `UnmarshalJSON`s to decode into the 
receiver via `aux := (*Alias)(m)`. The v2 and v3 subtests fail, as they should. 
The v1 subtest passes.
   
   The reason is that the invalid v1 document differs from the valid one only 
inside `"schema"`, and the error it raises — `invalid schema: multiple fields 
for id 1: x and y` — comes out of `json.Unmarshal` itself. Every field the 
decoder writes before reaching that point is byte-identical to what the 
receiver already holds, so `before == after` whether or not the fix is present.
   
   This matters because v1 is the version with the largest partial-mutation 
surface: `metadataV1.preValidate` (`table/metadata.go:2432-2464`) mutates 
`SchemaList`, `Specs`, `DefaultSpecID`, `LastPartitionID`, and `SortOrderList` 
before validation runs.
   
   The fix is to perturb a top-level scalar so a partial write is observable. I 
verified two candidates — both fail with the fix reverted and pass with it in 
place:
   
   - `"current-snapshot-id": -1` → `999`, which fails with `invalid metadata: 
snapshot ref main with ID 999 does not exist in snapshot list`. This is the 
direct parallel to what the v2 and v3 subtests already do.
   - `"last-column-id": 3` → `-5`, which fails with `invalid metadata: missing 
last-column-id`.
   
   Either works; the first keeps the three subtests symmetric.
   
   **2. The new `assert.Equal(t, int64(-1), metadata.LastSeqNum)` pins a 
pre-existing bug as expected behavior.**
   
   I raised this leak last time as non-blocking, and it is genuinely 
pre-existing rather than anything this PR introduces — I confirmed that on 
`main`. But it is now asserted, which changes its status: a future fix to the 
sentinel normalization will break this line and read as a regression.
   
   To be concrete about what is being pinned: for a v2 document that omits 
`last-sequence-number` and has no snapshots, `checkLastSequenceNumber` 
(`table/metadata.go:2709`) only iterates the snapshot list, so with zero 
snapshots nothing checks it. On `main` today, `ParseMetadataBytes` on such a 
document returns successfully, `LastSequenceNumber()` reports `-1`, and 
re-serializing emits `"last-sequence-number": -1` — an invalid v2 document, 
through the public API.
   
   A short comment on the assertion noting that `-1` is the un-normalized 
sentinel and not the desired end state would be enough. Happy to file the 
underlying issue separately.
   
   **3. Still outstanding from last time: the description.**
   
   `ccc5e4e` has no commit body, so the wording lives only in the PR 
description, which still reads "Existing version-specific defaults and 
sentinels are preserved". They are now applied *unconditionally*, which makes 
direct `UnmarshalJSON` strictly more rejecting — `default-spec-id` becomes 
required for v2 and `next-row-id` for v3, matching what `ParseMetadataBytes` 
already enforced. That is the right behavior and unobservable externally since 
`metadataV{1,2,3}` are unexported, but it is a tightening rather than a 
preservation, and the description is what carries into the record on squash.
   
   Nothing here touches the production change, which I verified last pass and 
which is unchanged. On my side: `go test ./table/... ./ -count=1` green, `gofmt 
-l table/` and `go vet ./table/...` clean, all 15 CI checks passing.
   
   Happy to approve once the v1 fixture is swapped and the description is 
updated.
   


-- 
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