From 588653a4993975ffc617a550bedb7c9208e76c1e Mon Sep 17 00:00:00 2001 From: Aarushi Singh Date: Thu, 14 May 2026 14:28:22 +0530 Subject: [PATCH] fix: honor --full-refresh for unaltered views (#1404) --- CHANGELOG.md | 1 + .../macros/materializations/view.sql | 3 ++ tests/functional/adapter/views/test_views.py | 32 +++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c24c673d..212b74923 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - Warn when `contract.enforced: true` is set on a `materialized_view` model ([#1279](https://github.com/databricks/dbt-databricks/issues/1279)) - Fix `materialized_view` models with `databricks_tags` silently going stale on `dbt run`. `MaterializedViewAPI._describe_relation` was not fetching `information_schema.tags`, so existing tags always parsed as empty, producing a spurious tag diff that routed the materialization to `ALTER ... SET TAGS` instead of `REFRESH MATERIALIZED VIEW` ([#1419](https://github.com/databricks/dbt-databricks/issues/1419)) - Fix `dbt docs generate` failing with `RuntimeError: Tables contain columns with the same names ... but different types` during catalog merge across schemas ([#1392](https://github.com/databricks/dbt-databricks/issues/1392)) +- Fix view materialization incorrectly producing a no-op instead of forcing recreation when `--full-refresh` is provided alongside `view_update_via_alter: true` and `use_materialization_v2: true` ([#1404](https://github.com/databricks/dbt-databricks/issues/1404)) ## dbt-databricks 1.11.7 (Apr 17, 2026) diff --git a/dbt/include/databricks/macros/materializations/view.sql b/dbt/include/databricks/macros/materializations/view.sql index a2b443d94..913ce2f43 100644 --- a/dbt/include/databricks/macros/materializations/view.sql +++ b/dbt/include/databricks/macros/materializations/view.sql @@ -86,6 +86,9 @@ {% endmacro %} {% macro relation_should_be_altered(existing_relation) %} + {% if should_full_refresh() %} + {{ return(False) }} + {% endif %} {% set update_via_alter = config.get('view_update_via_alter', False) | as_bool %} {% if existing_relation.is_view and update_via_alter %} {% if existing_relation.is_hive_metastore() %} diff --git a/tests/functional/adapter/views/test_views.py b/tests/functional/adapter/views/test_views.py index 20baaed5f..5b21b8bbf 100644 --- a/tests/functional/adapter/views/test_views.py +++ b/tests/functional/adapter/views/test_views.py @@ -59,6 +59,22 @@ def test_view_update_nothing(self, project): assert results[0][2] == "This is the id column" +class BaseUpdateFullRefresh(BaseUpdateView): + """Ensure that a full refresh forces a recreation even when there are no changes.""" + + def test_view_update_full_refresh(self, project): + util.run_dbt(["build"]) + # Should not no-op, but we at least ensure it runs successfully. + # The logs should contain "Using replace_with_view" but we can't easily assert that. + util.run_dbt(["run", "--full-refresh"]) + + results = project.run_sql( + "describe extended {database}.{schema}.initial_view", + fetch="all", + ) + assert results[0][2] == "This is the id column" + + class BaseUpdateTblProperties(BaseUpdateView): def test_view_update_tblproperties(self, project): util.run_dbt(["build"]) @@ -143,6 +159,22 @@ def project_config_update(self): } +@pytest.mark.skip_profile("databricks_cluster") +class TestUpdateViewViaAlterFullRefresh(BaseUpdateFullRefresh): + @pytest.fixture(scope="class") + def project_config_update(self): + return { + "flags": {"use_materialization_v2": True}, + "models": { + "+view_update_via_alter": True, + "+persist_docs": { + "relation": True, + "columns": True, + }, + }, + } + + @pytest.mark.skip_profile("databricks_cluster") class TestUpdateViewViaAlterQuery(BaseUpdateQuery): @pytest.fixture(scope="class")