diff options
| author | Simon Charette <charette.s@gmail.com> | 2025-01-11 01:08:35 -0500 |
|---|---|---|
| committer | Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> | 2025-01-13 11:13:29 +0100 |
| commit | 9e552015556661d183a999078a9e846200ef6765 (patch) | |
| tree | 434cbeb5be28ffb5e89c51d629377dfc28932105 /django/db/models/sql/compiler.py | |
| parent | 20eb4bca7de945d8858d1354a8c624406c0b90bd (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.py | 14 |
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) |
