Use two models in generated migrations. Test column addition and removal.
This commit is contained in:
parent
15f571d296
commit
a1968e7f7d
@ -42,14 +42,15 @@ class TestSchemaDiff(fixture.DB):
|
|||||||
|
|
||||||
def assertDiff(isDiff, tablesMissingInDatabase, tablesMissingInModel, tablesWithDiff):
|
def assertDiff(isDiff, tablesMissingInDatabase, tablesMissingInModel, tablesWithDiff):
|
||||||
diff = schemadiff.getDiffOfModelAgainstDatabase(self.meta, self.engine, excludeTables=['migrate_version'])
|
diff = schemadiff.getDiffOfModelAgainstDatabase(self.meta, self.engine, excludeTables=['migrate_version'])
|
||||||
eq_(bool(diff), isDiff)
|
|
||||||
eq_(
|
eq_(
|
||||||
(diff.tables_missing_from_B,
|
(diff.tables_missing_from_B,
|
||||||
diff.tables_missing_from_A,
|
diff.tables_missing_from_A,
|
||||||
diff.tables_different.keys()),
|
diff.tables_different.keys(),
|
||||||
|
bool(diff)),
|
||||||
(tablesMissingInDatabase,
|
(tablesMissingInDatabase,
|
||||||
tablesMissingInModel,
|
tablesMissingInModel,
|
||||||
tablesWithDiff)
|
tablesWithDiff,
|
||||||
|
isDiff)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Model is defined but database is empty.
|
# Model is defined but database is empty.
|
||||||
@ -64,8 +65,9 @@ class TestSchemaDiff(fixture.DB):
|
|||||||
if repr(String()) == 'String()':
|
if repr(String()) == 'String()':
|
||||||
self.assertEqualsIgnoreWhitespace(decls, '''
|
self.assertEqualsIgnoreWhitespace(decls, '''
|
||||||
from migrate.changeset import schema
|
from migrate.changeset import schema
|
||||||
meta = MetaData()
|
pre_meta = MetaData()
|
||||||
tmp_schemadiff = Table('tmp_schemadiff', meta,
|
post_meta = MetaData()
|
||||||
|
tmp_schemadiff = Table('tmp_schemadiff', post_meta,
|
||||||
Column('id', Integer, primary_key=True, nullable=False),
|
Column('id', Integer, primary_key=True, nullable=False),
|
||||||
Column('name', UnicodeText),
|
Column('name', UnicodeText),
|
||||||
Column('data', UnicodeText),
|
Column('data', UnicodeText),
|
||||||
@ -74,19 +76,14 @@ class TestSchemaDiff(fixture.DB):
|
|||||||
else:
|
else:
|
||||||
self.assertEqualsIgnoreWhitespace(decls, '''
|
self.assertEqualsIgnoreWhitespace(decls, '''
|
||||||
from migrate.changeset import schema
|
from migrate.changeset import schema
|
||||||
meta = MetaData()
|
pre_meta = MetaData()
|
||||||
tmp_schemadiff = Table('tmp_schemadiff', meta,
|
post_meta = MetaData()
|
||||||
|
tmp_schemadiff = Table('tmp_schemadiff', post_meta,
|
||||||
Column('id', Integer, primary_key=True, nullable=False),
|
Column('id', Integer, primary_key=True, nullable=False),
|
||||||
Column('name', UnicodeText(length=None)),
|
Column('name', UnicodeText(length=None)),
|
||||||
Column('data', UnicodeText(length=None)),
|
Column('data', UnicodeText(length=None)),
|
||||||
)
|
)
|
||||||
''')
|
''')
|
||||||
self.assertEqualsIgnoreWhitespace(upgradeCommands,
|
|
||||||
'''meta.bind = migrate_engine
|
|
||||||
tmp_schemadiff.create()''')
|
|
||||||
self.assertEqualsIgnoreWhitespace(downgradeCommands,
|
|
||||||
'''meta.bind = migrate_engine
|
|
||||||
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()
|
||||||
@ -111,12 +108,14 @@ class TestSchemaDiff(fixture.DB):
|
|||||||
else:
|
else:
|
||||||
dataId = result.last_inserted_ids()[0]
|
dataId = result.last_inserted_ids()[0]
|
||||||
|
|
||||||
# Modify table in model (by removing it and adding it back to model) -- drop column data and add column data2.
|
# Modify table in model (by removing it and adding it back to model)
|
||||||
|
# Drop column data, add columns data2 and data3.
|
||||||
self.meta.remove(self.table)
|
self.meta.remove(self.table)
|
||||||
self.table = Table(self.table_name,self.meta,
|
self.table = Table(self.table_name,self.meta,
|
||||||
Column('id',Integer(),primary_key=True),
|
Column('id',Integer(),primary_key=True),
|
||||||
Column('name',UnicodeText(length=None)),
|
Column('name',UnicodeText(length=None)),
|
||||||
Column('data2',Integer(),nullable=True),
|
Column('data2',Integer(),nullable=True),
|
||||||
|
Column('data3',Integer(),nullable=True),
|
||||||
)
|
)
|
||||||
assertDiff(True, [], [], [self.table_name])
|
assertDiff(True, [], [], [self.table_name])
|
||||||
|
|
||||||
@ -124,6 +123,36 @@ class TestSchemaDiff(fixture.DB):
|
|||||||
self._applyLatestModel()
|
self._applyLatestModel()
|
||||||
assertDiff(False, [], [], [])
|
assertDiff(False, [], [], [])
|
||||||
|
|
||||||
|
# Drop column data3, add data4
|
||||||
|
self.meta.remove(self.table)
|
||||||
|
self.table = Table(self.table_name,self.meta,
|
||||||
|
Column('id',Integer(),primary_key=True),
|
||||||
|
Column('name',UnicodeText(length=None)),
|
||||||
|
Column('data2',Integer(),nullable=True),
|
||||||
|
Column('data4',Float(),nullable=True),
|
||||||
|
)
|
||||||
|
assertDiff(True, [], [], [self.table_name])
|
||||||
|
|
||||||
|
diff = schemadiff.getDiffOfModelAgainstDatabase(
|
||||||
|
self.meta, self.engine, excludeTables=['migrate_version'])
|
||||||
|
decls, upgradeCommands, downgradeCommands = genmodel.ModelGenerator(diff,self.engine).genB2AMigration(indent='')
|
||||||
|
|
||||||
|
# decls have changed since genBDefinition
|
||||||
|
exec decls in locals()
|
||||||
|
# migration commands expect a namespace containing migrate_engine
|
||||||
|
migrate_engine = self.engine
|
||||||
|
# run the migration up and down
|
||||||
|
exec upgradeCommands in locals()
|
||||||
|
assertDiff(False, [], [], [])
|
||||||
|
|
||||||
|
exec decls in locals()
|
||||||
|
exec downgradeCommands in locals()
|
||||||
|
assertDiff(True, [], [], [self.table_name])
|
||||||
|
|
||||||
|
exec decls in locals()
|
||||||
|
exec upgradeCommands in locals()
|
||||||
|
assertDiff(False, [], [], [])
|
||||||
|
|
||||||
if not self.engine.name == 'oracle':
|
if not self.engine.name == 'oracle':
|
||||||
# Make sure data is still present.
|
# Make sure data is still present.
|
||||||
result = self.engine.execute(self.table.select(self.table.c.id==dataId))
|
result = self.engine.execute(self.table.select(self.table.c.id==dataId))
|
||||||
|
@ -158,8 +158,8 @@ def upgrade(migrate_engine):
|
|||||||
repository=self.repo_path,
|
repository=self.repo_path,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertTrue('User.create()' in source_script)
|
self.assertTrue("['User'].create()" in source_script)
|
||||||
self.assertTrue('User.drop()' in source_script)
|
self.assertTrue("['User'].drop()" in source_script)
|
||||||
|
|
||||||
@fixture.usedb()
|
@fixture.usedb()
|
||||||
def test_make_update_script_for_equal_models(self):
|
def test_make_update_script_for_equal_models(self):
|
||||||
@ -196,9 +196,9 @@ def upgrade(migrate_engine):
|
|||||||
|
|
||||||
self.assertTrue(0
|
self.assertTrue(0
|
||||||
< source_script.find('upgrade')
|
< source_script.find('upgrade')
|
||||||
< source_script.find('User.create()')
|
< source_script.find("['User'].create()")
|
||||||
< source_script.find('downgrade')
|
< source_script.find('downgrade')
|
||||||
< source_script.find('User.drop()'))
|
< source_script.find("['User'].drop()"))
|
||||||
|
|
||||||
def setup_model_params(self):
|
def setup_model_params(self):
|
||||||
self.script_path = self.tmp_py()
|
self.script_path = self.tmp_py()
|
||||||
|
@ -96,7 +96,7 @@ class ModelGenerator(object):
|
|||||||
else:
|
else:
|
||||||
return """Column(%(name)r, %(commonStuff)s)""" % data
|
return """Column(%(name)r, %(commonStuff)s)""" % data
|
||||||
|
|
||||||
def _getTableDefn(self, table):
|
def _getTableDefn(self, table, metaName='meta'):
|
||||||
out = []
|
out = []
|
||||||
tableName = table.name
|
tableName = table.name
|
||||||
if self.declarative:
|
if self.declarative:
|
||||||
@ -107,8 +107,8 @@ class ModelGenerator(object):
|
|||||||
out.append(" %s" % self.column_repr(col))
|
out.append(" %s" % self.column_repr(col))
|
||||||
out.append('\n')
|
out.append('\n')
|
||||||
else:
|
else:
|
||||||
out.append("%(table)s = Table('%(table)s', meta," %
|
out.append("%(table)s = Table('%(table)s', %(meta)s," %
|
||||||
{'table': tableName})
|
{'table': tableName, 'meta': metaName})
|
||||||
for col in table.columns:
|
for col in table.columns:
|
||||||
out.append(" %s," % self.column_repr(col))
|
out.append(" %s," % self.column_repr(col))
|
||||||
out.append(")\n")
|
out.append(")\n")
|
||||||
@ -151,46 +151,61 @@ class ModelGenerator(object):
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
decls = ['from migrate.changeset import schema',
|
decls = ['from migrate.changeset import schema',
|
||||||
'meta = MetaData()']
|
'pre_meta = MetaData()',
|
||||||
for table in self._get_tables(
|
'post_meta = MetaData()',
|
||||||
missingA=True,missingB=True,modified=True
|
]
|
||||||
):
|
upgradeCommands = ['pre_meta.bind = migrate_engine',
|
||||||
decls.extend(self._getTableDefn(table))
|
'post_meta.bind = migrate_engine']
|
||||||
|
downgradeCommands = list(upgradeCommands)
|
||||||
|
|
||||||
upgradeCommands, downgradeCommands = [], []
|
for tn in self.diff.tables_missing_from_A:
|
||||||
for tableName in self.diff.tables_missing_from_A:
|
pre_table = self.diff.metadataB.tables[tn]
|
||||||
upgradeCommands.append("%(table)s.drop()" % {'table': tableName})
|
decls.extend(self._getTableDefn(pre_table, metaName='pre_meta'))
|
||||||
downgradeCommands.append("%(table)s.create()" % \
|
upgradeCommands.append(
|
||||||
{'table': tableName})
|
"pre_meta.tables[%(table)r].drop()" % {'table': tn})
|
||||||
for tableName in self.diff.tables_missing_from_B:
|
downgradeCommands.append(
|
||||||
upgradeCommands.append("%(table)s.create()" % {'table': tableName})
|
"pre_meta.tables[%(table)r].create()" % {'table': tn})
|
||||||
downgradeCommands.append("%(table)s.drop()" % {'table': tableName})
|
|
||||||
|
for tn in self.diff.tables_missing_from_B:
|
||||||
|
post_table = self.diff.metadataA.tables[tn]
|
||||||
|
decls.extend(self._getTableDefn(post_table, metaName='post_meta'))
|
||||||
|
upgradeCommands.append(
|
||||||
|
"post_meta.tables[%(table)r].create()" % {'table': tn})
|
||||||
|
downgradeCommands.append(
|
||||||
|
"post_meta.tables[%(table)r].drop()" % {'table': tn})
|
||||||
|
|
||||||
|
for (tn, td) in self.diff.tables_different.iteritems():
|
||||||
|
if td.columns_missing_from_A or td.columns_different:
|
||||||
|
pre_table = self.diff.metadataB.tables[tn]
|
||||||
|
decls.extend(self._getTableDefn(
|
||||||
|
pre_table, metaName='pre_meta'))
|
||||||
|
if td.columns_missing_from_B or td.columns_different:
|
||||||
|
post_table = self.diff.metadataA.tables[tn]
|
||||||
|
decls.extend(self._getTableDefn(
|
||||||
|
post_table, metaName='post_meta'))
|
||||||
|
|
||||||
for tableName in self.diff.tables_different:
|
|
||||||
dbTable = self.diff.metadataB.tables[tableName]
|
|
||||||
td = self.diff.tables_different[tableName]
|
|
||||||
for col in td.columns_missing_from_A:
|
for col in td.columns_missing_from_A:
|
||||||
upgradeCommands.append('%s.append_column(%s)' % (
|
upgradeCommands.append(
|
||||||
tableName,
|
'pre_meta.tables[%r].columns[%r].drop()' % (tn, col))
|
||||||
self.column_repr(
|
downgradeCommands.append(
|
||||||
self.diff.metadataB.tables[tableName].columns[col])))
|
'pre_meta.tables[%r].columns[%r].create()' % (tn, col))
|
||||||
downgradeCommands.append('%s.columns[%r].drop()' % (tableName, col))
|
|
||||||
for col in td.columns_missing_from_B:
|
for col in td.columns_missing_from_B:
|
||||||
upgradeCommands.append('%s.columns[%r].drop()' % (tableName, col))
|
upgradeCommands.append(
|
||||||
downgradeCommands.append('%s.columns[%r].create()' % (tableName, col))
|
'post_meta.tables[%r].columns[%r].create()' % (tn, col))
|
||||||
|
downgradeCommands.append(
|
||||||
|
'post_meta.tables[%r].columns[%r].drop()' % (tn, col))
|
||||||
for modelCol, databaseCol, modelDecl, databaseDecl in td.columns_different:
|
for modelCol, databaseCol, modelDecl, databaseDecl in td.columns_different:
|
||||||
upgradeCommands.append(
|
upgradeCommands.append(
|
||||||
'assert False, "Can\'t alter columns: %s:%s=>%s"' % (
|
'assert False, "Can\'t alter columns: %s:%s=>%s"' % (
|
||||||
tableName, modelCol.name, databaseCol.name))
|
tn, modelCol.name, databaseCol.name))
|
||||||
downgradeCommands.append(
|
downgradeCommands.append(
|
||||||
'assert False, "Can\'t alter columns: %s:%s=>%s"' % (
|
'assert False, "Can\'t alter columns: %s:%s=>%s"' % (
|
||||||
tableName, modelCol.name, databaseCol.name))
|
tn, modelCol.name, databaseCol.name))
|
||||||
pre_command = ' meta.bind = migrate_engine'
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
'\n'.join(decls),
|
'\n'.join(decls),
|
||||||
'\n'.join([pre_command] + ['%s%s' % (indent, line) for line in upgradeCommands]),
|
'\n'.join('%s%s' % (indent, line) for line in upgradeCommands),
|
||||||
'\n'.join([pre_command] + ['%s%s' % (indent, line) for line in downgradeCommands]))
|
'\n'.join('%s%s' % (indent, line) for line in downgradeCommands))
|
||||||
|
|
||||||
def _db_can_handle_this_change(self,td):
|
def _db_can_handle_this_change(self,td):
|
||||||
"""Check if the database can handle going from B to A."""
|
"""Check if the database can handle going from B to A."""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user