Repository: dbt-labs/dbt-core

Issue:
dbt=0.20.0-rc1 on postgres throws "maximum recursion depth exceeded while calling a Python object" error
### Describe the bug
Hi folks! Not sure what I gunked up, but [this PR](https://github.com/calogica/dbt-expectations/pull/82) to update `dbt-expectations` to 0.20.0 currently won't run against my `postgres` target but works fine against BigQuery and Snowflake.
```
integration_tests git:(fix/dbt-0.20.0-compatibility) dbt run -t postgres
```
```
Running with dbt=0.20.0-rc1
Encountered an error:
maximum recursion depth exceeded while calling a Python object
```
### Steps To Reproduce
Probably the best way is to check out [the PR](https://github.com/calogica/dbt-expectations/pull/82), then `cd integration_tests` and run `dbt run -t postgres` where `postgres` is one of the targets in your `integration_tests` profile.
I'm running **PostgreSQL 13** via the Mac Postgres app.

### System information
**Which database are you using dbt with?**
- [x] postgres
- [ ] redshift
- [ ] bigquery
- [ ] snowflake
- [ ] other (specify: ____________)


**The output of `dbt --version`:**
```
installed version: 0.20.0-rc1
   latest version: 0.19.1

Your version of dbt is ahead of the latest release!

Plugins:
  - bigquery: 0.20.0rc1
  - snowflake: 0.20.0rc1
  - redshift: 0.20.0rc1
  - postgres: 0.20.0rc1
 ```

**The operating system you're using:**
mac OS Big Sur 11.2.1 (20D74)
 
**The output of `python --version`:**
Python 3.8.1



Discussion:
@clausherther Gross! Thanks for the report. I just checked out your branch and reproduced the error. Here's the relevant bit from the stacktrace:
```
  File "/usr/local/Cellar/dbt@0.20.0-rc1/0.20.0rc1_1/libexec/lib/python3.8/site-packages/dbt/parser/schemas.py", line 359, in _parse_generic_test
    self.render_test_update(node, config, builder)
  File "/usr/local/Cellar/dbt@0.20.0-rc1/0.20.0rc1_1/libexec/lib/python3.8/site-packages/dbt/parser/schemas.py", line 415, in render_test_update
    context = generate_test_context(
  File "/usr/local/Cellar/dbt@0.20.0-rc1/0.20.0rc1_1/libexec/lib/python3.8/site-packages/dbt/context/providers.py", line 1464, in generate_test_context
    ctx = TestContext(
  File "/usr/local/Cellar/dbt@0.20.0-rc1/0.20.0rc1_1/libexec/lib/python3.8/site-packages/dbt/context/providers.py", line 1426, in __init__
    self._build_test_namespace()
  File "/usr/local/Cellar/dbt@0.20.0-rc1/0.20.0rc1_1/libexec/lib/python3.8/site-packages/dbt/context/providers.py", line 1450, in _build_test_namespace
    macro_namespace = TestMacroNamespace(
  File "/usr/local/Cellar/dbt@0.20.0-rc1/0.20.0rc1_1/libexec/lib/python3.8/site-packages/dbt/context/macro_resolver.py", line 154, in __init__
    self.recursively_get_depends_on_macros(depends_on_macros, dep_macros)
  File "/usr/local/Cellar/dbt@0.20.0-rc1/0.20.0rc1_1/libexec/lib/python3.8/site-packages/dbt/context/macro_resolver.py", line 176, in recursively_get_depends_on_macros
    self.recursively_get_depends_on_macros(macro.depends_on.macros, dep_macros)
  File "/usr/local/Cellar/dbt@0.20.0-rc1/0.20.0rc1_1/libexec/lib/python3.8/site-packages/dbt/context/macro_resolver.py", line 176, in recursively_get_depends_on_macros
    self.recursively_get_depends_on_macros(macro.depends_on.macros, dep_macros)
  File "/usr/local/Cellar/dbt@0.20.0-rc1/0.20.0rc1_1/libexec/lib/python3.8/site-packages/dbt/context/macro_resolver.py", line 176, in recursively_get_depends_on_macros
    self.recursively_get_depends_on_macros(macro.depends_on.macros, dep_macros)
  [Previous line repeated 973 more times]
  File "/usr/local/Cellar/dbt@0.20.0-rc1/0.20.0rc1_1/libexec/lib/python3.8/site-packages/dbt/context/macro_resolver.py", line 172, in recursively_get_depends_on_macros
    dep_macros.append(macro_unique_id)
RecursionError: maximum recursion depth exceeded while calling a Python object
```
Given that this seems related to our changes to infer macro dependencies, which is also making its way into 0.19.2, I'm going to test with 0.19.2-rc2 and see if I can reproduce the same error.
Attaching logs...
[dbt.log](https://github.com/fishtown-analytics/dbt/files/6618592/dbt.log)

relevant lines (?)
```
File "/Users/claus/.pyenv/versions/3.8.1/envs/dbt020/lib/python3.8/site-packages/dbt/context/macro_resolver.py", line 154, in __init__
    self.recursively_get_depends_on_macros(depends_on_macros, dep_macros)
  File "/Users/claus/.pyenv/versions/3.8.1/envs/dbt020/lib/python3.8/site-packages/dbt/context/macro_resolver.py", line 176, in recursively_get_depends_on_macros
    self.recursively_get_depends_on_macros(macro.depends_on.macros, dep_macros)
  File "/Users/claus/.pyenv/versions/3.8.1/envs/dbt020/lib/python3.8/site-packages/dbt/context/macro_resolver.py", line 176, in recursively_get_depends_on_macros
    self.recursively_get_depends_on_macros(macro.depends_on.macros, dep_macros)
  File "/Users/claus/.pyenv/versions/3.8.1/envs/dbt020/lib/python3.8/site-packages/dbt/context/macro_resolver.py", line 176, in recursively_get_depends_on_macros
    self.recursively_get_depends_on_macros(macro.depends_on.macros, dep_macros)
  [Previous line repeated 973 more times]
  File "/Users/claus/.pyenv/versions/3.8.1/envs/dbt020/lib/python3.8/site-packages/dbt/context/macro_resolver.py", line 172, in recursively_get_depends_on_macros
    dep_macros.append(macro_unique_id)
```
I'm guessing I have some dispatch loop for postgres that I don't have for the other targets... 
Oh - that could be! If that's the case, we could raise a more helpful error once a loop is detected. I just took a quick look at the `postgres__` macros in the package, but at first glance, I don't see any funny business...
Confirmed that this raises the same error on 0.19.2-rc2 as well:
```
Running with dbt=0.19.2-rc2
Encountered an error:
maximum recursion depth exceeded while calling a Python object
```
Mmmh. Do you think this is something with an upstream package? I'm using the 0.20 dev branch for `dbt-date` for this, but can't see anthing weird (and that one works with postgres) and using dbt-utils 0.7.0 (not sure if you were using that for 0.19.2?).
@clausherther I figured out what's going on :)

This is coming from `dbt_utils.postgres__datediff`, which (in turn) calls `dbt_utils.datediff` [a bunch of times](https://github.com/fishtown-analytics/dbt-utils/blob/2fbadf78d072afb3fccbc5047ed2c39696503e9d/macros/cross_db_utils/datediff.sql#L27-L58). This sort of recursion is totally legit for Jinja macros.

I'm not sure why this only came up in integration testing for `dbt-expectations`, and not our integration tests in `dbt-utils`.

@gshank Do you think this kind of recursive self-dependency would be simple to handle within `recursively_get_depends_on_macros`?

Edit: I previously thought I had also figured out a short-term fix, but really I hadn't.
Oh man, good sleuthing @jtcohen6! Let me know if there's anything I can do to help with this.

Resolving patch:
diff --git a/core/dbt/context/macro_resolver.py b/core/dbt/context/macro_resolver.py
--- a/core/dbt/context/macro_resolver.py
+++ b/core/dbt/context/macro_resolver.py
@@ -169,6 +169,8 @@ def __init__(
 
     def recursively_get_depends_on_macros(self, depends_on_macros, dep_macros):
         for macro_unique_id in depends_on_macros:
+            if macro_unique_id in dep_macros:
+                continue
             dep_macros.append(macro_unique_id)
             if macro_unique_id in self.macro_resolver.macros:
                 macro = self.macro_resolver.macros[macro_unique_id]


Test patch:
diff --git a/test/integration/008_schema_tests_test/local_utils/macros/datediff.sql b/test/integration/008_schema_tests_test/local_utils/macros/datediff.sql
new file mode 100644
--- /dev/null
+++ b/test/integration/008_schema_tests_test/local_utils/macros/datediff.sql
@@ -0,0 +1,28 @@
+{% macro datediff(first_date, second_date, datepart) %}
+  {{ return(adapter.dispatch('datediff', 'local_utils')(first_date, second_date, datepart)) }}
+{% endmacro %}
+
+
+{% macro default__datediff(first_date, second_date, datepart) %}
+
+    datediff(
+        {{ datepart }},
+        {{ first_date }},
+        {{ second_date }}
+        )
+
+{% endmacro %}
+
+
+{% macro postgres__datediff(first_date, second_date, datepart) %}
+
+    {% if datepart == 'year' %}
+        (date_part('year', ({{second_date}})::date) - date_part('year', ({{first_date}})::date))
+    {% elif datepart == 'quarter' %}
+        ({{ local_utils.datediff(first_date, second_date, 'year') }} * 4 + date_part('quarter', ({{second_date}})::date) - date_part('quarter', ({{first_date}})::date))
+    {% else %}
+        ( 1000 )
+    {% endif %}
+
+{% endmacro %}
+
diff --git a/test/integration/008_schema_tests_test/test-context-macros/test_my_datediff.sql b/test/integration/008_schema_tests_test/test-context-macros/test_my_datediff.sql
new file mode 100644
--- /dev/null
+++ b/test/integration/008_schema_tests_test/test-context-macros/test_my_datediff.sql
@@ -0,0 +1,3 @@
+{% macro test_my_datediff(model) %}
+    select {{ local_utils.datediff() }}
+{% endmacro %}
diff --git a/test/integration/008_schema_tests_test/test-context-models/schema.yml b/test/integration/008_schema_tests_test/test-context-models/schema.yml
--- a/test/integration/008_schema_tests_test/test-context-models/schema.yml
+++ b/test/integration/008_schema_tests_test/test-context-models/schema.yml
@@ -10,3 +10,4 @@ models:
       tests:
         - call_pkg_macro
         - local_utils.pkg_and_dispatch
+        - my_datediff
diff --git a/test/integration/008_schema_tests_test/test_schema_v2_tests.py b/test/integration/008_schema_tests_test/test_schema_v2_tests.py
--- a/test/integration/008_schema_tests_test/test_schema_v2_tests.py
+++ b/test/integration/008_schema_tests_test/test_schema_v2_tests.py
@@ -420,17 +420,19 @@ def test_postgres_test_context_tests(self):
         run_result = self.run_dbt(['test'], expect_pass=False)
         results = run_result.results
         results = sorted(results, key=lambda r: r.node.name)
-        self.assertEqual(len(results), 4)
+        self.assertEqual(len(results), 5)
         # call_pkg_macro_model_c_
         self.assertEqual(results[0].status, TestStatus.Fail)
         # pkg_and_dispatch_model_c_
         self.assertEqual(results[1].status, TestStatus.Fail)
+        # my_datediff
+        self.assertRegex(results[2].node.compiled_sql, r'1000')
         # type_one_model_a_
-        self.assertEqual(results[2].status, TestStatus.Fail)
-        self.assertRegex(results[2].node.compiled_sql, r'union all')
-        # type_two_model_a_
         self.assertEqual(results[3].status, TestStatus.Fail)
-        self.assertEqual(results[3].node.config.severity, 'WARN')
+        self.assertRegex(results[3].node.compiled_sql, r'union all')
+        # type_two_model_a_
+        self.assertEqual(results[4].status, TestStatus.Fail)
+        self.assertEqual(results[4].node.config.severity, 'WARN')
 
 class TestSchemaTestContextWithMacroNamespace(DBTIntegrationTest):
     @property