#34151: Adding explicit primary key with different type doesn't update related
ManyToManyFields.
-------------------------------------+-------------------------------------
Reporter: STANISLAV LEPEKHOV | Owner: Carol
| Naranjo
Type: Bug | Status: assigned
Component: Migrations | Version: 4.1
Severity: Normal | Resolution:
Keywords: migrations pk uuid | Triage Stage: Accepted
relation |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Carol Naranjo):
Thanks for the details. I was able to reproduce the exact issue in older
versions of Django (including the reported 4.0.3), psycopg2-binary 2.9.11,
and the latest PostgreSQL (18.3 as of today). Here are my findings:
**Behavior with Django 4.0.3 to 5.2.12:**
I confirmed that in these versions, the migration proceeds but results in
an inconsistent database state: The relationship table is not updated to
match the new primary key type and the foreign key is dropped in the many-
to-many table.
**Behavior with Django >= 6.0:**
I tested the same scenario in the latest versions (6.0 and 6.1-dev), and
the behavior has changed significantly. Instead of a silent failure when
attempting to run this particular migration (which generates RemoveField
and AddField operations for the primary key change), the database now
explicitly blocks the destructive operation with an **InternalError**:
{{{
# (0.003) ALTER TABLE "issue34151_place" DROP COLUMN "id"; args=None;
alias=default
# ...
# django.db.utils.InternalError: cannot drop column id of table
issue34151_place
# because other objects depend on it
# DETAIL: constraint issue34151_storechain_place_id_97554049_fk_issue3415
on
# table issue34151_storechain_places depends on column id of table
issue34151_place
# HINT: Use DROP ... CASCADE to drop the dependent objects too.
}}}
This is, in my opinion, the correct and expected behavior. By triggering a
database-level error, Django prevents the creation of the 'broken' state
described in the original report so **I recommend closing this ticket** as
the behavior in the latest mainstream-supported versions is consistent
with expected database integrity standards.
**Additional Information / Hints for Users**
In order to perform this type of migration (changing both the name and
type of a primary key), here are a few considerations:
- **Manual Migration Steps**: An alternative way to apply this change
would be writing a migration with RenameField and AlterType operations.
However, be aware that for this specific example, PostgreSQL would still
fail to cast a BigInt directly into a UUID. This is a database-level
requirement for explicit casting, not a bug in Django. If for example the
type was altered to a compatible format (such as a string/VarChar) instead
of a UUID, the operation would execute correctly as expected.
- **The Limits of Automated Migration Generation**: Django migrations
provide a 'best guess' of the operations required to keep tables and
relationships consistent. However, according to the documentation ''“some
of the more complex operations are not autodetectable and are only
available via a hand-written migration”'' (See
[https://docs.djangoproject.com/en/6.0/topics/migrations/#migration-files
link] ) . When these limitations are hit, manual migration adjustments are
the standard procedure.
--
Ticket URL: <https://code.djangoproject.com/ticket/34151#comment:22>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/django-updates/0107019d1a952b16-08c46f2c-d2e1-4575-af89-cc8d849a930f-000000%40eu-central-1.amazonses.com.