Skip to content

Commit e993bf7

Browse files
committed
SQL Catalog: Filter on iceberg_type in commit_table (#3337)
1 parent 7539661 commit e993bf7

2 files changed

Lines changed: 33 additions & 2 deletions

File tree

pyiceberg/catalog/sql.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,7 @@ def commit_table(
517517
with Session(self.engine) as session:
518518
if current_table:
519519
# table exists, update it
520+
type_filter = self._iceberg_type_filter()
520521
if self.engine.dialect.supports_sane_rowcount:
521522
stmt = (
522523
update(IcebergTables)
@@ -531,12 +532,14 @@ def commit_table(
531532
previous_metadata_location=current_table.metadata_location,
532533
)
533534
)
535+
if type_filter is not None:
536+
stmt = stmt.where(type_filter)
534537
result = session.execute(stmt)
535538
if result.rowcount < 1:
536539
raise CommitFailedException(f"Table has been updated by another process: {namespace}.{table_name}")
537540
else:
538541
try:
539-
tbl = (
542+
query = (
540543
session.query(IcebergTables)
541544
.with_for_update(of=IcebergTables)
542545
.filter(
@@ -545,8 +548,10 @@ def commit_table(
545548
IcebergTables.table_name == table_name,
546549
IcebergTables.metadata_location == current_table.metadata_location,
547550
)
548-
.one()
549551
)
552+
if type_filter is not None:
553+
query = query.filter(type_filter)
554+
tbl = query.one()
550555
tbl.metadata_location = updated_staged_table.metadata_location
551556
tbl.previous_metadata_location = current_table.metadata_location
552557
except NoResultFound as e:

tests/catalog/test_sql.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
SqlCatalogBaseTable,
3333
)
3434
from pyiceberg.exceptions import (
35+
CommitFailedException,
3536
NoSuchPropertyException,
3637
NoSuchTableError,
3738
TableAlreadyExistsError,
@@ -388,6 +389,31 @@ def test_rename_table_ignores_view_rows(warehouse: Path) -> None:
388389
assert row[0] == "VIEW"
389390

390391

392+
def test_commit_table_ignores_view_rows(warehouse: Path) -> None:
393+
catalog = SqlCatalog(
394+
name="test", uri=f"sqlite:///{warehouse.as_posix()}/test_commit_view.db", warehouse=f"file://{warehouse}"
395+
)
396+
catalog.create_namespace("ns")
397+
schema = Schema(NestedField(1, "id", StringType(), required=True))
398+
tbl = catalog.create_table(("ns", "a_view"), schema=schema)
399+
400+
# Tamper the table row into a VIEW (simulating external writer)
401+
with catalog.engine.connect() as conn:
402+
conn.execute(text("UPDATE iceberg_tables SET iceberg_type = 'VIEW' WHERE table_name = 'a_view'"))
403+
conn.commit()
404+
405+
# Attempting to commit table updates must fail and not modify the VIEW row
406+
with pytest.raises(CommitFailedException):
407+
with tbl.update_schema() as update:
408+
update.add_column("new_col", StringType())
409+
410+
# The view row must remain untouched with iceberg_type == 'VIEW'
411+
with catalog.engine.connect() as conn:
412+
row = conn.execute(text("SELECT iceberg_type FROM iceberg_tables WHERE table_name = 'a_view'")).fetchone()
413+
assert row is not None
414+
assert row[0] == "VIEW"
415+
416+
391417
def test_migration_to_v1_with_property_set(warehouse: Path) -> None:
392418
uri = f"sqlite:///{warehouse.as_posix()}/test-v1-migrate"
393419
engine = _create_v0_db(uri)

0 commit comments

Comments
 (0)