Skip to content

Propagate rename_table to inbound ForeignKey references in the schema snapshot - #1436

Open
regiscamimura wants to merge 1 commit into
piccolo-orm:masterfrom
regiscamimura:rename-table-fk-references
Open

regiscamimura wants to merge 1 commit into
piccolo-orm:masterfrom
regiscamimura:rename-table-fk-references

Conversation

@regiscamimura

Copy link
Copy Markdown
Contributor

The bug

piccolo migrations new <app> --auto diffs the current tables against a SchemaSnapshot replayed from the migration history. When the history contains a rename_table, the snapshot renames that table — but leaves every ForeignKey on other tables still pointing at the old table class (params["references"]). The live models reference the new class, and SerialisedTableType compares by "{tablename}-{ClassName}", so every subsequent --auto emits an alter_column(references=New, old_params={"references": Old}) for each inbound FK, forever.

Repro from history:

manager_1.add_table("Band", "band")
manager_1.add_table("Concert", "concert")
manager_1.add_column("Concert", "concert", "band", column_class=ForeignKey, params={"references": Band})
manager_2.rename_table("Band", "band", "Performer", "performer")

concert = SchemaSnapshot([manager_1, manager_2]).get_table_from_snapshot("Concert")
concert.columns[0]._meta.params["references"].__name__   # "Band"  — should be "Performer"

In our app, a table rename in August produced the same nine phantom alter_columns in every one of the ten migrations generated since, each stripped by hand. (They execute no SQL — alter_column never acts on references — so committing them once also works around it downstream, which is how we found the cause.)

The fix

In SchemaSnapshot.get_snapshot, after applying a rename_table, walk every table's ForeignKey columns and replace a references that names the old class/tablename with a subclass carrying the new class name and tablename (via create_table_class), updating both _meta.params["references"] and _foreign_key_meta.references.

Test

test_rename_table_updates_foreign_key_references — asserts the snapshot's FK now names the new class and tablename, and that a DiffableTable built from the renamed model diffs to no alter_columns. Fails on master ("Band" != "Performer"), passes with the fix. tests/apps/migrations: 79 passed, 84 skipped (SQLite). black / isort / flake8 / mypy clean on the two files.

🤖 Generated with Claude Code

https://claude.ai/code/session_018o8TvRZFEEBXJWXvR1ikd9

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant