From 9753152b572842e6d8b2b8fd051596f60673d9fa Mon Sep 17 00:00:00 2001 From: Shiv Gupta Date: Sun, 20 Oct 2024 15:41:07 -0400 Subject: [PATCH 01/10] Add view exists --- pyiceberg/catalog/__init__.py | 11 +++++++++++ pyiceberg/catalog/dynamodb.py | 3 +++ pyiceberg/catalog/glue.py | 3 +++ pyiceberg/catalog/hive.py | 3 +++ pyiceberg/catalog/noop.py | 3 +++ pyiceberg/catalog/rest.py | 29 +++++++++++++++++++++++++++++ pyiceberg/catalog/sql.py | 3 +++ 7 files changed, 55 insertions(+) diff --git a/pyiceberg/catalog/__init__.py b/pyiceberg/catalog/__init__.py index 7eb8b02d40..03c71903bf 100644 --- a/pyiceberg/catalog/__init__.py +++ b/pyiceberg/catalog/__init__.py @@ -449,6 +449,17 @@ def table_exists(self, identifier: Union[str, Identifier]) -> bool: Returns: bool: True if the table exists, False otherwise. """ + + @abstractmethod + def view_exists(self, identifier: Union[str, Identifier]) -> bool: + """Check if a view exists. + + Args: + identifier (str | Identifier): View identifier. + + Returns: + bool: True if the view exists, False otherwise. + """ @abstractmethod def register_table(self, identifier: Union[str, Identifier], metadata_location: str) -> Table: diff --git a/pyiceberg/catalog/dynamodb.py b/pyiceberg/catalog/dynamodb.py index 59cbe8ce28..6f71e4ff1b 100644 --- a/pyiceberg/catalog/dynamodb.py +++ b/pyiceberg/catalog/dynamodb.py @@ -542,6 +542,9 @@ def list_views(self, namespace: Union[str, Identifier]) -> List[Identifier]: def drop_view(self, identifier: Union[str, Identifier]) -> None: raise NotImplementedError + + def view_exists(self, identifier: Union[str, Identifier]): + raise NotImplementedError def _get_iceberg_table_item(self, database_name: str, table_name: str) -> Dict[str, Any]: try: diff --git a/pyiceberg/catalog/glue.py b/pyiceberg/catalog/glue.py index 5c7b1ddcbd..60e80de0e9 100644 --- a/pyiceberg/catalog/glue.py +++ b/pyiceberg/catalog/glue.py @@ -782,6 +782,9 @@ def list_views(self, namespace: Union[str, Identifier]) -> List[Identifier]: def drop_view(self, identifier: Union[str, Identifier]) -> None: raise NotImplementedError + def view_exists(self, identifier: Union[str, Identifier]): + raise NotImplementedError + @staticmethod def __is_iceberg_table(table: TableTypeDef) -> bool: return table["Parameters"] is not None and table["Parameters"][TABLE_TYPE].lower() == ICEBERG diff --git a/pyiceberg/catalog/hive.py b/pyiceberg/catalog/hive.py index 030470e164..e3d61c28d9 100644 --- a/pyiceberg/catalog/hive.py +++ b/pyiceberg/catalog/hive.py @@ -409,6 +409,9 @@ def register_table(self, identifier: Union[str, Identifier], metadata_location: def list_views(self, namespace: Union[str, Identifier]) -> List[Identifier]: raise NotImplementedError + def view_exists(self, identifier: Union[str, Identifier]): + raise NotImplementedError + def _create_lock_request(self, database_name: str, table_name: str) -> LockRequest: lock_component: LockComponent = LockComponent( level=LockLevel.TABLE, type=LockType.EXCLUSIVE, dbname=database_name, tablename=table_name, isTransactional=True diff --git a/pyiceberg/catalog/noop.py b/pyiceberg/catalog/noop.py index caebf1e445..80ecac24e2 100644 --- a/pyiceberg/catalog/noop.py +++ b/pyiceberg/catalog/noop.py @@ -123,5 +123,8 @@ def update_namespace_properties( def list_views(self, namespace: Union[str, Identifier]) -> List[Identifier]: raise NotImplementedError + def view_exists(self, identifier: Union[str, Identifier]): + raise NotImplementedError + def drop_view(self, identifier: Union[str, Identifier]) -> None: raise NotImplementedError diff --git a/pyiceberg/catalog/rest.py b/pyiceberg/catalog/rest.py index 20a04d9c5b..55d5667776 100644 --- a/pyiceberg/catalog/rest.py +++ b/pyiceberg/catalog/rest.py @@ -105,6 +105,7 @@ class Endpoints: rename_table: str = "tables/rename" list_views: str = "namespaces/{namespace}/views" drop_view: str = "namespaces/{namespace}/views/{view}" + view_exists: str = "namespaces/{namespace}/views/{view}" class IdentifierKind(Enum): @@ -890,6 +891,34 @@ def table_exists(self, identifier: Union[str, Identifier]) -> bool: return False + @retry(**_RETRY_ARGS) + def view_exists(self, identifier: Union[str, Identifier]) -> bool: + """Check if a view exists. + + Args: + identifier (str | Identifier): View identifier. + + Returns: + bool: True if the view exists, False otherwise. + """ + identifier_tuple = self._identifier_to_tuple_without_catalog(identifier) + response = self._session.head( + self.url( + Endpoints.view_exists, prefixed=True, **self._split_identifier_for_path(identifier_tuple, IdentifierKind.VIEW) + ), + ) + if response.status_code == 404: + return False + elif response.status_code == 204: + return True + + try: + response.raise_for_status() + except HTTPError as exc: + self._handle_non_200_response(exc, {}) + + return False + @retry(**_RETRY_ARGS) def drop_view(self, identifier: Union[str]) -> None: identifier_tuple = self.identifier_to_tuple_without_catalog(identifier) diff --git a/pyiceberg/catalog/sql.py b/pyiceberg/catalog/sql.py index 6a4318253f..5d1163c759 100644 --- a/pyiceberg/catalog/sql.py +++ b/pyiceberg/catalog/sql.py @@ -707,6 +707,9 @@ def update_namespace_properties( def list_views(self, namespace: Union[str, Identifier]) -> List[Identifier]: raise NotImplementedError + + def view_exists(self, identifier: Union[str, Identifier]): + raise NotImplementedError def drop_view(self, identifier: Union[str, Identifier]) -> None: raise NotImplementedError From 871216899b82f7090b6e25c0307257b7fb80bcd2 Mon Sep 17 00:00:00 2001 From: Shiv Gupta Date: Sun, 20 Oct 2024 16:11:14 -0400 Subject: [PATCH 02/10] lint --- pyiceberg/catalog/__init__.py | 2 +- pyiceberg/catalog/dynamodb.py | 2 +- pyiceberg/catalog/glue.py | 2 +- pyiceberg/catalog/hive.py | 2 +- pyiceberg/catalog/noop.py | 2 +- pyiceberg/catalog/sql.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pyiceberg/catalog/__init__.py b/pyiceberg/catalog/__init__.py index 03c71903bf..9e3adca529 100644 --- a/pyiceberg/catalog/__init__.py +++ b/pyiceberg/catalog/__init__.py @@ -449,7 +449,7 @@ def table_exists(self, identifier: Union[str, Identifier]) -> bool: Returns: bool: True if the table exists, False otherwise. """ - + @abstractmethod def view_exists(self, identifier: Union[str, Identifier]) -> bool: """Check if a view exists. diff --git a/pyiceberg/catalog/dynamodb.py b/pyiceberg/catalog/dynamodb.py index 6f71e4ff1b..e336cbe71d 100644 --- a/pyiceberg/catalog/dynamodb.py +++ b/pyiceberg/catalog/dynamodb.py @@ -542,7 +542,7 @@ def list_views(self, namespace: Union[str, Identifier]) -> List[Identifier]: def drop_view(self, identifier: Union[str, Identifier]) -> None: raise NotImplementedError - + def view_exists(self, identifier: Union[str, Identifier]): raise NotImplementedError diff --git a/pyiceberg/catalog/glue.py b/pyiceberg/catalog/glue.py index 60e80de0e9..65c8dfec3a 100644 --- a/pyiceberg/catalog/glue.py +++ b/pyiceberg/catalog/glue.py @@ -784,7 +784,7 @@ def drop_view(self, identifier: Union[str, Identifier]) -> None: def view_exists(self, identifier: Union[str, Identifier]): raise NotImplementedError - + @staticmethod def __is_iceberg_table(table: TableTypeDef) -> bool: return table["Parameters"] is not None and table["Parameters"][TABLE_TYPE].lower() == ICEBERG diff --git a/pyiceberg/catalog/hive.py b/pyiceberg/catalog/hive.py index e3d61c28d9..ef2d80aa93 100644 --- a/pyiceberg/catalog/hive.py +++ b/pyiceberg/catalog/hive.py @@ -411,7 +411,7 @@ def list_views(self, namespace: Union[str, Identifier]) -> List[Identifier]: def view_exists(self, identifier: Union[str, Identifier]): raise NotImplementedError - + def _create_lock_request(self, database_name: str, table_name: str) -> LockRequest: lock_component: LockComponent = LockComponent( level=LockLevel.TABLE, type=LockType.EXCLUSIVE, dbname=database_name, tablename=table_name, isTransactional=True diff --git a/pyiceberg/catalog/noop.py b/pyiceberg/catalog/noop.py index 80ecac24e2..20e52109a6 100644 --- a/pyiceberg/catalog/noop.py +++ b/pyiceberg/catalog/noop.py @@ -125,6 +125,6 @@ def list_views(self, namespace: Union[str, Identifier]) -> List[Identifier]: def view_exists(self, identifier: Union[str, Identifier]): raise NotImplementedError - + def drop_view(self, identifier: Union[str, Identifier]) -> None: raise NotImplementedError diff --git a/pyiceberg/catalog/sql.py b/pyiceberg/catalog/sql.py index 5d1163c759..f677009490 100644 --- a/pyiceberg/catalog/sql.py +++ b/pyiceberg/catalog/sql.py @@ -707,7 +707,7 @@ def update_namespace_properties( def list_views(self, namespace: Union[str, Identifier]) -> List[Identifier]: raise NotImplementedError - + def view_exists(self, identifier: Union[str, Identifier]): raise NotImplementedError From 719cd8e7b3b491cfb8d97342a730982e290cc57f Mon Sep 17 00:00:00 2001 From: Shiv Gupta Date: Sun, 20 Oct 2024 16:13:20 -0400 Subject: [PATCH 03/10] add return type annotations --- pyiceberg/catalog/dynamodb.py | 2 +- pyiceberg/catalog/glue.py | 2 +- pyiceberg/catalog/hive.py | 2 +- pyiceberg/catalog/noop.py | 2 +- pyiceberg/catalog/sql.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pyiceberg/catalog/dynamodb.py b/pyiceberg/catalog/dynamodb.py index e336cbe71d..9bbd15a4cf 100644 --- a/pyiceberg/catalog/dynamodb.py +++ b/pyiceberg/catalog/dynamodb.py @@ -543,7 +543,7 @@ def list_views(self, namespace: Union[str, Identifier]) -> List[Identifier]: def drop_view(self, identifier: Union[str, Identifier]) -> None: raise NotImplementedError - def view_exists(self, identifier: Union[str, Identifier]): + def view_exists(self, identifier: Union[str, Identifier]) -> bool: raise NotImplementedError def _get_iceberg_table_item(self, database_name: str, table_name: str) -> Dict[str, Any]: diff --git a/pyiceberg/catalog/glue.py b/pyiceberg/catalog/glue.py index 65c8dfec3a..8faf7e074a 100644 --- a/pyiceberg/catalog/glue.py +++ b/pyiceberg/catalog/glue.py @@ -782,7 +782,7 @@ def list_views(self, namespace: Union[str, Identifier]) -> List[Identifier]: def drop_view(self, identifier: Union[str, Identifier]) -> None: raise NotImplementedError - def view_exists(self, identifier: Union[str, Identifier]): + def view_exists(self, identifier: Union[str, Identifier]) -> bool: raise NotImplementedError @staticmethod diff --git a/pyiceberg/catalog/hive.py b/pyiceberg/catalog/hive.py index ef2d80aa93..9a769d91f5 100644 --- a/pyiceberg/catalog/hive.py +++ b/pyiceberg/catalog/hive.py @@ -409,7 +409,7 @@ def register_table(self, identifier: Union[str, Identifier], metadata_location: def list_views(self, namespace: Union[str, Identifier]) -> List[Identifier]: raise NotImplementedError - def view_exists(self, identifier: Union[str, Identifier]): + def view_exists(self, identifier: Union[str, Identifier]) -> bool: raise NotImplementedError def _create_lock_request(self, database_name: str, table_name: str) -> LockRequest: diff --git a/pyiceberg/catalog/noop.py b/pyiceberg/catalog/noop.py index 20e52109a6..39a0b382a7 100644 --- a/pyiceberg/catalog/noop.py +++ b/pyiceberg/catalog/noop.py @@ -123,7 +123,7 @@ def update_namespace_properties( def list_views(self, namespace: Union[str, Identifier]) -> List[Identifier]: raise NotImplementedError - def view_exists(self, identifier: Union[str, Identifier]): + def view_exists(self, identifier: Union[str, Identifier]) -> bool: raise NotImplementedError def drop_view(self, identifier: Union[str, Identifier]) -> None: diff --git a/pyiceberg/catalog/sql.py b/pyiceberg/catalog/sql.py index f677009490..819265af43 100644 --- a/pyiceberg/catalog/sql.py +++ b/pyiceberg/catalog/sql.py @@ -708,7 +708,7 @@ def update_namespace_properties( def list_views(self, namespace: Union[str, Identifier]) -> List[Identifier]: raise NotImplementedError - def view_exists(self, identifier: Union[str, Identifier]): + def view_exists(self, identifier: Union[str, Identifier]) -> bool: raise NotImplementedError def drop_view(self, identifier: Union[str, Identifier]) -> None: From e7eb718b458d05c2bb750ae619cb8b82907cf943 Mon Sep 17 00:00:00 2001 From: Shiv Gupta Date: Sun, 20 Oct 2024 16:16:30 -0400 Subject: [PATCH 04/10] Add method to InMemoryCatalog --- tests/catalog/test_base.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/catalog/test_base.py b/tests/catalog/test_base.py index e212854ee2..6298f5e2b2 100644 --- a/tests/catalog/test_base.py +++ b/tests/catalog/test_base.py @@ -264,6 +264,9 @@ def list_views(self, namespace: Optional[Union[str, Identifier]] = None) -> List def drop_view(self, identifier: Union[str, Identifier]) -> None: raise NotImplementedError + def view_exists(self, identifier: Union[str, Identifier]) -> bool: + raise NotImplementedError + @pytest.fixture def catalog(tmp_path: PosixPath) -> InMemoryCatalog: From ee38a1cd9a5fb88e3980648a1d43e6a897e3178b Mon Sep 17 00:00:00 2001 From: Shiv Gupta Date: Sun, 20 Oct 2024 16:24:35 -0400 Subject: [PATCH 05/10] Add tests --- tests/catalog/test_rest.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/catalog/test_rest.py b/tests/catalog/test_rest.py index f05e15df38..84770a40e2 100644 --- a/tests/catalog/test_rest.py +++ b/tests/catalog/test_rest.py @@ -450,6 +450,28 @@ def test_list_views_404(rest_mock: Mocker) -> None: assert "Namespace does not exist" in str(e.value) +def test_view_exists_204(rest_mock: Mocker) -> None: + namespace = "examples" + view = "some_view" + rest_mock.head( + f"{TEST_URI}v1/namespaces/{namespace}/views/{view}", + status_code=204, + request_headers=TEST_HEADERS, + ) + catalog = RestCatalog("rest", uri=TEST_URI, token=TEST_TOKEN) + assert catalog.view_exists((namespace, view)) + +def test_view_exists_404(rest_mock: Mocker) -> None: + namespace = "examples" + view = "some_view" + rest_mock.head( + f"{TEST_URI}v1/namespaces/{namespace}/views/{view}", + status_code=404, + request_headers=TEST_HEADERS, + ) + catalog = RestCatalog("rest", uri=TEST_URI, token=TEST_TOKEN) + assert not catalog.view_exists((namespace, view)) + def test_list_namespaces_200(rest_mock: Mocker) -> None: rest_mock.get( f"{TEST_URI}v1/namespaces", From 9310fc9d0d9032a557cfc906c26c3bb80d628841 Mon Sep 17 00:00:00 2001 From: Shiv Gupta Date: Thu, 7 Nov 2024 18:51:15 -0500 Subject: [PATCH 06/10] Add test for multilevel namespace --- tests/catalog/test_rest.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/catalog/test_rest.py b/tests/catalog/test_rest.py index 84770a40e2..e8a5ccebfe 100644 --- a/tests/catalog/test_rest.py +++ b/tests/catalog/test_rest.py @@ -472,6 +472,17 @@ def test_view_exists_404(rest_mock: Mocker) -> None: catalog = RestCatalog("rest", uri=TEST_URI, token=TEST_TOKEN) assert not catalog.view_exists((namespace, view)) +def test_view_exists_multilevel_namespace_404(rest_mock: Mocker) -> None: + multilevel_namespace = "core.examples.some_namespace" + view = "some_view" + rest_mock.head( + f"{TEST_URI}v1/namespaces/{multilevel_namespace}/views/{view}", + status_code=404, + request_headers=TEST_HEADERS, + ) + catalog = RestCatalog("rest", uri=TEST_URI, token=TEST_TOKEN) + assert not catalog.view_exists((multilevel_namespace, view)) + def test_list_namespaces_200(rest_mock: Mocker) -> None: rest_mock.get( f"{TEST_URI}v1/namespaces", From ea68f8844f21f884a3d5dbfca78b6f180d2e6087 Mon Sep 17 00:00:00 2001 From: Shiv Gupta Date: Thu, 7 Nov 2024 18:52:36 -0500 Subject: [PATCH 07/10] Lint --- tests/catalog/test_rest.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/catalog/test_rest.py b/tests/catalog/test_rest.py index e8a5ccebfe..1eef85beda 100644 --- a/tests/catalog/test_rest.py +++ b/tests/catalog/test_rest.py @@ -461,6 +461,7 @@ def test_view_exists_204(rest_mock: Mocker) -> None: catalog = RestCatalog("rest", uri=TEST_URI, token=TEST_TOKEN) assert catalog.view_exists((namespace, view)) + def test_view_exists_404(rest_mock: Mocker) -> None: namespace = "examples" view = "some_view" @@ -472,6 +473,7 @@ def test_view_exists_404(rest_mock: Mocker) -> None: catalog = RestCatalog("rest", uri=TEST_URI, token=TEST_TOKEN) assert not catalog.view_exists((namespace, view)) + def test_view_exists_multilevel_namespace_404(rest_mock: Mocker) -> None: multilevel_namespace = "core.examples.some_namespace" view = "some_view" @@ -483,6 +485,7 @@ def test_view_exists_multilevel_namespace_404(rest_mock: Mocker) -> None: catalog = RestCatalog("rest", uri=TEST_URI, token=TEST_TOKEN) assert not catalog.view_exists((multilevel_namespace, view)) + def test_list_namespaces_200(rest_mock: Mocker) -> None: rest_mock.get( f"{TEST_URI}v1/namespaces", From a0fd80ace8ad53f2af95f2b4ac5b75cee357514f Mon Sep 17 00:00:00 2001 From: Shiv Gupta Date: Thu, 7 Nov 2024 19:01:27 -0500 Subject: [PATCH 08/10] Docs --- mkdocs/docs/api.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/mkdocs/docs/api.md b/mkdocs/docs/api.md index eaffb84a54..237564aa22 100644 --- a/mkdocs/docs/api.md +++ b/mkdocs/docs/api.md @@ -1129,6 +1129,19 @@ with table.manage_snapshots() as ms: ms.create_branch(snapshot_id1, "Branch_A").create_tag(snapshot_id2, "tag789") ``` +## Views + +PyIceberg supports view operations. + +### Check if a view exists + +```python +from pyiceberg.catalog import load_catalog + +catalog = load_catalog("default") +catalog.view_exists("default.bar") +``` + ## Query the data To query a table, a table scan is needed. A table scan accepts a filter, columns, optionally a limit and a snapshot ID: From c02804281eb55e0395b54246bc4b2a54b6fc5cd6 Mon Sep 17 00:00:00 2001 From: Shiv Gupta <18354771+shiv-io@users.noreply.github.com> Date: Sun, 19 Jan 2025 18:42:26 +0000 Subject: [PATCH 09/10] Add integration test --- pyiceberg/catalog/rest.py | 5 ++--- tests/integration/test_writes/test_writes.py | 12 ++++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/pyiceberg/catalog/rest.py b/pyiceberg/catalog/rest.py index 861bac73e0..76a64fc8a7 100644 --- a/pyiceberg/catalog/rest.py +++ b/pyiceberg/catalog/rest.py @@ -917,15 +917,14 @@ def view_exists(self, identifier: Union[str, Identifier]) -> bool: Returns: bool: True if the view exists, False otherwise. """ - identifier_tuple = self._identifier_to_tuple_without_catalog(identifier) response = self._session.head( self.url( - Endpoints.view_exists, prefixed=True, **self._split_identifier_for_path(identifier_tuple, IdentifierKind.VIEW) + Endpoints.view_exists, prefixed=True, **self._split_identifier_for_path(identifier, IdentifierKind.VIEW) ), ) if response.status_code == 404: return False - elif response.status_code == 204: + elif response.status_code in [200, 204]: return True try: diff --git a/tests/integration/test_writes/test_writes.py b/tests/integration/test_writes/test_writes.py index fff48b9373..5a0af656bd 100644 --- a/tests/integration/test_writes/test_writes.py +++ b/tests/integration/test_writes/test_writes.py @@ -1424,6 +1424,18 @@ def test_table_v1_with_null_nested_namespace(session_catalog: Catalog, arrow_tab # We expect no error here session_catalog.drop_table(identifier) +@pytest.mark.integration +def test_view_exists(spark: SparkSession, session_catalog: Catalog,) -> None: + identifier = "default.some_view" + spark.sql( + f""" + CREATE VIEW {identifier} + AS + (SELECT 1 as some_col) + """ + ).collect() + assert session_catalog.view_exists(identifier) + session_catalog.drop_view(identifier) # clean up @pytest.mark.integration def test_overwrite_all_data_with_filter(session_catalog: Catalog) -> None: From 4672e1586915d3c2b7e014f67d057ebc6fa4dccf Mon Sep 17 00:00:00 2001 From: Shiv Gupta <18354771+shiv-io@users.noreply.github.com> Date: Wed, 22 Jan 2025 02:36:14 +0000 Subject: [PATCH 10/10] lint --- pyiceberg/catalog/rest.py | 4 +--- tests/integration/test_writes/test_writes.py | 11 ++++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pyiceberg/catalog/rest.py b/pyiceberg/catalog/rest.py index 76a64fc8a7..fd111354ed 100644 --- a/pyiceberg/catalog/rest.py +++ b/pyiceberg/catalog/rest.py @@ -918,9 +918,7 @@ def view_exists(self, identifier: Union[str, Identifier]) -> bool: bool: True if the view exists, False otherwise. """ response = self._session.head( - self.url( - Endpoints.view_exists, prefixed=True, **self._split_identifier_for_path(identifier, IdentifierKind.VIEW) - ), + self.url(Endpoints.view_exists, prefixed=True, **self._split_identifier_for_path(identifier, IdentifierKind.VIEW)), ) if response.status_code == 404: return False diff --git a/tests/integration/test_writes/test_writes.py b/tests/integration/test_writes/test_writes.py index 5a0af656bd..1fe29c684c 100644 --- a/tests/integration/test_writes/test_writes.py +++ b/tests/integration/test_writes/test_writes.py @@ -1424,18 +1424,23 @@ def test_table_v1_with_null_nested_namespace(session_catalog: Catalog, arrow_tab # We expect no error here session_catalog.drop_table(identifier) + @pytest.mark.integration -def test_view_exists(spark: SparkSession, session_catalog: Catalog,) -> None: +def test_view_exists( + spark: SparkSession, + session_catalog: Catalog, +) -> None: identifier = "default.some_view" spark.sql( f""" CREATE VIEW {identifier} - AS + AS (SELECT 1 as some_col) """ ).collect() assert session_catalog.view_exists(identifier) - session_catalog.drop_view(identifier) # clean up + session_catalog.drop_view(identifier) # clean up + @pytest.mark.integration def test_overwrite_all_data_with_filter(session_catalog: Catalog) -> None: