Changed __year lookup to use a BETWEEN SQL statement instead of comparing the result of EXTRACT(year). This should be more efficient.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@4505 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
9efa60dafb
commit
4c4209b144
|
@ -164,7 +164,7 @@ class Field(object):
|
||||||
|
|
||||||
def get_db_prep_lookup(self, lookup_type, value):
|
def get_db_prep_lookup(self, lookup_type, value):
|
||||||
"Returns field's value prepared for database lookup."
|
"Returns field's value prepared for database lookup."
|
||||||
if lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte', 'year', 'month', 'day', 'search'):
|
if lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte', 'month', 'day', 'search'):
|
||||||
return [value]
|
return [value]
|
||||||
elif lookup_type in ('range', 'in'):
|
elif lookup_type in ('range', 'in'):
|
||||||
return value
|
return value
|
||||||
|
@ -178,7 +178,13 @@ class Field(object):
|
||||||
return ["%%%s" % prep_for_like_query(value)]
|
return ["%%%s" % prep_for_like_query(value)]
|
||||||
elif lookup_type == 'isnull':
|
elif lookup_type == 'isnull':
|
||||||
return []
|
return []
|
||||||
raise TypeError, "Field has invalid lookup: %s" % lookup_type
|
elif lookup_type == 'year':
|
||||||
|
try:
|
||||||
|
value = int(value)
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError("The __year lookup type requires an integer argument")
|
||||||
|
return ['%s-01-01 00:00:00' % value, '%s-12-31 23:59:59.999999' % value]
|
||||||
|
raise TypeError("Field has invalid lookup: %s" % lookup_type)
|
||||||
|
|
||||||
def has_default(self):
|
def has_default(self):
|
||||||
"Returns a boolean of whether this field has a default value."
|
"Returns a boolean of whether this field has a default value."
|
||||||
|
|
|
@ -198,17 +198,17 @@ class QuerySet(object):
|
||||||
counter = self._clone()
|
counter = self._clone()
|
||||||
counter._order_by = ()
|
counter._order_by = ()
|
||||||
counter._select_related = False
|
counter._select_related = False
|
||||||
|
|
||||||
offset = counter._offset
|
offset = counter._offset
|
||||||
limit = counter._limit
|
limit = counter._limit
|
||||||
counter._offset = None
|
counter._offset = None
|
||||||
counter._limit = None
|
counter._limit = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
select, sql, params = counter._get_sql_clause()
|
select, sql, params = counter._get_sql_clause()
|
||||||
except EmptyResultSet:
|
except EmptyResultSet:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
if self._distinct:
|
if self._distinct:
|
||||||
id_col = "%s.%s" % (backend.quote_name(self.model._meta.db_table),
|
id_col = "%s.%s" % (backend.quote_name(self.model._meta.db_table),
|
||||||
|
@ -553,7 +553,7 @@ class ValuesQuerySet(QuerySet):
|
||||||
else: # Default to all fields.
|
else: # Default to all fields.
|
||||||
columns = [f.column for f in self.model._meta.fields]
|
columns = [f.column for f in self.model._meta.fields]
|
||||||
field_names = [f.attname for f in self.model._meta.fields]
|
field_names = [f.attname for f in self.model._meta.fields]
|
||||||
|
|
||||||
select = ['%s.%s' % (backend.quote_name(self.model._meta.db_table), backend.quote_name(c)) for c in columns]
|
select = ['%s.%s' % (backend.quote_name(self.model._meta.db_table), backend.quote_name(c)) for c in columns]
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params)
|
cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params)
|
||||||
|
@ -576,12 +576,12 @@ class DateQuerySet(QuerySet):
|
||||||
if self._field.null:
|
if self._field.null:
|
||||||
self._where.append('%s.%s IS NOT NULL' % \
|
self._where.append('%s.%s IS NOT NULL' % \
|
||||||
(backend.quote_name(self.model._meta.db_table), backend.quote_name(self._field.column)))
|
(backend.quote_name(self.model._meta.db_table), backend.quote_name(self._field.column)))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
select, sql, params = self._get_sql_clause()
|
select, sql, params = self._get_sql_clause()
|
||||||
except EmptyResultSet:
|
except EmptyResultSet:
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
|
|
||||||
sql = 'SELECT %s %s GROUP BY 1 ORDER BY 1 %s' % \
|
sql = 'SELECT %s %s GROUP BY 1 ORDER BY 1 %s' % \
|
||||||
(backend.get_date_trunc_sql(self._kind, '%s.%s' % (backend.quote_name(self.model._meta.db_table),
|
(backend.get_date_trunc_sql(self._kind, '%s.%s' % (backend.quote_name(self.model._meta.db_table),
|
||||||
backend.quote_name(self._field.column))), sql, self._order)
|
backend.quote_name(self._field.column))), sql, self._order)
|
||||||
|
@ -598,15 +598,15 @@ class DateQuerySet(QuerySet):
|
||||||
c._kind = self._kind
|
c._kind = self._kind
|
||||||
c._order = self._order
|
c._order = self._order
|
||||||
return c
|
return c
|
||||||
|
|
||||||
class EmptyQuerySet(QuerySet):
|
class EmptyQuerySet(QuerySet):
|
||||||
def __init__(self, model=None):
|
def __init__(self, model=None):
|
||||||
super(EmptyQuerySet, self).__init__(model)
|
super(EmptyQuerySet, self).__init__(model)
|
||||||
self._result_cache = []
|
self._result_cache = []
|
||||||
|
|
||||||
def count(self):
|
def count(self):
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -708,9 +708,9 @@ def get_where_clause(lookup_type, table_prefix, field_name, value):
|
||||||
return '%s%s IN (%s)' % (table_prefix, field_name, in_string)
|
return '%s%s IN (%s)' % (table_prefix, field_name, in_string)
|
||||||
else:
|
else:
|
||||||
raise EmptyResultSet
|
raise EmptyResultSet
|
||||||
elif lookup_type == 'range':
|
elif lookup_type in ('range', 'year'):
|
||||||
return '%s%s BETWEEN %%s AND %%s' % (table_prefix, field_name)
|
return '%s%s BETWEEN %%s AND %%s' % (table_prefix, field_name)
|
||||||
elif lookup_type in ('year', 'month', 'day'):
|
elif lookup_type in ('month', 'day'):
|
||||||
return "%s = %%s" % backend.get_date_extract_sql(lookup_type, table_prefix + field_name)
|
return "%s = %%s" % backend.get_date_extract_sql(lookup_type, table_prefix + field_name)
|
||||||
elif lookup_type == 'isnull':
|
elif lookup_type == 'isnull':
|
||||||
return "%s%s IS %sNULL" % (table_prefix, field_name, (not value and 'NOT ' or ''))
|
return "%s%s IS %sNULL" % (table_prefix, field_name, (not value and 'NOT ' or ''))
|
||||||
|
@ -791,7 +791,7 @@ def parse_lookup(kwarg_items, opts):
|
||||||
|
|
||||||
if len(path) < 1:
|
if len(path) < 1:
|
||||||
raise TypeError, "Cannot parse keyword query %r" % kwarg
|
raise TypeError, "Cannot parse keyword query %r" % kwarg
|
||||||
|
|
||||||
if value is None:
|
if value is None:
|
||||||
# Interpret '__exact=None' as the sql '= NULL'; otherwise, reject
|
# Interpret '__exact=None' as the sql '= NULL'; otherwise, reject
|
||||||
# all uses of None as a query value.
|
# all uses of None as a query value.
|
||||||
|
@ -1007,7 +1007,7 @@ def delete_objects(seen_objs):
|
||||||
pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE])
|
pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE])
|
||||||
for f in cls._meta.many_to_many:
|
for f in cls._meta.many_to_many:
|
||||||
if isinstance(f, GenericRelation):
|
if isinstance(f, GenericRelation):
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
query_extra = 'AND %s=%%s' % f.rel.to._meta.get_field(f.content_type_field_name).column
|
query_extra = 'AND %s=%%s' % f.rel.to._meta.get_field(f.content_type_field_name).column
|
||||||
args_extra = [ContentType.objects.get_for_model(cls).id]
|
args_extra = [ContentType.objects.get_for_model(cls).id]
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -12,7 +12,7 @@ class Article(models.Model):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ('pub_date','headline')
|
ordering = ('pub_date','headline')
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.headline
|
return self.headline
|
||||||
|
|
||||||
|
@ -319,7 +319,6 @@ AttributeError: Manager isn't accessible via Article instances
|
||||||
>>> Article.objects.filter(id__lte=4).delete()
|
>>> Article.objects.filter(id__lte=4).delete()
|
||||||
>>> Article.objects.all()
|
>>> Article.objects.all()
|
||||||
[<Article: Article 6>, <Article: Default headline>, <Article: Article 7>, <Article: Updated article 8>]
|
[<Article: Article 6>, <Article: Default headline>, <Article: Article 7>, <Article: Updated article 8>]
|
||||||
|
|
||||||
"""}
|
"""}
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -358,4 +357,11 @@ __test__['API_TESTS'] += """
|
||||||
>>> a10 = Article.objects.create(headline="Article 10", pub_date=datetime(2005, 7, 31, 12, 30, 45))
|
>>> a10 = Article.objects.create(headline="Article 10", pub_date=datetime(2005, 7, 31, 12, 30, 45))
|
||||||
>>> Article.objects.get(headline="Article 10")
|
>>> Article.objects.get(headline="Article 10")
|
||||||
<Article: Article 10>
|
<Article: Article 10>
|
||||||
|
|
||||||
|
# Edge-case test: A year lookup should retrieve all objects in the given
|
||||||
|
year, including Jan. 1 and Dec. 31.
|
||||||
|
>>> a11 = Article.objects.create(headline='Article 11', pub_date=datetime(2008, 1, 1))
|
||||||
|
>>> a12 = Article.objects.create(headline='Article 12', pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999))
|
||||||
|
>>> Article.objects.filter(pub_date__year=2008)
|
||||||
|
[<Article: Article 11>, <Article: Article 12>]
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue