2424)
2525
2626from sqlalchemy import (
27+ ColumnElement ,
2728 String ,
2829 create_engine ,
2930 delete ,
8485DEFAULT_ECHO_VALUE = "false"
8586DEFAULT_POOL_PRE_PING_VALUE = "false"
8687DEFAULT_INIT_CATALOG_TABLES = "true"
88+ ICEBERG_TABLE_TYPE = "TABLE"
8789
8890
8991class SqlCatalogBaseTable (MappedAsDataclass , DeclarativeBase ):
@@ -209,9 +211,16 @@ def _create_table_row(self, namespace: str, table_name: str, metadata_location:
209211 "previous_metadata_location" : None ,
210212 }
211213 if self ._schema_version == "v1" :
212- row ["iceberg_type" ] = "TABLE"
214+ row ["iceberg_type" ] = ICEBERG_TABLE_TYPE
213215 return row
214216
217+ def _iceberg_type_filter (self ) -> ColumnElement [bool ] | None :
218+ # Excludes non-table rows (e.g. views written by iceberg-java or iceberg-rust) from table
219+ # lookups. None on v0 schemas, where the iceberg_type column doesn't exist to filter on.
220+ if self ._schema_version != "v1" :
221+ return None
222+ return (IcebergTables .iceberg_type == ICEBERG_TABLE_TYPE ) | (IcebergTables .iceberg_type .is_ (None ))
223+
215224 def _convert_orm_to_iceberg (self , orm_table : IcebergTables ) -> Table :
216225 # Check for expected properties.
217226 if not (metadata_location := orm_table .metadata_location ):
@@ -349,6 +358,8 @@ def load_table(self, identifier: str | Identifier) -> Table:
349358 IcebergTables .table_namespace == namespace ,
350359 IcebergTables .table_name == table_name ,
351360 )
361+ if (type_filter := self ._iceberg_type_filter ()) is not None :
362+ stmt = stmt .where (type_filter )
352363 result = session .scalar (stmt )
353364 if result :
354365 return self ._convert_orm_to_iceberg (result )
@@ -367,29 +378,33 @@ def drop_table(self, identifier: str | Identifier) -> None:
367378 namespace_tuple = Catalog .namespace_from (identifier )
368379 namespace = Catalog .namespace_to_string (namespace_tuple )
369380 table_name = Catalog .table_name_from (identifier )
381+ type_filter = self ._iceberg_type_filter ()
370382 with Session (self .engine ) as session :
371383 if self .engine .dialect .supports_sane_rowcount :
372- res = session .execute (
373- delete (IcebergTables ).where (
374- IcebergTables .catalog_name == self .name ,
375- IcebergTables .table_namespace == namespace ,
376- IcebergTables .table_name == table_name ,
377- )
384+ stmt = delete (IcebergTables ).where (
385+ IcebergTables .catalog_name == self .name ,
386+ IcebergTables .table_namespace == namespace ,
387+ IcebergTables .table_name == table_name ,
378388 )
389+ if type_filter is not None :
390+ stmt = stmt .where (type_filter )
391+ res = session .execute (stmt )
379392 if res .rowcount < 1 :
380393 raise NoSuchTableError (f"Table does not exist: { namespace } .{ table_name } " )
381394 else :
382395 try :
383- tbl = (
396+ query = (
384397 session .query (IcebergTables )
385398 .with_for_update (of = IcebergTables )
386399 .filter (
387400 IcebergTables .catalog_name == self .name ,
388401 IcebergTables .table_namespace == namespace ,
389402 IcebergTables .table_name == table_name ,
390403 )
391- .one ()
392404 )
405+ if type_filter is not None :
406+ query = query .filter (type_filter )
407+ tbl = query .one ()
393408 session .delete (tbl )
394409 except NoResultFound as e :
395410 raise NoSuchTableError (f"Table does not exist: { namespace } .{ table_name } " ) from e
@@ -419,6 +434,7 @@ def rename_table(self, from_identifier: str | Identifier, to_identifier: str | I
419434 to_table_name = Catalog .table_name_from (to_identifier )
420435 if not self .namespace_exists (to_namespace ):
421436 raise NoSuchNamespaceError (f"Namespace does not exist: { to_namespace } " )
437+ type_filter = self ._iceberg_type_filter ()
422438 with Session (self .engine ) as session :
423439 try :
424440 if self .engine .dialect .supports_sane_rowcount :
@@ -431,21 +447,25 @@ def rename_table(self, from_identifier: str | Identifier, to_identifier: str | I
431447 )
432448 .values (table_namespace = to_namespace , table_name = to_table_name )
433449 )
450+ if type_filter is not None :
451+ stmt = stmt .where (type_filter )
434452 result = session .execute (stmt )
435453 if result .rowcount < 1 :
436454 raise NoSuchTableError (f"Table does not exist: { from_table_name } " )
437455 else :
438456 try :
439- tbl = (
457+ query = (
440458 session .query (IcebergTables )
441459 .with_for_update (of = IcebergTables )
442460 .filter (
443461 IcebergTables .catalog_name == self .name ,
444462 IcebergTables .table_namespace == from_namespace ,
445463 IcebergTables .table_name == from_table_name ,
446464 )
447- .one ()
448465 )
466+ if type_filter is not None :
467+ query = query .filter (type_filter )
468+ tbl = query .one ()
449469 tbl .table_namespace = to_namespace
450470 tbl .table_name = to_table_name
451471 except NoResultFound as e :
@@ -656,9 +676,8 @@ def list_tables(self, namespace: str | Identifier) -> list[Identifier]:
656676 IcebergTables .table_namespace == namespace ,
657677 )
658678
659- # Filter out views only if schema_version is v1
660- if self ._schema_version == "v1" :
661- stmt = stmt .where ((IcebergTables .iceberg_type == "TABLE" ) | (IcebergTables .iceberg_type .is_ (None )))
679+ if (type_filter := self ._iceberg_type_filter ()) is not None :
680+ stmt = stmt .where (type_filter )
662681
663682 with Session (self .engine ) as session :
664683 result = session .scalars (stmt )
0 commit comments