Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[1.0.X] Fixed #6767: changed the way the Oracle backend fetches numbe…
…rs to prevent decimals being returned as floats. Backport of [9750] from trunk.

git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.0.X@9751 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
nightflyerkilo committed Jan 15, 2009
1 parent 43c1a87 commit ad93542
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 3 deletions.
1 change: 1 addition & 0 deletions django/contrib/gis/measure.py
Expand Up @@ -46,6 +46,7 @@ def default_units(self, kwargs):
"""
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
Expand Down
48 changes: 45 additions & 3 deletions django/db/backends/oracle/base.py
Expand Up @@ -7,6 +7,7 @@
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'
Expand Down Expand Up @@ -287,6 +288,8 @@ def _cursor(self, settings):
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
Expand Down Expand Up @@ -390,18 +393,57 @@ def fetchone(self):
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):
"""
Expand Down

0 comments on commit ad93542

Please sign in to comment.