Added SpatialFeatures.empty_intersection_returns_none.

This commit is contained in:
Tim Graham 2020-11-11 22:23:22 -05:00 committed by Mariusz Felisiak
parent 4c62cdaa10
commit 9f91122ed8
4 changed files with 20 additions and 10 deletions

View File

@ -54,6 +54,10 @@ class BaseSpatialFeatures:
# Set of options that AsGeoJSON() doesn't support. # Set of options that AsGeoJSON() doesn't support.
unsupported_geojson_options = {} unsupported_geojson_options = {}
# Does Intersection() return None (rather than an empty GeometryCollection)
# for empty results?
empty_intersection_returns_none = True
@property @property
def supports_bbcontains_lookup(self): def supports_bbcontains_lookup(self):
return 'bbcontains' in self.connection.ops.gis_operators return 'bbcontains' in self.connection.ops.gis_operators

View File

@ -17,8 +17,11 @@ class DatabaseFeatures(BaseSpatialFeatures, MySQLDatabaseFeatures):
unsupported_geojson_options = {'crs'} unsupported_geojson_options = {'crs'}
@cached_property @cached_property
def supports_empty_geometry_collection(self): def empty_intersection_returns_none(self):
return self.connection.mysql_version >= (5, 7, 5) return (
not self.connection.mysql_is_mariadb and
self.connection.mysql_version < (5, 7, 5)
)
@cached_property @cached_property
def supports_geometry_field_unique_index(self): def supports_geometry_field_unique_index(self):

View File

@ -10,3 +10,4 @@ class DatabaseFeatures(BaseSpatialFeatures, Psycopg2DatabaseFeatures):
supports_3d_functions = True supports_3d_functions = True
supports_raster = True supports_raster = True
supports_empty_geometries = True supports_empty_geometries = True
empty_intersection_returns_none = False

View File

@ -12,7 +12,7 @@ from django.db import NotSupportedError, connection
from django.db.models import IntegerField, Sum, Value from django.db.models import IntegerField, Sum, Value
from django.test import TestCase, skipUnlessDBFeature from django.test import TestCase, skipUnlessDBFeature
from ..utils import FuncTestMixin, mariadb, mysql, oracle, postgis, spatialite from ..utils import FuncTestMixin, mariadb, mysql, oracle, postgis
from .models import City, Country, CountryWebMercator, State, Track from .models import City, Country, CountryWebMercator, State, Track
@ -295,11 +295,10 @@ class GISFunctionsTests(FuncTestMixin, TestCase):
geom = Point(5, 23, srid=4326) geom = Point(5, 23, srid=4326)
qs = Country.objects.annotate(inter=functions.Intersection('mpoly', geom)) qs = Country.objects.annotate(inter=functions.Intersection('mpoly', geom))
for c in qs: for c in qs:
if spatialite or (mysql and not connection.features.supports_empty_geometry_collection) or oracle: expected = (
# When the intersection is empty, some databases return None. None if connection.features.empty_intersection_returns_none
expected = None else c.mpoly.intersection(geom)
else: )
expected = c.mpoly.intersection(geom)
self.assertEqual(c.inter, expected) self.assertEqual(c.inter, expected)
@skipUnlessDBFeature("has_IsValid_function") @skipUnlessDBFeature("has_IsValid_function")
@ -570,8 +569,11 @@ class GISFunctionsTests(FuncTestMixin, TestCase):
return return
for c in qs: for c in qs:
self.assertTrue(c.mpoly.difference(geom).equals(c.difference)) self.assertTrue(c.mpoly.difference(geom).equals(c.difference))
if not (spatialite or mysql): expected_intersection = (
self.assertEqual(c.mpoly.intersection(geom), c.intersection) None if connection.features.empty_intersection_returns_none
else c.mpoly.intersection(geom)
)
self.assertEqual(c.intersection, expected_intersection)
self.assertTrue(c.mpoly.sym_difference(geom).equals(c.sym_difference)) self.assertTrue(c.mpoly.sym_difference(geom).equals(c.sym_difference))
self.assertTrue(c.mpoly.union(geom).equals(c.union)) self.assertTrue(c.mpoly.union(geom).equals(c.union))