You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit af7308c
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: README.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -24,7 +24,7 @@ All state is persisted as append-only tables in the warehouse alongside your dat
24
24
-**Cursor-based incremental processing.** Automatic gap detection and resume, with microbatch mode for large ranges. No external checkpoint to maintain.
25
25
-**Ingestion and Python nodes.** Load external data with Python `@loader` functions, and run `@task`, `@asset`, and `@check` nodes as first-class members of the same DAG as your SQL models.
26
26
27
-
See the [documentation](https://docs.sqlbuild.com) for the full feature set, including providers, lifecycle hooks, Python macros, UDFs, custom materializations, data diffs, zero-copy cloning, and virtual environments. To coordinate dbt and SQLBuild projects, see the [dbt compatibility guide](https://docs.sqlbuild.com/concepts/dbt-compatibility/overview).
27
+
See the [documentation](https://docs.sqlbuild.com) for the full feature set, including providers, lifecycle hooks, Python macros, UDFs, custom materializations, data diffs, zero-copy cloning, and virtual environments. This repository also includes a focused guide to [model and raw-query diffs](docs/query-diffs.md). To coordinate dbt and SQLBuild projects, see the [dbt compatibility guide](https://docs.sqlbuild.com/concepts/dbt-compatibility/overview).
Copy file name to clipboardExpand all lines: src/sqlbuild/.agents/skills/sqlbuild/SKILL.md
+90-12Lines changed: 90 additions & 12 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7753,10 +7753,12 @@ Compare schemas and data between targets or virtual environments to validate cha
7753
7753
7754
7754
SQLBuild can compare schemas and row-level data between two build contexts. This lets you validate that changes produce the expected results before promoting them.
7755
7755
7756
-
`sqb diff FROM:TO` compares:
7756
+
`sqb diff` supports two input modes:
7757
7757
7758
-
- **two targets** (e.g. `prod:dev`) in direct mode, or
7759
-
- **two virtual environments** (VDEs) when [virtual environments](/concepts/virtual-environments) are enabled.
7758
+
- **model mode:** `sqb diff FROM:TO --select ...` compares two targets (for example `prod:dev`) in
7759
+
direct mode, or two virtual environments when virtual environments are enabled;
7760
+
- **raw-query mode:** inline SQL or SQL files identify the two sides and execute through the active
7761
+
target connection or an explicit `--target`.
7760
7762
7761
7763
The mechanics below are identical for both; only what `FROM` and `TO` refer to changes.
7762
7764
@@ -7770,9 +7772,30 @@ for that execution connection still fail before warehouse inspection.
Raw-query mode omits `FROM:TO` and requires repeated `--key` values or explicit `--unkeyed` for a
7776
+
row comparison. Inputs must each be one literal read-only `SELECT`, `WITH`, or `VALUES` expression;
7777
+
SQLBuild templates such as `ref()` are not expanded.
7778
+
7779
+
```bash
7780
+
sqb diff \
7781
+
--left-query 'SELECT order_id, amount_cents FROM analytics.orders_before' \
7782
+
--right-query 'SELECT order_id, amount_cents FROM analytics.orders_after' \
7783
+
--key order_id
7784
+
7785
+
sqb diff \
7786
+
--left-query-file queries/orders_before.sql \
7787
+
--right-query-file queries/orders_after.sql \
7788
+
--target dev \
7789
+
--key account_id \
7790
+
--key order_id
7791
+
```
7792
+
7793
+
Query mode defaults to a full comparison and also supports `--schema-only`. It does not accept
7794
+
`--bounded`; put the desired filter in both SQL inputs instead.
7795
+
7773
7796
### Comparison modes
7774
7797
7775
-
Every diff requires exactly one mode:
7798
+
Model mode requires exactly one mode. Raw-query mode defaults to full when no mode is supplied:
7776
7799
7777
7800
#### Full diff
7778
7801
@@ -7864,7 +7887,9 @@ side.
7864
7887
7865
7888
### Row matching
7866
7889
7867
-
Rows are matched between the two sides using the model's `unique_key`. Models without a `unique_key` can use schema-only diff but cannot run full or bounded row comparisons.
7890
+
Rows are matched using the model's `unique_key` or repeated invocation-level `--key` overrides.
7891
+
For inputs without stable row identity, `--unkeyed` performs an exhaustive exact multiset
7892
+
comparison in which duplicate rows retain their multiplicity. SQLBuild never guesses a key.
7868
7893
7869
7894
The diff output categorises rows as:
7870
7895
- **Equal** - same key, same values on both sides
@@ -7896,6 +7921,10 @@ Tolerance rules support:
7896
7921
7897
7922
Tolerances can be set per-column (`by_column`) or per-type (`by_type`).
7898
7923
7924
+
Use repeated `--tolerance COLUMN:absolute=VALUE` or `--tolerance COLUMN:relative=VALUE` arguments
7925
+
to override per-column rules for one model or raw-query invocation. Unkeyed comparison is exact and
7926
+
does not accept tolerances.
7927
+
7899
7928
### Excluded columns
7900
7929
7901
7930
Columns that are expected to differ between the two sides (like timestamps or context-specific values) can be excluded from the row comparison:
@@ -7910,6 +7939,29 @@ MODEL (
7910
7939
7911
7940
Excluded columns are still shown in the schema comparison but skipped during row-level diffing. A column cannot be in both `row_diff_exclude_columns` and `unique_key`.
7912
7941
7942
+
Use repeated `--exclude-column COLUMN` arguments for invocation-level exclusions.
7943
+
7944
+
### Raw-query artifacts and crash recovery
7945
+
7946
+
SQLBuild materializes each raw query once in the active target schema, compares the stable results,
7947
+
and drops both artifacts in a `finally` path. Every successfully created artifact appends an
7948
+
immutable `query_diff_artifact` fingerprint containing ownership and expiry metadata. Query
7949
+
execution and comparison never depend on historical fingerprints; they are ownership evidence for
7950
+
later cleanup, not workflow status.
7951
+
7952
+
Before a query diff, and independently through `sqb janitor`, SQLBuild removes an expired artifact
7953
+
only when its exact physical identity and reserved name match its fingerprint. A reserved-name
7954
+
relation without matching ownership evidence is reported and retained for manual investigation.
7955
+
Configure the crash-recovery TTL, which defaults to 24 hours, in `sqlbuild_project.toml`:
7956
+
7957
+
```toml
7958
+
[diff]
7959
+
query_artifact_ttl = "24h"
7960
+
```
7961
+
7962
+
Historical ownership inspection failures are warnings and do not prevent the current query pair
7963
+
from running. Current-run ownership publication and immediate cleanup remain mandatory.
7964
+
7913
7965
### Verbose output
7914
7966
7915
7967
Add `--verbose` or `-v` to see more example rows for mismatches and side-only rows:
@@ -7955,7 +8007,7 @@ observed schema for each model before starting its row comparison.
7955
8007
7956
8008
### Selectors
7957
8009
7958
-
Diff requires `--select` in the current version. You can use any selector syntax:
8010
+
Model diff requires `--select` in the current version. You can use any selector syntax:
`sqb diff` returns exit code `0` when all selected models have no differences, and `1` when any model has schema or row differences. This makes it usable in CI pipelines as a validation gate.
8025
+
`sqb diff` returns exit code `0` when no differences are found, and `1` when any input has schema or
8026
+
row differences or the comparison cannot execute successfully. This makes it usable in CI pipelines
8027
+
as a validation gate.
7974
8028
7975
8029
## Execution Observability
7976
8030
@@ -14448,23 +14502,30 @@ destination. Managed physical sources may bootstrap a destination that has not b
14448
14502
14449
14503
Source: `cli/diff.mdx`
14450
14504
14451
-
Compare schemas and data between targets or virtual environments.
14505
+
Compare schemas and data between targets, virtual environments, or two literal read-only queries.
14452
14506
14453
-
Compares schemas and optionally row-level data between two build contexts: two targets (e.g. `prod:dev`) in direct mode, or two virtual environments when virtual mode is enabled. See [Data Diffs](/concepts/diff) for detailed usage.
14507
+
Compares schemas and optionally row-level data between two build contexts, or materialized results
14508
+
from two literal read-only SQL inputs. See [Data Diffs](/concepts/diff) for detailed usage.
The first argument is a positional `FROM:TO` range. Exactly one mode is required: `--full`, `--schema-only`, or `--bounded <duration>`.
14518
+
Model mode uses a positional `FROM:TO` range and requires exactly one of `--full`, `--schema-only`,
14519
+
or `--bounded <duration>`. Raw-query mode does not accept `FROM:TO`; it defaults to full comparison,
14520
+
also supports `--schema-only`, and does not support `--bounded`.
14462
14521
14463
14522
In direct mode, `FROM` and `TO` are configured target names. Their database/schema namespaces remain
14464
14523
authoritative, while the `TO` target's named connection executes the complete comparison and must
14465
14524
be able to read both namespaces.
14466
14525
14467
-
Full and bounded row comparisons require the model to define `unique_key`. Bounded mode uses the model's cursor and falls back to a full row comparison when no cursor is configured.
14526
+
Full and bounded keyed comparisons use the model's `unique_key` unless repeated `--key` arguments
14527
+
override it. `--unkeyed` opts into exact multiset comparison. Bounded mode uses the model's cursor
14528
+
and falls back to a full row comparison when no cursor is configured.
14468
14529
14469
14530
### Flags
14470
14531
@@ -14482,6 +14543,15 @@ Full and bounded row comparisons require the model to define `unique_key`. Bound
14482
14543
| `--json-output` | Write structured comparison scope, coverage, and results to a JSON file |
14483
14544
| `--max-models` | Fail when the selected scope contains more models than this limit |
14484
14545
| `--max-columns` | Fail when either side of a model has more columns than this limit |
14546
+
| `--left-query` | Literal read-only SQL for the left side |
14547
+
| `--left-query-file` | UTF-8 SQL file for the left side |
14548
+
| `--right-query` | Literal read-only SQL for the right side |
14549
+
| `--right-query-file` | UTF-8 SQL file for the right side |
14550
+
| `--target` | Target connection for raw-query mode; defaults to the active target |
14551
+
| `--key` | Row identity column; repeat for a composite key or to override model configuration |
14552
+
| `--unkeyed` | Compare exact full-row multiplicities without a key |
14553
+
| `--exclude-column` | Column to omit from row comparison; repeat as needed |
14554
+
| `--tolerance` | Per-column numeric rule such as `amount:absolute=0.01`; repeat as needed |
14485
14555
| `--no-sql-analysis` | Disable compile-time SQL analysis (`--no-sql-validation` is an alias) |
14486
14556
| `--select`, `-s` | Select specific models to diff (required in v1) |
14487
14557
| `--exclude` | Exclude specific models from diffing |
0 commit comments