qubu 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -0
- package/dist/{complete-DP7pliuY.mjs → canonical-B5_ouh-c.mjs} +466 -241
- package/dist/codegen.d.mts +2 -2
- package/dist/codegen.mjs +180 -90
- package/dist/column-Cyc2CMnG.mjs +116 -0
- package/dist/column-DDRvD7SF.mjs +721 -0
- package/dist/{constraints-YGyNPQ_z.mjs → constraints-CAmi18Uk.mjs} +8 -3
- package/dist/core.d.mts +3 -3
- package/dist/core.mjs +4 -5
- package/dist/diagnostics-I9vVtXkc.mjs +40 -0
- package/dist/diff.d.mts +9 -9
- package/dist/diff.mjs +152 -102
- package/dist/{explain-CkIK13L_.mjs → explain-BIqEmZha.mjs} +1 -1
- package/dist/expressions-_6JF_J77.mjs +130 -0
- package/dist/index-CaxrMD1A.d.mts +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +414 -77
- package/dist/introspection/mysql.d.mts +26 -0
- package/dist/introspection/mysql.mjs +1278 -0
- package/dist/introspection/postgres.d.mts +43 -0
- package/dist/introspection/postgres.mjs +1889 -0
- package/dist/introspection/sqlite.d.mts +15 -0
- package/dist/introspection/sqlite.mjs +1172 -0
- package/dist/introspection.d.mts +26 -87
- package/dist/introspection.mjs +3 -4351
- package/dist/mysql.d.mts +3 -3
- package/dist/mysql.mjs +8 -7
- package/dist/{errors-Dxv73YJu.mjs → omit-VEr9Ydux.mjs} +5 -1
- package/dist/{on-conflict-DZQ85f1t.mjs → on-conflict-B2rFyHGF.mjs} +78 -8
- package/dist/on-duplicate-key-update-Czsw1Yq-.mjs +95 -0
- package/dist/postgres-hFhd0I9n.mjs +68 -0
- package/dist/postgres.d.mts +3 -3
- package/dist/postgres.mjs +3 -52
- package/dist/registry-BXE_4M9P.mjs +127 -0
- package/dist/{relational-CxnLCqZQ.mjs → relational-CoPBETjI.mjs} +3 -3
- package/dist/schema.d.mts +2 -2
- package/dist/schema.mjs +8 -7
- package/dist/{serialize-BN07IK0v.mjs → serialize-CyobNEx-.mjs} +174 -30
- package/dist/serialize-Du2UPZMt.d.mts +92 -0
- package/dist/snapshot/mysql.d.mts +5 -5
- package/dist/snapshot/mysql.mjs +32 -32
- package/dist/snapshot/postgres.d.mts +5 -5
- package/dist/snapshot/postgres.mjs +25 -25
- package/dist/snapshot/sqlite.d.mts +5 -5
- package/dist/snapshot/sqlite.mjs +30 -30
- package/dist/snapshot-mIb-Zzb5.mjs +1489 -0
- package/dist/snapshot.d.mts +4 -5
- package/dist/snapshot.mjs +3 -4
- package/dist/{source-SqrKWjFJ.mjs → source-DYSUqzvb.mjs} +2 -2
- package/dist/sqlite.d.mts +2 -2
- package/dist/sqlite.mjs +10 -10
- package/dist/{table-BwflqeAj.mjs → table-B8zEq0az.mjs} +4 -4
- package/dist/{types-BIJsj2fJ.mjs → types-CYHpSPwj.mjs} +10 -7
- package/dist/{types-CTCqtFlS.d.mts → types-CiMvKi5V.d.mts} +14 -4
- package/dist/{types-C0VkiwpR.d.mts → types-Dqr4o2I1.d.mts} +640 -189
- package/dist/value-CpaUFtjw.mjs +45 -0
- package/dist/vite/ambient.d.ts +2 -0
- package/dist/vite.d.mts +1 -1
- package/dist/vite.mjs +2 -0
- package/docs/dialects-and-execution.md +61 -11
- package/docs/getting-started.md +1 -1
- package/docs/guides/compose-queries.md +22 -0
- package/docs/guides/drizzle.md +11 -11
- package/docs/guides/extensions/typed-expressions.md +5 -3
- package/docs/guides/json.md +95 -2
- package/docs/guides/mutations.md +125 -0
- package/docs/guides/valtio-sync.md +113 -0
- package/docs/index.md +1 -1
- package/docs/migrations/adapters.md +58 -21
- package/docs/migrations/index.md +50 -12
- package/docs/migrations/operations.md +20 -6
- package/docs/migrations/recovery.md +7 -1
- package/docs/query-model/fragments.md +21 -1
- package/docs/reference/introspection-support.md +16 -18
- package/docs/reference/supported-surface.md +23 -11
- package/docs/schema/catalog-model.md +20 -7
- package/docs/schema/code-generation.md +4 -3
- package/docs/schema/diff.md +2 -2
- package/docs/schema/introspection.md +24 -16
- package/docs/schema/snapshots.md +18 -8
- package/docs/schema/storage-and-schema-sql.md +7 -2
- package/docs/sql-semantic-types.md +8 -0
- package/package.json +14 -1
- package/dist/canonical-DMvR9yBe.mjs +0 -972
- package/dist/column-Da37jYSD.mjs +0 -309
- package/dist/column-r1Y4ivwt.mjs +0 -327
- package/dist/complete-types-CY0KbzNw.d.mts +0 -371
- package/dist/index-B2rZf3-2.d.mts +0 -32
- package/dist/json-Db7XRD91.mjs +0 -169
- package/dist/omit-OxV58AwX.mjs +0 -5
- package/dist/registry-BRcUuazJ.mjs +0 -256
- package/dist/serialize-CEIIlWhC.d.mts +0 -66
- package/dist/snapshot-Xam8-q0j.mjs +0 -392
- package/dist/standard-DfcZEVOj.mjs +0 -12
- package/dist/value-D14I_XgL.mjs +0 -29
package/docs/index.md
CHANGED
|
@@ -33,7 +33,7 @@ define a table, build a `SELECT`, and inspect its SQL and parameters.
|
|
|
33
33
|
derivation and a native transactional database adapter.
|
|
34
34
|
- [Extend Qubu](guides/extensions/overview.md) with a custom source, clause,
|
|
35
35
|
dialect policy, or typed expression.
|
|
36
|
-
- [
|
|
36
|
+
- [Query nested JSON](guides/json.md) or read scalars from structured paths.
|
|
37
37
|
- [Enable the Vite compiler hint](guides/vite-plugin.md) when query modules
|
|
38
38
|
should opt into named imports through a directive.
|
|
39
39
|
- [Inspect an existing database](schema/introspection.md) through the optional
|
|
@@ -2,38 +2,47 @@
|
|
|
2
2
|
|
|
3
3
|
> Select a migration adapter from capabilities proven by its driver and environment, not from dialect name alone.
|
|
4
4
|
|
|
5
|
-
Every executable migration adapter opens
|
|
5
|
+
Every executable migration adapter opens a migration session and
|
|
6
6
|
advertises the exact behavior the executor may use:
|
|
7
7
|
|
|
8
|
-
| Field | Contract
|
|
9
|
-
| -------------------------------------- |
|
|
10
|
-
| `dialect`, `serverVersion` | Physical target and optional version used for compatibility checks
|
|
11
|
-
| `session` |
|
|
12
|
-
| `transactionalDdl` | Whether DDL effects can roll back
|
|
13
|
-
| `optionalTransactions`, `transactions` | Whether optional phases join a transaction and which requirements are proven
|
|
14
|
-
| `lease`, `leaseKind` | Database-backed exclusion of another migration runner
|
|
15
|
-
| `locks` | Independently supported program DDL lock requirements
|
|
16
|
-
| `journal` | Database storage, head compare-and-swap, and atomic applied-record/head advancement
|
|
17
|
-
| `parameters` | Supported tagged parameter kinds
|
|
18
|
-
| `commitAmbiguity` | Ambiguous commit becomes `recovery-required`
|
|
19
|
-
| `forbiddenPhases` | Checkpointed support or explicit rejection
|
|
20
|
-
| `features` | Named constraints an artifact may require
|
|
8
|
+
| Field | Contract |
|
|
9
|
+
| -------------------------------------- | -------------------------------------------------------------------------------------- |
|
|
10
|
+
| `dialect`, `serverVersion` | Physical target and optional version used for compatibility checks |
|
|
11
|
+
| `session` | `pinned` for the full lifecycle, or `atomic-batch` for one complete artifact per batch |
|
|
12
|
+
| `transactionalDdl` | Whether DDL effects can roll back |
|
|
13
|
+
| `optionalTransactions`, `transactions` | Whether optional phases join a transaction and which requirements are proven |
|
|
14
|
+
| `lease`, `leaseKind` | Database-backed exclusion of another migration runner |
|
|
15
|
+
| `locks` | Independently supported program DDL lock requirements |
|
|
16
|
+
| `journal` | Database storage, head compare-and-swap, and atomic applied-record/head advancement |
|
|
17
|
+
| `parameters` | Supported tagged parameter kinds |
|
|
18
|
+
| `commitAmbiguity` | Ambiguous commit becomes `recovery-required` |
|
|
19
|
+
| `forbiddenPhases` | Checkpointed support or explicit rejection |
|
|
20
|
+
| `features` | Named constraints an artifact may require |
|
|
21
21
|
|
|
22
22
|
The migrator lease and a program's DDL lock are different controls. The lease
|
|
23
23
|
excludes another Qubu runner; a DDL lock protects the database operation. The
|
|
24
24
|
executor never treats one as proof of the other.
|
|
25
25
|
|
|
26
|
+
## Trusted migration SQL
|
|
27
|
+
|
|
28
|
+
Migration SQL, including SQL conditions, is trusted across all adapters. Qubu
|
|
29
|
+
validates program structure and adapter capabilities, but does not parse SQL
|
|
30
|
+
to enforce safety. Callers must preserve executor-owned transactions, connection
|
|
31
|
+
settings, and migration journal state. For example, an explicit `COMMIT` can
|
|
32
|
+
leave schema changes applied without their journal record; atomicity and recovery
|
|
33
|
+
guarantees depend on respecting this contract.
|
|
34
|
+
|
|
26
35
|
## Current profiles
|
|
27
36
|
|
|
28
37
|
The following stable profiles have live conformance coverage in this checkout:
|
|
29
38
|
|
|
30
|
-
| Migration entrypoint | Dialect | Transactions | Locks | Forbidden phases | Notes
|
|
31
|
-
| ------------------------------------- | ---------- | ----------------------------- | --------------- | ---------------- |
|
|
32
|
-
| `@qubu/adapter-libsql/migration` | SQLite | required, optional | none, exclusive | unsupported |
|
|
33
|
-
| `@qubu/adapter-node-sqlite/migration` | SQLite | required, optional | none, exclusive | unsupported | Pinned application-owned `DatabaseSync`
|
|
34
|
-
| `@qubu/adapter-pg/migration` | PostgreSQL | required, optional, forbidden | none, exclusive | checkpointed | Caller supplies an already-pinned client
|
|
35
|
-
| `@qubu/adapter-postgresjs/migration` | PostgreSQL | required, optional, forbidden | none, exclusive | checkpointed | Reserves and releases one connection
|
|
36
|
-
| `@qubu/adapter-pglite/migration` | PostgreSQL | required, optional, forbidden | none, exclusive | checkpointed | Uses the database query queue as the pinned session
|
|
39
|
+
| Migration entrypoint | Dialect | Transactions | Locks | Forbidden phases | Notes |
|
|
40
|
+
| ------------------------------------- | ---------- | ----------------------------- | --------------- | ---------------- | ------------------------------------------------------ |
|
|
41
|
+
| `@qubu/adapter-libsql/migration` | SQLite | required, optional | none, exclusive | unsupported | Single-phase atomic batches through `client.migrate()` |
|
|
42
|
+
| `@qubu/adapter-node-sqlite/migration` | SQLite | required, optional | none, exclusive | unsupported | Pinned application-owned `DatabaseSync` |
|
|
43
|
+
| `@qubu/adapter-pg/migration` | PostgreSQL | required, optional, forbidden | none, exclusive | checkpointed | Caller supplies an already-pinned client |
|
|
44
|
+
| `@qubu/adapter-postgresjs/migration` | PostgreSQL | required, optional, forbidden | none, exclusive | checkpointed | Reserves and releases one connection |
|
|
45
|
+
| `@qubu/adapter-pglite/migration` | PostgreSQL | required, optional, forbidden | none, exclusive | checkpointed | Uses the database query queue as the pinned session |
|
|
37
46
|
|
|
38
47
|
All five support every current tagged parameter kind (`null`, `boolean`,
|
|
39
48
|
`string`, `number`, `bigint`, `bytes`, and `json`), a database journal and
|
|
@@ -68,3 +77,31 @@ const adapter = libsqlMigrationAdapter(client, {
|
|
|
68
77
|
|
|
69
78
|
`DATABASE_URL` remains application configuration; neither the adapter nor CLI
|
|
70
79
|
assigns deployment-provider meaning to it.
|
|
80
|
+
|
|
81
|
+
## libSQL batch execution
|
|
82
|
+
|
|
83
|
+
Each executable artifact must contain exactly one phase and an embedded before
|
|
84
|
+
snapshot. The adapter submits its statements, SQL assertions, applied-history
|
|
85
|
+
record, head update, and terminal attempt state in one `client.migrate()` call.
|
|
86
|
+
For example, creating a table and recording that migration either both commit
|
|
87
|
+
or both roll back. Multiple artifacts are separate batches; earlier successful
|
|
88
|
+
artifacts remain applied if a later one fails.
|
|
89
|
+
|
|
90
|
+
Preparation reads the schema in a read transaction. The submitted batch checks
|
|
91
|
+
that the catalog still matches that inspection, the lease is still owned, and
|
|
92
|
+
the head still equals the expected parent. Foreign-key validation runs before
|
|
93
|
+
commit because libSQL temporarily disables enforcement during `migrate()`.
|
|
94
|
+
|
|
95
|
+
Schema fingerprint and property preconditions are checked against the embedded
|
|
96
|
+
before snapshot, whose physical facts are verified during preparation and
|
|
97
|
+
guarded by the in-batch catalog assertion. Object-presence and scalar SQL checks
|
|
98
|
+
run inside the batch. Postconditions must be object-presence/absence checks
|
|
99
|
+
without fingerprints, or scalar SQL checks returning `1`. Unsupported conditions
|
|
100
|
+
and multiple phases are rejected. SQL content is passed to the driver without
|
|
101
|
+
safety validation; each program entry must follow the driver's statement contract.
|
|
102
|
+
|
|
103
|
+
The database-row lease has no expiry or heartbeat. A process crash can leave
|
|
104
|
+
it held; ownership must be resolved before another runner can proceed. A lost
|
|
105
|
+
batch response is an uncertain outcome requiring journal inspection and, when
|
|
106
|
+
the attempt remains unresolved, explicit recovery. It is never assumed to be
|
|
107
|
+
a successful rollback.
|
package/docs/migrations/index.md
CHANGED
|
@@ -25,18 +25,26 @@ The `@qubu/migrate` root intentionally exports only format/version constants
|
|
|
25
25
|
and the central plan and artifact types. Import behavior from its focused
|
|
26
26
|
entrypoint:
|
|
27
27
|
|
|
28
|
-
| Entrypoint
|
|
29
|
-
|
|
|
30
|
-
| `@qubu/migrate/plan`
|
|
31
|
-
| `@qubu/migrate/ddl`
|
|
32
|
-
| `@qubu/migrate/
|
|
33
|
-
| `@qubu/migrate/
|
|
34
|
-
| `@qubu/migrate/
|
|
35
|
-
| `@qubu/migrate/
|
|
36
|
-
| `@qubu/migrate/
|
|
37
|
-
| `@qubu/migrate/
|
|
38
|
-
| `@qubu/migrate/
|
|
39
|
-
| `@qubu/migrate/
|
|
28
|
+
| Entrypoint | Use it for |
|
|
29
|
+
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
|
30
|
+
| `@qubu/migrate/plan` | Create, encode, decode, fingerprint, and validate migration plans |
|
|
31
|
+
| `@qubu/migrate/ddl` | Preview deterministic dialect SQL without opening a database |
|
|
32
|
+
| `@qubu/migrate/ddl/postgres` | Preview PostgreSQL SQL from an approved migration plan |
|
|
33
|
+
| `@qubu/migrate/ddl/sqlite` | Preview SQLite SQL from an approved migration plan |
|
|
34
|
+
| `@qubu/migrate/ddl/mysql` | Preview MySQL SQL from an approved migration plan |
|
|
35
|
+
| `@qubu/migrate/artifact` | Compile programs with a caller-supplied `SchemaDialect`; canonicalize, digest, seal, encode, and decode artifacts |
|
|
36
|
+
| `@qubu/migrate/artifact/postgres` | Compile reviewed plans with PostgreSQL's schema dialect |
|
|
37
|
+
| `@qubu/migrate/artifact/sqlite` | Compile reviewed plans with SQLite's schema dialect, including table rebuilds |
|
|
38
|
+
| `@qubu/migrate/artifact/mysql` | Compile reviewed plans with MySQL's schema dialect |
|
|
39
|
+
| `@qubu/migrate/repository` | Verify a complete artifact chain and its journal prefix |
|
|
40
|
+
| `@qubu/migrate/journal` | Implement or inspect the storage-neutral journal contract |
|
|
41
|
+
| `@qubu/migrate/executor` | Apply artifacts and reconcile uncertain attempts |
|
|
42
|
+
| `@qubu/migrate/baseline` | Verify and record the initial non-executable baseline |
|
|
43
|
+
| `@qubu/migrate/status` | Inspect pending work, drift, requirements, and interrupted attempts |
|
|
44
|
+
| `@qubu/migrate/bootstrap` | Prepare a fresh schema diff and expose shared bootstrap types; accepts a caller-supplied `SchemaDialect` for generic planning |
|
|
45
|
+
| `@qubu/migrate/bootstrap/postgres` | Plan a fresh PostgreSQL schema through the normal compiler |
|
|
46
|
+
| `@qubu/migrate/bootstrap/sqlite` | Plan a fresh SQLite schema through the normal compiler |
|
|
47
|
+
| `@qubu/migrate/testing` | Test adapter capabilities and deterministic failure boundaries |
|
|
40
48
|
|
|
41
49
|
Start with [Artifacts and approval policy](artifacts-and-policy.md) when
|
|
42
50
|
reviewing a migration format. Check [Adapter capability
|
|
@@ -44,3 +52,33 @@ profiles](adapters.md), use [Command line operations](operations.md) to
|
|
|
44
52
|
configure an application, then keep [Recovery and reconciliation](recovery.md)
|
|
45
53
|
with the deployment runbook. [Lotta Games adoption](lotta-adoption.md) records
|
|
46
54
|
the downstream cutover boundary and current combo-matrix blocker.
|
|
55
|
+
|
|
56
|
+
Choose the dialect-specific bootstrap entrypoint when using a built-in dialect:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { planSchemaBootstrap } from "@qubu/migrate/bootstrap/postgres"
|
|
60
|
+
|
|
61
|
+
const result = planSchemaBootstrap(targetSnapshot)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The neutral `@qubu/migrate/bootstrap` entrypoint contains the shared preparation
|
|
65
|
+
logic and generic planner. The PostgreSQL and SQLite entrypoints each import
|
|
66
|
+
only their matching schema dialect.
|
|
67
|
+
|
|
68
|
+
Use the same entrypoint pattern for convenience artifact compilers:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { compileMigrationProgram } from "@qubu/migrate/artifact/postgres"
|
|
72
|
+
|
|
73
|
+
const compiled = compileMigrationProgram(plan)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The DDL entrypoints follow the same pattern. Use the neutral entrypoint when
|
|
77
|
+
the application supplies a `SchemaDialect`; use a dialect subpath when the
|
|
78
|
+
built-in dialect should be selected by the module:
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
import { emitMigrationPlan } from "@qubu/migrate/ddl/postgres"
|
|
82
|
+
|
|
83
|
+
const preview = emitMigrationPlan(plan)
|
|
84
|
+
```
|
|
@@ -70,7 +70,7 @@ working directory.
|
|
|
70
70
|
| `qubu migrate apply [--dry-run]` | Applies the complete verified pending chain; dry-run performs status/preflight only | It never limits discovery to Git-added or branch-diff files |
|
|
71
71
|
| `qubu migrate baseline <id> --confirm <fact>... [--dry-run]` | Without dry-run, strictly compares the live managed schema, initializes an empty journal, records baseline, then writes the artifact | Requires an empty artifact repository and all seven exact confirmations; dry-run does not inspect the database |
|
|
72
72
|
| `qubu migrate reconcile <attempt-id> --outcome applied\|rolled_back --reason <text>` | Runs application-owned verification, then records the explicit outcome | Requires `verifyReconciliation` in config; no automatic inference |
|
|
73
|
-
| `qubu schema bootstrap [--approve <operation-id=reason>...] [--dry-run]` | Plans an empty SQLite snapshot through diff/plan/program; executes through the normal executor unless dry-run
|
|
73
|
+
| `qubu schema bootstrap [--approve <operation-id=reason>...] [--dry-run]` | Plans an empty SQLite or PostgreSQL snapshot through diff/plan/program; executes through the normal executor unless dry-run | Rejects other dialects; unsafe or incomplete facts still require exact approvals or custom programs |
|
|
74
74
|
|
|
75
75
|
JSON output is stable, newline-terminated, recursively key-sorted, and redacts
|
|
76
76
|
credential-like keys and credentials or secrets embedded in URLs. Human output
|
|
@@ -94,11 +94,25 @@ snapshot. Logical IDs help reporting but do not prove equality. Objects not
|
|
|
94
94
|
owned by the managed snapshot are returned separately as `unmanagedObjects`;
|
|
95
95
|
Qubu journal objects are excluded by migration snapshot readers.
|
|
96
96
|
|
|
97
|
-
`schema bootstrap` is for a fresh SQLite database
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
97
|
+
`schema bootstrap` is for a fresh SQLite database or a fresh PostgreSQL schema.
|
|
98
|
+
It produces the same reviewed plan, versioned program, sealed artifact, and
|
|
99
|
+
executor path as a migration. A complete PostgreSQL snapshot retains standalone
|
|
100
|
+
enums as authoritative objects; bootstrap creates each enum before a table that
|
|
101
|
+
uses it as a native column type. SQLite inline constraints are compiled into
|
|
102
|
+
table creation, while table rebuilds are explicit phases with copy/postcondition
|
|
103
|
+
checks. Session settings such as SQLite PRAGMAs remain in the application or
|
|
104
|
+
adapter setup.
|
|
105
|
+
|
|
106
|
+
Use the reviewed complete snapshot directly as the PostgreSQL target:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
qubu schema bootstrap --dry-run --format json --non-interactive
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The dry run prints the ordered phases without opening the adapter. Remove
|
|
113
|
+
`--dry-run` only after reviewing any operation IDs that require `--approve` or
|
|
114
|
+
an application-owned custom program. Bootstrap does not import or replay
|
|
115
|
+
Drizzle migration history.
|
|
102
116
|
|
|
103
117
|
## Baseline and cutover checklist
|
|
104
118
|
|
|
@@ -46,13 +46,19 @@ head, or a non-prefix repository fail before any statement executes.
|
|
|
46
46
|
## Execution and concurrency guarantees
|
|
47
47
|
|
|
48
48
|
For each invocation, the executor verifies the entire repository, opens one
|
|
49
|
-
|
|
49
|
+
migration session, checks capabilities, acquires the migrator lease, validates the
|
|
50
50
|
journal and repository prefix, checks the live before-snapshot digest, then
|
|
51
51
|
applies each pending artifact. Within an artifact it creates an attempt,
|
|
52
52
|
executes ordered phases with preconditions and postconditions, writes durable
|
|
53
53
|
checkpoints, appends immutable history, and compare-and-swaps the head.
|
|
54
54
|
Resources are released in reverse order: DDL lock, migrator lease, then session.
|
|
55
55
|
|
|
56
|
+
An `atomic-batch` profile instead applies one single-phase artifact in one
|
|
57
|
+
database transaction, including its checks and terminal journal writes. It
|
|
58
|
+
records a completed phase checkpoint rather than intermediate statement
|
|
59
|
+
checkpoints. See [libSQL batch execution](./adapters.md#libsql-batch-execution)
|
|
60
|
+
for its supported conditions and concurrency guards.
|
|
61
|
+
|
|
56
62
|
A second runner cannot rely on the lease alone. Atomic applied-record/head
|
|
57
63
|
advancement uses the expected parent as a compare-and-swap guard. A runner that
|
|
58
64
|
observes the already-matching head exits idempotently; a conflicting head is a
|
|
@@ -51,7 +51,8 @@ producer, consumer, and regression test all exist.
|
|
|
51
51
|
## Parameters are runtime data
|
|
52
52
|
|
|
53
53
|
Parameter values are not fragment metadata. A renderer calls
|
|
54
|
-
`context.parameter(value)`, and `render()` collects values in placeholder order
|
|
54
|
+
`context.parameter(value)`, and `render()` collects values in placeholder order.
|
|
55
|
+
Pass a second argument when the adapter needs the runtime SQL domain too:
|
|
55
56
|
|
|
56
57
|
```ts
|
|
57
58
|
import { and, eq, from, integer, like, render, select, table, text, where } from "qubu"
|
|
@@ -72,6 +73,25 @@ render(query)
|
|
|
72
73
|
// parameters: [7, '%Ada%']
|
|
73
74
|
```
|
|
74
75
|
|
|
76
|
+
The optional domain metadata stays in a sidecar aligned with `parameters`:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
import { typedValue } from "qubu/core"
|
|
80
|
+
import type { SqlUuid } from "qubu"
|
|
81
|
+
|
|
82
|
+
const id = typedValue<SqlUuid, string>("108cb836-20d2-41b2-8c23-f0c94700aa7e", "uuid")
|
|
83
|
+
render(id)
|
|
84
|
+
// parameterSqlTypes: ["uuid"]
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The domain is a binding hint, not an instruction to convert the returned
|
|
88
|
+
JavaScript value. Result decoding comes from a field's `type` or an explicit
|
|
89
|
+
decoder.
|
|
90
|
+
|
|
91
|
+
Plain JavaScript values remain untyped at runtime. Use an explicit domain when
|
|
92
|
+
`Date` could mean either `DATE` or `TIMESTAMP`, or when a string is a UUID
|
|
93
|
+
rather than text.
|
|
94
|
+
|
|
75
95
|
The parameter array follows the placeholders in the rendered text. `select()`
|
|
76
96
|
normalizes independent clause values, but keep the final call in SQL order in
|
|
77
97
|
new code so source scope and repair hints are visible at a glance.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
The optional `qubu/introspection` entrypoint reads one selected database
|
|
6
6
|
namespace through a user-owned `CatalogConnection`. It returns normalized
|
|
7
|
-
catalog data and can map that data to canonical Snapshot v1
|
|
7
|
+
catalog data and can map that data to canonical Snapshot v1. The
|
|
8
8
|
application owns the driver and connection lifecycle. Snapshot diffing,
|
|
9
9
|
migration planning, and DDL emission are separate Qubu capabilities; see the
|
|
10
10
|
[ownership map](supported-surface.md#ownership-boundary).
|
|
@@ -46,7 +46,7 @@ SQL.
|
|
|
46
46
|
## PostgreSQL complete catalog surface
|
|
47
47
|
|
|
48
48
|
The PostgreSQL reader also fills the complete normalized catalog used by
|
|
49
|
-
Snapshot
|
|
49
|
+
Snapshot v1. It keeps PostgreSQL OIDs in current-run physical references and
|
|
50
50
|
keeps decompiler output such as `pg_get_viewdef`, `pg_get_triggerdef`, and
|
|
51
51
|
`pg_get_functiondef` as tagged SQL data. It does not evaluate that text.
|
|
52
52
|
|
|
@@ -55,9 +55,9 @@ The query and normalization layout follows the catalog-oriented parts of the
|
|
|
55
55
|
while Qubu keeps the result as typed data instead of generating TypeScript
|
|
56
56
|
declarations.
|
|
57
57
|
|
|
58
|
-
Use `
|
|
59
|
-
`
|
|
60
|
-
Snapshot v1.
|
|
58
|
+
Use `mapCatalogToSnapshot()` or its explicit
|
|
59
|
+
`mapCatalogToCompleteSnapshot()` alias for this object set. Both produce the
|
|
60
|
+
canonical Snapshot v1 shape.
|
|
61
61
|
|
|
62
62
|
## SQLite complete catalog surface
|
|
63
63
|
|
|
@@ -86,10 +86,9 @@ the selected namespace. SQLite does not provide the PostgreSQL object families
|
|
|
86
86
|
such as routines, materialized views, policies, or ownership, so the reader
|
|
87
87
|
does not fabricate them.
|
|
88
88
|
|
|
89
|
-
`
|
|
90
|
-
objects, opaque boundaries, and dialect
|
|
91
|
-
|
|
92
|
-
behavior.
|
|
89
|
+
`mapCatalogToSnapshot()` delegates to `mapCatalogToCompleteSnapshot()` and
|
|
90
|
+
retains typed views, triggers, deferred objects, opaque boundaries, and dialect
|
|
91
|
+
extensions in Snapshot v1.
|
|
93
92
|
|
|
94
93
|
The query and normalization seams follow the catalog-reading portions of the
|
|
95
94
|
[Drizzle SQLite introspector](https://github.com/drizzle-team/drizzle-orm/blob/main/drizzle-kit/src/introspect-sqlite.ts).
|
|
@@ -110,13 +109,13 @@ MySQL has typed complete records for views, routines and their parameters,
|
|
|
110
109
|
triggers, partitions, collations used by selected tables or columns, and
|
|
111
110
|
comments. View definitions come from `INFORMATION_SCHEMA.VIEWS`; each view's
|
|
112
111
|
columns are joined back to the matching `COLUMNS` rows by physical table name,
|
|
113
|
-
so the complete Snapshot
|
|
112
|
+
so the complete Snapshot v1 cross-reference points at the view's own column
|
|
114
113
|
IDs. Missing view definitions or unresolved trigger, partition, or other
|
|
115
114
|
object references become deferred records with diagnostics.
|
|
116
115
|
|
|
117
116
|
Scheduled events are retained as `CatalogOpaqueObject` records. Their event
|
|
118
117
|
metadata and definition remain opaque, and the reader emits an
|
|
119
|
-
`unmodeled-object` warning. Snapshot
|
|
118
|
+
`unmodeled-object` warning. Snapshot v1 keeps these records in
|
|
120
119
|
`opaqueObjects`; they are not treated as typed routines, triggers, or
|
|
121
120
|
migration operations.
|
|
122
121
|
|
|
@@ -132,13 +131,12 @@ The query and normalization layout follows the catalog-reading portions of the
|
|
|
132
131
|
while Qubu keeps the result as typed data instead of generating TypeScript
|
|
133
132
|
declarations.
|
|
134
133
|
|
|
135
|
-
Use `mapCatalogToCompleteSnapshot()` to retain these
|
|
136
|
-
the opaque or deferred boundaries in Snapshot
|
|
137
|
-
when a caller explicitly needs the existing table-only Snapshot v1.
|
|
134
|
+
Use `mapCatalogToSnapshot()` or `mapCatalogToCompleteSnapshot()` to retain these
|
|
135
|
+
typed MySQL families and the opaque or deferred boundaries in Snapshot v1.
|
|
138
136
|
|
|
139
137
|
## Snapshot v1 surface
|
|
140
138
|
|
|
141
|
-
The mapper
|
|
139
|
+
The mapper emits these facts in canonical Snapshot v1:
|
|
142
140
|
|
|
143
141
|
- one namespace and ordinary tables;
|
|
144
142
|
- exact dialect-native column storage;
|
|
@@ -162,14 +160,14 @@ Snapshot v1 objects:
|
|
|
162
160
|
- views and materialized views;
|
|
163
161
|
- sequences, enums, domains, routines, triggers, policies, extensions,
|
|
164
162
|
collations, comments, and partition metadata;
|
|
165
|
-
- PostgreSQL identity sequence options that have no typed
|
|
163
|
+
- PostgreSQL identity sequence options that have no typed field;
|
|
166
164
|
- SQLite virtual/shadow tables, attached namespaces, and unrecoverable
|
|
167
165
|
generated or expression definitions;
|
|
168
166
|
- MySQL/MariaDB differences, prefix indexes, invisible indexes, and advanced
|
|
169
167
|
functional, full-text, or spatial index semantics.
|
|
170
168
|
|
|
171
|
-
Use the
|
|
172
|
-
|
|
169
|
+
Use the Snapshot v1 mapper to retain supported PostgreSQL and MySQL families.
|
|
170
|
+
MySQL scheduled events stay opaque, and MySQL sequences,
|
|
173
171
|
materialized views, row-level security (RLS) policies, extension objects, and
|
|
174
172
|
ownership stay unsupported or deferred. When a row cannot be normalized safely, the reader
|
|
175
173
|
keeps a typed deferred or opaque record and emits a diagnostic instead of
|
|
@@ -9,12 +9,15 @@
|
|
|
9
9
|
| `qubu` | Runtime | Ordinary query and schema definitions, reads, writes, SQL templates, rendering, EXPLAIN, and execution contracts |
|
|
10
10
|
| `qubu/core` | Runtime | Fragment and rendering primitives, dialect construction, SQL types, and extension constructors |
|
|
11
11
|
| `qubu/codegen` | Runtime | Deterministic machine-owned TypeScript schemas from complete, non-lossy introspection |
|
|
12
|
-
| `qubu/diff` | Runtime | Canonical Snapshot v1
|
|
13
|
-
| `qubu/introspection` | Runtime |
|
|
12
|
+
| `qubu/diff` | Runtime | Canonical Snapshot v1 comparison, rename hints, suggestions, and safety diagnostics |
|
|
13
|
+
| `qubu/introspection` | Runtime | Shared catalog contracts, normalized catalog models, diagnostics, and mapping to Snapshot v1 |
|
|
14
|
+
| `qubu/introspection/postgres` | Runtime | PostgreSQL catalog reader and catalog queries for one selected namespace |
|
|
15
|
+
| `qubu/introspection/sqlite` | Runtime | SQLite catalog reader and catalog queries for one selected namespace |
|
|
16
|
+
| `qubu/introspection/mysql` | Runtime | MySQL catalog reader and catalog queries for one selected namespace |
|
|
14
17
|
| `qubu/mysql` | Runtime | The MySQL query dialect policy |
|
|
15
18
|
| `qubu/postgres` | Runtime | PostgreSQL query dialect helpers such as `postgresDialect()` and `ilike()` |
|
|
16
19
|
| `qubu/schema` | Runtime | Advanced schema metadata, storage and constraint models, source models, and schema-expression extensions |
|
|
17
|
-
| `qubu/snapshot` | Runtime | Canonical Snapshot v1
|
|
20
|
+
| `qubu/snapshot` | Runtime | Canonical Snapshot v1 traversal, encoding, decoding, diagnostics, and fingerprints |
|
|
18
21
|
| `qubu/snapshot/mysql` | Runtime | MySQL snapshot adapter, schema dialect, and convenience creators |
|
|
19
22
|
| `qubu/snapshot/postgres` | Runtime | PostgreSQL snapshot adapter, schema dialect, and convenience creators |
|
|
20
23
|
| `qubu/snapshot/sqlite` | Runtime | SQLite snapshot adapter, schema dialect, affinity helper, and convenience creators |
|
|
@@ -22,15 +25,24 @@
|
|
|
22
25
|
| `qubu/vite` | Runtime | The optional `qubu()` Vite compiler hint |
|
|
23
26
|
| `qubu/package.json` | JSON | The published package manifest |
|
|
24
27
|
| `@qubu/migrate` | Runtime | Migration compiler format identity and shared plan types |
|
|
28
|
+
| `@qubu/pgvector` | Runtime | PostgreSQL pgvector columns, dense-vector codecs, distance expressions, and HNSW/IVFFlat index metadata |
|
|
25
29
|
| `@qubu/migrate/plan` | Runtime | Pure migration planning with dependencies, decisions, preconditions, and explicit custom SQL |
|
|
26
|
-
| `@qubu/migrate/ddl` | Runtime | DDL preflight and
|
|
27
|
-
| `@qubu/migrate/
|
|
30
|
+
| `@qubu/migrate/ddl` | Runtime | DDL preflight and generic emission from a migration plan and supplied schema dialect |
|
|
31
|
+
| `@qubu/migrate/ddl/postgres` | Runtime | PostgreSQL DDL emission from an approved migration plan |
|
|
32
|
+
| `@qubu/migrate/ddl/sqlite` | Runtime | SQLite DDL emission from an approved migration plan |
|
|
33
|
+
| `@qubu/migrate/ddl/mysql` | Runtime | MySQL DDL emission from an approved migration plan |
|
|
34
|
+
| `@qubu/migrate/artifact` | Runtime | Generic versioned program compilation with a caller-supplied schema dialect, plus strict artifacts and baselines |
|
|
35
|
+
| `@qubu/migrate/artifact/postgres` | Runtime | PostgreSQL versioned program compilation |
|
|
36
|
+
| `@qubu/migrate/artifact/sqlite` | Runtime | SQLite versioned program compilation, including table rebuilds |
|
|
37
|
+
| `@qubu/migrate/artifact/mysql` | Runtime | MySQL versioned program compilation |
|
|
28
38
|
| `@qubu/migrate/repository` | Runtime | Strict full-chain and journal-prefix verification |
|
|
29
39
|
| `@qubu/migrate/journal` | Runtime | Storage-neutral journal records, transitions, validation, and reference storage |
|
|
30
40
|
| `@qubu/migrate/executor` | Runtime | Portable execution, structured errors, checkpointing, and explicit reconciliation |
|
|
31
41
|
| `@qubu/migrate/baseline` | Runtime | Strict live baseline verification and physical managed-schema comparison |
|
|
32
42
|
| `@qubu/migrate/status` | Runtime | Pending chain, managed drift, unmanaged objects, interrupted attempts, and incompatible requirements |
|
|
33
|
-
| `@qubu/migrate/bootstrap` | Runtime |
|
|
43
|
+
| `@qubu/migrate/bootstrap` | Runtime | Shared bootstrap preparation, result types, and generic planning with a caller-supplied schema dialect |
|
|
44
|
+
| `@qubu/migrate/bootstrap/postgres` | Runtime | Fresh PostgreSQL schema planning through the normal diff, plan, and program compiler |
|
|
45
|
+
| `@qubu/migrate/bootstrap/sqlite` | Runtime | Fresh SQLite schema planning through the normal diff, plan, and program compiler |
|
|
34
46
|
| `@qubu/migrate/testing` | Runtime | Deterministic fake adapters, fault boundaries, and adapter conformance checks |
|
|
35
47
|
| `@qubu/cli` | Runtime and CLI | `@alloc/cmd-ts` commands, typed config, filesystem repositories, stable output, and exit codes |
|
|
36
48
|
| `@qubu/drizzle` | Runtime | Shared Drizzle conversion errors and dialect types |
|
|
@@ -67,17 +79,17 @@ entrypoint table.
|
|
|
67
79
|
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
68
80
|
| Schema values | `table`, immutable `schema` registries with namespaces, portable and dialect-native column storage descriptors, canonical default and generated-column metadata, identity descriptors, named primary, candidate-key, nullable unique, foreign-key, and check constraints, physical object names, included-column indexes, typed dialect extensions, and typed column helpers |
|
|
69
81
|
| Read queries | Named projections, spreadable source columns, aliases, joins, typed custom and LATERAL `FROM` sources, correlated subqueries, `WHERE`, grouping with declared-key proofs, `HAVING`, ordering, window expressions, distinctness, pagination, row locking, ordinary and recursive CTEs, subqueries, and set operations |
|
|
70
|
-
| Expressions | Comparison, boolean, arithmetic, null, range, membership, aggregate, window, string, JSON scalar reads, definition-backed and raw casts, cases, parameterized SQL templates, custom expressions, and branded deterministic schema expressions
|
|
82
|
+
| Expressions | Comparison, boolean, arithmetic, null, range, membership, aggregate, window, string, JSON scalar reads and typed nested JSON query results, definition-backed and raw casts, cases, parameterized SQL templates, custom expressions, and branded deterministic schema expressions |
|
|
71
83
|
| SQL type metadata | Portable domains and capabilities, physical column storage descriptors, `SqlTypeOf`, projected SQL type maps, `SourceLike` and `TableLike` field constraints, contextual literals, typed extension values, calls, and casts, plus a permissive `SqlUnknown` fallback |
|
|
72
|
-
| Write queries | `INSERT` values, defaults, and selects; `UPDATE
|
|
84
|
+
| Write queries | `INSERT` values, defaults, and selects; typed `UPDATE`, PostgreSQL `UPDATE ... FROM`, and `DELETE`; typed assignments; PostgreSQL/SQLite conflict clauses; MySQL duplicate-key updates and incoming rows; `RETURNING` on supporting dialects; and explicit unrestricted-write opt-in |
|
|
73
85
|
| Rendering | Standard, PostgreSQL, SQLite, MySQL, and user-created policies for identifiers, placeholders, pagination, row locking, JSON, logical cast targets, schema literals, and EXPLAIN options |
|
|
74
86
|
| Execution boundary | `QueryAdapter`, opt-in `ExplainableQueryAdapter`, `StreamingQueryAdapter`, and `TransactionalQueryAdapter` capabilities, bound clients from `qubu()`, structured results from `execute()` or `db.execute()`, row-only results from `executeRows()` or `db.rows()`, typed read streams from `stream()` or `db.stream()`, and adapter-decoded plan rows from `explain()` or `db.explain()` |
|
|
75
|
-
| Snapshots | Pure Snapshot v1
|
|
87
|
+
| Snapshots | Pure Snapshot v1 creation, canonical encoding and strict decoding, immutable data, diagnostics, and FNV change-detection fingerprints |
|
|
76
88
|
| Introspection | PostgreSQL, SQLite, and MySQL catalog readers for one selected namespace, normalized catalog data, structured diagnostics, and strict or explicit lossy snapshot mapping |
|
|
77
|
-
| Snapshot diffing | Pure Snapshot v1
|
|
89
|
+
| Snapshot diffing | Pure Snapshot v1 comparison, explicit rename evidence, non-authoritative suggestions, and safety diagnostics |
|
|
78
90
|
| Migration planning | Pure, dialect-neutral plans with stable ordering, dependency edges, preconditions, explicit review decisions, and tagged custom SQL |
|
|
79
91
|
| DDL emission | Preflight plus deterministic PostgreSQL, SQLite, and MySQL statements from an approved `MigrationPlan` and matching `SchemaDialect` |
|
|
80
|
-
| Migration operations | Strict artifacts and baselines, authoritative programs, repository and journal validation, adapter capability preflight, execution, status/drift, reconciliation, and
|
|
92
|
+
| Migration operations | Strict artifacts and baselines, authoritative programs, repository and journal validation, adapter capability preflight, execution, status/drift, reconciliation, SQLite bootstrap, and complete PostgreSQL bootstrap with standalone enum ordering |
|
|
81
93
|
| Build tooling | The optional Vite directive transform and its matching TypeScript ambient declarations |
|
|
82
94
|
| Drizzle conversion | Optional, dialect-specific runtime conversion from Qubu schema registries to Drizzle tables |
|
|
83
95
|
| Source generation | Pure Snapshot v1 table source printing, deterministic camelCase IDs, exact physical metadata, controlled type mappings, and structured failure diagnostics |
|
|
@@ -31,25 +31,38 @@ IDs are evidence selected by the adapter's identity policy. PostgreSQL OIDs,
|
|
|
31
31
|
SQLite implementation names, and similar catalog keys stay in current-run
|
|
32
32
|
references and are not used as logical IDs.
|
|
33
33
|
|
|
34
|
-
## Snapshot
|
|
34
|
+
## Snapshot v1
|
|
35
35
|
|
|
36
36
|
`qubu/snapshot` provides the strict complete format as a separate API:
|
|
37
37
|
|
|
38
38
|
```ts
|
|
39
39
|
import { decodeCompleteSchemaSnapshot, encodeCompleteSchemaSnapshot } from "qubu/snapshot"
|
|
40
40
|
|
|
41
|
-
const encoded = encodeCompleteSchemaSnapshot(
|
|
41
|
+
const encoded = encodeCompleteSchemaSnapshot(snapshotV1)
|
|
42
42
|
const decoded = decodeCompleteSchemaSnapshot(encoded)
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
Snapshot
|
|
45
|
+
Snapshot v1 uses the same `qubu-schema` envelope with `version: 1`. Its
|
|
46
46
|
namespace, capability facts, object-family arrays, cross-object references,
|
|
47
47
|
provenance, typed dialect extensions, and deferred/opaque boundaries are
|
|
48
48
|
strictly validated. Arrays are ordered by logical ID (with ordinal sequences
|
|
49
49
|
and index terms ordered by their semantic position), and the fingerprint is computed
|
|
50
50
|
from the deterministic encoding.
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
Normalized references to nested catalog objects retain their owner scope. A
|
|
53
|
+
table-local index or constraint reference is mapped with
|
|
54
|
+
`owner: { kind: "table", id }`; view columns use the view kind and ID; domain
|
|
55
|
+
constraints use the domain kind and ID. The legacy `tableId` shorthand on
|
|
56
|
+
catalog entity references is converted to that owner form at the Snapshot v1
|
|
57
|
+
boundary. Top-level references have no owner. This scope prevents equal child
|
|
58
|
+
IDs from different tables or object families from overwriting one another.
|
|
59
|
+
|
|
60
|
+
Catalog extension payloads and configuration records are opaque JSON. Their
|
|
61
|
+
keys and values are preserved through normalization and canonical encoding;
|
|
62
|
+
objects inside those payloads are not treated as Snapshot expressions or
|
|
63
|
+
native storage declarations.
|
|
64
|
+
|
|
65
|
+
Snapshot v1 is the only strict schema snapshot format. `decodeSchemaSnapshot`
|
|
66
|
+
and `decodeCompleteSchemaSnapshot` both validate the same version-1 envelope,
|
|
67
|
+
reject unknown fields and future versions, and never evaluate database-provided
|
|
68
|
+
SQL.
|
|
@@ -14,9 +14,10 @@ generator:
|
|
|
14
14
|
```ts
|
|
15
15
|
import { writeFile } from "node:fs/promises"
|
|
16
16
|
import { generateSchemaSource } from "qubu/codegen"
|
|
17
|
-
import { mapCatalogToSnapshot
|
|
17
|
+
import { mapCatalogToSnapshot } from "qubu/introspection"
|
|
18
|
+
import { readCatalog } from "qubu/introspection/sqlite"
|
|
18
19
|
|
|
19
|
-
const catalog = await
|
|
20
|
+
const catalog = await readCatalog(connection, { namespace: "main" })
|
|
20
21
|
const introspection = mapCatalogToSnapshot(catalog, { namespace: "main" })
|
|
21
22
|
const generated = generateSchemaSource(introspection)
|
|
22
23
|
|
|
@@ -134,6 +135,6 @@ module does not look complete by omission.
|
|
|
134
135
|
|
|
135
136
|
The entrypoint does not provide a CLI, filesystem ownership, live driver
|
|
136
137
|
integration, multiple namespaces, runtime schema materialization, migrations,
|
|
137
|
-
DDL,
|
|
138
|
+
DDL, non-table object generation, or hand-edit merging. Use
|
|
138
139
|
[Database introspection](introspection.md) for the catalog boundary and
|
|
139
140
|
[Canonical schema snapshots](snapshots.md) for the identity artifact.
|
package/docs/schema/diff.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Snapshot diffing
|
|
2
2
|
|
|
3
|
-
> Compare canonical Snapshot v1
|
|
3
|
+
> Compare canonical Snapshot v1 values and review identity changes before a later planning step.
|
|
4
4
|
|
|
5
5
|
The optional `qubu/diff` entrypoint compares immutable snapshot data. It does
|
|
6
6
|
not open a connection, render SQL, execute a change, or infer migration history.
|
|
@@ -57,7 +57,7 @@ an `ambiguous` diagnostic and leaves both operations visible for review.
|
|
|
57
57
|
|
|
58
58
|
Removing an object is marked `destructive`. Narrowing nullability, changing
|
|
59
59
|
storage, removing a value, or changing a constraint can also receive that
|
|
60
|
-
classification. Opaque and deferred Snapshot
|
|
60
|
+
classification. Opaque and deferred Snapshot v1 records remain visible as
|
|
61
61
|
`add` or `remove` data and produce `lossy` or `unsupported` diagnostics. They
|
|
62
62
|
cannot be silently promoted to a rename.
|
|
63
63
|
|