I just looked at SA's PickleType and came up with a couple of issues.
1. dumps/loads
It looks like you can provide a custom pickler to PickleType, but the Python
Pickler class does not have dumps()/loads() methods. Those methods are only
available at the module level. This is a minor issue since it's not that hard
to implement a wrapper for pickler/unpickler that supports dumps/loads.
However, it may be a good idea to note this issue in the documentation.
2. persistent_id/persistent_load
I need to supply a custom pickler that will use persistent_id() and
persistent_load(). These pickle extensions are natural requirements in a
database environment. They allow objects that will be pickled to hold
references to persistent objects and have those links automatically preserved
across pickle/unpickle without actually pickling the persistent objects.
However, there is no easy way to use these methods with SQLAlchemy--I'm
referring specifically to the orm package here.
Here's a bit of (untested) code to illustrate:
from cStringIO import StringIO
from cPickle import Pickle, Unpickle
class MyPickler(object):
def __init__(self, session, typeMap):
self.session = session
self.typeMap = typeMap # map class names to types
def persistent_id(self, obj):
if hasattr(obj, "id"):
# only mapped objects have an "id"
return "%s:%s" % (type(obj).__name__, obj.id)
return None
def persistent_load(self, key):
name, ident = key.split(":")
class_ = self.typeMap[name]
return self.session.query(class_).get(ident)
def dumps(self, graph):
src = StringIO()
pickler = Pickler(src)
pickler.persistent_id = self.persistent_id
pickler.dump(graph)
return src.getvalue()
def loads(self, data):
dst = StringIO(data)
unpickler = Unpickler(dst)
unpickler.persistent_load = self.persistent_load
return unpickler.load()
...
t = Table(...
Column("pdata", PickleType(pickler=MyPickler(.?.)))
Now the obvious flaw here is that MyPickler needs a session at instantiation
time, and it uses the same session for every unpickle throughout the entire
application. From what I can tell PickleType has no way of getting at the
session of the current load/save taking place when the data is selected
from/written to the database. I'm not using thread-local sessions, so that
won't work, however there are multiple concurrent sessions within my
application.
My other thought was to use a mapper extension to unpickle on populate_instance
and pickle on before_insert/before_update. The session is easier to get there,
and I might have been able to hack it somehow, but I had no way to tell the
mapper to perform an update if the only thing that changed was the pickle data.
Am I missing something? Is there any way to do what I'm trying to do?
~ Daniel
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---