Skip to content

Drizzle: no standalone repair for a broken encrypted ALTER COLUMN migration #710

Description

@tobyhede

Follow-up to #693 (fixed in the fix/drizzle-v3-alter-column work). That change made rewriteEncryptedAlterColumns match the EQL v3 domain family and wired the sweep into stash eql migration --drizzle, which is the only v3 command that had a natural place for it. That is a bounded improvement, not a complete fix — this issue records the gap.

The sweep runs at the wrong moment

In the intended v3 flow the sweep sees an empty directory:

1. stash eql migration --drizzle   -> writes 0000_install-eql.sql, sweeps (nothing there yet)
2. edit the schema to use v3 columns
3. drizzle-kit generate            -> writes 0001 with the broken ALTER COLUMN
4. drizzle-kit migrate             -> fails

The broken migration is created at step 3, after the sweep has already run. Today the only way to get it repaired is to run stash eql migration --drizzle a second time at step 4 — which works, and is how people actually find this, but it means generating a redundant install migration to trigger an unrelated repair. The same shape applies to the v2 path (stash eql install --drizzle, install.ts step 5); this is not new to v3.

Proposal

A standalone repair that a user can run at step 4:

  • stash eql repair --drizzle (or similar), sweeping the migrations directory and reporting what it rewrote; or
  • fold the check into stash encrypt plan, which already inspects intent vs. observed state and is the command a user is likely to reach for next.

Either removes the need to regenerate an install migration to get the repair.

Known hazard to handle in the design

The sweep is unfiltered — it rewrites any matching file regardless of whether it has already been applied. That is safe for essentially every match, because a matching statement is un-runnable by construction (Postgres rejects both the mangled "undefined"."eql_v3_*" form and the valid-looking bare form, since there is no cast from text/numeric to an EQL domain), so the migration failed on apply and is unapplied.

The exception: a jsonb column changed to a v3 domain coerces successfully, so that migration can be applied. Rewriting it afterwards changes the file's hash, and drizzle-kit migrate would then treat it as unapplied and re-run an ADD/DROP/RENAME sequence against a table already in the target shape.

Narrow, and pre-existing in the v2 sweep, but a standalone repair command is the right place to fix it — it can consult the drizzle journal (and, given --database-url, __drizzle_migrations) and refuse to touch an applied migration, which the offline migration-first path cannot.

Notes

An ordering filter (only sweep entries after the install migration) was considered and rejected: whether the broken migration sorts before or after the install migration depends on when each was generated, so the filter would suppress the repair in exactly the recovery path above.

Metadata

Metadata

Assignees

Labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions