[SQLite]: Skip blank statement chunks and reject empty migrations - #6208
Open
jsiu93 wants to merge 1 commit into
Open
[SQLite]: Skip blank statement chunks and reject empty migrations#6208jsiu93 wants to merge 1 commit into
jsiu93 wants to merge 1 commit into
Conversation
Breakpoint splitting and hand-edited migration files can leave whitespace-only chunks, and a `drizzle-kit generate --custom` placeholder is blank until it is filled in. Passing those to SQLite drivers aborts the migration: better-sqlite3 throws a RangeError, while expo-sqlite can crash in native code (expo/expo#49066). Drop whitespace-only chunks before running a migration in both the sync and async SQLite migrators. A migration with nothing left to run now fails with a DrizzleError naming its timestamp instead of being recorded as applied, so a forgotten custom placeholder cannot slip past silently. The better-sqlite3 regression tests cover a trailing breakpoint (applied and recorded) and an empty placeholder (rejected, transaction rolled back). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jsiu93
force-pushed
the
fix/sqlite-migrator-skip-blank-statements
branch
from
August 29, 2026 22:53
8e54a81 to
a45d8f2
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Migration SQL is split on
--> statement-breakpointand each chunk is executed as-is. Hand-edited files can leave a whitespace-only chunk (for example a trailing breakpoint), and adrizzle-kit generate --customplaceholder is blank until it is filled in. SQLite drivers do not agree on what to do with an empty statement: better-sqlite3 throwsRangeError: The supplied SQL string contains no statements, libsql and sql-js accept it, and expo-sqlite crashes in native code (expo/expo#49066). On the strict drivers the migration transaction never completes, and on Expo the app dies before any JS error surfaces.Closes #6207.
How
SQLiteSyncDialect.migrateandSQLiteAsyncDialect.migratenow take their statements from a sharedmigrationStatements()helper insqlite-core/dialect.ts:DrizzleErrornaming its timestamp, so the transaction rolls back and the migration is not recorded. A forgotten custom placeholder therefore fails loudly with one readable error on every driver instead of a driver-specific RangeError or a native crash, and it cannot be marked as applied.Hash bookkeeping and the
__drizzle_migrationsinsert are unchanged. The filter lives insqlite-corerather than in each driver'sreadMigrationFiles, so every SQLite driver (better-sqlite3, bun, libsql, sql-js, d1, durable objects, expo, op-sqlite, proxy) gets the same behaviour from one place.Tests
Two new cases in
integration-tests/tests/sqlite/better-sqlite.test.ts:migrator skips blank statement chunks(fixturedrizzle2/sqlite-blank-statements/, trailing breakpoint): applies and records the migration. Fails onmainwith the RangeError above.migrator rejects a migration with no statements(fixturedrizzle2/sqlite-empty-migration/, single-newline custom migration): throwscontains no SQL statements, no table created, no migration recorded.Run locally (no Docker):
better-sqlite137 passed,sql-js137 passed,libsql-sqlite3138 passed. The Docker-backed Postgres and MySQL suites were not run; the change only touchessqlite-core.