summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2025-06-18 17:51:08 +0200
committerSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2025-06-25 08:58:22 +0200
commit7091801e046dc85dba2238ed4eaf0b3f62bcfc7f (patch)
treee788679445d7ff0c854806631a99646c6226dc1d
parentb2407e4d7d25e4a5839bb512cb2fdf71e9e30a21 (diff)
Fixed #36471 -- Added support for __coveredby GIS lookup and Collect, GeoHash, IsValid on MariaDB 12.0.1+.
-rw-r--r--django/contrib/gis/db/backends/mysql/operations.py12
-rw-r--r--docs/ref/contrib/gis/db-api.txt93
-rw-r--r--docs/ref/contrib/gis/functions.txt12
-rw-r--r--docs/ref/contrib/gis/geoquerysets.txt35
-rw-r--r--docs/releases/6.0.txt6
-rw-r--r--tests/gis_tests/relatedapp/tests.py9
6 files changed, 101 insertions, 66 deletions
diff --git a/django/contrib/gis/db/backends/mysql/operations.py b/django/contrib/gis/db/backends/mysql/operations.py
index 8af78d8703..f838a79da6 100644
--- a/django/contrib/gis/db/backends/mysql/operations.py
+++ b/django/contrib/gis/db/backends/mysql/operations.py
@@ -45,6 +45,7 @@ class MySQLOperations(BaseSpatialOperations, DatabaseOperations):
"bboverlaps": SpatialOperator(func="MBROverlaps"), # ...
"contained": SpatialOperator(func="MBRWithin"), # ...
"contains": SpatialOperator(func="ST_Contains"),
+ "coveredby": SpatialOperator(func="MBRCoveredBy"),
"crosses": SpatialOperator(func="ST_Crosses"),
"disjoint": SpatialOperator(func="ST_Disjoint"),
"equals": SpatialOperator(func="ST_Equals"),
@@ -57,9 +58,10 @@ class MySQLOperations(BaseSpatialOperations, DatabaseOperations):
}
if self.connection.mysql_is_mariadb:
operators["relate"] = SpatialOperator(func="ST_Relate")
+ if self.connection.mysql_version < (12, 0, 1):
+ del operators["coveredby"]
else:
operators["covers"] = SpatialOperator(func="MBRCovers")
- operators["coveredby"] = SpatialOperator(func="MBRCoveredBy")
return operators
@cached_property
@@ -71,7 +73,10 @@ class MySQLOperations(BaseSpatialOperations, DatabaseOperations):
models.Union,
]
is_mariadb = self.connection.mysql_is_mariadb
- if is_mariadb or self.connection.mysql_version < (8, 0, 24):
+ if is_mariadb:
+ if self.connection.mysql_version < (12, 0, 1):
+ disallowed_aggregates.insert(0, models.Collect)
+ elif self.connection.mysql_version < (8, 0, 24):
disallowed_aggregates.insert(0, models.Collect)
return tuple(disallowed_aggregates)
@@ -106,7 +111,8 @@ class MySQLOperations(BaseSpatialOperations, DatabaseOperations):
}
if self.connection.mysql_is_mariadb:
unsupported.remove("PointOnSurface")
- unsupported.update({"GeoHash", "IsValid"})
+ if self.connection.mysql_version < (12, 0, 1):
+ unsupported.update({"GeoHash", "IsValid"})
return unsupported
def geo_db_type(self, f):
diff --git a/docs/ref/contrib/gis/db-api.txt b/docs/ref/contrib/gis/db-api.txt
index ee365b9320..5ce009e9bb 100644
--- a/docs/ref/contrib/gis/db-api.txt
+++ b/docs/ref/contrib/gis/db-api.txt
@@ -339,42 +339,42 @@ divided into the three categories described in the :ref:`raster lookup details
<spatial-lookup-raster>`: native support ``N``, bilateral native support ``B``,
and geometry conversion support ``C``.
-================================= ========= ======== ========== ============ ========== ========
-Lookup Type PostGIS Oracle MariaDB MySQL [#]_ SpatiaLite PGRaster
-================================= ========= ======== ========== ============ ========== ========
-:lookup:`bbcontains` X X X X N
-:lookup:`bboverlaps` X X X X N
-:lookup:`contained` X X X X N
-:lookup:`contains <gis-contains>` X X X X X B
-:lookup:`contains_properly` X B
-:lookup:`coveredby` X X X X B
-:lookup:`covers` X X X X B
-:lookup:`crosses` X X X X C
-:lookup:`disjoint` X X X X X B
-:lookup:`distance_gt` X X X X X N
-:lookup:`distance_gte` X X X X X N
-:lookup:`distance_lt` X X X X X N
-:lookup:`distance_lte` X X X X X N
-:lookup:`dwithin` X X X B
-: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 Type PostGIS Oracle MariaDB MySQL [#]_ SpatiaLite PGRaster
+================================= ========= ======== ============ ============ ========== ========
+:lookup:`bbcontains` X X X X N
+:lookup:`bboverlaps` X X X X N
+:lookup:`contained` X X X X N
+:lookup:`contains <gis-contains>` X X X X X B
+:lookup:`contains_properly` X B
+:lookup:`coveredby` X X X (≥ 12.0.1) X X B
+:lookup:`covers` X X X X B
+:lookup:`crosses` X X X X C
+:lookup:`disjoint` X X X X X B
+:lookup:`distance_gt` X X X X X N
+:lookup:`distance_gte` X X X X X N
+:lookup:`distance_lt` X X X X X N
+:lookup:`distance_lte` X X X X X N
+:lookup:`dwithin` X X X B
+: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:`isempty` 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
-:lookup:`touches` X X X X X B
-:lookup:`within` X X X X X B
-:lookup:`left` X C
-:lookup:`right` X C
-:lookup:`overlaps_left` X B
-:lookup:`overlaps_right` X B
-:lookup:`overlaps_above` X C
-:lookup:`overlaps_below` X C
-:lookup:`strictly_above` X C
-:lookup:`strictly_below` X C
-================================= ========= ======== ========== ============ ========== ========
+:lookup:`isvalid` X X X (≥ 12.0.1) 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
+:lookup:`touches` X X X X X B
+:lookup:`within` X X X X X B
+:lookup:`left` X C
+:lookup:`right` X C
+:lookup:`overlaps_left` X B
+:lookup:`overlaps_right` X B
+:lookup:`overlaps_above` X C
+:lookup:`overlaps_below` X C
+:lookup:`strictly_above` X C
+:lookup:`strictly_below` X C
+================================= ========= ======== ============ ============ ========== ========
.. _database-functions-compatibility:
@@ -406,11 +406,11 @@ Function PostGIS Oracle MariaDB MySQL
:class:`ForcePolygonCW` X X
:class:`FromWKB` X X X X X
:class:`FromWKT` X X X X X
-:class:`GeoHash` X X X (LWGEOM/RTTOPO)
+:class:`GeoHash` X X (≥ 12.0.1) X X (LWGEOM/RTTOPO)
:class:`GeometryDistance` X
:class:`Intersection` X X X X X
:class:`IsEmpty` X
-:class:`IsValid` X X X X
+:class:`IsValid` X X X (≥ 12.0.1) X X
:class:`Length` X X X X X
:class:`LineLocatePoint` X X
:class:`MakeValid` X X (LWGEOM/RTTOPO)
@@ -433,20 +433,19 @@ Aggregate Functions
-------------------
The following table provides a summary of what GIS-specific aggregate functions
-are available on each spatial backend. Please note that MariaDB does not
-support any of these aggregates, and is thus excluded from the table.
+are available on each spatial backend.
.. currentmodule:: django.contrib.gis.db.models
-======================= ======= ====== ============ ==========
-Aggregate PostGIS Oracle MySQL SpatiaLite
-======================= ======= ====== ============ ==========
-:class:`Collect` X X (≥ 8.0.24) X
-:class:`Extent` X X X
+======================= ======= ====== ============ ============ ==========
+Aggregate PostGIS Oracle MariaDB MySQL SpatiaLite
+======================= ======= ====== ============ ============ ==========
+:class:`Collect` X X (≥ 12.0.1) X (≥ 8.0.24) X
+:class:`Extent` X X X
:class:`Extent3D` X
-:class:`MakeLine` X X
-:class:`Union` X X X
-======================= ======= ====== ============ ==========
+:class:`MakeLine` X X
+:class:`Union` X X X
+======================= ======= ====== ============ ============ ==========
.. rubric:: Footnotes
.. [#fnwkt] *See* Open Geospatial Consortium, Inc., `OpenGIS Simple Feature Specification For SQL <https://portal.ogc.org/files/?artifact_id=829>`_, Document 99-049 (May 5, 1999), at Ch. 3.2.5, p. 3-11 (SQL Textual Representation of Geometry).
diff --git a/docs/ref/contrib/gis/functions.txt b/docs/ref/contrib/gis/functions.txt
index 3133e89b59..f9939c5e63 100644
--- a/docs/ref/contrib/gis/functions.txt
+++ b/docs/ref/contrib/gis/functions.txt
@@ -589,7 +589,7 @@ Example:
.. class:: GeoHash(expression, precision=None, **extra)
-*Availability*: `MySQL
+*Availability*: MariaDB, `MySQL
<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)
@@ -602,6 +602,10 @@ result.
__ https://en.wikipedia.org/wiki/Geohash
+.. versionchanged:: 6.0
+
+ MariaDB 12.0.1+ support was added.
+
Miscellaneous
=============
@@ -620,13 +624,17 @@ geometry. Returns ``True`` if its value is empty and ``False`` otherwise.
.. class:: IsValid(expr)
-*Availability*: `MySQL
+*Availability*: MariaDB, `MySQL
<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.
Returns ``True`` if its value is a valid geometry and ``False`` otherwise.
+.. versionchanged:: 6.0
+
+ MariaDB 12.0.1+ support was added.
+
``MemSize``
-----------
diff --git a/docs/ref/contrib/gis/geoquerysets.txt b/docs/ref/contrib/gis/geoquerysets.txt
index 5881eb0a85..0231ce6af8 100644
--- a/docs/ref/contrib/gis/geoquerysets.txt
+++ b/docs/ref/contrib/gis/geoquerysets.txt
@@ -183,7 +183,7 @@ PostGIS ``ST_ContainsProperly(poly, geom)``
-------------
*Availability*: `PostGIS <https://postgis.net/docs/ST_CoveredBy.html>`__,
-Oracle, MySQL, PGRaster (Bilateral), SpatiaLite
+Oracle, MariaDB, MySQL, PGRaster (Bilateral), SpatiaLite
Tests if no point in the geometry field is outside the lookup geometry.
[#fncovers]_
@@ -197,6 +197,7 @@ Backend SQL Equivalent
========== =============================
PostGIS ``ST_CoveredBy(poly, geom)``
Oracle ``SDO_COVEREDBY(poly, geom)``
+MariaDB ``MBRCoveredBy(poly, geom)``
MySQL ``MBRCoveredBy(poly, geom)``
SpatiaLite ``CoveredBy(poly, geom)``
========== =============================
@@ -205,6 +206,10 @@ SpatiaLite ``CoveredBy(poly, geom)``
MySQL support was added.
+.. versionchanged:: 6.0
+
+ MariaDB 12.0.1+ support was added.
+
.. fieldlookup:: covers
``covers``
@@ -374,8 +379,8 @@ Example::
``isvalid``
-----------
-*Availability*: MySQL, `PostGIS <https://postgis.net/docs/ST_IsValid.html>`__,
-Oracle, SpatiaLite
+*Availability*: MariaDB, MySQL,
+`PostGIS <https://postgis.net/docs/ST_IsValid.html>`__, Oracle, SpatiaLite
Tests if the geometry is valid.
@@ -383,12 +388,16 @@ Example::
Zipcode.objects.filter(poly__isvalid=True)
-========================== ================================================================
-Backend SQL Equivalent
-========================== ================================================================
-MySQL, PostGIS, SpatiaLite ``ST_IsValid(poly)``
-Oracle ``SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT(poly, 0.05) = 'TRUE'``
-========================== ================================================================
+=================================== ================================================================
+Backend SQL Equivalent
+=================================== ================================================================
+MariaDB, MySQL, PostGIS, SpatiaLite ``ST_IsValid(poly)``
+Oracle ``SDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXT(poly, 0.05) = 'TRUE'``
+=================================== ================================================================
+
+.. versionchanged:: 6.0
+
+ MariaDB 12.0.1+ support was added.
.. fieldlookup:: overlaps
@@ -880,8 +889,8 @@ Example:
.. class:: Collect(geo_field, filter=None)
-*Availability*: `PostGIS <https://postgis.net/docs/ST_Collect.html>`__, MySQL,
-SpatiaLite
+*Availability*: `PostGIS <https://postgis.net/docs/ST_Collect.html>`__,
+MariaDB, MySQL, SpatiaLite
Returns a ``GEOMETRYCOLLECTION`` or a ``MULTI`` geometry object from the geometry
column. This is analogous to a simplified version of the :class:`Union`
@@ -889,6 +898,10 @@ aggregate, except it can be several orders of magnitude faster than performing
a union because it rolls up geometries into a collection or multi object, not
caring about dissolving boundaries.
+.. versionchanged:: 6.0
+
+ MariaDB 12.0.1+ support was added.
+
``Extent``
~~~~~~~~~~
diff --git a/docs/releases/6.0.txt b/docs/releases/6.0.txt
index 304343256f..e653884163 100644
--- a/docs/releases/6.0.txt
+++ b/docs/releases/6.0.txt
@@ -76,6 +76,12 @@ Minor features
* The new :attr:`.BaseGeometryWidget.base_layer` attribute allows specifying a
JavaScript map base layer, enabling customization of map tile providers.
+* :lookup:`coveredby` and :lookup:`isvalid` lookups,
+ :class:`~django.contrib.gis.db.models.Collect` aggregation, and
+ :class:`~django.contrib.gis.db.models.functions.GeoHash` and
+ :class:`~django.contrib.gis.db.models.functions.IsValid` database functions
+ are now supported on MariaDB 12.0.1+.
+
:mod:`django.contrib.messages`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/gis_tests/relatedapp/tests.py b/tests/gis_tests/relatedapp/tests.py
index 303d357705..2db635b0c0 100644
--- a/tests/gis_tests/relatedapp/tests.py
+++ b/tests/gis_tests/relatedapp/tests.py
@@ -346,9 +346,12 @@ class RelatedGeoModelTest(TestCase):
)
)
city = qs.get(name="Aurora")
- self.assertIsInstance(city.parcel_centroid, Point)
- self.assertAlmostEqual(city.parcel_centroid[0], 3.2128, 4)
- self.assertAlmostEqual(city.parcel_centroid[1], 1.5, 4)
+ if connection.ops.mariadb:
+ self.assertIsNone(city.parcel_centroid)
+ else:
+ self.assertIsInstance(city.parcel_centroid, Point)
+ self.assertAlmostEqual(city.parcel_centroid[0], 3.2128, 4)
+ self.assertAlmostEqual(city.parcel_centroid[1], 1.5, 4)
@skipUnlessDBFeature("supports_make_line_aggr")
def test_make_line_filter(self):