diff --git a/crates/iceberg/src/spec/table_metadata.rs b/crates/iceberg/src/spec/table_metadata.rs index 38204fc154..94f1191b26 100644 --- a/crates/iceberg/src/spec/table_metadata.rs +++ b/crates/iceberg/src/spec/table_metadata.rs @@ -425,6 +425,22 @@ impl TableMetadata { .insert(snapshot.snapshot_id(), Arc::new(snapshot)); } + fn construct_refs(&mut self) { + if let Some(current_snapshot_id) = self.current_snapshot_id { + if !self.refs.contains_key(MAIN_BRANCH) { + self.refs + .insert(MAIN_BRANCH.to_string(), SnapshotReference { + snapshot_id: current_snapshot_id, + retention: SnapshotRetention::Branch { + min_snapshots_to_keep: None, + max_snapshot_age_ms: None, + max_ref_age_ms: None, + }, + }); + } + } + } + /// Normalize this partition spec. /// /// This is an internal method @@ -435,6 +451,7 @@ impl TableMetadata { pub(super) fn try_normalize(&mut self) -> Result<&mut Self> { self.validate_current_schema()?; self.normalize_current_snapshot()?; + self.construct_refs(); self.validate_refs()?; self.validate_chronological_snapshot_logs()?; self.validate_chronological_metadata_logs()?; diff --git a/crates/iceberg/src/spec/table_metadata_builder.rs b/crates/iceberg/src/spec/table_metadata_builder.rs index 26ee52b53e..68ed76987b 100644 --- a/crates/iceberg/src/spec/table_metadata_builder.rs +++ b/crates/iceberg/src/spec/table_metadata_builder.rs @@ -1220,14 +1220,19 @@ impl From for TableMetadata { #[cfg(test)] mod tests { + use std::fs::File; + use std::io::BufReader; use std::thread::sleep; use super::*; + use crate::io::FileIOBuilder; use crate::spec::{ BlobMetadata, NestedField, NullOrder, Operation, PartitionSpec, PrimitiveType, Schema, SnapshotRetention, SortDirection, SortField, StructType, Summary, Transform, Type, UnboundPartitionField, }; + use crate::table::Table; + use crate::TableIdent; const TEST_LOCATION: &str = "s3://bucket/test/location"; const LAST_ASSIGNED_COLUMN_ID: i32 = 3; @@ -2381,4 +2386,30 @@ mod tests { last_updated_ms ); } + + #[test] + fn test_construct_default_main_branch() { + // Load the table without ref + let file = File::open(format!( + "{}/testdata/table_metadata/{}", + env!("CARGO_MANIFEST_DIR"), + "TableMetadataV2Valid.json" + )) + .unwrap(); + let reader = BufReader::new(file); + let resp = serde_json::from_reader::<_, TableMetadata>(reader).unwrap(); + + let table = Table::builder() + .metadata(resp) + .metadata_location("s3://bucket/test/location/metadata/v1.json".to_string()) + .identifier(TableIdent::from_strs(["ns1", "test1"]).unwrap()) + .file_io(FileIOBuilder::new("memory").build().unwrap()) + .build() + .unwrap(); + + assert_eq!( + table.metadata().refs.get(MAIN_BRANCH).unwrap().snapshot_id, + table.metadata().current_snapshot_id().unwrap() + ); + } }