From 87660cb9286e11ea50c44ccd547829bada373c2c Mon Sep 17 00:00:00 2001 From: Vincent Chan Date: Tue, 19 Aug 2025 12:05:11 -0700 Subject: [PATCH 1/3] Feat(dbt): Add support for adapter.rename_relation --- sqlmesh/dbt/adapter.py | 20 +++++++++++++++++++- tests/dbt/test_adapter.py | 13 +++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/sqlmesh/dbt/adapter.py b/sqlmesh/dbt/adapter.py index b524acc160..8e1a9c9a2a 100644 --- a/sqlmesh/dbt/adapter.py +++ b/sqlmesh/dbt/adapter.py @@ -15,7 +15,6 @@ if t.TYPE_CHECKING: import agate - import pandas as pd from dbt.adapters.base import BaseRelation from dbt.adapters.base.column import Column from dbt.adapters.base.impl import AdapterResponse @@ -86,6 +85,10 @@ def drop_schema(self, relation: BaseRelation) -> None: def drop_relation(self, relation: BaseRelation) -> None: """Drops a relation (table) in the target database.""" + @abc.abstractmethod + def rename_relation(self, from_relation: BaseRelation, to_relation: BaseRelation) -> None: + """Renames a relation (table) in the target database.""" + @abc.abstractmethod def execute( self, sql: str, auto_begin: bool = False, fetch: bool = False @@ -210,6 +213,9 @@ def drop_schema(self, relation: BaseRelation) -> None: def drop_relation(self, relation: BaseRelation) -> None: self._raise_parsetime_adapter_call_error("drop relation") + def rename_relation(self, from_relation: BaseRelation, to_relation: BaseRelation) -> None: + self._raise_parsetime_adapter_call_error("rename relation") + def execute( self, sql: str, auto_begin: bool = False, fetch: bool = False ) -> t.Tuple[AdapterResponse, agate.Table]: @@ -349,6 +355,18 @@ def drop_relation(self, relation: BaseRelation) -> None: if relation.schema is not None and relation.identifier is not None: self.engine_adapter.drop_table(self._normalize(self._relation_to_table(relation))) + def rename_relation(self, from_relation: BaseRelation, to_relation: BaseRelation) -> None: + old_table_name = None + if from_relation.schema is not None and from_relation.identifier is not None: + old_table_name = self._normalize(self._relation_to_table(from_relation)) + + new_table_name = None + if to_relation.schema is not None and to_relation.identifier is not None: + new_table_name = self._normalize(self._relation_to_table(to_relation)) + + if old_table_name and new_table_name: + self.engine_adapter.rename_table(old_table_name, new_table_name) + def execute( self, sql: str, auto_begin: bool = False, fetch: bool = False ) -> t.Tuple[AdapterResponse, agate.Table]: diff --git a/tests/dbt/test_adapter.py b/tests/dbt/test_adapter.py index 944c4ce78d..5a41d237d3 100644 --- a/tests/dbt/test_adapter.py +++ b/tests/dbt/test_adapter.py @@ -81,6 +81,19 @@ def test_adapter_relation(sushi_test_project: Project, runtime_renderer: t.Calla == "[]" ) + renderer(""" + {%- set old_relation = adapter.get_relation( + database=None, + schema='foo', + identifier='bar') -%} + + {%- set backup_relation = api.Relation.create(schema='foo', identifier='bar__backup') -%} + + {% do adapter.rename_relation(old_relation, backup_relation) %} + """) + assert not engine_adapter.table_exists("foo.bar") + assert engine_adapter.table_exists("foo.bar__backup") + def test_bigquery_get_columns_in_relation( sushi_test_project: Project, From 3810b484580f34149257de31767276e4b9301b53 Mon Sep 17 00:00:00 2001 From: Vincent Chan Date: Tue, 19 Aug 2025 14:17:54 -0700 Subject: [PATCH 2/3] PR feedback --- sqlmesh/dbt/adapter.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/sqlmesh/dbt/adapter.py b/sqlmesh/dbt/adapter.py index 8e1a9c9a2a..7de90a8ea5 100644 --- a/sqlmesh/dbt/adapter.py +++ b/sqlmesh/dbt/adapter.py @@ -356,16 +356,10 @@ def drop_relation(self, relation: BaseRelation) -> None: self.engine_adapter.drop_table(self._normalize(self._relation_to_table(relation))) def rename_relation(self, from_relation: BaseRelation, to_relation: BaseRelation) -> None: - old_table_name = None - if from_relation.schema is not None and from_relation.identifier is not None: - old_table_name = self._normalize(self._relation_to_table(from_relation)) + old_table_name = self._normalize(self._relation_to_table(from_relation)) + new_table_name = self._normalize(self._relation_to_table(to_relation)) - new_table_name = None - if to_relation.schema is not None and to_relation.identifier is not None: - new_table_name = self._normalize(self._relation_to_table(to_relation)) - - if old_table_name and new_table_name: - self.engine_adapter.rename_table(old_table_name, new_table_name) + self.engine_adapter.rename_table(old_table_name, new_table_name) def execute( self, sql: str, auto_begin: bool = False, fetch: bool = False From 5be2fd2daf896439f3c0a63593028685bfb436ce Mon Sep 17 00:00:00 2001 From: Vincent Chan Date: Tue, 19 Aug 2025 15:20:03 -0700 Subject: [PATCH 3/3] Update docs --- docs/integrations/dbt.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/integrations/dbt.md b/docs/integrations/dbt.md index a07e02bb23..e58bde7776 100644 --- a/docs/integrations/dbt.md +++ b/docs/integrations/dbt.md @@ -355,7 +355,7 @@ SQLMesh supports running dbt projects using the majority of dbt jinja methods, i | builtins | modules | source | | | config | print | statement | | -\* `adapter.rename_relation` and `adapter.expand_target_column_types` are not currently supported. +\* `adapter.expand_target_column_types` is not currently supported. ## Unsupported dbt jinja methods @@ -364,7 +364,6 @@ The dbt jinja methods that are not currently supported are: * debug * selected_sources * adapter.expand_target_column_types -* adapter.rename_relation * graph.nodes.values * graph.metrics.values