mirror of https://github.com/django/django.git
Fixed #33718 -- Dropped support for MySQL 5.7.
This commit is contained in:
parent
ccbf714ebe
commit
eb3699ea77
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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 = []
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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+
|
||||
================== ============================== ================== =========================================
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
---------------------------------
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue