almost done issue 12: generate downgrade method for schema migration

This commit is contained in:
christian.simms 2008-04-24 18:52:36 +00:00
parent 16144bb606
commit 9a44d9bd57
4 changed files with 21 additions and 22 deletions

View File

@ -80,25 +80,27 @@ class ModelGenerator(object):
out.append("") out.append("")
return '\n'.join(out) return '\n'.join(out)
def toUpgradePython(self, indent=' '): def toUpgradeDowngradePython(self, indent=' '):
''' Assume model is most current and database is out-of-date. ''' ''' Assume model is most current and database is out-of-date. '''
decls = ['meta = MetaData(migrate_engine)'] decls = ['meta = MetaData(migrate_engine)']
for table in self.diff.tablesMissingInModel + self.diff.tablesMissingInDatabase: for table in self.diff.tablesMissingInModel + self.diff.tablesMissingInDatabase:
decls.extend(self.getTableDefn(table)) decls.extend(self.getTableDefn(table))
cmds = [] upgradeCommands, downgradeCommands = [], []
for table in self.diff.tablesMissingInModel: for table in self.diff.tablesMissingInModel:
tableName = table.name tableName = table.name
cmds.append("%(table)s.drop()" % {'table': tableName}) upgradeCommands.append("%(table)s.drop()" % {'table': tableName})
downgradeCommands.append("%(table)s.create()" % {'table': tableName})
for table in self.diff.tablesMissingInDatabase: for table in self.diff.tablesMissingInDatabase:
tableName = table.name tableName = table.name
cmds.append("%(table)s.create()" % {'table': tableName}) upgradeCommands.append("%(table)s.create()" % {'table': tableName})
downgradeCommands.append("%(table)s.drop()" % {'table': tableName})
return '\n'.join(decls), '\n'.join(['%s%s' % (indent, line) for line in cmds]) return ('\n'.join(decls),
'\n'.join(['%s%s' % (indent, line) for line in upgradeCommands]),
def toDowngradePython(self, indent=' '): '\n'.join(['%s%s' % (indent, line) for line in downgradeCommands])
return ' pass #TODO DOWNGRADE' )
def applyModel(self): def applyModel(self):
''' Apply model to current database. ''' ''' Apply model to current database. '''

View File

@ -22,7 +22,6 @@ class PythonScript(base.BaseScript):
@classmethod @classmethod
def make_update_script_for_model(cls,engine,oldmodel,model,repository,**opts): def make_update_script_for_model(cls,engine,oldmodel,model,repository,**opts):
"""Create a migration script""" """Create a migration script"""
#cls.require_notfound(path) # TODO: yank?
# Compute differences. # Compute differences.
if isinstance(repository, basestring): if isinstance(repository, basestring):
@ -31,20 +30,17 @@ class PythonScript(base.BaseScript):
oldmodel = loadModel(oldmodel) oldmodel = loadModel(oldmodel)
model = loadModel(model) model = loadModel(model)
diff = schemadiff.getDiffOfModelAgainstModel(oldmodel, model, engine, excludeTables=[repository.version_table]) diff = schemadiff.getDiffOfModelAgainstModel(oldmodel, model, engine, excludeTables=[repository.version_table])
upgradeDecls, upgradeCommands = genmodel.ModelGenerator(diff).toUpgradePython() decls, upgradeCommands, downgradeCommands = genmodel.ModelGenerator(diff).toUpgradeDowngradePython()
#downgradeCommands = genmodel.ModelGenerator(diff).toDowngradePython()
# TODO: Use the default script template (defined in the template # Store differences into file.
# module) for now, but we might want to allow people to specify a
# different one later.
template_file = None template_file = None
src = template.get_script(template_file) src = template.get_script(template_file)
contents = open(src).read() contents = open(src).read()
search = 'def upgrade():' search = 'def upgrade():'
contents = contents.replace(search, upgradeDecls + '\n\n' + search, 1) contents = contents.replace(search, decls + '\n\n' + search, 1)
if upgradeCommands: contents = contents.replace(' pass', upgradeCommands, 1) if upgradeCommands: contents = contents.replace(' pass', upgradeCommands, 1)
#if downgradeCommands: contents = contents.replace(' pass', downgradeCommands, 1) # TODO if downgradeCommands: contents = contents.replace(' pass', downgradeCommands, 1)
return contents # TODO: reinstate? open(path, 'w').write(contents) return contents
@classmethod @classmethod
def verify_module(cls,path): def verify_module(cls,path):

View File

@ -50,10 +50,10 @@ class TestSchemaDiff(fixture.DB):
# Model is defined but database is empty. # Model is defined but database is empty.
assertDiff(True, [self.table_name], [], []) assertDiff(True, [self.table_name], [], [])
# Check Python upgrade of database from updated model. # Check Python upgrade and downgrade of database from updated model.
diff = schemadiff.getDiffOfModelAgainstDatabase(self.meta, self.engine, excludeTables=['migrate_version']) diff = schemadiff.getDiffOfModelAgainstDatabase(self.meta, self.engine, excludeTables=['migrate_version'])
decl, commands = genmodel.ModelGenerator(diff).toUpgradePython() decls, upgradeCommands, downgradeCommands = genmodel.ModelGenerator(diff).toUpgradeDowngradePython()
self.assertEqualsIgnoreWhitespace(decl, ''' self.assertEqualsIgnoreWhitespace(decls, '''
meta = MetaData(migrate_engine) meta = MetaData(migrate_engine)
tmp_schemadiff = Table('tmp_schemadiff',meta, tmp_schemadiff = Table('tmp_schemadiff',meta,
Column('id',Integer(),primary_key=True,nullable=False), Column('id',Integer(),primary_key=True,nullable=False),
@ -61,7 +61,8 @@ class TestSchemaDiff(fixture.DB):
Column('data',UnicodeText(length=None)), Column('data',UnicodeText(length=None)),
) )
''') ''')
self.assertEqualsIgnoreWhitespace(commands, '''tmp_schemadiff.create()''') self.assertEqualsIgnoreWhitespace(upgradeCommands, '''tmp_schemadiff.create()''')
self.assertEqualsIgnoreWhitespace(downgradeCommands, '''tmp_schemadiff.drop()''')
# Create table in database, now model should match database. # Create table in database, now model should match database.
self._applyLatestModel() self._applyLatestModel()

View File

@ -542,7 +542,7 @@ class TestShellDatabase(Shell,fixture.DB):
def downgrade(): def downgrade():
# Operations to reverse the above upgrade go here. # Operations to reverse the above upgrade go here.
pass tmp_account_rundiffs.drop()
""") """)
# Commit the change. # Commit the change.