diff --git a/dbt-athena/.changes/unreleased/Features-20241217-001238.yaml b/dbt-athena/.changes/unreleased/Features-20241217-001238.yaml new file mode 100644 index 00000000..e8da240b --- /dev/null +++ b/dbt-athena/.changes/unreleased/Features-20241217-001238.yaml @@ -0,0 +1,6 @@ +kind: Features +body: Implement drop_glue_database macro and method +time: 2024-12-17T00:12:38.943084+01:00 +custom: + Author: svdimchenko + Issue: "768" diff --git a/dbt-athena/src/dbt/adapters/athena/impl.py b/dbt-athena/src/dbt/adapters/athena/impl.py index e70cca3c..f915de0c 100755 --- a/dbt-athena/src/dbt/adapters/athena/impl.py +++ b/dbt-athena/src/dbt/adapters/athena/impl.py @@ -9,7 +9,7 @@ from functools import lru_cache from textwrap import dedent from threading import Lock -from typing import Any, Dict, FrozenSet, Iterable, List, Optional, Set, Tuple, Type +from typing import TYPE_CHECKING, Any, Dict, FrozenSet, Iterable, List, Optional, Set, Tuple, Type from urllib.parse import urlparse from uuid import uuid4 @@ -69,6 +69,10 @@ from dbt.adapters.contracts.relation import RelationConfig from dbt.adapters.sql import SQLAdapter + +if TYPE_CHECKING: + from mypy_boto3_glue.client import GlueClient + boto3_client_lock = Lock() @@ -1173,6 +1177,23 @@ def delete_from_glue_catalog(self, relation: AthenaRelation) -> None: LOGGER.error(e) raise e + @available + def drop_glue_database(self, database_name: str, catalog_name: str = "awsdatacatalog") -> None: + conn = self.connections.get_thread_connection() + creds = conn.credentials + client = conn.handle + catalog = self._get_data_catalog(catalog_name) + catalog_id = get_catalog_id(catalog) + + with boto3_client_lock: + glue_client: GlueClient = client.session.client( + "glue", + region_name=client.region_name, + config=get_boto3_config(num_retries=creds.effective_num_retries), + ) + glue_client.delete_database(Name=database_name, CatalogId=catalog_id) + LOGGER.debug(f"Glue database successfully deleted: {catalog_name}.{database_name}") + @available.parse_none def valid_snapshot_target(self, relation: BaseRelation) -> None: """Log an error to help developers migrate to the new snapshot logic""" diff --git a/dbt-athena/src/dbt/include/athena/macros/adapters/schema.sql b/dbt-athena/src/dbt/include/athena/macros/adapters/schema.sql index 2750a7f9..a8a60fef 100644 --- a/dbt-athena/src/dbt/include/athena/macros/adapters/schema.sql +++ b/dbt-athena/src/dbt/include/athena/macros/adapters/schema.sql @@ -13,3 +13,8 @@ drop schema if exists {{ relation.without_identifier().render_hive() }} cascade {% endcall %} {% endmacro %} + + +{% macro drop_glue_database(database_name, catalog_name='awsdatacatalog') -%} + {{ adapter.drop_glue_database(database_name, catalog_name) }} +{% endmacro %} diff --git a/dbt-athena/tests/unit/test_adapter.py b/dbt-athena/tests/unit/test_adapter.py index e3c3b923..ad336f97 100644 --- a/dbt-athena/tests/unit/test_adapter.py +++ b/dbt-athena/tests/unit/test_adapter.py @@ -12,6 +12,7 @@ from dbt_common.exceptions import ConnectionError, DbtRuntimeError from moto import mock_aws from moto.core import DEFAULT_ACCOUNT_ID +from mypy_boto3_glue.client import GlueClient from dbt.adapters.athena import AthenaAdapter from dbt.adapters.athena import Plugin as AthenaPlugin @@ -1252,6 +1253,17 @@ def test_format_unsupported_type(self): with pytest.raises(ValueError): self.adapter.format_value_for_partition("test", "unsupported_type") + @mock_aws + def test_drop_glue_database(self): + glue_client: GlueClient = boto3.client("glue", region_name=AWS_REGION) + test_input = {"Name": "test"} + glue_client.create_database(DatabaseInput=test_input) + database_list = glue_client.get_databases()["DatabaseList"] + assert [test_input["Name"]] == [db["Name"] for db in database_list] + self.adapter.acquire_connection("dummy") + self.adapter.drop_glue_database(database_name=test_input["Name"]) + assert glue_client.get_databases()["DatabaseList"] == [] + class TestAthenaFilterCatalog: def test__catalog_filter_table(self):