Factored out database-specific date_trunc behavior into dbmod.get_date_trunc_sql(). Refs #46

git-svn-id: http://code.djangoproject.com/svn/django/trunk@161 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2005-07-17 20:16:06 +00:00
parent d4ddc06021
commit b1c543d091
4 changed files with 27 additions and 3 deletions

View File

@ -29,5 +29,6 @@ dictfetchall = dbmod.dictfetchall
dictfetchall = dbmod.dictfetchall dictfetchall = dbmod.dictfetchall
get_last_insert_id = dbmod.get_last_insert_id get_last_insert_id = dbmod.get_last_insert_id
get_date_extract_sql = dbmod.get_date_extract_sql get_date_extract_sql = dbmod.get_date_extract_sql
get_date_trunc_sql = dbmod.get_date_trunc_sql
OPERATOR_MAPPING = dbmod.OPERATOR_MAPPING OPERATOR_MAPPING = dbmod.OPERATOR_MAPPING
DATA_TYPES = dbmod.DATA_TYPES DATA_TYPES = dbmod.DATA_TYPES

View File

@ -64,8 +64,21 @@ def get_last_insert_id(cursor, table_name, pk_name):
def get_date_extract_sql(lookup_type, table_name): def get_date_extract_sql(lookup_type, table_name):
# lookup_type is 'year', 'month', 'day' # lookup_type is 'year', 'month', 'day'
# http://dev.mysql.com/doc/mysql/en/date-and-time-functions.html
return "EXTRACT(%s FROM %s)" % (lookup_type.upper(), table_name) return "EXTRACT(%s FROM %s)" % (lookup_type.upper(), table_name)
def get_date_trunc_sql(lookup_type, field_name):
# lookup_type is 'year', 'month', 'day'
# http://dev.mysql.com/doc/mysql/en/date-and-time-functions.html
# MySQL doesn't support DATE_TRUNC, so we fake it by subtracting intervals.
# If you know of a better way to do this, please file a Django ticket.
subtractions = ["interval (DATE_FORMAT(%s, '%%%%s')) second - interval (DATE_FORMAT(%s, '%%%%i')) minute - interval (DATE_FORMAT(%s, '%%%%H')) hour" % (field_name, field_name, field_name)]
if lookup_type in ('year', 'month'):
subtractions.append(" - interval (DATE_FORMAT(%s, '%%%%e')-1) day" % field_name)
if lookup_type == 'year':
subtractions.append(" - interval (DATE_FORMAT(%s, '%%%%m')-1) month" % field_name)
return "(%s - %s)" % (field_name, ''.join(subtractions))
OPERATOR_MAPPING = { OPERATOR_MAPPING = {
'exact': '=', 'exact': '=',
'iexact': 'LIKE', 'iexact': 'LIKE',

View File

@ -63,8 +63,14 @@ def get_last_insert_id(cursor, table_name, pk_name):
def get_date_extract_sql(lookup_type, table_name): def get_date_extract_sql(lookup_type, table_name):
# lookup_type is 'year', 'month', 'day' # lookup_type is 'year', 'month', 'day'
# http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT
return "EXTRACT('%s' FROM %s)" % (lookup_type, table_name) return "EXTRACT('%s' FROM %s)" % (lookup_type, table_name)
def get_date_trunc_sql(lookup_type, field_name):
# lookup_type is 'year', 'month', 'day'
# http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
return "DATE_TRUNC('%s', %s)" % (lookup_type, field_name)
# Register these custom typecasts, because Django expects dates/times to be # Register these custom typecasts, because Django expects dates/times to be
# in Python's native (standard-library) datetime/time format, whereas psycopg # in Python's native (standard-library) datetime/time format, whereas psycopg
# use mx.DateTime by default. # use mx.DateTime by default.

View File

@ -1264,6 +1264,7 @@ def function_get_latest(opts, klass, does_not_exist_exception, **kwargs):
return function_get_object(opts, klass, does_not_exist_exception, **kwargs) return function_get_object(opts, klass, does_not_exist_exception, **kwargs)
def function_get_date_list(opts, field, *args, **kwargs): def function_get_date_list(opts, field, *args, **kwargs):
from django.core.db.typecasts import typecast_timestamp
kind = args and args[0] or kwargs['kind'] kind = args and args[0] or kwargs['kind']
assert kind in ("month", "year", "day"), "'kind' must be one of 'year', 'month' or 'day'." assert kind in ("month", "year", "day"), "'kind' must be one of 'year', 'month' or 'day'."
order = 'ASC' order = 'ASC'
@ -1275,10 +1276,13 @@ def function_get_date_list(opts, field, *args, **kwargs):
if field.null: if field.null:
kwargs.setdefault('where', []).append('%s.%s IS NOT NULL' % (opts.db_table, field.name)) kwargs.setdefault('where', []).append('%s.%s IS NOT NULL' % (opts.db_table, field.name))
select, sql, params = function_get_sql_clause(opts, **kwargs) select, sql, params = function_get_sql_clause(opts, **kwargs)
sql = "SELECT DATE_TRUNC(%%s, %s.%s) %s GROUP BY 1 ORDER BY 1 %s" % (opts.db_table, field.name, sql, order) sql = 'SELECT %s %s GROUP BY 1 ORDER BY 1' % (db.get_date_trunc_sql(kind, '%s.%s' % (opts.db_table, field.name)), sql)
cursor = db.db.cursor() cursor = db.db.cursor()
cursor.execute(sql, [kind] + params) cursor.execute(sql, params)
return [row[0] for row in cursor.fetchall()] # We have to manually run typecast_timestamp(str()) on the results, because
# MySQL doesn't automatically cast the result of date functions as datetime
# objects -- MySQL returns the values as strings, instead.
return [typecast_timestamp(str(row[0])) for row in cursor.fetchall()]
################################### ###################################
# HELPER FUNCTIONS (MANIPULATORS) # # HELPER FUNCTIONS (MANIPULATORS) #