diff --git a/.changes/unreleased/Fixes-20231004-154558.yaml b/.changes/unreleased/Fixes-20231004-154558.yaml new file mode 100644 index 00000000000..9f26a05f870 --- /dev/null +++ b/.changes/unreleased/Fixes-20231004-154558.yaml @@ -0,0 +1,6 @@ +kind: Fixes +body: Foreign key constraint on incremental model results in Database Error +time: 2023-10-04T15:45:58.298548+01:00 +custom: + Author: aranke + Issue: "8022" diff --git a/core/dbt/include/global_project/macros/materializations/models/table/create_table_as.sql b/core/dbt/include/global_project/macros/materializations/models/table/create_table_as.sql index 8e15d85d9cd..7b50195b177 100644 --- a/core/dbt/include/global_project/macros/materializations/models/table/create_table_as.sql +++ b/core/dbt/include/global_project/macros/materializations/models/table/create_table_as.sql @@ -26,7 +26,7 @@ create {% if temporary: -%}temporary{%- endif %} table {{ relation.include(database=(not temporary), schema=(not temporary)) }} {% set contract_config = config.get('contract') %} - {% if contract_config.enforced %} + {% if contract_config.enforced and (not temporary) %} {{ get_assert_columns_equivalent(sql) }} {{ get_table_columns_and_constraints() }} {%- set sql = get_select_subquery(sql) %} diff --git a/plugins/postgres/dbt/include/postgres/macros/adapters.sql b/plugins/postgres/dbt/include/postgres/macros/adapters.sql index 0c56232bb22..6fbb5fd0a1b 100644 --- a/plugins/postgres/dbt/include/postgres/macros/adapters.sql +++ b/plugins/postgres/dbt/include/postgres/macros/adapters.sql @@ -10,7 +10,7 @@ unlogged {%- endif %} table {{ relation }} {% set contract_config = config.get('contract') %} - {% if contract_config.enforced %} + {% if contract_config.enforced and (not temporary) %} {{ get_assert_columns_equivalent(sql) }} {{ get_table_columns_and_constraints() }} ; insert into {{ relation }} ( diff --git a/tests/adapter/dbt/tests/adapter/constraints/fixtures.py b/tests/adapter/dbt/tests/adapter/constraints/fixtures.py index c8c98b26bd5..5c0620194c1 100644 --- a/tests/adapter/dbt/tests/adapter/constraints/fixtures.py +++ b/tests/adapter/dbt/tests/adapter/constraints/fixtures.py @@ -539,3 +539,47 @@ - name: column_name data_type: text """ + +create_table_macro_sql = """ +{% macro create_table_macro() %} +create table if not exists numbers (n int not null primary key) +{% endmacro %} +""" + +incremental_foreign_key_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) +""" + +incremental_foreign_key_model_raw_numbers_sql = """ +select 1 as n +""" + +incremental_foreign_key_model_stg_numbers_sql = """ +select * from {{ ref('raw_numbers') }} +""" diff --git a/tests/adapter/dbt/tests/adapter/constraints/test_constraints.py b/tests/adapter/dbt/tests/adapter/constraints/test_constraints.py index 188c3793032..28257d177db 100644 --- a/tests/adapter/dbt/tests/adapter/constraints/test_constraints.py +++ b/tests/adapter/dbt/tests/adapter/constraints/test_constraints.py @@ -34,6 +34,10 @@ my_model_contract_sql_header_sql, my_model_incremental_contract_sql_header_sql, model_contract_header_schema_yml, + create_table_macro_sql, + incremental_foreign_key_schema_yml, + incremental_foreign_key_model_raw_numbers_sql, + incremental_foreign_key_model_stg_numbers_sql, ) @@ -530,3 +534,31 @@ def expected_sql(self): class TestConstraintQuotedColumn(BaseConstraintQuotedColumn): pass + + +class TestIncrementalForeignKeyConstraint: + @pytest.fixture(scope="class") + def macros(self): + return { + "create_table.sql": create_table_macro_sql, + } + + @pytest.fixture(scope="class") + def models(self): + return { + "schema.yml": incremental_foreign_key_schema_yml, + "raw_numbers.sql": incremental_foreign_key_model_raw_numbers_sql, + "stg_numbers.sql": incremental_foreign_key_model_stg_numbers_sql, + } + + def test_incremental_foreign_key_constraint(self, project): + unformatted_constraint_schema_yml = read_file("models", "schema.yml") + write_file( + unformatted_constraint_schema_yml.format(schema=project.test_schema), + "models", + "schema.yml", + ) + + run_dbt(["run", "--select", "raw_numbers"]) + run_dbt(["run", "--select", "stg_numbers"]) + run_dbt(["run", "--select", "stg_numbers"])