Skip to content

Commit

Permalink
Fixed #15169 -- Corrected handling of model boolean fields in MySQL s…
Browse files Browse the repository at this point in the history
…patial backend.

Thanks goes to zmsmith and others for reporting the issue and to Justin Bronn for the fix.

Refs #7190, r12578, r12900, #13293, r12939.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17588 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
ramiro committed Feb 26, 2012
1 parent 5a013ce commit 9f6859e
Show file tree
Hide file tree
Showing 7 changed files with 27 additions and 11 deletions.
2 changes: 1 addition & 1 deletion django/contrib/gis/db/backends/mysql/operations.py
Expand Up @@ -5,7 +5,7 @@

class MySQLOperations(DatabaseOperations, BaseSpatialOperations):

compiler_module = 'django.contrib.gis.db.models.sql.compiler'
compiler_module = 'django.contrib.gis.db.backends.mysql.compiler'
mysql = True
name = 'mysql'
select = 'AsText(%s)'
Expand Down
7 changes: 4 additions & 3 deletions django/contrib/gis/db/models/sql/compiler.py
Expand Up @@ -185,9 +185,10 @@ def resolve_columns(self, row, fields=()):
self.query.extra_select_fields.get(a, None),
self.connection)
for v, a in izip(row[rn_offset:index_start], aliases)]
if self.connection.ops.oracle or getattr(self.query, 'geo_values', False):
# We resolve the rest of the columns if we're on Oracle or if
# the `geo_values` attribute is defined.

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 MySQL, Oracle or
# if the `geo_values` attribute is defined.
for value, field in map(None, row[index_start:], fields):
values.append(self.query.convert_values(value, field, self.connection))
else:
Expand Down
4 changes: 2 additions & 2 deletions django/contrib/gis/db/models/sql/query.py
Expand Up @@ -56,8 +56,8 @@ def convert_values(self, value, field, connection):
extra selection objects into Geometry and Distance objects.
TODO: Make converted objects 'lazy' for less overhead.
"""
if connection.ops.oracle:
# Running through Oracle's first.
if connection.ops.oracle or connection.ops.mysql:
# On MySQL and Oracle, call their version of `convert_values` first.
value = super(GeoQuery, self).convert_values(value, field or GeomField(), connection)

if value is None:
Expand Down
4 changes: 4 additions & 0 deletions django/contrib/gis/tests/geoapp/models.py
Expand Up @@ -34,6 +34,10 @@ class Track(models.Model):
objects = models.GeoManager()
def __unicode__(self): return self.name

class Truth(models.Model):
val = models.BooleanField()
objects = models.GeoManager()

if not spatialite:
class Feature(models.Model):
name = models.CharField(max_length=20)
Expand Down
10 changes: 9 additions & 1 deletion django/contrib/gis/tests/geoapp/test_regress.py
Expand Up @@ -7,7 +7,7 @@
from django.db.models import Count
from django.test import TestCase

from .models import City, PennsylvaniaCity, State
from .models import City, PennsylvaniaCity, State, Truth


class GeoRegressionTests(TestCase):
Expand Down Expand Up @@ -64,3 +64,11 @@ def test06_defer_or_only_with_annotate(self):
"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')).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)
6 changes: 6 additions & 0 deletions django/db/backends/mysql/base.py
Expand Up @@ -176,6 +176,12 @@ def _can_introspect_foreign_keys(self):
class DatabaseOperations(BaseDatabaseOperations):
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):
# http://dev.mysql.com/doc/mysql/en/date-and-time-functions.html
if lookup_type == 'week_day':
Expand Down
5 changes: 1 addition & 4 deletions django/db/backends/mysql/compiler.py
Expand Up @@ -5,10 +5,7 @@ def resolve_columns(self, row, fields=()):
values = []
index_extra_select = len(self.query.extra_select.keys())
for value, field in map(None, row[index_extra_select:], fields):
if (field and field.get_internal_type() in ("BooleanField", "NullBooleanField") and
value in (0, 1)):
value = bool(value)
values.append(value)
values.append(self.query.convert_values(value, field, connection=self.connection))
return row[:index_extra_select] + tuple(values)

class SQLInsertCompiler(compiler.SQLInsertCompiler, SQLCompiler):
Expand Down

0 comments on commit 9f6859e

Please sign in to comment.