Skip to content

Commit e45606f

Browse files
committed
Add next-row-id default and Spark integration test
1 parent bc64319 commit e45606f

3 files changed

Lines changed: 39 additions & 0 deletions

File tree

‎pyiceberg/table/metadata.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464

6565
INITIAL_SEQUENCE_NUMBER = 0
6666
INITIAL_SPEC_ID = 0
67+
INITIAL_ROW_ID = 0
6768
DEFAULT_SCHEMA_ID = 0
6869

6970
SUPPORTED_TABLE_FORMAT_VERSION = 2
@@ -652,6 +653,7 @@ def new_table_metadata(
652653
properties=properties,
653654
last_partition_id=fresh_partition_spec.last_assigned_field_id,
654655
table_uuid=table_uuid,
656+
next_row_id=INITIAL_ROW_ID,
655657
)
656658
else:
657659
raise ValidationError(f"Unknown format version: {format_version}")

‎tests/integration/test_writes/test_writes.py‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2386,6 +2386,28 @@ def test_nanosecond_support_on_catalog(
23862386
)
23872387

23882388

2389+
@pytest.mark.integration
2390+
def test_spark_reads_v3_table_metadata_written_by_pyiceberg(spark: SparkSession, session_catalog_hive: Catalog) -> None:
2391+
"""Spark should be able to load a V3 table whose metadata file PyIceberg wrote.
2392+
2393+
The Hive catalog is used rather than REST because REST has the server build the metadata,
2394+
which would leave PyIceberg's serialization untested. Rows cannot be written to a V3 table
2395+
yet (`_manifest_writer` rejects version 3), so this covers the metadata itself.
2396+
"""
2397+
identifier = "default.test_spark_reads_v3_table_metadata_written_by_pyiceberg"
2398+
tbl = _create_table(session_catalog_hive, identifier, {"format-version": "3"})
2399+
2400+
assert tbl.metadata.format_version == 3
2401+
assert tbl.metadata.next_row_id == 0
2402+
2403+
properties = {row.key: row.value for row in spark.sql(f"SHOW TBLPROPERTIES hive.{identifier}").collect()}
2404+
assert properties["format-version"] == "3"
2405+
2406+
df = spark.table(f"hive.{identifier}")
2407+
assert df.count() == 0
2408+
assert df.columns == [field.name for field in tbl.schema().fields]
2409+
2410+
23892411
@pytest.mark.integration
23902412
@pytest.mark.parametrize("format_version", [1, 2])
23912413
def test_stage_only_delete(

‎tests/table/test_metadata.py‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,7 @@ def test_new_table_metadata_with_v3_schema() -> None:
840840
default_sort_order_id=1,
841841
refs={},
842842
format_version=3,
843+
next_row_id=0,
843844
)
844845

845846
assert actual.model_dump() == expected.model_dump()
@@ -848,6 +849,20 @@ def test_new_table_metadata_with_v3_schema() -> None:
848849
assert actual.sort_orders == [expected_sort_order]
849850

850851

852+
def test_new_table_metadata_v3_initializes_next_row_id() -> None:
853+
"""`next-row-id` is required in V3, so a new table has to start it at 0 rather than leave it unset."""
854+
actual = new_table_metadata(
855+
schema=Schema(NestedField(field_id=1, name="foo", field_type=StringType(), required=False)),
856+
partition_spec=PartitionSpec(),
857+
sort_order=SortOrder(),
858+
location="s3://some_v3_location/",
859+
properties={"format-version": "3"},
860+
)
861+
862+
assert actual.next_row_id == 0
863+
assert json.loads(actual.model_dump_json())["next-row-id"] == 0
864+
865+
851866
@pytest.mark.parametrize(
852867
"field_type",
853868
[

0 commit comments

Comments
 (0)