Implemented QuerySet.datetimes on MySQL.
This commit is contained in:
parent
22d52681d3
commit
68ab511a4f
|
@ -30,3 +30,6 @@ class SQLAggregateCompiler(compiler.SQLAggregateCompiler, GeoSQLCompiler):
|
|||
|
||||
class SQLDateCompiler(compiler.SQLDateCompiler, GeoSQLCompiler):
|
||||
pass
|
||||
|
||||
class SQLDateTimeCompiler(compiler.SQLDateTimeCompiler, GeoSQLCompiler):
|
||||
pass
|
||||
|
|
|
@ -30,6 +30,7 @@ if (version < (1, 2, 1) or (version[:3] == (1, 2, 1) and
|
|||
from MySQLdb.converters import conversions, Thing2Literal
|
||||
from MySQLdb.constants import FIELD_TYPE, CLIENT
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import utils
|
||||
from django.db.backends import *
|
||||
from django.db.backends.signals import connection_created
|
||||
|
@ -193,6 +194,12 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
|||
"Confirm support for introspected foreign keys"
|
||||
return self._mysql_storage_engine != 'MyISAM'
|
||||
|
||||
@cached_property
|
||||
def has_zoneinfo_database(self):
|
||||
cursor = self.connection.cursor()
|
||||
cursor.execute("SELECT 1 FROM mysql.time_zone LIMIT 1")
|
||||
return cursor.fetchone() is not None
|
||||
|
||||
class DatabaseOperations(BaseDatabaseOperations):
|
||||
compiler_module = "django.db.backends.mysql.compiler"
|
||||
|
||||
|
@ -218,6 +225,32 @@ class DatabaseOperations(BaseDatabaseOperations):
|
|||
sql = "CAST(DATE_FORMAT(%s, '%s') AS DATETIME)" % (field_name, format_str)
|
||||
return sql
|
||||
|
||||
def datetime_extract_sql(self, lookup_type, field_name):
|
||||
if settings.USE_TZ:
|
||||
field_name = "CONVERT_TZ(%s, 'UTC', %%s)" % field_name
|
||||
# http://dev.mysql.com/doc/mysql/en/date-and-time-functions.html
|
||||
if lookup_type == 'week_day':
|
||||
# DAYOFWEEK() returns an integer, 1-7, Sunday=1.
|
||||
# Note: WEEKDAY() returns 0-6, Monday=0.
|
||||
return "DAYOFWEEK(%s)" % field_name
|
||||
else:
|
||||
return "EXTRACT(%s FROM %s)" % (lookup_type.upper(), field_name)
|
||||
|
||||
def datetime_trunc_sql(self, lookup_type, field_name):
|
||||
if settings.USE_TZ:
|
||||
field_name = "CONVERT_TZ(%s, 'UTC', %%s)" % field_name
|
||||
fields = ['year', 'month', 'day', 'hour', 'minute', 'second']
|
||||
format = ('%%Y-', '%%m', '-%%d', ' %%H:', '%%i', ':%%s') # Use double percents to escape.
|
||||
format_def = ('0000-', '01', '-01', ' 00:', '00', ':00')
|
||||
try:
|
||||
i = fields.index(lookup_type) + 1
|
||||
except ValueError:
|
||||
sql = field_name
|
||||
else:
|
||||
format_str = ''.join([f for f in format[:i]] + [f for f in format_def[i:]])
|
||||
sql = "CAST(DATE_FORMAT(%s, '%s') AS DATETIME)" % (field_name, format_str)
|
||||
return sql
|
||||
|
||||
def date_interval_sql(self, sql, connector, timedelta):
|
||||
return "(%s %s INTERVAL '%d 0:0:%d:%d' DAY_MICROSECOND)" % (sql, connector,
|
||||
timedelta.days, timedelta.seconds, timedelta.microseconds)
|
||||
|
@ -314,11 +347,10 @@ class DatabaseOperations(BaseDatabaseOperations):
|
|||
# MySQL doesn't support microseconds
|
||||
return six.text_type(value.replace(microsecond=0))
|
||||
|
||||
def year_lookup_bounds(self, value):
|
||||
def year_lookup_bounds_for_datetime_field(self, value):
|
||||
# Again, no microseconds
|
||||
first = '%s-01-01 00:00:00'
|
||||
second = '%s-12-31 23:59:59.99'
|
||||
return [first % value, second % value]
|
||||
first, second = super(DatabaseOperations, self).year_lookup_bounds_for_datetime_field(value)
|
||||
return [first.replace(microsecond=0), second.replace(microsecond=0)]
|
||||
|
||||
def max_name_length(self):
|
||||
return 64
|
||||
|
|
|
@ -31,3 +31,6 @@ class SQLAggregateCompiler(compiler.SQLAggregateCompiler, SQLCompiler):
|
|||
|
||||
class SQLDateCompiler(compiler.SQLDateCompiler, SQLCompiler):
|
||||
pass
|
||||
|
||||
class SQLDateTimeCompiler(compiler.SQLDateTimeCompiler, SQLCompiler):
|
||||
pass
|
||||
|
|
Loading…
Reference in New Issue