Refs #26657 -- Fixed a crash induced by invalid WKT returned by MySQL 5.7.5+.

This commit is contained in:
Sergey Fedoseev 2016-06-22 00:57:45 +05:00 committed by Tim Graham
parent 9031a4c13b
commit 4178488881
2 changed files with 19 additions and 2 deletions

View File

@ -2,7 +2,7 @@ from django.contrib.gis.db.backends.base.adapter import WKTAdapter
from django.contrib.gis.db.backends.base.operations import \ from django.contrib.gis.db.backends.base.operations import \
BaseSpatialOperations BaseSpatialOperations
from django.contrib.gis.db.backends.utils import SpatialOperator from django.contrib.gis.db.backends.utils import SpatialOperator
from django.contrib.gis.db.models import aggregates from django.contrib.gis.db.models import GeometryField, aggregates
from django.db.backends.mysql.operations import DatabaseOperations from django.db.backends.mysql.operations import DatabaseOperations
from django.utils.functional import cached_property from django.utils.functional import cached_property
@ -22,6 +22,10 @@ class MySQLOperations(BaseSpatialOperations, DatabaseOperations):
def is_mysql_5_6(self): def is_mysql_5_6(self):
return self.connection.mysql_version < (5, 7, 6) return self.connection.mysql_version < (5, 7, 6)
@cached_property
def uses_invalid_empty_geometry_collection(self):
return self.connection.mysql_version >= (5, 7, 5)
@cached_property @cached_property
def select(self): def select(self):
if self.is_mysql_5_5: if self.is_mysql_5_5:
@ -105,3 +109,16 @@ class MySQLOperations(BaseSpatialOperations, DatabaseOperations):
else: else:
placeholder = '%s(%%s)' % self.from_text placeholder = '%s(%%s)' % self.from_text
return placeholder return placeholder
def get_db_converters(self, expression):
converters = super(MySQLOperations, self).get_db_converters(expression)
if isinstance(expression.output_field, GeometryField) and self.uses_invalid_empty_geometry_collection:
converters.append(self.convert_invalid_empty_geometry_collection)
return converters
# https://dev.mysql.com/doc/refman/5.7/en/spatial-function-argument-handling.html
# MySQL 5.7.5 adds support for the empty geometry collections, but they are represented with invalid WKT.
def convert_invalid_empty_geometry_collection(self, value, expression, connection, context):
if value == b'GEOMETRYCOLLECTION()':
return b'GEOMETRYCOLLECTION EMPTY'
return value

View File

@ -223,7 +223,7 @@ class GISFunctionsTests(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 or oracle: if spatialite or (mysql and not connection.ops.uses_invalid_empty_geometry_collection) or oracle:
# When the intersection is empty, some databases return None. # When the intersection is empty, some databases return None.
expected = None expected = None
else: else: