Re: persistence and __setstate__

[email protected] (Jeremy Hylton) Wed, 31 Jul 2002 11:19:48 -0400
Newsgroups gmane.comp.python.zope.zodb4
Message-ID <[email protected]>
>>>>> "BAW" == Barry A Warsaw <[email protected]> writes:
>>>>> "JH" == Jeremy Hylton <[email protected]> writes:
>>>>> "FG" == Florent Guillaume <[email protected]> writes:

  JH> An object is always changed when its __setstate__() method is
  JH> invoked, except perhaps for some degenerate cases.  It would be
  JH> unacceptable to mark an object as changed every time it is
  JH> loaded.

  FG> So won't all objects that upgrade themselves in __setstate__
  FG> keep being upgraded whenever they are reloaded, until they are
  FG> modified from outside __setstate__ ?

  JH> Yes.

  BAW> So that means that "schema" updates have to happen external to
  BAW> the object, because you can't update in __setstate__ and have
  BAW> that update persist?  Which means if you say, added an
  BAW> attribute to Foo objects in your database, you'll need a script
  BAW> to troll through the database, looking for instances of Foo,
  BAW> make the change, commit them and move on.  That could be more
  BAW> expensive than an on-demand update.

If you put code in the __setstate__ to handle object evolution, that
code will be executed every time the object is loaded until there is a
transaction that also modifies the object.  Doesn't sound too
pleasant, but also sounds unavoidable.

Here are some sketches of other approaches:

- The database could provide a mechanism to register an object
  transform function that is executed when an out-of-date object is
  loaded.  The transform could execute in a separate transaction.  The
  hardest part is probably providing a means to identify which objects
  are out-of-date, presumably some kind of class revision id.

- It should be possible to provide some workaround to register an
  object as modified within its __setstate__().  It's certainly
  possible to explicitly register the object with the Connection,
  although that doesn't mark it as changed.  But we could add some
  hacks.

A potential concern for any solution: If the object is updated on
demand, it is probably important to execute the change as a separate
transaction.  If you don't, then the object update gets mixed in with
arbitrary updates to other objects, which unnecessarily complicates
undo.

Jeremy