-
Notifications
You must be signed in to change notification settings - Fork 491
Raise errors on view-table collisions #3380
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -323,6 +323,20 @@ def delete_data_files(io: FileIO, manifests_to_delete: list[ManifestFile]) -> No | |
| deleted_files[path] = True | ||
|
|
||
|
|
||
| def _raise_if_view_exists(catalog: Catalog, identifier: str | Identifier) -> None: | ||
| """Raise `TableAlreadyExistsError` if a view exists at the given identifier. | ||
|
|
||
| Catalogs that don't support views raise `NotImplementedError` from `view_exists` — | ||
| treat that as "no view at this identifier". | ||
| """ | ||
| try: | ||
| view_collision = catalog.view_exists(identifier) | ||
| except NotImplementedError: | ||
| view_collision = False | ||
| if view_collision: | ||
| raise TableAlreadyExistsError(f"View with same name already exists: {identifier}") | ||
|
|
||
|
|
||
| def _import_catalog(name: str, catalog_impl: str, properties: Properties) -> Catalog | None: | ||
| try: | ||
| path_parts = catalog_impl.split(".") | ||
|
|
@@ -920,6 +934,7 @@ def create_table_transaction( | |
| sort_order: SortOrder = UNSORTED_SORT_ORDER, | ||
| properties: Properties = EMPTY_DICT, | ||
| ) -> CreateTableTransaction: | ||
| _raise_if_view_exists(self, identifier) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Deliberate divergence from Java: Java |
||
| return CreateTableTransaction( | ||
| self._create_staged_table(identifier, schema, location, partition_spec, sort_order, properties) | ||
| ) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,7 +28,7 @@ | |
| from google.oauth2 import service_account | ||
| from typing_extensions import override | ||
|
|
||
| from pyiceberg.catalog import WAREHOUSE_LOCATION, MetastoreCatalog, PropertiesUpdateSummary | ||
| from pyiceberg.catalog import WAREHOUSE_LOCATION, MetastoreCatalog, PropertiesUpdateSummary, _raise_if_view_exists | ||
| from pyiceberg.exceptions import NamespaceAlreadyExistsError, NoSuchNamespaceError, NoSuchTableError, TableAlreadyExistsError | ||
| from pyiceberg.io import load_file_io | ||
| from pyiceberg.partitioning import UNPARTITIONED_PARTITION_SPEC, PartitionSpec | ||
|
|
@@ -134,6 +134,7 @@ def create_table( | |
| schema: Schema = self._convert_schema_if_needed(schema) # type: ignore | ||
|
|
||
| dataset_name, table_name = self.identifier_to_database_and_table(identifier) | ||
| _raise_if_view_exists(self, identifier) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No iceberg-java BigQuery analog. Hive reference for the semantics: |
||
|
|
||
| location = self._resolve_table_location(location, dataset_name, table_name) | ||
| provider = load_location_provider(table_location=location, table_properties=properties) | ||
|
|
@@ -295,6 +296,7 @@ def register_table(self, identifier: str | Identifier, metadata_location: str, o | |
| if overwrite: | ||
| raise NotImplementedError("`overwrite` isn't supported") | ||
|
|
||
| _raise_if_view_exists(self, identifier) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No iceberg-java BigQuery analog. Hive reference: |
||
| dataset_name, table_name = self.identifier_to_database_and_table(identifier) | ||
|
|
||
| dataset_ref = DatasetReference(project=self.project_id, dataset_id=dataset_name) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,6 +34,7 @@ | |
| TABLE_TYPE, | ||
| MetastoreCatalog, | ||
| PropertiesUpdateSummary, | ||
| _raise_if_view_exists, | ||
| ) | ||
| from pyiceberg.exceptions import ( | ||
| ConditionalCheckFailedException, | ||
|
|
@@ -187,6 +188,7 @@ def create_table( | |
| ) | ||
|
|
||
| database_name, table_name = self.identifier_to_database_and_table(identifier) | ||
| _raise_if_view_exists(self, identifier) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Java |
||
|
|
||
| location = self._resolve_table_location(location, database_name, table_name) | ||
| provider = load_location_provider(table_location=location, table_properties=properties) | ||
|
|
@@ -313,6 +315,7 @@ def rename_table(self, from_identifier: str | Identifier, to_identifier: str | I | |
| """ | ||
| from_database_name, from_table_name = self.identifier_to_database_and_table(from_identifier, NoSuchTableError) | ||
| to_database_name, to_table_name = self.identifier_to_database_and_table(to_identifier) | ||
| _raise_if_view_exists(self, to_identifier) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No Java DynamoDb analog. Hive reference: |
||
|
|
||
| from_table_item = self._get_iceberg_table_item(database_name=from_database_name, table_name=from_table_name) | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,6 +39,7 @@ | |
| TABLE_TYPE, | ||
| MetastoreCatalog, | ||
| PropertiesUpdateSummary, | ||
| _raise_if_view_exists, | ||
| ) | ||
| from pyiceberg.exceptions import ( | ||
| CommitFailedException, | ||
|
|
@@ -571,6 +572,7 @@ def create_table( | |
| """ | ||
| database_name, table_name = self.identifier_to_database_and_table(identifier) | ||
| _raise_if_view_exists(self, identifier) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Java |
||
|
|
||
| if self._is_s3tables_database(database_name): | ||
| return self._create_table_s3tables( | ||
|
|
@@ -621,6 +623,7 @@ def register_table(self, identifier: str | Identifier, metadata_location: str, o | |
| if overwrite: | ||
| raise NotImplementedError("`overwrite` isn't supported") | ||
|
|
||
| _raise_if_view_exists(self, identifier) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same shape as the other Glue call sites — no Java analog (Glue Java has no view support), Hive reference |
||
| database_name, table_name = self.identifier_to_database_and_table(identifier) | ||
| properties = EMPTY_DICT | ||
| io = self._load_file_io(location=metadata_location) | ||
|
|
@@ -772,6 +775,7 @@ def rename_table(self, from_identifier: str | Identifier, to_identifier: str | I | |
| """ | ||
| from_database_name, from_table_name = self.identifier_to_database_and_table(from_identifier, NoSuchTableError) | ||
| to_database_name, to_table_name = self.identifier_to_database_and_table(to_identifier) | ||
| _raise_if_view_exists(self, to_identifier) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No Java Glue analog. Hive reference: |
||
| try: | ||
| get_table_response = self.glue.get_table(DatabaseName=from_database_name, Name=from_table_name) | ||
| except self.glue.exceptions.EntityNotFoundException as e: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -61,6 +61,7 @@ | |
| URI, | ||
| MetastoreCatalog, | ||
| PropertiesUpdateSummary, | ||
| _raise_if_view_exists, | ||
| ) | ||
| from pyiceberg.exceptions import ( | ||
| CommitFailedException, | ||
|
|
@@ -413,6 +414,7 @@ def create_table( | |
| ValueError: If the identifier is invalid. | ||
| """ | ||
| properties = {**DEFAULT_PROPERTIES, **properties} | ||
| _raise_if_view_exists(self, identifier) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1:1 with Java |
||
| staged_table = self._create_staged_table( | ||
| identifier=identifier, | ||
| schema=schema, | ||
|
|
@@ -461,6 +463,7 @@ def register_table(self, identifier: str | Identifier, metadata_location: str, o | |
| if overwrite: | ||
| raise NotImplementedError("`overwrite` isn't supported") | ||
|
|
||
| _raise_if_view_exists(self, identifier) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1:1 with Java |
||
| database_name, table_name = self.identifier_to_database_and_table(identifier) | ||
| io = self._load_file_io(location=metadata_location) | ||
| metadata_file = io.new_input(metadata_location) | ||
|
|
@@ -700,6 +703,7 @@ def rename_table(self, from_identifier: str | Identifier, to_identifier: str | I | |
|
|
||
| if self.table_exists(to_identifier): | ||
| raise TableAlreadyExistsError(f"Table already exists: {to_table_name}") | ||
| _raise_if_view_exists(self, to_identifier) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1:1 with Java |
||
|
|
||
| try: | ||
| with self._client as open_client: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,6 +46,7 @@ | |
| Catalog, | ||
| MetastoreCatalog, | ||
| PropertiesUpdateSummary, | ||
| _raise_if_view_exists, | ||
| ) | ||
| from pyiceberg.exceptions import ( | ||
| CommitFailedException, | ||
|
|
@@ -211,6 +212,7 @@ def create_table( | |
| table_name = Catalog.table_name_from(identifier) | ||
| if not self.namespace_exists(namespace_identifier): | ||
| raise NoSuchNamespaceError(f"Namespace does not exist: {namespace_identifier}") | ||
| _raise_if_view_exists(self, identifier) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mirrors Java |
||
|
|
||
| namespace = Catalog.namespace_to_string(namespace_identifier) | ||
| location = self._resolve_table_location(location, namespace, table_name) | ||
|
|
@@ -263,6 +265,7 @@ def register_table(self, identifier: str | Identifier, metadata_location: str, o | |
| table_name = Catalog.table_name_from(identifier) | ||
| if not self.namespace_exists(namespace): | ||
| raise NoSuchNamespaceError(f"Namespace does not exist: {namespace}") | ||
| _raise_if_view_exists(self, identifier) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mirrors Java |
||
|
|
||
| with Session(self.engine) as session: | ||
| try: | ||
|
|
@@ -376,6 +379,7 @@ def rename_table(self, from_identifier: str | Identifier, to_identifier: str | I | |
| to_table_name = Catalog.table_name_from(to_identifier) | ||
| if not self.namespace_exists(to_namespace): | ||
| raise NoSuchNamespaceError(f"Namespace does not exist: {to_namespace}") | ||
| _raise_if_view_exists(self, to_identifier) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mirrors Java |
||
| with Session(self.engine) as session: | ||
| try: | ||
| if self.engine.dialect.supports_sane_rowcount: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Helper mirrors the pattern from Java
HiveCatalogand Java REST'sRESTSessionCatalog.replaceTransaction. Re-usesTableAlreadyExistsErrorso existingcreate_table_if_not_existscallers keep working. Catalogs without view support raiseNotImplementedErrorfromview_exists— treat that as 'no view'.