Correctly reference foreign key references when deferring (#12199)

This commit is contained in:
Michelle Ark
2025-11-25 13:37:07 -05:00
committed by GitHub
parent 09bce7af63
commit 0015e35a1b
4 changed files with 80 additions and 2 deletions

View 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"

View File

@@ -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,

View File

@@ -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 %}
"""

View File

@@ -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"'