mirror of
https://github.com/dbt-labs/dbt-core
synced 2025-12-17 19:31:34 +00:00
Correctly reference foreign key references when deferring (#12199)
This commit is contained in:
6
.changes/unreleased/Fixes-20251124-170855.yaml
Normal file
6
.changes/unreleased/Fixes-20251124-170855.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
kind: Fixes
|
||||
body: ':bug: :snowman: Correctly reference foreign key references when --defer and --state provided'
|
||||
time: 2025-11-24T17:08:55.387946-05:00
|
||||
custom:
|
||||
Author: michellark
|
||||
Issue: "11885"
|
||||
@@ -654,8 +654,15 @@ class Compiler:
|
||||
raise GraphDependencyNotFoundError(node, to_expression)
|
||||
|
||||
adapter = get_adapter(self.config)
|
||||
relation_name = str(adapter.Relation.create_from(self.config, foreign_key_node))
|
||||
return relation_name
|
||||
|
||||
if (
|
||||
hasattr(foreign_key_node, "defer_relation")
|
||||
and foreign_key_node.defer_relation
|
||||
and self.config.args.defer
|
||||
):
|
||||
return str(adapter.Relation.create_from(self.config, foreign_key_node.defer_relation))
|
||||
else:
|
||||
return str(adapter.Relation.create_from(self.config, foreign_key_node))
|
||||
|
||||
# This method doesn't actually "compile" any of the nodes. That is done by the
|
||||
# "compile_node" method. This creates a Linker and builds the networkx graph,
|
||||
|
||||
@@ -113,3 +113,10 @@ models:
|
||||
to: source('test_source', 'test_table')
|
||||
to_columns: [id]
|
||||
"""
|
||||
|
||||
|
||||
stateful_generate_alias_name_macros_sql = """
|
||||
{% macro generate_alias_name(custom_alias_name, node) -%}
|
||||
{{ node.name }}_{{ var("state", "dev") }}
|
||||
{%- endmacro %}
|
||||
"""
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import os
|
||||
import shutil
|
||||
|
||||
import pytest
|
||||
|
||||
from dbt.artifacts.resources import RefArgs
|
||||
@@ -17,6 +20,7 @@ from tests.functional.constraints.fixtures import (
|
||||
model_foreign_key_model_node_not_found_schema_yml,
|
||||
model_foreign_key_model_schema_yml,
|
||||
model_foreign_key_source_schema_yml,
|
||||
stateful_generate_alias_name_macros_sql,
|
||||
)
|
||||
|
||||
|
||||
@@ -239,3 +243,57 @@ class TestColumnLevelForeignKeyConstraintRefSyntaxError:
|
||||
match="Invalid 'ref' or 'source' syntax on foreign key constraint 'to' on model my_model: invalid.",
|
||||
):
|
||||
run_dbt(["parse"])
|
||||
|
||||
|
||||
class BaseForeignKeyDeferState:
|
||||
@pytest.fixture(scope="class")
|
||||
def macros(self):
|
||||
return {
|
||||
"generate_alias_name.sql": stateful_generate_alias_name_macros_sql,
|
||||
}
|
||||
|
||||
def copy_state(self, project_root):
|
||||
state_path = os.path.join(project_root, "state")
|
||||
if not os.path.exists(state_path):
|
||||
os.makedirs(state_path)
|
||||
shutil.copyfile(
|
||||
f"{project_root}/target/manifest.json", f"{project_root}/state/manifest.json"
|
||||
)
|
||||
|
||||
|
||||
class TestModelLevelForeignKeyConstraintRefToDeferRelation(BaseForeignKeyDeferState):
|
||||
@pytest.fixture(scope="class")
|
||||
def models(self):
|
||||
return {
|
||||
"constraints_schema.yml": model_foreign_key_model_schema_yml,
|
||||
"my_model.sql": "select 1 as id",
|
||||
"my_model_to.sql": "select 1 as id",
|
||||
}
|
||||
|
||||
def test_model_level_fk_to_defer_relation(self, project):
|
||||
results = run_dbt(["run", "--vars", "state: prod"])
|
||||
self.copy_state(project.project_root)
|
||||
|
||||
results = run_dbt(["compile", "--defer", "--state", "state"])
|
||||
|
||||
my_model_node = [r.node for r in results.results if r.node.name == "my_model"][0]
|
||||
assert my_model_node.constraints[0].to.split(".")[-1] == '"my_model_to_prod"'
|
||||
|
||||
|
||||
class TestColumnLevelForeignKeyConstraintToRefDeferRelation(BaseForeignKeyDeferState):
|
||||
@pytest.fixture(scope="class")
|
||||
def models(self):
|
||||
return {
|
||||
"constraints_schema.yml": model_foreign_key_model_column_schema_yml,
|
||||
"my_model.sql": "select 1 as id",
|
||||
"my_model_to.sql": "select 1 as id",
|
||||
}
|
||||
|
||||
def test_column_level_fk_to_defer_relation(self, project):
|
||||
results = run_dbt(["run", "--vars", "state: prod"])
|
||||
self.copy_state(project.project_root)
|
||||
|
||||
results = run_dbt(["compile", "--defer", "--state", "state"])
|
||||
|
||||
my_model_node = [r.node for r in results.results if r.node.name == "my_model"][0]
|
||||
assert my_model_node.columns["id"].constraints[0].to.split(".")[-1] == '"my_model_to_prod"'
|
||||
|
||||
Reference in New Issue
Block a user