qubu 0.6.2 → 0.7.0
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/dist/codegen.d.mts +1 -1
- package/dist/codegen.mjs +1 -1
- package/dist/core.d.mts +1 -1
- package/dist/diff.d.mts +1 -1
- package/dist/index-DB07P2X8.d.mts +2 -0
- package/dist/index.d.mts +1 -1
- package/dist/introspection/mysql.d.mts +1 -1
- package/dist/introspection/postgres.d.mts +1 -1
- package/dist/introspection/sqlite.d.mts +1 -1
- package/dist/introspection.d.mts +3 -2
- package/dist/introspection.mjs +1 -1
- package/dist/mysql.d.mts +2 -2
- package/dist/postgres.d.mts +2 -2
- package/dist/schema.d.mts +1 -1
- package/dist/{serialize-Du2UPZMt.d.mts → serialize-Dg-Q55YQ.d.mts} +1 -1
- package/dist/snapshot/mysql.d.mts +2 -2
- package/dist/snapshot/postgres.d.mts +2 -2
- package/dist/snapshot/sqlite.d.mts +2 -2
- package/dist/{snapshot-mIb-Zzb5.mjs → snapshot-C1x2R-iK.mjs} +25 -9
- package/dist/snapshot.d.mts +3 -3
- package/dist/sqlite.d.mts +2 -2
- package/dist/{types-CiMvKi5V.d.mts → types-CdcYI0lU.d.mts} +1 -1
- package/dist/{types-Dqr4o2I1.d.mts → types-DcIiNePM.d.mts} +7 -0
- package/docs/dialects-and-execution.md +54 -25
- package/docs/getting-started.md +9 -9
- package/docs/guides/better-auth.md +16 -5
- package/docs/guides/compose-queries.md +21 -9
- package/docs/guides/drizzle.md +8 -3
- package/docs/guides/extensions/dialects.md +1 -1
- package/docs/guides/extensions/overview.md +1 -1
- package/docs/guides/extensions/sources-and-clauses.md +7 -3
- package/docs/guides/extensions/typed-expressions.md +25 -13
- package/docs/guides/extensions/unsafe-syntax.md +10 -6
- package/docs/guides/json.md +52 -27
- package/docs/guides/mutations.md +15 -6
- package/docs/guides/select/conditions.md +18 -11
- package/docs/guides/select/grouping-and-windows.md +5 -2
- package/docs/guides/select/ordering-and-pagination.md +5 -3
- package/docs/guides/select/overview.md +6 -3
- package/docs/guides/sql-templates.md +11 -5
- package/docs/guides/valtio-sync.md +11 -5
- package/docs/guides/vite-plugin.md +2 -2
- package/docs/index.md +24 -17
- package/docs/migrations/adapters.md +58 -22
- package/docs/migrations/adopt.md +331 -0
- package/docs/migrations/artifacts-and-policy.md +49 -20
- package/docs/migrations/index.md +18 -9
- package/docs/migrations/operations.md +60 -70
- package/docs/migrations/recovery.md +34 -17
- package/docs/query-model/fragments.md +13 -5
- package/docs/query-model/result-shapes.md +2 -2
- package/docs/query-model/source-scope.md +5 -3
- package/docs/reference/introspection-support.md +26 -19
- package/docs/reference/mysql-snapshot.md +19 -4
- package/docs/reference/postgres-snapshot.md +17 -4
- package/docs/reference/sqlite-snapshot.md +19 -2
- package/docs/reference/supported-surface.md +221 -85
- package/docs/schema/catalog-model.md +24 -7
- package/docs/schema/code-generation.md +40 -21
- package/docs/schema/columns-and-writes.md +21 -11
- package/docs/schema/constraints-and-indexes.md +12 -5
- package/docs/schema/ddl-emission.md +16 -5
- package/docs/schema/diff.md +12 -4
- package/docs/schema/introspection.md +47 -21
- package/docs/schema/migration-plans.md +18 -10
- package/docs/schema/snapshots.md +57 -29
- package/docs/schema/storage-and-schema-sql.md +10 -4
- package/docs/schema/tables-and-names.md +1 -1
- package/docs/sql-semantic-types.md +11 -8
- package/docs/troubleshooting.md +14 -6
- package/package.json +1 -1
- package/dist/index-CaxrMD1A.d.mts +0 -1
- package/docs/migrations/lotta-adoption.md +0 -50
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# Artifacts and approval policy
|
|
2
2
|
|
|
3
|
-
> Review
|
|
3
|
+
> Review migration files and approve the exact operations they will run.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
An artifact is a versioned migration file. Qubu supports two kinds:
|
|
6
|
+
|
|
7
|
+
- An **executable migration** contains a reviewed plan and the program to run.
|
|
8
|
+
- A **verified baseline** records the observed schema as a starting point. It
|
|
9
|
+
does not claim that historical SQL ran through Qubu.
|
|
8
10
|
|
|
9
11
|
## Published formats
|
|
10
12
|
|
|
@@ -38,18 +40,30 @@ An executable artifact records:
|
|
|
38
40
|
- operation-scoped approvals and custom-program provenance;
|
|
39
41
|
- artifact provenance and `artifactDigest`.
|
|
40
42
|
|
|
41
|
-
The program
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
The executor runs the program stored in the artifact. The SQL preview from
|
|
44
|
+
`emitMigrationPlan(...).sql` is not an executable artifact.
|
|
45
|
+
|
|
46
|
+
Each phase declares:
|
|
47
|
+
|
|
48
|
+
- Its position and dependencies.
|
|
49
|
+
- Transaction and lock requirements.
|
|
50
|
+
- Preconditions and postconditions.
|
|
51
|
+
- Ordered statements.
|
|
52
|
+
|
|
53
|
+
Each statement declares its operation ID, dependencies, SQL, and tagged parameters.
|
|
46
54
|
|
|
47
55
|
### Baseline artifact schema
|
|
48
56
|
|
|
49
|
-
A baseline records
|
|
50
|
-
|
|
51
|
-
`
|
|
52
|
-
|
|
57
|
+
A baseline records:
|
|
58
|
+
|
|
59
|
+
- `id`, sequence, and parent lineage.
|
|
60
|
+
- Encoding descriptors.
|
|
61
|
+
- Dialect and optional constraints.
|
|
62
|
+
- One verified snapshot descriptor and `verifiedAt`.
|
|
63
|
+
- Provenance and optional operator metadata.
|
|
64
|
+
- `artifactDigest`.
|
|
65
|
+
|
|
66
|
+
It has no migration plan, program, or SQL digest.
|
|
53
67
|
|
|
54
68
|
Artifact IDs are stable identities, not repository order. Sequence and parent
|
|
55
69
|
digest establish the linear chain. Renumbering therefore changes lineage and
|
|
@@ -57,21 +71,36 @@ the artifact digest.
|
|
|
57
71
|
|
|
58
72
|
## Canonical bytes and digest domains
|
|
59
73
|
|
|
60
|
-
`encodeCanonical()`
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
74
|
+
`encodeCanonical()` produces a repeatable byte representation:
|
|
75
|
+
|
|
76
|
+
- Sort object keys by Unicode code-point order.
|
|
77
|
+
- Preserve array order.
|
|
78
|
+
- Emit compact UTF-8 JSON.
|
|
79
|
+
- Normalize `-0` to `0` and reject non-finite numbers.
|
|
80
|
+
- End the file with one line feed.
|
|
81
|
+
|
|
82
|
+
`digestCanonical()` prefixes those bytes with the UTF-8 bytes for:
|
|
64
83
|
|
|
65
84
|
```text
|
|
66
85
|
qubu:migrate:v1:<domain>\0
|
|
67
86
|
```
|
|
68
87
|
|
|
69
|
-
The
|
|
70
|
-
|
|
71
|
-
|
|
88
|
+
The digest identifies its purpose through one of five domains:
|
|
89
|
+
|
|
90
|
+
- `artifact`.
|
|
91
|
+
- `baseline`.
|
|
92
|
+
- `migration-plan`.
|
|
93
|
+
- `migration-program`.
|
|
94
|
+
- `schema-snapshot`.
|
|
95
|
+
|
|
96
|
+
The prefix ensures that identical JSON used for different purposes gets
|
|
97
|
+
different digests.
|
|
98
|
+
|
|
72
99
|
Operational digests have the form `sha256:` plus 64 lowercase hexadecimal
|
|
73
100
|
digits and are recomputed while sealing or decoding.
|
|
74
101
|
|
|
102
|
+
### Fingerprints and integrity digests
|
|
103
|
+
|
|
75
104
|
Snapshot and plan `fingerprint` APIs are deterministic FNV-1a64 change
|
|
76
105
|
detectors. They remain useful for caches and fixture assertions, but they are
|
|
77
106
|
not cryptographic integrity evidence and are never valid journal heads,
|
package/docs/migrations/index.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Migration operations
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Find the packages and guides for planning, running, and recovering migrations.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
These packages handle different parts of a migration:
|
|
6
6
|
|
|
7
7
|
| Owner | Imports | Responsibility |
|
|
8
8
|
| --------------- | --------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -21,6 +21,8 @@ import { emitMigrationPlan } from "@qubu/migrate/ddl"
|
|
|
21
21
|
import { compileMigrationProgram, sealExecutableArtifact } from "@qubu/migrate/artifact"
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
## Choose an import
|
|
25
|
+
|
|
24
26
|
The `@qubu/migrate` root intentionally exports only format/version constants
|
|
25
27
|
and the central plan and artifact types. Import behavior from its focused
|
|
26
28
|
entrypoint:
|
|
@@ -39,19 +41,26 @@ entrypoint:
|
|
|
39
41
|
| `@qubu/migrate/repository` | Verify a complete artifact chain and its journal prefix |
|
|
40
42
|
| `@qubu/migrate/journal` | Implement or inspect the storage-neutral journal contract |
|
|
41
43
|
| `@qubu/migrate/executor` | Apply artifacts and reconcile uncertain attempts |
|
|
42
|
-
| `@qubu/migrate/baseline` |
|
|
44
|
+
| `@qubu/migrate/baseline` | Capture, preflight, and accept a reviewed live schema as the initial non-executable baseline |
|
|
43
45
|
| `@qubu/migrate/status` | Inspect pending work, drift, requirements, and interrupted attempts |
|
|
44
46
|
| `@qubu/migrate/bootstrap` | Prepare a fresh schema diff and expose shared bootstrap types; accepts a caller-supplied `SchemaDialect` for generic planning |
|
|
45
47
|
| `@qubu/migrate/bootstrap/postgres` | Plan a fresh PostgreSQL schema through the normal compiler |
|
|
46
48
|
| `@qubu/migrate/bootstrap/sqlite` | Plan a fresh SQLite schema through the normal compiler |
|
|
47
49
|
| `@qubu/migrate/testing` | Test adapter capabilities and deterministic failure boundaries |
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
## Choose a guide
|
|
52
|
+
|
|
53
|
+
- [Artifacts and approval policy](artifacts-and-policy.md): review migration
|
|
54
|
+
files and approve operations.
|
|
55
|
+
- [Adapter capability profiles](adapters.md): choose a supported driver.
|
|
56
|
+
- [Command line operations](operations.md): configure and use the CLI.
|
|
57
|
+
- [Adopt an existing database](adopt.md): capture, review, and accept the live
|
|
58
|
+
starting schema before applying separate migrations.
|
|
59
|
+
- [Recovery and reconciliation](recovery.md): handle interrupted migrations.
|
|
60
|
+
- [Lotta Games adoption](lotta-adoption.md): review the downstream cutover
|
|
61
|
+
plan and combo-matrix release blocker.
|
|
62
|
+
|
|
63
|
+
## Select a built-in dialect
|
|
55
64
|
|
|
56
65
|
Choose the dialect-specific bootstrap entrypoint when using a built-in dialect:
|
|
57
66
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Command line operations
|
|
2
2
|
|
|
3
|
-
> Configure, inspect
|
|
3
|
+
> Configure the CLI, inspect migration status, and apply a migration chain.
|
|
4
4
|
|
|
5
5
|
Install the CLI, migration library, and one verified migration adapter. For a
|
|
6
6
|
libSQL application:
|
|
@@ -9,11 +9,16 @@ libSQL application:
|
|
|
9
9
|
pnpm add @qubu/cli @qubu/migrate @qubu/adapter-libsql @libsql/client
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
The `qubu`
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
The `qubu` command loads `qubu.config.js` by default. Use `--config <path>` to
|
|
13
|
+
select another configuration module.
|
|
14
|
+
|
|
15
|
+
Every command accepts:
|
|
16
|
+
|
|
17
|
+
- `--format human|json`, defaulting to `human`.
|
|
18
|
+
- `--non-interactive`, to state that the command must run without prompts.
|
|
19
|
+
|
|
20
|
+
Commands currently never prompt. Missing required input fails even without
|
|
21
|
+
`--non-interactive`.
|
|
17
22
|
|
|
18
23
|
## Configuration
|
|
19
24
|
|
|
@@ -21,7 +26,7 @@ Export a typed config and keep credentials inside the adapter factory:
|
|
|
21
26
|
|
|
22
27
|
```ts
|
|
23
28
|
import { createClient } from "@libsql/client"
|
|
24
|
-
import {
|
|
29
|
+
import { migrationAdapter, readMigrationSnapshot } from "@qubu/adapter-libsql/migration"
|
|
25
30
|
import { defineConfig } from "@qubu/cli/config"
|
|
26
31
|
import snapshot from "./schema.snapshot.js"
|
|
27
32
|
|
|
@@ -33,8 +38,8 @@ export default defineConfig({
|
|
|
33
38
|
snapshot,
|
|
34
39
|
environment: "production",
|
|
35
40
|
adapter: () =>
|
|
36
|
-
|
|
37
|
-
readSnapshot:
|
|
41
|
+
migrationAdapter(createClient({ url }), {
|
|
42
|
+
readSnapshot: readMigrationSnapshot,
|
|
38
43
|
}),
|
|
39
44
|
provenance: { source: "my-service" },
|
|
40
45
|
})
|
|
@@ -46,35 +51,40 @@ approvals, custom programs, renderer/server constraints, baseline operator
|
|
|
46
51
|
metadata, and reconciliation proof. `artifacts` is resolved from the CLI
|
|
47
52
|
working directory.
|
|
48
53
|
|
|
49
|
-
| Field | Required | Meaning
|
|
50
|
-
| ------------------------------------------ | ------------------- |
|
|
51
|
-
| `artifacts` | yes | Artifact directory, relative to the command working directory unless absolute
|
|
52
|
-
| `snapshot` | one snapshot source | Snapshot value or sync/async factory
|
|
53
|
-
| `schema` + `snapshotFromSchema` | one snapshot source | Application-owned conversion when the source is a Qubu `Schema`
|
|
54
|
-
| `adapter` | database commands | Sync/async factory returning a migration adapter
|
|
55
|
-
| `approvals` | no | Sync/async operation policy; receives the operation, finding codes, and requested CLI reason
|
|
56
|
-
| `customPrograms` | no | Exact operation substitutions with execution requirements and provenance
|
|
57
|
-
| `renderer`, `serverVersion`, `constraints` | no | Renderer identity and target compatibility constraints
|
|
58
|
-
| `provenance` | no | Artifact source/revision/actor/metadata; defaults to `{ source: "@qubu/cli" }`
|
|
59
|
-
| `environment` | no | `development`, `test`, `staging`, or `production`; context only
|
|
60
|
-
| `baselineOperator` | no | JSON-safe operator metadata stored in a baseline
|
|
61
|
-
| `verifyReconciliation` | reconcile only | Application-owned proof of the selected live outcome
|
|
54
|
+
| Field | Required | Meaning |
|
|
55
|
+
| ------------------------------------------ | ------------------- | --------------------------------------------------------------------------------------------------- |
|
|
56
|
+
| `artifacts` | yes | Artifact directory, relative to the command working directory unless absolute |
|
|
57
|
+
| `snapshot` | one snapshot source | Snapshot value or sync/async factory |
|
|
58
|
+
| `schema` + `snapshotFromSchema` | one snapshot source | Application-owned conversion when the source is a Qubu `Schema` |
|
|
59
|
+
| `adapter` | database commands | Sync/async factory returning a migration adapter, or an adoption-only adapter for baseline commands |
|
|
60
|
+
| `approvals` | no | Sync/async operation policy; receives the operation, finding codes, and requested CLI reason |
|
|
61
|
+
| `customPrograms` | no | Exact operation substitutions with execution requirements and provenance |
|
|
62
|
+
| `renderer`, `serverVersion`, `constraints` | no | Renderer identity and target compatibility constraints |
|
|
63
|
+
| `provenance` | no | Artifact source/revision/actor/metadata; defaults to `{ source: "@qubu/cli" }` |
|
|
64
|
+
| `environment` | no | `development`, `test`, `staging`, or `production`; context only |
|
|
65
|
+
| `baselineOperator` | no | JSON-safe operator metadata stored in a baseline |
|
|
66
|
+
| `verifyReconciliation` | reconcile only | Application-owned proof of the selected live outcome |
|
|
62
67
|
|
|
63
68
|
## Commands
|
|
64
69
|
|
|
65
|
-
| Syntax | Reads or writes | Important failure behavior
|
|
66
|
-
| --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
67
|
-
| `qubu migrate create <id> [--approve <operation-id=reason>...] [--approved-by <actor>] [--dry-run]` | Verifies the full repository, plans from its embedded final snapshot, seals, then writes one canonical artifact unless dry-run | Unknown operation IDs or missing exact approvals fail policy
|
|
68
|
-
| `qubu migrate verify` | Strictly decodes and verifies every artifact and the complete chain | Any malformed, tampered, forked, gapped, or mismatched artifact fails validation
|
|
69
|
-
| `qubu migrate status` | Opens a session and lease; reports managed drift, unmanaged objects, pending artifacts, interrupted attempts, and incompatible requirements | Recovery, validation, drift, and capability policy are distinct failures
|
|
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
|
-
| `qubu migrate baseline
|
|
72
|
-
| `qubu migrate
|
|
73
|
-
| `qubu
|
|
70
|
+
| Syntax | Reads or writes | Important failure behavior |
|
|
71
|
+
| --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
|
72
|
+
| `qubu migrate create <id> [--approve <operation-id=reason>...] [--approved-by <actor>] [--dry-run]` | Verifies the full repository, plans from its embedded final snapshot, seals, then writes one canonical artifact unless dry-run | Unknown operation IDs or missing exact approvals fail policy |
|
|
73
|
+
| `qubu migrate verify` | Strictly decodes and verifies every artifact and the complete chain | Any malformed, tampered, forked, gapped, or mismatched artifact fails validation |
|
|
74
|
+
| `qubu migrate status` | Opens a session and lease; reports managed drift, unmanaged objects, pending artifacts, interrupted attempts, and incompatible requirements | Recovery, validation, drift, and capability policy are distinct failures |
|
|
75
|
+
| `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 |
|
|
76
|
+
| `qubu migrate baseline-capture --out <path>` | Strictly reads live managed schema and writes a new candidate snapshot outside the artifact repository | Strict inspection failures block capture; existing candidate files are not overwritten |
|
|
77
|
+
| `qubu migrate baseline <id> --candidate <path> [--confirm <fact>...] [--dry-run]` | Reinspects the reviewed candidate; acceptance records baseline then writes its artifact | Empty repository and adapter history required; acceptance requires seven confirmations; dry-run inspects without recording |
|
|
78
|
+
| `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 |
|
|
79
|
+
| `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 |
|
|
80
|
+
|
|
81
|
+
## Output and exit codes
|
|
74
82
|
|
|
75
|
-
JSON output
|
|
76
|
-
credential-like keys and
|
|
77
|
-
|
|
83
|
+
JSON output has stable, recursively sorted keys and ends with a newline. It
|
|
84
|
+
redacts credential-like keys and secrets embedded in URLs. Human output is
|
|
85
|
+
brief.
|
|
86
|
+
|
|
87
|
+
Signals pass through adapters. An abort exits with code 130.
|
|
78
88
|
|
|
79
89
|
| Exit | Meaning |
|
|
80
90
|
| ---: | ----------------------------------------------------------------------------- |
|
|
@@ -94,14 +104,19 @@ snapshot. Logical IDs help reporting but do not prove equality. Objects not
|
|
|
94
104
|
owned by the managed snapshot are returned separately as `unmanagedObjects`;
|
|
95
105
|
Qubu journal objects are excluded by migration snapshot readers.
|
|
96
106
|
|
|
107
|
+
### Bootstrap a fresh database
|
|
108
|
+
|
|
97
109
|
`schema bootstrap` is for a fresh SQLite database or a fresh PostgreSQL schema.
|
|
98
110
|
It produces the same reviewed plan, versioned program, sealed artifact, and
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
111
|
+
execution path as a migration.
|
|
112
|
+
|
|
113
|
+
Database-specific behavior:
|
|
114
|
+
|
|
115
|
+
- PostgreSQL bootstrap creates standalone enums before tables that use them
|
|
116
|
+
as native column types. The complete target snapshot defines those enums.
|
|
117
|
+
- SQLite inline constraints are included in table creation. Table rebuilds
|
|
118
|
+
use explicit phases with data-copy and postcondition checks.
|
|
119
|
+
- Session settings, such as SQLite PRAGMAs, stay in application or adapter setup.
|
|
105
120
|
|
|
106
121
|
Use the reviewed complete snapshot directly as the PostgreSQL target:
|
|
107
122
|
|
|
@@ -114,34 +129,9 @@ The dry run prints the ordered phases without opening the adapter. Remove
|
|
|
114
129
|
an application-owned custom program. Bootstrap does not import or replay
|
|
115
130
|
Drizzle migration history.
|
|
116
131
|
|
|
117
|
-
##
|
|
118
|
-
|
|
119
|
-
A baseline is a statement about the live database now, not a replay of its
|
|
120
|
-
history. Before supplying all seven confirmations, the operator must verify:
|
|
121
|
-
|
|
122
|
-
- `database-target`: the connection names the intended environment;
|
|
123
|
-
- `snapshot-source`: the reviewed snapshot is the intended source of truth;
|
|
124
|
-
- `zero-managed-drift`: strict inspection reports no managed mismatch;
|
|
125
|
-
- `backup-restore-ready`: backup and restore procedures are ready;
|
|
126
|
-
- `other-migrators-stopped`: no other migration runner can race the cutover;
|
|
127
|
-
- `application-compatible`: deployed code is compatible with the live schema;
|
|
128
|
-
- `legacy-history-cutover`: the team accepts the new baseline as the lineage start.
|
|
129
|
-
|
|
130
|
-
For example, repeat `--confirm` once per exact value. The CLI rejects missing
|
|
131
|
-
or unknown confirmation names even outside production; `environment` is
|
|
132
|
-
reported as context rather than used to weaken the policy.
|
|
133
|
-
|
|
134
|
-
```bash
|
|
135
|
-
qubu migrate baseline lotta-cutover \
|
|
136
|
-
--confirm database-target \
|
|
137
|
-
--confirm snapshot-source \
|
|
138
|
-
--confirm zero-managed-drift \
|
|
139
|
-
--confirm backup-restore-ready \
|
|
140
|
-
--confirm other-migrators-stopped \
|
|
141
|
-
--confirm application-compatible \
|
|
142
|
-
--confirm legacy-history-cutover \
|
|
143
|
-
--format json --non-interactive
|
|
144
|
-
```
|
|
132
|
+
## Adopt an existing database
|
|
145
133
|
|
|
146
|
-
|
|
147
|
-
|
|
134
|
+
Follow the [adoption guide](adopt.md) to capture a live candidate, review its
|
|
135
|
+
scope and facts, run preflight, and explicitly accept it.
|
|
136
|
+
Keep the configured application snapshot as the desired schema for subsequent
|
|
137
|
+
migration planning. Baseline acceptance does not certify application compatibility.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# Recovery and reconciliation
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Verify what happened after an uncertain migration and record the outcome before continuing.
|
|
4
4
|
|
|
5
|
-
The journal
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
schema inspection.
|
|
5
|
+
The journal records migration progress in the same database as the schema.
|
|
6
|
+
Its head is the digest of the last applied artifact.
|
|
7
|
+
|
|
8
|
+
Adapters reserve objects prefixed with `__qubu_migration_` and exclude them
|
|
9
|
+
from managed schema inspection. The journal contains these records:
|
|
10
10
|
|
|
11
11
|
| Record | Fields and invariant |
|
|
12
12
|
| ---------------- | -------------------------------------------------------------------------------------------------------------- |
|
|
@@ -45,13 +45,23 @@ head, or a non-prefix repository fail before any statement executes.
|
|
|
45
45
|
|
|
46
46
|
## Execution and concurrency guarantees
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
Before applying migrations, the executor:
|
|
49
|
+
|
|
50
|
+
1. Verifies the entire artifact repository.
|
|
51
|
+
2. Opens one migration session and checks its capabilities.
|
|
52
|
+
3. Acquires the migrator lease.
|
|
53
|
+
4. Verifies that the journal matches the start of the repository chain.
|
|
54
|
+
5. Checks the live before-snapshot digest.
|
|
55
|
+
|
|
56
|
+
For each pending artifact, it:
|
|
57
|
+
|
|
58
|
+
1. Creates an attempt record.
|
|
59
|
+
2. Runs phases in order, checking their preconditions and postconditions.
|
|
60
|
+
3. Writes durable checkpoints.
|
|
61
|
+
4. Appends the applied history and updates the head only if it still matches
|
|
62
|
+
the expected parent.
|
|
63
|
+
|
|
64
|
+
Cleanup releases the DDL lock, then the migrator lease, then the session.
|
|
55
65
|
|
|
56
66
|
An `atomic-batch` profile instead applies one single-phase artifact in one
|
|
57
67
|
database transaction, including its checks and terminal journal writes. It
|
|
@@ -76,10 +86,17 @@ must be resolved by the renderer or explicit custom program before sealing.
|
|
|
76
86
|
Transactions are phase-scoped. Do not infer that an earlier committed phase
|
|
77
87
|
will roll back because a later phase fails.
|
|
78
88
|
|
|
79
|
-
Errors
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
89
|
+
### Errors and retries
|
|
90
|
+
|
|
91
|
+
Errors use stable codes:
|
|
92
|
+
|
|
93
|
+
- `validation`, `policy`, and `capability`.
|
|
94
|
+
- `drift` and `concurrency`.
|
|
95
|
+
- `definite-rollback`, `uncertain-outcome`, and `recovery-required`.
|
|
96
|
+
- `aborted` and `adapter`.
|
|
97
|
+
|
|
98
|
+
Error context may identify the artifact, attempt, phase, and statement.
|
|
99
|
+
Persisted failures omit SQL parameters and credentials.
|
|
83
100
|
|
|
84
101
|
Do not automatically retry after any statement may have taken effect. Only an
|
|
85
102
|
error explicitly marked `retry: "safe"`—normally validation or a failure proven
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Fragments and metadata
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Understand how SQL fragments carry the type information Qubu needs to check a query.
|
|
4
4
|
|
|
5
5
|
## A fragment has a renderer and metadata
|
|
6
6
|
|
|
@@ -39,9 +39,12 @@ Composition helpers keep the facts that their children already carry:
|
|
|
39
39
|
| `groupBy()` | Record grouping expressions and the column dependencies they make available. |
|
|
40
40
|
| `leftJoin()` | Add `NullableSourceMeta` for the joined source. |
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
`
|
|
42
|
+
Use these types to read a fragment’s metadata:
|
|
43
|
+
|
|
44
|
+
- `OutputOf<T>`: the result type.
|
|
45
|
+
- `SqlTypeOf<T>`: the SQL domain.
|
|
46
|
+
- `RequiresOf<T>`: the sources it requires.
|
|
47
|
+
- `NullabilityOf<T>`: the sources that can make it null after an outer join.
|
|
45
48
|
|
|
46
49
|
Qubu does not infer every SQL rule. Grouping checks use declared dependencies,
|
|
47
50
|
and functional dependencies from database keys are handled where the source
|
|
@@ -73,7 +76,10 @@ render(query)
|
|
|
73
76
|
// parameters: [7, '%Ada%']
|
|
74
77
|
```
|
|
75
78
|
|
|
76
|
-
|
|
79
|
+
### Give parameters a SQL domain
|
|
80
|
+
|
|
81
|
+
Optional SQL domains are stored in `parameterSqlTypes`. Each entry matches
|
|
82
|
+
the parameter at the same position:
|
|
77
83
|
|
|
78
84
|
```ts
|
|
79
85
|
import { typedValue } from "qubu/core"
|
|
@@ -96,6 +102,8 @@ The parameter array follows the placeholders in the rendered text. `select()`
|
|
|
96
102
|
normalizes independent clause values, but keep the final call in SQL order in
|
|
97
103
|
new code so source scope and repair hints are visible at a glance.
|
|
98
104
|
|
|
105
|
+
### Compose SQL templates
|
|
106
|
+
|
|
99
107
|
The public [`sql` template tag](../guides/sql-templates.md) uses the same
|
|
100
108
|
renderer. Ordinary substitutions call `context.parameter()`, while expression,
|
|
101
109
|
query, and fragment substitutions call back into the active render context.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Result shapes and cardinality
|
|
2
2
|
|
|
3
|
-
> Choose
|
|
3
|
+
> Choose result fields and understand when a join or subquery can make them null.
|
|
4
4
|
|
|
5
5
|
## Name the selected row
|
|
6
6
|
|
|
@@ -27,7 +27,7 @@ type Row = typeof query.row
|
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
The projection key also names the SQL output column. Use explicit fields for a
|
|
30
|
-
shaped result.
|
|
30
|
+
shaped result. Use `all(source)` when you want every source column. It
|
|
31
31
|
expands to named columns, so the SQL columns and inferred row keys stay aligned:
|
|
32
32
|
|
|
33
33
|
```ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Source scope
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Learn why a column must belong to a source in the query, and how to refer to an enclosing query.
|
|
4
4
|
|
|
5
5
|
A column carries the identity of the source that provides it. Qubu checks that
|
|
6
6
|
identity when you assemble a query. The source must appear in `FROM` or a join
|
|
@@ -118,7 +118,9 @@ const query = select({ value: entries.value }, from(entries), where(eq(entries.k
|
|
|
118
118
|
```
|
|
119
119
|
|
|
120
120
|
`identity` is the type-level source key. `reference` is the SQL qualifier used
|
|
121
|
-
by the generated columns.
|
|
121
|
+
by the generated columns.
|
|
122
|
+
|
|
123
|
+
The nullable `value` column stays nullable, and a
|
|
122
124
|
`leftJoin()` adds outer-join nullability to every selected column from
|
|
123
125
|
`entries`.
|
|
124
126
|
|
|
@@ -128,7 +130,7 @@ keeps those values in placeholder order.
|
|
|
128
130
|
## Correlate an inner query
|
|
129
131
|
|
|
130
132
|
Use `correlate()` when an inner query intentionally reads a source from its
|
|
131
|
-
enclosing query.
|
|
133
|
+
enclosing query. `correlate()` changes type checking but emits no SQL:
|
|
132
134
|
|
|
133
135
|
```ts
|
|
134
136
|
import { correlate, crossJoin, eq, from, integer, lateral, select, table, where } from "qubu"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Introspection support
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Check supported database versions, catalog objects, and snapshot-mapping limits.
|
|
4
4
|
|
|
5
5
|
The optional `qubu/introspection` entrypoint reads one selected database
|
|
6
6
|
namespace through a user-owned `CatalogConnection`. It returns normalized
|
|
@@ -67,19 +67,22 @@ table-valued PRAGMAs `database_list`, `table_list`, `table_xinfo`,
|
|
|
67
67
|
receives bound namespace or object parameters through the caller's
|
|
68
68
|
`CatalogConnection`. The reader does not interpolate a database name into SQL.
|
|
69
69
|
|
|
70
|
-
SQLite views and triggers become typed
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
SQLite views and triggers become typed catalog objects when Qubu can recover
|
|
71
|
+
their definition and target from CREATE SQL. Their SQL remains opaque data,
|
|
72
|
+
tagged with the `sqlite` dialect and a catalog reference.
|
|
73
|
+
|
|
74
|
+
Generated column expressions, declared storage types, SQLite affinity, rowid aliases, and
|
|
74
75
|
`AUTOINCREMENT` are kept as column or identity dialect extensions. User indexes
|
|
75
|
-
retain ordered column or expression terms and partial predicates.
|
|
76
|
-
|
|
76
|
+
retain ordered column or expression terms and partial predicates.
|
|
77
|
+
|
|
78
|
+
Inline UNIQUE constraints are recovered from their internal indexes with deterministic Qubu
|
|
77
79
|
names, so SQLite's `sqlite_autoindex_*` names do not become persisted logical
|
|
78
80
|
IDs.
|
|
79
81
|
|
|
80
82
|
SQLite virtual tables and shadow tables remain typed deferred objects with an
|
|
81
|
-
`unmodeled-object` diagnostic.
|
|
82
|
-
|
|
83
|
+
`unmodeled-object` diagnostic.
|
|
84
|
+
|
|
85
|
+
A selected attached database can expose table PRAGMA rows, but its schema SQL is outside the fixed `main` and `temp`
|
|
83
86
|
statements. Qubu marks that result as limited and keeps other attached
|
|
84
87
|
databases as opaque boundary records. It never combines attached databases into
|
|
85
88
|
the selected namespace. SQLite does not provide the PostgreSQL object families
|
|
@@ -101,13 +104,20 @@ strict Snapshot v1 result through a separate controlled printer.
|
|
|
101
104
|
|
|
102
105
|
The MySQL reader accepts MySQL 8.0.16 and later within the MySQL 8 series. It
|
|
103
106
|
rejects MariaDB and older MySQL versions instead of applying MySQL catalog
|
|
104
|
-
rules to a different product or server version.
|
|
105
|
-
|
|
107
|
+
rules to a different product or server version.
|
|
108
|
+
|
|
109
|
+
It reads `INFORMATION_SCHEMA` rows for one selected database and retains database-provided SQL as tagged,
|
|
106
110
|
unevaluated MySQL data.
|
|
107
111
|
|
|
108
|
-
MySQL has typed
|
|
109
|
-
|
|
110
|
-
|
|
112
|
+
MySQL has typed records for:
|
|
113
|
+
|
|
114
|
+
- Views.
|
|
115
|
+
- Routines and their parameters.
|
|
116
|
+
- Triggers and partitions.
|
|
117
|
+
- Collations used by selected tables or columns.
|
|
118
|
+
- Comments.
|
|
119
|
+
|
|
120
|
+
View definitions come from `INFORMATION_SCHEMA.VIEWS`; each view's
|
|
111
121
|
columns are joined back to the matching `COLUMNS` rows by physical table name,
|
|
112
122
|
so the complete Snapshot v1 cross-reference points at the view's own column
|
|
113
123
|
IDs. Missing view definitions or unresolved trigger, partition, or other
|
|
@@ -154,12 +164,9 @@ canonical content, not an identity or rename marker.
|
|
|
154
164
|
|
|
155
165
|
## Deferred and limited features
|
|
156
166
|
|
|
157
|
-
|
|
158
|
-
|
|
167
|
+
Supported object families become typed Snapshot v1 records, as described in
|
|
168
|
+
the database sections above. Limits still apply to individual features:
|
|
159
169
|
|
|
160
|
-
- views and materialized views;
|
|
161
|
-
- sequences, enums, domains, routines, triggers, policies, extensions,
|
|
162
|
-
collations, comments, and partition metadata;
|
|
163
170
|
- PostgreSQL identity sequence options that have no typed field;
|
|
164
171
|
- SQLite virtual/shadow tables, attached namespaces, and unrecoverable
|
|
165
172
|
generated or expression definitions;
|