diff --git a/.changes/unreleased/Features-20230822-234732.yaml b/.changes/unreleased/Features-20230822-234732.yaml new file mode 100644 index 000000000..297630745 --- /dev/null +++ b/.changes/unreleased/Features-20230822-234732.yaml @@ -0,0 +1,6 @@ +kind: Features +body: Support replacing tables/views with dynamic tables and vice versa +time: 2023-08-22T23:47:32.27784-04:00 +custom: + Author: mikealfare + Issue: "753" diff --git a/dbt/adapters/snowflake/relation.py b/dbt/adapters/snowflake/relation.py index 9139362a4..9d6182a71 100644 --- a/dbt/adapters/snowflake/relation.py +++ b/dbt/adapters/snowflake/relation.py @@ -20,6 +20,14 @@ class SnowflakeRelation(BaseRelation): type: Optional[SnowflakeRelationType] = None # type: ignore quote_policy: SnowflakeQuotePolicy = field(default_factory=lambda: SnowflakeQuotePolicy()) + renameable_relations = frozenset({SnowflakeRelationType.Table, SnowflakeRelationType.View}) + replaceable_relations = frozenset( + { + SnowflakeRelationType.DynamicTable, + SnowflakeRelationType.Table, + SnowflakeRelationType.View, + } + ) @property def is_dynamic_table(self) -> bool: diff --git a/dbt/include/snowflake/macros/materializations/dynamic_table.sql b/dbt/include/snowflake/macros/materializations/dynamic_table.sql index 54ecafae8..23dedb65e 100644 --- a/dbt/include/snowflake/macros/materializations/dynamic_table.sql +++ b/dbt/include/snowflake/macros/materializations/dynamic_table.sql @@ -1,68 +1,38 @@ {% materialization dynamic_table, adapter='snowflake' %} - {% set original_query_tag = set_query_tag() %} + {% set query_tag = set_query_tag() %} {% set existing_relation = load_cached_relation(this) %} {% set target_relation = this.incorporate(type=this.DynamicTable) %} - {% set intermediate_relation = make_intermediate_relation(target_relation) %} - {% set backup_relation_type = target_relation.DynamicTable if existing_relation is none else existing_relation.type %} - {% set backup_relation = make_backup_relation(target_relation, backup_relation_type) %} - {{ dynamic_table_setup(backup_relation, intermediate_relation, pre_hooks) }} + {{ run_hooks(pre_hooks) }} - {% set build_sql = dynamic_table_get_build_sql(existing_relation, target_relation, backup_relation, intermediate_relation) %} + {% set build_sql = dynamic_table_get_build_sql(existing_relation, target_relation) %} - {% if build_sql == '' %} - {{ dynamic_table_execute_no_op(target_relation) }} - {% else %} - {{ dynamic_table_execute_build_sql(build_sql, existing_relation, target_relation, post_hooks) }} - {% endif %} + {% if build_sql == '' %} + {{ dynamic_table_execute_no_op(target_relation) }} + {% else %} + {{ dynamic_table_execute_build_sql(build_sql, existing_relation, target_relation) }} + {% endif %} - {{ dynamic_table_teardown(backup_relation, intermediate_relation, post_hooks) }} + {{ run_hooks(post_hooks) }} - {% do unset_query_tag(original_query_tag) %} + {% do unset_query_tag(query_tag) %} {{ return({'relations': [target_relation]}) }} {% endmaterialization %} -{% macro dynamic_table_setup(backup_relation, intermediate_relation, pre_hooks) %} - - -- backup_relation and intermediate_relation should not already exist in the database - -- it's possible these exist because of a previous run that exited unexpectedly - {% set preexisting_backup_relation = load_cached_relation(backup_relation) %} - {% set preexisting_intermediate_relation = load_cached_relation(intermediate_relation) %} - - -- drop the temp relations if they exist already in the database - {{ snowflake__get_drop_dynamic_table_sql(preexisting_backup_relation) }} - {{ snowflake__get_drop_dynamic_table_sql(preexisting_intermediate_relation) }} - - {{ run_hooks(pre_hooks) }} - -{% endmacro %} - - -{% macro dynamic_table_teardown(backup_relation, intermediate_relation, post_hooks) %} - - -- drop the temp relations if they exist to leave the database clean for the next run - {{ snowflake__get_drop_dynamic_table_sql(backup_relation) }} - {{ snowflake__get_drop_dynamic_table_sql(intermediate_relation) }} - - {{ run_hooks(post_hooks) }} - -{% endmacro %} - - -{% macro dynamic_table_get_build_sql(existing_relation, target_relation, backup_relation, intermediate_relation) %} +{% macro dynamic_table_get_build_sql(existing_relation, target_relation) %} {% set full_refresh_mode = should_full_refresh() %} -- determine the scenario we're in: create, full_refresh, alter, refresh data {% if existing_relation is none %} - {% set build_sql = snowflake__get_create_dynamic_table_as_sql(target_relation, sql) %} + {% set build_sql = get_create_sql(target_relation, sql) %} {% elif full_refresh_mode or not existing_relation.is_dynamic_table %} - {% set build_sql = snowflake__get_replace_dynamic_table_as_sql(target_relation, sql, existing_relation, backup_relation, intermediate_relation) %} + {% set build_sql = get_replace_sql(existing_relation, target_relation, sql) %} {% else %} -- get config options @@ -74,7 +44,7 @@ {{ exceptions.warn("No configuration changes were identified on: `" ~ target_relation ~ "`. Continuing.") }} {% elif on_configuration_change == 'apply' %} - {% set build_sql = snowflake__get_alter_dynamic_table_as_sql(target_relation, configuration_changes, sql, existing_relation, backup_relation, intermediate_relation) %} + {% set build_sql = snowflake__get_alter_dynamic_table_as_sql(existing_relation, configuration_changes, target_relation, sql) %} {% elif on_configuration_change == 'continue' %} {% set build_sql = '' %} {{ exceptions.warn("Configuration changes were identified and `on_configuration_change` was set to `continue` for `" ~ target_relation ~ "`") }} @@ -94,17 +64,17 @@ {% endmacro %} -{% macro dynamic_table_execute_no_op(target_relation) %} +{% macro dynamic_table_execute_no_op(relation) %} {% do store_raw_result( name="main", - message="skip " ~ target_relation, + message="skip " ~ relation, code="skip", rows_affected="-1" ) %} {% endmacro %} -{% macro dynamic_table_execute_build_sql(build_sql, existing_relation, target_relation, post_hooks) %} +{% macro dynamic_table_execute_build_sql(build_sql, existing_relation, target_relation) %} {% set grant_config = config.get('grants') %} diff --git a/dbt/include/snowflake/macros/materializations/view.sql b/dbt/include/snowflake/macros/materializations/view.sql index b03fffb02..cb306e79f 100644 --- a/dbt/include/snowflake/macros/materializations/view.sql +++ b/dbt/include/snowflake/macros/materializations/view.sql @@ -1,7 +1,7 @@ {% materialization view, adapter='snowflake' -%} {% set original_query_tag = set_query_tag() %} - {% set to_return = create_or_replace_view() %} + {% set to_return = snowflake__create_or_replace_view() %} {% set target_relation = this.incorporate(type='view') %} diff --git a/dbt/include/snowflake/macros/relations/create.sql b/dbt/include/snowflake/macros/relations/create.sql new file mode 100644 index 000000000..e2cfd38c7 --- /dev/null +++ b/dbt/include/snowflake/macros/relations/create.sql @@ -0,0 +1,11 @@ +{% macro snowflake__get_create_sql(relation, sql) %} + + {% if relation.is_dynamic_table %} + {{ snowflake__get_create_dynamic_table_as_sql(relation, sql) }} + + {% else %} + {{ default__get_create_sql(relation, sql) }} + + {% endif %} + +{% endmacro %} diff --git a/dbt/include/snowflake/macros/relations/drop.sql b/dbt/include/snowflake/macros/relations/drop.sql index 1d1de9325..99b487461 100644 --- a/dbt/include/snowflake/macros/relations/drop.sql +++ b/dbt/include/snowflake/macros/relations/drop.sql @@ -1,9 +1,11 @@ -{% macro snowflake__drop_relation(relation) -%} - {%- if relation.is_dynamic_table -%} - {% call statement('drop_relation', auto_begin=False) -%} - drop dynamic table if exists {{ relation }} - {%- endcall %} - {%- else -%} - {{- default__drop_relation(relation) -}} - {%- endif -%} +{% macro snowflake__get_drop_sql(relation) %} + + {% if relation.is_dynamic_table %} + {{ snowflake__get_drop_dynamic_table_sql(relation) }} + + {% else %} + {{ default__get_drop_sql(relation) }} + + {% endif %} + {% endmacro %} diff --git a/dbt/include/snowflake/macros/relations/dynamic_table/_replace.sql b/dbt/include/snowflake/macros/relations/dynamic_table/_replace.sql deleted file mode 100644 index 939322316..000000000 --- a/dbt/include/snowflake/macros/relations/dynamic_table/_replace.sql +++ /dev/null @@ -1,5 +0,0 @@ -{% macro snowflake__get_replace_dynamic_table_as_sql(target_relation, sql, existing_relation, backup_relation, intermediate_relation) -%} - {{- log('Applying REPLACE to: ' ~ target_relation) -}} - {{ snowflake__get_drop_dynamic_table_sql(existing_relation) }}; - {{ snowflake__get_create_dynamic_table_as_sql(target_relation, sql) }} -{%- endmacro %} diff --git a/dbt/include/snowflake/macros/relations/dynamic_table/alter.sql b/dbt/include/snowflake/macros/relations/dynamic_table/alter.sql index 2d2dd978e..f4b1be699 100644 --- a/dbt/include/snowflake/macros/relations/dynamic_table/alter.sql +++ b/dbt/include/snowflake/macros/relations/dynamic_table/alter.sql @@ -1,15 +1,13 @@ {% macro snowflake__get_alter_dynamic_table_as_sql( - target_relation, - configuration_changes, - sql, existing_relation, - backup_relation, - intermediate_relation + configuration_changes, + target_relation, + sql ) -%} - {{- log('Applying ALTER to: ' ~ target_relation) -}} + {{- log('Applying ALTER to: ' ~ existing_relation) -}} {% if configuration_changes.requires_full_refresh %} - {{- snowflake__get_replace_dynamic_table_as_sql(target_relation, sql, existing_relation, backup_relation, intermediate_relation) -}} + {{- get_replace_sql(existing_relation, target_relation, sql) -}} {% else %} diff --git a/dbt/include/snowflake/macros/relations/dynamic_table/create.sql b/dbt/include/snowflake/macros/relations/dynamic_table/create.sql index 45271be21..bf84c58cb 100644 --- a/dbt/include/snowflake/macros/relations/dynamic_table/create.sql +++ b/dbt/include/snowflake/macros/relations/dynamic_table/create.sql @@ -1,7 +1,6 @@ {% macro snowflake__get_create_dynamic_table_as_sql(relation, sql) -%} - {{- log('Applying CREATE to: ' ~ relation) -}} - create or replace dynamic table {{ relation }} + create dynamic table {{ relation }} target_lag = '{{ config.get("target_lag") }}' warehouse = {{ config.get("snowflake_warehouse") }} as ( diff --git a/dbt/include/snowflake/macros/relations/dynamic_table/replace.sql b/dbt/include/snowflake/macros/relations/dynamic_table/replace.sql new file mode 100644 index 000000000..385ce119c --- /dev/null +++ b/dbt/include/snowflake/macros/relations/dynamic_table/replace.sql @@ -0,0 +1,12 @@ +{% macro snowflake__get_replace_dynamic_table_sql(relation, sql) %} + + create or replace dynamic table {{ relation }} + target_lag = '{{ config.get("target_lag") }}' + warehouse = {{ config.get("snowflake_warehouse") }} + as ( + {{ sql }} + ) + ; + {{ snowflake__refresh_dynamic_table(relation) }} + +{% endmacro %} diff --git a/dbt/include/snowflake/macros/relations/replace.sql b/dbt/include/snowflake/macros/relations/replace.sql new file mode 100644 index 000000000..1e57c135a --- /dev/null +++ b/dbt/include/snowflake/macros/relations/replace.sql @@ -0,0 +1,11 @@ +{% macro snowflake__get_replace_sql(existing_relation, target_relation, sql) %} + + {% if existing_relation.is_dynamic_table and target_relation.is_dynamic_table %} + {{ snowflake__get_replace_dynamic_table_sql(target_relation, sql) }} + + {% else %} + {{ default__get_replace_sql(existing_relation, target_relation, sql) }} + + {% endif %} + +{% endmacro %} diff --git a/dbt/include/snowflake/macros/relations/table/drop.sql b/dbt/include/snowflake/macros/relations/table/drop.sql new file mode 100644 index 000000000..9799d3998 --- /dev/null +++ b/dbt/include/snowflake/macros/relations/table/drop.sql @@ -0,0 +1,3 @@ +{% macro snowflake__get_drop_table_sql(relation) %} + drop table if exists {{ relation }} cascade +{% endmacro %} diff --git a/dbt/include/snowflake/macros/relations/table/rename.sql b/dbt/include/snowflake/macros/relations/table/rename.sql new file mode 100644 index 000000000..7b363e03d --- /dev/null +++ b/dbt/include/snowflake/macros/relations/table/rename.sql @@ -0,0 +1,3 @@ +{%- macro snowflake__get_rename_table_sql(relation, new_name) -%} + alter table {{ relation }} rename to {{ new_name }} +{%- endmacro -%} diff --git a/dbt/include/snowflake/macros/relations/table/replace.sql b/dbt/include/snowflake/macros/relations/table/replace.sql new file mode 100644 index 000000000..6b93e2ab5 --- /dev/null +++ b/dbt/include/snowflake/macros/relations/table/replace.sql @@ -0,0 +1,3 @@ +{% macro snowflake__get_replace_table_sql(relation, sql) %} + {{ snowflake__create_table_as(False, relation, sql) }} +{% endmacro %} diff --git a/dbt/include/snowflake/macros/relations/view/create.sql b/dbt/include/snowflake/macros/relations/view/create.sql index 3212e15c6..d518ac3e1 100644 --- a/dbt/include/snowflake/macros/relations/view/create.sql +++ b/dbt/include/snowflake/macros/relations/view/create.sql @@ -28,3 +28,46 @@ {% macro snowflake__create_view_as(relation, sql) -%} {{ snowflake__create_view_as_with_temp_flag(relation, sql) }} {% endmacro %} + + +/* {# +Vendored from dbt-core for the purpose of overwriting small pieces to support dynamics tables. This should +eventually be retired in favor of a standardized approach. Changed line: + +{%- if old_relation is not none and old_relation.is_table -%} -> +{%- if old_relation is not none and not old_relation.is_view -%} +#} */ + +{% macro snowflake__create_or_replace_view() %} + {%- set identifier = model['alias'] -%} + + {%- set old_relation = adapter.get_relation(database=database, schema=schema, identifier=identifier) -%} + {%- set exists_as_view = (old_relation is not none and old_relation.is_view) -%} + + {%- set target_relation = api.Relation.create( + identifier=identifier, schema=schema, database=database, + type='view') -%} + {% set grant_config = config.get('grants') %} + + {{ run_hooks(pre_hooks) }} + + -- If there's a table with the same name and we weren't told to full refresh, + -- that's an error. If we were told to full refresh, drop it. This behavior differs + -- for Snowflake and BigQuery, so multiple dispatch is used. + {%- if old_relation is not none and not old_relation.is_view -%} + {{ handle_existing_table(should_full_refresh(), old_relation) }} + {%- endif -%} + + -- build model + {% call statement('main') -%} + {{ get_create_view_as_sql(target_relation, sql) }} + {%- endcall %} + + {% set should_revoke = should_revoke(exists_as_view, full_refresh_mode=True) %} + {% do apply_grants(target_relation, grant_config, should_revoke=should_revoke) %} + + {{ run_hooks(post_hooks) }} + + {{ return({'relations': [target_relation]}) }} + +{% endmacro %} diff --git a/dbt/include/snowflake/macros/relations/view/drop.sql b/dbt/include/snowflake/macros/relations/view/drop.sql new file mode 100644 index 000000000..708ca3386 --- /dev/null +++ b/dbt/include/snowflake/macros/relations/view/drop.sql @@ -0,0 +1,3 @@ +{% macro snowflake__get_drop_view_sql(relation) %} + drop view if exists {{ relation }} cascade +{% endmacro %} diff --git a/dbt/include/snowflake/macros/relations/view/rename.sql b/dbt/include/snowflake/macros/relations/view/rename.sql new file mode 100644 index 000000000..4cfd410a4 --- /dev/null +++ b/dbt/include/snowflake/macros/relations/view/rename.sql @@ -0,0 +1,3 @@ +{%- macro snowflake__get_rename_view_sql(relation, new_name) -%} + alter view {{ relation }} rename to {{ new_name }} +{%- endmacro -%} diff --git a/dbt/include/snowflake/macros/relations/view/replace.sql b/dbt/include/snowflake/macros/relations/view/replace.sql new file mode 100644 index 000000000..a46898f01 --- /dev/null +++ b/dbt/include/snowflake/macros/relations/view/replace.sql @@ -0,0 +1,3 @@ +{% macro snowflake__get_replace_view_sql(relation, sql) %} + {{ snowflake__create_view_as(relation, sql) }} +{% endmacro %} diff --git a/tests/functional/adapter/dynamic_table_tests/test_dynamic_tables_basic.py b/tests/functional/adapter/dynamic_table_tests/test_dynamic_tables_basic.py index a03d9d93c..a17f5d267 100644 --- a/tests/functional/adapter/dynamic_table_tests/test_dynamic_tables_basic.py +++ b/tests/functional/adapter/dynamic_table_tests/test_dynamic_tables_basic.py @@ -3,7 +3,6 @@ import pytest from dbt.tests.util import ( - assert_message_in_logs, get_model_file, run_dbt, run_dbt_and_capture, @@ -89,41 +88,26 @@ def my_seed(self, project) -> SnowflakeRelation: ) @staticmethod - def swap_table_to_dynamic_table(project, table): - initial_model = get_model_file(project, table) - new_model = initial_model.replace("materialized='table'", "materialized='dynamic_table'") - set_model_file(project, table, new_model) - - @staticmethod - def swap_view_to_dynamic_table(project, view): - initial_model = get_model_file(project, view) - new_model = initial_model.replace("materialized='view'", "materialized='dynamic_table'") - set_model_file(project, view, new_model) - - @staticmethod - def swap_dynamic_table_to_table(project, dynamic_table): - initial_model = get_model_file(project, dynamic_table) - new_model = initial_model.replace("materialized='dynamic_table'", "materialized='table'") - set_model_file(project, dynamic_table, new_model) - - @staticmethod - def swap_dynamic_table_to_view(project, dynamic_table): - initial_model = get_model_file(project, dynamic_table) - new_model = initial_model.replace("materialized='dynamic_table'", "materialized='view'") - set_model_file(project, dynamic_table, new_model) + def load_model(project, current_model, new_model): + model_to_load = get_model_file(project, new_model) + set_model_file(project, current_model, model_to_load) @pytest.fixture(scope="function", autouse=True) - def setup(self, project, my_dynamic_table): + def setup(self, project, my_dynamic_table, my_view, my_table): run_dbt(["seed"]) run_dbt(["run", "--models", my_dynamic_table.identifier, "--full-refresh"]) # the tests touch these files, store their contents in memory - initial_model = get_model_file(project, my_dynamic_table) + my_dynamic_table_config = get_model_file(project, my_dynamic_table) + my_view_config = get_model_file(project, my_view) + my_table_config = get_model_file(project, my_table) yield # and then reset them after the test runs - set_model_file(project, my_dynamic_table, initial_model) + set_model_file(project, my_dynamic_table, my_dynamic_table_config) + set_model_file(project, my_view, my_view_config) + set_model_file(project, my_table, my_table_config) project.run_sql(f"drop schema if exists {project.test_schema} cascade") def test_dynamic_table_create(self, project, my_dynamic_table): @@ -141,52 +125,39 @@ def test_dynamic_table_full_refresh(self, project, my_dynamic_table): ["--debug", "run", "--models", my_dynamic_table.identifier, "--full-refresh"] ) assert self.query_relation_type(project, my_dynamic_table) == "dynamic_table" - assert_message_in_logs(f"Applying REPLACE to: {my_dynamic_table}", logs) - @pytest.mark.skip( - "The current implementation does not support overwriting tables with dynamic tables." - ) - def test_dynamic_table_replaces_table(self, project, my_table): + def test_dynamic_table_replaces_table(self, project, my_table, my_dynamic_table): run_dbt(["run", "--models", my_table.identifier]) assert self.query_relation_type(project, my_table) == "table" - self.swap_table_to_dynamic_table(project, my_table) + self.load_model(project, my_table, my_dynamic_table) run_dbt(["run", "--models", my_table.identifier]) assert self.query_relation_type(project, my_table) == "dynamic_table" - @pytest.mark.skip( - "The current implementation does not support overwriting views with dynamic tables." - ) - def test_dynamic_table_replaces_view(self, project, my_view): + def test_dynamic_table_replaces_view(self, project, my_view, my_dynamic_table): run_dbt(["run", "--models", my_view.identifier]) assert self.query_relation_type(project, my_view) == "view" - self.swap_view_to_dynamic_table(project, my_view) + self.load_model(project, my_view, my_dynamic_table) run_dbt(["run", "--models", my_view.identifier]) assert self.query_relation_type(project, my_view) == "dynamic_table" - @pytest.mark.skip( - "The current implementation does not support overwriting dynamic tables with tables." - ) - def test_table_replaces_dynamic_table(self, project, my_dynamic_table): + def test_table_replaces_dynamic_table(self, project, my_dynamic_table, my_table): run_dbt(["run", "--models", my_dynamic_table.identifier]) assert self.query_relation_type(project, my_dynamic_table) == "dynamic_table" - self.swap_dynamic_table_to_table(project, my_dynamic_table) + self.load_model(project, my_dynamic_table, my_table) run_dbt(["run", "--models", my_dynamic_table.identifier]) assert self.query_relation_type(project, my_dynamic_table) == "table" - @pytest.mark.skip( - "The current implementation does not support overwriting dynamic tables with views." - ) - def test_view_replaces_dynamic_table(self, project, my_dynamic_table): + def test_view_replaces_dynamic_table(self, project, my_dynamic_table, my_view): run_dbt(["run", "--models", my_dynamic_table.identifier]) assert self.query_relation_type(project, my_dynamic_table) == "dynamic_table" - self.swap_dynamic_table_to_view(project, my_dynamic_table) + self.load_model(project, my_dynamic_table, my_view) run_dbt(["run", "--models", my_dynamic_table.identifier]) assert self.query_relation_type(project, my_dynamic_table) == "view" diff --git a/tests/functional/adapter/dynamic_table_tests/test_dynamic_tables_changes.py b/tests/functional/adapter/dynamic_table_tests/test_dynamic_tables_changes.py index 84fa22a0c..a88adf398 100644 --- a/tests/functional/adapter/dynamic_table_tests/test_dynamic_tables_changes.py +++ b/tests/functional/adapter/dynamic_table_tests/test_dynamic_tables_changes.py @@ -118,8 +118,12 @@ def test_full_refresh_occurs_with_changes(self, project, my_dynamic_table): ["--debug", "run", "--models", my_dynamic_table.identifier, "--full-refresh"] ) assert self.query_relation_type(project, my_dynamic_table) == "dynamic_table" - assert_message_in_logs(f"Applying ALTER to: {my_dynamic_table}", logs, False) - assert_message_in_logs(f"Applying REPLACE to: {my_dynamic_table}", logs) + assert_message_in_logs( + f"Applying ALTER to: {my_dynamic_table.render().upper()}", logs.replace('"', ""), False + ) + assert_message_in_logs( + f"Applying REPLACE to: {my_dynamic_table.render().upper()}", logs.replace('"', "") + ) class TestSnowflakeDynamicTableChangesApply(SnowflakeDynamicTableChanges): @@ -138,8 +142,14 @@ def test_change_is_applied_via_alter(self, project, adapter, my_dynamic_table): # self.check_state_alter_change_is_applied(adapter, my_dynamic_table) - assert_message_in_logs(f"Applying ALTER to: {my_dynamic_table}", logs) - assert_message_in_logs(f"Applying REPLACE to: {my_dynamic_table}", logs, False) + assert_message_in_logs( + f"Applying ALTER to: {my_dynamic_table.render().upper()}", logs.replace('"', "") + ) + assert_message_in_logs( + f"Applying REPLACE to: {my_dynamic_table.render().upper()}", + logs.replace('"', ""), + False, + ) def test_change_is_applied_via_alter_downstream(self, project, adapter, my_dynamic_table): """ @@ -152,8 +162,14 @@ def test_change_is_applied_via_alter_downstream(self, project, adapter, my_dynam # self.check_state_alter_change_is_applied_downstream(adapter, my_dynamic_table) - assert_message_in_logs(f"Applying ALTER to: {my_dynamic_table}", logs) - assert_message_in_logs(f"Applying REPLACE to: {my_dynamic_table}", logs, False) + assert_message_in_logs( + f"Applying ALTER to: {my_dynamic_table.render().upper()}", logs.replace('"', "") + ) + assert_message_in_logs( + f"Applying REPLACE to: {my_dynamic_table.render().upper()}", + logs.replace('"', ""), + False, + ) @pytest.mark.skip( "dbt-snowflake does not currently monitor any changes the trigger a full refresh" @@ -168,7 +184,9 @@ def test_change_is_applied_via_replace(self, project, adapter, my_dynamic_table) # self.check_state_alter_change_is_applied(adapter, my_dynamic_table) # self.check_state_replace_change_is_applied(adapter, my_dynamic_table) - assert_message_in_logs(f"Applying REPLACE to: {my_dynamic_table}", logs) + assert_message_in_logs( + f"Applying REPLACE to: {my_dynamic_table.render().upper()}", logs.replace('"', "") + ) class TestSnowflakeDynamicTableChangesContinue(SnowflakeDynamicTableChanges): @@ -192,8 +210,14 @@ def test_change_is_not_applied_via_alter(self, project, adapter, my_dynamic_tabl f" to `continue` for `{my_dynamic_table}`", logs, ) - assert_message_in_logs(f"Applying ALTER to: {my_dynamic_table}", logs, False) - assert_message_in_logs(f"Applying REPLACE to: {my_dynamic_table}", logs, False) + assert_message_in_logs( + f"Applying ALTER to: {my_dynamic_table.render().upper()}", logs.replace('"', ""), False + ) + assert_message_in_logs( + f"Applying REPLACE to: {my_dynamic_table.render().upper()}", + logs.replace('"', ""), + False, + ) def test_change_is_not_applied_via_replace(self, project, adapter, my_dynamic_table): # self.check_start_state(adapter, my_dynamic_table) @@ -209,8 +233,14 @@ def test_change_is_not_applied_via_replace(self, project, adapter, my_dynamic_ta f" to `continue` for `{my_dynamic_table}`", logs, ) - assert_message_in_logs(f"Applying ALTER to: {my_dynamic_table}", logs, False) - assert_message_in_logs(f"Applying REPLACE to: {my_dynamic_table}", logs, False) + assert_message_in_logs( + f"Applying ALTER to: {my_dynamic_table.render().upper()}", logs.replace('"', ""), False + ) + assert_message_in_logs( + f"Applying REPLACE to: {my_dynamic_table.render().upper()}", + logs.replace('"', ""), + False, + ) class TestSnowflakeDynamicTableChangesFailMixin(SnowflakeDynamicTableChanges): @@ -236,8 +266,14 @@ def test_change_is_not_applied_via_alter(self, project, adapter, my_dynamic_tabl f" to `fail` for `{my_dynamic_table}`", logs, ) - assert_message_in_logs(f"Applying ALTER to: {my_dynamic_table}", logs, False) - assert_message_in_logs(f"Applying REPLACE to: {my_dynamic_table}", logs, False) + assert_message_in_logs( + f"Applying ALTER to: {my_dynamic_table.render().upper()}", logs.replace('"', ""), False + ) + assert_message_in_logs( + f"Applying REPLACE to: {my_dynamic_table.render().upper()}", + logs.replace('"', ""), + False, + ) def test_change_is_not_applied_via_replace(self, project, adapter, my_dynamic_table): # self.check_start_state(adapter, my_dynamic_table) @@ -255,5 +291,11 @@ def test_change_is_not_applied_via_replace(self, project, adapter, my_dynamic_ta f" to `fail` for `{my_dynamic_table}`", logs, ) - assert_message_in_logs(f"Applying ALTER to: {my_dynamic_table}", logs, False) - assert_message_in_logs(f"Applying REPLACE to: {my_dynamic_table}", logs, False) + assert_message_in_logs( + f"Applying ALTER to: {my_dynamic_table.render().upper()}", logs.replace('"', ""), False + ) + assert_message_in_logs( + f"Applying REPLACE to: {my_dynamic_table.render().upper()}", + logs.replace('"', ""), + False, + )