#26336 closed Bug (wontfix)
GIS queries with distance and extra select fields generate a SQL exception in pagination
| Reported by: | simondrabble | Owned by: | nobody |
|---|---|---|---|
| Component: | GIS | Version: | 1.8 |
| Severity: | Normal | Keywords: | gis pagination query extra |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Given:
from django.contrib.gis.db import models as gis
from django.contrib.gis.geos import Point
from django.db import models
POINT = Point(-104.9903, 39.7392, srid=4326)
class PagedModel(models.Model):
objects = gis.GeoManager()
name = models.CharField(max_length=64, default='Nothing')
location = gis.PointField(srid=4326, default=POINT)
and:
from django.contrib.gis.geos import Point
from django.core import paginator
def test():
point = Point(-101.214, 36.135, srid=4326)
qs = models.PagedModel.objects.all()
# Both of these modifiers are required to trigger the bug.
qs = qs.distance(point)
qs = qs.extra(select={'confidence': '0'})
pager = paginator.Paginator(qs, 1)
results = pager.page(1)
Observed:
SELECT COUNT(*) FROM (
SELECT (0) AS "confidence",
"example_pagedmodel"."id" AS Col1,
(ST_distance_sphere("example_pagedmodel"."location",
ST_GeomFromEWKB('\x0101000020e610000004560e2db24d59c0e17a14ae47114240'::bytea))
) AS "distance"
FROM "example_pagedmodel"
GROUP BY "example_pagedmodel"."id",
(0), -- Here is the problem
-- Should be a 1-based column number,
-- or the name of the column ("confidence")
(ST_distance_sphere("example_pagedmodel"."location",
ST_GeomFromEWKB('\x0101000020e610000004560e2db24d59c0e17a14ae47114240'::bytea)))
) subquery
which is exposed as
======================================================================
ERROR: test_pagination (pagebug.example.tests.PagedModelTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/funstuff/django/pagebug/pagebug/example/tests.py", line 48, in test_pagination
results = pager.page(1)
File "/pyenv/django1.8/lib/python2.7/site-packages/django/core/paginator.py", line 50, in page
number = self.validate_number(number)
File "/pyenv/django1.8/lib/python2.7/site-packages/django/core/paginator.py", line 39, in validate_number
if number > self.num_pages:
File "/pyenv/django1.8/lib/python2.7/site-packages/django/core/paginator.py", line 86, in _get_num_pages
if self.count == 0 and not self.allow_empty_first_page:
File "/pyenv/django1.8/lib/python2.7/site-packages/django/core/paginator.py", line 72, in _get_count
self._count = self.object_list.count()
File "/pyenv/django1.8/lib/python2.7/site-packages/django/db/models/query.py", line 318, in count
return self.query.get_count(using=self.db)
File "/pyenv/django1.8/lib/python2.7/site-packages/django/db/models/sql/query.py", line 466, in get_count
number = obj.get_aggregation(using, ['__count'])['__count']
File "/pyenv/django1.8/lib/python2.7/site-packages/django/db/models/sql/query.py", line 447, in get_aggregation
result = compiler.execute_sql(SINGLE)
File "/pyenv/django1.8/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 840, in execute_sql
cursor.execute(sql, params)
File "/pyenv/django1.8/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/pyenv/django1.8/lib/python2.7/site-packages/django/db/utils.py", line 98, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/pyenv/django1.8/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
ProgrammingError: GROUP BY position 0 is not in select list
LINE 1: ..._pagedmodel" GROUP BY "example_pagedmodel"."id", (0), (ST_di...
Expected:
Pagination query completes successfully.
Looks like the 0 from the extra() clause is being used explicitly as a column name/ alias.
I have a test project that tickles the bug at https://github.com/simondrabble/pagebug
Change History (4)
comment:1 by , 10 years ago
comment:2 by , 10 years ago
| Resolution: | → wontfix |
|---|---|
| Status: | new → closed |
Also QuerySet.extra() is discouraged and we aren't fixing bugs with its usage:
This is an old API that we aim to deprecate at some point in the future. Use it only if you cannot express your query using other queryset methods. If you do need to use it, please file a ticket using the
QuerySet.extrakeyword with your use case (please check the list of existing tickets first) so that we can enhance the QuerySet API to allow removingextra(). We are no longer improving or fixing bugs for this method.
comment:3 by , 10 years ago
Thanks for the quick responses!
I verified the bug exists in Django 1.9 with the Distance function, but replacing the call to extra() with an appropriate call to annotate() solves the problem. Thanks for the pointers!
comment:4 by , 10 years ago
Also verified (for completeness) simply replacing extra() with an appropriate annotate() fixes the problem in Django 1.8
Do you have the opportunity to test with Django 1.9 and the new Distance function?
https://docs.djangoproject.com/en/1.9/ref/contrib/gis/functions/#django.contrib.gis.db.models.functions.Distance
The legacy GeoQuerySet methods are now deprecated and unless the issue can be reproduced with the Distance function, we probably won't fix the old method.