Fixed #31403 -- Added support for returning fields from INSERT statements on MariaDB 10.5+.

This commit is contained in:
Adam Johnson 2020-03-25 08:58:21 +00:00 committed by Mariusz Felisiak
parent c06d7c9239
commit 93ed71e058
4 changed files with 36 additions and 3 deletions

View File

@ -70,6 +70,12 @@ class DatabaseFeatures(BaseDatabaseFeatures):
"Confirm support for introspected foreign keys" "Confirm support for introspected foreign keys"
return self._mysql_storage_engine != 'MyISAM' 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 @cached_property
def has_zoneinfo_database(self): def has_zoneinfo_database(self):
# Test if the time zone definitions are installed. CONVERT_TZ returns # Test if the time zone definitions are installed. CONVERT_TZ returns

View File

@ -143,6 +143,13 @@ class DatabaseOperations(BaseDatabaseOperations):
def date_interval_sql(self, timedelta): def date_interval_sql(self, timedelta):
return 'INTERVAL %s MICROSECOND' % duration_microseconds(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): def format_for_duration_arithmetic(self, sql):
return 'INTERVAL %s MICROSECOND' % sql return 'INTERVAL %s MICROSECOND' % sql
@ -173,6 +180,19 @@ class DatabaseOperations(BaseDatabaseOperations):
def random_function_sql(self): def random_function_sql(self):
return 'RAND()' 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): def sql_flush(self, style, tables, sequences, allow_cascade=False):
# NB: The generated SQL below is specific to MySQL # NB: The generated SQL below is specific to MySQL
# 'TRUNCATE x;', 'TRUNCATE y;', 'TRUNCATE z;'... style SQL statements # 'TRUNCATE x;', 'TRUNCATE y;', 'TRUNCATE z;'... style SQL statements

View File

@ -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 * The model's ``save()`` method will not be called, and the ``pre_save`` and
``post_save`` signals will not be sent. ``post_save`` signals will not be sent.
* It does not work with child models in a multi-table inheritance scenario. * 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 * If the model's primary key is an :class:`~django.db.models.AutoField`, the
does not retrieve and set the primary key attribute, as ``save()`` does, primary key attribute can only be retrieved on certain databases (currently
unless the database backend supports it (currently PostgreSQL). PostgreSQL and MariaDB 10.5+). On other databases, it will not be set.
* It does not work with many-to-many relationships. * It does not work with many-to-many relationships.
* It casts ``objs`` to a list, which fully evaluates ``objs`` if it's a * 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 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. 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()`` ``bulk_update()``
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~

View File

@ -344,6 +344,9 @@ Models
* The new :class:`~django.db.models.F` expression ``bitxor()`` method allows * The new :class:`~django.db.models.F` expression ``bitxor()`` method allows
:ref:`bitwise XOR operation <using-f-expressions-in-filters>`. :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 Pagination
~~~~~~~~~~ ~~~~~~~~~~