Repository: dbt-labs/dbt-core

Issue:
[CT-1483] [Bug] Macros whose names contain "materialization" treated as materialization macros by compiler, fail with "no supported_languages..."
### Is this a new bug in dbt-core?

- [X] I believe this is a new bug in dbt-core
- [X] I have searched the existing issues, and I could not find an existing issue for this bug

### Current Behavior

After upgrading to dbt 1.3.0 which adds `supported_languages` for materialization macros (#5695), all standard macros whose name has `"materlialization"` as a substring prevent compilation.

A project I'm contributing to contains a macro named `get_materialization` (it defaults model materializations to view under certain conditions). The parser seems to treat it as a materialization macro for that, even though it's not (location of this in dbt-core code referenced below in "Additional Context").

So when running `dbt run` or `dbt compile` I get the following error:
```
No supported_languages found in materialization macro <project_prefix>__get_materialization
```

### Expected Behavior

Only materialization macros are able to trigger this compilation error when not declaring supported languages.

A regular macro (`{% macro_name([params]) %}`) with the substring `"materialization"` in its name is not considered a materialization macro (`{% materialization [materialization_name] ... %}`) and does not trigger the compilation error.

### Steps To Reproduce

1. Create a new regular macro and have its name contain the substring `"materialization"`, e.g. `get_materialization` or `print_materialization`.
2. Run `dbt compile`.

### Relevant log output

_No response_

### Environment

```markdown
- OS: macOS 12.5.1
- Python: 3.8.15
- dbt: 1.3.0
```


### Which database adapter are you using with dbt?

snowflake

### Additional Context

The `parse_unparsed_macros` method performs this "generalization":
https://github.com/dbt-labs/dbt-core/blob/f02243506df2a9b6851abe6bcfe10af8808d41cc/core/dbt/parser/macros.py#L88


Discussion:
Thanks for surfacing this @CraftyIvan !

Agreed that this is a surprising result when there is a non-materialization macro that happens to have "materialization" within the name.

Our next step will be to determine what our options are for changing the implementation.
### Goal
- Only set the `node.supported_languages` configuration for materialization nodes
- Determine the node type independently of the name
    - so that non-materialization nodes may have "materialization" in their name without failing during compilation

### Idea for resolution
@stu-k I saw you worked on this area of the code -- do you know if we could do something like the following? If not, do you have any other suggestions?

Replace:

https://github.com/dbt-labs/dbt-core/blob/9f280a84694fde5644cad1cc2263a0e8494f9b3d/core/dbt/parser/macros.py#L87-L90

with something like:

```python
 # get supported_languages for materialization macro 
 if block.block_type_name == "materialization": 
     node.supported_languages = jinja.get_supported_languages(macro) 
 yield node 
```
@dbeatty10 Your suggested change makes sense to me! Much better than the idea I was halfway through typing.

I'm going to tag this one for `Team:Language`, since that's whose surface area this falls under. Stu was original implementer here, so still very happy to hear from him too.
This issue has been marked as Stale because it has been open for 180 days with no activity. If you would like the issue to remain open, please comment on the issue or else it will be closed in 7 days.
Although we are closing this issue as stale, it's not gone forever. Issues can be reopened if there is renewed community interest. Just add a comment to notify the maintainers.
please reopen this ticket, now we have version 1.5.2 and it is still not fixed :(
Given how straightforward Doug's proposed fix is, I think this could be a community contribution.

@mjedrzejczak-wh Any interest in giving it a spin?
@jtcohen6 unfortunately we have in our projects such macros, which block us effectively from upgrade

and I would prefer not to fix this myself - I do not know dbt internals so well
@jtcohen6 @mjedrzejczak-wh @dbeatty10 @CraftyIvan @joevandyk 

Just FYI, I too faced the same error while trying to upgrade dbt.

I did try the code change suggested by @dbeatty10 locally in my python virtual environment and it is working as expected. I am facing some other project specific errors but thought to share this here so that we are all aware that the idea proposed above is fixing the issue.

Resolving patch:
diff --git a/core/dbt/parser/macros.py b/core/dbt/parser/macros.py
--- a/core/dbt/parser/macros.py
+++ b/core/dbt/parser/macros.py
@@ -81,7 +81,7 @@ def parse_unparsed_macros(self, base_node: UnparsedMacro) -> Iterable[Macro]:
             name: str = macro.name.replace(MACRO_PREFIX, "")
             node = self.parse_macro(block, base_node, name)
             # get supported_languages for materialization macro
-            if "materialization" in name:
+            if block.block_type_name == "materialization":
                 node.supported_languages = jinja.get_supported_languages(macro)
             yield node
 


Test patch:
diff --git a/tests/functional/macros/fixtures.py b/tests/functional/macros/fixtures.py
--- a/tests/functional/macros/fixtures.py
+++ b/tests/functional/macros/fixtures.py
@@ -4,6 +4,12 @@
 }}
 """
 
+models__materialization_macro = """
+{{
+    materialization_macro()
+}}
+"""
+
 models__with_undefined_macro = """
 {{ dispatch_to_nowhere() }}
 select 1 as id
@@ -75,6 +81,12 @@
 {% endmacro %}
 """
 
+macros__named_materialization = """
+{% macro materialization_macro() %}
+    select 1 as foo
+{% endmacro %}
+"""
+
 macros__no_default_macros = """
 {% macro do_something2(foo2, bar2) %}
 
diff --git a/tests/functional/macros/test_macros.py b/tests/functional/macros/test_macros.py
--- a/tests/functional/macros/test_macros.py
+++ b/tests/functional/macros/test_macros.py
@@ -20,12 +20,14 @@
     models__override_get_columns_macros,
     models__deprecated_adapter_macro_model,
     models__incorrect_dispatch,
+    models__materialization_macro,
     macros__my_macros,
     macros__no_default_macros,
     macros__override_get_columns_macros,
     macros__package_override_get_columns_macros,
     macros__deprecated_adapter_macro,
     macros__incorrect_dispatch,
+    macros__named_materialization,
 )
 
 
@@ -78,6 +80,21 @@ def test_working_macros(self, project):
         check_relations_equal(project.adapter, ["expected_local_macro", "local_macro"])
 
 
+class TestMacrosNamedMaterialization:
+    @pytest.fixture(scope="class")
+    def models(self):
+        return {
+            "models_materialization_macro.sql": models__materialization_macro,
+        }
+
+    @pytest.fixture(scope="class")
+    def macros(self):
+        return {"macros_named_materialization.sql": macros__named_materialization}
+
+    def test_macro_with_materialization_in_name_works(self, project):
+        run_dbt(expect_pass=True)
+
+
 class TestInvalidMacros:
     @pytest.fixture(scope="class")
     def models(self):