#30379: ProgrammingError from exclude using models.F with long relation -------------------------------------+------------------------------------- Reporter: PeterJCLaw | Owner: nobody Type: Bug | Status: new Component: Database layer | Version: 2.2 (models, ORM) | Severity: Normal | Resolution: Keywords: | Triage Stage: | Unreviewed Has patch: 0 | Needs documentation: 0 Needs tests: 0 | Patch needs improvement: 0 Easy pickings: 0 | UI/UX: 0 -------------------------------------+------------------------------------- Description changed by PeterJCLaw:
Old description: > The following query emits a `ProgrammingError` due to the query omitting > the definitions of a number of references it uses: > {{{#!python > Alert.objects.exclude( > item__order_items__order__user=models.F('user'), > ) > }}} > > {{{ > django.db.utils.ProgrammingError: missing FROM-clause entry for table > "u2" > }}} > > The spelling using a specific user does seem to work correctly, hinting > that the issue is somehow related to the handling of the `models.F` > component. > > {{{#!python > Alert.objects.exclude( > item__order_items__order__user=the_user, > ) > }}} > > Models: > {{{#!python > from django.db import models > > class Item(models.Model): > name = models.TextField() > > class Order(models.Model): > user = models.ForeignKey('auth.User', on_delete=models.CASCADE) > > class UnsizedOrderItem(models.Model): > order = models.ForeignKey(Order, on_delete=models.CASCADE, > related_name='items') > item = models.ForeignKey(Item, on_delete=models.CASCADE, > related_name='order_items') > > class Alert(models.Model): > user = models.ForeignKey('auth.User', on_delete=models.CASCADE) > item = models.ForeignKey(Item, on_delete=models.CASCADE, > related_name='alerts') > }}} > > I originally saw this with another layer of many-to-many between the item > and the order, but that turned out not to be necessary to reproduce the > issue: > {{{#!python > class SizedItem(models.Model): > item = models.ForeignKey(Item, on_delete=models.CASCADE, > related_name='sizes') > size = models.TextField() > > class SizedOrderItem(models.Model): > order = models.ForeignKey(Order, on_delete=models.CASCADE, > related_name='sized_items') > sized_item = models.ForeignKey(SizedItem, on_delete=models.CASCADE, > related_name='sized_order_items') > > Alert.objects.exclude( > item__sizes__sized_order_items__order__user=models.F('user'), > ) > }}} > > Traceback: > {{{ > File ".../lib/python3.5/site-packages/django/db/models/query.py", line > 55, in __iter__ > results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, > chunk_size=self.chunk_size) > File ".../lib/python3.5/site- > packages/django/db/models/sql/compiler.py", line 1097, in execute_sql > cursor.execute(sql, params) > File ".../lib/python3.5/site- > packages/sentry_sdk/integrations/django/__init__.py", line 298, in > execute > return real_execute(self, sql, params) > File "/home/peter-thread/thread/styleme/styleme/graphql/metrics.py", > line 112, in wrapper > return fn(wrapped_self, *args, **kwargs) > File ".../lib/python3.5/site-packages/django/db/backends/utils.py", > line 67, in execute > return self._execute_with_wrappers(sql, params, many=False, > executor=self._execute) > File ".../lib/python3.5/site-packages/django/db/backends/utils.py", > line 76, in _execute_with_wrappers > return executor(sql, params, many, context) > File ".../lib/python3.5/site-packages/django/db/backends/utils.py", > line 84, in _execute > return self.cursor.execute(sql, params) > File ".../lib/python3.5/site-packages/django/db/utils.py", line 89, in > __exit__ > raise dj_exc_value.with_traceback(traceback) from exc_value > File ".../lib/python3.5/site-packages/django/db/backends/utils.py", > line 84, in _execute > return self.cursor.execute(sql, params) > django.db.utils.ProgrammingError: missing FROM-clause entry for table > "u2" > LINE 1: ...JOIN "liked_email_alerts_unsizedorderitem" U3 ON (U2."id" = > ... > ^ > }}} > > Versions: > * I've seen this under both 2.1.7 and 2.2 > * I'm using Python 3.5.2 > * I'm using Postgres 9.6 (psycopg2-binary==2.7.7) > > For reference here's the SQL generated by printing the `.query` on the > querysets: > {{{#!sql > -- relative > > SELECT > "liked_email_alerts_alert"."id", > "liked_email_alerts_alert"."user_id", > "liked_email_alerts_alert"."item_id" > FROM > "liked_email_alerts_alert" > WHERE > NOT ("liked_email_alerts_alert"."item_id" IN ( > SELECT > U3. "item_id" > FROM > "liked_email_alerts_alert" U0 > INNER JOIN "liked_email_alerts_unsizedorderitem" U3 ON > (U2. "id" = U3. "item_id") > INNER JOIN "liked_email_alerts_order" U4 ON (U3. > "order_id" = U4. "id") > WHERE > U4. "user_id" = (U0. "user_id"))); > > -- specific > > SELECT > "liked_email_alerts_alert"."id", > "liked_email_alerts_alert"."user_id", > "liked_email_alerts_alert"."item_id" > FROM > "liked_email_alerts_alert" > WHERE > NOT ("liked_email_alerts_alert"."item_id" IN ( > SELECT > U2. "item_id" > FROM > "liked_email_alerts_unsizedorderitem" U2 > INNER JOIN "liked_email_alerts_order" U3 ON (U2. > "order_id" = U3. "id") > WHERE > U3. "user_id" = 13)) > }}} New description: The following query emits a `ProgrammingError` due to the query omitting the definitions of a number of references it uses: {{{#!python Alert.objects.exclude( item__order_items__order__user=models.F('user'), ) }}} {{{ django.db.utils.ProgrammingError: missing FROM-clause entry for table "u2" }}} The spelling using a specific user does seem to work correctly, hinting that the issue is somehow related to the handling of the `models.F` component. {{{#!python Alert.objects.exclude( item__order_items__order__user=the_user, ) }}} Models: {{{#!python from django.db import models class Item(models.Model): name = models.TextField() class Order(models.Model): user = models.ForeignKey('auth.User', on_delete=models.CASCADE) class UnsizedOrderItem(models.Model): order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='items') item = models.ForeignKey(Item, on_delete=models.CASCADE, related_name='order_items') class Alert(models.Model): user = models.ForeignKey('auth.User', on_delete=models.CASCADE) item = models.ForeignKey(Item, on_delete=models.CASCADE, related_name='alerts') }}} I originally saw this with another layer of many-to-many between the item and the order, but that turned out not to be necessary to reproduce the issue: {{{#!python class SizedItem(models.Model): item = models.ForeignKey(Item, on_delete=models.CASCADE, related_name='sizes') size = models.TextField() class SizedOrderItem(models.Model): order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='sized_items') sized_item = models.ForeignKey(SizedItem, on_delete=models.CASCADE, related_name='sized_order_items') Alert.objects.exclude( item__sizes__sized_order_items__order__user=models.F('user'), ) }}} Traceback: {{{ File ".../lib/python3.5/site-packages/django/db/models/query.py", line 55, in __iter__ results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size) File ".../lib/python3.5/site-packages/django/db/models/sql/compiler.py", line 1097, in execute_sql cursor.execute(sql, params) File ".../lib/python3.5/site- packages/sentry_sdk/integrations/django/__init__.py", line 298, in execute return real_execute(self, sql, params) File ".../lib/python3.5/site-packages/django/db/backends/utils.py", line 67, in execute return self._execute_with_wrappers(sql, params, many=False, executor=self._execute) File ".../lib/python3.5/site-packages/django/db/backends/utils.py", line 76, in _execute_with_wrappers return executor(sql, params, many, context) File ".../lib/python3.5/site-packages/django/db/backends/utils.py", line 84, in _execute return self.cursor.execute(sql, params) File ".../lib/python3.5/site-packages/django/db/utils.py", line 89, in __exit__ raise dj_exc_value.with_traceback(traceback) from exc_value File ".../lib/python3.5/site-packages/django/db/backends/utils.py", line 84, in _execute return self.cursor.execute(sql, params) django.db.utils.ProgrammingError: missing FROM-clause entry for table "u2" LINE 1: ...JOIN "liked_email_alerts_unsizedorderitem" U3 ON (U2."id" = ... ^ }}} Versions: * I've seen this under both 2.1.7 and 2.2 * I'm using Python 3.5.2 * I'm using Postgres 9.6 (psycopg2-binary==2.7.7) For reference here's the SQL generated by printing the `.query` on the querysets: {{{#!sql -- relative SELECT "liked_email_alerts_alert"."id", "liked_email_alerts_alert"."user_id", "liked_email_alerts_alert"."item_id" FROM "liked_email_alerts_alert" WHERE NOT ("liked_email_alerts_alert"."item_id" IN ( SELECT U3. "item_id" FROM "liked_email_alerts_alert" U0 INNER JOIN "liked_email_alerts_unsizedorderitem" U3 ON (U2. "id" = U3. "item_id") INNER JOIN "liked_email_alerts_order" U4 ON (U3. "order_id" = U4. "id") WHERE U4. "user_id" = (U0. "user_id"))); -- specific SELECT "liked_email_alerts_alert"."id", "liked_email_alerts_alert"."user_id", "liked_email_alerts_alert"."item_id" FROM "liked_email_alerts_alert" WHERE NOT ("liked_email_alerts_alert"."item_id" IN ( SELECT U2. "item_id" FROM "liked_email_alerts_unsizedorderitem" U2 INNER JOIN "liked_email_alerts_order" U3 ON (U2. "order_id" = U3. "id") WHERE U3. "user_id" = 13)) }}} -- -- Ticket URL: <https://code.djangoproject.com/ticket/30379#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 django-updates+unsubscr...@googlegroups.com. To post to this group, send email to django-updates@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-updates/068.64366c77618c37e39a34a2e956f1a00e%40djangoproject.com. For more options, visit https://groups.google.com/d/optout.