Author: ikelly
Date: 2009-01-15 14:40:40 -0600 (Thu, 15 Jan 2009)
New Revision: 9751

Modified:
   django/branches/releases/1.0.X/
   django/branches/releases/1.0.X/django/contrib/gis/measure.py
   django/branches/releases/1.0.X/django/db/backends/oracle/base.py
Log:
[1.0.X] Fixed #6767: changed the way the Oracle backend fetches numbers to 
prevent decimals being returned as floats. Backport of [9750] from trunk.


Property changes on: django/branches/releases/1.0.X
___________________________________________________________________
Name: svnmerge-integrated
   - 
/django/trunk:1-9097,9099-9102,9104-9109,9111,9113-9144,9146-9151,9153-9156,9158-9159,9161-9187,9189-9247,9249-9262,9264-9277,9279-9298,9301-9302,9305-9331,9333-9343,9345,9347,9350-9352,9355-9396,9399-9462,9466-9469,9471-9488,9491-9526,9529,9533-9536,9539-9550,9556-9557,9559-9560,9562-9568,9570-9591,9595-9619,9621-9624,9626-9636,9638-9642,9644-9645,9647-9689,9691,9693-9699,9703-9706,9709-9713,9716-9723,9725-9726,9730-9733
   + 
/django/trunk:1-9097,9099-9102,9104-9109,9111,9113-9144,9146-9151,9153-9156,9158-9159,9161-9187,9189-9247,9249-9262,9264-9277,9279-9298,9301-9302,9305-9331,9333-9343,9345,9347,9350-9352,9355-9396,9399-9462,9466-9469,9471-9488,9491-9526,9529,9533-9536,9539-9550,9556-9557,9559-9560,9562-9568,9570-9591,9595-9619,9621-9624,9626-9636,9638-9642,9644-9645,9647-9689,9691,9693-9699,9703-9706,9709-9713,9716-9723,9725-9726,9730-9733,9750

Modified: django/branches/releases/1.0.X/django/contrib/gis/measure.py
===================================================================
--- django/branches/releases/1.0.X/django/contrib/gis/measure.py        
2009-01-15 20:39:09 UTC (rev 9750)
+++ django/branches/releases/1.0.X/django/contrib/gis/measure.py        
2009-01-15 20:40:40 UTC (rev 9751)
@@ -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/branches/releases/1.0.X/django/db/backends/oracle/base.py
===================================================================
--- django/branches/releases/1.0.X/django/db/backends/oracle/base.py    
2009-01-15 20:39:09 UTC (rev 9750)
+++ django/branches/releases/1.0.X/django/db/backends/oracle/base.py    
2009-01-15 20:40:40 UTC (rev 9751)
@@ -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
-~----------~----~----~----~------~----~------~--~---

Reply via email to