Models
Contracts
Validate required or exact model output schemas.
A model’s declared columns provide output metadata, type enforcement, and column audit attachment. The project column_contract_mode and model contract policy determine whether those declarations also define a statically validated output shape.
| Model declaration | Behavior |
|---|---|
| Unspecified | Follow settings.column_contract_mode: implicit validates declared columns as an open shape; explicit treats them as metadata and audit attachment only. |
none |
Do not activate declared-shape or nullability contract validation for this model. Explicit type enforcement remains active. |
enforced |
Treat declared columns as the complete authoritative output shape and enable runtime exact-schema checks on supported materializations. |
The project default is column_contract_mode = "implicit", which preserves SQLBuild’s original behavior. Projects that use column declarations primarily for metadata and audits, including migrations from dbt, can opt into explicit contracts:
[settings]column_contract_mode = "explicit"Under explicit mode, a model must declare contract enforced to activate shape validation. A model-level contract enforced or contract none always overrides the project mode.
MODEL ( materialized table, contract enforced, columns ( order_id (type INTEGER, nullable false), customer_id (type INTEGER, nullable false), amount_cents (type INTEGER), status (type VARCHAR), ),);Validation
Section titled “Validation”Compile time
Section titled “Compile time”When declared-shape validation is active and SQL analysis can infer the model’s output:
- A missing declared column fails.
- A proven type mismatch fails when type enforcement or an exact contract is active.
- A declared non-null column fails when its expression is proven nullable.
- Additional inferred columns fail only for
contract enforced.
If SQLBuild cannot infer the output shape, these static shape checks cannot run. An enforced contract additionally requires a non-empty column declaration and adds runtime requirements on supported materializations.
Type enforcement remains independent. Typed columns continue to receive static type checks and supported runtime casts under explicit mode and contract none.
Configuration fields that reference output columns, including unique_key, cursor, updated_at, and check_columns, are checked against an enforced declaration.
Runtime
Section titled “Runtime”For supported materialization paths, contract enforced inspects the staged relation and rejects:
- Missing declared columns.
- Additional undeclared columns.
- Warehouse types that differ from declared types.
Runtime contract validation does not scan data for nulls and does not inspect warehouse nullability metadata. nullable false participates in static nullability analysis; add a not_null audit when null values must be checked at runtime.
Runtime exact-schema validation currently runs for:
- Staged full-table builds.
- Non-microbatch incremental deltas.
- Snapshot deltas.
Views and custom materializations rely on compile-time contract analysis. Microbatch incrementals currently apply type enforcement and audits but do not perform the framework runtime exact-schema validation step.
Staged table validation happens before promotion, so a failure leaves the existing destination untouched. Immediate table promotion is incompatible with contract enforced because SQLBuild cannot validate output before replacing the destination.
Type enforcement
Section titled “Type enforcement”Declaring a model column type enables type enforcement automatically, independently of the contract policy. Type enforcement controls static type compatibility and runtime casts on supported table and incremental paths; contracts control output shape. See Type Enforcement for the materialization matrix.
Reusable schemas
Section titled “Reusable schemas”Contracts apply to the effective declaration, not only the reusable base:
MODEL ( model_schema order, columns ( ingestion_batch_id (type VARCHAR, nullable false), ), contract enforced,);With contract enforced, this requires exactly the resolved order columns plus ingestion_batch_id. With contract none, the resolved columns remain metadata, audit attachment points, and inputs to explicit type enforcement without activating shape validation. See Schemas.
Enum columns
Section titled “Enum columns”A column may use a declared enum as a portable logical domain type:
MODEL ( contract enforced, columns ( fulfillment_method (type fulfillment_method), ),);This does not require, create, or reference a warehouse-native enum type. SQLBuild resolves string-valued enums to VARCHAR and integer-valued enums to INTEGER. Under contract enforced, it also generates an accepted_values audit for the declared members. Audit severity and timing follow normal audit configuration and materialization behavior. With the default error severity, it gates staged-table promotion and pre-DML delta paths; views and custom materializations may already have changed their relation when the audit runs.
Enum member references such as @enum("fulfillment_method").DELIVERY are a separate feature that render one validated SQL literal. See Enum Model Contracts for the complete distinction and lowering behavior.
Adopting an existing schema
Section titled “Adopting an existing schema”Ordinary sqb compile validates authored contracts offline. To compare declarations with existing
warehouse relations, use the explicitly online, read-only contract commands:
sqb contract diff --from prod --select tag:commercesqb contract generate --from prod --select tag:commerceThe target named by --from supplies the database and schema namespace to inspect. SQLBuild uses
the active project connection and never resolves a second set of origin credentials.
Preview and write
Section titled “Preview and write”contract diff returns exit code 1 when declarations and physical relations disagree.
contract generate prints proposed declaration changes without changing files:
# Fill missing types and append physical columns missing from codesqb contract generate --from prod --select tag:commerce --write
# Replace conflicting types/names and remove declarations absent physicallysqb contract generate --from prod --select tag:commerce --write --overwriteContract commands never mutate warehouse relations, lifecycle state, or fingerprints.
Safety rules
Section titled “Safety rules”- Additive generation preserves existing types on conflict, repository-only columns, comments, descriptions, audits, nullability, enums, tags, freshness, and loader configuration.
--overwriteis an explicit repository replacement policy, not a warehouse write.- Generation does not add
contract enforced; activation remains an authored decision. - A shared
SCHEMA()is not changed from one model’s evidence. Ownership conflicts are reported. - Writes are atomic and SQLBuild recompiles the project, restoring prior contents if validation fails.
- Sources are first-class selectable resources, for example
--select source:raw_orders.
Enforced upstream contracts are authoritative compile-time interfaces. When input evidence is
complete, missing or ambiguous columns fail in projections, joins, filters, grouping, windows, and
ordering. Partial or opaque schemas remain open; SQLBuild does not turn missing metadata into a
false error. Use sqb lineage <model> --include-uses --format json to inspect direct
non-projection uses such as join_on, where, group_by, and window_order_by.
Related policies
Section titled “Related policies”The project default is implicit open-shape validation for models that omit contract. A repository can select explicit opt-in contracts with settings.column_contract_mode = "explicit" or configure a custom Rule that requires enforced contracts for selected model families.
Contracts also constrain schema-change behavior. For example, snapshot_schema_change append_new_columns is incompatible with contract enforced because an unannounced appended column would violate the exact declaration.