qubu 0.6.1 → 0.6.3
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/{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-DM_tarXc.mjs → constraints-CAmi18Uk.mjs} +8 -3
- package/dist/core.d.mts +3 -3
- package/dist/core.mjs +4 -4
- 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-BCjc08zw.mjs → expressions-_6JF_J77.mjs} +2 -1
- package/dist/index-CaxrMD1A.d.mts +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +368 -74
- package/dist/introspection/mysql.d.mts +1 -1
- package/dist/introspection/mysql.mjs +156 -23
- package/dist/introspection/postgres.d.mts +6 -3
- package/dist/introspection/postgres.mjs +388 -53
- package/dist/introspection/sqlite.d.mts +1 -1
- package/dist/introspection/sqlite.mjs +198 -12
- package/dist/introspection.d.mts +26 -12
- package/dist/introspection.mjs +2 -672
- package/dist/mysql.d.mts +3 -3
- package/dist/mysql.mjs +6 -5
- package/dist/{errors-Dxv73YJu.mjs → omit-VEr9Ydux.mjs} +5 -1
- package/dist/{on-conflict-CnaY5qso.mjs → on-conflict-B2rFyHGF.mjs} +6 -8
- package/dist/on-duplicate-key-update-Czsw1Yq-.mjs +95 -0
- package/dist/{postgres-Dey7QXPL.mjs → postgres-hFhd0I9n.mjs} +4 -5
- package/dist/postgres.d.mts +2 -2
- package/dist/postgres.mjs +2 -2
- package/dist/{registry-oWDiqD7i.mjs → registry-BXE_4M9P.mjs} +1 -1
- package/dist/{relational-DSAJ-l58.mjs → relational-CoPBETjI.mjs} +3 -2
- package/dist/schema.d.mts +2 -2
- package/dist/schema.mjs +8 -8
- package/dist/{serialize-CE-gw5_s.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 +8 -8
- package/dist/snapshot/postgres.d.mts +3 -3
- package/dist/snapshot/postgres.mjs +9 -9
- package/dist/snapshot/sqlite.d.mts +3 -3
- package/dist/snapshot/sqlite.mjs +7 -7
- package/dist/snapshot-mIb-Zzb5.mjs +1489 -0
- package/dist/snapshot.d.mts +4 -5
- package/dist/snapshot.mjs +3 -4
- package/dist/{source-BDuUXmAk.mjs → source-DYSUqzvb.mjs} +2 -2
- package/dist/sqlite.d.mts +2 -2
- package/dist/sqlite.mjs +6 -6
- package/dist/{table-C1QGNe4P.mjs → table-B8zEq0az.mjs} +4 -4
- package/dist/{types-BLNRatG_.mjs → types-CYHpSPwj.mjs} +10 -5
- package/dist/{types-BEn0N_al.d.mts → types-CiMvKi5V.d.mts} +14 -4
- package/dist/{types-DUe6eeI0.d.mts → types-Dqr4o2I1.d.mts} +590 -168
- 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 +105 -26
- package/docs/getting-started.md +10 -10
- 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 +26 -12
- package/docs/guides/extensions/unsafe-syntax.md +10 -6
- package/docs/guides/json.md +126 -8
- package/docs/guides/mutations.md +51 -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 +25 -18
- package/docs/migrations/adapters.md +92 -27
- package/docs/migrations/artifacts-and-policy.md +49 -20
- package/docs/migrations/index.md +15 -8
- package/docs/migrations/lotta-adoption.md +16 -5
- package/docs/migrations/operations.md +29 -15
- package/docs/migrations/recovery.md +40 -17
- package/docs/query-model/fragments.md +33 -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 +42 -37
- 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 -84
- package/docs/schema/catalog-model.md +44 -14
- 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 +13 -5
- package/docs/schema/introspection.md +64 -31
- package/docs/schema/migration-plans.md +18 -10
- package/docs/schema/snapshots.md +68 -30
- package/docs/schema/storage-and-schema-sql.md +16 -5
- 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 +2 -1
- package/dist/canonical-DMvR9yBe.mjs +0 -972
- package/dist/column-BzN8KFJa.mjs +0 -364
- package/dist/column-CFvSbil0.mjs +0 -309
- package/dist/complete-types-CNMWBWap.d.mts +0 -371
- package/dist/index-CGui70hi.d.mts +0 -32
- package/dist/json-Db7XRD91.mjs +0 -169
- package/dist/omit-OxV58AwX.mjs +0 -5
- package/dist/serialize-OvXCLzjm.d.mts +0 -66
- package/dist/snapshot-DgsOhf_8.mjs +0 -354
|
@@ -1,45 +1,67 @@
|
|
|
1
1
|
# Adapter capability profiles
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Choose a migration adapter based on what its driver and environment have been tested to support.
|
|
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
|
+
Qubu validates program structure and adapter capabilities. It trusts the SQL
|
|
29
|
+
you supply, including SQL conditions, and does not parse it for safety.
|
|
30
|
+
|
|
31
|
+
Migration SQL must preserve the executor’s transactions, connection settings,
|
|
32
|
+
and journal state. For example, an explicit `COMMIT` can apply schema changes
|
|
33
|
+
without their journal record, breaking the executor’s recovery guarantees.
|
|
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 |
|
|
46
|
+
|
|
47
|
+
All five support:
|
|
48
|
+
|
|
49
|
+
- Every current tagged parameter kind.
|
|
50
|
+
- A journal and migrator lease stored in the database.
|
|
51
|
+
- An atomic update of the applied record and journal head.
|
|
52
|
+
- A recovery-required result when a commit’s outcome is uncertain.
|
|
53
|
+
|
|
54
|
+
Parameter kinds are:
|
|
37
55
|
|
|
38
|
-
|
|
39
|
-
`string
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
56
|
+
- `null` and `boolean`.
|
|
57
|
+
- `string` and `number`.
|
|
58
|
+
- `bigint` and `bytes`.
|
|
59
|
+
- `json`.
|
|
60
|
+
|
|
61
|
+
The artifact’s server, feature, transaction, and lock requirements must still
|
|
62
|
+
match the adapter.
|
|
63
|
+
|
|
64
|
+
### Unavailable profiles
|
|
43
65
|
|
|
44
66
|
These exported profiles are unavailable and must not be passed to the
|
|
45
67
|
executor:
|
|
@@ -53,6 +75,8 @@ executor:
|
|
|
53
75
|
Unavailable profiles expose `reason` and `missingCapabilities`; they do not
|
|
54
76
|
fall back to a generic executor.
|
|
55
77
|
|
|
78
|
+
### Configure libSQL inspection
|
|
79
|
+
|
|
56
80
|
For libSQL, let the migration entrypoint exclude all reserved journal objects
|
|
57
81
|
during strict inspection:
|
|
58
82
|
|
|
@@ -68,3 +92,44 @@ const adapter = libsqlMigrationAdapter(client, {
|
|
|
68
92
|
|
|
69
93
|
`DATABASE_URL` remains application configuration; neither the adapter nor CLI
|
|
70
94
|
assigns deployment-provider meaning to it.
|
|
95
|
+
|
|
96
|
+
## libSQL batch execution
|
|
97
|
+
|
|
98
|
+
Each executable artifact must contain exactly one phase and an embedded before
|
|
99
|
+
snapshot. The adapter submits its statements, SQL assertions, applied-history
|
|
100
|
+
record, head update, and terminal attempt state in one `client.migrate()` call.
|
|
101
|
+
For example, creating a table and recording that migration either both commit
|
|
102
|
+
or both roll back.
|
|
103
|
+
|
|
104
|
+
Multiple artifacts are separate batches; earlier successful
|
|
105
|
+
artifacts remain applied if a later one fails.
|
|
106
|
+
|
|
107
|
+
Preparation reads the schema in a read transaction. The submitted batch checks
|
|
108
|
+
that the catalog still matches that inspection, the lease is still owned, and
|
|
109
|
+
the head still equals the expected parent. Foreign-key validation runs before
|
|
110
|
+
commit because libSQL temporarily disables enforcement during `migrate()`.
|
|
111
|
+
|
|
112
|
+
### Supported conditions
|
|
113
|
+
|
|
114
|
+
Schema fingerprint and property preconditions are checked against the embedded
|
|
115
|
+
before snapshot. Preparation verifies its physical facts, and the batch
|
|
116
|
+
asserts that the catalog still matches.
|
|
117
|
+
|
|
118
|
+
Object-presence and scalar SQL checks run inside the batch. Postconditions
|
|
119
|
+
must use either:
|
|
120
|
+
|
|
121
|
+
- Object-presence or absence checks without fingerprints.
|
|
122
|
+
- Scalar SQL checks returning `1`.
|
|
123
|
+
|
|
124
|
+
Unsupported conditions and multiple phases are rejected.
|
|
125
|
+
|
|
126
|
+
SQL is passed to the driver without safety validation. Each program entry
|
|
127
|
+
must follow the driver’s statement contract.
|
|
128
|
+
|
|
129
|
+
### Crashes and uncertain outcomes
|
|
130
|
+
|
|
131
|
+
The database-row lease has no expiry or heartbeat. A process crash can leave
|
|
132
|
+
it held; ownership must be resolved before another runner can proceed. A lost
|
|
133
|
+
batch response is an uncertain outcome requiring journal inspection and, when
|
|
134
|
+
the attempt remains unresolved, explicit recovery. It is never assumed to be
|
|
135
|
+
a successful rollback.
|
|
@@ -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:
|
|
@@ -46,12 +48,17 @@ entrypoint:
|
|
|
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
|
+
- [Recovery and reconciliation](recovery.md): handle interrupted migrations.
|
|
58
|
+
- [Lotta Games adoption](lotta-adoption.md): review the downstream cutover
|
|
59
|
+
plan and combo-matrix release blocker.
|
|
60
|
+
|
|
61
|
+
## Select a built-in dialect
|
|
55
62
|
|
|
56
63
|
Choose the dialect-specific bootstrap entrypoint when using a built-in dialect:
|
|
57
64
|
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# Lotta Games adoption
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Move Lotta to Qubu migrations while keeping deployment decisions in Lotta.
|
|
4
4
|
|
|
5
5
|
Adopt the released `@qubu/migrate`, `@qubu/cli`, and libSQL migration entrypoint
|
|
6
6
|
as a hard cutover. Do not add an upstream decoder for Lotta's provisional JSON,
|
|
7
7
|
FNV artifact digests, journal, or broad unsafe flags.
|
|
8
8
|
|
|
9
|
+
## Establish the starting state
|
|
10
|
+
|
|
9
11
|
Before changing downstream state, inspect every environment for a provisional
|
|
10
12
|
journal or baseline row. Regenerate unreleased migrations in the Qubu artifact
|
|
11
13
|
format. For an existing database, create one standard baseline only after strict
|
|
@@ -13,6 +15,8 @@ live introspection matches the intended Qubu snapshot. That baseline records a
|
|
|
13
15
|
verified starting state; it does not claim that old migrations ran through
|
|
14
16
|
Qubu.
|
|
15
17
|
|
|
18
|
+
## Keep deployment policy in Lotta
|
|
19
|
+
|
|
16
20
|
Keep these concerns in Lotta:
|
|
17
21
|
|
|
18
22
|
- Turso credentials and environment selection;
|
|
@@ -30,10 +34,17 @@ databases with `schema bootstrap`; keep connection PRAGMAs in the test harness.
|
|
|
30
34
|
> Drizzle history. A verified baseline is the handoff from historical state to
|
|
31
35
|
> Qubu lineage.
|
|
32
36
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
## Verify the cutover
|
|
38
|
+
|
|
39
|
+
Cover these scenarios downstream:
|
|
40
|
+
|
|
41
|
+
- A fresh bootstrap.
|
|
42
|
+
- An already baselined database.
|
|
43
|
+
- A deploy with no pending migrations.
|
|
44
|
+
- Pending migrations in both deployment timing modes.
|
|
45
|
+
- Refusal when the schema has drifted.
|
|
46
|
+
- Concurrent migration attempts.
|
|
47
|
+
- Rollback and explicit recovery.
|
|
37
48
|
|
|
38
49
|
## Combo-matrix release blocker
|
|
39
50
|
|
|
@@ -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
|
|
|
@@ -72,9 +77,13 @@ working directory.
|
|
|
72
77
|
| `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
78
|
| `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
79
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
80
|
+
## Output and exit codes
|
|
81
|
+
|
|
82
|
+
JSON output has stable, recursively sorted keys and ends with a newline. It
|
|
83
|
+
redacts credential-like keys and secrets embedded in URLs. Human output is
|
|
84
|
+
brief.
|
|
85
|
+
|
|
86
|
+
Signals pass through adapters. An abort exits with code 130.
|
|
78
87
|
|
|
79
88
|
| Exit | Meaning |
|
|
80
89
|
| ---: | ----------------------------------------------------------------------------- |
|
|
@@ -94,14 +103,19 @@ snapshot. Logical IDs help reporting but do not prove equality. Objects not
|
|
|
94
103
|
owned by the managed snapshot are returned separately as `unmanagedObjects`;
|
|
95
104
|
Qubu journal objects are excluded by migration snapshot readers.
|
|
96
105
|
|
|
106
|
+
### Bootstrap a fresh database
|
|
107
|
+
|
|
97
108
|
`schema bootstrap` is for a fresh SQLite database or a fresh PostgreSQL schema.
|
|
98
109
|
It produces the same reviewed plan, versioned program, sealed artifact, and
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
110
|
+
execution path as a migration.
|
|
111
|
+
|
|
112
|
+
Database-specific behavior:
|
|
113
|
+
|
|
114
|
+
- PostgreSQL bootstrap creates standalone enums before tables that use them
|
|
115
|
+
as native column types. The complete target snapshot defines those enums.
|
|
116
|
+
- SQLite inline constraints are included in table creation. Table rebuilds
|
|
117
|
+
use explicit phases with data-copy and postcondition checks.
|
|
118
|
+
- Session settings, such as SQLite PRAGMAs, stay in application or adapter setup.
|
|
105
119
|
|
|
106
120
|
Use the reviewed complete snapshot directly as the PostgreSQL target:
|
|
107
121
|
|
|
@@ -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,29 @@ 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.
|
|
65
|
+
|
|
66
|
+
An `atomic-batch` profile instead applies one single-phase artifact in one
|
|
67
|
+
database transaction, including its checks and terminal journal writes. It
|
|
68
|
+
records a completed phase checkpoint rather than intermediate statement
|
|
69
|
+
checkpoints. See [libSQL batch execution](./adapters.md#libsql-batch-execution)
|
|
70
|
+
for its supported conditions and concurrency guards.
|
|
55
71
|
|
|
56
72
|
A second runner cannot rely on the lease alone. Atomic applied-record/head
|
|
57
73
|
advancement uses the expected parent as a compare-and-swap guard. A runner that
|
|
@@ -70,10 +86,17 @@ must be resolved by the renderer or explicit custom program before sealing.
|
|
|
70
86
|
Transactions are phase-scoped. Do not infer that an earlier committed phase
|
|
71
87
|
will roll back because a later phase fails.
|
|
72
88
|
|
|
73
|
-
Errors
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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.
|
|
77
100
|
|
|
78
101
|
Do not automatically retry after any statement may have taken effect. Only an
|
|
79
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
|
|
@@ -51,7 +54,8 @@ producer, consumer, and regression test all exist.
|
|
|
51
54
|
## Parameters are runtime data
|
|
52
55
|
|
|
53
56
|
Parameter values are not fragment metadata. A renderer calls
|
|
54
|
-
`context.parameter(value)`, and `render()` collects values in placeholder order
|
|
57
|
+
`context.parameter(value)`, and `render()` collects values in placeholder order.
|
|
58
|
+
Pass a second argument when the adapter needs the runtime SQL domain too:
|
|
55
59
|
|
|
56
60
|
```ts
|
|
57
61
|
import { and, eq, from, integer, like, render, select, table, text, where } from "qubu"
|
|
@@ -72,10 +76,34 @@ render(query)
|
|
|
72
76
|
// parameters: [7, '%Ada%']
|
|
73
77
|
```
|
|
74
78
|
|
|
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:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import { typedValue } from "qubu/core"
|
|
86
|
+
import type { SqlUuid } from "qubu"
|
|
87
|
+
|
|
88
|
+
const id = typedValue<SqlUuid, string>("108cb836-20d2-41b2-8c23-f0c94700aa7e", "uuid")
|
|
89
|
+
render(id)
|
|
90
|
+
// parameterSqlTypes: ["uuid"]
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The domain is a binding hint, not an instruction to convert the returned
|
|
94
|
+
JavaScript value. Result decoding comes from a field's `type` or an explicit
|
|
95
|
+
decoder.
|
|
96
|
+
|
|
97
|
+
Plain JavaScript values remain untyped at runtime. Use an explicit domain when
|
|
98
|
+
`Date` could mean either `DATE` or `TIMESTAMP`, or when a string is a UUID
|
|
99
|
+
rather than text.
|
|
100
|
+
|
|
75
101
|
The parameter array follows the placeholders in the rendered text. `select()`
|
|
76
102
|
normalizes independent clause values, but keep the final call in SQL order in
|
|
77
103
|
new code so source scope and repair hints are visible at a glance.
|
|
78
104
|
|
|
105
|
+
### Compose SQL templates
|
|
106
|
+
|
|
79
107
|
The public [`sql` template tag](../guides/sql-templates.md) uses the same
|
|
80
108
|
renderer. Ordinary substitutions call `context.parameter()`, while expression,
|
|
81
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"
|