Fixed #33718 -- Dropped support for MySQL 5.7.

This commit is contained in:
Mariusz Felisiak 2022-07-08 13:30:12 +02:00 committed by GitHub
parent ccbf714ebe
commit eb3699ea77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 42 additions and 126 deletions

View File

@ -4,6 +4,7 @@ from django.utils.functional import cached_property
class DatabaseFeatures(BaseSpatialFeatures, MySQLDatabaseFeatures):
empty_intersection_returns_none = False
has_spatialrefsys_table = False
supports_add_srs_entry = False
supports_distance_geodetic = False
@ -14,31 +15,7 @@ class DatabaseFeatures(BaseSpatialFeatures, MySQLDatabaseFeatures):
supports_num_points_poly = False
unsupported_geojson_options = {"crs"}
@cached_property
def empty_intersection_returns_none(self):
return (
not self.connection.mysql_is_mariadb
and self.connection.mysql_version < (5, 7, 5)
)
@cached_property
def supports_geometry_field_unique_index(self):
# Not supported in MySQL since https://dev.mysql.com/worklog/task/?id=11808
return self.connection.mysql_is_mariadb
@cached_property
def django_test_skips(self):
skips = super().django_test_skips
if not self.connection.mysql_is_mariadb and self.connection.mysql_version < (
8,
0,
0,
):
skips.update(
{
"MySQL < 8 gives different results.": {
"gis_tests.geoapp.tests.GeoLookupTest.test_disjoint_lookup",
},
}
)
return skips

View File

@ -28,10 +28,6 @@ class MySQLIntrospection(DatabaseIntrospection):
return field_type, field_params
def supports_spatial_index(self, cursor, table_name):
# Supported with MyISAM/Aria, or InnoDB on MySQL 5.7.5+/MariaDB.
# Supported with MyISAM, Aria, or InnoDB.
storage_engine = self.get_storage_engine(cursor, table_name)
if storage_engine == "InnoDB":
if self.connection.mysql_is_mariadb:
return True
return self.connection.mysql_version >= (5, 7, 5)
return storage_engine in ("MyISAM", "Aria")
return storage_engine in ("MyISAM", "Aria", "InnoDB")

View File

@ -86,8 +86,6 @@ class MySQLOperations(BaseSpatialOperations, DatabaseOperations):
if self.connection.mysql_is_mariadb:
unsupported.remove("PointOnSurface")
unsupported.update({"GeoHash", "IsValid"})
elif self.connection.mysql_version < (5, 7, 5):
unsupported.update({"AsGeoJSON", "GeoHash", "IsValid"})
return unsupported
def geo_db_type(self, f):

View File

@ -81,8 +81,7 @@ class MySQLGISSchemaEditor(DatabaseSchemaEditor):
self.execute(sql)
except OperationalError:
logger.error(
"Cannot create SPATIAL INDEX %s. Only MyISAM and (as of "
"MySQL 5.7.5) InnoDB support them.",
sql,
f"Cannot create SPATIAL INDEX {sql}. Only MyISAM, Aria, and InnoDB "
f"support them.",
)
self.geometry_sql = []

View File

@ -61,15 +61,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
if self.connection.mysql_is_mariadb:
return (10, 4)
else:
return (5, 7)
@cached_property
def bare_select_suffix(self):
if not self.connection.mysql_is_mariadb and self.connection.mysql_version < (
8,
):
return " FROM DUAL"
return ""
return (8,)
@cached_property
def test_collations(self):
@ -128,27 +120,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
},
}
)
if not self.connection.mysql_is_mariadb and self.connection.mysql_version < (
8,
):
skips.update(
{
"Casting to datetime/time is not supported by MySQL < 8.0. "
"(#30224)": {
"aggregation.tests.AggregateTestCase."
"test_aggregation_default_using_time_from_python",
"aggregation.tests.AggregateTestCase."
"test_aggregation_default_using_datetime_from_python",
},
"MySQL < 8.0 returns string type instead of datetime/time. "
"(#30224)": {
"aggregation.tests.AggregateTestCase."
"test_aggregation_default_using_time_from_database",
"aggregation.tests.AggregateTestCase."
"test_aggregation_default_using_datetime_from_database",
},
}
)
if self.connection.mysql_is_mariadb and (
10,
4,
@ -175,21 +146,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
},
}
)
if not self.connection.mysql_is_mariadb and self.connection.mysql_version < (
8,
):
skips.update(
{
"Parenthesized combined queries are not supported on MySQL < 8.": {
"queries.test_qs_combinators.QuerySetSetOperationTests."
"test_union_in_subquery",
"queries.test_qs_combinators.QuerySetSetOperationTests."
"test_union_in_subquery_related_outerref",
"queries.test_qs_combinators.QuerySetSetOperationTests."
"test_union_in_with_ordering",
}
}
)
if not self.supports_explain_analyze:
skips.update(
{
@ -341,17 +297,11 @@ class DatabaseFeatures(BaseDatabaseFeatures):
# To be added in https://jira.mariadb.org/browse/MDEV-12981.
return not self.connection.mysql_is_mariadb
@cached_property
def supports_json_field(self):
if self.connection.mysql_is_mariadb:
return True
return self.connection.mysql_version >= (5, 7, 8)
@cached_property
def can_introspect_json_field(self):
if self.connection.mysql_is_mariadb:
return self.supports_json_field and self.can_introspect_check_constraints
return self.supports_json_field
return self.can_introspect_check_constraints
return True
@cached_property
def supports_index_column_ordering(self):

View File

@ -389,12 +389,8 @@ class DatabaseOperations(BaseDatabaseOperations):
return prefix
def regex_lookup(self, lookup_type):
# REGEXP BINARY doesn't work correctly in MySQL 8+ and REGEXP_LIKE
# doesn't exist in MySQL 5.x or in MariaDB.
if (
self.connection.mysql_version < (8, 0, 0)
or self.connection.mysql_is_mariadb
):
# REGEXP_LIKE doesn't exist in MariaDB.
if self.connection.mysql_is_mariadb:
if lookup_type == "regex":
return "%s REGEXP BINARY %s"
return "%s REGEXP %s"

View File

@ -22,11 +22,9 @@ GeoDjango currently provides the following spatial database backends:
MySQL Spatial Limitations
-------------------------
Before MySQL 5.6.1, spatial extensions only support bounding box operations
(what MySQL calls minimum bounding rectangles, or MBR). Specifically, MySQL did
not conform to the OGC standard. Django supports spatial functions operating on
real geometries available in modern MySQL versions. However, the spatial
functions are not as rich as other backends like PostGIS.
Django supports spatial functions operating on real geometries available in
modern MySQL versions. However, the spatial functions are not as rich as other
backends like PostGIS.
Raster Support
--------------
@ -318,7 +316,7 @@ Lookup Type PostGIS Oracle MariaDB MySQL [#]_ Sp
:lookup:`equals` X X X X X C
:lookup:`exact <same_as>` X X X X X B
:lookup:`intersects` X X X X X B
:lookup:`isvalid` X X X (≥ 5.7.5) X
:lookup:`isvalid` X X X X
:lookup:`overlaps` X X X X X B
:lookup:`relate` X X X X C
:lookup:`same_as` X X X X X B
@ -348,7 +346,7 @@ functions are available on each spatial backend.
Function PostGIS Oracle MariaDB MySQL SpatiaLite
==================================== ======= ============== ============ =========== =================
:class:`Area` X X X X X
:class:`AsGeoJSON` X X X X (≥ 5.7.5) X
:class:`AsGeoJSON` X X X X X
:class:`AsGML` X X X
:class:`AsKML` X X
:class:`AsSVG` X X
@ -361,9 +359,9 @@ Function PostGIS Oracle MariaDB MySQL
:class:`Distance` X X X X X
:class:`Envelope` X X X X X
:class:`ForcePolygonCW` X X
:class:`GeoHash` X X (≥ 5.7.5) X (LWGEOM/RTTOPO)
:class:`GeoHash` X X X (LWGEOM/RTTOPO)
:class:`Intersection` X X X X X
:class:`IsValid` X X X (≥ 5.7.5) X
:class:`IsValid` X X X X
:class:`Length` X X X X X
:class:`LineLocatePoint` X X
:class:`MakeValid` X X (LWGEOM/RTTOPO)

View File

@ -53,7 +53,7 @@ geographic SRSes.
.. class:: AsGeoJSON(expression, bbox=False, crs=False, precision=8, **extra)
*Availability*: MariaDB, `MySQL
<https://dev.mysql.com/doc/refman/en/spatial-geojson-functions.html#function_st-asgeojson>`__ (≥ 5.7.5),
<https://dev.mysql.com/doc/refman/en/spatial-geojson-functions.html#function_st-asgeojson>`__,
Oracle, `PostGIS <https://postgis.net/docs/ST_AsGeoJSON.html>`__, SpatiaLite
Accepts a single geographic field or expression and returns a `GeoJSON
@ -333,7 +333,7 @@ are returned unchanged.
.. class:: GeoHash(expression, precision=None, **extra)
*Availability*: `MySQL
<https://dev.mysql.com/doc/refman/en/spatial-geohash-functions.html#function_st-geohash>`__ (≥ 5.7.5),
<https://dev.mysql.com/doc/refman/en/spatial-geohash-functions.html#function_st-geohash>`__,
`PostGIS <https://postgis.net/docs/ST_GeoHash.html>`__, SpatiaLite
(LWGEOM/RTTOPO)
@ -374,7 +374,7 @@ intersection between them.
.. class:: IsValid(expr)
*Availability*: `MySQL
<https://dev.mysql.com/doc/refman/en/spatial-convenience-functions.html#function_st-isvalid>`__ (≥ 5.7.5),
<https://dev.mysql.com/doc/refman/en/spatial-convenience-functions.html#function_st-isvalid>`__,
`PostGIS <https://postgis.net/docs/ST_IsValid.html>`__, Oracle, SpatiaLite
Accepts a geographic field or expression and tests if the value is well formed.

View File

@ -351,8 +351,8 @@ SpatiaLite ``Intersects(poly, geom)``
``isvalid``
-----------
*Availability*: MySQL (≥ 5.7.5), `PostGIS
<https://postgis.net/docs/ST_IsValid.html>`__, Oracle, SpatiaLite
*Availability*: MySQL, `PostGIS <https://postgis.net/docs/ST_IsValid.html>`__,
Oracle, SpatiaLite
Tests if the geometry is valid.

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, PostGIS 12+ Requires PostGIS.
MySQL GEOS, GDAL 5.7+ :ref:`Limited functionality <mysql-spatial-limitations>`.
MySQL GEOS, GDAL 8+ :ref:`Limited functionality <mysql-spatial-limitations>`.
Oracle GEOS, GDAL 19+ XE not supported.
SQLite GEOS, GDAL, PROJ, SpatiaLite 3.9.0+ Requires SpatiaLite 4.3+
================== ============================== ================== =========================================

View File

@ -352,7 +352,7 @@ MySQL notes
Version support
---------------
Django supports MySQL 5.7 and higher.
Django supports MySQL 8 and higher.
Django's ``inspectdb`` feature uses the ``information_schema`` database, which
contains detailed data on all database schemas.
@ -535,11 +535,10 @@ Several other `MySQLdb connection options`_ may be useful, such as ``ssl``,
Setting ``sql_mode``
~~~~~~~~~~~~~~~~~~~~
From MySQL 5.7 onward, the default value of the ``sql_mode`` option contains
``STRICT_TRANS_TABLES``. That option escalates warnings into errors when data
are truncated upon insertion, so Django highly recommends activating a
`strict mode`_ for MySQL to prevent data loss (either ``STRICT_TRANS_TABLES``
or ``STRICT_ALL_TABLES``).
The default value of the ``sql_mode`` option contains ``STRICT_TRANS_TABLES``.
That option escalates warnings into errors when data are truncated upon
insertion, so Django highly recommends activating a `strict mode`_ for MySQL to
prevent data loss (either ``STRICT_TRANS_TABLES`` or ``STRICT_ALL_TABLES``).
.. _strict mode: https://dev.mysql.com/doc/refman/en/sql-mode.html#sql-mode-strict

View File

@ -1200,8 +1200,8 @@ A field for storing JSON encoded data. In Python the data is represented in its
Python native format: dictionaries, lists, strings, numbers, booleans and
``None``.
``JSONField`` is supported on MariaDB, MySQL 5.7.8+, Oracle, PostgreSQL, and
SQLite (with the :ref:`JSON1 extension enabled <sqlite-json1>`).
``JSONField`` is supported on MariaDB, MySQL, Oracle, PostgreSQL, and SQLite
(with the :ref:`JSON1 extension enabled <sqlite-json1>`).
.. attribute:: JSONField.encoder

View File

@ -249,6 +249,12 @@ Dropped support for MariaDB 10.3
Upstream support for MariaDB 10.3 ends in May 2023. Django 4.2 supports MariaDB
10.4 and higher.
Dropped support for MySQL 5.7
-----------------------------
Upstream support for MySQL 5.7 ends in October 2023. Django 4.2 supports MySQL
8 and higher.
Dropped support for PostgreSQL 11
---------------------------------

View File

@ -1837,7 +1837,7 @@ class AggregateTestCase(TestCase):
default=datetime.time(17),
)
if connection.vendor == "mysql":
# Workaround for #30224 for MySQL 8.0+ & MariaDB.
# Workaround for #30224 for MySQL & MariaDB.
expr.default = Cast(expr.default, TimeField())
queryset = Book.objects.annotate(oldest_store_opening=expr).order_by("isbn")
self.assertSequenceEqual(
@ -1887,7 +1887,7 @@ class AggregateTestCase(TestCase):
def test_aggregation_default_using_date_from_python(self):
expr = Min("book__pubdate", default=datetime.date(1970, 1, 1))
if connection.vendor == "mysql":
# Workaround for #30224 for MySQL 5.7+ & MariaDB.
# Workaround for #30224 for MySQL & MariaDB.
expr.default = Cast(expr.default, DateField())
queryset = Publisher.objects.annotate(earliest_pubdate=expr).order_by("name")
self.assertSequenceEqual(
@ -1938,7 +1938,7 @@ class AggregateTestCase(TestCase):
default=datetime.datetime(1970, 1, 1),
)
if connection.vendor == "mysql":
# Workaround for #30224 for MySQL 8.0+ & MariaDB.
# Workaround for #30224 for MySQL & MariaDB.
expr.default = Cast(expr.default, DateTimeField())
queryset = Book.objects.annotate(oldest_store_opening=expr).order_by("isbn")
self.assertSequenceEqual(

View File

@ -110,8 +110,8 @@ class Tests(TestCase):
mocked_get_database_version.return_value = (10, 3)
msg = "MariaDB 10.4 or later is required (found 10.3)."
else:
mocked_get_database_version.return_value = (5, 6)
msg = "MySQL 5.7 or later is required (found 5.6)."
mocked_get_database_version.return_value = (5, 7)
msg = "MySQL 8 or later is required (found 5.7)."
with self.assertRaisesMessage(NotSupportedError, msg):
connection.check_database_version_supported()

View File

@ -345,12 +345,9 @@ class GeoLookupTest(TestCase):
invalid_geom = fromstr("POLYGON((0 0, 0 1, 1 1, 1 0, 1 1, 1 0, 0 0))")
State.objects.create(name="invalid", poly=invalid_geom)
qs = State.objects.all()
if connection.ops.oracle or (
connection.ops.mysql and connection.mysql_version < (8, 0, 0)
):
if connection.ops.oracle:
# Kansas has adjacent vertices with distance 6.99244813842e-12
# which is smaller than the default Oracle tolerance.
# It's invalid on MySQL < 8 also.
qs = qs.exclude(name="Kansas")
self.assertEqual(
State.objects.filter(name="Kansas", poly__isvalid=False).count(), 1