diff --git a/django/contrib/gis/db/backends/mysql/operations.py b/django/contrib/gis/db/backends/mysql/operations.py index cfd780022f4..de64bc95db0 100644 --- a/django/contrib/gis/db/backends/mysql/operations.py +++ b/django/contrib/gis/db/backends/mysql/operations.py @@ -34,8 +34,11 @@ class MySQLOperations(BaseSpatialOperations, DatabaseOperations): } function_names = { + 'Difference': 'ST_Difference', 'Distance': 'ST_Distance', + 'Intersection': 'ST_Intersection', 'Length': 'GLength', + 'SymDifference': 'ST_SymDifference', 'Union': 'ST_Union', } @@ -48,12 +51,12 @@ class MySQLOperations(BaseSpatialOperations, DatabaseOperations): def unsupported_functions(self): unsupported = { 'AsGeoJSON', 'AsGML', 'AsKML', 'AsSVG', 'BoundingCircle', - 'Difference', 'ForceRHR', 'GeoHash', 'Intersection', 'MemSize', + 'ForceRHR', 'GeoHash', 'MemSize', 'Perimeter', 'PointOnSurface', 'Reverse', 'Scale', 'SnapToGrid', - 'SymDifference', 'Transform', 'Translate', + 'Transform', 'Translate', } if self.connection.mysql_version < (5, 6, 1): - unsupported.update({'Distance', 'Union'}) + unsupported.update({'Difference', 'Distance', 'Intersection', 'SymDifference', 'Union'}) 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 94228027e1d..75baf93b5a4 100644 --- a/docs/ref/contrib/gis/db-api.txt +++ b/docs/ref/contrib/gis/db-api.txt @@ -312,12 +312,12 @@ Function PostGIS Oracle MySQL SpatiaLite :class:`AsSVG` X X :class:`BoundingCircle` X :class:`Centroid` X X X X -:class:`Difference` X X X +:class:`Difference` X X X (≥ 5.6.1) X :class:`Distance` X X X (≥ 5.6.1) X :class:`Envelope` X X X :class:`ForceRHR` X :class:`GeoHash` X -:class:`Intersection` X X X +:class:`Intersection` X X X (≥ 5.6.1) X :class:`Length` X X X X :class:`MemSize` X :class:`NumGeometries` X X X X @@ -327,7 +327,7 @@ Function PostGIS Oracle MySQL SpatiaLite :class:`Reverse` X X X (≥ 4.0) :class:`Scale` X X :class:`SnapToGrid` X X (≥ 3.1) -:class:`SymDifference` X X X +:class:`SymDifference` X X X (≥ 5.6.1) X :class:`Transform` X X X :class:`Translate` X X :class:`Union` X X X (≥ 5.6.1) X diff --git a/tests/gis_tests/geoapp/test_functions.py b/tests/gis_tests/geoapp/test_functions.py index 745a0dee6f6..ff99cc48551 100644 --- a/tests/gis_tests/geoapp/test_functions.py +++ b/tests/gis_tests/geoapp/test_functions.py @@ -169,9 +169,9 @@ class GISFunctionsTests(TestCase): qs = qs.exclude(name='Texas') for c in qs: - self.assertEqual(c.mpoly.difference(geom), c.diff) + self.assertTrue(c.mpoly.difference(geom).equals(c.diff)) - @skipUnlessDBFeature("has_Difference_function") + @skipUnlessDBFeature("has_Difference_function", "has_Transform_function") def test_difference_mixed_srid(self): """Testing with mixed SRID (Country has default 4326).""" geom = Point(556597.4, 2632018.6, srid=3857) # Spherical mercator @@ -180,7 +180,7 @@ class GISFunctionsTests(TestCase): if spatialite: qs = qs.exclude(name='Texas') for c in qs: - self.assertEqual(c.mpoly.difference(geom), c.difference) + self.assertTrue(c.mpoly.difference(geom).equals(c.difference)) @skipUnlessDBFeature("has_Envelope_function") def test_envelope(self): @@ -218,8 +218,8 @@ class GISFunctionsTests(TestCase): geom = Point(5, 23, srid=4326) qs = Country.objects.annotate(inter=functions.Intersection('mpoly', geom)) for c in qs: - if spatialite: - # When the intersection is empty, Spatialite returns None + if spatialite or mysql: + # When the intersection is empty, Spatialite and MySQL return None expected = None else: expected = c.mpoly.intersection(geom) @@ -376,9 +376,7 @@ class GISFunctionsTests(TestCase): geom = Point(5, 23, srid=4326) qs = Country.objects.annotate(sym_difference=functions.SymDifference('mpoly', geom)) for country in qs: - # Ordering might differ in collections - self.assertSetEqual(set(g.wkt for g in country.mpoly.sym_difference(geom)), - set(g.wkt for g in country.sym_difference)) + self.assertTrue(country.mpoly.sym_difference(geom).equals(country.sym_difference)) @skipUnlessDBFeature("has_Transform_function") def test_transform(self): @@ -431,14 +429,11 @@ class GISFunctionsTests(TestCase): # SpatiaLite). return for c in qs: - self.assertEqual(c.mpoly.difference(geom), c.difference) - if not spatialite: + self.assertTrue(c.mpoly.difference(geom).equals(c.difference)) + if not (spatialite or mysql): self.assertEqual(c.mpoly.intersection(geom), c.intersection) - # Ordering might differ in collections - self.assertSetEqual(set(g.wkt for g in c.mpoly.sym_difference(geom)), - set(g.wkt for g in c.sym_difference)) - self.assertSetEqual(set(g.wkt for g in c.mpoly.union(geom)), - set(g.wkt for g in c.union)) + self.assertTrue(c.mpoly.sym_difference(geom).equals(c.sym_difference)) + self.assertTrue(c.mpoly.union(geom).equals(c.union)) @skipUnlessDBFeature("has_Union_function") def test_union(self):