From 9e552015556661d183a999078a9e846200ef6765 Mon Sep 17 00:00:00 2001 From: Simon Charette Date: Sat, 11 Jan 2025 01:08:35 -0500 Subject: 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. --- django/db/models/sql/compiler.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'django/db/models/sql/compiler.py') 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) -- cgit v1.3