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 sqlalchemy@googlegroups.com
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to