Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Factored out database-specific date_trunc behavior into dbmod.get_dat…

…e_trunc_sql(). Refs #46

git-svn-id: http://code.djangoproject.com/svn/django/trunk@161 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit b1c543d0910a79f4de93464fa684416c9441f7ce 1 parent d4ddc06
Adrian Holovaty authored
1  django/core/db/__init__.py
@@ -29,5 +29,6 @@
29 29
 dictfetchall = dbmod.dictfetchall
30 30
 get_last_insert_id = dbmod.get_last_insert_id
31 31
 get_date_extract_sql = dbmod.get_date_extract_sql
  32
+get_date_trunc_sql = dbmod.get_date_trunc_sql
32 33
 OPERATOR_MAPPING = dbmod.OPERATOR_MAPPING
33 34
 DATA_TYPES = dbmod.DATA_TYPES
13  django/core/db/backends/mysql.py
@@ -64,8 +64,21 @@ def get_last_insert_id(cursor, table_name, pk_name):
64 64
 
65 65
 def get_date_extract_sql(lookup_type, table_name):
66 66
     # lookup_type is 'year', 'month', 'day'
  67
+    # http://dev.mysql.com/doc/mysql/en/date-and-time-functions.html
67 68
     return "EXTRACT(%s FROM %s)" % (lookup_type.upper(), table_name)
68 69
 
  70
+def get_date_trunc_sql(lookup_type, field_name):
  71
+    # lookup_type is 'year', 'month', 'day'
  72
+    # http://dev.mysql.com/doc/mysql/en/date-and-time-functions.html
  73
+    # MySQL doesn't support DATE_TRUNC, so we fake it by subtracting intervals.
  74
+    # If you know of a better way to do this, please file a Django ticket.
  75
+    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)]
  76
+    if lookup_type in ('year', 'month'):
  77
+        subtractions.append(" - interval (DATE_FORMAT(%s, '%%%%e')-1) day" % field_name)
  78
+    if lookup_type == 'year':
  79
+        subtractions.append(" - interval (DATE_FORMAT(%s, '%%%%m')-1) month" % field_name)
  80
+    return "(%s - %s)" % (field_name, ''.join(subtractions))
  81
+
69 82
 OPERATOR_MAPPING = {
70 83
     'exact': '=',
71 84
     'iexact': 'LIKE',
6  django/core/db/backends/postgresql.py
@@ -63,8 +63,14 @@ def get_last_insert_id(cursor, table_name, pk_name):
63 63
 
64 64
 def get_date_extract_sql(lookup_type, table_name):
65 65
     # lookup_type is 'year', 'month', 'day'
  66
+    # http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT
66 67
     return "EXTRACT('%s' FROM %s)" % (lookup_type, table_name)
67 68
 
  69
+def get_date_trunc_sql(lookup_type, field_name):
  70
+    # lookup_type is 'year', 'month', 'day'
  71
+    # http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
  72
+    return "DATE_TRUNC('%s', %s)" % (lookup_type, field_name)
  73
+
68 74
 # Register these custom typecasts, because Django expects dates/times to be
69 75
 # in Python's native (standard-library) datetime/time format, whereas psycopg
70 76
 # use mx.DateTime by default.
10  django/core/meta.py
@@ -1264,6 +1264,7 @@ def function_get_latest(opts, klass, does_not_exist_exception, **kwargs):
1264 1264
     return function_get_object(opts, klass, does_not_exist_exception, **kwargs)
1265 1265
 
1266 1266
 def function_get_date_list(opts, field, *args, **kwargs):
  1267
+    from django.core.db.typecasts import typecast_timestamp
1267 1268
     kind = args and args[0] or kwargs['kind']
1268 1269
     assert kind in ("month", "year", "day"), "'kind' must be one of 'year', 'month' or 'day'."
1269 1270
     order = 'ASC'
@@ -1275,10 +1276,13 @@ def function_get_date_list(opts, field, *args, **kwargs):
1275 1276
     if field.null:
1276 1277
         kwargs.setdefault('where', []).append('%s.%s IS NOT NULL' % (opts.db_table, field.name))
1277 1278
     select, sql, params = function_get_sql_clause(opts, **kwargs)
1278  
-    sql = "SELECT DATE_TRUNC(%%s, %s.%s) %s GROUP BY 1 ORDER BY 1 %s" % (opts.db_table, field.name, sql, order)
  1279
+    sql = 'SELECT %s %s GROUP BY 1 ORDER BY 1' % (db.get_date_trunc_sql(kind, '%s.%s' % (opts.db_table, field.name)), sql)
1279 1280
     cursor = db.db.cursor()
1280  
-    cursor.execute(sql, [kind] + params)
1281  
-    return [row[0] for row in cursor.fetchall()]
  1281
+    cursor.execute(sql, params)
  1282
+    # We have to manually run typecast_timestamp(str()) on the results, because
  1283
+    # MySQL doesn't automatically cast the result of date functions as datetime
  1284
+    # objects -- MySQL returns the values as strings, instead.
  1285
+    return [typecast_timestamp(str(row[0])) for row in cursor.fetchall()]
1282 1286
 
1283 1287
 ###################################
1284 1288
 # HELPER FUNCTIONS (MANIPULATORS) #

0 notes on commit b1c543d

Please sign in to comment.
Something went wrong with that request. Please try again.