Fixed #6767: changed the way the Oracle backend fetches numbers to prevent decimals being returned as floats.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@9750 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
f60d0f597a
commit
acfe5cc880
|
@ -46,6 +46,7 @@ class MeasureBase(object):
|
|||
"""
|
||||
val = 0.0
|
||||
for unit, value in kwargs.iteritems():
|
||||
if not isinstance(value, float): value = float(value)
|
||||
if unit in self.UNITS:
|
||||
val += self.UNITS[unit] * value
|
||||
default_unit = unit
|
||||
|
|
|
@ -7,6 +7,7 @@ Requires cx_Oracle: http://cx-oracle.sourceforge.net/
|
|||
import os
|
||||
import datetime
|
||||
import time
|
||||
from decimal import Decimal
|
||||
|
||||
# Oracle takes client-side character set encoding from the environment.
|
||||
os.environ['NLS_LANG'] = '.UTF8'
|
||||
|
@ -287,6 +288,8 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
|||
pass
|
||||
if not cursor:
|
||||
cursor = FormatStylePlaceholderCursor(self.connection)
|
||||
# Necessary to retrieve decimal values without rounding error.
|
||||
cursor.numbersAsStrings = True
|
||||
# Default arraysize of 1 is highly sub-optimal.
|
||||
cursor.arraysize = 100
|
||||
return cursor
|
||||
|
@ -390,18 +393,57 @@ class FormatStylePlaceholderCursor(Database.Cursor):
|
|||
row = Database.Cursor.fetchone(self)
|
||||
if row is None:
|
||||
return row
|
||||
return tuple([to_unicode(e) for e in row])
|
||||
return self._rowfactory(row)
|
||||
|
||||
def fetchmany(self, size=None):
|
||||
if size is None:
|
||||
size = self.arraysize
|
||||
return tuple([tuple([to_unicode(e) for e in r])
|
||||
return tuple([self._rowfactory(r)
|
||||
for r in Database.Cursor.fetchmany(self, size)])
|
||||
|
||||
def fetchall(self):
|
||||
return tuple([tuple([to_unicode(e) for e in r])
|
||||
return tuple([self._rowfactory(r)
|
||||
for r in Database.Cursor.fetchall(self)])
|
||||
|
||||
def _rowfactory(self, row):
|
||||
# Cast numeric values as the appropriate Python type based upon the
|
||||
# cursor description, and convert strings to unicode.
|
||||
casted = []
|
||||
for value, desc in zip(row, self.description):
|
||||
if value is not None and desc[1] is Database.NUMBER:
|
||||
precision, scale = desc[4:6]
|
||||
if scale == -127:
|
||||
if precision == 0:
|
||||
# NUMBER column: decimal-precision floating point
|
||||
# This will normally be an integer from a sequence,
|
||||
# but it could be a decimal value.
|
||||
if '.' in value:
|
||||
value = Decimal(value)
|
||||
else:
|
||||
value = int(value)
|
||||
else:
|
||||
# FLOAT column: binary-precision floating point.
|
||||
# This comes from FloatField columns.
|
||||
value = float(value)
|
||||
elif precision > 0:
|
||||
# NUMBER(p,s) column: decimal-precision fixed point.
|
||||
# This comes from IntField and DecimalField columns.
|
||||
if scale == 0:
|
||||
value = int(value)
|
||||
else:
|
||||
value = Decimal(value)
|
||||
elif '.' in value:
|
||||
# No type information. This normally comes from a
|
||||
# mathematical expression in the SELECT list. Guess int
|
||||
# or Decimal based on whether it has a decimal point.
|
||||
value = Decimal(value)
|
||||
else:
|
||||
value = int(value)
|
||||
else:
|
||||
value = to_unicode(value)
|
||||
casted.append(value)
|
||||
return tuple(casted)
|
||||
|
||||
|
||||
def to_unicode(s):
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue