#34229: "no such column" when combining FilteredRelation and multi-table
inheritance models
-------------------------------------+-------------------------------------
               Reporter:  lufte      |          Owner:  nobody
                   Type:             |         Status:  new
  Uncategorized                      |
              Component:  Database   |        Version:  4.1
  layer (models, ORM)                |       Keywords:  filteredrelation
               Severity:  Normal     |  such column
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 I have found that a certain queryset that combines multi-table inheritance
 models, FilteredRelation, and aggregation, can result in a "no such
 column" database error.

 The following `models.py` and `tests.py` modules can be placed in the app
 of a newly created Django project to reproduce the bug. I've successfully
 reproduced it with Django 3.2.4 (using PostgreSQL) and 4.1.4 (using
 sqlite3). The tests module includes two tests which are pretty similar,
 however one of them fails because of this bug, the full stacktrace being:
 {{{
 Traceback (most recent call last):
   File "/tmp/env/lib/python3.10/site-
 packages/django/db/backends/utils.py", line 89, in _execute
     return self.cursor.execute(sql, params)
   File "/tmp/env/lib/python3.10/site-
 packages/django/db/backends/sqlite3/base.py", line 357, in execute
     return Database.Cursor.execute(self, query, params)
 sqlite3.OperationalError: no such column: myapp_user.superuser

 The above exception was the direct cause of the following exception:

 Traceback (most recent call last):
   File "/tmp/dec1389/myapp/tests.py", line 34, in test_fails
     print(
   File "/tmp/env/lib/python3.10/site-packages/django/db/models/query.py",
 line 370, in __repr__
     data = list(self[: REPR_OUTPUT_SIZE + 1])
   File "/tmp/env/lib/python3.10/site-packages/django/db/models/query.py",
 line 394, in __iter__
     self._fetch_all()
   File "/tmp/env/lib/python3.10/site-packages/django/db/models/query.py",
 line 1867, in _fetch_all
     self._result_cache = list(self._iterable_class(self))
   File "/tmp/env/lib/python3.10/site-packages/django/db/models/query.py",
 line 87, in __iter__
     results = compiler.execute_sql(
   File "/tmp/env/lib/python3.10/site-
 packages/django/db/models/sql/compiler.py", line 1398, in execute_sql
     cursor.execute(sql, params)
   File "/tmp/env/lib/python3.10/site-
 packages/django/db/backends/utils.py", line 67, in execute
     return self._execute_with_wrappers(
   File "/tmp/env/lib/python3.10/site-
 packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
     return executor(sql, params, many, context)
   File "/tmp/env/lib/python3.10/site-
 packages/django/db/backends/utils.py", line 84, in _execute
     with self.db.wrap_database_errors:
   File "/tmp/env/lib/python3.10/site-packages/django/db/utils.py", line
 91, in __exit__
     raise dj_exc_value.with_traceback(traceback) from exc_value
   File "/tmp/env/lib/python3.10/site-
 packages/django/db/backends/utils.py", line 89, in _execute
     return self.cursor.execute(sql, params)
   File "/tmp/env/lib/python3.10/site-
 packages/django/db/backends/sqlite3/base.py", line 357, in execute
     return Database.Cursor.execute(self, query, params)
 django.db.utils.OperationalError: no such column: myapp_user.superuser
 }}}

 === models.py:
 {{{
 from django.db import models

 class School(models.Model):
     name = models.CharField(max_length=100)


 class User(models.Model):
     superuser = models.BooleanField(default=True)


 class Student(User):
     superstudent = models.BooleanField(default=True)
     school = models.ForeignKey(School, on_delete=models.CASCADE)
 }}}

 === tests.py
 {{{
 from django.test import TestCase
 from django.db.models import Q, FilteredRelation, Count
 from .models import School, Student


 class FilteredRelationBugTestCase(TestCase):

     @classmethod
     def setUpClass(cls):
         super().setUpClass()
         p = School.objects.create(name='p1')
         Student.objects.create(school=p, superuser=False,
 superstudent=False)
         Student.objects.create(school=p, superuser=False,
 superstudent=True)
         Student.objects.create(school=p, superuser=True,
 superstudent=False)
         Student.objects.create(school=p, superuser=True,
 superstudent=True)

     def test_works(self):
         print(
             School.objects.annotate(
                 superstudents=FilteredRelation(
                     'student',
                     condition=Q(
                         student__superstudent=True,
                     ),
                 ),
                 superuser_count=Count(
                     'superstudents',
                     filter=Q(superstudents__superuser=True)
                 ),
             ).all()
         )

     def test_fails(self):
         print(
             School.objects.annotate(
                 superusers=FilteredRelation(
                     'student',
                     condition=Q(
                         student__superuser=True,
                     ),
                 ),
                 superstudents_count=Count(
                     'superusers',
                     filter=Q(superusers__superstudent=True)
                 ),
             ).all()
         )
 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34229>
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 unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/010701855082f374-35537afc-9d6f-4402-8c7b-4610b975ae71-000000%40eu-central-1.amazonses.com.

Reply via email to