[ZODB-Dev] Support for graceful ZODB Class renaming
Pieter Nagel
pieter@nagel.co.za
Sat, 18 Jan 2003 16:26:16 +0200
I believe that database schema changes (whether class renamings or
instance attribute rearrangements), should be done atomically in one fell
swoop.
There I favour solution 2 (a utility that transforms fixes all instances
of the renamed classes in the database), and I dislike the lazy-renaming
approach. I dislike the alias approach (supporting old class names
indefinitely) even more.
The way I do it is basically:
class Migrator:
def __init__(self):
self.oldToNewClassMapping = {}
def renamedClass(self, oldName, newClass):
parts = oldName.split('.')
moduleName = '.'.join(parts[:-1])
className = parts[-1]
self.oldToNewClassMapping[(moduleName, className)] = newClass.__module__, newClass.__name__
def migrateAll(self, conn):
self._oldClassFactory = conn._db._classFactory
conn._db.setClassFactory(self._classFactory)
import OidSweep
for oid in OidSweep.allOids(conn):
ob = conn[oid]
ob._p_activate()
def _classFactory(self, connection, location, name, **kwargs):
location, name = self.oldToNewClassMapping.get((location, name), (location, name))
try:
return self._oldClassFactory(connection, location, name, **kwargs)
except:
print 'classFactory failed on', location, name
return PlaceHolderForDeletedClass
You instantiate a Migrator object and tell it about class renamings via
renamedClass (mine can also handle instance renamings and other ad-hoc
data transformations). You invoke migrateAll on a connection when ready.
The OidSweep.allOids functions returns all oids in the database (I
implemented it lazily in terms of a FileStorage's index, but one could
achieve the same with a iterator-generator and referencesf).
The only catch is this depends on setClassFactory which disappeared from
the latest ZODB :-)
On Thu, Jan 16, 2003 at 03:14:25PM -0500, Jim Fulton wrote:
> A bother with this approach is that the aliases need to be maintained
> as long as the old pickles exist in the database, which could be
> indefinitely.
Yuck.
> A real problem with this approach is that we could end up
> unpickling objects with the wrong class if the old names get
> reused by new classes.
...
> This requires enough bad luck, however, that
> we haven't been bitten by it yet AFAIK,
I think this could easily happen, especialy in iterative development
styles like XP where one tends to change the code a lot.
The problem domain has a concept - Portfolio, say - and one codes a
Portfolio class. Later one realises that this object actually only
embodies one's holdings in a fund, and renames it to FundAccount. But the
original Portfolio concept is still hanging in the air; at a future point
of development one finally embodies it in code - whammo! reusing the old
name.
--
,_
/_) /| /
/ i e t e r / |/ a g e l
http://www.nagel.co.za