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
|
val = 0.0
|
||||||
for unit, value in kwargs.iteritems():
|
for unit, value in kwargs.iteritems():
|
||||||
|
if not isinstance(value, float): value = float(value)
|
||||||
if unit in self.UNITS:
|
if unit in self.UNITS:
|
||||||
val += self.UNITS[unit] * value
|
val += self.UNITS[unit] * value
|
||||||
default_unit = unit
|
default_unit = unit
|
||||||
|
|
|
@ -7,6 +7,7 @@ Requires cx_Oracle: http://cx-oracle.sourceforge.net/
|
||||||
import os
|
import os
|
||||||
import datetime
|
import datetime
|
||||||
import time
|
import time
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
# Oracle takes client-side character set encoding from the environment.
|
# Oracle takes client-side character set encoding from the environment.
|
||||||
os.environ['NLS_LANG'] = '.UTF8'
|
os.environ['NLS_LANG'] = '.UTF8'
|
||||||
|
@ -287,6 +288,8 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
||||||
pass
|
pass
|
||||||
if not cursor:
|
if not cursor:
|
||||||
cursor = FormatStylePlaceholderCursor(self.connection)
|
cursor = FormatStylePlaceholderCursor(self.connection)
|
||||||
|
# Necessary to retrieve decimal values without rounding error.
|
||||||
|
cursor.numbersAsStrings = True
|
||||||
# Default arraysize of 1 is highly sub-optimal.
|
# Default arraysize of 1 is highly sub-optimal.
|
||||||
cursor.arraysize = 100
|
cursor.arraysize = 100
|
||||||
return cursor
|
return cursor
|
||||||
|
@ -390,18 +393,57 @@ class FormatStylePlaceholderCursor(Database.Cursor):
|
||||||
row = Database.Cursor.fetchone(self)
|
row = Database.Cursor.fetchone(self)
|
||||||
if row is None:
|
if row is None:
|
||||||
return row
|
return row
|
||||||
return tuple([to_unicode(e) for e in row])
|
return self._rowfactory(row)
|
||||||
|
|
||||||
def fetchmany(self, size=None):
|
def fetchmany(self, size=None):
|
||||||
if size is None:
|
if size is None:
|
||||||
size = self.arraysize
|
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)])
|
for r in Database.Cursor.fetchmany(self, size)])
|
||||||
|
|
||||||
def fetchall(self):
|
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)])
|
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):
|
def to_unicode(s):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue