Skip to content

Commit 0fd3ad9

Browse files
committed
add type convesrions for legacy drivers from string to datetime
1 parent 5c8cb03 commit 0fd3ad9

File tree

1 file changed

+36
-3
lines changed

1 file changed

+36
-3
lines changed

sql_server/pyodbc/operations.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import datetime
22
import time
33
import uuid
4+
import warnings
45

56
from django.conf import settings
67
from django.db.backends.base.operations import BaseDatabaseOperations
@@ -33,6 +34,15 @@ def _get_utcoffset(self, tzname):
3334
delta = zone.localize(now, is_dst=False).utcoffset()
3435
return delta.days * 86400 + delta.seconds
3536

37+
def _warn_legacy_driver(self, sqltype):
38+
warnings.warn(
39+
'A %s value was received as a string. This is because you '
40+
'are now using a legacy ODBC driver which does not support '
41+
'this data type while your database has been migrated using it. '
42+
'You should upgrade your ODBC driver for consistency with your '
43+
'database migration.' % sqltype,
44+
RuntimeWarning)
45+
3646
def bulk_batch_size(self, fields, objs):
3747
"""
3848
Returns the maximum allowed batch size for the backend. The fields
@@ -83,19 +93,40 @@ def combine_expression(self, connector, sub_expressions):
8393

8494
def convert_datefield_value(self, value, expression, connection, context):
8595
if value is not None:
86-
if self.connection.use_legacy_datetime:
96+
# WDAC and old FreeTDS receive a date value as a string
97+
# http://blogs.msdn.com/b/sqlnativeclient/archive/2008/02/27/microsoft-sql-server-native-client-and-microsoft-sql-server-2008-native-client.aspx
98+
if isinstance(value, string_types):
99+
self._warn_legacy_driver('date')
100+
value = datetime.date(*map(lambda x: int(x), value.split('-')))
101+
elif self.connection.use_legacy_datetime:
87102
if isinstance(value, datetime.datetime):
88103
value = value.date() # extract date
89104
return value
90105

106+
def convert_datetimefield_value(self, value, expression, connection, context):
107+
if value is not None:
108+
# WDAC and old FreeTDS receive a datetime2 value as a string
109+
# http://blogs.msdn.com/b/sqlnativeclient/archive/2008/02/27/microsoft-sql-server-native-client-and-microsoft-sql-server-2008-native-client.aspx
110+
if isinstance(value, string_types):
111+
self._warn_legacy_driver('datetime2')
112+
value = datetime.datetime.strptime(value[:26], '%Y-%m-%d %H:%M:%S.%f')
113+
if settings.USE_TZ:
114+
value = timezone.make_aware(value, timezone.utc)
115+
return value
116+
91117
def convert_floatfield_value(self, value, expression, connection, context):
92118
if value is not None:
93119
value = float(value)
94120
return value
95121

96122
def convert_timefield_value(self, value, expression, connection, context):
97123
if value is not None:
98-
if self.connection.use_legacy_datetime:
124+
# WDAC and old FreeTDS receive a time value as a string
125+
# http://blogs.msdn.com/b/sqlnativeclient/archive/2008/02/27/microsoft-sql-server-native-client-and-microsoft-sql-server-2008-native-client.aspx
126+
if isinstance(value, string_types):
127+
self._warn_legacy_driver('time')
128+
value = datetime.time(*map(lambda x: int(x), value[:15].replace('.', ':').split(':')))
129+
elif self.connection.use_legacy_datetime:
99130
if (isinstance(value, datetime.datetime) and value.year == 1900 and value.month == value.day == 1):
100131
value = value.time() # extract time
101132
return value
@@ -194,6 +225,8 @@ def get_db_converters(self, expression):
194225
internal_type = expression.output_field.get_internal_type()
195226
if internal_type == 'DateField':
196227
converters.append(self.convert_datefield_value)
228+
if internal_type == 'DateTimeField':
229+
converters.append(self.convert_datetimefield_value)
197230
elif internal_type == 'FloatField':
198231
converters.append(self.convert_floatfield_value)
199232
elif internal_type == 'TimeField':
@@ -392,7 +425,7 @@ def value_to_db_datetime(self, value):
392425
return None
393426
if settings.USE_TZ and timezone.is_aware(value):
394427
# pyodbc donesn't support datetimeoffset
395-
value = value.astimezone(timezone.utc)
428+
value = value.astimezone(timezone.utc).replace(tzinfo=None)
396429
if not self.connection.features.supports_microsecond_precision:
397430
value = value.replace(microsecond=0)
398431
return value

0 commit comments

Comments
 (0)