summaryrefslogtreecommitdiff
path: root/django/db/models/sql/compiler.py
diff options
context:
space:
mode:
authorSimon Charette <charette.s@gmail.com>2025-01-11 01:08:35 -0500
committerSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2025-01-13 11:13:29 +0100
commit9e552015556661d183a999078a9e846200ef6765 (patch)
tree434cbeb5be28ffb5e89c51d629377dfc28932105 /django/db/models/sql/compiler.py
parent20eb4bca7de945d8858d1354a8c624406c0b90bd (diff)
Fixed #36086 -- Fixed crash when using GeneratedField with non-AutoField pk.
The previous logic was systematically attempting to retrieve last_insert_id even for models without an AutoField primary key when they had a GeneratedField on backends that can't return columns from INSERT. The issue affected MySQL, SQLite < 3.35, and Oracle when the use_returning_into option was disabled and could result in either crashes when the non-auto primary key wasn't an IntegerField subclass or silent misassignment of bogus insert ids (0 or the previous auto primary key insert value) to the first defined generated field value.
Diffstat (limited to 'django/db/models/sql/compiler.py')
-rw-r--r--django/db/models/sql/compiler.py14
1 files changed, 10 insertions, 4 deletions
diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py
index 0d5cd764da..6f90f11f1b 100644
--- a/django/db/models/sql/compiler.py
+++ b/django/db/models/sql/compiler.py
@@ -8,7 +8,7 @@ from django.core.exceptions import EmptyResultSet, FieldError, FullResultSet
from django.db import DatabaseError, NotSupportedError
from django.db.models.constants import LOOKUP_SEP
from django.db.models.expressions import ColPairs, F, OrderBy, RawSQL, Ref, Value
-from django.db.models.fields import composite
+from django.db.models.fields import AutoField, composite
from django.db.models.functions import Cast, Random
from django.db.models.lookups import Lookup
from django.db.models.query_utils import select_related_descend
@@ -1910,17 +1910,23 @@ class SQLInsertCompiler(SQLCompiler):
)
]
cols = [field.get_col(opts.db_table) for field in self.returning_fields]
- else:
- cols = [opts.pk.get_col(opts.db_table)]
+ elif returning_fields and isinstance(
+ returning_field := returning_fields[0], AutoField
+ ):
+ cols = [returning_field.get_col(opts.db_table)]
rows = [
(
self.connection.ops.last_insert_id(
cursor,
opts.db_table,
- opts.pk.column,
+ returning_field.column,
),
)
]
+ else:
+ # Backend doesn't support returning fields and no auto-field
+ # that can be retrieved from `last_insert_id` was specified.
+ return []
converters = self.get_converters(cols)
if converters:
rows = self.apply_converters(rows, converters)