Skip to content

feat(cli): wheels migrate rename-system-tables (F15 Phase 2)#2403

Merged
bpamiri merged 1 commit into
developfrom
claude/fresh-vm-batch-k-f15-phase2
May 1, 2026
Merged

feat(cli): wheels migrate rename-system-tables (F15 Phase 2)#2403
bpamiri merged 1 commit into
developfrom
claude/fresh-vm-batch-k-f15-phase2

Conversation

@bpamiri
Copy link
Copy Markdown
Collaborator

@bpamiri bpamiri commented May 1, 2026

Summary

Phase 2 of F15. Phase 1 (#2402) shipped the new `wheels_` defaults plus runtime detection that flips back to `c_o_r_e_` when legacy tables exist. Phase 2 ships the opt-in tooling that actually does the rename when the user is ready.

What's new

Framework

  • `Migrator.renameSystemTables(boolean dryRun = false)` — new public method that probes for legacy and new system tables, generates the per-adapter rename SQL, and (unless `dryRun`) executes it inside a transaction. Returns `{success, renamed, skipped, errors, sql}`.

  • Per-adapter SQL:

    Adapter Rename syntax
    MySQL atomic `RENAME TABLE old1 TO new1, old2 TO new2`
    SQL Server `EXEC sp_rename` (one per table)
    Oracle `RENAME old TO new`
    SQLite / PostgreSQL / H2 / CockroachDB `ALTER TABLE old RENAME TO new`
  • Partial-rename safeguard: refuses to run when both `c_o_r_e_` AND `wheels_` versions of a table coexist. The user must drop whichever is empty and re-run — better than silent destruction.

HTTP / CLI

  • `/wheels/cli?command=renameSystemTables[&dryRun=true]` — HTTP endpoint that calls the method and returns the result struct as JSON.

  • `wheels migrate rename-system-tables [--dry-run]` — new CLI command:

    • default mode: idempotent rename. No-op when legacy tables don't exist. Reports each table renamed.
    • `--dry-run`: prints the per-adapter SQL without executing.

Tests

  • Four new specs in `migratorSpec.cfc`:

    • No-op when neither family exists.
    • Happy path: `c_o_r_e_` → `wheels_` rename + settings flip.
    • Refuses on partial state (both exist).
    • `--dry-run` returns SQL without executing.
  • Migrator suite: 183 passed (was 179, +4 new)

  • Full SQLite suite: 3377 passed, 0 failed (was 3373, +4 new)

Note on FK constraint name

The `fk_core_level` constraint on `wheels_migrator_versions` is NOT renamed by this PR. Constraint names are scoped to their table; renaming them requires DROP/CREATE which is more invasive. Cosmetic blemish only — the constraint still correctly references `wheels_levels.id` because every supported engine auto-updates FK target references on table rename.

Phase 3 (5.0) will drop/recreate the constraint with the new name as part of the final cleanup pass alongside removing all `c_o_r_e_*`-aware code paths.

Usage

# After upgrading to a Wheels version with both Phase 1 and Phase 2:
wheels migrate rename-system-tables --dry-run    # preview
wheels migrate rename-system-tables              # do it

The detection helper from Phase 1 keeps existing apps working without action; this command is purely opt-in.

Test plan

  • Migrator suite green locally (183 passed)
  • Full SQLite suite green locally (3377 passed)
  • CI cross-engine matrix green
  • Manual test on a fresh-VM Wheels install: create app, run `wheels migrate latest`, verify `c_o_r_e_` exists, run `wheels migrate rename-system-tables`, verify `wheels_` exists and migrations still work

🤖 Generated with Claude Code

…_r_e_* rename

Phase 2 of F15. Phase 1 (#2402) shipped the new `wheels_*` defaults plus
runtime detection that flips back to `c_o_r_e_*` when legacy tables
exist. Phase 2 ships the opt-in tooling that actually does the rename
when the user is ready.

What's new:

  - `Migrator.renameSystemTables(boolean dryRun = false)` — new public
    method that probes for legacy and new system tables, generates the
    per-adapter rename SQL, and (unless dryRun) executes it inside a
    transaction. Returns a structured result with success/renamed/
    skipped/errors/sql fields.

  - Per-adapter rename SQL:
      MySQL:           atomic RENAME TABLE old1 TO new1, old2 TO new2
      SQL Server:      EXEC sp_rename
      Oracle:          RENAME old TO new
      SQLite/Postgres/H2/CockroachDB: ALTER TABLE old RENAME TO new

  - Refuses to run on partial-rename state (both c_o_r_e_* AND wheels_*
    versions of a table coexist) — better to stop than to silently
    destroy one set. The user can drop whichever is empty and re-run.

  - `/wheels/cli?command=renameSystemTables` HTTP endpoint that calls
    the method and returns the result struct as JSON.

  - `wheels migrate rename-system-tables [--dry-run]` CLI command:
      - default mode: idempotent rename. No-op when legacy tables don't
        exist. Reports each table renamed.
      - --dry-run: prints the per-adapter SQL without executing.

Tests:

  - Four new specs in migratorSpec.cfc cover:
    - No-op when neither family exists.
    - Happy path: c_o_r_e_* → wheels_* rename + settings flip.
    - Refuses on partial state (both exist).
    - --dry-run returns SQL without executing.

  - Migrator suite: 183 passed (was 179, +4 new).
  - Full SQLite suite: 3377 passed, 0 failed (was 3373, +4 new).

Note on FK constraint name: the `fk_core_level` constraint name on
wheels_migrator_versions is NOT renamed by this PR. Constraint names
are scoped to their table and renaming them requires DROP/CREATE
which would lose data. Cosmetic blemish only — the constraint still
correctly references wheels_levels.id (every supported engine
auto-updates FK target references on table rename). Phase 3 (5.0)
will drop/recreate the constraint with the new name as part of the
final cleanup pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bpamiri bpamiri merged commit 613c12a into develop May 1, 2026
4 checks passed
@bpamiri bpamiri deleted the claude/fresh-vm-batch-k-f15-phase2 branch May 1, 2026 18:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant