Ticket #6767: 6767.diff

File 6767.diff, 4.1 KB (added by Erin Kelly, 16 years ago)

Prevents float conversions by pulling in numeric data as strings and casting them by hand. Testing is covered by the regression test for #5079.

  • django/db/backends/oracle/base.py

     
    77import os
    88import datetime
    99import time
     10from decimal import Decimal
    1011
    1112# Oracle takes client-side character set encoding from the environment.
    1213os.environ['NLS_LANG'] = '.UTF8'
     
    287288                pass
    288289        if not cursor:
    289290            cursor = FormatStylePlaceholderCursor(self.connection)
     291        # Necessary to retrieve decimal values without rounding error.
     292        cursor.numbersAsStrings = True
    290293        # Default arraysize of 1 is highly sub-optimal.
    291294        cursor.arraysize = 100
    292295        return cursor
     
    390393        row = Database.Cursor.fetchone(self)
    391394        if row is None:
    392395            return row
    393         return tuple([to_unicode(e) for e in row])
     396        return self._rowfactory(row)
    394397
    395398    def fetchmany(self, size=None):
    396399        if size is None:
    397400            size = self.arraysize
    398         return tuple([tuple([to_unicode(e) for e in r])
     401        return tuple([self._rowfactory(r)
    399402                      for r in Database.Cursor.fetchmany(self, size)])
    400403
    401404    def fetchall(self):
    402         return tuple([tuple([to_unicode(e) for e in r])
     405        return tuple([self._rowfactory(r)
    403406                      for r in Database.Cursor.fetchall(self)])
    404407
     408    def _rowfactory(self, row):
     409        # Cast numeric values as the appropriate Python type based upon the
     410        # cursor description, and convert strings to unicode.
     411        casted = []
     412        for value, desc in zip(row, self.description):
     413            if value is not None and desc[1] is Database.NUMBER:
     414                precision, scale = desc[4:6]
     415                if scale == -127:
     416                    if precision == 0:
     417                        # NUMBER column: decimal-precision floating point
     418                        # This will normally be an integer from a sequence,
     419                        # but it could be a decimal value.
     420                        if '.' in value:
     421                            value = Decimal(value)
     422                        else:
     423                            value = int(value)
     424                    else:
     425                        # FLOAT column: binary-precision floating point.
     426                        # This comes from FloatField columns.
     427                        value = float(value)
     428                elif precision > 0:
     429                    # NUMBER(p,s) column: decimal-precision fixed point.
     430                    # This comes from IntField and DecimalField columns.
     431                    if scale == 0:
     432                        value = int(value)
     433                    else:
     434                        value = Decimal(value)
     435                elif '.' in value:
     436                    # No type information. This normally comes from a
     437                    # mathematical expression in the SELECT list. Guess int
     438                    # or Decimal based on whether it has a decimal point.
     439                    value = Decimal(value)
     440                else:
     441                    value = int(value)
     442            else:
     443                value = to_unicode(value)
     444            casted.append(value)
     445        return tuple(casted)
    405446
     447
    406448def to_unicode(s):
    407449    """
    408450    Convert strings to Unicode objects (and return all other data types
  • django/db/backends/oracle/query.py

     
    6666            # Convert 1 or 0 to True or False
    6767            elif value in (1, 0) and isinstance(field, (BooleanField, NullBooleanField)):
    6868                value = bool(value)
    69             # Convert floats to decimals
    70             elif value is not None and isinstance(field, DecimalField):
    71                 value = util.typecast_decimal(field.format_number(value))
    7269            # cx_Oracle always returns datetime.datetime objects for
    7370            # DATE and TIMESTAMP columns, but Django wants to see a
    7471            # python datetime.date, .time, or .datetime.  We use the type
Back to Top