Skip to content

Commit 0b30bed

Browse files
committed
queryset-refactor: Pass any extra(select=...) columns through the value
conversion function in the Oracle backend after reading the row from the database. Refs django#7087 (see comment 7 on that ticket). git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@7470 bcc190cf-cafb-0310-a4f2-bffc1f526a37
1 parent 3933aff commit 0b30bed

File tree

1 file changed

+46
-40
lines changed

1 file changed

+46
-40
lines changed

django/db/backends/oracle/query.py

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -29,49 +29,55 @@ def resolve_columns(self, row, fields=()):
2929
from django.db.models.fields import DateField, DateTimeField, \
3030
TimeField, BooleanField, NullBooleanField, DecimalField, Field
3131
index_start = len(self.extra_select.keys())
32-
values = list(row[:index_start])
32+
values = [self.convert_values(v, None) for v in row[:index_start]]
3333
for value, field in map(None, row[index_start:], fields):
34-
if isinstance(value, Database.LOB):
35-
value = value.read()
36-
# Oracle stores empty strings as null. We need to undo this in
37-
# order to adhere to the Django convention of using the empty
38-
# string instead of null, but only if the field accepts the
39-
# empty string.
40-
if value is None and isinstance(field, Field) and field.empty_strings_allowed:
41-
value = u''
42-
# Convert 1 or 0 to True or False
43-
elif value in (1, 0) and isinstance(field, (BooleanField, NullBooleanField)):
44-
value = bool(value)
45-
# Convert floats to decimals
46-
elif value is not None and isinstance(field, DecimalField):
47-
value = util.typecast_decimal(field.format_number(value))
48-
# cx_Oracle always returns datetime.datetime objects for
49-
# DATE and TIMESTAMP columns, but Django wants to see a
50-
# python datetime.date, .time, or .datetime. We use the type
51-
# of the Field to determine which to cast to, but it's not
52-
# always available.
53-
# As a workaround, we cast to date if all the time-related
54-
# values are 0, or to time if the date is 1/1/1900.
55-
# This could be cleaned a bit by adding a method to the Field
56-
# classes to normalize values from the database (the to_python
57-
# method is used for validation and isn't what we want here).
58-
elif isinstance(value, Database.Timestamp):
59-
# In Python 2.3, the cx_Oracle driver returns its own
60-
# Timestamp object that we must convert to a datetime class.
61-
if not isinstance(value, datetime.datetime):
62-
value = datetime.datetime(value.year, value.month, value.day, value.hour,
63-
value.minute, value.second, value.fsecond)
64-
if isinstance(field, DateTimeField):
65-
pass # DateTimeField subclasses DateField so must be checked first.
66-
elif isinstance(field, DateField):
67-
value = value.date()
68-
elif isinstance(field, TimeField) or (value.year == 1900 and value.month == value.day == 1):
69-
value = value.time()
70-
elif value.hour == value.minute == value.second == value.microsecond == 0:
71-
value = value.date()
72-
values.append(value)
34+
values.append(self.convert_values(value, field))
7335
return values
7436

37+
def convert_values(self, value, field):
38+
if isinstance(value, Database.LOB):
39+
value = value.read()
40+
# Oracle stores empty strings as null. We need to undo this in
41+
# order to adhere to the Django convention of using the empty
42+
# string instead of null, but only if the field accepts the
43+
# empty string.
44+
if value is None and isinstance(field, Field) and field.empty_strings_allowed:
45+
value = u''
46+
# Convert 1 or 0 to True or False
47+
elif value in (1, 0) and isinstance(field, (BooleanField, NullBooleanField)):
48+
value = bool(value)
49+
# Convert floats to decimals
50+
elif value is not None and isinstance(field, DecimalField):
51+
value = util.typecast_decimal(field.format_number(value))
52+
# cx_Oracle always returns datetime.datetime objects for
53+
# DATE and TIMESTAMP columns, but Django wants to see a
54+
# python datetime.date, .time, or .datetime. We use the type
55+
# of the Field to determine which to cast to, but it's not
56+
# always available.
57+
# As a workaround, we cast to date if all the time-related
58+
# values are 0, or to time if the date is 1/1/1900.
59+
# This could be cleaned a bit by adding a method to the Field
60+
# classes to normalize values from the database (the to_python
61+
# method is used for validation and isn't what we want here).
62+
elif isinstance(value, Database.Timestamp):
63+
# In Python 2.3, the cx_Oracle driver returns its own
64+
# Timestamp object that we must convert to a datetime class.
65+
if not isinstance(value, datetime.datetime):
66+
value = datetime.datetime(value.year, value.month,
67+
value.day, value.hour, value.minute, value.second,
68+
value.fsecond)
69+
if isinstance(field, DateTimeField):
70+
# DateTimeField subclasses DateField so must be checked
71+
# first.
72+
pass
73+
elif isinstance(field, DateField):
74+
value = value.date()
75+
elif isinstance(field, TimeField) or (value.year == 1900 and value.month == value.day == 1):
76+
value = value.time()
77+
elif value.hour == value.minute == value.second == value.microsecond == 0:
78+
value = value.date()
79+
return value
80+
7581
def as_sql(self, with_limits=True, with_col_aliases=False):
7682
"""
7783
Creates the SQL for this query. Returns the SQL string and list

0 commit comments

Comments
 (0)