From cac570c6c3e0afafd6dcd47f21524e85936d43fd Mon Sep 17 00:00:00 2001 From: Anupam Saini <4581797+anupam-saini@users.noreply.github.com> Date: Mon, 11 Mar 2024 12:19:59 +0000 Subject: [PATCH 1/4] Add `table_exist` method to Catalog --- pyiceberg/catalog/__init__.py | 7 +++++++ tests/catalog/test_base.py | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/pyiceberg/catalog/__init__.py b/pyiceberg/catalog/__init__.py index db83658f1f..0098d4997c 100644 --- a/pyiceberg/catalog/__init__.py +++ b/pyiceberg/catalog/__init__.py @@ -646,6 +646,13 @@ def purge_table(self, identifier: Union[str, Identifier]) -> None: delete_files(io, prev_metadata_files, PREVIOUS_METADATA) delete_files(io, {table.metadata_location}, METADATA) + def table_exist(self, identifier: Union[str, Identifier]) -> bool: + try: + self.load_table(identifier) + return True + except NoSuchTableError: + return False + @staticmethod def _write_metadata(metadata: TableMetadata, io: FileIO, metadata_path: str) -> None: ToOutputFile.table_metadata(metadata, io.new_output(metadata_path)) diff --git a/tests/catalog/test_base.py b/tests/catalog/test_base.py index 1f0060780e..e439be0319 100644 --- a/tests/catalog/test_base.py +++ b/tests/catalog/test_base.py @@ -377,6 +377,17 @@ def test_table_raises_error_on_table_not_found(catalog: InMemoryCatalog) -> None catalog.load_table(TEST_TABLE_IDENTIFIER) +def test_table_exist(catalog: InMemoryCatalog) -> None: + # Given + given_catalog_has_a_table(catalog) + # Then + assert catalog.table_exist(TEST_TABLE_IDENTIFIER) + + +def test_table_exist_on_table_not_found(catalog: InMemoryCatalog) -> None: + assert not catalog.table_exist(TEST_TABLE_IDENTIFIER) + + def test_drop_table(catalog: InMemoryCatalog) -> None: # Given given_catalog_has_a_table(catalog) From 9fc1b63edd07c3143c9df353a41ddfae4559ca8a Mon Sep 17 00:00:00 2001 From: Anupam Saini <4581797+anupam-saini@users.noreply.github.com> Date: Mon, 11 Mar 2024 12:27:29 +0000 Subject: [PATCH 2/4] `table_exist` -> `table_exists` --- pyiceberg/catalog/__init__.py | 2 +- tests/catalog/test_base.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pyiceberg/catalog/__init__.py b/pyiceberg/catalog/__init__.py index 0098d4997c..cb1325610d 100644 --- a/pyiceberg/catalog/__init__.py +++ b/pyiceberg/catalog/__init__.py @@ -646,7 +646,7 @@ def purge_table(self, identifier: Union[str, Identifier]) -> None: delete_files(io, prev_metadata_files, PREVIOUS_METADATA) delete_files(io, {table.metadata_location}, METADATA) - def table_exist(self, identifier: Union[str, Identifier]) -> bool: + def table_exists(self, identifier: Union[str, Identifier]) -> bool: try: self.load_table(identifier) return True diff --git a/tests/catalog/test_base.py b/tests/catalog/test_base.py index e439be0319..3218239dd9 100644 --- a/tests/catalog/test_base.py +++ b/tests/catalog/test_base.py @@ -377,15 +377,15 @@ def test_table_raises_error_on_table_not_found(catalog: InMemoryCatalog) -> None catalog.load_table(TEST_TABLE_IDENTIFIER) -def test_table_exist(catalog: InMemoryCatalog) -> None: +def test_table_exists(catalog: InMemoryCatalog) -> None: # Given given_catalog_has_a_table(catalog) # Then - assert catalog.table_exist(TEST_TABLE_IDENTIFIER) + assert catalog.table_exists(TEST_TABLE_IDENTIFIER) -def test_table_exist_on_table_not_found(catalog: InMemoryCatalog) -> None: - assert not catalog.table_exist(TEST_TABLE_IDENTIFIER) +def test_table_exists_on_table_not_found(catalog: InMemoryCatalog) -> None: + assert not catalog.table_exists(TEST_TABLE_IDENTIFIER) def test_drop_table(catalog: InMemoryCatalog) -> None: From 500d04d501b558b71578b85e2e5cdf4ce86b14de Mon Sep 17 00:00:00 2001 From: Anupam Saini <4581797+anupam-saini@users.noreply.github.com> Date: Tue, 12 Mar 2024 12:09:51 +0000 Subject: [PATCH 3/4] Add `table_exists` for RestCatalog --- pyiceberg/catalog/rest.py | 8 ++++++++ tests/catalog/test_rest.py | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/pyiceberg/catalog/rest.py b/pyiceberg/catalog/rest.py index a5f33f02dd..0aa5f1f5b0 100644 --- a/pyiceberg/catalog/rest.py +++ b/pyiceberg/catalog/rest.py @@ -719,3 +719,11 @@ def update_namespace_properties( updated=parsed_response.updated, missing=parsed_response.missing, ) + + @retry(**_RETRY_ARGS) + def table_exists(self, identifier: Union[str, Identifier]) -> bool: + identifier_tuple = self.identifier_to_tuple_without_catalog(identifier) + response = self._session.head( + self.url(Endpoints.load_table, prefixed=True, **self._split_identifier_for_path(identifier_tuple)) + ) + return response.status_code == 200 diff --git a/tests/catalog/test_rest.py b/tests/catalog/test_rest.py index 850e5f0180..4956fffe6c 100644 --- a/tests/catalog/test_rest.py +++ b/tests/catalog/test_rest.py @@ -644,6 +644,26 @@ def test_load_table_404(rest_mock: Mocker) -> None: assert "Table does not exist" in str(e.value) +def test_table_exist_200(rest_mock: Mocker) -> None: + rest_mock.head( + f"{TEST_URI}v1/namespaces/fokko/tables/table", + status_code=200, + request_headers=TEST_HEADERS, + ) + catalog = RestCatalog("rest", uri=TEST_URI, token=TEST_TOKEN) + assert catalog.table_exists(("fokko", "table")) + + +def test_table_exist_500(rest_mock: Mocker) -> None: + rest_mock.head( + f"{TEST_URI}v1/namespaces/fokko/tables/table", + status_code=500, + request_headers=TEST_HEADERS, + ) + catalog = RestCatalog("rest", uri=TEST_URI, token=TEST_TOKEN) + assert not catalog.table_exists(("fokko", "table")) + + def test_drop_table_404(rest_mock: Mocker) -> None: rest_mock.delete( f"{TEST_URI}v1/namespaces/fokko/tables/does_not_exists", From 22d2166c37daff1bd2c08124c0bdf7df1af84a16 Mon Sep 17 00:00:00 2001 From: Anupam Saini <4581797+anupam-saini@users.noreply.github.com> Date: Wed, 13 Mar 2024 12:04:09 +0000 Subject: [PATCH 4/4] Add doc --- mkdocs/docs/api.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/mkdocs/docs/api.md b/mkdocs/docs/api.md index 724a45c52f..35b271ae9e 100644 --- a/mkdocs/docs/api.md +++ b/mkdocs/docs/api.md @@ -194,6 +194,16 @@ static_table = StaticTable.from_metadata( The static-table is considered read-only. +## Check if a table exists + +To check whether the `bids` table exists: + +```python +catalog.table_exists("docs_example.bids") +``` + +Returns `True` if the table already exists. + ## Write support With PyIceberg 0.6.0 write support is added through Arrow. Let's consider an Arrow Table: