mirror of
https://github.com/django/django.git
synced 2025-03-25 16:50:45 +00:00
Fixed #25377 -- Changed Count queries to execute COUNT(*) instead of COUNT('*').
This commit is contained in:
parent
4d933ad418
commit
3fe3887a2e
@ -2,7 +2,7 @@
|
|||||||
Classes to represent the definitions of aggregate functions.
|
Classes to represent the definitions of aggregate functions.
|
||||||
"""
|
"""
|
||||||
from django.core.exceptions import FieldError
|
from django.core.exceptions import FieldError
|
||||||
from django.db.models.expressions import Func, Value
|
from django.db.models.expressions import Func, Star
|
||||||
from django.db.models.fields import FloatField, IntegerField
|
from django.db.models.fields import FloatField, IntegerField
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
@ -98,7 +98,7 @@ class Count(Aggregate):
|
|||||||
|
|
||||||
def __init__(self, expression, distinct=False, **extra):
|
def __init__(self, expression, distinct=False, **extra):
|
||||||
if expression == '*':
|
if expression == '*':
|
||||||
expression = Value(expression)
|
expression = Star()
|
||||||
super(Count, self).__init__(
|
super(Count, self).__init__(
|
||||||
expression, distinct='DISTINCT ' if distinct else '', output_field=IntegerField(), **extra)
|
expression, distinct='DISTINCT ' if distinct else '', output_field=IntegerField(), **extra)
|
||||||
|
|
||||||
|
@ -593,6 +593,14 @@ class RawSQL(Expression):
|
|||||||
return [self]
|
return [self]
|
||||||
|
|
||||||
|
|
||||||
|
class Star(Expression):
|
||||||
|
def __repr__(self):
|
||||||
|
return "'*'"
|
||||||
|
|
||||||
|
def as_sql(self, compiler, connection):
|
||||||
|
return '*', []
|
||||||
|
|
||||||
|
|
||||||
class Random(Expression):
|
class Random(Expression):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(Random, self).__init__(output_field=fields.FloatField())
|
super(Random, self).__init__(output_field=fields.FloatField())
|
||||||
|
@ -32,3 +32,7 @@ Bugfixes
|
|||||||
|
|
||||||
* Fixed migrations crash on MySQL when adding a text or a blob field with an
|
* Fixed migrations crash on MySQL when adding a text or a blob field with an
|
||||||
unhashable default (:ticket:`25393`).
|
unhashable default (:ticket:`25393`).
|
||||||
|
|
||||||
|
* Changed ``Count`` queries to execute ``COUNT(*)`` instead of ``COUNT('*')``
|
||||||
|
as versions of Django before 1.8 did (:ticket:`25377`). This may fix a
|
||||||
|
performance regression on some databases.
|
||||||
|
@ -405,6 +405,12 @@ class AggregateTestCase(TestCase):
|
|||||||
vals = Book.objects.aggregate(Count("rating", distinct=True))
|
vals = Book.objects.aggregate(Count("rating", distinct=True))
|
||||||
self.assertEqual(vals, {"rating__count": 4})
|
self.assertEqual(vals, {"rating__count": 4})
|
||||||
|
|
||||||
|
def test_count_star(self):
|
||||||
|
with self.assertNumQueries(1) as ctx:
|
||||||
|
Book.objects.aggregate(n=Count("*"))
|
||||||
|
sql = ctx.captured_queries[0]['sql']
|
||||||
|
self.assertIn('SELECT COUNT(*) ', sql)
|
||||||
|
|
||||||
def test_non_grouped_annotation_not_in_group_by(self):
|
def test_non_grouped_annotation_not_in_group_by(self):
|
||||||
"""
|
"""
|
||||||
An annotation not included in values() before an aggregate should be
|
An annotation not included in values() before an aggregate should be
|
||||||
|
@ -878,6 +878,7 @@ class ReprTests(TestCase):
|
|||||||
def test_aggregates(self):
|
def test_aggregates(self):
|
||||||
self.assertEqual(repr(Avg('a')), "Avg(F(a))")
|
self.assertEqual(repr(Avg('a')), "Avg(F(a))")
|
||||||
self.assertEqual(repr(Count('a')), "Count(F(a), distinct=False)")
|
self.assertEqual(repr(Count('a')), "Count(F(a), distinct=False)")
|
||||||
|
self.assertEqual(repr(Count('*')), "Count('*', distinct=False)")
|
||||||
self.assertEqual(repr(Max('a')), "Max(F(a))")
|
self.assertEqual(repr(Max('a')), "Max(F(a))")
|
||||||
self.assertEqual(repr(Min('a')), "Min(F(a))")
|
self.assertEqual(repr(Min('a')), "Min(F(a))")
|
||||||
self.assertEqual(repr(StdDev('a')), "StdDev(F(a), sample=False)")
|
self.assertEqual(repr(StdDev('a')), "StdDev(F(a), sample=False)")
|
||||||
|
@ -63,25 +63,25 @@ class TestDebugSQL(unittest.TestCase):
|
|||||||
|
|
||||||
if six.PY3:
|
if six.PY3:
|
||||||
expected_outputs = [
|
expected_outputs = [
|
||||||
('''QUERY = 'SELECT COUNT(%s) AS "__count" '''
|
('''QUERY = 'SELECT COUNT(*) AS "__count" '''
|
||||||
'''FROM "test_runner_person" WHERE '''
|
'''FROM "test_runner_person" WHERE '''
|
||||||
'''"test_runner_person"."first_name" = %s' '''
|
'''"test_runner_person"."first_name" = %s' '''
|
||||||
'''- PARAMS = ('*', 'error');'''),
|
'''- PARAMS = ('error',);'''),
|
||||||
('''QUERY = 'SELECT COUNT(%s) AS "__count" '''
|
('''QUERY = 'SELECT COUNT(*) AS "__count" '''
|
||||||
'''FROM "test_runner_person" WHERE '''
|
'''FROM "test_runner_person" WHERE '''
|
||||||
'''"test_runner_person"."first_name" = %s' '''
|
'''"test_runner_person"."first_name" = %s' '''
|
||||||
'''- PARAMS = ('*', 'fail');'''),
|
'''- PARAMS = ('fail',);'''),
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
expected_outputs = [
|
expected_outputs = [
|
||||||
('''QUERY = u'SELECT COUNT(%s) AS "__count" '''
|
('''QUERY = u'SELECT COUNT(*) AS "__count" '''
|
||||||
'''FROM "test_runner_person" WHERE '''
|
'''FROM "test_runner_person" WHERE '''
|
||||||
'''"test_runner_person"."first_name" = %s' '''
|
'''"test_runner_person"."first_name" = %s' '''
|
||||||
'''- PARAMS = (u'*', u'error');'''),
|
'''- PARAMS = (u'error',);'''),
|
||||||
('''QUERY = u'SELECT COUNT(%s) AS "__count" '''
|
('''QUERY = u'SELECT COUNT(*) AS "__count" '''
|
||||||
'''FROM "test_runner_person" WHERE '''
|
'''FROM "test_runner_person" WHERE '''
|
||||||
'''"test_runner_person"."first_name" = %s' '''
|
'''"test_runner_person"."first_name" = %s' '''
|
||||||
'''- PARAMS = (u'*', u'fail');'''),
|
'''- PARAMS = (u'fail',);'''),
|
||||||
]
|
]
|
||||||
|
|
||||||
verbose_expected_outputs = [
|
verbose_expected_outputs = [
|
||||||
@ -94,15 +94,15 @@ class TestDebugSQL(unittest.TestCase):
|
|||||||
]
|
]
|
||||||
if six.PY3:
|
if six.PY3:
|
||||||
verbose_expected_outputs += [
|
verbose_expected_outputs += [
|
||||||
('''QUERY = 'SELECT COUNT(%s) AS "__count" '''
|
('''QUERY = 'SELECT COUNT(*) AS "__count" '''
|
||||||
'''FROM "test_runner_person" WHERE '''
|
'''FROM "test_runner_person" WHERE '''
|
||||||
'''"test_runner_person"."first_name" = %s' '''
|
'''"test_runner_person"."first_name" = %s' '''
|
||||||
'''- PARAMS = ('*', 'pass');'''),
|
'''- PARAMS = ('pass',);'''),
|
||||||
]
|
]
|
||||||
else:
|
else:
|
||||||
verbose_expected_outputs += [
|
verbose_expected_outputs += [
|
||||||
('''QUERY = u'SELECT COUNT(%s) AS "__count" '''
|
('''QUERY = u'SELECT COUNT(*) AS "__count" '''
|
||||||
'''FROM "test_runner_person" WHERE '''
|
'''FROM "test_runner_person" WHERE '''
|
||||||
'''"test_runner_person"."first_name" = %s' '''
|
'''"test_runner_person"."first_name" = %s' '''
|
||||||
'''- PARAMS = (u'*', u'pass');'''),
|
'''- PARAMS = (u'pass',);'''),
|
||||||
]
|
]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user