Browse Source

Fixed #30890 -- Added MariaDB support for the relate lookup.

Mariusz Felisiak 5 years ago
parent
commit
3a8af298b9

+ 4 - 1
django/contrib/gis/db/backends/mysql/operations.py

@@ -29,7 +29,7 @@ class MySQLOperations(BaseSpatialOperations, DatabaseOperations):
 
     @cached_property
     def gis_operators(self):
-        return {
+        operators = {
             'bbcontains': SpatialOperator(func='MBRContains'),  # For consistency w/PostGIS API
             'bboverlaps': SpatialOperator(func='MBROverlaps'),  # ...
             'contained': SpatialOperator(func='MBRWithin'),  # ...
@@ -44,6 +44,9 @@ class MySQLOperations(BaseSpatialOperations, DatabaseOperations):
             'touches': SpatialOperator(func='ST_Touches'),
             'within': SpatialOperator(func='ST_Within'),
         }
+        if self.connection.mysql_is_mariadb:
+            operators['relate'] = SpatialOperator(func='ST_Relate')
+        return operators
 
     disallowed_aggregates = (
         aggregates.Collect, aggregates.Extent, aggregates.Extent3D,

+ 1 - 1
docs/ref/contrib/gis/db-api.txt

@@ -332,7 +332,7 @@ Lookup Type                        PostGIS    Oracle   MariaDB   MySQL [#]_   Sp
 :lookup:`intersects`               X          X        X         X            X          B
 :lookup:`isvalid`                  X          X                  X (≥ 5.7.5)  X (LWGEOM)
 :lookup:`overlaps`                 X          X        X         X            X          B
-:lookup:`relate`                   X          X                               X          C
+: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

+ 9 - 4
docs/ref/contrib/gis/geoquerysets.txt

@@ -426,14 +426,15 @@ SpatiaLite  ``Overlaps(poly, geom)``
 ----------
 
 *Availability*: `PostGIS <https://postgis.net/docs/ST_Relate.html>`__,
-Oracle, SpatiaLite, PGRaster (Conversion)
+MariaDB, Oracle, SpatiaLite, PGRaster (Conversion)
 
 Tests if the geometry field is spatially related to the lookup geometry by
 the values given in the given pattern.  This lookup requires a tuple parameter,
 ``(geom, pattern)``; the form of ``pattern`` will depend on the spatial backend:
 
-PostGIS & SpatiaLite
-~~~~~~~~~~~~~~~~~~~~
+MariaDB, PostGIS, and SpatiaLite
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 On these spatial backends the intersection pattern is a string comprising
 nine characters, which  define intersections between  the interior, boundary,
 and exterior of the geometry field and the lookup geometry.
@@ -447,7 +448,7 @@ Geometry example::
     # the intersection pattern (the pattern here is for 'contains').
     Zipcode.objects.filter(poly__relate=(geom, 'T*T***FF*'))
 
-PostGIS SQL equivalent:
+PostGIS and MariaDB SQL equivalent:
 
 .. code-block:: sql
 
@@ -471,6 +472,10 @@ PostGIS SQL equivalent:
     SELECT ... WHERE ST_Relate(poly, ST_Polygon(rast, 1), 'T*T***FF*')
     SELECT ... WHERE ST_Relate(ST_Polygon(rast, 2), ST_Polygon(rast, 1), 'T*T***FF*')
 
+.. versionchanged:: 3.1
+
+    MariaDB support was added.
+
 Oracle
 ~~~~~~
 

+ 1 - 1
docs/releases/3.1.txt

@@ -59,7 +59,7 @@ Minor features
 :mod:`django.contrib.gis`
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
-* ...
+* :lookup:`relate` lookup is now supported on MariaDB.
 
 :mod:`django.contrib.messages`
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

+ 11 - 3
tests/gis_tests/geoapp/tests.py

@@ -450,7 +450,7 @@ class GeoLookupTest(TestCase):
                 qs.count()
 
         # Relate works differently for the different backends.
-        if postgis or spatialite:
+        if postgis or spatialite or mariadb:
             contains_mask = 'T*T***FF*'
             within_mask = 'T*F**F***'
             intersects_mask = 'T********'
@@ -461,7 +461,11 @@ class GeoLookupTest(TestCase):
             intersects_mask = 'overlapbdyintersect'
 
         # Testing contains relation mask.
-        self.assertEqual('Texas', Country.objects.get(mpoly__relate=(pnt1, contains_mask)).name)
+        if connection.features.supports_transform:
+            self.assertEqual(
+                Country.objects.get(mpoly__relate=(pnt1, contains_mask)).name,
+                'Texas',
+            )
         self.assertEqual('Texas', Country.objects.get(mpoly__relate=(pnt2, contains_mask)).name)
 
         # Testing within relation mask.
@@ -470,7 +474,11 @@ class GeoLookupTest(TestCase):
 
         # Testing intersection relation mask.
         if not oracle:
-            self.assertEqual('Texas', Country.objects.get(mpoly__relate=(pnt1, intersects_mask)).name)
+            if connection.features.supports_transform:
+                self.assertEqual(
+                    Country.objects.get(mpoly__relate=(pnt1, intersects_mask)).name,
+                    'Texas',
+                )
             self.assertEqual('Texas', Country.objects.get(mpoly__relate=(pnt2, intersects_mask)).name)
             self.assertEqual('Lawrence', City.objects.get(point__relate=(ks.poly, intersects_mask)).name)