Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

gis: Modified the Oracle database backend so that the input size of p…

…arameters may be customized (this was preventing the `gis` branch from working because Oracle's WKT stored procedures require CLOB rather than NCLOB as input). Ian Kelly has approved this patch; notwithstanding any further concerns, its functionality should appear in trunk sometime in the future.

git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@7637 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit eb30cad66ab1d5ff6a56425ecdf7efd0ade6d750 1 parent a245b72
Justin Bronn authored June 15, 2008

Showing 1 changed file with 34 additions and 11 deletions. Show diff stats Hide diff stats

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

0 notes on commit eb30cad

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