diff --git a/.changes/unreleased/Features-20230823-140407.yaml b/.changes/unreleased/Features-20230823-140407.yaml new file mode 100644 index 00000000000..2b5101ecf11 --- /dev/null +++ b/.changes/unreleased/Features-20230823-140407.yaml @@ -0,0 +1,6 @@ +kind: Features +body: Add --no-inject-ephemeral-ctes flag for `compile` command, for usage by linting. +time: 2023-08-23T14:04:07.617476-04:00 +custom: + Author: benmosher + Issue: "8480" diff --git a/core/dbt/cli/main.py b/core/dbt/cli/main.py index b53ff3277ba..9b6e8459cb0 100644 --- a/core/dbt/cli/main.py +++ b/core/dbt/cli/main.py @@ -330,6 +330,7 @@ def docs_serve(ctx, **kwargs): @p.state @p.defer_state @p.deprecated_state +@p.compile_inject_ephemeral_ctes @p.target @p.target_path @p.threads diff --git a/core/dbt/cli/params.py b/core/dbt/cli/params.py index 3c016958fb4..f7a7365a07e 100644 --- a/core/dbt/cli/params.py +++ b/core/dbt/cli/params.py @@ -40,6 +40,14 @@ default=True, ) +compile_inject_ephemeral_ctes = click.option( + "--inject-ephemeral-ctes/--no-inject-ephemeral-ctes", + envvar=None, + help="Internal flag controlling injection of referenced ephemeral models' CTEs during `compile`.", + hidden=True, + default=True, +) + config_dir = click.option( "--config-dir", envvar=None, diff --git a/core/dbt/compilation.py b/core/dbt/compilation.py index 959ad2516d1..f37e248515a 100644 --- a/core/dbt/compilation.py +++ b/core/dbt/compilation.py @@ -320,6 +320,10 @@ def _recursively_prepend_ctes( if model.compiled_code is None: raise DbtRuntimeError("Cannot inject ctes into an uncompiled node", model) + # tech debt: safe flag/arg access (#6259) + if not getattr(self.config.args, "inject_ephemeral_ctes", True): + return (model, []) + # extra_ctes_injected flag says that we've already recursively injected the ctes if model.extra_ctes_injected: return (model, model.extra_ctes) diff --git a/tests/functional/materializations/test_ephemeral_compilation.py b/tests/functional/materializations/test_ephemeral_compilation.py index 56f49928756..c9f17d3e00c 100644 --- a/tests/functional/materializations/test_ephemeral_compilation.py +++ b/tests/functional/materializations/test_ephemeral_compilation.py @@ -1,3 +1,5 @@ +from dbt.contracts.graph.nodes import ModelNode +from dbt.contracts.results import RunExecutionResult, RunResult import pytest from dbt.tests.util import run_dbt @@ -53,6 +55,16 @@ """ +SUPPRESSED_CTE_EXPECTED_OUTPUT = """-- fct_eph_first.sql + + +with int_eph_first as( + select * from __dbt__cte__int_eph_first +) + +select * from int_eph_first""" + + class TestEphemeralCompilation: @pytest.fixture(scope="class") def models(self): @@ -67,5 +79,13 @@ def test_ephemeral_compilation(self, project): results = run_dbt(["run"]) assert len(results) == 0 - results = run_dbt(["test"]) - len(results) == 4 + def test__suppress_injected_ctes(self, project): + compile_output = run_dbt( + ["compile", "--no-inject-ephemeral-ctes", "--select", "fct_eph_first"] + ) + assert isinstance(compile_output, RunExecutionResult) + node_result = compile_output.results[0] + assert isinstance(node_result, RunResult) + node = node_result.node + assert isinstance(node, ModelNode) + assert node.compiled_code == SUPPRESSED_CTE_EXPECTED_OUTPUT