Opened 3 weeks ago

Closed 2 weeks ago

Last modified 12 days ago

#37260 closed Bug (fixed)

AlterField changing only a Python-level on_delete option performs unnecessary DDL

Reported by: Adam Johnson Owned by: Adam Johnson
Component: Database layer (models, ORM) Version: 6.1
Severity: Release blocker Keywords:
Cc: Mariusz Felisiak Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Database-level delete options, added in #21961, made an AlterField that changes only the Python-level on_delete option of a ForeignKey (e.g. CASCADE to PROTECT, or SET_NULL to CASCADE) execute real DDL. On most backends the foreign key constraint is dropped and recreated, and on SQLite the whole table is rebuilt. In 6.0 such migrations were database no-ops: the AlterField operation was generated for state, but BaseDatabaseSchemaEditor._field_should_be_altered() returned False, so previously-free migrations become expensive and locking after upgrading to 6.1.

Change History (6)

comment:1 by Jacob Walls, 3 weeks ago

Cc: Mariusz Felisiak added
Triage Stage: UnreviewedAccepted

comment:2 by Jacob Walls, 2 weeks ago

Triage Stage: AcceptedReady for checkin

comment:3 by Jacob Walls <jacobtylerwalls@…>, 2 weeks ago

Resolution: fixed
Status: assignedclosed

In 07d4f69:

Fixed #37260 -- Made alterations between Python on_delete options noops.

Support for database-level delete options removed "on_delete" from
Field.non_db_attrs because changes to or from the new DB_CASCADE,
DB_SET_DEFAULT, and DB_SET_NULL options require schema changes. As a
consequence, an AlterField changing only a Python-level on_delete option
(such as CASCADE to PROTECT) performs unnecessary schema changes when it
was previously a no-op at the database level.

This commit makes ForeignObject.non_db_attrs a property that includes
"on_delete"only when the option is not a database-level one, so that:

  • Python-level to Python-level changes skip DDL again,
  • changes to, from, or between database-level options still alter the field.

Regression in 0c487aa3a7b2417481bf48c1e5355c855873e210.

comment:4 by Jacob Walls <jacobtylerwalls@…>, 2 weeks ago

In bccee1b1:

[6.1.x] Fixed #37260 -- Made alterations between Python on_delete options noops.

Support for database-level delete options removed "on_delete" from
Field.non_db_attrs because changes to or from the new DB_CASCADE,
DB_SET_DEFAULT, and DB_SET_NULL options require schema changes. As a
consequence, an AlterField changing only a Python-level on_delete option
(such as CASCADE to PROTECT) performs unnecessary schema changes when it
was previously a no-op at the database level.

This commit makes ForeignObject.non_db_attrs a property that includes
"on_delete"only when the option is not a database-level one, so that:

  • Python-level to Python-level changes skip DDL again,
  • changes to, from, or between database-level options still alter the field.

Regression in 0c487aa3a7b2417481bf48c1e5355c855873e210.

Backport of 07d4f69c94a0e32c583b3aee5daf48fd81b4cd69 from main.

comment:5 by Jacob Walls <jacobtylerwalls@…>, 12 days ago

In 504d1f1:

Refs #37260 -- Added missing skip condition to test_fk_alter_on_delete_db_level.

comment:6 by Jacob Walls <jacobtylerwalls@…>, 12 days ago

In d3549de3:

[6.1.x] Refs #37260 -- Added missing skip condition to test_fk_alter_on_delete_db_level.

Backport of 504d1f12cd5879177295fecd2ba4da1001a0930f from main.

Note: See TracTickets for help on using tickets.
Back to Top