#28939: QuerySet used by prefetch_related() does not use expected connection.
-------------------------------------+-------------------------------------
               Reporter:  Nick Pope  |          Owner:  nobody
                   Type:  Bug        |         Status:  new
              Component:  Database   |        Version:  master
  layer (models, ORM)                |       Keywords:  prefetch,
               Severity:  Normal     |  prefetch_related, using, connection
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 I've run into an case with prefetching where the connection used for the
 prefetch queries is not the one I would expect:

 {{{#!python
 # When using the default database connection:

 In [1]: from django.db import connections

 In [2]: connections['default'].queries
 Out[2]: []

 In [3]: connections['readonly'].queries
 Out[3]: []

 In [4]: User.objects.prefetch_related('operators').first()
 Out[4]: <User: example>

 In [5]: connections['default'].queries
 Out[5]:
 [{'sql': 'SELECT ... FROM "auth_user" ORDER BY "auth_user"."id" ASC LIMIT
 1', 'time': '0.205'},
  {'sql': 'SELECT ... AS "_prefetch_related_val_user_id", ... FROM
 "operator" INNER JOIN "operator_users" ON ("operator"."id" =
 "operator_users"."operator_id") WHERE "operator_users"."user_id" IN (1)
 ORDER BY "operator"."code" ASC', 'time': '0.011'}]

 In [6]: connections['readonly'].queries
 Out[6]: []

 # When specifying the database connection to use:

 In [1]: from django.db import connections

 In [2]: connections['default'].queries
 Out[2]: []

 In [3]: connections['readonly'].queries
 Out[3]: []

 In [4]:
 User.objects.using('readonly').prefetch_related('operators').first()
 Out[4]: <User: example>

 In [5]: connections['default'].queries
 Out[5]:
 [{'sql': 'SELECT ... AS "_prefetch_related_val_user_id", ... FROM
 "operator" INNER JOIN "operator_users" ON ("operator"."id" =
 "operator_users"."operator_id") WHERE "operator_users"."user_id" IN (1)
 ORDER BY "operator"."code" ASC', 'time': '0.010'}]

 In [6]: connections['readonly'].queries
 Out[6]:
 [{'sql': 'SELECT ... FROM "auth_user" ORDER BY "auth_user"."id" ASC LIMIT
 1', 'time': '0.002'}]
 }}}

 In the second case I would have expected all queries to be executed on the
 {{{readonly}}} connection by default.

 This can be achieved by using {{{Prefetch('operators',
 queryset=Operator.objects.using('readonly'))}}}, but it means that plain
 strings cannot be used and often a lot of nested {{{Prefetch()}}} objects
 can be required.

 A solution to this could be to do the following:

 1. Use the connection from the original {{{QuerySet}}} that called
 {{{.prefetch_related()}}} by default.
 2. ~~Possibly add {{{QuerySet.prefetch_related(using=...)}}} to allow
 overriding for all prefetch queries.~~ (Doesn't fit nicely with the API.)
 3. Possibly add {{{Prefetch(using=...)}}} to allow overriding for a
 specific branch of prefetching. (This would propagate down.)

-- 
Ticket URL: <https://code.djangoproject.com/ticket/28939>
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/050.158901b7c9f86ae37982457f21eacfb0%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to