You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 99bd27c
Browse filesBrowse the repository at this point in the historyBrowse files
fix(migrate): D1/SQLite verify no longer reports false schema drift
meta verify --dialect d1 reported permanent, unfixable schema drift for a
hand-migrated D1/SQLite database that genuinely matches its metadata, because the
shared sqlite/d1 diff path compared distinctions SQLite cannot physically store.
Four fixes, scoped to sqlite/d1 (Postgres unchanged):
- Type canon: on sqlite/d1, collapse json->text and drop text maxLength before
comparing (a hand-written bare TEXT column IS the maxLength'd / jsonb one — SQLite
stores neither). Also stops meta migrate emitting a no-op change for a
metadata-only maxLength change on sqlite.
- Anonymous CHECK reconciliation: introspection parses unnamed inline CHECK(...)
(masking comments + string literals so a CHECK( inside them is never mis-parsed),
and the diff matches a modeled named check to an actual by normalized expression on
sqlite/d1. Comma spacing in an IN(...) list is normalized outside literals only.
- Bare-NULL default: the D1/wrangler runner stringifies SQL NULL to "null", read as a
literal default on every no-default column (permanent, destructive-recreate false
drift). A bare null/NULL is now no default; a quoted 'null' stays a literal.
Gated by a new sqlite-hand-migrated-verify integration test + parseSqliteChecks /
normalizeCheckExpr unit gates (598 pass). An adversarial review caught two regressions
(a literal-unaware comma-collapse hiding regex/predicate drift; the relaxed CHECK
finder matching inside comments/literals) — both fixed + pinned.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014xy8powhHYJ6gfFt9Ut8dL
`meta verify --dialect d1` reported permanent, unfixable schema drift for a
13
+
hand-migrated D1/SQLite database whose schema genuinely matches its metadata,
14
+
because the shared sqlite/d1 diff path compared distinctions SQLite cannot
15
+
physically represent. Four fixes, all scoped to sqlite/d1 (Postgres behavior
16
+
unchanged) and gated by a new `sqlite-hand-migrated-verify` integration test plus
17
+
`parseSqliteChecks` / `normalizeCheckExpr` unit gates:
18
+
19
+
-**`json` and `VARCHAR(N)` length no longer read as drift.** SQLite/D1 has one text
20
+
storage class — a `field.object @storage:jsonb` column is stored as `TEXT`, and a
21
+
`VARCHAR(N)` length is cosmetic (not enforced). A hand-written bare `TEXT` column is
22
+
the same physical column as the maxLength'd / jsonb one, so the diff now canonicalizes
23
+
`json→text` and drops text `maxLength` on sqlite/d1 before comparing. This also
24
+
corrects `meta migrate`: a metadata-only `maxLength` change on sqlite/d1 now emits no
25
+
migration — nothing physical changes in SQLite.
26
+
-**Anonymous inline `CHECK (…)` constraints now reconcile.** Hand-written migrations
27
+
write unnamed inline checks; introspection parses them (previously skipped, and now
28
+
with a mask so a `CHECK (` inside a comment or string literal is never mis-parsed) and
29
+
the diff matches a modeled named check against an actual check by normalized expression
30
+
on sqlite/d1, so an already-enforced constraint is no longer re-proposed as add-check.
31
+
Comma spacing in an `IN (…)` list is normalized *outside string literals only*
32
+
(`'a', 'b'` == `'a','b'`, but a comma inside a literal/regex stays significant).
33
+
-**A bare `NULL` default is now no default.** The D1/wrangler runner stringifies a SQL
34
+
`NULL``dflt_value` to the string `"null"`, which was read as a literal default on
35
+
every no-default column — permanent (and, on SQLite/D1, destructive recreate-and-copy)
36
+
false drift on every `verify`/`migrate`. `DEFAULT NULL` is equivalent to no default; a
37
+
quoted `'null'` stays a genuine string literal.
38
+
10
39
## [0.20.1] — 2026-07-25
11
40
12
41
**npm `0.20.1`** (patch; NuGet 0.19.3 / PyPI 0.19.5 / Maven 7.11.3 unchanged). `meta init` quickstart polish: the post-init next-steps no longer lists the working `meta gen` / `meta docs` under "ship in later sub-projects" (only `ingest`/`serve`/`install-hooks` are unshipped), and `meta init` now scaffolds a minimal root `.gitignore` (node_modules/, *.sqlite, dist/) when the project has none, so a `git add -A` right after init does not stage node_modules or a local dev DB. No API or codegen-output change.
0 commit comments