#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.


Reply via email to