Skip to content

Commit

Permalink
Fixed #28848 -- Fixed SQLite/MySQL crash when ordering by a filtered …
Browse files Browse the repository at this point in the history
…subquery that uses nulls_first/nulls_last.
  • Loading branch information
raphaelm authored and timgraham committed Nov 27, 2017
1 parent ad5f33e commit 616f468
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 1 deletion.
1 change: 1 addition & 0 deletions django/db/models/expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1106,6 +1106,7 @@ def as_sql(self, compiler, connection, template=None, **extra_context):
}
placeholders.update(extra_context)
template = template or self.template
params *= template.count('%(expression)s')
return (template % placeholders).rstrip(), params

def as_sqlite(self, compiler, connection):
Expand Down
3 changes: 3 additions & 0 deletions docs/releases/1.11.8.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,6 @@ Bugfixes

* Made ``QuerySet.iterator()`` use server-side cursors on PostgreSQL after
``values()`` and ``values_list()`` (:ticket:`28817`).

* Fixed crash on SQLite and MySQL when ordering by a filtered subquery that
uses ``nulls_first`` or ``nulls_last`` (:ticket:`28848`).
23 changes: 22 additions & 1 deletion tests/ordering/tests.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from datetime import datetime
from operator import attrgetter

from django.db.models import F
from django.db.models import DateTimeField, F, Max, OuterRef, Subquery
from django.db.models.functions import Upper
from django.test import TestCase

Expand Down Expand Up @@ -138,6 +138,27 @@ def test_order_by_nulls_first(self):
[self.a1, self.a2, self.a4, self.a3],
)

def test_orders_nulls_first_on_filtered_subquery(self):
Article.objects.filter(headline='Article 1').update(author=self.author_1)
Article.objects.filter(headline='Article 2').update(author=self.author_1)
Article.objects.filter(headline='Article 4').update(author=self.author_2)
Author.objects.filter(name__isnull=True).delete()
author_3 = Author.objects.create(name='Name 3')
article_subquery = Article.objects.filter(
author=OuterRef('pk'),
headline__icontains='Article',
).order_by().values('author').annotate(
last_date=Max('pub_date'),
).values('last_date')
self.assertQuerysetEqualReversible(
Author.objects.annotate(
last_date=Subquery(article_subquery, output_field=DateTimeField())
).order_by(
F('last_date').asc(nulls_first=True)
).distinct(),
[author_3, self.author_1, self.author_2],
)

def test_stop_slicing(self):
"""
Use the 'stop' part of slicing notation to limit the results.
Expand Down

0 comments on commit 616f468

Please sign in to comment.