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

This commit is contained in:
Mariusz Felisiak 2019-10-17 14:02:37 +02:00
parent bebf61de11
commit 3a8af298b9
5 changed files with 26 additions and 10 deletions

View File

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

View File

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

View File

@ -426,14 +426,15 @@ SpatiaLite ``Overlaps(poly, geom)``
---------- ----------
*Availability*: `PostGIS <https://postgis.net/docs/ST_Relate.html>`__, *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 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, 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: ``(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 On these spatial backends the intersection pattern is a string comprising
nine characters, which define intersections between the interior, boundary, nine characters, which define intersections between the interior, boundary,
and exterior of the geometry field and the lookup geometry. 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'). # the intersection pattern (the pattern here is for 'contains').
Zipcode.objects.filter(poly__relate=(geom, 'T*T***FF*')) Zipcode.objects.filter(poly__relate=(geom, 'T*T***FF*'))
PostGIS SQL equivalent: PostGIS and MariaDB SQL equivalent:
.. code-block:: sql .. 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(poly, ST_Polygon(rast, 1), 'T*T***FF*')
SELECT ... WHERE ST_Relate(ST_Polygon(rast, 2), 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 Oracle
~~~~~~ ~~~~~~

View File

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

View File

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