summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2022-07-08 13:30:12 +0200
committerGitHub <noreply@github.com>2022-07-08 13:30:12 +0200
commiteb3699ea775548a22e0407ad12bf8cbdeaf95ff5 (patch)
treebed4fed56dfc92b6808de048d1c2b6132d064ed4
parentccbf714ebeff51d1370789e5e487a978d0e2dbfb (diff)
Fixed #33718 -- Dropped support for MySQL 5.7.
-rw-r--r--django/contrib/gis/db/backends/mysql/features.py25
-rw-r--r--django/contrib/gis/db/backends/mysql/introspection.py8
-rw-r--r--django/contrib/gis/db/backends/mysql/operations.py2
-rw-r--r--django/contrib/gis/db/backends/mysql/schema.py5
-rw-r--r--django/db/backends/mysql/features.py56
-rw-r--r--django/db/backends/mysql/operations.py8
-rw-r--r--docs/ref/contrib/gis/db-api.txt16
-rw-r--r--docs/ref/contrib/gis/functions.txt6
-rw-r--r--docs/ref/contrib/gis/geoquerysets.txt4
-rw-r--r--docs/ref/contrib/gis/install/index.txt2
-rw-r--r--docs/ref/databases.txt11
-rw-r--r--docs/ref/models/fields.txt4
-rw-r--r--docs/releases/4.2.txt6
-rw-r--r--tests/aggregation/tests.py6
-rw-r--r--tests/backends/mysql/tests.py4
-rw-r--r--tests/gis_tests/geoapp/tests.py5
16 files changed, 42 insertions, 126 deletions
diff --git a/django/contrib/gis/db/backends/mysql/features.py b/django/contrib/gis/db/backends/mysql/features.py
index 8999a38bf9..cd99420374 100644
--- a/django/contrib/gis/db/backends/mysql/features.py
+++ b/django/contrib/gis/db/backends/mysql/features.py
@@ -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
@@ -15,30 +16,6 @@ class DatabaseFeatures(BaseSpatialFeatures, MySQLDatabaseFeatures):
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
diff --git a/django/contrib/gis/db/backends/mysql/introspection.py b/django/contrib/gis/db/backends/mysql/introspection.py
index 7497ad520c..4d6aea78a2 100644
--- a/django/contrib/gis/db/backends/mysql/introspection.py
+++ b/django/contrib/gis/db/backends/mysql/introspection.py
@@ -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")
diff --git a/django/contrib/gis/db/backends/mysql/operations.py b/django/contrib/gis/db/backends/mysql/operations.py
index 4ef014b36b..6d04874537 100644
--- a/django/contrib/gis/db/backends/mysql/operations.py
+++ b/django/contrib/gis/db/backends/mysql/operations.py
@@ -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):
diff --git a/django/contrib/gis/db/backends/mysql/schema.py b/django/contrib/gis/db/backends/mysql/schema.py
index b173df0198..1c9fe0e565 100644
--- a/django/contrib/gis/db/backends/mysql/schema.py
+++ b/django/contrib/gis/db/backends/mysql/schema.py
@@ -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 = []
diff --git a/django/db/backends/mysql/features.py b/django/db/backends/mysql/features.py
index b454618646..db04d42e24 100644
--- a/django/db/backends/mysql/features.py
+++ b/django/db/backends/mysql/features.py
@@ -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(
{
@@ -342,16 +298,10 @@ class DatabaseFeatures(BaseDatabaseFeatures):
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):
diff --git a/django/db/backends/mysql/operations.py b/django/db/backends/mysql/operations.py
index 34cdfc0292..6c0c6ebd2b 100644
--- a/django/db/backends/mysql/operations.py
+++ b/django/db/backends/mysql/operations.py
@@ -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"
diff --git a/docs/ref/contrib/gis/db-api.txt b/docs/ref/contrib/gis/db-api.txt
index 4cc9ceafd2..bc216c7caf 100644
--- a/docs/ref/contrib/gis/db-api.txt
+++ b/docs/ref/contrib/gis/db-api.txt
@@ -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)
diff --git a/docs/ref/contrib/gis/functions.txt b/docs/ref/contrib/gis/functions.txt
index 44cde315e2..00c48e665e 100644
--- a/docs/ref/contrib/gis/functions.txt
+++ b/docs/ref/contrib/gis/functions.txt
@@ -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.
diff --git a/docs/ref/contrib/gis/geoquerysets.txt b/docs/ref/contrib/gis/geoquerysets.txt
index dac663e3b8..760d508b17 100644
--- a/docs/ref/contrib/gis/geoquerysets.txt
+++ b/docs/ref/contrib/gis/geoquerysets.txt
@@ -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.
diff --git a/docs/ref/contrib/gis/install/index.txt b/docs/ref/contrib/gis/install/index.txt
index 2277b7c5ee..629a070bb8 100644
--- a/docs/ref/contrib/gis/install/index.txt
+++ b/docs/ref/contrib/gis/install/index.txt
@@ -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+
================== ============================== ================== =========================================
diff --git a/docs/ref/databases.txt b/docs/ref/databases.txt
index 05ae78b876..442b1a15a3 100644
--- a/docs/ref/databases.txt
+++ b/docs/ref/databases.txt
@@ -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
diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt
index da65c62766..384c5e50bf 100644
--- a/docs/ref/models/fields.txt
+++ b/docs/ref/models/fields.txt
@@ -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
diff --git a/docs/releases/4.2.txt b/docs/releases/4.2.txt
index 6282bfa580..a8de626993 100644
--- a/docs/releases/4.2.txt
+++ b/docs/releases/4.2.txt
@@ -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
---------------------------------
diff --git a/tests/aggregation/tests.py b/tests/aggregation/tests.py
index c6d73e8042..75a4e0d022 100644
--- a/tests/aggregation/tests.py
+++ b/tests/aggregation/tests.py
@@ -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(
diff --git a/tests/backends/mysql/tests.py b/tests/backends/mysql/tests.py
index d02f465cbf..da6c53de48 100644
--- a/tests/backends/mysql/tests.py
+++ b/tests/backends/mysql/tests.py
@@ -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()
diff --git a/tests/gis_tests/geoapp/tests.py b/tests/gis_tests/geoapp/tests.py
index fd5fc3c793..8a86d4a2be 100644
--- a/tests/gis_tests/geoapp/tests.py
+++ b/tests/gis_tests/geoapp/tests.py
@@ -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