Django

Code

Changeset 7470

Show
Ignore:
Timestamp:
04/26/08 06:21:02 (2 months ago)
Author:
mtredinnick
Message:

queryset-refactor: Pass any extra(select=...) columns through the value
conversion function in the Oracle backend after reading the row from the
database.

Refs #7087 (see comment 7 on that ticket).

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/queryset-refactor/django/db/backends/oracle/query.py

    r7457 r7470  
    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 
     36 
     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 
    7480 
    7581        def as_sql(self, with_limits=True, with_col_aliases=False):