1
0
mirror of https://github.com/django/django.git synced 2025-07-06 18:59:13 +00:00

queryset-refactor: Made qs.dates(...).count() work.

This involved a slight change in the SQL for .dates() which appears to be
correct and passes all the tests, but may have some side-effect I don't know
about.

Refs #6203.


git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@6959 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2007-12-19 12:23:59 +00:00
parent 18adbb6363
commit 470ddafe97
3 changed files with 35 additions and 12 deletions

View File

@ -50,12 +50,14 @@ class Count(Aggregate):
quote_func = lambda x: x quote_func = lambda x: x
if isinstance(self.col, (list, tuple)): if isinstance(self.col, (list, tuple)):
col = ('%s.%s' % tuple([quote_func(c) for c in self.col])) col = ('%s.%s' % tuple([quote_func(c) for c in self.col]))
elif hasattr(self.col, 'as_sql'):
col = self.col.as_sql(quote_func)
else: else:
col = self.col col = self.col
if self.distinct: if self.distinct:
return 'COUNT(DISTINCT %s)' % col return 'COUNT(DISTINCT %s)' % col
else: else:
return 'COUNT(%s)' % self.col return 'COUNT(%s)' % col
class Date(object): class Date(object):
""" """

View File

@ -193,6 +193,8 @@ class Query(object):
if obj.distinct and len(obj.select) > 1: if obj.distinct and len(obj.select) > 1:
obj = self.clone(CountQuery, _query=obj, where=WhereNode(), obj = self.clone(CountQuery, _query=obj, where=WhereNode(),
distinct=False) distinct=False)
obj.select = []
obj.extra_select = SortedDict()
obj.add_count_column() obj.add_count_column()
data = obj.execute_sql(SINGLE) data = obj.execute_sql(SINGLE)
if not data: if not data:
@ -1008,13 +1010,18 @@ class Query(object):
def add_count_column(self): def add_count_column(self):
""" """
Converts the query to do count(*) or count(distinct(pk)) in order to Converts the query to do count(...) or count(distinct(pk)) in order to
get its size. get its size.
""" """
# TODO: When group_by support is added, this needs to be adjusted so # TODO: When group_by support is added, this needs to be adjusted so
# that it doesn't totally overwrite the select list. # that it doesn't totally overwrite the select list.
if not self.distinct: if not self.distinct:
select = Count() if not self.select:
select = Count()
else:
assert len(self.select) == 1, \
"Cannot add count col with multiple cols in 'select': %r" % self.select
select = Count(self.select[0])
else: else:
opts = self.model._meta opts = self.model._meta
if not self.select: if not self.select:
@ -1229,11 +1236,8 @@ class DateQuery(Query):
select = Date((alias, column), lookup_type, select = Date((alias, column), lookup_type,
self.connection.ops.date_trunc_sql) self.connection.ops.date_trunc_sql)
self.select = [select] self.select = [select]
self.distinct = True
self.order_by = order == 'ASC' and [1] or [-1] self.order_by = order == 'ASC' and [1] or [-1]
if self.connection.features.allows_group_by_ordinal:
self.group_by = [1]
else:
self.group_by = [select]
class CountQuery(Query): class CountQuery(Query):
""" """

View File

@ -2,6 +2,8 @@
Various complex queries that have been problematic in the past. Various complex queries that have been problematic in the past.
""" """
import datetime
from django.db import models from django.db import models
from django.db.models.query import Q from django.db.models.query import Q
@ -42,6 +44,7 @@ class Author(models.Model):
class Item(models.Model): class Item(models.Model):
name = models.CharField(max_length=10) name = models.CharField(max_length=10)
created = models.DateTimeField()
tags = models.ManyToManyField(Tag, blank=True, null=True) tags = models.ManyToManyField(Tag, blank=True, null=True)
creator = models.ForeignKey(Author) creator = models.ForeignKey(Author)
note = models.ForeignKey(Note) note = models.ForeignKey(Note)
@ -129,15 +132,19 @@ by 'info'. Helps detect some problems later.
>>> a4 = Author(name='a4', num=4004, extra=e2) >>> a4 = Author(name='a4', num=4004, extra=e2)
>>> a4.save() >>> a4.save()
>>> i1 = Item(name='one', creator=a1, note=n3) >>> time1 = datetime.datetime(2007, 12, 19, 22, 25, 0)
>>> time2 = datetime.datetime(2007, 12, 19, 21, 0, 0)
>>> time3 = datetime.datetime(2007, 12, 20, 22, 25, 0)
>>> time4 = datetime.datetime(2007, 12, 20, 21, 0, 0)
>>> i1 = Item(name='one', created=time1, creator=a1, note=n3)
>>> i1.save() >>> i1.save()
>>> i1.tags = [t1, t2] >>> i1.tags = [t1, t2]
>>> i2 = Item(name='two', creator=a2, note=n2) >>> i2 = Item(name='two', created=time2, creator=a2, note=n2)
>>> i2.save() >>> i2.save()
>>> i2.tags = [t1, t3] >>> i2.tags = [t1, t3]
>>> i3 = Item(name='three', creator=a2, note=n3) >>> i3 = Item(name='three', created=time3, creator=a2, note=n3)
>>> i3.save() >>> i3.save()
>>> i4 = Item(name='four', creator=a4, note=n3) >>> i4 = Item(name='four', created=time4, creator=a4, note=n3)
>>> i4.save() >>> i4.save()
>>> i4.tags = [t4] >>> i4.tags = [t4]
@ -244,7 +251,7 @@ Bug #1878, #2939
# Create something with a duplicate 'name' so that we can test multi-column # Create something with a duplicate 'name' so that we can test multi-column
# cases (which require some tricky SQL transformations under the covers). # cases (which require some tricky SQL transformations under the covers).
>>> xx = Item(name='four', creator=a2, note=n1) >>> xx = Item(name='four', created=time1, creator=a2, note=n1)
>>> xx.save() >>> xx.save()
>>> Item.objects.exclude(name='two').values('creator', 'name').distinct().count() >>> Item.objects.exclude(name='two').values('creator', 'name').distinct().count()
4 4
@ -471,5 +478,15 @@ Multiple filter statements are joined using "AND" all the time.
[<Author: a1>] [<Author: a1>]
>>> Author.objects.filter(Q(extra__note=n1)|Q(item__note=n3)).filter(id=a1.id) >>> Author.objects.filter(Q(extra__note=n1)|Q(item__note=n3)).filter(id=a1.id)
[<Author: a1>] [<Author: a1>]
Bug #6203
>>> Item.objects.count()
4
>>> Item.objects.dates('created', 'month').count()
1
>>> Item.objects.dates('created', 'day').count()
2
>>> len(Item.objects.dates('created', 'day'))
2
"""} """}