Skip to content

Change your schema

tablewalk migrate changes the database with versioned SQL files, and checks the App against the schema they make.

Terminal window
npx tablewalk migrate new add_payoff_quote --app . # writes migrations/V2__add_payoff_quote.sql
npx tablewalk check --app . --pending # the App against the schema to come
npx tablewalk migrate up --app . # apply, regenerate the types, check
  • V2__add_payoff_quote.sql runs once, in version order, in its own transaction with its history row: applied and recorded, or neither. Forward only. R__views.sql runs after them, again whenever it changes.
  • They live in migrations/ in the App, or the connection’s "migrations": { "dir": "db/migrations" } in tablewalk.json, or --migrations. A V3__index.sql.conf saying executeInTransaction=false runs a PostgreSQL file outside a transaction (CREATE INDEX CONCURRENTLY).
  • MySQL commits DDL as it runs: a failure there stops the run and is recorded; finish or undo it by hand, then repair.
Command What it does
new <name> The next V file (--repeatable: an R__ one).
up Applies what is pending (--dry-run prints the SQL). With --app, then regenerates tablewalk-schema.d.ts and runs tablewalk check, which names the view, page or command a dropped or renamed column breaks (exit 4).
status Applied, pending, drift, and whether the App’s types are older than the database.
validate Exit 2 unless nothing is changed, missing, failed or pending and there is no drift.
baseline Records an existing database as version 0.
repair Removes failed entries, accepts changed files, marks missing ones deleted.

check --pending applies the pending files to a scratch copy — of the SQLite file, or on PostgreSQL CREATE DATABASE … TEMPLATE, which needs CREATEDB and nobody else connected — and judges the App against it. A run holds a lock (PostgreSQL’s advisory lock, the one Flyway takes; MySQL’s GET_LOCK; SQLite’s write lock), so two deploys never migrate at once.

Terminal window
npx tablewalk migrate baseline --app .
# Recorded ops as version 0: 41 tables, 388 objects in all. Nothing in it was changed.
# wrote migrations/baseline.schema.json (read-only, never run)

Nothing that existed is touched, and up refuses a database with tables and no history until it is baselined. The run owns only the schemas the App’s sources use (or the connection’s "schemas", or --schema), never tablewalk’s own __tablewalk_* tables.

Terminal window
npx tablewalk migrate status --app .
# Drift: 2 changes made outside migrations since they last ran. Adopt each in a migration, or undo it:
# + column public.loan.note text (added outside migrations)
# - index public.loan.loan_status_idx (dropped outside migrations)

A migration that changes or names the object settles it (ADD COLUMN IF NOT EXISTS note); one that leaves it alone keeps it drift.

The names, checksums and history layout are Flyway’s, so a team can switch either way. The history table is __tablewalk_schema_history, never another team’s; to take over from Flyway, name theirs (--history-table flyway_schema_history). --tool flyway runs a command with an installed Flyway (on the PATH, or TABLEWALK_FLYWAY) over the same files and history.