Skip to content

Commit 7e7d340

Browse files
authored
fix(table): preserve explicit snapshot ID zero in scans (#3998)
Distinguish snapshot ID zero from an omitted ID when selecting a scan snapshot and rejecting ref overrides.
1 parent 1302751 commit 7e7d340

2 files changed

Lines changed: 27 additions & 2 deletions

File tree

pyiceberg/table/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2191,7 +2191,7 @@ def __init__(
21912191
self.table_config = table_config
21922192

21932193
def snapshot(self) -> Snapshot | None:
2194-
if self.snapshot_id:
2194+
if self.snapshot_id is not None:
21952195
return self.table_metadata.snapshot_by_id(self.snapshot_id)
21962196
return self.table_metadata.current_snapshot()
21972197

@@ -2216,7 +2216,7 @@ def projection(self) -> Schema:
22162216
return current_schema.select(*self.selected_fields, case_sensitive=self.case_sensitive)
22172217

22182218
def use_ref(self: S, name: str) -> S:
2219-
if self.snapshot_id:
2219+
if self.snapshot_id is not None:
22202220
raise ValueError(f"Cannot override ref, already set snapshot id={self.snapshot_id}")
22212221
if snapshot := self.table_metadata.snapshot_by_name(name):
22222222
return self.update(snapshot_id=snapshot.snapshot_id)

tests/table/test_init.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,31 @@ def test_table_scan_ref(table_v2: Table) -> None:
290290
assert scan.use_ref("test").snapshot_id == 3051729675574597004
291291

292292

293+
@pytest.mark.parametrize(
294+
"snapshot_id, expected_snapshot_id",
295+
[(None, 3055729675574597004), (0, 0), (3051729675574597004, 3051729675574597004)],
296+
)
297+
def test_table_scan_snapshot(table_v2: Table, snapshot_id: int | None, expected_snapshot_id: int) -> None:
298+
table_v2.metadata.snapshots.append(
299+
Snapshot(snapshot_id=0, timestamp_ms=1515100955769, manifest_list="s3://a/b/zero.avro", schema_id=0)
300+
)
301+
302+
snapshot = table_v2.scan(snapshot_id=snapshot_id).snapshot()
303+
304+
assert snapshot is not None
305+
assert snapshot.snapshot_id == expected_snapshot_id
306+
307+
308+
def test_table_scan_missing_snapshot_zero(table_v2: Table) -> None:
309+
assert table_v2.scan(snapshot_id=0).snapshot() is None
310+
311+
312+
@pytest.mark.parametrize("snapshot_id", [0, 3051729675574597004])
313+
def test_table_scan_ref_cannot_override_snapshot(table_v2: Table, snapshot_id: int) -> None:
314+
with pytest.raises(ValueError, match=f"Cannot override ref, already set snapshot id={snapshot_id}"):
315+
table_v2.scan(snapshot_id=snapshot_id).use_ref("test")
316+
317+
293318
def test_table_scan_ref_does_not_exists(table_v2: Table) -> None:
294319
scan = table_v2.scan()
295320

0 commit comments

Comments
 (0)