Author: ikelly
Date: 2009-01-15 14:39:09 -0600 (Thu, 15 Jan 2009)
New Revision: 9750
Modified:
django/trunk/django/contrib/gis/measure.py
django/trunk/django/db/backends/oracle/base.py
Log:
Fixed #6767: changed the way the Oracle backend fetches numbers to prevent
decimals being returned as floats.
Modified: django/trunk/django/contrib/gis/measure.py
===================================================================
--- django/trunk/django/contrib/gis/measure.py 2009-01-15 19:50:29 UTC (rev
9749)
+++ django/trunk/django/contrib/gis/measure.py 2009-01-15 20:39:09 UTC (rev
9750)
@@ -46,6 +46,7 @@
"""
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
Modified: django/trunk/django/db/backends/oracle/base.py
===================================================================
--- django/trunk/django/db/backends/oracle/base.py 2009-01-15 19:50:29 UTC
(rev 9749)
+++ django/trunk/django/db/backends/oracle/base.py 2009-01-15 20:39:09 UTC
(rev 9750)
@@ -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'
@@ -287,6 +288,8 @@
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,19 +393,58 @@
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):
"""
Convert strings to Unicode objects (and return all other data types
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---