diff --git a/.changes/unreleased/Fixes-20241011-103317.yaml b/.changes/unreleased/Fixes-20241011-103317.yaml new file mode 100644 index 000000000..ba0e26d8e --- /dev/null +++ b/.changes/unreleased/Fixes-20241011-103317.yaml @@ -0,0 +1,6 @@ +kind: Fixes +body: Foreign key constraint on incremental model results in Database Error +time: 2024-10-11T10:33:17.860744-04:00 +custom: + Author: bdgeise + Issue: "628" diff --git a/dbt/include/redshift/macros/adapters.sql b/dbt/include/redshift/macros/adapters.sql index 8b74933bd..9b612efa8 100644 --- a/dbt/include/redshift/macros/adapters.sql +++ b/dbt/include/redshift/macros/adapters.sql @@ -42,37 +42,28 @@ {%- set backup = config.get('backup') -%} {{ sql_header if sql_header is not none }} - - {%- set contract_config = config.get('contract') -%} - {%- if contract_config.enforced -%} - create {% if temporary -%}temporary{%- endif %} table {{ relation.include(database=(not temporary), schema=(not temporary)) }} - {{ get_table_columns_and_constraints() }} - {{ get_assert_columns_equivalent(sql) }} - {%- set sql = get_select_subquery(sql) %} {% if backup == false -%}backup no{%- endif %} {{ dist(_dist) }} {{ sort(_sort_type, _sort) }} - ; - - insert into {{ relation.include(database=(not temporary), schema=(not temporary)) }} - ( - {{ sql }} - ) - ; + {%- set contract_config = config.get('contract') -%} + {%- if contract_config.enforced -%} + {{ get_assert_columns_equivalent(sql) }} + {% endif -%} + {% if contract_config.enforced and (not temporary) -%} + {{ get_table_columns_and_constraints() }}; + {%- set sql = get_select_subquery(sql) %} + insert into {{ relation.include(database=(not temporary), schema=(not temporary)) }} + ( + {{ sql }} + ) + ; {%- else %} - - create {% if temporary -%}temporary{%- endif %} table - {{ relation.include(database=(not temporary), schema=(not temporary)) }} - {% if backup == false -%}backup no{%- endif %} - {{ dist(_dist) }} - {{ sort(_sort_type, _sort) }} as ( {{ sql }} ); - {%- endif %} {%- endmacro %} diff --git a/tests/functional/adapter/test_constraints.py b/tests/functional/adapter/test_constraints.py index a97c66bbd..15a477224 100644 --- a/tests/functional/adapter/test_constraints.py +++ b/tests/functional/adapter/test_constraints.py @@ -9,6 +9,7 @@ BaseIncrementalConstraintsRollback, BaseModelConstraintsRuntimeEnforcement, BaseConstraintQuotedColumn, + TestIncrementalForeignKeyConstraint, ) _expected_sql_redshift = """ @@ -147,3 +148,54 @@ def expected_sql(self): ) as model_subq ); """ + + +class TestRedshiftIncrementalForeignKeyConstraint(TestIncrementalForeignKeyConstraint): + @pytest.fixture(scope="class") + def macros(self): + return { + "create_table.sql": """ +{% macro create_table_macro() %} +create table if not exists numbers (n int not null primary key) +{% endmacro %} +""", + } + + @pytest.fixture(scope="class") + def models(self): + return { + "schema.yml": """ +version: 2 +models: + - name: raw_numbers + config: + contract: + enforced: true + materialized: table + columns: + - name: n + data_type: integer + constraints: + - type: primary_key + - type: not_null + - name: stg_numbers + config: + contract: + enforced: true + materialized: incremental + on_schema_change: append_new_columns + unique_key: n + columns: + - name: n + data_type: integer + constraints: + - type: foreign_key + expression: {schema}.raw_numbers (n) +""", + "raw_numbers.sql": """ +select 1 as n +""", + "stg_numbers.sql": """ +select * from {{ ref('raw_numbers') }} +""", + }