This is an automated email from the ASF dual-hosted git repository.

laskoviymishka pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-rust.git


The following commit(s) were added to refs/heads/main by this push:
     new d05d56645 fix: mark _row_id and _last_updated_sequence_number optional 
(#2959)
d05d56645 is described below

commit d05d56645979804c659aa265f6041d93ea0e6557
Author: Anoop Johnson <[email protected]>
AuthorDate: Wed Aug 5 01:27:41 2026 -0700

    fix: mark _row_id and _last_updated_sequence_number optional (#2959)
    
    The two v3 row-lineage metadata columns were defined as required, but the
    spec requires readers to produce null for both in legitimate cases: when a
    data file has a null first_row_id (spec Row Lineage), and for added or
    modified rows before inheritance. Iceberg Java marks both
    NestedField.optional accordingly.
    
    Mark both fields optional to match. This is a prerequisite for
    materializing the columns on read, where a null result must be
    representable.
---
 crates/iceberg/src/metadata_columns.rs | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/crates/iceberg/src/metadata_columns.rs 
b/crates/iceberg/src/metadata_columns.rs
index d95b075be..aed418325 100644
--- a/crates/iceberg/src/metadata_columns.rs
+++ b/crates/iceberg/src/metadata_columns.rs
@@ -224,7 +224,7 @@ static COMMIT_SNAPSHOT_ID_FIELD: Lazy<NestedFieldRef> = 
Lazy::new(|| {
 /// This field represents a unique long assigned for row lineage.
 static ROW_ID_FIELD: Lazy<NestedFieldRef> = Lazy::new(|| {
     Arc::new(
-        NestedField::required(
+        NestedField::optional(
             RESERVED_FIELD_ID_ROW_ID,
             RESERVED_COL_NAME_ROW_ID,
             Type::Primitive(PrimitiveType::Long),
@@ -237,7 +237,7 @@ static ROW_ID_FIELD: Lazy<NestedFieldRef> = Lazy::new(|| {
 /// This field represents the sequence number which last updated this row.
 static LAST_UPDATED_SEQUENCE_NUMBER_FIELD: Lazy<NestedFieldRef> = Lazy::new(|| 
{
     Arc::new(
-        NestedField::required(
+        NestedField::optional(
             RESERVED_FIELD_ID_LAST_UPDATED_SEQUENCE_NUMBER,
             RESERVED_COL_NAME_LAST_UPDATED_SEQUENCE_NUMBER,
             Type::Primitive(PrimitiveType::Long),
@@ -601,6 +601,15 @@ mod tests {
         
assert!(get_metadata_field(RESERVED_FIELD_ID_LAST_UPDATED_SEQUENCE_NUMBER).is_ok());
     }
 
+    #[test]
+    fn test_row_lineage_metadata_fields_are_optional() {
+        // The spec requires readers to produce null for these columns in
+        // legitimate cases (e.g. a data file with a null first_row_id), so the
+        // fields must be optional rather than required.
+        assert!(!row_id_field().required);
+        assert!(!last_updated_sequence_number_field().required);
+    }
+
     #[test]
     fn test_data_table_metadata_columns() {
         // Both sides of the data-table metadata check (name and field id) 
must accept

Reply via email to