#19263: DatabaseError on using empty Page .object_list in __in clause in a query
------------------------------+------------------------------------
Reporter: chkwok@… | Owner: nobody
Type: Bug | Status: new
Component: Core (Other) | Version: 1.4
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------+------------------------------------
Changes (by aaugustin):
* type: Uncategorized => Bug
* component: Uncategorized => Core (Other)
* stage: Unreviewed => Accepted
Old description:
> I've noticed that after upgrading to Django 1.4, __in queries really
> don't like empty sets. Simple queries still work, like
> User.objects.filter(groups__in=[]), but most failures I've seen are with
> Paginators. I think this is the minimum set to cause a DatabaseError,
> create any app, add a models.py with:
>
> {{{#!python
> from django.db import models
>
> class Author(models.Model):
> pass
>
> class Book(models.Model):
> author = models.ForeignKey(Author)
>
> def crash():
> from django.core.paginator import Paginator
>
> pages = Paginator(Author.objects.all(), 25)
> page = pages.page(1)
>
> books = Book.objects.filter(author__in=page.object_list)
> print books
> }}}
>
> calling crash() will cause this stack trace:
>
> {{{
> C:\Workspace\someproject\src\someproject\test.py in <module>()
> 6
> 7 books = Book.objects.filter(author__in=page.object_list)
> ----> 8 print books
> 9
>
> C:\Dev\Python27\lib\site-packages\django\db\models\query.pyc in
> __repr__(self)
> 70
> 71 def __repr__(self):
> ---> 72 data = list(self[:REPR_OUTPUT_SIZE + 1])
> 73 if len(data) > REPR_OUTPUT_SIZE:
> 74 data[-1] = "...(remaining elements truncated)..."
>
> C:\Dev\Python27\lib\site-packages\django\db\models\query.pyc in
> __len__(self)
> 85 self._result_cache = list(self.iterator())
> 86 elif self._iter:
> ---> 87 self._result_cache.extend(self._iter)
> 88 if self._prefetch_related_lookups and not
> self._prefetch_done:
> 89 self._prefetch_related_objects()
>
> C:\Dev\Python27\lib\site-packages\django\db\models\query.pyc in
> iterator(self)
> 289 klass_info = get_klass_info(model,
> max_depth=max_depth,
> 290 requested=requested,
> only_load=only_load)
> --> 291 for row in compiler.results_iter():
> 292 if fill_cache:
> 293 obj, _ = get_cached_row(row, index_start, db,
> klass_info,
>
> C:\Dev\Python27\lib\site-packages\django\db\models\sql\compiler.pyc in
> results_iter(self)
> 761 if self.query.select_for_update and
> transaction.is_managed(self.using):
> 762 transaction.set_dirty(self.using)
> --> 763 for rows in self.execute_sql(MULTI):
> 764 for row in rows:
> 765 if resolve_columns:
>
> C:\Dev\Python27\lib\site-packages\django\db\models\sql\compiler.pyc in
> execute_sql(self, result_type)
> 816
> 817 cursor = self.connection.cursor()
> --> 818 cursor.execute(sql, params)
> 819
> 820 if not result_type:
>
> C:\Dev\Python27\lib\site-packages\django\db\backends\util.pyc in
> execute(self, sql, params)
> 38 start = time()
> 39 try:
> ---> 40 return self.cursor.execute(sql, params)
> 41 finally:
> 42 stop = time()
>
> C:\Dev\Python27\lib\site-
> packages\django\db\backends\postgresql_psycopg2\base.pyc in execute(self,
> query, args)
> 50 def execute(self, query, args=None):
> 51 try:
> ---> 52 return self.cursor.execute(query, args)
> 53 except Database.IntegrityError, e:
> 54 raise utils.IntegrityError,
> utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
>
> DatabaseError: syntax error at or near ")"
> LINE 1: ...ugtest_book" WHERE "bugtest_book"."author_id" IN () LIMIT 21
> }}}
>
> The SQL statement created is:
>
> {{{
> SELECT "bugtest_book"."id", "bugtest_book"."author_id" FROM
> "bugtest_book" WHERE "bugtest_book"."author_id" IN () LIMIT 21
> }}}
New description:
I've noticed that after upgrading to Django 1.4, `__in` queries really
don't like empty sets. Simple queries still work, like
`User.objects.filter(groups__in=[])`, but most failures I've seen are with
Paginators. I think this is the minimum set to cause a DatabaseError,
create any app, add a models.py with:
{{{#!python
from django.db import models
class Author(models.Model):
pass
class Book(models.Model):
author = models.ForeignKey(Author)
def crash():
from django.core.paginator import Paginator
pages = Paginator(Author.objects.all(), 25)
page = pages.page(1)
books = Book.objects.filter(author__in=page.object_list)
print books
}}}
calling crash() will cause this stack trace:
{{{
C:\Workspace\someproject\src\someproject\test.py in <module>()
6
7 books = Book.objects.filter(author__in=page.object_list)
----> 8 print books
9
C:\Dev\Python27\lib\site-packages\django\db\models\query.pyc in
__repr__(self)
70
71 def __repr__(self):
---> 72 data = list(self[:REPR_OUTPUT_SIZE + 1])
73 if len(data) > REPR_OUTPUT_SIZE:
74 data[-1] = "...(remaining elements truncated)..."
C:\Dev\Python27\lib\site-packages\django\db\models\query.pyc in
__len__(self)
85 self._result_cache = list(self.iterator())
86 elif self._iter:
---> 87 self._result_cache.extend(self._iter)
88 if self._prefetch_related_lookups and not
self._prefetch_done:
89 self._prefetch_related_objects()
C:\Dev\Python27\lib\site-packages\django\db\models\query.pyc in
iterator(self)
289 klass_info = get_klass_info(model,
max_depth=max_depth,
290 requested=requested,
only_load=only_load)
--> 291 for row in compiler.results_iter():
292 if fill_cache:
293 obj, _ = get_cached_row(row, index_start, db,
klass_info,
C:\Dev\Python27\lib\site-packages\django\db\models\sql\compiler.pyc in
results_iter(self)
761 if self.query.select_for_update and
transaction.is_managed(self.using):
762 transaction.set_dirty(self.using)
--> 763 for rows in self.execute_sql(MULTI):
764 for row in rows:
765 if resolve_columns:
C:\Dev\Python27\lib\site-packages\django\db\models\sql\compiler.pyc in
execute_sql(self, result_type)
816
817 cursor = self.connection.cursor()
--> 818 cursor.execute(sql, params)
819
820 if not result_type:
C:\Dev\Python27\lib\site-packages\django\db\backends\util.pyc in
execute(self, sql, params)
38 start = time()
39 try:
---> 40 return self.cursor.execute(sql, params)
41 finally:
42 stop = time()
C:\Dev\Python27\lib\site-
packages\django\db\backends\postgresql_psycopg2\base.pyc in execute(self,
query, args)
50 def execute(self, query, args=None):
51 try:
---> 52 return self.cursor.execute(query, args)
53 except Database.IntegrityError, e:
54 raise utils.IntegrityError,
utils.IntegrityError(*tuple(e)), sys.exc_info()[2]
DatabaseError: syntax error at or near ")"
LINE 1: ...ugtest_book" WHERE "bugtest_book"."author_id" IN () LIMIT 21
}}}
The SQL statement created is:
{{{
SELECT "bugtest_book"."id", "bugtest_book"."author_id" FROM "bugtest_book"
WHERE "bugtest_book"."author_id" IN () LIMIT 21
}}}
--
Comment:
I could reproduce the failure under PostgreSQL.
--
Ticket URL: <https://code.djangoproject.com/ticket/19263#comment:2>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit https://groups.google.com/groups/opt_out.