mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #36471 -- Added support for __coveredby GIS lookup and Collect, GeoHash, IsValid on MariaDB 12.0.1+.
This commit is contained in:
		
				
					committed by
					
						 Sarah Boyce
						Sarah Boyce
					
				
			
			
				
	
			
			
			
						parent
						
							b2407e4d7d
						
					
				
				
					commit
					7091801e04
				
			| @@ -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): | ||||
|   | ||||
| @@ -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). | ||||
|   | ||||
| @@ -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`` | ||||
| ----------- | ||||
|  | ||||
|   | ||||
| @@ -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`` | ||||
| ~~~~~~~~~~ | ||||
|  | ||||
|   | ||||
| @@ -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` | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
|   | ||||
| @@ -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): | ||||
|   | ||||
		Reference in New Issue
	
	Block a user