Changes to get raw queries working on the oracle backend.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@11968 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
cec64b96b0
commit
cdf5ad4217
|
@ -514,58 +514,18 @@ class FormatStylePlaceholderCursor(object):
|
||||||
row = self.cursor.fetchone()
|
row = self.cursor.fetchone()
|
||||||
if row is None:
|
if row is None:
|
||||||
return row
|
return row
|
||||||
return self._rowfactory(row)
|
return _rowfactory(row, self.cursor)
|
||||||
|
|
||||||
def fetchmany(self, size=None):
|
def fetchmany(self, size=None):
|
||||||
if size is None:
|
if size is None:
|
||||||
size = self.arraysize
|
size = self.arraysize
|
||||||
return tuple([self._rowfactory(r)
|
return tuple([_rowfactory(r, self.cursor)
|
||||||
for r in self.cursor.fetchmany(size)])
|
for r in self.cursor.fetchmany(size)])
|
||||||
|
|
||||||
def fetchall(self):
|
def fetchall(self):
|
||||||
return tuple([self._rowfactory(r)
|
return tuple([_rowfactory(r, self.cursor)
|
||||||
for r in self.cursor.fetchall()])
|
for r in self.cursor.fetchall()])
|
||||||
|
|
||||||
def _rowfactory(self, row):
|
|
||||||
# Cast numeric values as the appropriate Python type based upon the
|
|
||||||
# cursor description, and convert strings to unicode.
|
|
||||||
casted = []
|
|
||||||
for value, desc in zip(row, self.cursor.description):
|
|
||||||
if value is not None and desc[1] is Database.NUMBER:
|
|
||||||
precision, scale = desc[4:6]
|
|
||||||
if scale == -127:
|
|
||||||
if precision == 0:
|
|
||||||
# NUMBER column: decimal-precision floating point
|
|
||||||
# This will normally be an integer from a sequence,
|
|
||||||
# but it could be a decimal value.
|
|
||||||
if '.' in value:
|
|
||||||
value = Decimal(value)
|
|
||||||
else:
|
|
||||||
value = int(value)
|
|
||||||
else:
|
|
||||||
# FLOAT column: binary-precision floating point.
|
|
||||||
# This comes from FloatField columns.
|
|
||||||
value = float(value)
|
|
||||||
elif precision > 0:
|
|
||||||
# NUMBER(p,s) column: decimal-precision fixed point.
|
|
||||||
# This comes from IntField and DecimalField columns.
|
|
||||||
if scale == 0:
|
|
||||||
value = int(value)
|
|
||||||
else:
|
|
||||||
value = Decimal(value)
|
|
||||||
elif '.' in value:
|
|
||||||
# No type information. This normally comes from a
|
|
||||||
# mathematical expression in the SELECT list. Guess int
|
|
||||||
# or Decimal based on whether it has a decimal point.
|
|
||||||
value = Decimal(value)
|
|
||||||
else:
|
|
||||||
value = int(value)
|
|
||||||
elif desc[1] in (Database.STRING, Database.FIXED_CHAR,
|
|
||||||
Database.LONG_STRING):
|
|
||||||
value = to_unicode(value)
|
|
||||||
casted.append(value)
|
|
||||||
return tuple(casted)
|
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
def __getattr__(self, attr):
|
||||||
if attr in self.__dict__:
|
if attr in self.__dict__:
|
||||||
return self.__dict__[attr]
|
return self.__dict__[attr]
|
||||||
|
@ -573,7 +533,63 @@ class FormatStylePlaceholderCursor(object):
|
||||||
return getattr(self.cursor, attr)
|
return getattr(self.cursor, attr)
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter(self.cursor)
|
return CursorIterator(self.cursor)
|
||||||
|
|
||||||
|
|
||||||
|
class CursorIterator(object):
|
||||||
|
|
||||||
|
"""Cursor iterator wrapper that invokes our custom row factory."""
|
||||||
|
|
||||||
|
def __init__(self, cursor):
|
||||||
|
self.cursor = cursor
|
||||||
|
self.iter = iter(cursor)
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def next(self):
|
||||||
|
return _rowfactory(self.iter.next(), self.cursor)
|
||||||
|
|
||||||
|
|
||||||
|
def _rowfactory(row, cursor):
|
||||||
|
# Cast numeric values as the appropriate Python type based upon the
|
||||||
|
# cursor description, and convert strings to unicode.
|
||||||
|
casted = []
|
||||||
|
for value, desc in zip(row, cursor.description):
|
||||||
|
if value is not None and desc[1] is Database.NUMBER:
|
||||||
|
precision, scale = desc[4:6]
|
||||||
|
if scale == -127:
|
||||||
|
if precision == 0:
|
||||||
|
# NUMBER column: decimal-precision floating point
|
||||||
|
# This will normally be an integer from a sequence,
|
||||||
|
# but it could be a decimal value.
|
||||||
|
if '.' in value:
|
||||||
|
value = Decimal(value)
|
||||||
|
else:
|
||||||
|
value = int(value)
|
||||||
|
else:
|
||||||
|
# FLOAT column: binary-precision floating point.
|
||||||
|
# This comes from FloatField columns.
|
||||||
|
value = float(value)
|
||||||
|
elif precision > 0:
|
||||||
|
# NUMBER(p,s) column: decimal-precision fixed point.
|
||||||
|
# This comes from IntField and DecimalField columns.
|
||||||
|
if scale == 0:
|
||||||
|
value = int(value)
|
||||||
|
else:
|
||||||
|
value = Decimal(value)
|
||||||
|
elif '.' in value:
|
||||||
|
# No type information. This normally comes from a
|
||||||
|
# mathematical expression in the SELECT list. Guess int
|
||||||
|
# or Decimal based on whether it has a decimal point.
|
||||||
|
value = Decimal(value)
|
||||||
|
else:
|
||||||
|
value = int(value)
|
||||||
|
elif desc[1] in (Database.STRING, Database.FIXED_CHAR,
|
||||||
|
Database.LONG_STRING):
|
||||||
|
value = to_unicode(value)
|
||||||
|
casted.append(value)
|
||||||
|
return tuple(casted)
|
||||||
|
|
||||||
|
|
||||||
def to_unicode(s):
|
def to_unicode(s):
|
||||||
|
|
|
@ -1210,10 +1210,11 @@ class RawQuerySet(object):
|
||||||
A dict mapping column names to model field names.
|
A dict mapping column names to model field names.
|
||||||
"""
|
"""
|
||||||
if not hasattr(self, '_model_fields'):
|
if not hasattr(self, '_model_fields'):
|
||||||
|
converter = connections[self.db].introspection.table_name_converter
|
||||||
self._model_fields = {}
|
self._model_fields = {}
|
||||||
for field in self.model._meta.fields:
|
for field in self.model._meta.fields:
|
||||||
name, column = field.get_attname_column()
|
name, column = field.get_attname_column()
|
||||||
self._model_fields[column] = name
|
self._model_fields[converter(column)] = name
|
||||||
return self._model_fields
|
return self._model_fields
|
||||||
|
|
||||||
def transform_results(self, values):
|
def transform_results(self, values):
|
||||||
|
|
|
@ -42,7 +42,9 @@ class RawQuery(object):
|
||||||
def get_columns(self):
|
def get_columns(self):
|
||||||
if self.cursor is None:
|
if self.cursor is None:
|
||||||
self._execute_query()
|
self._execute_query()
|
||||||
return [column_meta[0] for column_meta in self.cursor.description]
|
converter = connections[self.using].introspection.table_name_converter
|
||||||
|
return [converter(column_meta[0])
|
||||||
|
for column_meta in self.cursor.description]
|
||||||
|
|
||||||
def validate_sql(self, sql):
|
def validate_sql(self, sql):
|
||||||
if not sql.lower().strip().startswith('select'):
|
if not sql.lower().strip().startswith('select'):
|
||||||
|
@ -53,7 +55,7 @@ class RawQuery(object):
|
||||||
# Always execute a new query for a new iterator.
|
# Always execute a new query for a new iterator.
|
||||||
# This could be optomized with a cache at the expense of RAM.
|
# This could be optomized with a cache at the expense of RAM.
|
||||||
self._execute_query()
|
self._execute_query()
|
||||||
return self.cursor
|
return iter(self.cursor)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<RawQuery: %r>" % (self.sql % self.params)
|
return "<RawQuery: %r>" % (self.sql % self.params)
|
||||||
|
|
Loading…
Reference in New Issue