qubu 0.6.2 → 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/mysql.d.mts +1 -1
- package/dist/postgres.d.mts +1 -1
- 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 +47 -19
- 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 +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
|
@@ -60,9 +60,11 @@ each item a stable application name in the constraints or indexes record. The
|
|
|
60
60
|
record key becomes `constraint.id` or `index.id`. Qubu resolves `physicalName` from
|
|
61
61
|
the explicit option or the version-one snake_case policy.
|
|
62
62
|
|
|
63
|
-
Index terms may use `asc()` or `desc()`. Set
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
Index terms may use `asc()` or `desc()`. Set these options as needed:
|
|
64
|
+
|
|
65
|
+
- `unique: true` creates a unique index.
|
|
66
|
+
- `where` supplies a partial-index predicate.
|
|
67
|
+
- `include` lists columns stored in the index payload but not used as key terms.
|
|
66
68
|
|
|
67
69
|
## Distinguish candidate keys from unique constraints
|
|
68
70
|
|
|
@@ -100,8 +102,11 @@ same length and matching known `SqlSemanticType` identities. `SqlUnknown` cannot
|
|
|
100
102
|
prove a foreign-key match.
|
|
101
103
|
|
|
102
104
|
The target tuple must exactly match a primary key, unique() constraint, or
|
|
103
|
-
eligible unique index.
|
|
104
|
-
|
|
105
|
+
eligible unique index. These options record database behavior as metadata:
|
|
106
|
+
|
|
107
|
+
- `onUpdate` and `onDelete`.
|
|
108
|
+
- `match`.
|
|
109
|
+
- `deferrable` and `initially`.
|
|
105
110
|
|
|
106
111
|
```ts
|
|
107
112
|
const memberships = table("memberships", { accountId: integer() }, (memberships) => ({
|
|
@@ -118,6 +123,8 @@ const memberships = table("memberships", { accountId: integer() }, (memberships)
|
|
|
118
123
|
Use the preliminary callback table for direct self-references. Wrap the target
|
|
119
124
|
in a function when two modules import each other's tables.
|
|
120
125
|
|
|
126
|
+
### Restrictions on schema expressions
|
|
127
|
+
|
|
121
128
|
Checks, index expressions, and partial-index predicates may read only columns
|
|
122
129
|
from their callback table. They cannot contain aggregates, window functions, or
|
|
123
130
|
subqueries. Check expressions and partial predicates must have the boolean SQL
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# DDL emission
|
|
2
2
|
|
|
3
|
-
> Preview
|
|
3
|
+
> Preview the SQL for a migration plan before preparing it for execution.
|
|
4
4
|
|
|
5
5
|
The `@qubu/migrate/ddl` entrypoint accepts only a `MigrationPlan` and a `SchemaDialect`.
|
|
6
6
|
It does not read a catalog, open a connection, start a transaction, or write a
|
|
@@ -22,8 +22,13 @@ for (const statement of result.statements) {
|
|
|
22
22
|
}
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
`statements`
|
|
26
|
-
|
|
25
|
+
`statements` contains the SQL preview in dependency order. Each statement has:
|
|
26
|
+
|
|
27
|
+
- Its operation ID.
|
|
28
|
+
- Its position in that order.
|
|
29
|
+
- SQL text.
|
|
30
|
+
- An ordered parameter list.
|
|
31
|
+
|
|
27
32
|
Schema literals and expressions are parameter-free by contract. `sql` joins
|
|
28
33
|
the statements with a newline and adds a semicolon for migration-file writers.
|
|
29
34
|
|
|
@@ -31,12 +36,16 @@ the statements with a newline and adds a semicolon for migration-file writers.
|
|
|
31
36
|
|
|
32
37
|
The emitter rejects a plan with `ready: false`, `decision-required` operations,
|
|
33
38
|
unknown or lossy facts, unsupported safety, or destructive changes unless the
|
|
34
|
-
caller supplies the matching explicit option.
|
|
39
|
+
caller supplies the matching explicit option.
|
|
40
|
+
|
|
41
|
+
`allowUnsafe` is available for
|
|
35
42
|
preview integrations, but it is not accepted as an artifact approval and does
|
|
36
43
|
not make an opaque object renderable. Opaque and deferred catalog records need
|
|
37
44
|
an explicit tagged `custom-sql` operation for preview and an operation-scoped
|
|
38
45
|
custom program for sealed execution.
|
|
39
46
|
|
|
47
|
+
### Check execution requirements
|
|
48
|
+
|
|
40
49
|
Lock and transaction requirements describe what a later executor must provide.
|
|
41
50
|
Pass `lock` or `transaction` to preflight those requirements against the
|
|
42
51
|
executor's context. A required transaction with `transaction: 'autocommit'`
|
|
@@ -74,7 +83,9 @@ an inline constraint declaration or an explicit rebuild/custom-SQL operation.
|
|
|
74
83
|
Custom SQL stays opaque and appears at its plan position. The emitter does not
|
|
75
84
|
inspect it for object names or infer SQL from an opaque catalog record.
|
|
76
85
|
|
|
77
|
-
|
|
86
|
+
## Prepare for execution
|
|
87
|
+
|
|
88
|
+
For execution, compile the plan with `compileMigrationProgram()` from
|
|
78
89
|
`@qubu/migrate/artifact`. The versioned program—not the aggregate `sql`
|
|
79
90
|
string—is authoritative. See [Artifacts and approval
|
|
80
91
|
policy](../migrations/artifacts-and-policy.md).
|
package/docs/schema/diff.md
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
# Snapshot diffing
|
|
2
2
|
|
|
3
|
-
> Compare
|
|
3
|
+
> Compare two snapshots and review changes before planning a migration.
|
|
4
4
|
|
|
5
5
|
The optional `qubu/diff` entrypoint compares immutable snapshot data. It does
|
|
6
|
-
not
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
not access a database or execute changes. Each result keeps the information
|
|
7
|
+
needed to review it:
|
|
8
|
+
|
|
9
|
+
- Object kind and namespace.
|
|
10
|
+
- Logical ID and physical name.
|
|
11
|
+
- Dialect and path.
|
|
12
|
+
- Catalog evidence.
|
|
9
13
|
|
|
10
14
|
```ts
|
|
11
15
|
import { diffSnapshots } from "qubu/diff"
|
|
@@ -17,6 +21,8 @@ for (const change of result.changes) {
|
|
|
17
21
|
}
|
|
18
22
|
```
|
|
19
23
|
|
|
24
|
+
## How objects are matched
|
|
25
|
+
|
|
20
26
|
The matcher first uses an explicit rename hint, then a stable logical ID. A
|
|
21
27
|
physical-name change for a stable match is a `physical-rename` operation. Other
|
|
22
28
|
matched fields become `property-change` operations. Unmatched records remain
|
|
@@ -61,6 +67,8 @@ classification. Opaque and deferred Snapshot v1 records remain visible as
|
|
|
61
67
|
`add` or `remove` data and produce `lossy` or `unsupported` diagnostics. They
|
|
62
68
|
cannot be silently promoted to a rename.
|
|
63
69
|
|
|
70
|
+
### Equality and ordering
|
|
71
|
+
|
|
64
72
|
`result.equal` means that no diff operation was emitted. A result can therefore
|
|
65
73
|
be equal while still carrying a warning about an unchanged opaque record. The
|
|
66
74
|
diagnostics remain part of the review boundary.
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
# Database introspection
|
|
2
2
|
|
|
3
|
-
> Read
|
|
3
|
+
> Read an existing database schema and turn it into a Qubu snapshot.
|
|
4
4
|
|
|
5
5
|
Database introspection is an optional capability exported from
|
|
6
6
|
`qubu/introspection`. It discovers database facts; it does not recreate the
|
|
7
|
-
original TypeScript declarations.
|
|
7
|
+
original TypeScript declarations.
|
|
8
|
+
|
|
9
|
+
Planning and DDL emission use the separate
|
|
8
10
|
`@qubu/migrate/plan` and `@qubu/migrate/ddl` entrypoints, while migration
|
|
9
|
-
execution remains application-owned.
|
|
11
|
+
execution remains application-owned.
|
|
12
|
+
|
|
13
|
+
The separate
|
|
10
14
|
`qubu/codegen` entrypoint can create a new machine-owned schema module from a
|
|
11
15
|
complete Snapshot v1 result.
|
|
12
16
|
|
|
@@ -32,9 +36,12 @@ continuity, and strict versus lossy output.
|
|
|
32
36
|
|
|
33
37
|
## Supply a connection
|
|
34
38
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
Adapt your existing driver to `CatalogConnection`. Your application handles:
|
|
40
|
+
|
|
41
|
+
- Opening and closing connections.
|
|
42
|
+
- Driver selection and connection pools.
|
|
43
|
+
- Authentication.
|
|
44
|
+
- Retries and transactions.
|
|
38
45
|
|
|
39
46
|
```ts
|
|
40
47
|
import type { CatalogConnection } from "qubu/introspection"
|
|
@@ -127,6 +134,8 @@ generated expressions, checks, predicates, and expression index terms remain
|
|
|
127
134
|
dialect-tagged SQL. Falsy values such as `0`, `false`, `NULL`, and empty
|
|
128
135
|
strings are preserved.
|
|
129
136
|
|
|
137
|
+
### References and dialect metadata
|
|
138
|
+
|
|
130
139
|
References to nested columns, constraints, and indexes include their owning
|
|
131
140
|
table, view, or domain in the complete Snapshot v1 output. References to
|
|
132
141
|
top-level objects remain unscoped, and table-local backing relationships must
|
|
@@ -135,21 +144,34 @@ native storage, and typed expressions are checked against the selected
|
|
|
135
144
|
snapshot dialect; arbitrary catalog `data` and `configuration` JSON remains
|
|
136
145
|
opaque.
|
|
137
146
|
|
|
138
|
-
PostgreSQL
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
147
|
+
## PostgreSQL catalog support
|
|
148
|
+
|
|
149
|
+
PostgreSQL readers expose typed catalog records for:
|
|
150
|
+
|
|
151
|
+
- Views and materialized views.
|
|
152
|
+
- Sequences, enums, and domains.
|
|
153
|
+
- Collations.
|
|
154
|
+
- Routines and triggers.
|
|
155
|
+
- Policies and partitions.
|
|
156
|
+
- Extensions.
|
|
157
|
+
- Comments and ownership.
|
|
158
|
+
|
|
159
|
+
`mapCatalogToCompleteSnapshot()` retains those records in Snapshot v1.
|
|
160
|
+
`mapCatalogToSnapshot()` uses the same complete mapping and keeps each object
|
|
161
|
+
as its own kind.
|
|
162
|
+
|
|
163
|
+
If a PostgreSQL catalog row lacks the evidence needed for safe normalization,
|
|
164
|
+
the reader retains a deferred or opaque record and emits a diagnostic.
|
|
165
|
+
|
|
166
|
+
## SQLite catalog support
|
|
146
167
|
|
|
147
168
|
SQLite readers expose recoverable views and triggers as typed complete records.
|
|
148
169
|
They retain virtual and shadow tables as deferred objects, and keep attached
|
|
149
170
|
databases outside the selected namespace as opaque boundary records. SQLite
|
|
150
171
|
declared types, derived affinity, generated expressions, rowid identity, and
|
|
151
|
-
`AUTOINCREMENT` stay tagged with SQLite dialect metadata.
|
|
152
|
-
|
|
172
|
+
`AUTOINCREMENT` stay tagged with SQLite dialect metadata.
|
|
173
|
+
|
|
174
|
+
When an attached database is selected, table PRAGMAs may be visible but CREATE SQL remains
|
|
153
175
|
limited to the fixed `main` and `temp` catalog statements, so the reader marks
|
|
154
176
|
the catalog visibility as limited instead of combining namespaces.
|
|
155
177
|
|
|
@@ -191,11 +213,15 @@ MySQL families and their opaque or deferred boundaries.
|
|
|
191
213
|
|
|
192
214
|
## Diagnostics and safety
|
|
193
215
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
216
|
+
Each diagnostic includes:
|
|
217
|
+
|
|
218
|
+
- Severity and a stable code.
|
|
219
|
+
- A catalog path.
|
|
220
|
+
- A physical reference, when available.
|
|
221
|
+
- A hint for fixing the problem.
|
|
222
|
+
|
|
223
|
+
Codes distinguish connection failures and permission limits from unsupported
|
|
224
|
+
features or incomplete mappings.
|
|
199
225
|
|
|
200
226
|
Introspection is read-only from Qubu's perspective. Do not pass credentials or
|
|
201
227
|
DSNs through diagnostic fields. Keep driver-specific error text in the
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
# Migration plans
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Turn a reviewed schema diff into an ordered migration plan.
|
|
4
4
|
|
|
5
|
-
The `@qubu/migrate/plan` entrypoint
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
The `@qubu/migrate/plan` entrypoint takes a resolved `SnapshotDiff` and returns
|
|
6
|
+
an immutable plan. Each operation records:
|
|
7
|
+
|
|
8
|
+
- Its ID and path.
|
|
9
|
+
- Evidence for logical and physical identities.
|
|
10
|
+
- Dependencies and preconditions.
|
|
11
|
+
- Safety classification.
|
|
12
|
+
- Lock and transaction requirements.
|
|
13
|
+
- Whether the change can be reversed.
|
|
9
14
|
|
|
10
15
|
```ts
|
|
11
16
|
import { createMigrationPlan } from "@qubu/migrate/plan"
|
|
@@ -16,8 +21,9 @@ if (!result.ok) {
|
|
|
16
21
|
}
|
|
17
22
|
```
|
|
18
23
|
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
The planner only returns data. It does not access the database or render SQL.
|
|
25
|
+
|
|
26
|
+
A physical rename remains a
|
|
21
27
|
`physical-rename` operation; it is never represented as custom SQL or silently
|
|
22
28
|
changed into a drop and add.
|
|
23
29
|
|
|
@@ -64,9 +70,11 @@ extracts SQL from opaque catalog payloads.
|
|
|
64
70
|
|
|
65
71
|
## Ordering and validation
|
|
66
72
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
73
|
+
The planner creates parents before children and removes children before
|
|
74
|
+
parents. It also orders operations by their references and explicit custom-SQL
|
|
75
|
+
dependencies. The same inputs produce the same order.
|
|
76
|
+
|
|
77
|
+
`encodeMigrationPlan()` emits canonical JSON;
|
|
70
78
|
`decodeMigrationPlan()` and `validateMigrationPlan()` reject unknown fields,
|
|
71
79
|
future versions, malformed operations, missing edges, and dependency cycles.
|
|
72
80
|
|
package/docs/schema/snapshots.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Canonical schema snapshots
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Save a schema as versioned data that you can compare and check into source control.
|
|
4
4
|
|
|
5
5
|
Qubu's schema tooling lives behind the `qubu/snapshot` entrypoint. It converts
|
|
6
6
|
an immutable `schema()` registry into versioned data that can be inspected,
|
|
@@ -14,21 +14,33 @@ const snapshot = createSchemaSnapshot(appSchema)
|
|
|
14
14
|
const json = encodeSchemaSnapshot(snapshot)
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
## What a snapshot contains
|
|
18
|
+
|
|
19
|
+
The Snapshot v1 envelope contains:
|
|
20
|
+
|
|
21
|
+
- A format version.
|
|
22
|
+
- An independently versioned dialect extension.
|
|
23
|
+
- A versioned naming-policy description.
|
|
24
|
+
- A namespace.
|
|
25
|
+
- Supported-capability facts.
|
|
26
|
+
- Arrays for each supported object family.
|
|
27
|
+
|
|
28
|
+
Tables, columns, constraints, and indexes are sorted by stable logical ID. Physical
|
|
21
29
|
names are values in the snapshot, not identities:
|
|
22
30
|
changing a physical name does not change the TypeScript field or metadata key.
|
|
23
31
|
|
|
24
|
-
Snapshot
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
expressions through the standard schema context; a dialect adapter may replace
|
|
32
|
+
Snapshot expressions are data records without parameters. Decoding does not
|
|
33
|
+
create executable table or column objects, or rendering functions.
|
|
34
|
+
|
|
35
|
+
The neutral fallback renders branded built-in expressions through the standard schema context; a dialect adapter may replace
|
|
28
36
|
that hook with its own literal and expression policy. An explicitly unsafe
|
|
29
37
|
expression retains its dialect tag and is rejected when it does not match the
|
|
30
38
|
selected snapshot dialect.
|
|
31
39
|
|
|
40
|
+
## Decode and validate a snapshot
|
|
41
|
+
|
|
42
|
+
Use `decodeSchemaSnapshot()` to read saved JSON and inspect validation failures:
|
|
43
|
+
|
|
32
44
|
```ts
|
|
33
45
|
import { decodeSchemaSnapshot } from "qubu/snapshot"
|
|
34
46
|
|
|
@@ -46,6 +58,8 @@ dialect metadata, and broken foreign-key or column references as structured
|
|
|
46
58
|
diagnostics. It does not call `process.exit()` and has no runtime validation
|
|
47
59
|
library dependency.
|
|
48
60
|
|
|
61
|
+
### References and ownership
|
|
62
|
+
|
|
49
63
|
References to nested columns, constraints, and indexes carry an explicit
|
|
50
64
|
`owner: { kind, id }` scope. Table columns, constraints, and indexes are owned
|
|
51
65
|
by their table; view columns are owned by their view; and domain constraints
|
|
@@ -55,6 +69,8 @@ checked only in typed snapshot fields. Extension `data`, `configuration`, and
|
|
|
55
69
|
other opaque JSON payloads are retained as data and are not interpreted as
|
|
56
70
|
typed metadata.
|
|
57
71
|
|
|
72
|
+
### Content fingerprints
|
|
73
|
+
|
|
58
74
|
`schemaSnapshotFingerprint()` computes a deterministic content fingerprint from canonical
|
|
59
75
|
JSON. The fingerprint is useful for cache keys and fixture assertions only. It is not
|
|
60
76
|
an entity identity, a rename marker, or migration lineage.
|
|
@@ -69,15 +85,23 @@ and advertised capabilities while adding schema encoders and validation under
|
|
|
69
85
|
second query dialect. The schema snapshot format version remains independent
|
|
70
86
|
from the dialect identity.
|
|
71
87
|
|
|
72
|
-
The
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
88
|
+
The shared serializer handles:
|
|
89
|
+
|
|
90
|
+
- Logical IDs and fixed property order.
|
|
91
|
+
- Canonical sorting and portable constraints.
|
|
92
|
+
- Cross-reference checks.
|
|
93
|
+
- The immutable snapshot envelope.
|
|
94
|
+
|
|
95
|
+
A dialect adapter handles:
|
|
96
|
+
|
|
97
|
+
- Physical storage mapping.
|
|
98
|
+
- SQL literal and expression encoding.
|
|
99
|
+
- Dialect extensions and capability checks.
|
|
100
|
+
- Any dialect-specific naming policy.
|
|
101
|
+
|
|
102
|
+
PostgreSQL, SQLite, and MySQL adapters can implement `SchemaSnapshotAdapter`
|
|
103
|
+
without duplicating traversal or decoder rules. Import built-in adapters from
|
|
104
|
+
their dedicated subpaths:
|
|
81
105
|
|
|
82
106
|
```ts
|
|
83
107
|
import { createSchemaSnapshot } from "qubu/snapshot"
|
|
@@ -97,17 +121,21 @@ matrix](../reference/mysql-snapshot.md). Its query and snapshot dialects both
|
|
|
97
121
|
use `mysql`, while MySQL-only `ON UPDATE` and `AUTO_INCREMENT` details remain
|
|
98
122
|
inside the column and identity metadata they describe.
|
|
99
123
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
optional `qubu/introspection` entrypoint can produce
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
124
|
+
## Use a snapshot in later steps
|
|
125
|
+
|
|
126
|
+
The optional `qubu/introspection` entrypoint can produce Snapshot v1 data from
|
|
127
|
+
a catalog connection you provide. The [catalog model](catalog-model.md)
|
|
128
|
+
describes the complete-snapshot APIs.
|
|
129
|
+
|
|
130
|
+
A snapshot then passes through separate steps:
|
|
131
|
+
|
|
132
|
+
1. Diffing compares Snapshot v1 values.
|
|
133
|
+
2. Migration planning uses the resolved diff.
|
|
134
|
+
3. DDL emission renders an approved plan.
|
|
135
|
+
|
|
136
|
+
These steps return data without accessing the database. The
|
|
137
|
+
[ownership map](../reference/supported-surface.md#ownership-boundary) explains
|
|
138
|
+
how they connect to application-owned execution.
|
|
111
139
|
|
|
112
140
|
The optional [schema source generator](code-generation.md) consumes a complete,
|
|
113
141
|
non-lossy introspection result and makes its generated schema the next identity
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
# Storage and schema SQL
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Describe database storage types and write expressions for schema definitions.
|
|
4
4
|
|
|
5
5
|
## Keep application and SQL types separate
|
|
6
6
|
|
|
7
|
-
A column can
|
|
8
|
-
|
|
7
|
+
A column can describe four different things:
|
|
8
|
+
|
|
9
|
+
- Its application value type.
|
|
10
|
+
- Its SQL semantic domain, which controls compatible operations.
|
|
11
|
+
- Its physical database storage type.
|
|
12
|
+
- Its target type when used in a cast.
|
|
9
13
|
|
|
10
14
|
For example, `numeric()` decodes to a TypeScript number, carries `SqlDecimal`,
|
|
11
15
|
uses portable numeric storage, and has a logical decimal cast target. Read
|
|
@@ -45,7 +49,9 @@ const accounts = table("accounts", {
|
|
|
45
49
|
`nativeStorage()` preserves the declaration text and freezes the descriptor. The
|
|
46
50
|
`ColumnStorageOf`, `ColumnStorageTypeOf`, `ColumnStorageDialectOf`, and
|
|
47
51
|
`ColumnStorageDeclarationOf` helpers read its metadata. Native storage is
|
|
48
|
-
descriptive.
|
|
52
|
+
descriptive.
|
|
53
|
+
|
|
54
|
+
The optional `sqlType` field is the runtime semantic domain passed
|
|
49
55
|
to adapters; provide it for custom domains because the compile-time SQL type is
|
|
50
56
|
not available at runtime. It does not change selection, mutation, or query
|
|
51
57
|
rendering.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Tables and names
|
|
2
2
|
|
|
3
|
-
> Define
|
|
3
|
+
> Define tables and control how TypeScript field names map to database names.
|
|
4
4
|
|
|
5
5
|
`table()` definitions describe the columns Qubu can select and write. They are
|
|
6
6
|
not database introspection and they do not create or migrate a database.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SQL semantic types
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Understand which SQL operations a column supports, even when its JavaScript type looks the same as another column’s.
|
|
4
4
|
|
|
5
5
|
Qubu tracks four independent facts for a field or result expression:
|
|
6
6
|
|
|
@@ -11,7 +11,7 @@ Qubu tracks four independent facts for a field or result expression:
|
|
|
11
11
|
| Nullability | Can the selected value be `null`? | `false` |
|
|
12
12
|
| SQL domain | Which portable SQL operations may consume the expression? | `SqlText` or `SqlUuid` |
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
These facts are separate. Both `text()` and `uuid()` decode to a
|
|
15
15
|
JavaScript `string`, but their SQL behavior differs. Likewise, two
|
|
16
16
|
`timestamp()` definitions may share `SqlTimestamp` while a custom column uses
|
|
17
17
|
different JavaScript output and write types for its driver.
|
|
@@ -111,12 +111,15 @@ target is vendor-specific.
|
|
|
111
111
|
|
|
112
112
|
## Known incompatibility is rejected
|
|
113
113
|
|
|
114
|
-
Qubu
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
114
|
+
When Qubu knows both SQL domains, it checks these rules:
|
|
115
|
+
|
|
116
|
+
- Arithmetic and `SUM`/`AVG` require numeric-like expressions.
|
|
117
|
+
- Text functions, concatenation, and pattern matching (`LIKE` or `ILIKE`)
|
|
118
|
+
require text-like expressions.
|
|
119
|
+
- Ordering and range comparisons require compatible ordering groups.
|
|
120
|
+
- Equality comparisons and `IN` require compatible equality groups. The same
|
|
121
|
+
rule applies to `CASE`, `COALESCE`, and set-operation fields.
|
|
122
|
+
- Boolean clauses require a boolean SQL domain.
|
|
120
123
|
|
|
121
124
|
These checks model portable capability and group relationships, not every
|
|
122
125
|
database's implicit casts. An expression accepted by one database after an
|
package/docs/troubleshooting.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Troubleshooting
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Find a common error, check its cause, and fix the query.
|
|
4
4
|
|
|
5
5
|
## Column is not available in this query scope
|
|
6
6
|
|
|
@@ -73,9 +73,13 @@ driver that expects `?` placeholders.
|
|
|
73
73
|
## Read and repair query diagnostics
|
|
74
74
|
|
|
75
75
|
Type-level query failures carry stable properties in the diagnostic type, and
|
|
76
|
-
runtime authoring failures throw `QueryValidationError`.
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
runtime authoring failures throw `QueryValidationError`. Check these fields
|
|
77
|
+
before changing the query:
|
|
78
|
+
|
|
79
|
+
- `code`: the kind of error.
|
|
80
|
+
- `context`: where the error occurred.
|
|
81
|
+
- `path`: the clause or field that needs attention.
|
|
82
|
+
- `hint`: how to fix it.
|
|
79
83
|
|
|
80
84
|
```ts
|
|
81
85
|
import { QueryValidationError, fetchFirst } from "qubu"
|
|
@@ -130,8 +134,12 @@ Verify all three opt-ins:
|
|
|
130
134
|
3. TypeScript includes `qubu/globals` in its `types` list or includes the
|
|
131
135
|
declaration explicitly.
|
|
132
136
|
|
|
133
|
-
The transform skips
|
|
134
|
-
|
|
137
|
+
The transform skips:
|
|
138
|
+
|
|
139
|
+
- Non-script files.
|
|
140
|
+
- Dependencies under `node_modules`.
|
|
141
|
+
- Files excluded by filters.
|
|
142
|
+
- Modules that reference no eligible Qubu global.
|
|
135
143
|
|
|
136
144
|
## Parameters are in an unexpected order
|
|
137
145
|
|