MODEL() header
Every model file starts with aMODEL() block that declares its materialization, configuration, and schema metadata:
Materialization types
view
Creates a database view. Rebuilt on every run.table
Creates a table viaCREATE TABLE AS. SQLBuild materializes into a staging table first, runs audits, then promotes to the target. Fully rebuilt each time.
incremental
Inserts or updates into an existing table using a cursor-based strategy. See Incremental for full configuration.snapshot
Maintains historical row versions with SCD Type 2 semantics. Supports timestamp-based and value-check-based change detection, historical source inputs, hard delete invalidation, and configurable full-refresh safety policies.custom
User-defined Python materialization function. Custom materializations get full access to the framework including adapter, schema change signals, query change detection, and audit hooks.@@@placeholder syntax for values substituted at runtime. These deferred placeholders are preserved through compilation and resolved by the materialization at execution time. The config block passes arbitrary key-value pairs to the Python materialize() function via ctx.config.
References
Models use typed reference calls that SQLBuild resolves to qualified warehouse relation names during compilation:__seed(), not __ref(). Using __ref() with a seed name raises a compile error with a helpful message pointing you to __seed().
See Functions for UDF and table function details.
DAG ordering
SQLBuild automatically discovers the dependency graph from reference calls, then executes models in topological order. Upstream models are always built before their downstream dependents.Schema declarations
Model metadata - description, columns, audits, and type information - lives directly in theMODEL() header. There is no separate schema.yml for models.
Column-level audits
Attach audits to individual columns inside thecolumns block. Simple audits like not_null and unique are listed by name. Parameterized audits like accepted_values pass arguments inline:
Model-level audits
Attach audits to the model itself for multi-column or expression-based checks:Type enforcement
Type enforcement is implicit. If any column in theMODEL() header declares a type, type enforcement is automatically enabled for that model:
type_enforcement: true explicitly.
Contracts
Contracts enforce that a model’s output matches its declared column schema exactly - column names, column count, and column types. Whencontract enforced is set, the declared columns become the authoritative output contract.
unique_key, cursor, updated_at, check_columns) are validated against the declared column names. If a referenced column is not in the contract, compilation fails.
Runtime - after materialization into the staging table, SQLBuild inspects the actual output columns and validates them against the contract before promotion:
- Missing declared columns fail with code
K010 - Extra undeclared columns fail with code
K011 - Type mismatches (e.g.
VARCHARwhereINTEGERwas declared) fail with codeK013
Contracts interact with schema change policies. For snapshot models,
snapshot_schema_change append_new_columns is incompatible with contract enforced because appending columns would violate the contract.
Audit run scope
Audits on incremental models can specifyrun_scope to control when they execute:
delta_and_final runs the audit against each delta batch before DML and again against the target after all batches complete. See Audits for details.
Hooks
Pre-hooks and post-hooks run before and after materialization. Each entry is either asql("...") hook that executes SQL, or a python("hook_name") hook that calls a Python function from the hooks/ directory.
SQL hooks
@macro()), project variables (@@name), environment variables (@@ENV:NAME), and context variables (@@CTX:). SQL is validated at compile time when SQL analysis is enabled.
Available context variables in hooks:
Python hooks
Python hooks call@hook-decorated functions discovered from the hooks/ directory:
Hook context
Python hooks receive aHookContext as their first parameter (named ctx, context, or hook_context):
Pre-hooks can return
ctx.skip(...) to skip the model’s materialization entirely. A soft skip skips only this model; a hard skip also blocks downstream models. Providers can also be injected directly as hook function parameters by name. See Providers.
Hook decorator
The@hook decorator accepts optional metadata:
Discovery rules
- Hook functions are discovered from
.pyfiles underhooks/recursively - Files named
__init__.pyor starting with_are skipped - Each function decorated with
@hookis registered by name - Hook names must be unique across all hook files
- Python hook references in MODEL() headers are validated at compile time: unknown names, unknown kwargs, and missing required parameters all raise compile errors
Validation
At compile time, SQLBuild validates everypython("hook_name") reference:
- The hook name must match a discovered
@hookfunction - Any keyword arguments passed in the MODEL() header must match parameters on the function signature
- If the function does not accept
**kwargs, unknown arguments raise a compile error
Config reference
Common config
Four knobs gate compile-time SQL validation, from broadest to narrowest:
settings.sql_analysis- master switch for all SQL-analysis features--no-sql-validation- per-run CLI kill switchsettings.sql_validation- project-level validation settingMODEL (sql_validation ...)- per-model override of the project setting
sql_analysis must be on and --no-sql-validation absent before the project/model sql_validation values are consulted.
Incremental config
See Incremental for detailed usage.

