Django builds wrong sql query.

50 views
Skip to first unread message

Алексей Широков

unread,
Mar 19, 2015, 9:11:39 AM3/19/15
to django...@googlegroups.com
I have the following code:

package_queryset = Package.objects.extra(
    where=[(' "document_package"."id" IN (SELECT DISTINCT ON ("document_id") "id"'
            '                             FROM "document_package"'
            '                             WHERE "status" NOT IN (\'unknown\','
            '                                                    \'deleted\')'
            '                             ORDER BY "document_id" ASC,'
            '                                      "completed" DESC,'
            '                                      "last_modified" DESC)')]
)

document_queryset = Document.objects.select_related(
    'contractor',
    'stagcy',
    'period',
).filter(
    packages=package_queryset.all(),
).extra(
    select={
        'st_result': ('(CASE'
                      '     WHEN ("document_package"."state"::json -> \'result\' ->> \'status\') = \'failure\' THEN 2'
                      '     WHEN ("document_package"."state"::json -> \'result\' ->> \'status\') = \'warning\' THEN 1'
                      '     ELSE 0'
                      '  END)'),
        'st_sending': ('(CASE'
                       '     WHEN ("document_package"."state"::json -> \'sending\' ->> \'status\') = \'failure\' THEN 4'
                       '     WHEN ("document_package"."state"::json -> \'sending\' ->> \'status\') = \'warning\' THEN 3'
                       '     WHEN ("document_package"."state"::json -> \'sending\' ->> \'status\') = \'unknown\' THEN 2'
                       '     WHEN ("document_package"."state"::json -> \'sending\' ->> \'status\') = \'success\' THEN 1'
                       '     ELSE 0'
                       '  END)'),
        'st_exchange': ('(CASE'
                        '     WHEN ("document_package"."state"::json -> \'exchange\' ->> \'status\') = \'success\' THEN 1'
                        '     ELSE 0'
                        '  END)'),
    }
).order_by(
    '-st_result',
    '-st_sending',
    'st_exchange',
    '-packages__last_modified',
)

result:

SELECT ...
FROM "document_document"
INNER JOIN "document_package" ON ("document_document"."id" = "document_package"."document_id")
INNER JOIN "contractor_contractor" ON ("document_document"."contractor_id" = "contractor_contractor"."id")
INNER JOIN "stateagency_stateagency" ON ("document_document"."stagcy_id" = "stateagency_stateagency"."id")
LEFT OUTER JOIN "document_period" ON ("document_document"."period_id" = "document_period"."id")
WHERE "document_package"."id" IN
    (SELECT U0."id"
     FROM "document_package" U0
     WHERE (("document_package"."id" IN   // <-- must be U0
               (SELECT DISTINCT ON ("document_id") "id"
                FROM "document_package"
                WHERE "status" NOT IN ('unknown',
                                       'deleted')
                ORDER BY "document_id" ASC, "completed" DESC, "last_modified" DESC))
            AND NOT (U0."status" IN (completed_manually,
                                     completed_success))))
ORDER BY "st_result" DESC,
         "st_sending" DESC,
         "st_exchange" ASC,
         "document_package"."last_modified" DESC


I tested it on the versions 1.7 and 1.8

Tim Graham

unread,
Mar 19, 2015, 9:53:06 AM3/19/15
to django...@googlegroups.com
Try ditching .extra() and using the expressions API in Django 1.8. We're trying to make everything that's possible with .extra() available through better APIs so try to avoid it as even if there is a bug, it's probably unlikely to be fixed.

Алексей Широков

unread,
Mar 19, 2015, 1:10:58 PM3/19/15
to django...@googlegroups.com
Thanks for your reply, I will try...
Reply all
Reply to author
Forward
0 new messages