Skip to content

Commit 511ff8e

Browse files
authored
Fix duplicate error when multiple macros in one file with macro patches (#11531)
1 parent 0220941 commit 511ff8e

File tree

4 files changed

+103
-1
lines changed

4 files changed

+103
-1
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
kind: Fixes
2+
body: Fix duplicate macro error message with multiple macros and multiple patches
3+
time: 2025-04-22T12:28:35.642843-04:00
4+
custom:
5+
Author: gshank
6+
Issue: "4233"

core/dbt/parser/partial.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,10 +920,14 @@ def delete_schema_macro_patch(self, schema_file, macro):
920920
if macro["name"] in schema_file.macro_patches:
921921
macro_unique_id = schema_file.macro_patches[macro["name"]]
922922
del schema_file.macro_patches[macro["name"]]
923+
# Need to delete all macros in the same file
924+
# and then reapply all schema file updates for those macros
923925
if macro_unique_id and macro_unique_id in self.saved_manifest.macros:
924926
macro = self.saved_manifest.macros.pop(macro_unique_id)
925927
macro_file_id = macro.file_id
926928
if macro_file_id in self.new_files:
929+
source_file = self.saved_files[macro_file_id]
930+
self.delete_macro_file(source_file)
927931
self.saved_files[macro_file_id] = deepcopy(self.new_files[macro_file_id])
928932
self.add_to_pp_files(self.saved_files[macro_file_id])
929933

tests/functional/partial_parsing/fixtures.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1288,3 +1288,29 @@
12881288
12891289
12901290
"""
1291+
1292+
macros_sql = """
1293+
{% macro foo() %}
1294+
foo
1295+
{% endmacro %}
1296+
1297+
{% macro bar() %}
1298+
bar
1299+
{% endmacro %}
1300+
"""
1301+
1302+
macros_schema1_yml = """
1303+
macros:
1304+
- name: foo
1305+
description: Lorem.
1306+
- name: bar
1307+
description: Lorem.
1308+
"""
1309+
1310+
macros_schema2_yml = """
1311+
macros:
1312+
- name: foo
1313+
description: Lorem.
1314+
- name: bar
1315+
description: Lorem ipsum.
1316+
"""

tests/functional/partial_parsing/test_partial_parsing.py

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@
3939
local_dependency__models__model_to_import_sql,
4040
local_dependency__models__schema_yml,
4141
local_dependency__seeds__seed_csv,
42+
macros_schema1_yml,
43+
macros_schema2_yml,
4244
macros_schema_yml,
45+
macros_sql,
4346
macros_yml,
4447
model_a_sql,
4548
model_b_sql,
@@ -255,13 +258,24 @@ def test_pp_models(self, project):
255258
with pytest.raises(CompilationError):
256259
results = run_dbt(["--partial-parse", "--warn-error", "run"])
257260

258-
# put back macro file, got back to schema file with no macro
261+
# put back macro file, go back to schema file with no macro
259262
# add separate macro patch schema file
260263
write_file(models_schema2_yml, project.project_root, "models", "schema.yml")
261264
write_file(my_macro_sql, project.project_root, "macros", "my_macro.sql")
262265
write_file(macros_yml, project.project_root, "macros", "macros.yml")
263266
results = run_dbt(["--partial-parse", "run"])
264267

268+
# add macro file with two macros and schema file with patches for both
269+
write_file(macros_schema1_yml, project.project_root, "macros", "macros_x.yml")
270+
write_file(macros_sql, project.project_root, "macros", "macros_x.sql")
271+
results = run_dbt(["--partial-parse", "parse"])
272+
273+
# modify one of the patches
274+
write_file(macros_schema2_yml, project.project_root, "macros", "macros_x.yml")
275+
results = run_dbt(["--partial-parse", "parse"])
276+
rm_file(project.project_root, "macros", "macros_x.sql")
277+
rm_file(project.project_root, "macros", "macros_x.yml")
278+
265279
# delete macro and schema file
266280
rm_file(project.project_root, "macros", "my_macro.sql")
267281
rm_file(project.project_root, "macros", "macros.yml")
@@ -565,6 +579,58 @@ def test_skip_macros(self, project):
565579
assert "Starting full parse." in log_output
566580

567581

582+
class TestMacroDescriptionUpdate:
583+
@pytest.fixture(scope="class")
584+
def models(self):
585+
return {
586+
"my_model.sql": model_one_sql,
587+
}
588+
589+
@pytest.fixture(scope="class")
590+
def macros(self):
591+
return {
592+
"macros.sql": macros_sql,
593+
"schema.yml": macros_schema1_yml,
594+
}
595+
596+
def test_pp_macro_description_update(self, project):
597+
# initial parse
598+
run_dbt(["parse"])
599+
600+
manifest = get_manifest(project.project_root)
601+
assert "macro.test.foo" in manifest.macros
602+
assert "macro.test.bar" in manifest.macros
603+
assert manifest.macros["macro.test.foo"].description == "Lorem."
604+
assert manifest.macros["macro.test.bar"].description == "Lorem."
605+
assert manifest.macros["macro.test.foo"].patch_path == "test://" + normalize(
606+
"macros/schema.yml"
607+
)
608+
assert manifest.macros["macro.test.bar"].patch_path == "test://" + normalize(
609+
"macros/schema.yml"
610+
)
611+
612+
# edit YAML in macros-path
613+
write_file(macros_schema2_yml, project.project_root, "macros", "schema.yml")
614+
615+
# parse again
616+
run_dbt(["--partial-parse", "parse"])
617+
618+
manifest = get_manifest(project.project_root)
619+
assert "macro.test.foo" in manifest.macros
620+
assert "macro.test.bar" in manifest.macros
621+
assert manifest.macros["macro.test.foo"].description == "Lorem."
622+
assert manifest.macros["macro.test.bar"].description == "Lorem ipsum."
623+
assert manifest.macros["macro.test.foo"].patch_path == "test://" + normalize(
624+
"macros/schema.yml"
625+
)
626+
assert manifest.macros["macro.test.bar"].patch_path == "test://" + normalize(
627+
"macros/schema.yml"
628+
)
629+
630+
# compile
631+
run_dbt(["--partial-parse", "compile"])
632+
633+
568634
class TestSnapshots:
569635
@pytest.fixture(scope="class")
570636
def models(self):

0 commit comments

Comments
 (0)