`besu migrate`
besu migrate reads a directory of numbered SQL files and applies the ones the journal does
not list, in version order. With --down it reverts them instead.
--database also reads DATABASE_URL. --to is only valid with --down; clap rejects it
on its own.
Applying
An up-to-date database prints database is up to date and exits zero. A directory with no
migration files prints no migrations found in migrations and returns before connecting, so
an unreachable database is not reported in that case.
Reverting
Only the journal knows which version is "one back", so --down without --to reverts the
newest row rather than the highest file in the directory. When there is nothing to revert it
prints nothing to revert.
Down statements run from the bottom of the file up, then the journal row is deleted. Write the down file as the mirror of the up file — the inverse of each statement in the same position — and the runner undoes them back to front. See custom migrations.
What a run does
- Reads the directory into
Migrationvalues, pairing eachNNNN_name.sqlwithNNNN_name.down.sqlby version. - Creates
_besu_migrationsif it is missing, and addsdown_checksumto a journal written before that column existed. - Rejects two files with the same version.
- Verifies the checksum of every already-applied migration, up and down.
- Executes the statements of each missing migration, then inserts its journal row.
The whole run is one transaction: a failure rolls every pending migration back. On SQLite that also keeps every statement on the same connection, which a schema change needs.
Gotchas
- MySQL commits DDL implicitly. The transaction cannot roll a failed migration back there, so earlier statements of the run stay applied. PostgreSQL and SQLite roll back.
- Reverting stops at the first migration without a down file. It does not skip it and continue: the newest applied version is the one that gets undone, so an un-revertable newest migration means nothing can go back. The error names the version.
- Renaming a migration changes its checksum. The name is part of the digest, so editing the name part of an applied file is refused even if the SQL is untouched.
--tois not "migrate up to". There is no way to apply only the first few pending files; the whole pending set runs.- There is no
--dry-run. To see what would change, runbesu generateagainst a copy, orbesu push --dry-runfor the schema-level difference. - Migrations are split on
;. The splitter understands quotes and--comments, not PostgreSQL dollar-quoting or/* */blocks, so aDO $$ ... $$body is cut in the middle. Put such a body in its own file with one statement, or run it outside the runner.
