Skip to content

Commit b8a1a08

Browse files
Merge pull request #81 from Snowflake-Labs/80-additional-model-exists-verification
80 additional model exists verification
2 parents 6b20f14 + 3fb434e commit b8a1a08

File tree

4 files changed

+83
-53
lines changed

4 files changed

+83
-53
lines changed

dbt_project.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
name: 'dbt_constraints'
3-
version: '1.0.3'
3+
version: '1.0.4'
44
config-version: 2
55

66
# These macros depend on the results and graph objects in dbt >=0.19.0

integration_tests/dbt_project.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ vars:
4242
dbt_constraints_sources_uk_enabled: true
4343
dbt_constraints_sources_fk_enabled: true
4444

45+
on-run-start:
46+
- "drop table if exists dim_orders"
4547

4648
models:
4749
+materialized: table

integration_tests/packages.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ packages:
22

33
# We will test unique keys based on dbt_utils.unique_combination_of_columns
44
- package: dbt-labs/dbt_utils
5-
version: [">=1.2.0"]
5+
version: [">=1.3.0"]
66

77
- local: ../

macros/create_constraints.sql

Lines changed: 79 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -174,16 +174,15 @@
174174
{#- This macro checks if a test or its model is selected -#}
175175
{%- macro test_selected(test_model) -%}
176176

177-
{%- if test_model.unique_id and test_model.unique_id in selected_resources -%}
177+
{%- if test_model.unique_id in selected_resources -%}
178178
{{ return("TEST_SELECTED") }}
179179
{%- endif -%}
180-
{%- if test_model.attached_node and test_model.attached_node in selected_resources -%} -%}
180+
{%- if test_model.attached_node in selected_resources -%} -%}
181181
{{ return("MODEL_SELECTED") }}
182182
{%- endif -%}
183183

184184
{#- Check if a PK/UK should be created because it is referenced by a selected FK -#}
185-
{%- if test_model.test_metadata
186-
and test_model.test_metadata.name in ("primary_key", "unique_key", "unique_combination_of_columns", "unique") -%}
185+
{%- if test_model.test_metadata.name in ("primary_key", "unique_key", "unique_combination_of_columns", "unique") -%}
187186
{%- set pk_test_args = test_model.test_metadata.kwargs -%}
188187
{%- set pk_test_columns = [] -%}
189188
{%- if pk_test_args.column_names -%}
@@ -230,7 +229,10 @@
230229
{%- for res in results
231230
if res.node.config.materialized == "test"
232231
and res.node.unique_id == test_model.unique_id -%}
233-
{%- if res.failures > 0 -%}
232+
{%- if res.failures == None -%}
233+
{#- Set '' if we do not know if there is a test failure -#}
234+
{{ return('') }}
235+
{%- elif res.failures > 0 -%}
234236
{#- Set NORELY if there is a test failure -#}
235237
{{ return('NORELY') }}
236238
{%- elif res.failures == 0 -%}
@@ -261,10 +263,17 @@
261263
{#- This macro is called internally and passed which constraint types to create. -#}
262264
{%- macro create_constraints_by_type(constraint_types, quote_columns, lookup_cache) -%}
263265

264-
{#- Loop through the metadata and find all tests that match the constraint_types -#}
266+
{#- Loop through the metadata and find all tests that match the constraint_types and have all the fields we check for tests -#}
265267
{%- for test_model in graph.nodes.values() | selectattr("resource_type", "equalto", "test")
266268
if test_model.test_metadata
269+
and test_model.test_metadata.kwargs
270+
and test_model.test_metadata.name
267271
and test_model.test_metadata.name is in( constraint_types )
272+
and test_model.unique_id
273+
and test_model.attached_node
274+
and test_model.depends_on
275+
and test_model.depends_on.nodes
276+
and test_model.config
268277
and test_model.config.enabled
269278
and test_model.config.get("dbt_constraints_enabled", true) -%}
270279

@@ -300,7 +309,8 @@
300309
{#- Find the table models that are referenced by this test. -#}
301310
{%- for table_node in test_model.depends_on.nodes -%}
302311
{%- for node in graph.nodes.values() | selectattr("unique_id", "equalto", table_node)
303-
if node.config.get("materialized", "other") not in ("view", "ephemeral", "dynamic_table")
312+
if node.config
313+
and node.config.get("materialized", "other") not in ("view", "ephemeral", "dynamic_table")
304314
and ( node.resource_type in ("model", "snapshot", "seed")
305315
or ( node.resource_type == "source" and var('dbt_constraints_sources_enabled', false)
306316
and ( ( var('dbt_constraints_sources_pk_enabled', false) and test_name in("primary_key") )
@@ -340,21 +350,25 @@
340350
) }}
341351
{%- endif -%}
342352

343-
{%- set table_relation = api.Relation.create(
353+
{%- set table_relation = adapter.get_relation(
344354
database=table_models[0].database,
345355
schema=table_models[0].schema,
346356
identifier=table_models[0].alias ) -%}
347-
{%- if dbt_constraints.table_columns_all_exist(table_relation, column_names, lookup_cache) -%}
348-
{%- if test_name == "primary_key" -%}
349-
{%- if dbt_constraints.adapter_supports_rely_norely("not_null") == true -%}
350-
{%- do dbt_constraints.create_not_null(table_relation, column_names, ns.verify_permissions, quote_columns, lookup_cache, rely_clause) -%}
357+
{%- if table_relation and table_relation.is_table -%}
358+
{%- if dbt_constraints.table_columns_all_exist(table_relation, column_names, lookup_cache) -%}
359+
{%- if test_name == "primary_key" -%}
360+
{%- if dbt_constraints.adapter_supports_rely_norely("not_null") == true -%}
361+
{%- do dbt_constraints.create_not_null(table_relation, column_names, ns.verify_permissions, quote_columns, lookup_cache, rely_clause) -%}
362+
{%- endif -%}
363+
{%- do dbt_constraints.create_primary_key(table_relation, column_names, ns.verify_permissions, quote_columns, test_parameters.constraint_name, lookup_cache, rely_clause) -%}
364+
{%- else -%}
365+
{%- do dbt_constraints.create_unique_key(table_relation, column_names, ns.verify_permissions, quote_columns, test_parameters.constraint_name, lookup_cache, rely_clause) -%}
351366
{%- endif -%}
352-
{%- do dbt_constraints.create_primary_key(table_relation, column_names, ns.verify_permissions, quote_columns, test_parameters.constraint_name, lookup_cache, rely_clause) -%}
353367
{%- else -%}
354-
{%- do dbt_constraints.create_unique_key(table_relation, column_names, ns.verify_permissions, quote_columns, test_parameters.constraint_name, lookup_cache, rely_clause) -%}
368+
{%- do log("Skipping primary/unique key because a physical column name was not found on the table: " ~ table_models[0].name ~ " " ~ column_names, info=true) -%}
355369
{%- endif -%}
356370
{%- else -%}
357-
{%- do log("Skipping primary/unique key because a physical column name was not found on the table: " ~ table_models[0].name ~ " " ~ column_names, info=true) -%}
371+
{%- do log("Skipping primary/unique key because the table was not found in the database: " ~ table_models[0].name, info=true) -%}
358372
{%- endif -%}
359373

360374
{#- We only create FK if there are two models referenced by the test
@@ -367,50 +381,60 @@
367381

368382
{%- if fk_model and pk_model -%}
369383

370-
{%- set fk_table_relation = api.Relation.create(
384+
{%- set fk_table_relation = adapter.get_relation(
371385
database=fk_model.database,
372386
schema=fk_model.schema,
373387
identifier=fk_model.alias) -%}
374388

375-
{%- set pk_table_relation = api.Relation.create(
389+
{%- set pk_table_relation = adapter.get_relation(
376390
database=pk_model.database,
377391
schema=pk_model.schema,
378392
identifier=pk_model.alias) -%}
379393

380-
{# Attempt to identify parameters we can use for the column names #}
381-
{%- set pk_column_names = [] -%}
382-
{%- if test_parameters.pk_column_names -%}
383-
{%- set pk_column_names = test_parameters.pk_column_names -%}
384-
{%- elif test_parameters.field -%}
385-
{%- set pk_column_names = [test_parameters.field] -%}
386-
{%- elif test_parameters.pk_column_name -%}
387-
{%- set pk_column_names = [test_parameters.pk_column_name] -%}
388-
{%- else -%}
389-
{{ exceptions.raise_compiler_error(
390-
"`pk_column_names`, `pk_column_name`, or `field` parameter missing for foreign key constraint on table: '" ~ fk_model.name ~ " " ~ test_parameters
391-
) }}
392-
{%- endif -%}
394+
{%- if fk_table_relation and pk_table_relation and fk_table_relation.is_table and pk_table_relation.is_table-%}
395+
{# Attempt to identify parameters we can use for the column names #}
396+
{%- set pk_column_names = [] -%}
397+
{%- if test_parameters.pk_column_names -%}
398+
{%- set pk_column_names = test_parameters.pk_column_names -%}
399+
{%- elif test_parameters.field -%}
400+
{%- set pk_column_names = [test_parameters.field] -%}
401+
{%- elif test_parameters.pk_column_name -%}
402+
{%- set pk_column_names = [test_parameters.pk_column_name] -%}
403+
{%- else -%}
404+
{{ exceptions.raise_compiler_error(
405+
"`pk_column_names`, `pk_column_name`, or `field` parameter missing for foreign key constraint on table: '" ~ fk_model.name ~ " " ~ test_parameters
406+
) }}
407+
{%- endif -%}
393408

394-
{%- set fk_column_names = [] -%}
395-
{%- if test_parameters.fk_column_names -%}
396-
{%- set fk_column_names = test_parameters.fk_column_names -%}
397-
{%- elif test_parameters.column_name -%}
398-
{%- set fk_column_names = [test_parameters.column_name] -%}
399-
{%- elif test_parameters.fk_column_name -%}
400-
{%- set fk_column_names = [test_parameters.fk_column_name] -%}
401-
{%- else -%}
402-
{{ exceptions.raise_compiler_error(
403-
"`fk_column_names`, `fk_column_name`, or `column_name` parameter missing for foreign key constraint on table: '" ~ fk_model.name ~ " " ~ test_parameters
404-
) }}
405-
{%- endif -%}
409+
{%- set fk_column_names = [] -%}
410+
{%- if test_parameters.fk_column_names -%}
411+
{%- set fk_column_names = test_parameters.fk_column_names -%}
412+
{%- elif test_parameters.column_name -%}
413+
{%- set fk_column_names = [test_parameters.column_name] -%}
414+
{%- elif test_parameters.fk_column_name -%}
415+
{%- set fk_column_names = [test_parameters.fk_column_name] -%}
416+
{%- else -%}
417+
{{ exceptions.raise_compiler_error(
418+
"`fk_column_names`, `fk_column_name`, or `column_name` parameter missing for foreign key constraint on table: '" ~ fk_model.name ~ " " ~ test_parameters
419+
) }}
420+
{%- endif -%}
406421

407-
{%- if not dbt_constraints.table_columns_all_exist(pk_table_relation, pk_column_names, lookup_cache) -%}
408-
{%- do log("Skipping foreign key because a physical column was not found on the pk table: " ~ pk_model.name ~ " " ~ pk_column_names, info=true) -%}
409-
{%- elif not dbt_constraints.table_columns_all_exist(fk_table_relation, fk_column_names, lookup_cache) -%}
410-
{%- do log("Skipping foreign key because a physical column was not found on the fk table: " ~ fk_model.name ~ " " ~ fk_column_names, info=true) -%}
422+
{%- if not dbt_constraints.table_columns_all_exist(pk_table_relation, pk_column_names, lookup_cache) -%}
423+
{%- do log("Skipping foreign key because a physical column was not found on the pk table: " ~ pk_model.name ~ " " ~ pk_column_names, info=true) -%}
424+
{%- elif not dbt_constraints.table_columns_all_exist(fk_table_relation, fk_column_names, lookup_cache) -%}
425+
{%- do log("Skipping foreign key because a physical column was not found on the fk table: " ~ fk_model.name ~ " " ~ fk_column_names, info=true) -%}
426+
{%- else -%}
427+
{%- do dbt_constraints.create_foreign_key(pk_table_relation, pk_column_names, fk_table_relation, fk_column_names, ns.verify_permissions, quote_columns, test_parameters.constraint_name, lookup_cache, rely_clause) -%}
428+
{%- endif -%}
411429
{%- else -%}
412-
{%- do dbt_constraints.create_foreign_key(pk_table_relation, pk_column_names, fk_table_relation, fk_column_names, ns.verify_permissions, quote_columns, test_parameters.constraint_name, lookup_cache, rely_clause) -%}
430+
{%- if fk_model == None or not fk_table_relation.is_table -%}
431+
{%- do log("Skipping foreign key to " ~ pk_model.alias ~ " because the child table was not found in the database: " ~ fk_model.alias, info=true) -%}
432+
{%- endif -%}
433+
{%- if pk_model == None or not pk_model.is_table -%}
434+
{%- do log("Skipping foreign key on " ~ fk_model.alias ~ " because the parent table was not found in the database: " ~ pk_model.alias, info=true) -%}
435+
{%- endif -%}
413436
{%- endif -%}
437+
414438
{%- else -%}
415439
{%- do log("Skipping foreign key because a we couldn't find the child table: model=" ~ test_model.attached_node ~ " or source", info=true) -%}
416440
{%- endif -%}
@@ -434,15 +458,19 @@
434458
) }}
435459
{%- endif -%}
436460

437-
{%- set table_relation = api.Relation.create(
461+
{%- set table_relation = adapter.get_relation(
438462
database=table_models[0].database,
439463
schema=table_models[0].schema,
440464
identifier=table_models[0].alias ) -%}
441465

442-
{%- if dbt_constraints.table_columns_all_exist(table_relation, column_names, lookup_cache) -%}
443-
{%- do dbt_constraints.create_not_null(table_relation, column_names, ns.verify_permissions, quote_columns, lookup_cache, rely_clause) -%}
466+
{%- if table_relation and table_relation.is_table -%}
467+
{%- if dbt_constraints.table_columns_all_exist(table_relation, column_names, lookup_cache) -%}
468+
{%- do dbt_constraints.create_not_null(table_relation, column_names, ns.verify_permissions, quote_columns, lookup_cache, rely_clause) -%}
469+
{%- else -%}
470+
{%- do log("Skipping not null constraint because a physical column name was not found on the table: " ~ table_models[0].name ~ " " ~ column_names, info=true) -%}
471+
{%- endif -%}
444472
{%- else -%}
445-
{%- do log("Skipping not null constraint because a physical column name was not found on the table: " ~ table_models[0].name ~ " " ~ column_names, info=true) -%}
473+
{%- do log("Skipping not null constraint because the table was not found in the database: " ~ table_models[0].name, info=true) -%}
446474
{%- endif -%}
447475

448476
{%- endif -%}

0 commit comments

Comments
 (0)