summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Johnson <me@adamj.eu>2020-03-25 08:58:21 +0000
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2020-03-31 07:25:50 +0200
commit93ed71e05802a47774b52503cdc3442686d686c1 (patch)
treef5eec1a66125ca1b141137c5f8f8bf3549c73619
parentc06d7c92392c799d5a17f2620f8e280e119409bf (diff)
Fixed #31403 -- Added support for returning fields from INSERT statements on MariaDB 10.5+.
-rw-r--r--django/db/backends/mysql/features.py6
-rw-r--r--django/db/backends/mysql/operations.py20
-rw-r--r--docs/ref/models/querysets.txt10
-rw-r--r--docs/releases/3.1.txt3
4 files changed, 36 insertions, 3 deletions
diff --git a/django/db/backends/mysql/features.py b/django/db/backends/mysql/features.py
index e1d4ce726b..8a2a64c5e4 100644
--- a/django/db/backends/mysql/features.py
+++ b/django/db/backends/mysql/features.py
@@ -71,6 +71,12 @@ class DatabaseFeatures(BaseDatabaseFeatures):
return self._mysql_storage_engine != 'MyISAM'
@cached_property
+ def can_return_columns_from_insert(self):
+ return self.connection.mysql_is_mariadb and self.connection.mysql_version >= (10, 5, 0)
+
+ can_return_rows_from_bulk_insert = property(operator.attrgetter('can_return_columns_from_insert'))
+
+ @cached_property
def has_zoneinfo_database(self):
# Test if the time zone definitions are installed. CONVERT_TZ returns
# NULL if 'UTC' timezone isn't loaded into the mysql.time_zone.
diff --git a/django/db/backends/mysql/operations.py b/django/db/backends/mysql/operations.py
index e9306f03fc..a8e9af2263 100644
--- a/django/db/backends/mysql/operations.py
+++ b/django/db/backends/mysql/operations.py
@@ -143,6 +143,13 @@ class DatabaseOperations(BaseDatabaseOperations):
def date_interval_sql(self, timedelta):
return 'INTERVAL %s MICROSECOND' % duration_microseconds(timedelta)
+ def fetch_returned_insert_rows(self, cursor):
+ """
+ Given a cursor object that has just performed an INSERT...RETURNING
+ statement into a table, return the tuple of returned data.
+ """
+ return cursor.fetchall()
+
def format_for_duration_arithmetic(self, sql):
return 'INTERVAL %s MICROSECOND' % sql
@@ -173,6 +180,19 @@ class DatabaseOperations(BaseDatabaseOperations):
def random_function_sql(self):
return 'RAND()'
+ def return_insert_columns(self, fields):
+ # MySQL and MariaDB < 10.5.0 don'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), ()
+
def sql_flush(self, style, tables, sequences, allow_cascade=False):
# NB: The generated SQL below is specific to MySQL
# 'TRUNCATE x;', 'TRUNCATE y;', 'TRUNCATE z;'... style SQL statements
diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt
index 9647b1a8ff..c51c4dd43a 100644
--- a/docs/ref/models/querysets.txt
+++ b/docs/ref/models/querysets.txt
@@ -2078,9 +2078,9 @@ This has a number of caveats though:
* The model's ``save()`` method will not be called, and the ``pre_save`` and
``post_save`` signals will not be sent.
* 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` it
- does not retrieve and set the primary key attribute, as ``save()`` does,
- unless the database backend supports it (currently PostgreSQL).
+* 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.
* 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
@@ -2110,6 +2110,10 @@ normally supports it).
Returns ``objs`` as cast to a list, in the same order as provided.
+.. versionchanged:: 3.1
+
+ Support for the fetching primary key attributes on MariaDB 10.5+ was added.
+
``bulk_update()``
~~~~~~~~~~~~~~~~~
diff --git a/docs/releases/3.1.txt b/docs/releases/3.1.txt
index ecd70feb2e..d133731c25 100644
--- a/docs/releases/3.1.txt
+++ b/docs/releases/3.1.txt
@@ -344,6 +344,9 @@ Models
* The new :class:`~django.db.models.F` expression ``bitxor()`` method allows
:ref:`bitwise XOR operation <using-f-expressions-in-filters>`.
+* :meth:`.QuerySet.bulk_create` now sets the primary key on objects when using
+ MariaDB 10.5+.
+
Pagination
~~~~~~~~~~