Fixed #7637 -- Added an extra parameterisation hook to the Oracle backend.

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
This commit is contained in:
Malcolm Tredinnick 2008-07-30 01:29:31 +00:00
parent 726a24c609
commit 464a9c8ca4
1 changed files with 33 additions and 10 deletions

View File

@ -257,6 +257,26 @@ class DatabaseWrapper(BaseDatabaseWrapper):
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"
@ -271,15 +291,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]
@ -288,13 +306,18 @@ class FormatStylePlaceholderCursor(Database.Cursor):
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 = []
@ -309,7 +332,7 @@ class FormatStylePlaceholderCursor(Database.Cursor):
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:
@ -324,9 +347,9 @@ class FormatStylePlaceholderCursor(Database.Cursor):
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)