#29697: Complex query crashes with "missing FROM-clause entry for table"
-------------------------------------+-------------------------------------
     Reporter:  Dmitry               |                    Owner:  nobody
         Type:  Bug                  |                   Status:  new
    Component:  Database layer       |                  Version:  2.1
  (models, ORM)                      |
     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 Tim Graham):

 * stage:  Unreviewed => Accepted


Old description:

> python version: 3.6.6
> database backend: psycopg2 v2.7.5
>
> Hi. I have next models in my project:
>
> {{{
> class Status(models.Model):
>     ...
>     company = models.ForeignKey(
>         'customauth.Company',
>         on_delete=models.CASCADE)
>     key = models.SlugField(max_length=255)
>     ...
>
> class User(models.Model):
>     ...
>     company = models.ForeignKey(
>         'customauth.Company',
>         on_delete=models.CASCADE,
>         related_name='employees',
>         db_index=True)
>     permissions = postgres.fields.JSONField(blank=True, default=list)
>     is_superuser = models.BooleanField(default=False)
>     ...
>
> class Company(models.Model):
>    ...
> }}}
>
> When trying execute next code:
>
> {{{
> Status.objects.filter(
>     Q(company__employees__is_superuser=True) |
>     ~Q(company__employees__permissions__has_key=Concat(Value('records.'),
> 'key', Value('.denied'))),
>     company__employees__pk=4)
> }}}
>
> raising error:
>
> {{{
> Traceback (most recent call last):
>   File "C:\Users\user\py366-tpr\lib\site-
> packages\django\db\backends\utils.py", line 85, in _execute
>     return self.cursor.execute(sql, params)
> psycopg2.ProgrammingError: missing FROM-clause entry for table "u1"
> LINE 1: ...status" U0 INNER JOIN "customauth_user" U2 ON (U1."id" = ...
>                                                           ^
> }}}
>
> SQL after call .query() look like this:
>
> {{{
> SELECT *
> FROM records_status
>     INNER JOIN customauth_company ON (records_status.company_id =
> customauth_company.id)
>     INNER JOIN customauth_user ON (customauth_company.id =
> customauth_user.company_id)
> WHERE
> (
>     (
>         customauth_user.is_superuser = True OR
>         NOT (
>             records_status.company_id IN (
>                 SELECT U2.company_id
>                 FROM records_status U0
>                     INNER JOIN customauth_user U2 ON (U1.id =
> U2.company_id)
>                 WHERE (
>                     U2.permissions ? (CONCAT('records.', CONCAT(U0.key,
> '.denied'))) AND
>                     U2.id = (customauth_user.id)
>                 )
>             )
>         )
>     ) AND
>     customauth_user.id = 4 AND
>     records_status.company_id = (customauth_user.company_id)
> )
> ORDER BY records_status.key ASC;
> }}}
>
> It is not clear where U1 alias comes from.

New description:

 python version: 3.6.6
 database backend: psycopg2 v2.7.5

 Hi. I have next models in my project:

 {{{
 from django.db import models
 from django.contrib.postgres.fields import JSONField

 class Company(models.Model):
    ...

 class Status(models.Model):
     ...
     company = models.ForeignKey(
         Company,
         on_delete=models.CASCADE)
     key = models.SlugField(max_length=255)
     ...

 class User(models.Model):
     ...
     company = models.ForeignKey(
         Company,
         on_delete=models.CASCADE,
         related_name='employees',
         db_index=True)
     permissions = JSONField(blank=True, default=list)
     is_superuser = models.BooleanField(default=False)
     ...

 }}}

 When trying execute next code:

 {{{
 from django.db.models import Q, Value
 from django.db.models.functions import Concat

 Status.objects.filter(
     Q(company__employees__is_superuser=True) |
     ~Q(company__employees__permissions__has_key=Concat(Value('records.'),
 'key', Value('.denied'))),
     company__employees__pk=4)
 }}}

 raising error:

 {{{
 Traceback (most recent call last):
   File "C:\Users\user\py366-tpr\lib\site-
 packages\django\db\backends\utils.py", line 85, in _execute
     return self.cursor.execute(sql, params)
 psycopg2.ProgrammingError: missing FROM-clause entry for table "u1"
 LINE 1: ...status" U0 INNER JOIN "customauth_user" U2 ON (U1."id" = ...
                                                           ^
 }}}

 SQL after call .query() look like this:

 {{{
 SELECT *
 FROM records_status
     INNER JOIN customauth_company ON (records_status.company_id =
 customauth_company.id)
     INNER JOIN customauth_user ON (customauth_company.id =
 customauth_user.company_id)
 WHERE
 (
     (
         customauth_user.is_superuser = True OR
         NOT (
             records_status.company_id IN (
                 SELECT U2.company_id
                 FROM records_status U0
                     INNER JOIN customauth_user U2 ON (U1.id =
 U2.company_id)
                 WHERE (
                     U2.permissions ? (CONCAT('records.', CONCAT(U0.key,
 '.denied'))) AND
                     U2.id = (customauth_user.id)
                 )
             )
         )
     ) AND
     customauth_user.id = 4 AND
     records_status.company_id = (customauth_user.company_id)
 )
 ORDER BY records_status.key ASC;
 }}}

 It is not clear where U1 alias comes from.

--

Comment:

 Reproduced at 50b8493581fea3d7137dd8db33bac7008868d23a.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/29697#comment:1>
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 post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/065.2faf1c772adc5f5ff76d856f657e2d09%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to