#30659: Annotate ignored when using after union
-------------------------------------+-------------------------------------
               Reporter:  Marc       |          Owner:  nobody
  DEBUREAUX                          |
                   Type:  Bug        |         Status:  new
              Component:  Database   |        Version:  2.2
  layer (models, ORM)                |
               Severity:  Normal     |       Keywords:
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 Using `annotate` after an `union` doesn't seem to have any effect at all
 when evaluated into a view/template and crashes when debugging step by
 step.

 Here the example by using the embedded shell with iPython:

 **Input:**
 {{{
 company_ids = [15, 20]

 base_query =
 TweetCse.objects.exclude(valid=False).filter(target=True).annotate(
                 su=F("tw_su__company_id")).values_list("su",
 flat=True).distinct()

 cse_subqueries = [base_query.filter(tw_corpo__company_id=company_id) for
 company_id in company_ids]

 cse_query = TweetCse.objects.none().union(*cse_subqueries,
 all=True).order_by("su")

 str(cse_query.query)
 }}}

 **Output:**
 {{{
 '(SELECT DISTINCT "generic_twitter"."company_id" AS "su" FROM
 "cse_tweetcse" INNER JOIN "generic_twitter" ON ("cse_tweetcse"."tw_su_id"
 = "generic_twitter"."username") INNER JOIN "generic_twitter" T4 ON
 ("cse_tweetcse"."tw_corpo_id" = T4."username") WHERE (NOT
 ("cse_tweetcse"."valid" = False AND "cse_tweetcse"."valid" IS NOT NULL)
 AND "cse_tweetcse"."target" = True AND T4."company_id" = 15)) UNION ALL
 (SELECT DISTINCT "generic_twitter"."company_id" AS "su" FROM
 "cse_tweetcse" INNER JOIN "generic_twitter" ON ("cse_tweetcse"."tw_su_id"
 = "generic_twitter"."username") INNER JOIN "generic_twitter" T4 ON
 ("cse_tweetcse"."tw_corpo_id" = T4."username") WHERE (NOT
 ("cse_tweetcse"."valid" = False AND "cse_tweetcse"."valid" IS NOT NULL)
 AND "cse_tweetcse"."target" = True AND T4."company_id" = 20)) ORDER BY (1)
 ASC'
 }}}

 **Input:**
 {{{
 cse_query =
 cse_query.annotate(nb=Count("su")).filter(nb__gte=len(company_ids))

 str(cse_query.query)
 }}}

 **Output:**
 {{{
 '(SELECT DISTINCT "generic_twitter"."company_id" AS "su" FROM
 "cse_tweetcse" INNER JOIN "generic_twitter" ON ("cse_tweetcse"."tw_su_id"
 = "generic_twitter"."username") INNER JOIN "generic_twitter" T4 ON
 ("cse_tweetcse"."tw_corpo_id" = T4."username") WHERE (NOT
 ("cse_tweetcse"."valid" = False AND "cse_tweetcse"."valid" IS NOT NULL)
 AND "cse_tweetcse"."target" = True AND T4."company_id" = 15)) UNION ALL
 (SELECT DISTINCT "generic_twitter"."company_id" AS "su" FROM
 "cse_tweetcse" INNER JOIN "generic_twitter" ON ("cse_tweetcse"."tw_su_id"
 = "generic_twitter"."username") INNER JOIN "generic_twitter" T4 ON
 ("cse_tweetcse"."tw_corpo_id" = T4."username") WHERE (NOT
 ("cse_tweetcse"."valid" = False AND "cse_tweetcse"."valid" IS NOT NULL)
 AND "cse_tweetcse"."target" = True AND T4."company_id" = 20)) ORDER BY (1)
 ASC'
 }}}

 As you can see, the query is absolutly the same, it does not include the
 annotation neither the filter on this annotation. But the query
 construction doesn't fail whereas the evaluation does.

 **Input:**
 {{{
 cse_query
 }}}

 **Output:**
 {{{
 ---------------------------------------------------------------------------
 IndexError                                Traceback (most recent call
 last)
 ~/.pyenv/versions/motherbase/lib/python3.7/site-
 packages/IPython/core/formatters.py in __call__(self, obj)
     700                 type_pprinters=self.type_printers,
     701                 deferred_pprinters=self.deferred_printers)
 --> 702             printer.pretty(obj)
     703             printer.flush()
     704             return stream.getvalue()

 ~/.pyenv/versions/motherbase/lib/python3.7/site-
 packages/IPython/lib/pretty.py in pretty(self, obj)
     400                         if cls is not object \
     401                                 and
 callable(cls.__dict__.get('__repr__')):
 --> 402                             return _repr_pprint(obj, self, cycle)
     403
     404             return _default_pprint(obj, self, cycle)

 ~/.pyenv/versions/motherbase/lib/python3.7/site-
 packages/IPython/lib/pretty.py in _repr_pprint(obj, p, cycle)
     695     """A pprint that just redirects to the normal repr
 function."""
     696     # Find newlines and replace them with p.break_()
 --> 697     output = repr(obj)
     698     for idx,output_line in enumerate(output.splitlines()):
     699         if idx:

 ~/.pyenv/versions/motherbase/lib/python3.7/site-
 packages/django/db/models/query.py in __repr__(self)
     248
     249     def __repr__(self):
 --> 250         data = list(self[:REPR_OUTPUT_SIZE + 1])
     251         if len(data) > REPR_OUTPUT_SIZE:
     252             data[-1] = "...(remaining elements truncated)..."

 ~/.pyenv/versions/motherbase/lib/python3.7/site-
 packages/django/db/models/query.py in __iter__(self)
     272                - Responsible for turning the rows into model
 objects.
     273         """
 --> 274         self._fetch_all()
     275         return iter(self._result_cache)
     276

 ~/.pyenv/versions/motherbase/lib/python3.7/site-
 packages/django/db/models/query.py in _fetch_all(self)
    1240     def _fetch_all(self):
    1241         if self._result_cache is None:
 -> 1242             self._result_cache = list(self._iterable_class(self))
    1243         if self._prefetch_related_lookups and not
 self._prefetch_done:
    1244             self._prefetch_related_objects()

 ~/.pyenv/versions/motherbase/lib/python3.7/site-
 packages/django/db/models/query.py in __iter__(self)
     180         queryset = self.queryset
     181         compiler = queryset.query.get_compiler(queryset.db)
 --> 182         for row in
 compiler.results_iter(chunked_fetch=self.chunked_fetch,
 chunk_size=self.chunk_size):
     183             yield row[0]
     184

 ~/.pyenv/versions/motherbase/lib/python3.7/site-
 packages/django/db/models/sql/compiler.py in apply_converters(self, rows,
 converters)
    1040         for row in map(list, rows):
    1041             for pos, (convs, expression) in converters:
 -> 1042                 value = row[pos]
    1043                 for converter in convs:
    1044                     value = converter(value, expression,
 connection)

 IndexError: list index out of range
 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/30659>
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/049.7de7ec72301e7526e765fa3e54ac1573%40djangoproject.com.

Reply via email to