Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

fixing bug which not allow to have two migrations with same timestamp

  • Loading branch information...
commit 5fae6f7ca5bae19ab24ddf15ed9d05fff1094ff2 1 parent 5dc4a25
@wandenberg wandenberg authored
View
7 example/mysql/20090211120001_add_user_address.migration
@@ -0,0 +1,7 @@
+SQL_UP = u"""
+ALTER TABLE users add column address varchar(500) default NULL;
+"""
+
+SQL_DOWN = u"""
+ALTER TABLE users drop column address;
+"""
View
13 simple_db_migrate/core/__init__.py
@@ -56,10 +56,21 @@ def _get_commands(self):
def compare_to(self, another_migration):
if self.version < another_migration.version:
return -1
- elif self.version > another_migration.version:
+ if self.version > another_migration.version:
+ return 1
+ if self.file_name < another_migration.file_name:
+ return -1
+ if self.file_name > another_migration.file_name:
return 1
return 0
+ def __eq__(self, other):
+ dict_1 = self.__dict__
+ dict_2 = other.__dict__
+ dict_1['id'] = dict_1['abspath'] = None
+ dict_2['id'] = dict_2['abspath'] = None
+ return dict_1 == dict_2
+
@staticmethod
def sort_migrations_list(migrations, reverse=False):
return sorted(migrations, cmp=lambda x,y: x.compare_to(y), reverse=reverse)
View
13 simple_db_migrate/main.py
@@ -126,19 +126,20 @@ def _get_destination_version(self):
def _get_migration_files_to_be_executed(self, current_version, destination_version, is_migration_up):
if current_version == destination_version and not self.config.get("force_execute_old_migrations_versions", False):
return []
- schema_versions = self.sgdb.get_all_schema_versions()
- migration_versions = self.db_migrate.get_all_migration_versions()
+
+ schema_migrations = self.sgdb.get_all_schema_migrations()
+ available_migrations = self.db_migrate.get_all_migrations()
# migration up
if is_migration_up:
- remaining_versions_to_execute = Lists.subtract(migration_versions, schema_versions)
- remaining_migrations_to_execute = [self.db_migrate.get_migration_from_version_number(version) for version in remaining_versions_to_execute if version <= destination_version]
+ remaining_migrations = Lists.subtract(available_migrations, schema_migrations)
+ remaining_migrations_to_execute = [migration for migration in remaining_migrations if migration.version <= destination_version]
return remaining_migrations_to_execute
# migration down...
destination_version_id = self.sgdb.get_version_id_from_version_number(destination_version)
- migrations = self.sgdb.get_all_schema_migrations()
- down_migrations_to_execute = [migration for migration in migrations if migration.id > destination_version_id]
+ migration_versions = self.db_migrate.get_all_migration_versions()
+ down_migrations_to_execute = [migration for migration in schema_migrations if migration.id > destination_version_id]
force_files = self.config.get("force_use_files_on_down", False)
for migration in down_migrations_to_execute:
if not migration.sql_down or force_files:
View
2  simple_db_migrate/mssql.py
@@ -156,7 +156,7 @@ def get_all_schema_versions(self):
def get_version_id_from_version_number(self, version):
db = self.__mssql_connect()
- result = db.execute_row("select id from %s where version = '%s';" % (self.__version_table, version))
+ result = db.execute_row("select id from %s where version = '%s' order by id desc;" % (self.__version_table, version))
id = result and int(result['id']) or None
db.close()
return id
View
2  simple_db_migrate/mysql.py
@@ -172,7 +172,7 @@ def get_all_schema_versions(self):
def get_version_id_from_version_number(self, version):
db = self.__mysql_connect()
cursor = db.cursor()
- cursor.execute("select id from %s where version = '%s';" % (self.__version_table, version))
+ cursor.execute("select id from %s where version = '%s' order by id desc;" % (self.__version_table, version))
result = cursor.fetchone()
id = result and int(result[0]) or None
cursor.close()
View
2  simple_db_migrate/oracle.py
@@ -267,7 +267,7 @@ def get_all_schema_versions(self):
def get_version_id_from_version_number(self, version):
conn = self.__connect()
cursor = conn.cursor()
- cursor.execute("select id from %s where version = '%s'" % (self.__version_table, version))
+ cursor.execute("select id from %s where version = '%s' order by id desc" % (self.__version_table, version))
result = cursor.fetchone()
id = result and int(result[0]) or None
cursor.close()
View
73 tests/main_test.py
@@ -681,9 +681,16 @@ def test_it_should_return_an_empty_list_of_files_to_execute_if_current_and_desti
self.assertEqual([], main._get_migration_files_to_be_executed('20090214115300', '20090214115300', True))
def test_it_should_check_if_has_any_old_files_to_execute_if_current_and_destiny_version_are_equals_and_force_old_migrations_is_set(self):
+ all_schema_migrations = [
+ Migration(file_name="20090214115100_01_test_migration.migration", version="20090214115100", sql_up="foo 1", sql_down="bar 1", id=1),
+ Migration(file_name="20090214115200_02_test_migration.migration", version="20090214115200", sql_up="foo 2", sql_down="bar 2", id=2),
+ Migration(file_name="20090214115300_03_test_migration.migration", version="20090214115300", sql_up="foo 3", sql_down="bar 3", id=3),
+ Migration(file_name="20090214115600_06_test_migration.migration", version="20090214115600", sql_up="foo 6", sql_down="bar 6", id=6),
+ ]
+
self.initial_config.update({"schema_version":None, "label_version":None, "database_migrations_dir":['migrations', '.'], 'force_execute_old_migrations_versions':True})
config=Config(self.initial_config)
- main = Main(sgdb=Mock(**{'get_all_schema_versions.return_value':['20090214115100', '20090214115200', '20090214115300', '20090214115600']}), config=config)
+ main = Main(sgdb=Mock(**{'get_all_schema_migrations.return_value':all_schema_migrations, 'get_all_schema_versions.return_value':['20090214115100', '20090214115200', '20090214115300', '20090214115600']}), config=config)
migrations = main._get_migration_files_to_be_executed('20090214115600', '20090214115600', True)
self.assertEqual(2, len(migrations))
@@ -691,9 +698,14 @@ def test_it_should_check_if_has_any_old_files_to_execute_if_current_and_destiny_
self.assertEqual('20090214115500_05_test_migration.migration', migrations[1].file_name)
def test_it_should_check_if_has_any_old_files_to_execute_if_current_and_destiny_version_are_different(self):
+ all_schema_migrations = [
+ Migration(file_name="20090214115100_01_test_migration.migration", version="20090214115100", sql_up="foo 1", sql_down="bar 1", id=1),
+ Migration(file_name="20090214115300_03_test_migration.migration", version="20090214115300", sql_up="foo 3", sql_down="bar 3", id=3),
+ ]
+
self.initial_config.update({"schema_version":None, "label_version":None, "database_migrations_dir":['migrations', '.']})
config=Config(self.initial_config)
- main = Main(sgdb=Mock(**{'get_all_schema_versions.return_value':['20090214115100', '20090214115300']}), config=config)
+ main = Main(sgdb=Mock(**{'get_all_schema_migrations.return_value':all_schema_migrations, 'get_all_schema_versions.return_value':['20090214115100', '20090214115300']}), config=config)
migrations = main._get_migration_files_to_be_executed('20090214115300', '20090214115500', True)
self.assertEqual(3, len(migrations))
@@ -701,6 +713,25 @@ def test_it_should_check_if_has_any_old_files_to_execute_if_current_and_destiny_
self.assertEqual('20090214115400_04_test_migration.migration', migrations[1].file_name)
self.assertEqual('20090214115500_05_test_migration.migration', migrations[2].file_name)
+ def test_it_should_return_migrations_with_same_version_to_execute(self):
+ self.test_migration_files.append(os.path.abspath(create_migration_file('20090214115400_04_1_same_version_test_migration.migration', 'foo 4_1', 'bar 4_1')))
+
+ all_schema_migrations = [
+ Migration(file_name="20090214115100_01_test_migration.migration", version="20090214115100", sql_up="foo 1", sql_down="bar 1", id=1),
+ Migration(file_name="20090214115300_03_test_migration.migration", version="20090214115300", sql_up="foo 3", sql_down="bar 3", id=3),
+ ]
+
+ self.initial_config.update({"schema_version":None, "label_version":None, "database_migrations_dir":['migrations', '.']})
+ config=Config(self.initial_config)
+ main = Main(sgdb=Mock(**{'get_all_schema_migrations.return_value':all_schema_migrations, 'get_all_schema_versions.return_value':['20090214115100', '20090214115300']}), config=config)
+ migrations = main._get_migration_files_to_be_executed('20090214115300', '20090214115500', True)
+
+ self.assertEqual(4, len(migrations))
+ self.assertEqual('20090214115200_02_test_migration.migration', migrations[0].file_name)
+ self.assertEqual('20090214115400_04_1_same_version_test_migration.migration', migrations[1].file_name)
+ self.assertEqual('20090214115400_04_test_migration.migration', migrations[2].file_name)
+ self.assertEqual('20090214115500_05_test_migration.migration', migrations[3].file_name)
+
def test_it_should_return_an_empty_list_of_files_to_execute_if_current_and_destiny_version_are_equals_and_is_down(self):
self.initial_config.update({"schema_version":None, "label_version":None, "database_migrations_dir":['migrations', '.']})
config=Config(self.initial_config)
@@ -795,6 +826,44 @@ def test_it_should_raise_exception_and_stop_process_when_a_migration_file_is_not
main = Main(sgdb=Mock(**{'get_all_schema_migrations.return_value':all_schema_migrations, 'get_all_schema_versions.return_value':['20090214115200', '20090214115301', '20090214115400'], 'get_version_id_from_version_number.side_effect':get_version_id_from_version_number_side_effect}), config=config)
self.assertRaisesWithMessage(Exception, 'impossible to migrate down: one of the versions was not found (20090214115301)', main._get_migration_files_to_be_executed, '20090214115400', '20090214115200', False)
+ def test_it_should_return_migrations_with_same_version_to_execute_when_is_down(self):
+ self.initial_config.update({"schema_version":None, "label_version":None, "database_migrations_dir":['migrations', '.']})
+ config=Config(self.initial_config)
+ all_schema_migrations = [
+ Migration(file_name="20090214115200_02_test_migration.migration", version="20090214115200", sql_up="sql up 02", sql_down="sql down 02", id=2),
+ Migration(file_name="20090214115301_03_test_migration.migration", version="20090214115301", sql_up="sql up 03.1", sql_down="sql down 03.1", id=3),
+ Migration(file_name="20090214115400_04_test_migration.migration", version="20090214115400", sql_up="sql up 04", sql_down="sql down 04", id=4),
+ Migration(file_name="20090214115400_04_1_same_version_test_migration.migration", version="20090214115400", sql_up="sql up 04.1", sql_down="sql down 04.1", id=5)
+ ]
+ main = Main(sgdb=Mock(**{'get_all_schema_migrations.return_value':all_schema_migrations, 'get_all_schema_versions.return_value':['20090214115200', '20090214115301', '20090214115400', '20090214115400'], 'get_version_id_from_version_number.side_effect':get_version_id_from_version_number_side_effect}), config=config)
+ migrations = main._get_migration_files_to_be_executed('20090214115400', '20090214115200', False)
+
+ self.assertEqual(3, len(migrations))
+ self.assertEqual('20090214115400_04_1_same_version_test_migration.migration', migrations[0].file_name)
+ self.assertEqual('20090214115400_04_test_migration.migration', migrations[1].file_name)
+ self.assertEqual('20090214115301_03_test_migration.migration', migrations[2].file_name)
+
+ def test_it_should_return_migrations_without_same_version_to_execute_when_is_down_and_the_duplicated_version_is_the_destination(self):
+ self.initial_config.update({"schema_version":None, "label_version":None, "database_migrations_dir":['migrations', '.']})
+ config=Config(self.initial_config)
+ all_schema_migrations = [
+ Migration(file_name="20090214115200_02_test_migration.migration", version="20090214115200", sql_up="sql up 02", sql_down="sql down 02", id=2),
+ Migration(file_name="20090214115301_03_test_migration.migration", version="20090214115301", sql_up="sql up 03.1", sql_down="sql down 03.1", id=3),
+ Migration(file_name="20090214115300_04_test_migration.migration", version="20090214115400", sql_up="sql up 04", sql_down="sql down 04", id=4),
+ Migration(file_name="20090214115400_04_1_same_version_test_migration.migration", version="20090214115400", sql_up="sql up 04.1", sql_down="sql down 04.1", id=5),
+ Migration(file_name="20090214115500_05_test_migration.migration", version="20090214115500", sql_up="sql up 05", sql_down="sql down 05", id=6)
+ ]
+
+ def get_version_id_from_version_number_side_effect(args):
+ return [migration.id for migration in Migration.sort_migrations_list(all_schema_migrations, reverse=True) if migration.version == str(args)][0]
+
+ main = Main(sgdb=Mock(**{'get_all_schema_migrations.return_value':all_schema_migrations, 'get_all_schema_versions.return_value':['20090214115200', '20090214115301', '20090214115400', '20090214115400', '20090214115500'], 'get_version_id_from_version_number.side_effect':get_version_id_from_version_number_side_effect}), config=config)
+ migrations = main._get_migration_files_to_be_executed('20090214115500', '20090214115400', False)
+
+ self.assertEqual(1, len(migrations))
+ self.assertEqual('20090214115500_05_test_migration.migration', migrations[0].file_name)
+
+
def get_version_id_from_version_number_side_effect(args):
if str(args) == '20090214115100':
return None
View
2  tests/mssql_test.py
@@ -386,7 +386,7 @@ def test_it_should_get_none_for_a_non_existent_version_in_database(self):
self.assertEqual(expected_execute_calls, self.db_mock.execute_scalar.mock_calls)
expected_execute_calls = [
- call("select id from __db_version__ where version = 'xxx';")
+ call("select id from __db_version__ where version = 'xxx' order by id desc;")
]
self.assertEqual(expected_execute_calls, self.db_mock.execute_row.mock_calls)
View
2  tests/mysql_test.py
@@ -395,7 +395,7 @@ def test_it_should_get_none_for_a_non_existent_version_in_database(self):
call('create table if not exists __db_version__ ( id int(11) NOT NULL AUTO_INCREMENT, version varchar(20) NOT NULL default "0", label varchar(255), name varchar(255), sql_up LONGTEXT, sql_down LONGTEXT, PRIMARY KEY (id))'),
call('select count(*) from __db_version__;'),
call('insert into __db_version__ (version) values ("0")'),
- call("select id from __db_version__ where version = 'xxx';")
+ call("select id from __db_version__ where version = 'xxx' order by id desc;")
]
self.assertEqual(expected_execute_calls, self.cursor_mock.execute.mock_calls)
self.assertEqual(4, self.cursor_mock.close.call_count)
View
2  tests/oracle_test.py
@@ -731,7 +731,7 @@ def test_it_should_get_none_for_a_non_existent_version_in_database(self):
call('select version from db_version'),
call('select count(*) from db_version'),
call("insert into db_version (id, version) values (db_version_seq.nextval, '0')"),
- call("select id from db_version where version = 'xxx'")
+ call("select id from db_version where version = 'xxx' order by id desc")
]
self.assertEqual(expected_execute_calls, self.cursor_mock.execute.mock_calls)
Please sign in to comment.
Something went wrong with that request. Please try again.