Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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
@jbronn jbronn authored
Showing with 34 additions and 11 deletions.
  1. +34 −11 django/db/backends/oracle/base.py
View
45 django/db/backends/oracle/base.py
@@ -244,6 +244,26 @@ def _cursor(self, settings):
cursor.arraysize = 100
return cursor
+class OracleParam(object):
+ """
+ Wrapper object for formatting parameters for Oracle. If the string
+ representation of the value is large enough (greater than 4000 characters)
+ the input size needs to be set as NCLOB. Alternatively, if the parameter has
+ an `input_size` attribute, then the value of the `input_size` attribute will
+ be used instead. Otherwise, no input size will be set for the parameter when
+ executing the query.
+ """
+ def __init__(self, param, charset, strings_only=False):
+ self.smart_str = smart_str(param, charset, strings_only)
+ if hasattr(param, 'input_size'):
+ # If parameter has `input_size` attribute, use that.
+ self.input_size = param.input_size
+ elif isinstance(param, basestring) and len(param) > 4000:
+ # Mark any string parameter greater than 4000 characters as an NCLOB.
+ self.input_size = Database.NCLOB
+ else:
+ self.input_size = None
+
class FormatStylePlaceholderCursor(Database.Cursor):
"""
Django uses "format" (e.g. '%s') style placeholders, but Oracle uses ":var"
@@ -258,15 +278,13 @@ class FormatStylePlaceholderCursor(Database.Cursor):
def _format_params(self, params):
if isinstance(params, dict):
result = {}
- charset = self.charset
for key, value in params.items():
- result[smart_str(key, charset)] = smart_str(value, charset)
+ result[smart_str(key, self.charset)] = OracleParam(param, self.charset)
return result
else:
- return tuple([smart_str(p, self.charset, True) for p in params])
-
+ return tuple([OracleParam(p, self.charset, True) for p in params])
+
def _guess_input_sizes(self, params_list):
- # Mark any string parameter greater than 4000 characters as an NCLOB.
if isinstance(params_list[0], dict):
sizes = {}
iterators = [params.iteritems() for params in params_list]
@@ -275,13 +293,18 @@ def _guess_input_sizes(self, params_list):
iterators = [enumerate(params) for params in params_list]
for iterator in iterators:
for key, value in iterator:
- if isinstance(value, basestring) and len(value) > 4000:
- sizes[key] = Database.NCLOB
+ if value.input_size: sizes[key] = value.input_size
if isinstance(sizes, dict):
self.setinputsizes(**sizes)
else:
self.setinputsizes(*sizes)
+ def _param_generator(self, params):
+ if isinstance(params, dict):
+ return dict([(k, p.smart_str) for k, p in params.iteritems()])
+ else:
+ return [p.smart_str for p in params]
+
def execute(self, query, params=None):
if params is None:
params = []
@@ -296,7 +319,7 @@ def execute(self, query, params=None):
query = query[:-1]
query = smart_str(query, self.charset) % tuple(args)
self._guess_input_sizes([params])
- return Database.Cursor.execute(self, query, params)
+ return Database.Cursor.execute(self, query, self._param_generator(params))
def executemany(self, query, params=None):
try:
@@ -311,9 +334,9 @@ def executemany(self, query, params=None):
if query.endswith(';') or query.endswith('/'):
query = query[:-1]
query = smart_str(query, self.charset) % tuple(args)
- new_param_list = [self._format_params(i) for i in params]
- self._guess_input_sizes(new_param_list)
- return Database.Cursor.executemany(self, query, new_param_list)
+ formatted = [self._format_params(i) for i in params]
+ self._guess_input_sizes(formatted)
+ return Database.Cursor.executemany(self, query, [self._param_generator(p) for p in formatted])
def fetchone(self):
row = Database.Cursor.fetchone(self)
Please sign in to comment.
Something went wrong with that request. Please try again.