From e6d269731d5c5c06f2ebf625d0837b1ecf5e30ed Mon Sep 17 00:00:00 2001 From: James Johnston Date: Mon, 24 Mar 2025 21:02:03 -0700 Subject: [PATCH] equality test: don't always require a Relation The equality test only needs a Relation when it needs to examine the model schema using the adapter. If the user provides all column names to compare, and does not use the 'precision' option, then no Relation is actually needed. In this case, an arbitrary subquery can be passed instead. For example, the get_where_subquery can be used. --- integration_tests/models/generic_tests/schema.yml | 14 ++++++++++++++ macros/generic_tests/equality.sql | 7 ++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/integration_tests/models/generic_tests/schema.yml b/integration_tests/models/generic_tests/schema.yml index b12e3c7f..4a107c0c 100644 --- a/integration_tests/models/generic_tests/schema.yml +++ b/integration_tests/models/generic_tests/schema.yml @@ -150,6 +150,20 @@ seeds: data_tests: - dbt_utils.equality: compare_model: ref('data_test_equality_a') + - dbt_utils.equality: + name: equality_test_with_where_clause + compare_model: | + (select 1 as col_a, 1 as col_b, 3 as col_c + union all + select 1 as col_a, 2 as col_b, 1 as col_c) compare_subquery + compare_columns: + - col_a + - col_b + - col_c + # NOTE: this 'where' syntax only works when we provide compare_columns and do not specify + # the precision parameter. + config: + where: col_a <> 2 - dbt_utils.equality: compare_model: ref('data_test_equality_b') error_if: "<1" #sneaky way to ensure that the test is returning failing rows diff --git a/macros/generic_tests/equality.sql b/macros/generic_tests/equality.sql index d7d7197c..7b9e6795 100644 --- a/macros/generic_tests/equality.sql +++ b/macros/generic_tests/equality.sql @@ -25,12 +25,11 @@ --- setup -{%- do dbt_utils._is_relation(model, 'test_equality') -%} - {# Ensure there are no extra columns in the compare_model vs model #} {%- if not compare_columns -%} + {%- do dbt_utils._is_relation(model, 'test_equality') -%} {%- do dbt_utils._is_ephemeral(model, 'test_equality') -%} + {%- do dbt_utils._is_relation(compare_model, 'test_equality') -%} {%- do dbt_utils._is_ephemeral(compare_model, 'test_equality') -%} {%- set model_columns = adapter.get_columns_in_relation(model) -%} @@ -75,6 +74,7 @@ You cannot get the columns in an ephemeral model (due to not existing in the information schema), so if the user does not provide an explicit list of columns we must error in the case it is ephemeral #} + {%- do dbt_utils._is_relation(model, 'test_equality') -%} {%- do dbt_utils._is_ephemeral(model, 'test_equality') -%} {%- set compare_columns = adapter.get_columns_in_relation(model)-%} @@ -102,6 +102,7 @@ {#- If rounding is required, we need to get the types, so it cannot be ephemeral even if they provide column names -#} + {%- do dbt_utils._is_relation(model, 'test_equality') -%} {%- do dbt_utils._is_ephemeral(model, 'test_equality') -%} {%- set columns = adapter.get_columns_in_relation(model) -%}