﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
36074	Updating a model instance with a composite primary key through .save() results in unnecessary re-assignment of primary key fields	Simon Charette	Simon Charette	"Looking at the code that gets involved and the generated SQL It appears that every `save` that results in an `UPDATE` for a model with a composite primary key also includes all the primary key field in the updated fields.

For example, for a model of the form

{{{#!python
class User(models.Model):
    tenant = models.ForeignKey(Tenant)
    id = models.UUIDField(default=uuid.uuid4)
    username = models.EmailField()
}}}

Then doing

{{{#!python
user = User.objects.create(tenant=tenant, id=1, email=""foo@bar.org"")
user.email = ""something@example.com""
user.save()
# Will result in UPDATE user SET tenant_id = %s, id = %s, email = %s WHERE tenant_id = %s AND id = %s
#                                ^^^^^^^^^^^^^^^^^^^^^^^  <- tenant_id and id should not be marked for UPDATE
}}}


Will result in the following SQL

{{{#!sql
INSERT INTO user(tenant_id, id, email) VALUES (%s, %s, %s)
UPDATE user SET tenant_id = %s, id = %s, email = %s WHERE tenant_id = %s AND id = %s
}}}

But the `UPDATE` statement should '''not''' set `tenant_id` and `id` as they are part of the primary key lookup. The `UPDATE` should be


{{{#!sql
UPDATE user SET email = %s WHERE tenant_id = %s AND id = %s
}}}

which is due to a non-audited usage of `.primary_key` in `save_tables


{{{#!diff
diff --git a/django/db/models/base.py b/django/db/models/base.py
index a7a26b405c..6d66080c20 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -1091,10 +1091,11 @@ def _save_table(
         for a single table.
         """"""
         meta = cls._meta
+        pk_fields = meta.pk_fields
         non_pks_non_generated = [
             f
             for f in meta.local_concrete_fields
-            if not f.primary_key and not f.generated
+            if f not in pk_fields and not f.generated
         ]

         if update_fields:
}}}

and makes me fear there might be others lying around that went unnoticed."	Bug	assigned	Database layer (models, ORM)	dev	Release blocker				Unreviewed	0	0	0	0	0	0
