Skip to content

Commit 84fb0ce

Browse files
committed
Fix TypedConstraint equality check
1 parent 6981678 commit 84fb0ce

File tree

5 files changed

+70
-0
lines changed

5 files changed

+70
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
### Fixes
44

55
- Fix inefficient query when getting column schema for MV/STs ([1074](https://github.com/databricks/dbt-databricks/issues/1074))
6+
- Fix bug causing false positives in diffing constraints between existing relation and model config for incremental runs ([1081](https://github.com/databricks/dbt-databricks/issues/1081))
67

78
## dbt-databricks 1.10.4 (June 24, 2025)
89

dbt/adapters/databricks/constraints.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,14 @@ def __hash__(self) -> int:
7676
)
7777
return hash(fields)
7878

79+
def __eq__(self, other: Any) -> bool:
80+
"""Override equality to only compare fields used in hash calculation.
81+
82+
This ensures hash/equality contract is maintained and prevents issues
83+
with set operations when warn_unenforced/warn_unsupported differ.
84+
"""
85+
return self.__hash__() == other.__hash__()
86+
7987

8088
class CustomConstraint(TypedConstraint):
8189
str_type = "custom"

tests/functional/adapter/incremental/fixtures.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,3 +1011,43 @@ def model(dbt, spark):
10111011
data = [[1, 'hello', 'blue']]
10121012
return spark.createDataFrame(data, schema=['id', 'msg', 'color'])
10131013
"""
1014+
1015+
warn_unenforced_override_sql = """
1016+
select "abc" as id
1017+
"""
1018+
1019+
warn_unenforced_override_model = """
1020+
version: 2
1021+
1022+
models:
1023+
- name: model_a
1024+
config:
1025+
materialized: incremental
1026+
on_schema_change: fail
1027+
columns:
1028+
- name: id
1029+
data_type: string
1030+
constraints:
1031+
- type: not_null
1032+
constraints:
1033+
- type: primary_key
1034+
columns:
1035+
- id
1036+
name: model_a_pk
1037+
warn_unenforced: false
1038+
1039+
- name: model_b
1040+
config:
1041+
materialized: table
1042+
columns:
1043+
- name: id
1044+
data_type: string
1045+
constraints:
1046+
- type: foreign_key
1047+
columns:
1048+
- id
1049+
name: model_b_fk
1050+
to: ref('model_a')
1051+
to_columns: [id]
1052+
warn_unenforced: false
1053+
"""

tests/functional/adapter/incremental/test_incremental_constraints.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,24 @@ def test_add_foreign_key_constraint(self, project):
216216
expected_pairs = {("fk_to_parent", "pk_parent"), ("fk_to_parent_2", "pk_parent_2")}
217217
assert constraint_pairs == expected_pairs
218218

219+
# Specifically for testing bugs like https://github.com/databricks/dbt-databricks/issues/1081
220+
# where the config diff between the existing relation and model definition incorrectly detected
221+
# constraints that were not changed. This is because the TypedConstraint read from existing
222+
# Databricks relations will just have a default value for warn_unenforced which should
223+
# be ignored during the diff
224+
def test_warn_unenforced_false(self, project):
225+
util.run_dbt(["run"])
226+
referential_constraints = project.run_sql(referential_constraint_sql, fetch="all")
227+
assert len(referential_constraints) == 0
228+
229+
util.write_file(fixtures.warn_unenforced_override_sql, "models", "model_a.sql")
230+
util.write_file(fixtures.warn_unenforced_override_sql, "models", "model_b.sql")
231+
util.write_file(fixtures.warn_unenforced_override_model, "models", "schema.yml")
232+
util.run_dbt(["run"])
233+
util.run_dbt(["run"])
234+
referential_constraints = project.run_sql(referential_constraint_sql, fetch="all")
235+
assert len(referential_constraints) == 1
236+
219237

220238
@pytest.mark.skip_profile("databricks_cluster")
221239
class TestIncrementalRemoveForeignKeyConstraint:

tests/unit/relation_configs/test_constraint.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ def test_get_diff__mixed_case(self):
281281
type=ConstraintType.check,
282282
name="check_name_length",
283283
expression="LENGTH (name) >= 1",
284+
warn_unenforced=False,
284285
),
285286
PrimaryKeyConstraint(
286287
type=ConstraintType.primary_key,
@@ -296,6 +297,8 @@ def test_get_diff__mixed_case(self):
296297
type=ConstraintType.check,
297298
name="check_name_length",
298299
expression="LENGTH (name) >= 1",
300+
# This should be ignored by the TypedConstraint equality check
301+
warn_unenforced=True,
299302
),
300303
PrimaryKeyConstraint(
301304
type=ConstraintType.primary_key,

0 commit comments

Comments
 (0)