tanmayrauth commented on code in PR #1762:
URL: https://github.com/apache/iceberg-go/pull/1762#discussion_r3763682824


##########
manifest.go:
##########
@@ -999,17 +999,66 @@ func ReadManifest(m ManifestFile, f io.Reader, 
discardDeleted bool) ([]ManifestE
        return results, nil
 }
 
+// Manifest-list entry field IDs used to infer the format version from an
+// embedded writer schema. Per the Iceberg spec, content and sequence_number
+// are required fields for v2+ manifest lists and first_row_id is a v3 field;
+// none of them exist in v1.
+const (
+       fieldIDManifestSequenceNumber = 515
+       fieldIDManifestContent        = 517
+       fieldIDManifestFirstRowID     = 520
+)
+
+// schemaFieldID returns the Iceberg "field-id" property of an Avro schema
+// field, if present. Props hold decoded JSON, so numbers arrive as float64.
+func schemaFieldID(f avro.SchemaField) (int, bool) {
+       if id, ok := f.Props["field-id"].(float64); ok {

Review Comment:
   The name fallback here answers the open question from the issue (writers 
that don't annotate ids), and it's the right call to keep since DuckDB does 
embed  them, so it's just belt-and-suspenders. One robustness gap though: this 
only accepts `float64`, while the existing field-id reader in this same file  
(`manifest.go:476`, `switch v := field.Props["field-id"].(type)`) handles both 
`int` and `float64`. For the read path here the writer schema is JSON-parsed 
from the OCF header, so numbers come through as `float64` and the DuckDB 
fixture proves it works — no live bug. But the two field-id readers now 
disagree on accepted types, and that sibling `int` case exists because an 
in-memory-built schema yields `int` props. If inference is ever handed such a 
schema, `schemaFieldID` returns false and silently degrades to name-matching, 
and a writer that annotates only field-ids (non-spec names) then misfires back 
to the v1 fallback this PR removes.  Worth mirroring the sibling type switch 
 to accept `int` too — ideally one shared helper both sites call so they can't 
drift again.



##########
manifest.go:
##########
@@ -1023,6 +1072,10 @@ func ReadManifestList(in io.Reader) ([]ManifestFile, 
error) {
                }
 
                if version == 1 {

Review Comment:
   This only half-satisfies the "key present must agree with the schema, error 
beats zeroed values" rule from the issue. It catches a key claiming v1 over a 
v2+ schema, but not a key claiming a *lower v2+* version than the schema 
carries: a file with key="2" but a v3 schema (first_row_id present, inferred 3) 
reads with version=2 and no error. first_row_id is read into the struct, but 
Version() reports 2, so a read-modify-rewrite through WriteManifestList(2, …) 
uses the v2 writer schema and silently drops v3 row lineage — the same 
corruption this PR fixes, one version up. No real writer emits a key that 
undershoots its schema today (DuckDB omits the key; Java/Py write consistent 
keys), so it's adversarial rather than a field bug — but it's cheap to close 
the whole class: generalize the check to `if version < inferred { return error 
}`, and add a key=2/schema=v3 case to  TestReadManifestListKeyContradictsSchema.



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