Преглед изворни кода

Fixed #32501 -- Added support for returning fields from INSERT statements on SQLite 3.35+.

girishsontakke пре 4 година
родитељ
комит
98abc0c90e

+ 6 - 0
django/db/backends/sqlite3/features.py

@@ -117,3 +117,9 @@ class DatabaseFeatures(BaseDatabaseFeatures):
 
     can_introspect_json_field = property(operator.attrgetter('supports_json_field'))
     has_json_object_function = property(operator.attrgetter('supports_json_field'))
+
+    @cached_property
+    def can_return_columns_from_insert(self):
+        return Database.sqlite_version_info >= (3, 35)
+
+    can_return_rows_from_bulk_insert = property(operator.attrgetter('can_return_columns_from_insert'))

+ 19 - 0
django/db/backends/sqlite3/operations.py

@@ -76,6 +76,13 @@ class DatabaseOperations(BaseDatabaseOperations):
         """
         return "django_date_extract('%s', %s)" % (lookup_type.lower(), field_name)
 
+    def fetch_returned_insert_rows(self, cursor):
+        """
+        Given a cursor object that has just performed an INSERT...RETURNING
+        statement into a table, return the list of returned data.
+        """
+        return cursor.fetchall()
+
     def format_for_duration_arithmetic(self, sql):
         """Do nothing since formatting is handled in the custom function."""
         return sql
@@ -365,3 +372,15 @@ class DatabaseOperations(BaseDatabaseOperations):
 
     def insert_statement(self, ignore_conflicts=False):
         return 'INSERT OR IGNORE INTO' if ignore_conflicts else super().insert_statement(ignore_conflicts)
+
+    def return_insert_columns(self, fields):
+        # SQLite < 3.35 doesn't support an INSERT...RETURNING statement.
+        if not fields:
+            return '', ()
+        columns = [
+            '%s.%s' % (
+                self.quote_name(field.model._meta.db_table),
+                self.quote_name(field.column),
+            ) for field in fields
+        ]
+        return 'RETURNING %s' % ', '.join(columns), ()

+ 6 - 1
docs/ref/models/querysets.txt

@@ -2171,7 +2171,8 @@ This has a number of caveats though:
 * It does not work with child models in a multi-table inheritance scenario.
 * If the model's primary key is an :class:`~django.db.models.AutoField`, the
   primary key attribute can only be retrieved on certain databases (currently
-  PostgreSQL and MariaDB 10.5+). On other databases, it will not be set.
+  PostgreSQL, MariaDB 10.5+, and SQLite 3.35+). On other databases, it will not
+  be set.
 * It does not work with many-to-many relationships.
 * It casts ``objs`` to a list, which fully evaluates ``objs`` if it's a
   generator. The cast allows inspecting all objects so that any objects with a
@@ -2210,6 +2211,10 @@ normally supports it).
 .. _MySQL documentation: https://dev.mysql.com/doc/refman/en/sql-mode.html#ignore-strict-comparison
 .. _MariaDB documentation: https://mariadb.com/kb/en/ignore/
 
+.. versionchanged:: 4.0
+
+    Support for the fetching primary key attributes on SQLite 3.35+ was added.
+
 ``bulk_update()``
 ~~~~~~~~~~~~~~~~~
 

+ 3 - 0
docs/releases/4.0.txt

@@ -230,6 +230,9 @@ Models
   :class:`Round() <django.db.models.functions.Round>` database function allows
   specifying the number of decimal places after rounding.
 
+* :meth:`.QuerySet.bulk_create` now sets the primary key on objects when using
+  SQLite 3.35+.
+
 Requests and Responses
 ~~~~~~~~~~~~~~~~~~~~~~