Repository navigation
Releases: sqlstack-io/sqlbuild
Release list
v0.187.3
v0.187.2
v0.187.1
v0.187.0
v0.186.2
v0.186.1
0.186.1 (2026-10-29)
Quoted columns in snapshots, microbatch cursors and merges
Following 0.186.0's support for quoted mixed-case columns, the remaining configuration checks now match them too:
- Snapshot keys, check columns and generated-column clashes, microbatch cursor columns, and merge immutable or excluded columns compare names the same way as contracts and incremental checks, so a quoted column such as
"listingId"is found. - On Snowflake, an unquoted configured name that only matches a case-sensitive column, such as
unique_key ['listingId']for a column created as"listingId", is now rejected with a message showing what to write ('"listingId"'). Previously it failed with a misleading "missing required columns" or "cursor not produced" error. Configurations that worked in 0.186.0 are unaffected; plain incremental merge and delete_insert keep accepting unquoted names. - The Snowflake adapter page has a new "Case-sensitive column names" section.
Internal
- Result and cost reporting moved behind the native boundary (#1272); no behaviour change.
Full change: #1273
v0.186.0
0.186.0 (2026-10-29)
Quoted mixed-case column names
Columns with quoted mixed-case names, such as "listingId", now work end to end on Snowflake and DuckDB: model headers, fixtures, contracts, planning, builds, runtime contract checks, type enforcement, incremental schema checks, loads, migrations and data diffs. A header may declare the column quoted or unquoted.
SQL is read with your adapter's lexical rules
Every scanner that finds references, macros and interpolations now follows the project adapter's rules for strings and comments: backslash escapes in Snowflake strings ('O\'Brien' no longer breaks local replay), E'…' and dollar-quoted strings on DuckDB and Postgres, raw and triple-quoted strings, and dialect line comments such as // and #.
sqb query
- No more "Project discovery" line. On a terminal, "Connecting to snowflake…" or "Running query…" appears only when that step takes longer than 300 ms; piped and JSON output contain only the result.
- The Snowflake adapter sets
SNOWFLAKE_DISABLE_PLATFORM_DETECTION=trueunless you have set it, which removes cloud-metadata probes and their warnings at connect time. The adapter page explains how to turn detection back on.
Fixes
- DuckDB
SET search_pathnow refreshes cached relation listings, and unqualified existence checks match schemas case-insensitively. - A build reuses the schema listings made while planning, refreshed after 60 seconds.
- The Python import hook looks in project paths first and handles changes of working directory.
- Three DuckShop core models are now deterministic.
- Requires
polyglot-sql-chio0.13.10, which fixes DuckDB lambda translation in local scenarios.
Behaviour change
- A
rule_ignoresentry whose exact path (without glob characters) does not exist now fails compilation, asrule_exceptionsalready did. Remove or correct stale entries.
Full change: #1270
v0.185.0
0.185.0 (2026-10-28)
DuckShop: an edge-case stress area
DuckShop, the example Snowflake project used for benchmarks, compiler goldens and translation tests, gains a separate edge-case area. It is the start of making DuckShop an all-round stress test.
- 38 models, 61 unit tests and 4 scenarios under
models/*/edge_cases/, with their own raw sources and loader, exercising values and shapes that isolated tests miss:- large integers and 38-digit decimals, FLOAT and NUMBER ties;
- extreme, pre-1970 and DST-boundary timestamps;
- JSON null versus missing keys, duplicate and case-differing keys;
- NULL ordering, LIKE escapes,
UNION ... BY NAME,OBJECT_INSERT,OBJECT_DELETE,OBJECT_CONSTRUCT_KEEP_NULL,TRY_TO_TIMESTAMP_NTZand more.
- Every hazard has fixture rows that a unit test or scenario reads, and expected results are captured from Snowflake under a pinned session profile with a committed capture script.
- A custom Rule requires every model in an
edge_casesfolder to carry theedge_casetag, and only those. - Benchmarks are unaffected: a core-only copy compiles to the same files as before, guarded by a checksum. DuckShop 10K is unchanged.
- The
QUOTED_IDENTIFIERS_IGNORE_CASEworkaround is removed from DuckShop's session settings; rebuild into a clean schema after upgrading.
Full change: dd0084a
v0.184.1
0.184.1 (2026-10-28)
Snowflake: fewer statements per model
Builds issue about a quarter to a third fewer statements, most of them housekeeping that queued for a warehouse behind model work.
- Models are replaced with
CREATE OR REPLACEand no pre-drop. Staging and delta tables are dropped only as the table kind SQLBuild created, and a microbatch delta is kept and replaced between batches. - Relation and retention lookups are answered from one
SHOW TABLES/SHOW VIEWSlisting per schema per run, which needs no warehouse, instead of oneinformation_schemaquery per table. The run's own DDL invalidates the listing. Session-only statements such asALTER SESSION SET QUERY_TAGandUSE WAREHOUSEkeep it. - If another session changes the destination just before promotion, promotion reads it again.
- The fingerprint table is set up once per build. A model whose identity hasn't changed writes no fingerprint row; rows stay append-only. Projects with model migration history keep writing every row.
COUNT(*)runs only when a statement reports no row count, and staging columns are read only for models with an enforced contract.- Scenario runs list their namespace once by prefix and reuse cleanup results.
Columns read for the schema-change check, and one information_schema read per build for source freshness, are kept.
Compile
- A compile whose Rules fail writes every model's SQL to
target/compiled-failed/, laid out liketarget/compiled/, with a not-buildable header on failing models, and leavestarget/compiled/as the last passing compile left it. The next passing compile removes the folder. The text report lists each failing model's SQL path; in--json,artifacts.compiled_sql_dirpoints at the failed folder andfailed_model_sqllists the files. target/compiled-models.txtfrom 0.184.0 is no longer written.- The compile after a Rules-failed compile runs in full rather than as a delta.
- A Rules-failed compile with
--manifestno longer reports writing a manifest; JSONartifacts.manifestisnull.
Fixes
- Concurrent models no longer set up the fingerprint table more than once on a first build.
Full change: 8d75270
v0.184.0
0.184.0 (2026-10-28)
⚠ BREAKING CHANGES
--format csvand--format tableare removed fromsqb query,sqb recall queryandsqb recall schema. They fail with a message naming the replacement: use the default output,--format longfor one record per row, or--jsonfor programs.
Query output
sqb queryandsqb recall queryshare one renderer. It prints a table with each column's warehouse type when the result fits the terminal (120 characters when redirected), and one record per row otherwise, so no column or value is cut. The footer says how to see more rows and, above 50 rows, suggests aggregating or limiting the query.- An adapter that reports no type for a column leaves the type cell empty.
Recall
- SIGTERM cancels running warehouse statements and stops in well under a second. The run is recorded as
cancelled, with its real end time, the signal and exit code 143 (130 for Ctrl+C), and its start and end events are written exactly once. A second SIGTERM kills the process immediately. - Each invocation records its effective selection, including selections passed in a selector file.
- Failing audits keep their evidence rows in Recall.
recall.audit_evidencecontrols this:warn-and-error(default),error(rows for error outcomes only) oroff. Rows are capped byevidence_limit(20 by default, overridable per audit) and 64 KB, with a truncation flag.offanderroralso stop rows from being collected for the warehouse audit history. - Failed and cancelled statements keep their SQL.
- Cost-telemetry statements are marked, and the cost-attribution status is recorded, so query-history timeouts no longer appear as unexplained failed statements.
Compile and Rules
- When Rules fail, compile still writes each model's expanded SQL, with a not-buildable header on failing models, and removes a stale
target/manifest.json. Other artifacts stay as the last passing compile left them, and the compiled file of a model removed from the project is deleted. Compile keeps a record of the model files it wrote intarget/compiled-models.txt. - SQBRSQL028 judges each column of a SQL macro call's query as it is written: plain slot reads in macro bodies are consistent, a read through a relation passed to the macro fits either style, and a macro's bare output beside hand-qualified columns is rejected.
Fixes
sqb auditon preserve targets stores standalone audit history beside the models instead of in a literalpreserveschema.
Build
- Requires fensu 0.28.0.
Full change: db2f274