Repository: dbt-labs/dbt-core

Issue:
Provide user-supplied configs to ParsedNodes before generating alias/schema names
### Describe the feature
dbt's `generate_alias_name` and `generate_schema_name` macros accept a `node` argument which contains a mostly-complete ParsedNode object. When the `generate_schema_name` and `generate_alias_name` macros are called for a node, the `tags` and `configs` properties on the `ParsedNode` are populated with dummy values. Instead, dbt should set the `tags` and `configs` properties for the `ParsedNode` before calling out to the `generate_*_name` macros.

This is specifically problematic when the `generate_alias_name` or `generate_schema_name` macros need to operate on the supplied `schema` or `alias` values for a node. In either instance, the user-supplied values for `alias` and `schema` will be unavailable in the node's `config` dictionary.


### Who will this benefit?
Users with complex needs around schema / alias generation.


Discussion:

Resolving patch:
diff --git a/core/dbt/parser/base.py b/core/dbt/parser/base.py
--- a/core/dbt/parser/base.py
+++ b/core/dbt/parser/base.py
@@ -206,6 +206,15 @@ def _update_parsed_node_info(self, parsed_node, config):
         generate and set the true values to use, overriding the temporary parse
         values set in _build_intermediate_parsed_node.
         """
+        # Set tags on node provided in config blocks
+        model_tags = config.config.get('tags', [])
+        parsed_node.tags.extend(model_tags)
+
+        # Overwrite node config
+        config_dict = parsed_node.get('config', {})
+        config_dict.update(config.config)
+        parsed_node.config = config_dict
+
         # Special macro defined in the global project. Use the root project's
         # definition, not the current package
         schema_override = config.config.get('schema')
@@ -231,15 +240,6 @@ def _update_parsed_node_info(self, parsed_node, config):
             'database', self.default_database
         ).strip()
 
-        # Set tags on node provided in config blocks
-        model_tags = config.config.get('tags', [])
-        parsed_node.tags.extend(model_tags)
-
-        # Overwrite node config
-        config_dict = parsed_node.get('config', {})
-        config_dict.update(config.config)
-        parsed_node.config = config_dict
-
         for hook_type in dbt.hooks.ModelHookType.Both:
             parsed_node.config[hook_type] = dbt.hooks.get_hooks(parsed_node,
                                                                 hook_type)


Test patch:
diff --git a/test/integration/024_custom_schema_test/custom-macros-configs/schema.sql b/test/integration/024_custom_schema_test/custom-macros-configs/schema.sql
new file mode 100644
--- /dev/null
+++ b/test/integration/024_custom_schema_test/custom-macros-configs/schema.sql
@@ -0,0 +1,6 @@
+
+{% macro generate_schema_name(schema_name, node) %}
+
+    {{ node.config['schema'] }}_{{ target.schema }}_macro
+
+{% endmacro %}
diff --git a/test/integration/024_custom_schema_test/test_custom_schema.py b/test/integration/024_custom_schema_test/test_custom_schema.py
--- a/test/integration/024_custom_schema_test/test_custom_schema.py
+++ b/test/integration/024_custom_schema_test/test_custom_schema.py
@@ -171,3 +171,31 @@ def test__postgres__custom_schema_from_macro(self):
         self.assertTablesEqual("seed", "view_1", schema, v1_schema)
         self.assertTablesEqual("seed", "view_2", schema, v2_schema)
         self.assertTablesEqual("agg", "view_3", schema, xf_schema)
+
+
+class TestCustomSchemaWithCustomMacroConfigs(TestCustomSchemaWithCustomMacro):
+
+    @property
+    def project_config(self):
+        return {
+            'macro-paths': ['custom-macros-configs'],
+            'models': {
+                'schema': 'dbt_test'
+            }
+        }
+
+    @use_profile('postgres')
+    def test__postgres__custom_schema_from_macro(self):
+        self.run_sql_file("seed.sql")
+
+        results = self.run_dbt()
+        self.assertEqual(len(results), 3)
+
+        schema = self.unique_schema()
+        v1_schema = "dbt_test_{}_macro".format(schema)
+        v2_schema = "custom_{}_macro".format(schema)
+        xf_schema = "test_{}_macro".format(schema)
+
+        self.assertTablesEqual("seed", "view_1", schema, v1_schema)
+        self.assertTablesEqual("seed", "view_2", schema, v2_schema)
+        self.assertTablesEqual("agg", "view_3", schema, xf_schema)
diff --git a/test/integration/043_custom_aliases_test/macros-configs/macros.sql b/test/integration/043_custom_aliases_test/macros-configs/macros.sql
new file mode 100644
--- /dev/null
+++ b/test/integration/043_custom_aliases_test/macros-configs/macros.sql
@@ -0,0 +1,21 @@
+
+{#-- Verify that the config['alias'] key is present #}
+{% macro generate_alias_name(custom_alias_name, node) -%}
+    {%- if custom_alias_name is none -%}
+        {{ node.name }}
+    {%- else -%}
+        custom_{{ node.config['alias'] | trim }}
+    {%- endif -%}
+{%- endmacro %}
+
+{% macro string_literal(s) -%}
+  {{ adapter_macro('test.string_literal', s) }}
+{%- endmacro %}
+
+{% macro default__string_literal(s) %}
+    '{{ s }}'::text
+{% endmacro %}
+
+{% macro bigquery__string_literal(s) %}
+    cast('{{ s }}' as string)
+{% endmacro %}
diff --git a/test/integration/043_custom_aliases_test/test_custom_aliases.py b/test/integration/043_custom_aliases_test/test_custom_aliases.py
--- a/test/integration/043_custom_aliases_test/test_custom_aliases.py
+++ b/test/integration/043_custom_aliases_test/test_custom_aliases.py
@@ -21,3 +21,17 @@ def test_postgres_customer_alias_name(self):
         results = self.run_dbt(['run'])
         self.assertEqual(len(results), 2)
         self.run_dbt(['test'])
+
+
+class TestAliasesWithConfig(TestAliases):
+    @property
+    def project_config(self):
+        return {
+            "macro-paths": ['macros-configs'],
+        }
+
+    @use_profile('postgres')
+    def test_postgres_customer_alias_name(self):
+        results = self.run_dbt(['run'])
+        self.assertEqual(len(results), 2)
+        self.run_dbt(['test'])