Author: ikelly
Date: 2010-04-28 12:08:06 -0500 (Wed, 28 Apr 2010)
New Revision: 13042

Modified:
   django/trunk/django/db/backends/oracle/base.py
   django/trunk/tests/regressiontests/backends/tests.py
Log:
Fixed a bug preventing cursor variables from being passed as bind parameters in 
the oracle backend.

Modified: django/trunk/django/db/backends/oracle/base.py
===================================================================
--- django/trunk/django/db/backends/oracle/base.py      2010-04-28 15:39:26 UTC 
(rev 13041)
+++ django/trunk/django/db/backends/oracle/base.py      2010-04-28 17:08:06 UTC 
(rev 13042)
@@ -423,6 +423,30 @@
             self.input_size = None
 
 
+class VariableWrapper(object):
+    """
+    An adapter class for cursor variables that prevents the wrapped object
+    from being converted into a string when used to instanciate an OracleParam.
+    This can be used generally for any other object that should be passed into
+    Cursor.execute as-is.
+    """
+
+    def __init__(self, var):
+        self.var = var
+
+    def bind_parameter(self, cursor):
+        return self.var
+
+    def __getattr__(self, key):
+        return getattr(self.var, key)
+
+    def __setattr__(self, key, value):
+        if key == 'var':
+            self.__dict__[key] = value
+        else:
+            setattr(self.var, key, value)
+
+
 class InsertIdVar(object):
     """
     A late-binding cursor variable that can be passed to Cursor.execute
@@ -431,7 +455,7 @@
     """
 
     def bind_parameter(self, cursor):
-        param = cursor.var(Database.NUMBER)
+        param = cursor.cursor.var(Database.NUMBER)
         cursor._insert_id_var = param
         return param
 
@@ -488,7 +512,7 @@
             raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), 
sys.exc_info()[2]
         except Database.DatabaseError, e:
             # cx_Oracle <= 4.4.0 wrongly raises a DatabaseError for ORA-01400.
-            if e.args[0].code == 1400 and not isinstance(e, IntegrityError):
+            if hasattr(e.args[0], 'code') and e.args[0].code == 1400 and not 
isinstance(e, IntegrityError):
                 raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), 
sys.exc_info()[2]
             raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), 
sys.exc_info()[2]
 
@@ -514,7 +538,7 @@
             raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), 
sys.exc_info()[2]
         except Database.DatabaseError, e:
             # cx_Oracle <= 4.4.0 wrongly raises a DatabaseError for ORA-01400.
-            if e.args[0].code == 1400 and not isinstance(e, IntegrityError):
+            if hasattr(e.args[0], 'code') and e.args[0].code == 1400 and not 
isinstance(e, IntegrityError):
                 raise utils.IntegrityError, utils.IntegrityError(*tuple(e)), 
sys.exc_info()[2]
             raise utils.DatabaseError, utils.DatabaseError(*tuple(e)), 
sys.exc_info()[2]
 
@@ -534,6 +558,12 @@
         return tuple([_rowfactory(r, self.cursor)
                       for r in self.cursor.fetchall()])
 
+    def var(self, *args):
+        return VariableWrapper(self.cursor.var(*args))
+
+    def arrayvar(self, *args):
+        return VariableWrapper(self.cursor.arrayvar(*args))
+
     def __getattr__(self, attr):
         if attr in self.__dict__:
             return self.__dict__[attr]

Modified: django/trunk/tests/regressiontests/backends/tests.py
===================================================================
--- django/trunk/tests/regressiontests/backends/tests.py        2010-04-28 
15:39:26 UTC (rev 13041)
+++ django/trunk/tests/regressiontests/backends/tests.py        2010-04-28 
17:08:06 UTC (rev 13042)
@@ -22,6 +22,16 @@
         else:
             return True
 
+    def test_cursor_var(self):
+        # If the backend is Oracle, test that we can pass cursor variables
+        # as query parameters.
+        if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] == 
'django.db.backends.oracle':
+            cursor = connection.cursor()
+            var = cursor.var(backend.Database.STRING)
+            cursor.execute("BEGIN %s := 'X'; END; ", [var])
+            self.assertEqual(var.getvalue(), 'X')
+
+
 class LongString(unittest.TestCase):
 
     def test_long_string(self):

-- 
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