Fixed #17796 -- Rolled back [17588] because the fix for the original relatively
corner case (boolean fields under MySQL spatial backend) had a wider scope with potentially unintended consequences affecting the main MySQL backend and the required changes wouldn't be appropiate at this point of the 1.4 development cycle. Refs #15169. git-svn-id: http://code.djangoproject.com/svn/django/trunk@17603 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
c471cfd674
commit
ae640e5ea0
|
@ -1,22 +0,0 @@
|
||||||
from django.contrib.gis.db.models.sql.compiler import GeoSQLCompiler as BaseGeoSQLCompiler
|
|
||||||
from django.db.backends.mysql import compiler
|
|
||||||
|
|
||||||
SQLCompiler = compiler.SQLCompiler
|
|
||||||
|
|
||||||
class GeoSQLCompiler(BaseGeoSQLCompiler, SQLCompiler):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class SQLInsertCompiler(compiler.SQLInsertCompiler, GeoSQLCompiler):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class SQLDeleteCompiler(compiler.SQLDeleteCompiler, GeoSQLCompiler):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class SQLUpdateCompiler(compiler.SQLUpdateCompiler, GeoSQLCompiler):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class SQLAggregateCompiler(compiler.SQLAggregateCompiler, GeoSQLCompiler):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class SQLDateCompiler(compiler.SQLDateCompiler, GeoSQLCompiler):
|
|
||||||
pass
|
|
|
@ -5,7 +5,7 @@ from django.contrib.gis.db.backends.base import BaseSpatialOperations
|
||||||
|
|
||||||
class MySQLOperations(DatabaseOperations, BaseSpatialOperations):
|
class MySQLOperations(DatabaseOperations, BaseSpatialOperations):
|
||||||
|
|
||||||
compiler_module = 'django.contrib.gis.db.backends.mysql.compiler'
|
compiler_module = 'django.contrib.gis.db.models.sql.compiler'
|
||||||
mysql = True
|
mysql = True
|
||||||
name = 'mysql'
|
name = 'mysql'
|
||||||
select = 'AsText(%s)'
|
select = 'AsText(%s)'
|
||||||
|
|
|
@ -185,10 +185,9 @@ class GeoSQLCompiler(compiler.SQLCompiler):
|
||||||
self.query.extra_select_fields.get(a, None),
|
self.query.extra_select_fields.get(a, None),
|
||||||
self.connection)
|
self.connection)
|
||||||
for v, a in izip(row[rn_offset:index_start], aliases)]
|
for v, a in izip(row[rn_offset:index_start], aliases)]
|
||||||
|
if self.connection.ops.oracle or getattr(self.query, 'geo_values', False):
|
||||||
if self.connection.ops.oracle or self.connection.ops.mysql or getattr(self.query, 'geo_values', False):
|
# We resolve the rest of the columns if we're on Oracle or if
|
||||||
# We resolve the rest of the columns if we're on MySQL, Oracle or
|
# the `geo_values` attribute is defined.
|
||||||
# if the `geo_values` attribute is defined.
|
|
||||||
for value, field in map(None, row[index_start:], fields):
|
for value, field in map(None, row[index_start:], fields):
|
||||||
values.append(self.query.convert_values(value, field, self.connection))
|
values.append(self.query.convert_values(value, field, self.connection))
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -56,8 +56,8 @@ class GeoQuery(sql.Query):
|
||||||
extra selection objects into Geometry and Distance objects.
|
extra selection objects into Geometry and Distance objects.
|
||||||
TODO: Make converted objects 'lazy' for less overhead.
|
TODO: Make converted objects 'lazy' for less overhead.
|
||||||
"""
|
"""
|
||||||
if connection.ops.oracle or connection.ops.mysql:
|
if connection.ops.oracle:
|
||||||
# On MySQL and Oracle, call their version of `convert_values` first.
|
# Running through Oracle's first.
|
||||||
value = super(GeoQuery, self).convert_values(value, field or GeomField(), connection)
|
value = super(GeoQuery, self).convert_values(value, field or GeomField(), connection)
|
||||||
|
|
||||||
if value is None:
|
if value is None:
|
||||||
|
|
|
@ -34,10 +34,6 @@ class Track(models.Model):
|
||||||
objects = models.GeoManager()
|
objects = models.GeoManager()
|
||||||
def __unicode__(self): return self.name
|
def __unicode__(self): return self.name
|
||||||
|
|
||||||
class Truth(models.Model):
|
|
||||||
val = models.BooleanField()
|
|
||||||
objects = models.GeoManager()
|
|
||||||
|
|
||||||
if not spatialite:
|
if not spatialite:
|
||||||
class Feature(models.Model):
|
class Feature(models.Model):
|
||||||
name = models.CharField(max_length=20)
|
name = models.CharField(max_length=20)
|
||||||
|
|
|
@ -7,7 +7,7 @@ from django.contrib.gis.shortcuts import render_to_kmz
|
||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from .models import City, PennsylvaniaCity, State, Truth
|
from .models import City, PennsylvaniaCity, State
|
||||||
|
|
||||||
|
|
||||||
class GeoRegressionTests(TestCase):
|
class GeoRegressionTests(TestCase):
|
||||||
|
@ -64,11 +64,3 @@ class GeoRegressionTests(TestCase):
|
||||||
"Regression for #16409 - make sure defer() and only() work with annotate()"
|
"Regression for #16409 - make sure defer() and only() work with annotate()"
|
||||||
self.assertIsInstance(list(City.objects.annotate(Count('point')).defer('name')), list)
|
self.assertIsInstance(list(City.objects.annotate(Count('point')).defer('name')), list)
|
||||||
self.assertIsInstance(list(City.objects.annotate(Count('point')).only('name')), list)
|
self.assertIsInstance(list(City.objects.annotate(Count('point')).only('name')), list)
|
||||||
|
|
||||||
def test04_boolean_conversion(self):
|
|
||||||
"Testing Boolean value conversion with the spatial backend, see #15169."
|
|
||||||
t1 = Truth.objects.create(val=True)
|
|
||||||
t2 = Truth.objects.create(val=False)
|
|
||||||
|
|
||||||
self.assertTrue(Truth.objects.get(pk=1).val is True)
|
|
||||||
self.assertTrue(Truth.objects.get(pk=2).val is False)
|
|
||||||
|
|
|
@ -190,12 +190,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
||||||
class DatabaseOperations(BaseDatabaseOperations):
|
class DatabaseOperations(BaseDatabaseOperations):
|
||||||
compiler_module = "django.db.backends.mysql.compiler"
|
compiler_module = "django.db.backends.mysql.compiler"
|
||||||
|
|
||||||
def convert_values(self, value, field):
|
|
||||||
if (field and field.get_internal_type() in ("BooleanField", "NullBooleanField") and
|
|
||||||
value in (0, 1)):
|
|
||||||
value = bool(value)
|
|
||||||
return value
|
|
||||||
|
|
||||||
def date_extract_sql(self, lookup_type, field_name):
|
def date_extract_sql(self, lookup_type, field_name):
|
||||||
# http://dev.mysql.com/doc/mysql/en/date-and-time-functions.html
|
# http://dev.mysql.com/doc/mysql/en/date-and-time-functions.html
|
||||||
if lookup_type == 'week_day':
|
if lookup_type == 'week_day':
|
||||||
|
|
|
@ -5,7 +5,10 @@ class SQLCompiler(compiler.SQLCompiler):
|
||||||
values = []
|
values = []
|
||||||
index_extra_select = len(self.query.extra_select.keys())
|
index_extra_select = len(self.query.extra_select.keys())
|
||||||
for value, field in map(None, row[index_extra_select:], fields):
|
for value, field in map(None, row[index_extra_select:], fields):
|
||||||
values.append(self.query.convert_values(value, field, connection=self.connection))
|
if (field and field.get_internal_type() in ("BooleanField", "NullBooleanField") and
|
||||||
|
value in (0, 1)):
|
||||||
|
value = bool(value)
|
||||||
|
values.append(value)
|
||||||
return row[:index_extra_select] + tuple(values)
|
return row[:index_extra_select] + tuple(values)
|
||||||
|
|
||||||
class SQLInsertCompiler(compiler.SQLInsertCompiler, SQLCompiler):
|
class SQLInsertCompiler(compiler.SQLInsertCompiler, SQLCompiler):
|
||||||
|
|
Loading…
Reference in New Issue