diff --git a/.changes/unreleased/Fixes-20230817-185739.yaml b/.changes/unreleased/Fixes-20230817-185739.yaml new file mode 100644 index 00000000000..74b1ed7551e --- /dev/null +++ b/.changes/unreleased/Fixes-20230817-185739.yaml @@ -0,0 +1,6 @@ +kind: Fixes +body: Add support for swapping materialized views with tables/views and vice versa +time: 2023-08-17T18:57:39.01958-04:00 +custom: + Author: mikealfare + Issue: "8449" diff --git a/core/dbt/adapters/base/relation.py b/core/dbt/adapters/base/relation.py index ae4e585d524..fa9cf6bfabb 100644 --- a/core/dbt/adapters/base/relation.py +++ b/core/dbt/adapters/base/relation.py @@ -1,6 +1,6 @@ from collections.abc import Hashable from dataclasses import dataclass, field -from typing import Optional, TypeVar, Any, Type, Dict, Iterator, Tuple, Set +from typing import Optional, TypeVar, Any, Type, Dict, Iterator, Tuple, Set, List from dbt.contracts.graph.nodes import SourceDefinition, ManifestNode, ResultNode, ParsedNode from dbt.contracts.relation import ( @@ -35,6 +35,10 @@ class BaseRelation(FakeAPIObject, Hashable): include_policy: Policy = field(default_factory=lambda: Policy()) quote_policy: Policy = field(default_factory=lambda: Policy()) dbt_created: bool = False + # register relation types that can be renamed for the purpose of replacing relations using stages and backups + renameable_relations: List[str] = field( + default_factory=lambda: [RelationType.Table, RelationType.View] + ) def _is_exactish_match(self, field: ComponentName, value: str) -> bool: if self.dbt_created and self.quote_policy.get_part(field) is False: @@ -169,7 +173,6 @@ def without_identifier(self) -> "BaseRelation": return self.include(identifier=False).replace_path(identifier=None) def _render_iterator(self) -> Iterator[Tuple[Optional[ComponentName], Optional[str]]]: - for key in ComponentName: path_part: Optional[str] = None if self.include_policy.get_part(key): @@ -286,6 +289,10 @@ def create( ) return cls.from_dict(kwargs) + @property + def can_be_renamed(self): + return self.type in self.renameable_relations + def __repr__(self) -> str: return "<{} {}>".format(self.__class__.__name__, self.render()) diff --git a/core/dbt/include/global_project/macros/adapters/relation.sql b/core/dbt/include/global_project/macros/adapters/relation.sql index 228bb03dcc4..1c2bd880079 100644 --- a/core/dbt/include/global_project/macros/adapters/relation.sql +++ b/core/dbt/include/global_project/macros/adapters/relation.sql @@ -77,10 +77,3 @@ {% macro load_relation(relation) %} {{ return(load_cached_relation(relation)) }} {% endmacro %} - - -{% macro drop_relation_if_exists(relation) %} - {% if relation is not none %} - {{ adapter.drop_relation(relation) }} - {% endif %} -{% endmacro %} diff --git a/core/dbt/include/global_project/macros/materializations/models/materialized_view/materialized_view.sql b/core/dbt/include/global_project/macros/materializations/models/materialized_view/materialized_view.sql index 015f6cb8585..6dc30bf9a9a 100644 --- a/core/dbt/include/global_project/macros/materializations/models/materialized_view/materialized_view.sql +++ b/core/dbt/include/global_project/macros/materializations/models/materialized_view/materialized_view.sql @@ -57,7 +57,7 @@ {% if existing_relation is none %} {% set build_sql = get_create_materialized_view_as_sql(target_relation, sql) %} {% elif full_refresh_mode or not existing_relation.is_materialized_view %} - {% set build_sql = get_replace_materialized_view_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 diff --git a/core/dbt/include/global_project/macros/materializations/models/view/create_or_replace_view.sql b/core/dbt/include/global_project/macros/materializations/models/view/create_or_replace_view.sql index 2846a322e82..e4279a0b124 100644 --- a/core/dbt/include/global_project/macros/materializations/models/view/create_or_replace_view.sql +++ b/core/dbt/include/global_project/macros/materializations/models/view/create_or_replace_view.sql @@ -1,7 +1,7 @@ /* {# Core materialization implementation. BigQuery and Snowflake are similar - because both can use `create or replace view` where the resulting view schema - is not necessarily the same as the existing view. On Redshift, this would + because both can use `create or replace view` where the resulting view's columns + are not necessarily the same as those of the existing view. On Redshift, this would result in: ERROR: cannot change number of columns in view This implementation is superior to the create_temp, swap_with_existing, drop_old diff --git a/core/dbt/include/global_project/macros/relations/create.sql b/core/dbt/include/global_project/macros/relations/create.sql new file mode 100644 index 00000000000..0cd1e0a70a3 --- /dev/null +++ b/core/dbt/include/global_project/macros/relations/create.sql @@ -0,0 +1,17 @@ +{%- macro get_create_sql(relation, sql) -%} + {{- log('Applying CREATE to: ' ~ relation) -}} + {{- adapter.dispatch('get_create_sql', 'dbt')(relation, sql) -}} +{%- endmacro -%} + + +{%- macro default__get_create_sql(relation, sql) -%} + + {%- if relation.is_materialized_view -%} + {{ get_create_materialized_view_as_sql(relation, sql) }} + + {%- else -%} + {{- exceptions.raise_compiler_error("`get_create_sql` has not been implemented for: " ~ relation.type ) -}} + + {%- endif -%} + +{%- endmacro -%} diff --git a/core/dbt/include/global_project/macros/relations/create_backup.sql b/core/dbt/include/global_project/macros/relations/create_backup.sql new file mode 100644 index 00000000000..f3fe39a6f32 --- /dev/null +++ b/core/dbt/include/global_project/macros/relations/create_backup.sql @@ -0,0 +1,17 @@ +{%- macro get_create_backup_sql(relation) -%} + {{- log('Applying CREATE BACKUP to: ' ~ relation) -}} + {{- adapter.dispatch('get_create_backup_sql', 'dbt')(relation) -}} +{%- endmacro -%} + + +{%- macro default__get_create_backup_sql(relation) -%} + + -- get the standard backup name + {% set backup_relation = make_backup_relation(relation, relation.type) %} + + -- drop any pre-existing backup + {{ get_drop_sql(backup_relation) }}; + + {{ get_rename_sql(relation, backup_relation.identifier) }} + +{%- endmacro -%} diff --git a/core/dbt/include/global_project/macros/relations/create_intermediate.sql b/core/dbt/include/global_project/macros/relations/create_intermediate.sql new file mode 100644 index 00000000000..a6bbadc42e1 --- /dev/null +++ b/core/dbt/include/global_project/macros/relations/create_intermediate.sql @@ -0,0 +1,17 @@ +{%- macro get_create_intermediate_sql(relation, sql) -%} + {{- log('Applying CREATE INTERMEDIATE to: ' ~ relation) -}} + {{- adapter.dispatch('get_create_intermediate_sql', 'dbt')(relation, sql) -}} +{%- endmacro -%} + + +{%- macro default__get_create_intermediate_sql(relation, sql) -%} + + -- get the standard intermediate name + {% set intermediate_relation = make_intermediate_relation(relation) %} + + -- drop any pre-existing intermediate + {{ get_drop_sql(intermediate_relation) }}; + + {{ get_create_sql(intermediate_relation, sql) }} + +{%- endmacro -%} diff --git a/core/dbt/include/global_project/macros/relations/drop.sql b/core/dbt/include/global_project/macros/relations/drop.sql index d02ad9327d2..58abd14d9aa 100644 --- a/core/dbt/include/global_project/macros/relations/drop.sql +++ b/core/dbt/include/global_project/macros/relations/drop.sql @@ -1,17 +1,41 @@ +{%- macro get_drop_sql(relation) -%} + {{- log('Applying DROP to: ' ~ relation) -}} + {{- adapter.dispatch('get_drop_sql', 'dbt')(relation) -}} +{%- endmacro -%} + + +{%- macro default__get_drop_sql(relation) -%} + + {%- if relation.is_view -%} + {{ drop_view(relation) }} + + {%- elif relation.is_table -%} + {{ drop_table(relation) }} + + {%- elif relation.is_materialized_view -%} + {{ drop_materialized_view(relation) }} + + {%- else -%} + drop {{ relation.type }} if exists {{ relation }} cascade + + {%- endif -%} + +{%- endmacro -%} + + {% macro drop_relation(relation) -%} {{ return(adapter.dispatch('drop_relation', 'dbt')(relation)) }} {% endmacro %} {% macro default__drop_relation(relation) -%} {% call statement('drop_relation', auto_begin=False) -%} - {%- if relation.is_table -%} - {{- drop_table(relation) -}} - {%- elif relation.is_view -%} - {{- drop_view(relation) -}} - {%- elif relation.is_materialized_view -%} - {{- drop_materialized_view(relation) -}} - {%- else -%} - drop {{ relation.type }} if exists {{ relation }} cascade - {%- endif -%} + {{ get_drop_sql(relation) }} {%- endcall %} {% endmacro %} + + +{% macro drop_relation_if_exists(relation) %} + {% if relation is not none %} + {{ adapter.drop_relation(relation) }} + {% endif %} +{% endmacro %} diff --git a/core/dbt/include/global_project/macros/relations/drop_backup.sql b/core/dbt/include/global_project/macros/relations/drop_backup.sql new file mode 100644 index 00000000000..e70f7981e77 --- /dev/null +++ b/core/dbt/include/global_project/macros/relations/drop_backup.sql @@ -0,0 +1,14 @@ +{%- macro get_drop_backup_sql(relation) -%} + {{- log('Applying DROP BACKUP to: ' ~ relation) -}} + {{- adapter.dispatch('get_drop_backup_sql', 'dbt')(relation) -}} +{%- endmacro -%} + + +{%- macro default__get_drop_backup_sql(relation) -%} + + -- get the standard backup name + {% set backup_relation = make_backup_relation(relation, relation.type) %} + + {{ get_drop_sql(backup_relation) }} + +{%- endmacro -%} diff --git a/core/dbt/include/global_project/macros/adapters/relations/materialized_view/_replace.sql b/core/dbt/include/global_project/macros/relations/materialized_view/_replace.sql similarity index 100% rename from core/dbt/include/global_project/macros/adapters/relations/materialized_view/_replace.sql rename to core/dbt/include/global_project/macros/relations/materialized_view/_replace.sql diff --git a/core/dbt/include/global_project/macros/adapters/relations/materialized_view/alter.sql b/core/dbt/include/global_project/macros/relations/materialized_view/alter.sql similarity index 100% rename from core/dbt/include/global_project/macros/adapters/relations/materialized_view/alter.sql rename to core/dbt/include/global_project/macros/relations/materialized_view/alter.sql diff --git a/core/dbt/include/global_project/macros/adapters/relations/materialized_view/create.sql b/core/dbt/include/global_project/macros/relations/materialized_view/create.sql similarity index 88% rename from core/dbt/include/global_project/macros/adapters/relations/materialized_view/create.sql rename to core/dbt/include/global_project/macros/relations/materialized_view/create.sql index 8b479964e6f..a0f2614c9ca 100644 --- a/core/dbt/include/global_project/macros/adapters/relations/materialized_view/create.sql +++ b/core/dbt/include/global_project/macros/relations/materialized_view/create.sql @@ -1,5 +1,4 @@ {% macro get_create_materialized_view_as_sql(relation, sql) -%} - {{- log('Applying CREATE to: ' ~ relation) -}} {{- adapter.dispatch('get_create_materialized_view_as_sql', 'dbt')(relation, sql) -}} {%- endmacro %} diff --git a/core/dbt/include/global_project/macros/adapters/relations/materialized_view/drop.sql b/core/dbt/include/global_project/macros/relations/materialized_view/drop.sql similarity index 85% rename from core/dbt/include/global_project/macros/adapters/relations/materialized_view/drop.sql rename to core/dbt/include/global_project/macros/relations/materialized_view/drop.sql index d176d2b759d..e60e1dc24d0 100644 --- a/core/dbt/include/global_project/macros/adapters/relations/materialized_view/drop.sql +++ b/core/dbt/include/global_project/macros/relations/materialized_view/drop.sql @@ -5,9 +5,10 @@ actually executes the drop, and `get_drop_sql`, which returns the template. */ #} {% macro drop_materialized_view(relation) -%} - {{ return(adapter.dispatch('drop_materialized_view', 'dbt')(relation)) }} + {{ return(adapter.dispatch('drop_materialized_view', 'dbt')(relation)) }} {%- endmacro %} + {% macro default__drop_materialized_view(relation) -%} drop materialized view if exists {{ relation }} cascade {%- endmacro %} diff --git a/core/dbt/include/global_project/macros/adapters/relations/materialized_view/refresh.sql b/core/dbt/include/global_project/macros/relations/materialized_view/refresh.sql similarity index 100% rename from core/dbt/include/global_project/macros/adapters/relations/materialized_view/refresh.sql rename to core/dbt/include/global_project/macros/relations/materialized_view/refresh.sql diff --git a/core/dbt/include/global_project/macros/relations/materialized_view/rename.sql b/core/dbt/include/global_project/macros/relations/materialized_view/rename.sql new file mode 100644 index 00000000000..abd5babf68e --- /dev/null +++ b/core/dbt/include/global_project/macros/relations/materialized_view/rename.sql @@ -0,0 +1,10 @@ +{% macro get_rename_materialized_view_sql(relation, new_name) %} + {{- adapter.dispatch('get_rename_materialized_view_sql', 'dbt')(relation, new_name) -}} +{% endmacro %} + + +{% macro default__get_rename_materialized_view_sql(relation, new_name) %} + {{ exceptions.raise_compiler_error( + "`get_rename_materialized_view_sql` has not been implemented for this adapter." + ) }} +{% endmacro %} diff --git a/core/dbt/include/global_project/macros/relations/rename.sql b/core/dbt/include/global_project/macros/relations/rename.sql index 7d6c979cfc1..d7f3a72e29a 100644 --- a/core/dbt/include/global_project/macros/relations/rename.sql +++ b/core/dbt/include/global_project/macros/relations/rename.sql @@ -1,3 +1,28 @@ +{%- macro get_rename_sql(relation, new_name) -%} + {{- log('Applying RENAME to: ' ~ relation) -}} + {{- adapter.dispatch('get_rename_sql', 'dbt')(relation, new_name) -}} +{%- endmacro -%} + + +{%- macro default__get_rename_sql(relation, new_name) -%} + + {%- if relation.is_view -%} + {{ get_rename_view_sql(relation, new_name) }} + + {%- elif relation.is_table -%} + {{ get_rename_table_sql(relation, new_name) }} + + {%- elif relation.is_materialized_view -%} + {{ get_rename_materialized_view_sql(relation, new_name) }} + + {%- else -%} + {{- exceptions.raise_compiler_error("`get_rename_sql` has not been implemented for: " ~ relation.type ) -}} + + {%- endif -%} + +{%- endmacro -%} + + {% macro rename_relation(from_relation, to_relation) -%} {{ return(adapter.dispatch('rename_relation', 'dbt')(from_relation, to_relation)) }} {% endmacro %} diff --git a/core/dbt/include/global_project/macros/relations/rename_intermediate.sql b/core/dbt/include/global_project/macros/relations/rename_intermediate.sql new file mode 100644 index 00000000000..5df238b67d7 --- /dev/null +++ b/core/dbt/include/global_project/macros/relations/rename_intermediate.sql @@ -0,0 +1,14 @@ +{%- macro get_rename_intermediate_sql(relation) -%} + {{- log('Applying RENAME INTERMEDIATE to: ' ~ relation) -}} + {{- adapter.dispatch('get_rename_intermediate_sql', 'dbt')(relation) -}} +{%- endmacro -%} + + +{%- macro default__get_rename_intermediate_sql(relation) -%} + + -- get the standard intermediate name + {% set intermediate_relation = make_intermediate_relation(relation) %} + + {{ get_rename_sql(intermediate_relation, relation.identifier) }} + +{%- endmacro -%} diff --git a/core/dbt/include/global_project/macros/relations/replace.sql b/core/dbt/include/global_project/macros/relations/replace.sql new file mode 100644 index 00000000000..77c6c8baa0e --- /dev/null +++ b/core/dbt/include/global_project/macros/relations/replace.sql @@ -0,0 +1,35 @@ +{% macro get_replace_sql(existing_relation, target_relation, sql) %} + {{- log('Applying REPLACE to: ' ~ existing_relation) -}} + {{- adapter.dispatch('get_replace_sql', 'dbt')(existing_relation, target_relation, sql) -}} +{% endmacro %} + + +{% macro default__get_replace_sql(existing_relation, target_relation, sql) %} + + {# /* create target_relation as an intermediate relation, then swap it out with the existing one using a backup */ #} + {%- if target_relation.can_be_renamed and existing_relation.can_be_renamed -%} + {{ get_create_intermediate_sql(target_relation, sql) }}; + {{ get_create_backup_sql(existing_relation) }}; + {{ get_rename_intermediate_sql(target_relation) }}; + {{ get_drop_backup_sql(existing_relation) }} + + {# /* create target_relation as an intermediate relation, then swap it out with the existing one using drop */ #} + {%- elif target_relation.can_be_renamed -%} + {{ get_create_intermediate_sql(target_relation, sql) }}; + {{ get_drop_sql(existing_relation) }}; + {{ get_rename_intermediate_sql(target_relation) }} + + {# /* create target_relation in place by first backing up the existing relation */ #} + {%- elif existing_relation.can_be_renamed -%} + {{ get_create_backup_sql(existing_relation) }}; + {{ get_create_sql(target_relation, sql) }}; + {{ get_drop_backup_sql(existing_relation) }} + + {# /* no renaming is allowed, so just drop and create */ #} + {%- else -%} + {{ get_drop_sql(existing_relation) }}; + {{ get_create_sql(target_relation, sql) }} + + {%- endif -%} + +{% endmacro %} diff --git a/core/dbt/include/global_project/macros/adapters/relations/table/drop.sql b/core/dbt/include/global_project/macros/relations/table/drop.sql similarity index 86% rename from core/dbt/include/global_project/macros/adapters/relations/table/drop.sql rename to core/dbt/include/global_project/macros/relations/table/drop.sql index 152676e3caa..359bab66db5 100644 --- a/core/dbt/include/global_project/macros/adapters/relations/table/drop.sql +++ b/core/dbt/include/global_project/macros/relations/table/drop.sql @@ -5,9 +5,10 @@ actually executes the drop, and `get_drop_sql`, which returns the template. */ #} {% macro drop_table(relation) -%} - {{ return(adapter.dispatch('drop_table', 'dbt')(relation)) }} + {{ return(adapter.dispatch('drop_table', 'dbt')(relation)) }} {%- endmacro %} + {% macro default__drop_table(relation) -%} drop table if exists {{ relation }} cascade {%- endmacro %} diff --git a/core/dbt/include/global_project/macros/relations/table/rename.sql b/core/dbt/include/global_project/macros/relations/table/rename.sql new file mode 100644 index 00000000000..4688780d68d --- /dev/null +++ b/core/dbt/include/global_project/macros/relations/table/rename.sql @@ -0,0 +1,10 @@ +{% macro get_rename_table_sql(relation, new_name) %} + {{- adapter.dispatch('get_rename_table_sql', 'dbt')(relation, new_name) -}} +{% endmacro %} + + +{% macro default__get_rename_table_sql(relation, new_name) %} + {{ exceptions.raise_compiler_error( + "`get_rename_table_sql` has not been implemented for this adapter." + ) }} +{% endmacro %} diff --git a/core/dbt/include/global_project/macros/adapters/relations/view/drop.sql b/core/dbt/include/global_project/macros/relations/view/drop.sql similarity index 86% rename from core/dbt/include/global_project/macros/adapters/relations/view/drop.sql rename to core/dbt/include/global_project/macros/relations/view/drop.sql index 46691b9e429..c905f8da059 100644 --- a/core/dbt/include/global_project/macros/adapters/relations/view/drop.sql +++ b/core/dbt/include/global_project/macros/relations/view/drop.sql @@ -5,9 +5,10 @@ actually executes the drop, and `get_drop_sql`, which returns the template. */ #} {% macro drop_view(relation) -%} - {{ return(adapter.dispatch('drop_view', 'dbt')(relation)) }} + {{ return(adapter.dispatch('drop_view', 'dbt')(relation)) }} {%- endmacro %} + {% macro default__drop_view(relation) -%} drop view if exists {{ relation }} cascade {%- endmacro %} diff --git a/core/dbt/include/global_project/macros/relations/view/rename.sql b/core/dbt/include/global_project/macros/relations/view/rename.sql new file mode 100644 index 00000000000..165dd514e40 --- /dev/null +++ b/core/dbt/include/global_project/macros/relations/view/rename.sql @@ -0,0 +1,10 @@ +{% macro get_rename_view_sql(relation, new_name) %} + {{- adapter.dispatch('get_rename_view_sql', 'dbt')(relation, new_name) -}} +{% endmacro %} + + +{% macro default__get_rename_view_sql(relation, new_name) %} + {{ exceptions.raise_compiler_error( + "`get_rename_view_sql` has not been implemented for this adapter." + ) }} +{% endmacro %} diff --git a/plugins/postgres/dbt/adapters/postgres/relation.py b/plugins/postgres/dbt/adapters/postgres/relation.py index 43822efb11f..26516af4819 100644 --- a/plugins/postgres/dbt/adapters/postgres/relation.py +++ b/plugins/postgres/dbt/adapters/postgres/relation.py @@ -7,6 +7,7 @@ RelationResults, ) from dbt.context.providers import RuntimeConfigObject +from dbt.contracts.relation import RelationType from dbt.exceptions import DbtRuntimeError from dbt.adapters.postgres.relation_configs import ( @@ -20,6 +21,12 @@ @dataclass(frozen=True, eq=False, repr=False) class PostgresRelation(BaseRelation): + relations_that_can_be_renamed = [ + RelationType.View, + RelationType.Table, + RelationType.MaterializedView, + ] + def __post_init__(self): # Check for length of Postgres table/view names. # Check self.type to exclude test relation identifiers diff --git a/plugins/postgres/dbt/include/postgres/macros/relations/materialized_view/alter.sql b/plugins/postgres/dbt/include/postgres/macros/relations/materialized_view/alter.sql index 0dd5189783d..d1270303bd7 100644 --- a/plugins/postgres/dbt/include/postgres/macros/relations/materialized_view/alter.sql +++ b/plugins/postgres/dbt/include/postgres/macros/relations/materialized_view/alter.sql @@ -10,7 +10,7 @@ -- apply a full refresh immediately if needed {% if configuration_changes.requires_full_refresh %} - {{ get_replace_materialized_view_as_sql(relation, sql, existing_relation, backup_relation, intermediate_relation) }} + {{ get_replace_sql(existing_relation, relation, sql) }} -- otherwise apply individual changes as needed {% else %} diff --git a/plugins/postgres/dbt/include/postgres/macros/relations/materialized_view/drop.sql b/plugins/postgres/dbt/include/postgres/macros/relations/materialized_view/drop.sql new file mode 100644 index 00000000000..2263bb652b2 --- /dev/null +++ b/plugins/postgres/dbt/include/postgres/macros/relations/materialized_view/drop.sql @@ -0,0 +1,3 @@ +{% macro postgres__drop_materialized_view(relation) -%} + drop materialized view if exists {{ relation }} cascade +{%- endmacro %} diff --git a/plugins/postgres/dbt/include/postgres/macros/relations/table/drop.sql b/plugins/postgres/dbt/include/postgres/macros/relations/table/drop.sql new file mode 100644 index 00000000000..146cfc8273f --- /dev/null +++ b/plugins/postgres/dbt/include/postgres/macros/relations/table/drop.sql @@ -0,0 +1,3 @@ +{% macro postgres__drop_table(relation) -%} + drop table if exists {{ relation }} cascade +{%- endmacro %} diff --git a/plugins/postgres/dbt/include/postgres/macros/relations/table/rename.sql b/plugins/postgres/dbt/include/postgres/macros/relations/table/rename.sql new file mode 100644 index 00000000000..bc3c234abb7 --- /dev/null +++ b/plugins/postgres/dbt/include/postgres/macros/relations/table/rename.sql @@ -0,0 +1,3 @@ +{% macro postgres__get_rename_table_sql(relation, new_name) %} + alter table {{ relation }} rename to {{ new_name }} +{% endmacro %} diff --git a/plugins/postgres/dbt/include/postgres/macros/relations/view/drop.sql b/plugins/postgres/dbt/include/postgres/macros/relations/view/drop.sql new file mode 100644 index 00000000000..46bd5a063eb --- /dev/null +++ b/plugins/postgres/dbt/include/postgres/macros/relations/view/drop.sql @@ -0,0 +1,3 @@ +{% macro postgres__drop_view(relation) -%} + drop view if exists {{ relation }} cascade +{%- endmacro %} diff --git a/plugins/postgres/dbt/include/postgres/macros/relations/view/rename.sql b/plugins/postgres/dbt/include/postgres/macros/relations/view/rename.sql new file mode 100644 index 00000000000..3c890a5b2d0 --- /dev/null +++ b/plugins/postgres/dbt/include/postgres/macros/relations/view/rename.sql @@ -0,0 +1,3 @@ +{% macro postgres__get_rename_view_sql(relation, new_name) %} + alter view {{ relation }} rename to {{ new_name }} +{% endmacro %} diff --git a/tests/functional/materializations/materialized_view_tests/test_materialized_view.py b/tests/functional/materializations/materialized_view_tests/test_materialized_view.py index 5f50afc994c..136186a5ec6 100644 --- a/tests/functional/materializations/materialized_view_tests/test_materialized_view.py +++ b/tests/functional/materializations/materialized_view_tests/test_materialized_view.py @@ -56,30 +56,6 @@ def query_row_count(project, relation: BaseRelation) -> int: def query_relation_type(project, relation: BaseRelation) -> Optional[str]: return query_relation_type(project, relation) - @pytest.mark.skip( - "The current implementation does not support overwriting materialized views with tables." - ) - def test_table_replaces_materialized_view(self, project, my_materialized_view): - super().test_table_replaces_materialized_view(project, my_materialized_view) - - @pytest.mark.skip( - "The current implementation does not support overwriting materialized views with views." - ) - def test_view_replaces_materialized_view(self, project, my_materialized_view): - super().test_view_replaces_materialized_view(project, my_materialized_view) - - @pytest.mark.skip( - "The current implementation does not support overwriting tables with materialized views." - ) - def test_materialized_view_replaces_table(self, project, my_table): - super().test_materialized_view_replaces_table(project, my_table) - - @pytest.mark.skip( - "The current implementation does not support overwriting views with materialized views." - ) - def test_materialized_view_replaces_view(self, project, my_view): - super().test_materialized_view_replaces_view(project, my_view) - class PostgresMaterializedViewChanges(MaterializedViewChanges): @pytest.fixture(scope="class", autouse=True) diff --git a/tests/unit/test_relation.py b/tests/unit/test_relation.py new file mode 100644 index 00000000000..77f87bd4461 --- /dev/null +++ b/tests/unit/test_relation.py @@ -0,0 +1,16 @@ +import pytest + +from dbt.adapters.base import BaseRelation +from dbt.contracts.relation import RelationType + + +@pytest.mark.parametrize( + "relation_type,result", + [ + (RelationType.View, True), + (RelationType.External, False), + ], +) +def test_can_be_renamed(relation_type, result): + my_relation = BaseRelation.create(type=relation_type) + assert my_relation.can_be_renamed is result