laskoviymishka commented on code in PR #2016:
URL: https://github.com/apache/iceberg-go/pull/2016#discussion_r4064433630


##########
table/transaction.go:
##########
@@ -1289,24 +1306,11 @@ func (t *Transaction) 
validateDeleteFilesToAdd(deleteFiles []rewriteDeleteFileAd
                }
 
                if IsDeletionVector(df) {

Review Comment:
   The self-guard landed inside `validateDeletionVectorToAdd`, so the helper is 
safe to call unconditionally now, good. That does leave two guards for the same 
predicate though: this outer `if IsDeletionVector(df)` is dead, since the 
`!IsDeletionVector` block above already returns or continues on every non-DV 
path, so we only reach here on a DV.
   
   Not blocking, but I'd drop the outer wrapper and let the helper's own guard 
carry it, then add a one-liner on `validateDeletionVectorToAdd` noting it's 
safe on any DataFile and no-ops on non-DVs. Keeps the precondition visible and 
drops a branch a reader would otherwise read as a real else. Happy either way.



##########
table/row_delta_test.go:
##########
@@ -1108,74 +1108,94 @@ func TestRowDeltaRemoveDeletesFailsInsteadOfReplaying(t 
*testing.T) {
                "the data file must carry exactly one live DV: the peer's")
 }
 
-func buildPuffinPosDeleteWithoutRef(t *testing.T, path string) 
iceberg.DataFile {
-       t.Helper()
-
-       b, err := iceberg.NewDataFileBuilder(*iceberg.UnpartitionedSpec, 
iceberg.EntryContentPosDeletes,
-               path, iceberg.PuffinFile, nil, nil, nil, 2, 128)
-       require.NoError(t, err)
-
-       return b.Build()
-}
-
-func TestRowDeltaRejectsDeletionVectorBelowV3(t *testing.T) {
+func TestRowDeltaRejectsInvalidDeletionVector(t *testing.T) {
        const (
                dataPath = "s3://bucket/data/insert.parquet"
                dvPath   = "s3://bucket/data/dv-001.puffin"
        )
+       offset, length := int64(4), int64(64)
+       negativeOffset, zeroLength := int64(-1), int64(0)
 
        tests := []struct {
                name          string
                formatVersion int
                rows          []iceberg.DataFile
-               deletes       func(*testing.T) []iceberg.DataFile
+               deletes       []iceberg.DataFile
                errContains   string
        }{
                {
                        name:          "deletion vector alone on v2",
                        formatVersion: 2,
-                       deletes: func(t *testing.T) []iceberg.DataFile {
-                               return []iceberg.DataFile{buildDVFile(t, 
dvPath, dataPath)}
-                       },
-                       errContains: "requires table format version >= 3",
+                       deletes:       []iceberg.DataFile{buildDVFile(t, 
dvPath, dataPath)},
+                       errContains:   "requires table format version >= 3",
                },
                {
                        name:          "deletion vector beside valid files on 
v2",
                        formatVersion: 2,
                        rows:          []iceberg.DataFile{buildDataFile(t, 
dataPath)},
-                       deletes: func(t *testing.T) []iceberg.DataFile {
-                               return []iceberg.DataFile{
-                                       buildPosDeleteFile(t, 
"s3://bucket/data/pos-del.parquet"),
-                                       buildEqDeleteFile(t, 
"s3://bucket/data/eq-del.parquet", []int{1}),
-                                       buildDVFile(t, dvPath, dataPath),
-                               }
+                       deletes: []iceberg.DataFile{
+                               buildPosDeleteFile(t, 
"s3://bucket/data/pos-del.parquet"),
+                               buildEqDeleteFile(t, 
"s3://bucket/data/eq-del.parquet", []int{1}),
+                               buildDVFile(t, dvPath, dataPath),
                        },
                        errContains: "requires table format version >= 3",
                },
                {
-                       name:          "deletion vector without referenced data 
file on v2",
+                       name:          "deletion vector missing ref still fails 
on format version for v2",

Review Comment:
   Small wording thing, non-blocking: this DV is missing ref, offset, and size, 
but the case name singles out the ref. What it actually proves is that the v2 
format-version check fires before any field check, so something like `format 
version check precedes field checks on v2` would read truer to intent.



##########
table/row_lineage_prune_delete_test.go:
##########
@@ -255,6 +252,28 @@ func buildTwoRowGroupV3Table(t *testing.T) *table.Table {
        return tbl
 }
 
+// commitLegacyPosDelete adds posDel while tbl is still v2, then upgrades it 
to v3.
+// The no-op Delete creates a v3 snapshot, which gives the existing rows a 
_row_id.

Review Comment:
   Optional: the comment says what this does, but the load-bearing bit is 
implicit. It leans on `Delete(AlwaysFalse)` still forcing a snapshot rewrite so 
the upgraded rows pick up a `_row_id`. The `require.NotNil(FirstRowID)` below 
would catch a regression, so it's not silently fragile, but a clause noting the 
no-op Delete has to stay a rewrite-triggering op would save a future reader 
from an empty-filter short-circuit quietly gutting this setup.



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