Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #7637 -- Added an extra parameterisation hook to the Oracle bac…

…kend.

Required for some extension modules (in particular, geo-django). Patch from
Justin Bronn.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@8145 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 464a9c8ca482f4a96c9da66e791bd3fb646ffbd2 1 parent 726a24c
Malcolm Tredinnick authored July 30, 2008

Showing 1 changed file with 33 additions and 10 deletions. Show diff stats Hide diff stats

  1. 43  django/db/backends/oracle/base.py
43  django/db/backends/oracle/base.py
@@ -257,6 +257,26 @@ def _cursor(self, settings):
257 257
         cursor.arraysize = 100
258 258
         return cursor
259 259
 
  260
+class OracleParam(object):
  261
+    """
  262
+    Wrapper object for formatting parameters for Oracle. If the string
  263
+    representation of the value is large enough (greater than 4000 characters)
  264
+    the input size needs to be set as NCLOB. Alternatively, if the parameter has
  265
+    an `input_size` attribute, then the value of the `input_size` attribute will
  266
+    be used instead. Otherwise, no input size will be set for the parameter when
  267
+    executing the query.
  268
+    """
  269
+    def __init__(self, param, charset, strings_only=False):
  270
+        self.smart_str = smart_str(param, charset, strings_only)
  271
+        if hasattr(param, 'input_size'):
  272
+            # If parameter has `input_size` attribute, use that.
  273
+            self.input_size = param.input_size
  274
+        elif isinstance(param, basestring) and len(param) > 4000:
  275
+            # Mark any string parameter greater than 4000 characters as an NCLOB.
  276
+            self.input_size = Database.NCLOB
  277
+        else:
  278
+            self.input_size = None
  279
+
260 280
 class FormatStylePlaceholderCursor(Database.Cursor):
261 281
     """
262 282
     Django uses "format" (e.g. '%s') style placeholders, but Oracle uses ":var"
@@ -271,15 +291,13 @@ class FormatStylePlaceholderCursor(Database.Cursor):
271 291
     def _format_params(self, params):
272 292
         if isinstance(params, dict):
273 293
             result = {}
274  
-            charset = self.charset
275 294
             for key, value in params.items():
276  
-                result[smart_str(key, charset)] = smart_str(value, charset)
  295
+                result[smart_str(key, self.charset)] = OracleParam(param, self.charset)
277 296
             return result
278 297
         else:
279  
-            return tuple([smart_str(p, self.charset, True) for p in params])
  298
+            return tuple([OracleParam(p, self.charset, True) for p in params])
280 299
 
281 300
     def _guess_input_sizes(self, params_list):
282  
-        # Mark any string parameter greater than 4000 characters as an NCLOB.
283 301
         if isinstance(params_list[0], dict):
284 302
             sizes = {}
285 303
             iterators = [params.iteritems() for params in params_list]
@@ -288,13 +306,18 @@ def _guess_input_sizes(self, params_list):
288 306
             iterators = [enumerate(params) for params in params_list]
289 307
         for iterator in iterators:
290 308
             for key, value in iterator:
291  
-                if isinstance(value, basestring) and len(value) > 4000:
292  
-                    sizes[key] = Database.NCLOB
  309
+                if value.input_size: sizes[key] = value.input_size
293 310
         if isinstance(sizes, dict):
294 311
             self.setinputsizes(**sizes)
295 312
         else:
296 313
             self.setinputsizes(*sizes)
297 314
 
  315
+    def _param_generator(self, params):
  316
+        if isinstance(params, dict):
  317
+            return dict([(k, p.smart_str) for k, p in params.iteritems()])
  318
+        else:
  319
+            return [p.smart_str for p in params]
  320
+
298 321
     def execute(self, query, params=None):
299 322
         if params is None:
300 323
             params = []
@@ -309,7 +332,7 @@ def execute(self, query, params=None):
309 332
             query = query[:-1]
310 333
         query = smart_str(query, self.charset) % tuple(args)
311 334
         self._guess_input_sizes([params])
312  
-        return Database.Cursor.execute(self, query, params)
  335
+        return Database.Cursor.execute(self, query, self._param_generator(params))
313 336
 
314 337
     def executemany(self, query, params=None):
315 338
         try:
@@ -324,9 +347,9 @@ def executemany(self, query, params=None):
324 347
         if query.endswith(';') or query.endswith('/'):
325 348
             query = query[:-1]
326 349
         query = smart_str(query, self.charset) % tuple(args)
327  
-        new_param_list = [self._format_params(i) for i in params]
328  
-        self._guess_input_sizes(new_param_list)
329  
-        return Database.Cursor.executemany(self, query, new_param_list)
  350
+        formatted = [self._format_params(i) for i in params]
  351
+        self._guess_input_sizes(formatted)
  352
+        return Database.Cursor.executemany(self, query, [self._param_generator(p) for p in formatted])
330 353
 
331 354
     def fetchone(self):
332 355
         row = Database.Cursor.fetchone(self)

0 notes on commit 464a9c8

Please sign in to comment.
Something went wrong with that request. Please try again.