def reset_db(self, default_data=None): """Remove all data from Trac tables, keeping the tables themselves. :param default_data: after clean-up, initialize with default data :return: True upon success """ from trac import db_default tables = [] dbm = DatabaseManager(self) try: db_version = dbm.get_database_version() except (TracError, self.db_exc.DatabaseError): pass else: if db_version == db_default.db_version: # same version, simply clear the tables (faster) tables = dbm.reset_tables() else: # different version or version unknown, drop the tables self.destroy_db() if not tables: dbm.init_db() # Make sure the next db_query()/db_transaction() will create # a new connection aware of the new data model - see #8518. if self.dburi != 'sqlite::memory:': dbm.shutdown() if default_data: dbm.insert_into_tables(db_default.get_data) else: dbm.set_database_version(db_default.db_version)
class UpgradeTestCase(unittest.TestCase): def setUp(self): self.env = EnvironmentStub(path=mkdtemp()) self.dbm = DatabaseManager(self.env) with self.env.db_transaction: self.dbm.drop_tables(new_schema) self.dbm.create_tables(old_schema) self.dbm.set_database_version(VERSION - 1) def tearDown(self): self.env.reset_db_and_disk() def test_attachment_table_upgraded(self): """The ipnr column is removed from the attachment table.""" db42.do_upgrade(self.env, VERSION, None) column_names = [col.name for col in new_attachment_schema.columns] self.assertEqual(column_names, self.dbm.get_column_names('attachment')) def test_wiki_table_upgraded(self): """The ipnr column is removed from the wiki table.""" db42.do_upgrade(self.env, VERSION, None) column_names = [col.name for col in new_wiki_schema.columns] self.assertEqual(column_names, self.dbm.get_column_names('wiki')) def test_attachments_data_migrated(self): """Attachment data is migrated on table upgrade.""" now = to_utimestamp(datetime_now(utc)) attachment_column_names = \ [col.name for col in old_attachment_schema.columns] attachment_data = (('ticket', '1', 'file1', 10, now, 'desc1', 'user1', '::1'), ('wiki', 'WikiStart', 'file2', 20, now, 'desc2', 'user2', '::2')) self.dbm.insert_into_tables( (('attachment', attachment_column_names, attachment_data), )) db42.do_upgrade(self.env, VERSION, None) ipnr_col = attachment_column_names.index('ipnr') i = 0 for i, data in enumerate( self.env.db_query(""" SELECT * FROM attachment ORDER BY type """)): self.assertEqual( attachment_data[i][:ipnr_col] + attachment_data[i][ipnr_col + 1:], data) self.assertEqual(len(attachment_data), i + 1) def test_wiki_data_migrated(self): """Wiki data is migrated on table upgrade.""" now = to_utimestamp(datetime_now(utc)) wiki_column_names = \ [col.name for col in old_wiki_schema.columns] wiki_data = (('TracGuide', 2, now, 'user2', '::4', 'The guide', 'Edit', 0), ('WikiStart', 1, now, 'user1', '::3', 'The page', 'Init', 1)) self.dbm.insert_into_tables((('wiki', wiki_column_names, wiki_data), )) db42.do_upgrade(self.env, VERSION, None) ipnr_col = wiki_column_names.index('ipnr') i = 0 for i, data in enumerate( self.env.db_query(""" SELECT * FROM wiki ORDER BY name """)): self.assertEqual( wiki_data[i][:ipnr_col] + wiki_data[i][ipnr_col + 1:], data) self.assertEqual(len(wiki_data), i + 1)
class PostgresConnectionTestCase(unittest.TestCase): def setUp(self): self.env = EnvironmentStub() self.schema = [ Table('test_simple', key='id')[Column('id', auto_increment=True), Column('username'), Column('email'), Column('enabled', type='int'), Column('extra'), Index(['username'], unique=True), Index(['email'], unique=False), ], Table('test_composite', key=['id', 'name'])[Column('id', type='int'), Column('name'), Column('value'), Column('enabled', type='int'), Index(['name', 'value'], unique=False), Index(['enabled', 'name'], unique=True), ], ] self.dbm = DatabaseManager(self.env) self.dbm.drop_tables(self.schema) self.dbm.create_tables(self.schema) self.dbm.insert_into_tables([ ('test_simple', ('username', 'email', 'enabled'), [('joe', '*****@*****.**', 1), (u'joé', '*****@*****.**', 0)]), ('test_composite', ('id', 'name', 'value', 'enabled'), [(1, 'foo', '42', 1), (1, 'bar', '42', 1), (2, 'foo', '43', 0), (2, 'bar', '43', 0)]), ]) def tearDown(self): DatabaseManager(self.env).drop_tables(self.schema) self.env.reset_db() def _drop_column(self, table, column): with self.env.db_transaction as db: db.drop_column(table, column) def _get_indices(self, table): with self.env.db_query: tab_oid = self._query( """ SELECT tab.oid FROM pg_class tab INNER JOIN pg_namespace ns ON ns.oid = tab.relnamespace AND ns.nspname = ANY (current_schemas(false)) WHERE tab.relname=%s AND tab.relkind = 'r' """, table)[0][0] column_names = self._query( """ SELECT attnum, attname FROM pg_attribute WHERE attrelid=%s AND attnum >= 0 AND NOT attisdropped """, tab_oid) column_names = dict((row[0], row[1]) for row in column_names) indices = self._query( """ SELECT ind.relname, d.indisprimary, d.indisunique, d.indkey FROM pg_index d INNER JOIN pg_class ind ON d.indexrelid = ind.oid AND ind.relkind = 'i' WHERE d.indrelid=%s """, tab_oid) results = {} for index, pk, unique, indkey in indices: columns = [column_names[int(i)] for i in indkey.split()] results[index] = { 'pk': bool(pk), 'unique': bool(unique), 'columns': columns } return results def _query(self, stmt, *args): return self.env.db_query(stmt, args) def test_remove_simple_keys(self): indices_0 = self._get_indices('test_simple') self.assertEqual([ 'test_simple_email_idx', 'test_simple_pkey', 'test_simple_username_idx' ], sorted(indices_0)) self.assertEqual({ 'pk': False, 'unique': True, 'columns': ['username'] }, indices_0['test_simple_username_idx']) self.assertEqual({ 'pk': True, 'unique': True, 'columns': ['id'] }, indices_0['test_simple_pkey']) self.assertEqual({ 'pk': False, 'unique': False, 'columns': ['email'] }, indices_0['test_simple_email_idx']) self._drop_column('test_simple', 'enabled') self.assertEqual(indices_0, self._get_indices('test_simple')) self._drop_column('test_simple', 'username') indices_1 = self._get_indices('test_simple') self.assertEqual(['test_simple_email_idx', 'test_simple_pkey'], sorted(indices_1)) self._drop_column('test_simple', 'email') indices_2 = self._get_indices('test_simple') self.assertEqual(['test_simple_pkey'], sorted(indices_2)) self._drop_column('test_simple', 'id') indices_3 = self._get_indices('test_simple') self.assertEqual({}, indices_3) def test_remove_composite_keys(self): indices_0 = self._get_indices('test_composite') self.assertEqual([ 'test_composite_enabled_name_idx', 'test_composite_name_value_idx', 'test_composite_pk' ], sorted(indices_0)) self.assertEqual( { 'pk': False, 'unique': False, 'columns': ['name', 'value'] }, indices_0['test_composite_name_value_idx']) self.assertEqual( { 'pk': False, 'unique': True, 'columns': ['enabled', 'name'] }, indices_0['test_composite_enabled_name_idx']) self.assertEqual( { 'pk': True, 'unique': True, 'columns': ['id', 'name'] }, indices_0['test_composite_pk']) self._drop_column('test_composite', 'id') indices_1 = self._get_indices('test_composite') self.assertEqual([ 'test_composite_enabled_name_idx', 'test_composite_name_value_idx' ], sorted(indices_1)) self.assertEqual(indices_0['test_composite_name_value_idx'], indices_1['test_composite_name_value_idx']) self.assertEqual(indices_0['test_composite_enabled_name_idx'], indices_1['test_composite_enabled_name_idx']) rows = self._query("""SELECT * FROM test_composite ORDER BY name, value, enabled""") self.assertEqual([('bar', '42', 1), ('bar', '43', 0), ('foo', '42', 1), ('foo', '43', 0)], rows) self._drop_column('test_composite', 'name') self.assertEqual({}, self._get_indices('test_composite')) rows = self._query("""SELECT * FROM test_composite ORDER BY value, enabled""") self.assertEqual([('42', 1), ('42', 1), ('43', 0), ('43', 0)], rows)
class ModifyTableTestCase(unittest.TestCase): def setUp(self): self.env = EnvironmentStub() self.dbm = DatabaseManager(self.env) self.schema = [ Table('table1', key='col1')[Column('col1', auto_increment=True), Column('col2'), Column('col3'), ], Table('table2', key='col1')[Column('col1'), Column('col2'), ], Table('table3', key='col2')[Column('col1'), Column('col2', type='int'), Column('col3')] ] self.dbm.create_tables(self.schema) self.new_schema = copy.deepcopy([self.schema[0], self.schema[2]]) self.new_schema[0].remove_columns(('col2', )) self.new_schema[1].columns.append(Column('col4')) def tearDown(self): self.dbm.drop_tables(self.schema) self.env.reset_db() def _insert_data(self): table_data = [ ('table1', ('col2', 'col3'), (('data1', 'data2'), ('data3', 'data4'))), ('table2', ('col1', 'col2'), (('data5', 'data6'), ('data7', 'data8'))), ('table3', ('col1', 'col2', 'col3'), (('data9', 10, 'data11'), ('data12', 13, 'data14'))), ] self.dbm.insert_into_tables(table_data) def test_drop_columns(self): """Data is preserved when column is dropped.""" self._insert_data() self.dbm.drop_columns('table1', ('col2', )) self.assertEqual(['col1', 'col3'], self.dbm.get_column_names('table1')) data = list(self.env.db_query("SELECT * FROM table1")) self.assertEqual((1, 'data2'), data[0]) self.assertEqual((2, 'data4'), data[1]) def test_drop_columns_multiple_columns(self): """Data is preserved when columns are dropped.""" self._insert_data() self.dbm.drop_columns('table3', ('col1', 'col3')) self.assertEqual(['col2'], self.dbm.get_column_names('table3')) data = list(self.env.db_query("SELECT * FROM table3")) self.assertEqual((10, ), data[0]) self.assertEqual((13, ), data[1]) def test_upgrade_tables_have_new_schema(self): """The upgraded tables have the new schema.""" self.dbm.upgrade_tables(self.new_schema) for table in self.new_schema: self.assertEqual([col.name for col in table.columns], self.dbm.get_column_names(table.name)) def test_upgrade_tables_data_is_migrated(self): """The data is migrated to the upgraded tables.""" self._insert_data() self.dbm.upgrade_tables(self.new_schema) self.env.db_transaction(""" INSERT INTO table1 (col3) VALUES ('data12') """) data = list(self.env.db_query("SELECT * FROM table1")) self.assertEqual((1, 'data2'), data[0]) self.assertEqual((2, 'data4'), data[1]) self.assertEqual( 3, self.env.db_query(""" SELECT col1 FROM table1 WHERE col3='data12'""")[0][0]) data = list(self.env.db_query("SELECT * FROM table2")) self.assertEqual(('data5', 'data6'), data[0]) self.assertEqual(('data7', 'data8'), data[1]) data = list(self.env.db_query("SELECT * FROM table3")) self.assertEqual(('data9', 10, 'data11', None), data[0]) self.assertEqual(('data12', 13, 'data14', None), data[1]) def test_upgrade_tables_no_common_columns(self): schema = [ Table('table1', key='id')[Column('id', auto_increment=True), Column('name'), Column('value'), ], ] self.dbm.upgrade_tables(schema) self.assertEqual(['id', 'name', 'value'], self.dbm.get_column_names('table1')) self.assertEqual([], list(self.env.db_query("SELECT * FROM table1")))
class ConnectionTestCase(unittest.TestCase): def setUp(self): self.env = EnvironmentStub() self.schema = [ Table('HOURS', key='ID')[Column('ID', auto_increment=True), Column('AUTHOR')], Table('blog', key='bid')[Column('bid', auto_increment=True), Column('author'), Column('comment')] ] self.dbm = DatabaseManager(self.env) self.dbm.drop_tables(self.schema) self.dbm.create_tables(self.schema) def tearDown(self): DatabaseManager(self.env).drop_tables(self.schema) self.env.reset_db() def test_drop_column(self): """Data is preserved when column is dropped.""" table_data = [ ('blog', ('author', 'comment'), (('author1', 'comment one'), ('author2', 'comment two'))), ] self.dbm.insert_into_tables(table_data) with self.env.db_transaction as db: db.drop_column('blog', 'comment') data = list(self.env.db_query("SELECT * FROM blog")) self.assertEqual((1, 'author1'), data[0]) self.assertEqual((2, 'author2'), data[1]) def test_drop_column_no_exists(self): """Error is not raised when dropping non-existent column.""" table_data = [ ('blog', ('author', 'comment'), (('author1', 'comment one'), ('author2', 'comment two'))), ] self.dbm.insert_into_tables(table_data) with self.env.db_transaction as db: db.drop_column('blog', 'tags') data = list(self.env.db_query("SELECT * FROM blog")) self.assertEqual((1, 'author1', 'comment one'), data[0]) self.assertEqual((2, 'author2', 'comment two'), data[1]) def test_get_last_id(self): q = "INSERT INTO report (author) VALUES ('anonymous')" with self.env.db_transaction as db: cursor = db.cursor() cursor.execute(q) # Row ID correct before... id1 = db.get_last_id(cursor, 'report') db.commit() cursor.execute(q) # ... and after commit() db.commit() id2 = db.get_last_id(cursor, 'report') self.assertNotEqual(0, id1) self.assertEqual(id1 + 1, id2) def test_update_sequence_default_column_name(self): with self.env.db_transaction as db: db("INSERT INTO report (id, author) VALUES (42, 'anonymous')") cursor = db.cursor() db.update_sequence(cursor, 'report') self.env.db_transaction( "INSERT INTO report (author) VALUES ('next-id')") self.assertEqual( 43, self.env.db_query("SELECT id FROM report WHERE author='next-id'") [0][0]) def test_update_sequence_nondefault_column_name(self): with self.env.db_transaction as db: cursor = db.cursor() cursor.execute( "INSERT INTO blog (bid, author) VALUES (42, 'anonymous')") db.update_sequence(cursor, 'blog', 'bid') self.env.db_transaction("INSERT INTO blog (author) VALUES ('next-id')") self.assertEqual( 43, self.env.db_query("SELECT bid FROM blog WHERE author='next-id'")[0] [0]) def test_identifiers_need_quoting(self): """Test for regression described in comment:4:ticket:11512.""" with self.env.db_transaction as db: db("INSERT INTO %s (%s, %s) VALUES (42, 'anonymous')" % (db.quote('HOURS'), db.quote('ID'), db.quote('AUTHOR'))) cursor = db.cursor() db.update_sequence(cursor, 'HOURS', 'ID') with self.env.db_transaction as db: cursor = db.cursor() cursor.execute("INSERT INTO %s (%s) VALUES ('next-id')" % (db.quote('HOURS'), db.quote('AUTHOR'))) last_id = db.get_last_id(cursor, 'HOURS', 'ID') self.assertEqual(43, last_id) def test_get_table_names(self): schema = default_schema + self.schema with self.env.db_query as db: # Some DB (e.g. MariaDB) normalize the table names to lower case self.assertEqual( sorted(table.name.lower() for table in schema), sorted(name.lower() for name in db.get_table_names())) def test_get_column_names(self): schema = default_schema + self.schema with self.env.db_query as db: for table in schema: column_names = [col.name for col in table.columns] self.assertEqual(column_names, db.get_column_names(table.name))
class SQLiteConnectionTestCase(unittest.TestCase): def setUp(self): self.env = EnvironmentStub() self.schema = [ Table('test_simple', key='id')[Column('id', auto_increment=True), Column('username'), Column('email'), Column('enabled', type='int'), Column('extra'), Index(['username'], unique=True), Index(['email'], unique=False), ], Table('test_composite', key=['id', 'name'])[Column('id', type='int'), Column('name'), Column('value'), Column('enabled', type='int'), Index(['name', 'value'], unique=False), Index(['name', 'enabled'], unique=True), ], ] self.dbm = DatabaseManager(self.env) self.dbm.drop_tables(self.schema) self.dbm.create_tables(self.schema) self.dbm.insert_into_tables([ ('test_simple', ('username', 'email', 'enabled'), [('joe', '*****@*****.**', 1), (u'joé', '*****@*****.**', 0)]), ('test_composite', ('id', 'name', 'value', 'enabled'), [(1, 'foo', '42', 1), (1, 'bar', '42', 1), (2, 'foo', '43', 0), (2, 'bar', '43', 0)]), ]) def tearDown(self): DatabaseManager(self.env).drop_tables(self.schema) self.env.reset_db() def _table_info(self, table): names = ('column', 'type', 'notnull', 'default', 'pk') with self.env.db_query as db: cursor = db.cursor() cursor.execute("PRAGMA table_info(%s)" % db.quote(table)) return [dict(zip(names, row[1:6])) for row in cursor] def _index_info(self, table): with self.env.db_query as db: cursor = db.cursor() cursor.execute("PRAGMA index_list(%s)" % db.quote(table)) results = {row[1]: {'unique': row[2]} for row in cursor} for index, info in results.iteritems(): cursor.execute("PRAGMA index_info(%s)" % db.quote(index)) info['columns'] = [row[2] for row in cursor] return results def _drop_column(self, table, column): with self.env.db_transaction as db: db.drop_column(table, column) def _query(self, stmt, *args): return self.env.db_query(stmt, args) def test_remove_simple_keys(self): coldef = { 'id': { 'column': 'id', 'type': 'integer', 'notnull': 0, 'default': None, 'pk': 1 }, 'username': { 'column': 'username', 'type': 'text', 'notnull': 0, 'default': None, 'pk': 0 }, 'email': { 'column': 'email', 'type': 'text', 'notnull': 0, 'default': None, 'pk': 0 }, 'enabled': { 'column': 'enabled', 'type': 'integer', 'notnull': 0, 'default': None, 'pk': 0 }, 'extra': { 'column': 'extra', 'type': 'text', 'notnull': 0, 'default': None, 'pk': 0 }, } columns_0 = self._table_info('test_simple') self.assertEqual([ coldef['id'], coldef['username'], coldef['email'], coldef['enabled'], coldef['extra'] ], columns_0) indices_0 = self._index_info('test_simple') self.assertEqual(['test_simple_email_idx', 'test_simple_username_idx'], sorted(indices_0)) self._drop_column('test_simple', 'extra') columns_1 = self._table_info('test_simple') indices_1 = self._index_info('test_simple') self.assertEqual([ coldef['id'], coldef['username'], coldef['email'], coldef['enabled'] ], columns_1) self.assertEqual(indices_1, indices_0) self._drop_column('test_simple', 'id') columns_2 = self._table_info('test_simple') indices_2 = self._index_info('test_simple') self.assertEqual( [coldef['username'], coldef['email'], coldef['enabled']], columns_2) self.assertEqual(indices_2, indices_0) self._drop_column('test_simple', 'username') columns_3 = self._table_info('test_simple') indices_3 = self._index_info('test_simple') self.assertEqual([coldef['email'], coldef['enabled']], columns_3) self.assertEqual(['test_simple_email_idx'], sorted(indices_3)) self._drop_column('test_simple', 'email') columns_4 = self._table_info('test_simple') indices_4 = self._index_info('test_simple') self.assertEqual([coldef['enabled']], columns_4) self.assertEqual({}, indices_4) def test_remove_composite_keys(self): indices_0 = self._index_info('test_composite') self.assertEqual([ 'sqlite_autoindex_test_composite_1', 'test_composite_name_enabled_idx', 'test_composite_name_value_idx' ], sorted(indices_0)) self.assertEqual({ 'unique': 1, 'columns': ['id', 'name'] }, indices_0['sqlite_autoindex_test_composite_1']) self.assertEqual({ 'unique': 0, 'columns': ['name', 'value'] }, indices_0['test_composite_name_value_idx']) self.assertEqual({ 'unique': 1, 'columns': ['name', 'enabled'] }, indices_0['test_composite_name_enabled_idx']) self._drop_column('test_composite', 'id') indices_1 = self._index_info('test_composite') self.assertEqual([ 'test_composite_name_enabled_idx', 'test_composite_name_value_idx' ], sorted(indices_1)) self.assertEqual(indices_0['test_composite_name_value_idx'], indices_1['test_composite_name_value_idx']) self.assertEqual(indices_0['test_composite_name_enabled_idx'], indices_1['test_composite_name_enabled_idx']) rows = self._query("""SELECT * FROM test_composite ORDER BY name, value, enabled""") self.assertEqual([('bar', '42', 1), ('bar', '43', 0), ('foo', '42', 1), ('foo', '43', 0)], rows) self._drop_column('test_composite', 'name') self.assertEqual({}, self._index_info('test_composite')) rows = self._query("""SELECT * FROM test_composite ORDER BY value, enabled""") self.assertEqual([('42', 1), ('42', 1), ('43', 0), ('43', 0)], rows)
class MySQLConnectionTestCase(unittest.TestCase): def setUp(self): self.env = EnvironmentStub() self.schema = [ Table('test_simple', key='id')[Column('id', auto_increment=True), Column('username'), Column('email'), Column('enabled', type='int'), Column('extra'), Index(['username'], unique=True), Index(['email'], unique=False), ], Table('test_composite', key=['id', 'name'])[Column('id', type='int'), Column('name'), Column('value'), Column('enabled', type='int'), Index(['name', 'value'], unique=False), Index(['name', 'enabled'], unique=True), ], ] self.dbm = DatabaseManager(self.env) self.dbm.drop_tables(self.schema) self.dbm.create_tables(self.schema) self.dbm.insert_into_tables([ ('test_simple', ('username', 'email', 'enabled'), [('joe', '*****@*****.**', 1), ('joé', '*****@*****.**', 0)]), ('test_composite', ('id', 'name', 'value', 'enabled'), [(1, 'foo', '42', 1), (1, 'bar', '42', 1), (2, 'foo', '43', 0), (2, 'bar', '43', 0)]), ]) def tearDown(self): DatabaseManager(self.env).drop_tables(self.schema) self.env.reset_db() def _show_index(self, table): with self.env.db_query as db: cursor = db.cursor() cursor.execute("SHOW INDEX FROM " + db.quote(table)) columns = get_column_names(cursor) rows = [dict(zip(columns, row)) for row in cursor] results = {} for index, group in itertools.groupby(rows, lambda v: v['Key_name']): group = list(group) results[index] = { 'unique': not group[0]['Non_unique'], 'columns': [row['Column_name'] for row in group], } return results def _drop_column(self, table, column): with self.env.db_transaction as db: db.drop_column(table, column) def _query(self, stmt, *args): return self.env.db_query(stmt, args) def test_remove_simple_keys(self): indices_0 = self._show_index('test_simple') self.assertEqual( ['PRIMARY', 'test_simple_email_idx', 'test_simple_username_idx'], sorted(indices_0)) self.assertEqual({ 'unique': True, 'columns': ['id'] }, indices_0['PRIMARY']) self.assertEqual({ 'unique': True, 'columns': ['username'] }, indices_0['test_simple_username_idx']) self.assertEqual({ 'unique': False, 'columns': ['email'] }, indices_0['test_simple_email_idx']) self._drop_column('test_simple', 'enabled') self.assertEqual(indices_0, self._show_index('test_simple')) self._drop_column('test_simple', 'username') indices_1 = self._show_index('test_simple') self.assertEqual(['PRIMARY', 'test_simple_email_idx'], sorted(indices_1)) self._drop_column('test_simple', 'email') indices_2 = self._show_index('test_simple') self.assertEqual(['PRIMARY'], sorted(indices_2)) self._drop_column('test_simple', 'id') indices_3 = self._show_index('test_simple') self.assertEqual({}, indices_3) def test_remove_composite_keys(self): indices_0 = self._show_index('test_composite') self.assertEqual([ 'PRIMARY', 'test_composite_name_enabled_idx', 'test_composite_name_value_idx' ], sorted(indices_0)) self.assertEqual({ 'unique': True, 'columns': ['id', 'name'] }, indices_0['PRIMARY']) self.assertEqual({ 'unique': False, 'columns': ['name', 'value'] }, indices_0['test_composite_name_value_idx']) self.assertEqual({ 'unique': True, 'columns': ['name', 'enabled'] }, indices_0['test_composite_name_enabled_idx']) self._drop_column('test_composite', 'id') indices_1 = self._show_index('test_composite') self.assertEqual([ 'test_composite_name_enabled_idx', 'test_composite_name_value_idx' ], sorted(indices_1)) self.assertEqual(indices_0['test_composite_name_value_idx'], indices_1['test_composite_name_value_idx']) self.assertEqual(indices_0['test_composite_name_enabled_idx'], indices_1['test_composite_name_enabled_idx']) rows = self._query("""SELECT * FROM test_composite ORDER BY name, value, enabled""") self.assertEqual([('bar', '42', 1), ('bar', '43', 0), ('foo', '42', 1), ('foo', '43', 0)], rows) self._drop_column('test_composite', 'name') self.assertEqual({}, self._show_index('test_composite')) rows = self._query("""SELECT * FROM test_composite ORDER BY value, enabled""") self.assertEqual([('42', 1), ('42', 1), ('43', 0), ('43', 0)], rows)