Skip to content

Commit

Permalink
Nicer error message for contracted model missing 'columns' (#8024) (#…
Browse files Browse the repository at this point in the history
…8041)

(cherry picked from commit 746ca7d)

Co-authored-by: Jeremy Cohen <[email protected]>
  • Loading branch information
github-actions[bot] and jtcohen6 authored Jul 11, 2023
1 parent f466740 commit 2d75829
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 1 deletion.
6 changes: 6 additions & 0 deletions .changes/unreleased/Fixes-20230704-114752.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Fixes
body: Nicer error message if model with enforced contract is missing 'columns' specification
time: 2023-07-04T11:47:52.976527+02:00
custom:
Author: jtcohen6
Issue: "7943"
5 changes: 5 additions & 0 deletions core/dbt/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2250,6 +2250,11 @@ def get_mismatches(self) -> agate.Table:
return table_from_data_flat(mismatches_sorted, column_names)

def get_message(self) -> str:
if not self.yaml_columns:
return (
"This model has an enforced contract, and its 'columns' specification is missing"
)

table: agate.Table = self.get_mismatches()
# Hack to get Agate table output as string
output = io.StringIO()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,17 @@
If any differences in name, data_type or number of columns exist between the two schemas, raises a compiler error
#}
{% macro assert_columns_equivalent(sql) %}

{#-- First ensure the user has defined 'columns' in yaml specification --#}
{%- set user_defined_columns = model['columns'] -%}
{%- if not user_defined_columns -%}
{{ exceptions.raise_contract_error([], []) }}
{%- endif -%}

{#-- Obtain the column schema provided by sql file. #}
{%- set sql_file_provided_columns = get_column_schema_from_query(sql, config.get('sql_header', none)) -%}
{#--Obtain the column schema provided by the schema file by generating an 'empty schema' query from the model's columns. #}
{%- set schema_file_provided_columns = get_column_schema_from_query(get_empty_schema_sql(model['columns'])) -%}
{%- set schema_file_provided_columns = get_column_schema_from_query(get_empty_schema_sql(user_defined_columns)) -%}

{#-- create dictionaries with name and formatted data type and strings for exception #}
{%- set sql_columns = format_columns(sql_file_provided_columns) -%}
Expand Down
15 changes: 15 additions & 0 deletions tests/functional/configs/test_contract_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -471,3 +471,18 @@ def test__python_errors(self, project):
exc_str = " ".join(str(err_info.value).split())
expected_python_error = "Language Error: Expected 'sql' but found 'python'"
assert expected_python_error in exc_str


class TestModelContractMissingYAMLColumns:
@pytest.fixture(scope="class")
def models(self):
return {
"my_model.sql": my_model_contract_sql,
}

def test__missing_column_contract_error(self, project):
results = run_dbt(["run"], expect_pass=False)
expected_error = (
"This model has an enforced contract, and its 'columns' specification is missing"
)
assert expected_error in results[0].message

0 comments on commit 2d75829

Please sign in to comment.