#12239 closed (fixed)
Float is rounded to integer on queries on integer field
Reported by: | Adrian Andreias | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.1 |
Severity: | Keywords: | __gte, __lte, query rounding | |
Cc: | Triage Stage: | Accepted | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
On queries (gte, lte) ran on an integer field with a float value to compare, the float value gets rounded to integer and this causes invalid results.
class Number(models.Model): val = models.IntegerField() # Python 2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit (Intel)] on win32 # Type "help", "copyright", "credits" or "license" for more information. # (InteractiveConsole) >>> n = Number(val=10) >>> n.save() >>> Number.objects.all() [<Number: Number object>] >>> Number.objects.filter(val__gte=10.1) [<Number: Number object>] >>> from django.db import connection >>> connection.queries[-1] {'time': '0.001', 'sql': 'SELECT "t1_number"."id", "t1_number"."val" FROM "t1_number" WHERE "t1_number"."val" >= 10 LIMIT 21'} >>> import django >>> django.VERSION (1, 1, 1, 'final', 0)
Attachments (3)
Change History (20)
comment:1 by , 15 years ago
milestone: | → 1.2 |
---|---|
Triage Stage: | Unreviewed → Accepted |
comment:2 by , 15 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
by , 15 years ago
Attachment: | bug12239.diff added |
---|
comment:3 by , 15 years ago
Has patch: | set |
---|
follow-up: 6 comment:4 by , 15 years ago
Owner: | changed from | to
---|---|
Status: | assigned → new |
comment:5 by , 15 years ago
Component: | Core framework → Database layer (models, ORM) |
---|
comment:7 by , 15 years ago
Patch needs improvement: | set |
---|
Flooring a 'gt' is fine, because field__gt=11.1
will floor to 11, which will still match field=12.
There's a problem with 'lt' too though, because field__lt=12.1
will floor to 12 which *should* still match field=12.
I also think that the patch should still run through get_prep_value
. My suggestion is to just math.ceil
float & Decimal values (if 'gte' or 'lt') and passing the result through super still.
comment:8 by , 15 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
by , 15 years ago
Attachment: | django-bug-12239.diff added |
---|
Updated previous patch with suggestions and added tests.
comment:9 by , 15 years ago
Owner: | changed from | to
---|---|
Patch needs improvement: | unset |
Status: | assigned → new |
Updated patch with changes suggested by SmileyChris, and added tests to cover the 'lt' case he mentioned. Should be ready for checkin.
comment:10 by , 15 years ago
Owner: | changed from | to
---|
comment:11 by , 15 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
comment:12 by , 15 years ago
comment:13 by , 15 years ago
Resolution: | fixed |
---|---|
Status: | closed → reopened |
Fix here broke some other tests:
====================================================================== ERROR: test_limits (regressiontests.model_fields.tests.BigIntegerFieldTests) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave-py2.4/parts/ubuntu9.10-py2.4-sqlite/django-trunk_ubuntu9.10-py2.4-sqlite/build/tests/regressiontests/model_fields/tests.py", line 250, in test_limits self.assertEqual(qs.count(), 1) File "/home/buildbot/slave-py2.4/parts/ubuntu9.10-py2.4-sqlite/django-trunk_ubuntu9.10-py2.4-sqlite/build/django/db/models/query.py", line 324, in count return self.query.get_count(using=self.db) File "/home/buildbot/slave-py2.4/parts/ubuntu9.10-py2.4-sqlite/django-trunk_ubuntu9.10-py2.4-sqlite/build/django/db/models/sql/query.py", line 366, in get_count number = obj.get_aggregation(using=using)[None] File "/home/buildbot/slave-py2.4/parts/ubuntu9.10-py2.4-sqlite/django-trunk_ubuntu9.10-py2.4-sqlite/build/django/db/models/sql/query.py", line 338, in get_aggregation result = query.get_compiler(using).execute_sql(SINGLE) File "/home/buildbot/slave-py2.4/parts/ubuntu9.10-py2.4-sqlite/django-trunk_ubuntu9.10-py2.4-sqlite/build/django/db/models/sql/compiler.py", line 729, in execute_sql cursor.execute(sql, params) File "/home/buildbot/slave-py2.4/parts/ubuntu9.10-py2.4-sqlite/django-trunk_ubuntu9.10-py2.4-sqlite/build/django/db/backends/sqlite3/base.py", line 197, in execute return Database.Cursor.execute(self, query, params) OverflowError: long too big to convert ====================================================================== FAIL: Doctest: modeltests.order_with_respect_to.models.__test__.API_TESTS ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/slave-py2.4/parts/ubuntu9.10-py2.4-sqlite/django-trunk_ubuntu9.10-py2.4-sqlite/build/django/test/_doctest.py", line 2180, in runTest raise self.failureException(self.format_failure(new.getvalue())) AssertionError: Failed doctest test for modeltests.order_with_respect_to.models.__test__.API_TESTS File "/home/buildbot/slave-py2.4/parts/ubuntu9.10-py2.4-sqlite/django-trunk_ubuntu9.10-py2.4-sqlite/build/tests/modeltests/order_with_respect_to/models.py", line unknown line number, in API_TESTS ---------------------------------------------------------------------- File "/home/buildbot/slave-py2.4/parts/ubuntu9.10-py2.4-sqlite/django-trunk_ubuntu9.10-py2.4-sqlite/build/tests/modeltests/order_with_respect_to/models.py", line ?, in modeltests.order_with_respect_to.models.__test__.API_TESTS Failed example: a4.get_previous_in_order() Exception raised: Traceback (most recent call last): File "/home/buildbot/slave-py2.4/parts/ubuntu9.10-py2.4-sqlite/django-trunk_ubuntu9.10-py2.4-sqlite/build/django/test/_doctest.py", line 1267, in __run compileflags, 1) in test.globs File "<doctest modeltests.order_with_respect_to.models.__test__.API_TESTS[17]>", line 1, in ? a4.get_previous_in_order() File "/home/buildbot/slave-py2.4/parts/ubuntu9.10-py2.4-sqlite/django-trunk_ubuntu9.10-py2.4-sqlite/build/django/utils/functional.py", line 55, in _curried return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs)) File "/home/buildbot/slave-py2.4/parts/ubuntu9.10-py2.4-sqlite/django-trunk_ubuntu9.10-py2.4-sqlite/build/django/db/models/base.py", line 660, in _get_next_or_previous_in_order obj = self._default_manager.filter(**{ File "/home/buildbot/slave-py2.4/parts/ubuntu9.10-py2.4-sqlite/django-trunk_ubuntu9.10-py2.4-sqlite/build/django/db/models/query.py", line 545, in filter return self._filter_or_exclude(False, *args, **kwargs) File "/home/buildbot/slave-py2.4/parts/ubuntu9.10-py2.4-sqlite/django-trunk_ubuntu9.10-py2.4-sqlite/build/django/db/models/query.py", line 563, in _filter_or_exclude clone.query.add_q(Q(*args, **kwargs)) File "/home/buildbot/slave-py2.4/parts/ubuntu9.10-py2.4-sqlite/django-trunk_ubuntu9.10-py2.4-sqlite/build/django/db/models/sql/query.py", line 1103, in add_q can_reuse=used_aliases) File "/home/buildbot/slave-py2.4/parts/ubuntu9.10-py2.4-sqlite/django-trunk_ubuntu9.10-py2.4-sqlite/build/django/db/models/sql/query.py", line 1043, in add_filter connector) File "/home/buildbot/slave-py2.4/parts/ubuntu9.10-py2.4-sqlite/django-trunk_ubuntu9.10-py2.4-sqlite/build/django/db/models/sql/where.py", line 66, in add value = obj.prepare(lookup_type, value) File "/home/buildbot/slave-py2.4/parts/ubuntu9.10-py2.4-sqlite/django-trunk_ubuntu9.10-py2.4-sqlite/build/django/db/models/sql/where.py", line 275, in prepare return self.field.get_prep_lookup(lookup_type, value) File "/home/buildbot/slave-py2.4/parts/ubuntu9.10-py2.4-sqlite/django-trunk_ubuntu9.10-py2.4-sqlite/build/django/db/models/fields/__init__.py", line 888, in get_prep_lookup value = math.ceil(value) TypeError: a float is required ----------------------------------------------------------------------
by , 15 years ago
Attachment: | django-bug-12239_fixed.diff added |
---|
Update of the previous patch which fixes test failures.
comment:14 by , 15 years ago
Owner: | changed from | to
---|---|
Status: | reopened → new |
Updated the fix to only perform the math.ceil if value is a float.
comment:15 by , 15 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
The bug is only for gte queries; lte already worked as expected. I've attached a patch that fixes it.