DBT单元测试遇结构体字段过多时执行失败的解决办法
DBT单元测试处理大结构体字段的问题与解决方案
问题描述
我在Databricks上运行DBT模型,实施单元测试时遇到了结构体字段过多导致的语法错误。
我的DBT单元测试代码如下:
unit_tests: - name: test_my_model model: my_model given: - input: source('my_schema', 'my_table_1') rows: - {application_id: 1, created_at: "2025-01-01"} - {application_id: 2, created_at: "2025-01-03"} - input: ref('reference__reference__days') rows: - {date: "2025-01-01"} - {date: "2025-01-02"} - {date: "2025-01-03"} - input: source('my_schema', 'my_table_2') rows: - {id: 10, application_id: 1, effective_on: "2025-01-01"} - {id: 11, application_id: 1, effective_on: "2025-01-02"} - {id: 20, application_id: 2, effective_on: "2025-01-03"} - {id: 21, application_id: 2, effective_on: "2025-01-03"} expect: rows: - {application_id: 1, date: "2025-01-01", effective_on: "2025-01-01"} - {application_id: 1, date: "2025-01-02", effective_on: "2025-01-02"} - {application_id: 1, date: "2025-01-03", effective_on: "2025-01-02"} - {application_id: 2, date: "2025-01-03", effective_on: "2025-01-03"}
运行测试时出现语法错误,错误信息显示DBT生成的SQL中结构体字段被截断(比如[20 more sub_fields...]),导致Databricks无法解析:
Runtime Error in unit_test test_my_model (tests/unit/test_path/test_my_model.yml) An error occurred during execution of unit test 'test_my_model'. There may be an error in the unit test definition: check the data types. Database Error [PARSE_SYNTAX_ERROR] Syntax error at or near '.'. SQLSTATE: 42601 == SQL == /* {"app": "dbt", "dbt_version": "1.9.4", "dbt_databricks_version": "1.10.2", "databricks_sql_connector_version": "4.0.3"} */ create or replace temporary view `test_my_model__dbt_tmp` as select * from ( with __dbt__cte__table_1 as ( -- Fixture for table_1 select cast(null as bigint) as field_1, cast(null as timestamp) as field_2, cast(null as array<struct<sub_field_1:boolean,sub_field_2:boolean,[20 more sub_fields...],... 108 more fields>>) as field_3, --------------------------------------------------------------------------------------------^^^ [more fields...]
我需要解决两个问题:
- 强制DBT发送完整Schema而非截断内容;
- 仅发送结构体中的必要字段而非全部字段。
解决方案
1. 强制DBT发送完整Schema,避免截断
DBT默认会对过长的Schema定义进行截断,可通过修改项目配置禁用或调整截断长度:
在dbt_project.yml中添加或修改以下配置:
tests: unit: schema_truncation_length: 0 # 0表示不截断,也可设置足够大的数值(如100000)
该配置控制单元测试生成SQL时Schema字段的截断长度,设置为0即可强制发送完整的结构体定义。
注意:若使用旧版本dbt-databricks插件,建议升级到1.11.0+版本,该版本优化了结构体字段的处理逻辑。
2. 仅发送结构体中的必要字段
如果模型只用到结构体中的部分子字段,可通过以下两种方式减少测试中的字段数量:
方式一:在单元测试fixture中明确指定所需字段
在given部分的输入定义里,用columns参数指定模型需要的字段(包括结构体的子字段),替代自动生成的全量Schema:
given: - input: source('my_schema', 'my_table_1') columns: - name: application_id data_type: bigint - name: created_at data_type: timestamp - name: field_3 data_type: array<struct<sub_field_1:boolean, sub_field_2:boolean>> # 仅包含需要的子字段 rows: - {application_id: 1, created_at: "2025-01-01", field_3: []} - {application_id: 2, created_at: "2025-01-03", field_3: []}
这种方式直接定义测试所需的字段和类型,避免生成不必要的结构体子字段。
方式二:创建测试专用的简化视图
在dbt项目中创建仅包含模型所需字段的视图,代替原表作为测试依赖:
-- models/test_utils/my_table_1_simplified.sql select application_id, created_at, array_transform(field_3, x -> struct(x.sub_field_1, x.sub_field_2)) as field_3 from {{ source('my_schema', 'my_table_1') }}
然后在单元测试中引用这个视图:
given: - input: ref('my_table_1_simplified') rows: - {application_id: 1, created_at: "2025-01-01", field_3: []} - {application_id: 2, created_at: "2025-01-03", field_3: []}
这种方式适合多个测试场景需要复用简化结构的情况。
内容的提问来源于stack exchange,提问作者Nakeuh
相关产品推荐
相关产品推荐

