|
| 1 | +{% macro check_for_nested_cte(sql) %} |
| 2 | + {% if execute %} {# Ensure this runs only at execution time #} |
| 3 | + {% set cleaned_sql = sql | lower | replace("\n", " ") %} {# Convert to lowercase and remove newlines #} |
| 4 | + {% set cte_count = cleaned_sql.count("with ") %} {# Count occurrences of "WITH " #} |
| 5 | + {% if cte_count > 1 %} |
| 6 | + {{ return(True) }} |
| 7 | + {% else %} |
| 8 | + {{ return(False) }} {# No nested CTEs found #} |
| 9 | + {% endif %} |
| 10 | + {% else %} |
| 11 | + {{ return(False) }} {# Return False during parsing #} |
| 12 | + {% endif %} |
| 13 | +{% endmacro %} |
| 14 | + |
| 15 | +{% macro sqlserver__unit_test_create_table_as(temporary, relation, sql) -%} |
| 16 | + {%- set query_label = apply_label() -%} |
| 17 | + {%- set contract_config = config.get('contract') -%} |
| 18 | + {%- set is_nested_cte = check_for_nested_cte(sql) -%} |
| 19 | + |
| 20 | + {%- if is_nested_cte -%} |
| 21 | + {{ exceptions.warn( |
| 22 | + "Nested CTE warning: Nested CTEs do not support CTAS. However, 2-level nested CTEs are supported due to a code bug. Please expect this fix in the future." |
| 23 | + ) }} |
| 24 | + {%- endif -%} |
| 25 | + |
| 26 | + {%- if is_nested_cte and contract_config.enforced -%} |
| 27 | + |
| 28 | + {{ exceptions.raise_compiler_error( |
| 29 | + "Unit test Materialization error: Since the contract is enforced and the model contains a nested CTE, unit tests cannot be materialized. Please refactor your model or unenforce model and try again." |
| 30 | + ) }} |
| 31 | + |
| 32 | + {%- elif not is_nested_cte and contract_config.enforced -%} |
| 33 | + |
| 34 | + {# Build CREATE TABLE + INSERT using a temporary view to avoid CTAS semantics #} |
| 35 | + CREATE TABLE {{ relation }} |
| 36 | + {{ build_columns_constraints(relation) }} |
| 37 | + {{ get_assert_columns_equivalent(sql) }}; |
| 38 | + |
| 39 | + {%- set listColumns -%} |
| 40 | + {%- for column in model['columns'] -%} |
| 41 | + {{ "["~column~"]" }}{{ ", " if not loop.last }} |
| 42 | + {%- endfor -%} |
| 43 | + {%- endset -%} |
| 44 | + |
| 45 | + {%- set tmp_vw_relation = relation.incorporate(path={"identifier": relation.identifier ~ '__dbt_tmp_vw'}, type='view') -%} |
| 46 | + {%- do adapter.drop_relation(tmp_vw_relation) -%} |
| 47 | + {{ get_create_view_as_sql(tmp_vw_relation, sql) }} |
| 48 | + |
| 49 | + INSERT INTO {{ relation }} ({{ listColumns }}) |
| 50 | + SELECT {{ listColumns }} FROM {{ tmp_vw_relation }} {{ query_label }}; |
| 51 | + |
| 52 | + DROP VIEW IF EXISTS {{ tmp_vw_relation.schema }}.{{ tmp_vw_relation.identifier }}; |
| 53 | + |
| 54 | + {%- else -%} |
| 55 | + |
| 56 | + {# Default: use SELECT INTO from an intermediate view so CTEs are preserved and labels are placed inside the selectable statement #} |
| 57 | + {%- set tmp_vw_relation = relation.incorporate(path={"identifier": relation.identifier ~ '__dbt_tmp_vw'}, type='view') -%} |
| 58 | + {%- do adapter.drop_relation(tmp_vw_relation) -%} |
| 59 | + |
| 60 | + {{ get_create_view_as_sql(tmp_vw_relation, sql) }} |
| 61 | + |
| 62 | + SELECT * INTO {{ relation }} FROM {{ tmp_vw_relation }} {{ query_label }}; |
| 63 | + |
| 64 | + DROP VIEW IF EXISTS {{ tmp_vw_relation.schema }}.{{ tmp_vw_relation.identifier }}; |
| 65 | + |
| 66 | + {%- endif -%} |
| 67 | + |
| 68 | +{%- endmacro %} |
0 commit comments