mirror of
https://github.com/django/django.git
synced 2025-07-06 02:39:12 +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:
parent
18adbb6363
commit
470ddafe97
@ -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):
|
||||||
"""
|
"""
|
||||||
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
@ -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
|
||||||
"""}
|
"""}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user