Summary
For a schema with a composite primary key, datacontract dbt sync generates a singular test that quotes column names with double quotes. Databricks and Spark SQL read a double-quoted value as a string literal, not as an identifier. The query then groups every row under one constant tuple, so on any table with more than one row it returns exactly one row and the test fails. Data that is actually unique still fails.
Version
- datacontract-cli 1.2.0. The same code is on
main, so 1.2.4 is affected too.
- dbt-core 1.11, dbt-databricks 1.12.1
Steps to reproduce
Contract excerpt (ODCS v3.1.0):
schema:
- name: my_fact
properties:
- name: machine_number
logicalType: integer
physicalType: int
required: true
primaryKey: true
primaryKeyPosition: 1
- name: calendar_date
logicalType: date
physicalType: date
required: true
primaryKey: true
primaryKeyPosition: 2
- name: shift
logicalType: string
physicalType: string
required: true
primaryKey: true
primaryKeyPosition: 3
Run datacontract dbt sync and then dbt build on Databricks.
Generated test
SELECT "machine_number", "calendar_date", "shift"
FROM {{ ref('my_fact') }}
GROUP BY "machine_number", "calendar_date", "shift"
HAVING COUNT(*) > 1
Actual result
Failure in test my_fact__1_0_0__my_fact__unique_combination
Got 1 result, configured to fail if != 0
The equivalent dbt_utils.unique_combination_of_columns test on the same table passes.
Cause
_quote_identifier in datacontract/integration/dbt_sync.py always uses ANSI double quotes, whatever the target adapter:
def _quote_identifier(name: str) -> str:
return '"' + name.replace('"', '""') + '"'
_composite_pk_singular_test uses it for both the SELECT and GROUP BY lists. On Databricks/Spark, unless spark.sql.ansi.doubleQuotedIdentifiers is enabled, "machine_number" is the string 'machine_number'.
Workaround
Do not declare a composite primaryKey in the contract, and keep a dbt_utils.unique_combination_of_columns test in the model YAML.
Summary
For a schema with a composite primary key,
datacontract dbt syncgenerates a singular test that quotes column names with double quotes. Databricks and Spark SQL read a double-quoted value as a string literal, not as an identifier. The query then groups every row under one constant tuple, so on any table with more than one row it returns exactly one row and the test fails. Data that is actually unique still fails.Version
main, so 1.2.4 is affected too.Steps to reproduce
Contract excerpt (ODCS v3.1.0):
Run
datacontract dbt syncand thendbt buildon Databricks.Generated test
Actual result
The equivalent
dbt_utils.unique_combination_of_columnstest on the same table passes.Cause
_quote_identifierindatacontract/integration/dbt_sync.pyalways uses ANSI double quotes, whatever the target adapter:_composite_pk_singular_testuses it for both theSELECTandGROUP BYlists. On Databricks/Spark, unlessspark.sql.ansi.doubleQuotedIdentifiersis enabled,"machine_number"is the string'machine_number'.Workaround
Do not declare a composite
primaryKeyin the contract, and keep adbt_utils.unique_combination_of_columnstest in the model YAML.