Clean up and simplify the common primary key constraint management.
Review Request #11097 — Created July 26, 2020 and submitted
The base evolver backend code provided some default functionality for
updating constraints for a field with a primary key when renaming a
model or renaming the table behind a
ManyToManyField. By default, it
DROP CONSTRAINTstatements surrounding
these renames, and to opt out of it, a subclass (SQLite's, for instance)
would have to set
support_constraints = False.
There were some issues with the implementation:
That flag was unclear. It implies SQLite doesn't support constraints,
which is not true. It does, the backend just doesn't want these
statements to be generated (sine they must be managed an entirely
different way). It was also doubly unclear in the context of
Django 2.2's new
The flag was also hacky. It was really there to turn off behavior
SQLite didn't want, rather than SQLite just implementing its own
behavior like it does for other operations.
The code used to stash away existing references, drop constraints,
and then re-add them was largely duplicated across
(with minor variations in when it considers a field something worth
The naming of those two functions weren't at all consistent, and the
former didn't leave the door open for other forms of automatic field
It imposed some code flow choices on table renaming that made code a
bit harder to really understand than was necessary.
This change reworks all this, in preparation for the new Django 2.2
support_constraintsflag is completely gone now. Instead, the
rename_table()code that used it just hard-codes usage of constraints,
and SQLite completely overrides it to perform table renaming its own
way. That simplifies a lot of the code and capability checking.
Instead of having the code duplicated in places, there's now central
functions that are meant to work together.
stash_field_ref_constraints()takes in the operations that are to be
performed (mapping of replaced table names or replaced fields),
calculates a bunch of state it needs, and determines the correct
references to track and the SQL to generate. It's able to be used for
both table and column renaming, and down the road can be updated for
This function returns the SQL and a
stashobject, which is just a
dictionary of state that can be passed in to
restore_field_ref_constraints(). That function then updates
model/field state and generates SQL based on that stashed state.
There's still plenty of room for improvement, but this sets us up to be
able to pursue that without the hackiness we had before.
Unit tests pass for all database types on all supported versions of
Django, on Python 2.7 and 3.x.
Fixed a typo in a comment.
Revision 2 (+618 -290)
Checks run (2 succeeded)