1
0
mirror of https://github.com/django/django.git synced 2025-01-03 06:55:47 +00:00

Fixed #33507 -- Used UUID data type on MariaDB 10.7+.

Co-Authored-By: Mariusz Felisiak <felisiak.mariusz@gmail.com>
This commit is contained in:
Albert Defler 2022-10-19 13:20:48 +01:00 committed by Mariusz Felisiak
parent ee36c332b2
commit 7cd187a5ba
6 changed files with 60 additions and 3 deletions

View File

@ -40,6 +40,7 @@ answer newbie questions, and generally made Django that much better:
Akshesh Doshi <aksheshdoshi+django@gmail.com> Akshesh Doshi <aksheshdoshi+django@gmail.com>
alang@bright-green.com alang@bright-green.com
Alasdair Nicol <https://al.sdair.co.uk/> Alasdair Nicol <https://al.sdair.co.uk/>
Albert Defler <albert.defler@gmail.com>
Albert Wang <https://github.com/albertyw/> Albert Wang <https://github.com/albertyw/>
Alcides Fonseca Alcides Fonseca
Aldian Fazrihady <mobile@aldian.net> Aldian Fazrihady <mobile@aldian.net>

View File

@ -103,7 +103,8 @@ class DatabaseWrapper(BaseDatabaseWrapper):
# types, as strings. Column-type strings can contain format strings; they'll # types, as strings. Column-type strings can contain format strings; they'll
# be interpolated against the values of Field.__dict__ before being output. # be interpolated against the values of Field.__dict__ before being output.
# If a column type is set to None, it won't be included in the output. # If a column type is set to None, it won't be included in the output.
data_types = {
_data_types = {
"AutoField": "integer AUTO_INCREMENT", "AutoField": "integer AUTO_INCREMENT",
"BigAutoField": "bigint AUTO_INCREMENT", "BigAutoField": "bigint AUTO_INCREMENT",
"BinaryField": "longblob", "BinaryField": "longblob",
@ -133,6 +134,13 @@ class DatabaseWrapper(BaseDatabaseWrapper):
"UUIDField": "char(32)", "UUIDField": "char(32)",
} }
@cached_property
def data_types(self):
_data_types = self._data_types.copy()
if self.features.has_native_uuid_field:
_data_types["UUIDField"] = "uuid"
return _data_types
# For these data types: # For these data types:
# - MySQL < 8.0.13 doesn't accept default values and implicitly treats them # - MySQL < 8.0.13 doesn't accept default values and implicitly treats them
# as nullable # as nullable

View File

@ -349,3 +349,8 @@ class DatabaseFeatures(BaseDatabaseFeatures):
if self.connection.mysql_is_mariadb: if self.connection.mysql_is_mariadb:
return True return True
return self.connection.mysql_version >= (8, 0, 13) return self.connection.mysql_version >= (8, 0, 13)
@cached_property
def has_native_uuid_field(self):
is_mariadb = self.connection.mysql_is_mariadb
return is_mariadb and self.connection.mysql_version >= (10, 7)

View File

@ -11,7 +11,8 @@ from django.utils.datastructures import OrderedSet
FieldInfo = namedtuple( FieldInfo = namedtuple(
"FieldInfo", "FieldInfo",
BaseFieldInfo._fields + ("extra", "is_unsigned", "has_json_constraint", "comment"), BaseFieldInfo._fields
+ ("extra", "is_unsigned", "has_json_constraint", "comment", "data_type"),
) )
InfoLine = namedtuple( InfoLine = namedtuple(
"InfoLine", "InfoLine",
@ -62,6 +63,8 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
return "PositiveIntegerField" return "PositiveIntegerField"
elif field_type == "SmallIntegerField": elif field_type == "SmallIntegerField":
return "PositiveSmallIntegerField" return "PositiveSmallIntegerField"
if description.data_type.upper() == "UUID":
return "UUIDField"
# JSON data type is an alias for LONGTEXT in MariaDB, use check # JSON data type is an alias for LONGTEXT in MariaDB, use check
# constraints clauses to introspect JSONField. # constraints clauses to introspect JSONField.
if description.has_json_constraint: if description.has_json_constraint:
@ -172,6 +175,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
info.is_unsigned, info.is_unsigned,
line[0] in json_constraints, line[0] in json_constraints,
info.comment, info.comment,
info.data_type,
) )
) )
return fields return fields

View File

@ -1118,7 +1118,10 @@ def create_forward_many_to_many_manager(superclass, rel, reverse):
return ( return (
queryset, queryset,
lambda result: tuple( lambda result: tuple(
getattr(result, "_prefetch_related_val_%s" % f.attname) f.get_db_prep_value(
getattr(result, f"_prefetch_related_val_{f.attname}"),
connection,
)
for f in fk.local_related_fields for f in fk.local_related_fields
), ),
lambda inst: tuple( lambda inst: tuple(

View File

@ -377,6 +377,10 @@ Models
* :meth:`.QuerySet.aiterator` now supports previous calls to * :meth:`.QuerySet.aiterator` now supports previous calls to
``prefetch_related()``. ``prefetch_related()``.
* On MariaDB 10.7+, ``UUIDField`` is now created as ``UUID`` column rather than
``CHAR(32)`` column. See the migration guide above for more details on
:ref:`migrating-uuidfield`.
Pagination Pagination
~~~~~~~~~~ ~~~~~~~~~~
@ -483,6 +487,38 @@ Using ``create_defaults__exact`` may now be required with ``QuerySet.update_or_c
``create_defaults`` that are used with an ``update_or_create()`` should specify ``create_defaults`` that are used with an ``update_or_create()`` should specify
the field in the lookup with ``create_defaults__exact``. the field in the lookup with ``create_defaults__exact``.
.. _migrating-uuidfield:
Migrating existing ``UUIDField`` on MariaDB 10.7+
-------------------------------------------------
On MariaDB 10.7+, ``UUIDField`` is now created as ``UUID`` column rather than
``CHAR(32)`` column. As a consequence, any ``UUIDField`` created in
Django < 5.0 should be replaced with a ``UUIDField`` subclass backed by
``CHAR(32)``::
class Char32UUIDField(models.UUIDField):
def db_type(self, connection):
return "char(32)"
For example::
class MyModel(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4)
Should become::
class Char32UUIDField(models.UUIDField):
def db_type(self, connection):
return "char(32)"
class MyModel(models.Model):
uuid = Char32UUIDField(primary_key=True, default=uuid.uuid4)
Running the :djadmin:`makemigrations` command will generate a migration
containing a no-op ``AlterField`` operation.
Miscellaneous Miscellaneous
------------- -------------