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


##########
table/arrow_scanner_posdelete_regression_test.go:
##########
@@ -265,6 +265,27 @@ func 
TestCollectPosDeletePositionsRejectsUnsupportedPosType(t *testing.T) {
        assert.Contains(t, err.Error(), "unsupported pos column type")
 }
 
+func TestCollectPosDeletePositionsRejectsNullPos(t *testing.T) {
+       mem := memory.NewCheckedAllocator(memory.DefaultAllocator)
+       defer mem.AssertSize(t, 0)
+
+       bldr := array.NewInt64Builder(mem)
+       bldr.Append(1)
+       bldr.AppendNull()
+       bldr.Append(2)
+       posArr := bldr.NewInt64Array()
+       bldr.Release()
+       defer posArr.Release()
+
+       posCol := arrow.NewChunked(arrow.PrimitiveTypes.Int64, 
[]arrow.Array{posArr})
+       defer posCol.Release()
+
+       deletes, err := collectPosDeletePositions(positionDeletes{posCol})

Review Comment:
   This calls `collectPosDeletePositions` directly, so it proves the guard in 
isolation but never exercises the actual path through `readDeletes` → 
`groupPosDeletesByFilePath`. That's exactly where the reachability question 
lives, so as written the test stays green even if a null pos gets silently 
dropped upstream.
   
   A test that builds a delete table with a null-pos row and drives it through 
`readDeletes` would lock the end-to-end contract and settle the Filter question 
either way.



##########
table/arrow_scanner.go:
##########
@@ -408,6 +408,10 @@ func collectPosDeletePositions(positionalDeletes 
positionDeletes) (set[int64], e
                                return nil, fmt.Errorf("%w: unsupported pos 
chunk array type %T in position delete file",
                                        iceberg.ErrInvalidSchema, arr)
                        }
+                       if posArr.NullN() > 0 {

Review Comment:
   The guard itself is correct, but I'm not sure it's reachable on the real 
path. By the time we hit `collectPosDeletePositions`, `readDeletes` has already 
pushed `posCol` through `groupPosDeletesByFilePath`, which runs 
`compute.Filter(..., DefaultFilterOptions())` — and I'm genuinely unsure 
whether arrow-go's default `NullSelectionBehavior` preserves a null-pos row 
here or silently drops it before it ever reaches this loop.
   
   Rather than hang correctness on that, I'd hoist the check up into 
`readDeletes` where `posCol` is first extracted, mirroring the 
`filePathCol.NullN() > 0` guard already at line 304. Then it fires before 
Filter regardless of the semantics. wdyt?



##########
table/arrow_scanner_posdelete_regression_test.go:
##########
@@ -265,6 +265,27 @@ func 
TestCollectPosDeletePositionsRejectsUnsupportedPosType(t *testing.T) {
        assert.Contains(t, err.Error(), "unsupported pos column type")
 }
 
+func TestCollectPosDeletePositionsRejectsNullPos(t *testing.T) {
+       mem := memory.NewCheckedAllocator(memory.DefaultAllocator)
+       defer mem.AssertSize(t, 0)
+
+       bldr := array.NewInt64Builder(mem)
+       bldr.Append(1)
+       bldr.AppendNull()
+       bldr.Append(2)
+       posArr := bldr.NewInt64Array()
+       bldr.Release()
+       defer posArr.Release()
+
+       posCol := arrow.NewChunked(arrow.PrimitiveTypes.Int64, 
[]arrow.Array{posArr})
+       defer posCol.Release()
+
+       deletes, err := collectPosDeletePositions(positionDeletes{posCol})
+       require.ErrorIs(t, err, iceberg.ErrInvalidSchema)
+       assert.Nil(t, deletes)
+       assert.Contains(t, err.Error(), "null pos")

Review Comment:
   Minor, but `"null pos"` is short enough that an unrelated future message 
could match it and give a false pass. The sibling assertions all pin a longer 
fragment, so I'd widen this to `"null pos in position delete file"` to match.



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