#34771: order_by on annotated field that's not present in values/values_list 
causes
SQL syntax error
-------------------------------------+-------------------------------------
     Reporter:  Yitao Xiong          |                    Owner:  nobody
         Type:  Bug                  |                   Status:  new
    Component:  Database layer       |                  Version:  3.2
  (models, ORM)                      |
     Severity:  Normal               |               Resolution:
     Keywords:  mysql                |             Triage Stage:
                                     |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------

Comment (by Yitao Xiong):

 Thanks for your reply Natalia!

 I tried this with `main` and it behaved the same:

 {{{
 In [5]: User.objects.annotate(random_stuff=Value(False,
 output_field=BooleanField())).values('id').order_by('random_stuff')
 ....
 ProgrammingError: (1064, "You have an error in your SQL syntax; check the
 manual that corresponds to your MySQL server version for the right syntax
 to use near 'bool) ASC LIMIT 21' at line 1")

 In [6]: print(User.objects.annotate(random_stuff=Value(False,
 output_field=BooleanField())).values('id').order_by('random_stuff').query)
 SELECT `auth_user`.`id` FROM `auth_user` ORDER BY CAST(False AS bool) ASC


 In [7]: from django import VERSION

 In [8]: VERSION
 Out[8]: (5, 0, 0, 'alpha', 0)

 In [9]:
 }}}

 For our specific scenario that caused this error, it wasn't really an
 intentional skipping on the annotated fields, it's more like this (it also
 wasn't the User model at all, using it to avoid exposing our business
 logics, apologize if that added confusions):

 {{{
 # Some generic queryset pre-assembling with annotations
 base_queryset =
 User.objects.annotate(random_field...).order_by('random_field')

 ...
 # Later in a specific path, needing some extra information from the
 base_queryset
 additional_lookup = base_queryset.filter(...).values('id', 'email')
 }}}

 So it's more like the field was annotated first, and developer just didn't
 care about it when later reusing the queryset. Using my example, this
 query with the `annotate` and `values` changed orders will produce the
 same error:

 {{{
 User.objects.annotate(random_stuff=Value(False,
 output_field=BooleanField())).order_by('random_stuff').values('id')
 ...

 ProgrammingError: (1064, "You have an error in your SQL syntax; check the
 manual that corresponds to your MySQL server version for the right syntax
 to use near 'bool) ASC LIMIT 21' at line 1")
 }}}

 To real-life use cases, I can see some cases when you want the rows
 returned in a specific order, but doesn't care about the value it's been
 ordered by.

 A user-login log table can be an example - you want the last 10 logged in
 users, but you don't really care about when they logged in. If we specific
 are looking for order with annotations, maybe an API usage log table would
 be a good example? You wanna see the 10 users who used the API last so you
 annotate with their max access time and order by it, without needing the
 actual values.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34771#comment:4>
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/01070189e5b466bb-1826f92a-e69f-40fb-91c4-6c51e68263e7-000000%40eu-central-1.amazonses.com.

Reply via email to