Fixed #9307 -- Added the ability to pickle the Query class used by the Oracle
backend. This allows Querysets to be cached for Oracle and should provide a model for adding pickling support to other (external) database backends that need a custom Query class. Thanks to Justin Bronn for some assistance with this patch. git-svn-id: http://code.djangoproject.com/svn/django/trunk@9272 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
03fcf19fd2
commit
3dfbaae32b
|
@ -25,6 +25,18 @@ def query_class(QueryClass, Database):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class OracleQuery(QueryClass):
|
class OracleQuery(QueryClass):
|
||||||
|
def __reduce__(self):
|
||||||
|
"""
|
||||||
|
Enable pickling for this class (normal pickling handling doesn't
|
||||||
|
work as Python can only pickle module-level classes by default).
|
||||||
|
"""
|
||||||
|
if hasattr(QueryClass, '__getstate__'):
|
||||||
|
assert hasattr(QueryClass, '__setstate__')
|
||||||
|
data = self.__getstate__()
|
||||||
|
else:
|
||||||
|
data = self.__dict__
|
||||||
|
return (unpickle_query_class, (QueryClass,), data)
|
||||||
|
|
||||||
def resolve_columns(self, row, fields=()):
|
def resolve_columns(self, row, fields=()):
|
||||||
# If this query has limit/offset information, then we expect the
|
# If this query has limit/offset information, then we expect the
|
||||||
# first column to be an extra "_RN" column that we need to throw
|
# first column to be an extra "_RN" column that we need to throw
|
||||||
|
@ -120,3 +132,17 @@ def query_class(QueryClass, Database):
|
||||||
|
|
||||||
_classes[QueryClass] = OracleQuery
|
_classes[QueryClass] = OracleQuery
|
||||||
return OracleQuery
|
return OracleQuery
|
||||||
|
|
||||||
|
def unpickle_query_class(QueryClass):
|
||||||
|
"""
|
||||||
|
Utility function, called by Python's unpickling machinery, that handles
|
||||||
|
unpickling of Oracle Query subclasses.
|
||||||
|
"""
|
||||||
|
# XXX: Would be nice to not have any dependency on cx_Oracle here. Since
|
||||||
|
# modules can't be pickled, we need a way to know to load the right module.
|
||||||
|
import cx_Oracle
|
||||||
|
|
||||||
|
klass = query_class(QueryClass, cx_Oracle)
|
||||||
|
return klass.__new__(klass)
|
||||||
|
unpickle_query_class.__safe_for_unpickling__ = True
|
||||||
|
|
||||||
|
|
|
@ -27,9 +27,9 @@ try:
|
||||||
except NameError:
|
except NameError:
|
||||||
from sets import Set as set # Python 2.3 fallback
|
from sets import Set as set # Python 2.3 fallback
|
||||||
|
|
||||||
__all__ = ['Query']
|
__all__ = ['Query', 'BaseQuery']
|
||||||
|
|
||||||
class Query(object):
|
class BaseQuery(object):
|
||||||
"""
|
"""
|
||||||
A single SQL query.
|
A single SQL query.
|
||||||
"""
|
"""
|
||||||
|
@ -1757,7 +1757,9 @@ class Query(object):
|
||||||
# Use the backend's custom Query class if it defines one. Otherwise, use the
|
# Use the backend's custom Query class if it defines one. Otherwise, use the
|
||||||
# default.
|
# default.
|
||||||
if connection.features.uses_custom_query_class:
|
if connection.features.uses_custom_query_class:
|
||||||
Query = connection.ops.query_class(Query)
|
Query = connection.ops.query_class(BaseQuery)
|
||||||
|
else:
|
||||||
|
Query = BaseQuery
|
||||||
|
|
||||||
def get_order_dir(field, default='ASC'):
|
def get_order_dir(field, default='ASC'):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue