mirror of
https://github.com/django/django.git
synced 2024-12-22 17:16:24 +00:00
Fixed #28552 -- Dropped support for MySQL 5.5.
This commit is contained in:
parent
6da140724d
commit
8a1768432b
@ -15,17 +15,10 @@ class MySQLOperations(BaseSpatialOperations, DatabaseOperations):
|
||||
|
||||
mysql = True
|
||||
name = 'mysql'
|
||||
geom_func_prefix = 'ST_'
|
||||
|
||||
Adapter = WKTAdapter
|
||||
|
||||
@cached_property
|
||||
def geom_func_prefix(self):
|
||||
return '' if self.is_mysql_5_5 else 'ST_'
|
||||
|
||||
@cached_property
|
||||
def is_mysql_5_5(self):
|
||||
return self.connection.mysql_version < (5, 6, 1)
|
||||
|
||||
@cached_property
|
||||
def is_mysql_5_6(self):
|
||||
return self.connection.mysql_version < (5, 7, 6)
|
||||
@ -56,10 +49,6 @@ class MySQLOperations(BaseSpatialOperations, DatabaseOperations):
|
||||
'within': SpatialOperator(func='MBRWithin'),
|
||||
}
|
||||
|
||||
@cached_property
|
||||
def function_names(self):
|
||||
return {'Length': 'GLength'} if self.is_mysql_5_5 else {}
|
||||
|
||||
disallowed_aggregates = (
|
||||
aggregates.Collect, aggregates.Extent, aggregates.Extent3D,
|
||||
aggregates.MakeLine, aggregates.Union,
|
||||
@ -75,8 +64,6 @@ class MySQLOperations(BaseSpatialOperations, DatabaseOperations):
|
||||
}
|
||||
if self.connection.mysql_version < (5, 7, 5):
|
||||
unsupported.update({'AsGeoJSON', 'GeoHash', 'IsValid'})
|
||||
if self.is_mysql_5_5:
|
||||
unsupported.update({'Difference', 'Distance', 'Intersection', 'SymDifference', 'Union'})
|
||||
return unsupported
|
||||
|
||||
def geo_db_type(self, f):
|
||||
|
@ -97,14 +97,14 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
||||
# types, as strings. Column-type strings can contain format strings; they'll
|
||||
# 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.
|
||||
_data_types = {
|
||||
data_types = {
|
||||
'AutoField': 'integer AUTO_INCREMENT',
|
||||
'BigAutoField': 'bigint AUTO_INCREMENT',
|
||||
'BinaryField': 'longblob',
|
||||
'BooleanField': 'bool',
|
||||
'CharField': 'varchar(%(max_length)s)',
|
||||
'DateField': 'date',
|
||||
'DateTimeField': 'datetime',
|
||||
'DateTimeField': 'datetime(6)',
|
||||
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
|
||||
'DurationField': 'bigint',
|
||||
'FileField': 'varchar(%(max_length)s)',
|
||||
@ -121,17 +121,10 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
||||
'SlugField': 'varchar(%(max_length)s)',
|
||||
'SmallIntegerField': 'smallint',
|
||||
'TextField': 'longtext',
|
||||
'TimeField': 'time',
|
||||
'TimeField': 'time(6)',
|
||||
'UUIDField': 'char(32)',
|
||||
}
|
||||
|
||||
@cached_property
|
||||
def data_types(self):
|
||||
if self.features.supports_microsecond_precision:
|
||||
return dict(self._data_types, DateTimeField='datetime(6)', TimeField='time(6)')
|
||||
else:
|
||||
return self._data_types
|
||||
|
||||
# For these columns, MySQL doesn't:
|
||||
# - accept default values and implicitly treats these columns as nullable
|
||||
# - support a database index
|
||||
|
@ -60,10 +60,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
||||
"Confirm support for introspected foreign keys"
|
||||
return self._mysql_storage_engine != 'MyISAM'
|
||||
|
||||
@cached_property
|
||||
def supports_microsecond_precision(self):
|
||||
return self.connection.mysql_version >= (5, 6, 4)
|
||||
|
||||
@cached_property
|
||||
def has_zoneinfo_database(self):
|
||||
# Test if the time zone definitions are installed.
|
||||
|
@ -109,10 +109,7 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||
return "INTERVAL '%06f' SECOND_MICROSECOND" % timedelta.total_seconds()
|
||||
|
||||
def format_for_duration_arithmetic(self, sql):
|
||||
if self.connection.features.supports_microsecond_precision:
|
||||
return 'INTERVAL %s MICROSECOND' % sql
|
||||
else:
|
||||
return 'INTERVAL FLOOR(%s / 1000000) SECOND' % sql
|
||||
return 'INTERVAL %s MICROSECOND' % sql
|
||||
|
||||
def force_no_ordering(self):
|
||||
"""
|
||||
@ -178,10 +175,6 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||
value = timezone.make_naive(value, self.connection.timezone)
|
||||
else:
|
||||
raise ValueError("MySQL backend does not support timezone-aware datetimes when USE_TZ is False.")
|
||||
|
||||
if not self.connection.features.supports_microsecond_precision:
|
||||
value = value.replace(microsecond=0)
|
||||
|
||||
return str(value)
|
||||
|
||||
def adapt_timefield_value(self, value):
|
||||
@ -258,17 +251,10 @@ class DatabaseOperations(BaseDatabaseOperations):
|
||||
def subtract_temporals(self, internal_type, lhs, rhs):
|
||||
lhs_sql, lhs_params = lhs
|
||||
rhs_sql, rhs_params = rhs
|
||||
if self.connection.features.supports_microsecond_precision:
|
||||
if internal_type == 'TimeField':
|
||||
return (
|
||||
"((TIME_TO_SEC(%(lhs)s) * POW(10, 6) + MICROSECOND(%(lhs)s)) -"
|
||||
" (TIME_TO_SEC(%(rhs)s) * POW(10, 6) + MICROSECOND(%(rhs)s)))"
|
||||
) % {'lhs': lhs_sql, 'rhs': rhs_sql}, lhs_params * 2 + rhs_params * 2
|
||||
else:
|
||||
return "TIMESTAMPDIFF(MICROSECOND, %s, %s)" % (rhs_sql, lhs_sql), rhs_params + lhs_params
|
||||
elif internal_type == 'TimeField':
|
||||
if internal_type == 'TimeField':
|
||||
return (
|
||||
"(TIME_TO_SEC(%s) * POW(10, 6) - TIME_TO_SEC(%s) * POW(10, 6))"
|
||||
) % (lhs_sql, rhs_sql), lhs_params + rhs_params
|
||||
"((TIME_TO_SEC(%(lhs)s) * POW(10, 6) + MICROSECOND(%(lhs)s)) -"
|
||||
" (TIME_TO_SEC(%(rhs)s) * POW(10, 6) + MICROSECOND(%(rhs)s)))"
|
||||
) % {'lhs': lhs_sql, 'rhs': rhs_sql}, lhs_params * 2 + rhs_params * 2
|
||||
else:
|
||||
return "(TIMESTAMPDIFF(SECOND, %s, %s) * POW(10, 6))" % (rhs_sql, lhs_sql), rhs_params + lhs_params
|
||||
return "TIMESTAMPDIFF(MICROSECOND, %s, %s)" % (rhs_sql, lhs_sql), rhs_params + lhs_params
|
||||
|
@ -379,12 +379,12 @@ Function PostGIS Oracle MySQL Spat
|
||||
:class:`Azimuth` X X (LWGEOM)
|
||||
:class:`BoundingCircle` X X
|
||||
:class:`Centroid` X X X X
|
||||
:class:`Difference` X X X (≥ 5.6.1) X
|
||||
:class:`Distance` X X X (≥ 5.6.1) X
|
||||
:class:`Difference` X X X X
|
||||
:class:`Distance` X X X X
|
||||
:class:`Envelope` X X X
|
||||
:class:`ForceRHR` X
|
||||
:class:`GeoHash` X X (≥ 5.7.5) X (LWGEOM)
|
||||
:class:`Intersection` X X X (≥ 5.6.1) X
|
||||
:class:`Intersection` X X X X
|
||||
:class:`IsValid` X X X (≥ 5.7.5) X (LWGEOM)
|
||||
:class:`Length` X X X X
|
||||
:class:`LineLocatePoint` X X
|
||||
@ -397,10 +397,10 @@ Function PostGIS Oracle MySQL Spat
|
||||
:class:`Reverse` X X X
|
||||
:class:`Scale` X X
|
||||
:class:`SnapToGrid` X X
|
||||
:class:`SymDifference` X X X (≥ 5.6.1) X
|
||||
:class:`SymDifference` X X X X
|
||||
:class:`Transform` X X X
|
||||
:class:`Translate` X X
|
||||
:class:`Union` X X X (≥ 5.6.1) X
|
||||
:class:`Union` X X X X
|
||||
==================================== ======= ============== =========== ==========
|
||||
|
||||
Aggregate Functions
|
||||
|
@ -208,7 +208,7 @@ value of the geometry.
|
||||
|
||||
.. class:: Difference(expr1, expr2, **extra)
|
||||
|
||||
*Availability*: MySQL (≥ 5.6.1), `PostGIS
|
||||
*Availability*: MySQL, `PostGIS
|
||||
<https://postgis.net/docs/ST_Difference.html>`__, Oracle, SpatiaLite
|
||||
|
||||
Accepts two geographic fields or expressions and returns the geometric
|
||||
@ -220,8 +220,8 @@ geometry B.
|
||||
|
||||
.. class:: Distance(expr1, expr2, spheroid=None, **extra)
|
||||
|
||||
*Availability*: MySQL (≥ 5.6.1), `PostGIS
|
||||
<https://postgis.net/docs/ST_Distance.html>`__, Oracle, SpatiaLite
|
||||
*Availability*: MySQL, `PostGIS <https://postgis.net/docs/ST_Distance.html>`__,
|
||||
Oracle, SpatiaLite
|
||||
|
||||
Accepts two geographic fields or expressions and returns the distance between
|
||||
them, as a :class:`~django.contrib.gis.measure.Distance` object. On MySQL, a raw
|
||||
@ -307,7 +307,7 @@ __ https://en.wikipedia.org/wiki/Geohash
|
||||
|
||||
.. class:: Intersection(expr1, expr2, **extra)
|
||||
|
||||
*Availability*: MySQL (≥ 5.6.1), `PostGIS
|
||||
*Availability*: MySQL, `PostGIS
|
||||
<https://postgis.net/docs/ST_Intersection.html>`__, Oracle, SpatiaLite
|
||||
|
||||
Accepts two geographic fields or expressions and returns the geometric
|
||||
@ -480,7 +480,7 @@ Number of Arguments Description
|
||||
|
||||
.. class:: SymDifference(expr1, expr2, **extra)
|
||||
|
||||
*Availability*: MySQL (≥ 5.6.1), `PostGIS
|
||||
*Availability*: MySQL, `PostGIS
|
||||
<https://postgis.net/docs/ST_SymDifference.html>`__, Oracle, SpatiaLite
|
||||
|
||||
Accepts two geographic fields or expressions and returns the geometric
|
||||
@ -522,8 +522,8 @@ parameters.
|
||||
|
||||
.. class:: Union(expr1, expr2, **extra)
|
||||
|
||||
*Availability*: MySQL (≥ 5.6.1), `PostGIS
|
||||
<https://postgis.net/docs/ST_Union.html>`__, Oracle, SpatiaLite
|
||||
*Availability*: MySQL, `PostGIS <https://postgis.net/docs/ST_Union.html>`__,
|
||||
Oracle, SpatiaLite
|
||||
|
||||
Accepts two geographic fields or expressions and returns the union of both
|
||||
geometries.
|
||||
|
@ -59,7 +59,7 @@ supported versions, and any notes for each of the supported database backends:
|
||||
Database Library Requirements Supported Versions Notes
|
||||
================== ============================== ================== =========================================
|
||||
PostgreSQL GEOS, GDAL, PROJ.4, PostGIS 9.3+ Requires PostGIS.
|
||||
MySQL GEOS, GDAL 5.5+ Not OGC-compliant; :ref:`limited functionality <mysql-spatial-limitations>`.
|
||||
MySQL GEOS, GDAL 5.6+ Not OGC-compliant; :ref:`limited functionality <mysql-spatial-limitations>`.
|
||||
Oracle GEOS, GDAL 12.1+ XE not supported.
|
||||
SQLite GEOS, GDAL, PROJ.4, SpatiaLite 3.6.+ Requires SpatiaLite 4.0+
|
||||
================== ============================== ================== =========================================
|
||||
|
@ -276,7 +276,7 @@ MySQL notes
|
||||
Version support
|
||||
---------------
|
||||
|
||||
Django supports MySQL 5.5 and higher.
|
||||
Django supports MySQL 5.6 and higher.
|
||||
|
||||
Django's ``inspectdb`` feature uses the ``information_schema`` database, which
|
||||
contains detailed data on all database schemas.
|
||||
@ -294,36 +294,20 @@ Storage engines
|
||||
MySQL has several `storage engines`_. You can change the default storage engine
|
||||
in the server configuration.
|
||||
|
||||
Until MySQL 5.5.4, the default engine was MyISAM_ [#]_. The main drawbacks of
|
||||
MyISAM are that it doesn't support transactions or enforce foreign-key
|
||||
constraints. On the plus side, it was the only engine that supported full-text
|
||||
indexing and searching until MySQL 5.6.4.
|
||||
MySQL's default storage engine is InnoDB_. This engine is fully transactional
|
||||
and supports foreign key references. It's the recommended choice. However, the
|
||||
InnoDB autoincrement counter is lost on a MySQL restart because it does not
|
||||
remember the ``AUTO_INCREMENT`` value, instead recreating it as "max(id)+1".
|
||||
This may result in an inadvertent reuse of :class:`~django.db.models.AutoField`
|
||||
values.
|
||||
|
||||
Since MySQL 5.5.5, the default storage engine is InnoDB_. This engine is fully
|
||||
transactional and supports foreign key references. It's probably the best
|
||||
choice at this point. However, note that the InnoDB autoincrement counter
|
||||
is lost on a MySQL restart because it does not remember the
|
||||
``AUTO_INCREMENT`` value, instead recreating it as "max(id)+1". This may
|
||||
result in an inadvertent reuse of :class:`~django.db.models.AutoField` values.
|
||||
|
||||
If you upgrade an existing project to MySQL 5.5.5 and subsequently add some
|
||||
tables, ensure that your tables are using the same storage engine (i.e. MyISAM
|
||||
vs. InnoDB). Specifically, if tables that have a ``ForeignKey`` between them
|
||||
use different storage engines, you may see an error like the following when
|
||||
running ``migrate``::
|
||||
|
||||
_mysql_exceptions.OperationalError: (
|
||||
1005, "Can't create table '\\db_name\\.#sql-4a8_ab' (errno: 150)"
|
||||
)
|
||||
The main drawbacks of MyISAM_ are that it doesn't support transactions or
|
||||
enforce foreign-key constraints.
|
||||
|
||||
.. _storage engines: https://dev.mysql.com/doc/refman/en/storage-engines.html
|
||||
.. _MyISAM: https://dev.mysql.com/doc/refman/en/myisam-storage-engine.html
|
||||
.. _InnoDB: https://dev.mysql.com/doc/refman/en/innodb-storage-engine.html
|
||||
|
||||
.. [#] Unless this was changed by the packager of your MySQL package. We've
|
||||
had reports that the Windows Community Server installer sets up InnoDB as
|
||||
the default storage engine, for example.
|
||||
|
||||
.. _mysql-db-api-drivers:
|
||||
|
||||
MySQL DB API Drivers
|
||||
|
@ -200,6 +200,12 @@ Database backend API
|
||||
|
||||
* ...
|
||||
|
||||
Dropped support for MySQL 5.5
|
||||
-----------------------------
|
||||
|
||||
The end of upstream support for MySQL 5.5 is December 2018. Django 2.1 supports
|
||||
MySQL 5.6 and higher.
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
|
||||
|
@ -2302,8 +2302,6 @@ class SchemaTests(TransactionTestCase):
|
||||
Changing the primary key field name of a model with a self-referential
|
||||
foreign key (#26384).
|
||||
"""
|
||||
if connection.vendor == 'mysql' and connection.mysql_version < (5, 6, 6):
|
||||
self.skipTest('Skip known bug renaming primary keys on older MySQL versions (#24995).')
|
||||
with connection.schema_editor() as editor:
|
||||
editor.create_model(Node)
|
||||
old_field = Node._meta.get_field('node_id')
|
||||
|
Loading…
Reference in New Issue
Block a user