1
0
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:
Tim Graham 2017-08-24 14:56:09 -04:00
parent 6da140724d
commit 8a1768432b
10 changed files with 38 additions and 88 deletions

View File

@ -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):

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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+
================== ============================== ================== =========================================

View File

@ -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

View File

@ -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
-------------

View File

@ -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')