diff options
author | Jim Rollenhagen <jim@jimrollenhagen.com> | 2019-09-26 09:56:42 -0400 |
---|---|---|
committer | Jim Rollenhagen <jim@jimrollenhagen.com> | 2019-09-26 09:56:42 -0400 |
commit | 52672a64cc0cab4ea14a4a756fce850eb03315e3 (patch) | |
tree | a86024e4e6141aa8983c750f751c58d924f5b11a /migrate/tests/changeset | |
parent | 8acab2cd75a5b23ac162e49c8e4fb1e3f958352a (diff) | |
download | sqlalchemy-migrate-master.tar.gz |
Diffstat (limited to 'migrate/tests/changeset')
-rw-r--r-- | migrate/tests/changeset/__init__.py | 0 | ||||
-rw-r--r-- | migrate/tests/changeset/databases/__init__.py | 0 | ||||
-rw-r--r-- | migrate/tests/changeset/databases/test_ibmdb2.py | 32 | ||||
-rw-r--r-- | migrate/tests/changeset/test_changeset.py | 976 | ||||
-rw-r--r-- | migrate/tests/changeset/test_constraint.py | 299 |
5 files changed, 0 insertions, 1307 deletions
diff --git a/migrate/tests/changeset/__init__.py b/migrate/tests/changeset/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/migrate/tests/changeset/__init__.py +++ /dev/null diff --git a/migrate/tests/changeset/databases/__init__.py b/migrate/tests/changeset/databases/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/migrate/tests/changeset/databases/__init__.py +++ /dev/null diff --git a/migrate/tests/changeset/databases/test_ibmdb2.py b/migrate/tests/changeset/databases/test_ibmdb2.py deleted file mode 100644 index 4b3f983..0000000 --- a/migrate/tests/changeset/databases/test_ibmdb2.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import mock - -import six - -from migrate.changeset.databases import ibmdb2 -from migrate.tests import fixture - - -class TestIBMDBDialect(fixture.Base): - """ - Test class for ibmdb2 dialect unit tests which do not require - a live backend database connection. - """ - - def test_is_unique_constraint_with_null_cols_supported(self): - test_values = { - '10.1': False, - '10.4.99': False, - '10.5': True, - '10.5.1': True - } - for version, supported in six.iteritems(test_values): - mock_dialect = mock.MagicMock() - mock_dialect.dbms_ver = version - self.assertEqual( - supported, - ibmdb2.is_unique_constraint_with_null_columns_supported( - mock_dialect), - 'Assertion failed on version: %s' % version) diff --git a/migrate/tests/changeset/test_changeset.py b/migrate/tests/changeset/test_changeset.py deleted file mode 100644 index c870c52..0000000 --- a/migrate/tests/changeset/test_changeset.py +++ /dev/null @@ -1,976 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -import sqlalchemy -import warnings - -from sqlalchemy import * - -from migrate import changeset, exceptions -from migrate.changeset import * -from migrate.changeset import constraint -from migrate.changeset.schema import ColumnDelta -from migrate.tests import fixture -from migrate.tests.fixture.warnings import catch_warnings -import six - -class TestAddDropColumn(fixture.DB): - """Test add/drop column through all possible interfaces - also test for constraints - """ - level = fixture.DB.CONNECT - table_name = 'tmp_adddropcol' - table_name_idx = 'tmp_adddropcol_idx' - table_int = 0 - - def _setup(self, url): - super(TestAddDropColumn, self)._setup(url) - self.meta = MetaData() - self.table = Table(self.table_name, self.meta, - Column('id', Integer, unique=True), - ) - self.table_idx = Table( - self.table_name_idx, - self.meta, - Column('id', Integer, primary_key=True), - Column('a', Integer), - Column('b', Integer), - Index('test_idx', 'a', 'b') - ) - self.meta.bind = self.engine - if self.engine.has_table(self.table.name): - self.table.drop() - if self.engine.has_table(self.table_idx.name): - self.table_idx.drop() - self.table.create() - self.table_idx.create() - - def _teardown(self): - if self.engine.has_table(self.table.name): - self.table.drop() - if self.engine.has_table(self.table_idx.name): - self.table_idx.drop() - self.meta.clear() - super(TestAddDropColumn,self)._teardown() - - def run_(self, create_column_func, drop_column_func, *col_p, **col_k): - col_name = 'data' - - def assert_numcols(num_of_expected_cols): - # number of cols should be correct in table object and in database - self.refresh_table(self.table_name) - result = len(self.table.c) - - self.assertEqual(result, num_of_expected_cols), - if col_k.get('primary_key', None): - # new primary key: check its length too - result = len(self.table.primary_key) - self.assertEqual(result, num_of_expected_cols) - - # we have 1 columns and there is no data column - assert_numcols(1) - self.assertTrue(getattr(self.table.c, 'data', None) is None) - if len(col_p) == 0: - col_p = [String(40)] - col = Column(col_name, *col_p, **col_k) - create_column_func(col) - assert_numcols(2) - # data column exists - self.assertTrue(self.table.c.data.type.length, 40) - - col2 = self.table.c.data - drop_column_func(col2) - assert_numcols(1) - - @fixture.usedb() - def test_undefined(self): - """Add/drop columns not yet defined in the table""" - def add_func(col): - return create_column(col, self.table) - def drop_func(col): - return drop_column(col, self.table) - return self.run_(add_func, drop_func) - - @fixture.usedb() - def test_defined(self): - """Add/drop columns already defined in the table""" - def add_func(col): - self.meta.clear() - self.table = Table(self.table_name, self.meta, - Column('id', Integer, primary_key=True), - col, - ) - return create_column(col) - def drop_func(col): - return drop_column(col) - return self.run_(add_func, drop_func) - - @fixture.usedb() - def test_method_bound(self): - """Add/drop columns via column methods; columns bound to a table - ie. no table parameter passed to function - """ - def add_func(col): - self.assertTrue(col.table is None, col.table) - self.table.append_column(col) - return col.create() - def drop_func(col): - #self.assertTrue(col.table is None,col.table) - #self.table.append_column(col) - return col.drop() - return self.run_(add_func, drop_func) - - @fixture.usedb() - def test_method_notbound(self): - """Add/drop columns via column methods; columns not bound to a table""" - def add_func(col): - return col.create(self.table) - def drop_func(col): - return col.drop(self.table) - return self.run_(add_func, drop_func) - - @fixture.usedb() - def test_tablemethod_obj(self): - """Add/drop columns via table methods; by column object""" - def add_func(col): - return self.table.create_column(col) - def drop_func(col): - return self.table.drop_column(col) - return self.run_(add_func, drop_func) - - @fixture.usedb() - def test_tablemethod_name(self): - """Add/drop columns via table methods; by column name""" - def add_func(col): - # must be bound to table - self.table.append_column(col) - return self.table.create_column(col.name) - def drop_func(col): - # Not necessarily bound to table - return self.table.drop_column(col.name) - return self.run_(add_func, drop_func) - - @fixture.usedb() - def test_byname(self): - """Add/drop columns via functions; by table object and column name""" - def add_func(col): - self.table.append_column(col) - return create_column(col.name, self.table) - def drop_func(col): - return drop_column(col.name, self.table) - return self.run_(add_func, drop_func) - - @fixture.usedb() - def test_drop_column_not_in_table(self): - """Drop column by name""" - def add_func(col): - return self.table.create_column(col) - def drop_func(col): - if SQLA_07: - self.table._columns.remove(col) - else: - self.table.c.remove(col) - return self.table.drop_column(col.name) - self.run_(add_func, drop_func) - - @fixture.usedb() - def test_fk(self): - """Can create columns with foreign keys""" - # create FK's target - reftable = Table('tmp_ref', self.meta, - Column('id', Integer, primary_key=True), - ) - if self.engine.has_table(reftable.name): - reftable.drop() - reftable.create() - - # create column with fk - col = Column('data', Integer, ForeignKey(reftable.c.id, name='testfk')) - col.create(self.table) - - # check if constraint is added - for cons in self.table.constraints: - if isinstance(cons, sqlalchemy.schema.ForeignKeyConstraint): - break - else: - self.fail('No constraint found') - - # TODO: test on db level if constraints work - - if SQLA_07: - self.assertEqual(reftable.c.id.name, - list(col.foreign_keys)[0].column.name) - else: - self.assertEqual(reftable.c.id.name, - col.foreign_keys[0].column.name) - - if self.engine.name == 'mysql': - constraint.ForeignKeyConstraint([self.table.c.data], - [reftable.c.id], - name='testfk').drop() - col.drop(self.table) - - if self.engine.has_table(reftable.name): - reftable.drop() - - @fixture.usedb(not_supported='sqlite') - def test_pk(self): - """Can create columns with primary key""" - col = Column('data', Integer, nullable=False) - self.assertRaises(exceptions.InvalidConstraintError, - col.create, self.table, primary_key_name=True) - col.create(self.table, primary_key_name='data_pkey') - - # check if constraint was added (cannot test on objects) - self.table.insert(values={'data': 4}).execute() - try: - self.table.insert(values={'data': 4}).execute() - except (sqlalchemy.exc.IntegrityError, - sqlalchemy.exc.ProgrammingError): - pass - else: - self.fail() - - col.drop() - - @fixture.usedb(not_supported=['mysql']) - def test_check(self): - """Can create columns with check constraint""" - col = Column('foo', - Integer, - sqlalchemy.schema.CheckConstraint('foo > 4')) - col.create(self.table) - - # check if constraint was added (cannot test on objects) - self.table.insert(values={'foo': 5}).execute() - try: - self.table.insert(values={'foo': 3}).execute() - except (sqlalchemy.exc.IntegrityError, - sqlalchemy.exc.ProgrammingError): - pass - else: - self.fail() - - col.drop() - - @fixture.usedb() - def test_unique_constraint(self): - self.assertRaises(exceptions.InvalidConstraintError, - Column('data', Integer, unique=True).create, self.table) - - col = Column('data', Integer) - col.create(self.table, unique_name='data_unique') - - # check if constraint was added (cannot test on objects) - self.table.insert(values={'data': 5}).execute() - try: - self.table.insert(values={'data': 5}).execute() - except (sqlalchemy.exc.IntegrityError, - sqlalchemy.exc.ProgrammingError): - pass - else: - self.fail() - - col.drop(self.table) - -# TODO: remove already attached columns with uniques, pks, fks .. - @fixture.usedb(not_supported=['ibm_db_sa', 'postgresql']) - def test_drop_column_of_composite_index(self): - # NOTE(rpodolyaka): postgresql automatically drops a composite index - # if one of its columns is dropped - # NOTE(mriedem): DB2 does the same. - self.table_idx.c.b.drop() - - reflected = Table(self.table_idx.name, MetaData(), autoload=True, - autoload_with=self.engine) - index = next(iter(reflected.indexes)) - self.assertEquals(['a'], [c.name for c in index.columns]) - - @fixture.usedb() - def test_drop_all_columns_of_composite_index(self): - self.table_idx.c.a.drop() - self.table_idx.c.b.drop() - - reflected = Table(self.table_idx.name, MetaData(), autoload=True, - autoload_with=self.engine) - self.assertEquals(0, len(reflected.indexes)) - - def _check_index(self,expected): - if 'mysql' in self.engine.name or 'postgres' in self.engine.name: - for index in tuple( - Table(self.table.name, MetaData(), - autoload=True, autoload_with=self.engine).indexes - ): - if index.name=='ix_data': - break - self.assertEqual(expected,index.unique) - - @fixture.usedb() - def test_index(self): - col = Column('data', Integer) - col.create(self.table, index_name='ix_data') - - self._check_index(False) - - col.drop() - - @fixture.usedb() - def test_index_unique(self): - # shows how to create a unique index - col = Column('data', Integer) - col.create(self.table) - Index('ix_data', col, unique=True).create(bind=self.engine) - - # check if index was added - self.table.insert(values={'data': 5}).execute() - try: - self.table.insert(values={'data': 5}).execute() - except (sqlalchemy.exc.IntegrityError, - sqlalchemy.exc.ProgrammingError): - pass - else: - self.fail() - - self._check_index(True) - - col.drop() - - @fixture.usedb() - def test_server_defaults(self): - """Can create columns with server_default values""" - col = Column('data', String(244), server_default='foobar') - col.create(self.table) - - self.table.insert(values={'id': 10}).execute() - row = self._select_row() - self.assertEqual(u'foobar', row['data']) - - col.drop() - - @fixture.usedb() - def test_populate_default(self): - """Test populate_default=True""" - def default(): - return 'foobar' - col = Column('data', String(244), default=default) - col.create(self.table, populate_default=True) - - self.table.insert(values={'id': 10}).execute() - row = self._select_row() - self.assertEqual(u'foobar', row['data']) - - col.drop() - - # TODO: test sequence - # TODO: test quoting - # TODO: test non-autoname constraints - - @fixture.usedb() - def test_drop_doesnt_delete_other_indexes(self): - # add two indexed columns - self.table.drop() - self.meta.clear() - self.table = Table( - self.table_name, self.meta, - Column('id', Integer, primary_key=True), - Column('d1', String(10), index=True), - Column('d2', String(10), index=True), - ) - self.table.create() - - # paranoid check - self.refresh_table() - self.assertEqual( - sorted([i.name for i in self.table.indexes]), - [u'ix_tmp_adddropcol_d1', u'ix_tmp_adddropcol_d2'] - ) - - # delete one - self.table.c.d2.drop() - - # ensure the other index is still there - self.refresh_table() - self.assertEqual( - sorted([i.name for i in self.table.indexes]), - [u'ix_tmp_adddropcol_d1'] - ) - - def _actual_foreign_keys(self): - from sqlalchemy.schema import ForeignKeyConstraint - result = [] - for cons in self.table.constraints: - if isinstance(cons,ForeignKeyConstraint): - col_names = [] - for col_name in cons.columns: - if not isinstance(col_name,six.string_types): - col_name = col_name.name - col_names.append(col_name) - result.append(col_names) - result.sort() - return result - - @fixture.usedb() - def test_drop_with_foreign_keys(self): - self.table.drop() - self.meta.clear() - - # create FK's target - reftable = Table('tmp_ref', self.meta, - Column('id', Integer, primary_key=True), - ) - if self.engine.has_table(reftable.name): - reftable.drop() - reftable.create() - - # add a table with two foreign key columns - self.table = Table( - self.table_name, self.meta, - Column('id', Integer, primary_key=True), - Column('r1', Integer, ForeignKey('tmp_ref.id', name='test_fk1')), - Column('r2', Integer, ForeignKey('tmp_ref.id', name='test_fk2')), - ) - self.table.create() - - # paranoid check - self.assertEqual([['r1'],['r2']], - self._actual_foreign_keys()) - - # delete one - if self.engine.name == 'mysql': - constraint.ForeignKeyConstraint([self.table.c.r2], [reftable.c.id], - name='test_fk2').drop() - self.table.c.r2.drop() - - # check remaining foreign key is there - self.assertEqual([['r1']], - self._actual_foreign_keys()) - - @fixture.usedb() - def test_drop_with_complex_foreign_keys(self): - from sqlalchemy.schema import ForeignKeyConstraint - from sqlalchemy.schema import UniqueConstraint - - self.table.drop() - self.meta.clear() - - # NOTE(mriedem): DB2 does not currently support unique constraints - # on nullable columns, so the columns that are used to create the - # foreign keys here need to be non-nullable for testing with DB2 - # to work. - - # create FK's target - reftable = Table('tmp_ref', self.meta, - Column('id', Integer, primary_key=True), - Column('jd', Integer, nullable=False), - UniqueConstraint('id','jd') - ) - if self.engine.has_table(reftable.name): - reftable.drop() - reftable.create() - - # add a table with a complex foreign key constraint - self.table = Table( - self.table_name, self.meta, - Column('id', Integer, primary_key=True), - Column('r1', Integer, nullable=False), - Column('r2', Integer, nullable=False), - ForeignKeyConstraint(['r1','r2'], - [reftable.c.id,reftable.c.jd], - name='test_fk') - ) - self.table.create() - - # paranoid check - self.assertEqual([['r1','r2']], - self._actual_foreign_keys()) - - # delete one - if self.engine.name == 'mysql': - constraint.ForeignKeyConstraint([self.table.c.r1, self.table.c.r2], - [reftable.c.id, reftable.c.jd], - name='test_fk').drop() - self.table.c.r2.drop() - - # check the constraint is gone, since part of it - # is no longer there - if people hit this, - # they may be confused, maybe we should raise an error - # and insist that the constraint is deleted first, separately? - self.assertEqual([], - self._actual_foreign_keys()) - -class TestRename(fixture.DB): - """Tests for table and index rename methods""" - level = fixture.DB.CONNECT - meta = MetaData() - - def _setup(self, url): - super(TestRename, self)._setup(url) - self.meta.bind = self.engine - - @fixture.usedb(not_supported='firebird') - def test_rename_table(self): - """Tables can be renamed""" - c_name = 'col_1' - table_name1 = 'name_one' - table_name2 = 'name_two' - index_name1 = 'x' + table_name1 - index_name2 = 'x' + table_name2 - - self.meta.clear() - self.column = Column(c_name, Integer) - self.table = Table(table_name1, self.meta, self.column) - self.index = Index(index_name1, self.column, unique=False) - - if self.engine.has_table(self.table.name): - self.table.drop() - if self.engine.has_table(table_name2): - tmp = Table(table_name2, self.meta, autoload=True) - tmp.drop() - tmp.deregister() - del tmp - self.table.create() - - def assert_table_name(expected, skip_object_check=False): - """Refresh a table via autoload - SA has changed some since this test was written; we now need to do - meta.clear() upon reloading a table - clear all rather than a - select few. So, this works only if we're working with one table at - a time (else, others will vanish too). - """ - if not skip_object_check: - # Table object check - self.assertEqual(self.table.name,expected) - newname = self.table.name - else: - # we know the object's name isn't consistent: just assign it - newname = expected - # Table DB check - self.meta.clear() - self.table = Table(newname, self.meta, autoload=True) - self.assertEqual(self.table.name, expected) - - def assert_index_name(expected, skip_object_check=False): - if not skip_object_check: - # Index object check - self.assertEqual(self.index.name, expected) - else: - # object is inconsistent - self.index.name = expected - # TODO: Index DB check - - def add_table_to_meta(name): - # trigger the case where table_name2 needs to be - # removed from the metadata in ChangesetTable.deregister() - tmp = Table(name, self.meta, Column(c_name, Integer)) - tmp.create() - tmp.drop() - - try: - # Table renames - assert_table_name(table_name1) - add_table_to_meta(table_name2) - rename_table(self.table, table_name2) - assert_table_name(table_name2) - self.table.rename(table_name1) - assert_table_name(table_name1) - - # test by just the string - rename_table(table_name1, table_name2, engine=self.engine) - assert_table_name(table_name2, True) # object not updated - - # Index renames - if self.url.startswith('sqlite') or self.url.startswith('mysql'): - self.assertRaises(exceptions.NotSupportedError, - self.index.rename, index_name2) - else: - assert_index_name(index_name1) - rename_index(self.index, index_name2, engine=self.engine) - assert_index_name(index_name2) - self.index.rename(index_name1) - assert_index_name(index_name1) - - # test by just the string - rename_index(index_name1, index_name2, engine=self.engine) - assert_index_name(index_name2, True) - - finally: - if self.table.exists(): - self.table.drop() - - -class TestColumnChange(fixture.DB): - level = fixture.DB.CONNECT - table_name = 'tmp_colchange' - - def _setup(self, url): - super(TestColumnChange, self)._setup(url) - self.meta = MetaData(self.engine) - self.table = Table(self.table_name, self.meta, - Column('id', Integer, primary_key=True), - Column('data', String(40), server_default=DefaultClause("tluafed"), - nullable=True), - ) - if self.table.exists(): - self.table.drop() - try: - self.table.create() - except sqlalchemy.exc.SQLError: - # SQLite: database schema has changed - if not self.url.startswith('sqlite://'): - raise - - def _teardown(self): - if self.table.exists(): - try: - self.table.drop(self.engine) - except sqlalchemy.exc.SQLError: - # SQLite: database schema has changed - if not self.url.startswith('sqlite://'): - raise - super(TestColumnChange, self)._teardown() - - @fixture.usedb() - def test_rename(self): - """Can rename a column""" - def num_rows(col, content): - return len(list(self.table.select(col == content).execute())) - # Table content should be preserved in changed columns - content = "fgsfds" - self.engine.execute(self.table.insert(), data=content, id=42) - self.assertEqual(num_rows(self.table.c.data, content), 1) - - # ...as a function, given a column object and the new name - alter_column('data', name='data2', table=self.table) - self.refresh_table() - alter_column(self.table.c.data2, name='atad') - self.refresh_table(self.table.name) - self.assertTrue('data' not in self.table.c.keys()) - self.assertTrue('atad' in self.table.c.keys()) - self.assertEqual(num_rows(self.table.c.atad, content), 1) - - # ...as a method, given a new name - self.table.c.atad.alter(name='data') - self.refresh_table(self.table.name) - self.assertTrue('atad' not in self.table.c.keys()) - self.table.c.data # Should not raise exception - self.assertEqual(num_rows(self.table.c.data, content), 1) - - # ...as a function, given a new object - alter_column(self.table.c.data, - name = 'atad', type=String(40), - server_default=self.table.c.data.server_default) - self.refresh_table(self.table.name) - self.assertTrue('data' not in self.table.c.keys()) - self.table.c.atad # Should not raise exception - self.assertEqual(num_rows(self.table.c.atad, content), 1) - - # ...as a method, given a new object - self.table.c.atad.alter( - name='data',type=String(40), - server_default=self.table.c.atad.server_default - ) - self.refresh_table(self.table.name) - self.assertTrue('atad' not in self.table.c.keys()) - self.table.c.data # Should not raise exception - self.assertEqual(num_rows(self.table.c.data,content), 1) - - @fixture.usedb() - def test_type(self): - # Test we can change a column's type - - # Just the new type - self.table.c.data.alter(type=String(43)) - self.refresh_table(self.table.name) - self.assertTrue(isinstance(self.table.c.data.type, String)) - self.assertEqual(self.table.c.data.type.length, 43) - - # Different type - self.assertTrue(isinstance(self.table.c.id.type, Integer)) - self.assertEqual(self.table.c.id.nullable, False) - - # SQLAlchemy 1.1 adds a third state to "autoincrement" called - # "auto". - self.assertTrue(self.table.c.id.autoincrement in ('auto', True)) - - if not self.engine.name == 'firebird': - self.table.c.id.alter(type=String(20)) - self.assertEqual(self.table.c.id.nullable, False) - - # a rule makes sure that autoincrement is set to False - # when we change off of Integer - self.assertEqual(self.table.c.id.autoincrement, False) - self.refresh_table(self.table.name) - self.assertTrue(isinstance(self.table.c.id.type, String)) - - # note that after reflection, "autoincrement" is likely - # to change back to a database-generated value. Should be - # False or "auto". if True, it's a bug; at least one of these - # exists prior to SQLAlchemy 1.1.3 - - @fixture.usedb() - def test_default(self): - """Can change a column's server_default value (DefaultClauses only) - Only DefaultClauses are changed here: others are managed by the - application / by SA - """ - self.assertEqual(self.table.c.data.server_default.arg, 'tluafed') - - # Just the new default - default = 'my_default' - self.table.c.data.alter(server_default=DefaultClause(default)) - self.refresh_table(self.table.name) - #self.assertEqual(self.table.c.data.server_default.arg,default) - # TextClause returned by autoload - self.assertTrue(default in str(self.table.c.data.server_default.arg)) - self.engine.execute(self.table.insert(), id=12) - row = self._select_row() - self.assertEqual(row['data'], default) - - # Column object - default = 'your_default' - self.table.c.data.alter(type=String(40), server_default=DefaultClause(default)) - self.refresh_table(self.table.name) - self.assertTrue(default in str(self.table.c.data.server_default.arg)) - - # Drop/remove default - self.table.c.data.alter(server_default=None) - self.assertEqual(self.table.c.data.server_default, None) - - self.refresh_table(self.table.name) - # server_default isn't necessarily None for Oracle - #self.assertTrue(self.table.c.data.server_default is None,self.table.c.data.server_default) - self.engine.execute(self.table.insert(), id=11) - row = self.table.select(self.table.c.id == 11).execution_options(autocommit=True).execute().fetchone() - self.assertTrue(row['data'] is None, row['data']) - - @fixture.usedb(not_supported='firebird') - def test_null(self): - """Can change a column's null constraint""" - self.assertEqual(self.table.c.data.nullable, True) - - # Full column - self.table.c.data.alter(type=String(40), nullable=False) - self.table.nullable = None - self.refresh_table(self.table.name) - self.assertEqual(self.table.c.data.nullable, False) - - # Just the new status - self.table.c.data.alter(nullable=True) - self.refresh_table(self.table.name) - self.assertEqual(self.table.c.data.nullable, True) - - @fixture.usedb() - def test_alter_deprecated(self): - try: - # py 2.4 compatibility :-/ - cw = catch_warnings(record=True) - w = cw.__enter__() - - warnings.simplefilter("always") - self.table.c.data.alter(Column('data', String(100))) - - self.assertEqual(len(w),1) - self.assertTrue(issubclass(w[-1].category, - MigrateDeprecationWarning)) - self.assertEqual( - 'Passing a Column object to alter_column is deprecated. ' - 'Just pass in keyword parameters instead.', - str(w[-1].message)) - finally: - cw.__exit__() - - @fixture.usedb() - def test_alter_returns_delta(self): - """Test if alter constructs return delta""" - - delta = self.table.c.data.alter(type=String(100)) - self.assertTrue('type' in delta) - - @fixture.usedb() - def test_alter_all(self): - """Tests all alter changes at one time""" - # test for each db separately - # since currently some dont support everything - - # test pre settings - self.assertEqual(self.table.c.data.nullable, True) - self.assertEqual(self.table.c.data.server_default.arg, 'tluafed') - self.assertEqual(self.table.c.data.name, 'data') - self.assertTrue(isinstance(self.table.c.data.type, String)) - self.assertTrue(self.table.c.data.type.length, 40) - - kw = dict(nullable=False, - server_default='foobar', - name='data_new', - type=String(50)) - if self.engine.name == 'firebird': - del kw['nullable'] - self.table.c.data.alter(**kw) - - # test altered objects - self.assertEqual(self.table.c.data.server_default.arg, 'foobar') - if not self.engine.name == 'firebird': - self.assertEqual(self.table.c.data.nullable, False) - self.assertEqual(self.table.c.data.name, 'data_new') - self.assertEqual(self.table.c.data.type.length, 50) - - self.refresh_table(self.table.name) - - # test post settings - if not self.engine.name == 'firebird': - self.assertEqual(self.table.c.data_new.nullable, False) - self.assertEqual(self.table.c.data_new.name, 'data_new') - self.assertTrue(isinstance(self.table.c.data_new.type, String)) - self.assertTrue(self.table.c.data_new.type.length, 50) - - # insert data and assert default - self.table.insert(values={'id': 10}).execute() - row = self._select_row() - self.assertEqual(u'foobar', row['data_new']) - - -class TestColumnDelta(fixture.DB): - """Tests ColumnDelta class""" - - level = fixture.DB.CONNECT - table_name = 'tmp_coldelta' - table_int = 0 - - def _setup(self, url): - super(TestColumnDelta, self)._setup(url) - self.meta = MetaData() - self.table = Table(self.table_name, self.meta, - Column('ids', String(10)), - ) - self.meta.bind = self.engine - if self.engine.has_table(self.table.name): - self.table.drop() - self.table.create() - - def _teardown(self): - if self.engine.has_table(self.table.name): - self.table.drop() - self.meta.clear() - super(TestColumnDelta,self)._teardown() - - def mkcol(self, name='id', type=String, *p, **k): - return Column(name, type, *p, **k) - - def verify(self, expected, original, *p, **k): - self.delta = ColumnDelta(original, *p, **k) - result = list(self.delta.keys()) - result.sort() - self.assertEqual(expected, result) - return self.delta - - def test_deltas_two_columns(self): - """Testing ColumnDelta with two columns""" - col_orig = self.mkcol(primary_key=True) - col_new = self.mkcol(name='ids', primary_key=True) - self.verify([], col_orig, col_orig) - self.verify(['name'], col_orig, col_orig, 'ids') - self.verify(['name'], col_orig, col_orig, name='ids') - self.verify(['name'], col_orig, col_new) - self.verify(['name', 'type'], col_orig, col_new, type=String) - - # Type comparisons - self.verify([], self.mkcol(type=String), self.mkcol(type=String)) - self.verify(['type'], self.mkcol(type=String), self.mkcol(type=Integer)) - self.verify(['type'], self.mkcol(type=String), self.mkcol(type=String(42))) - self.verify([], self.mkcol(type=String(42)), self.mkcol(type=String(42))) - self.verify(['type'], self.mkcol(type=String(24)), self.mkcol(type=String(42))) - self.verify(['type'], self.mkcol(type=String(24)), self.mkcol(type=Text(24))) - - # Other comparisons - self.verify(['primary_key'], self.mkcol(nullable=False), self.mkcol(primary_key=True)) - - # PK implies nullable=False - self.verify(['nullable', 'primary_key'], self.mkcol(nullable=True), self.mkcol(primary_key=True)) - self.verify([], self.mkcol(primary_key=True), self.mkcol(primary_key=True)) - self.verify(['nullable'], self.mkcol(nullable=True), self.mkcol(nullable=False)) - self.verify([], self.mkcol(nullable=True), self.mkcol(nullable=True)) - self.verify([], self.mkcol(server_default=None), self.mkcol(server_default=None)) - self.verify([], self.mkcol(server_default='42'), self.mkcol(server_default='42')) - - # test server default - delta = self.verify(['server_default'], self.mkcol(), self.mkcol('id', String, DefaultClause('foobar'))) - self.assertEqual(delta['server_default'].arg, 'foobar') - - self.verify([], self.mkcol(server_default='foobar'), self.mkcol('id', String, DefaultClause('foobar'))) - self.verify(['type'], self.mkcol(server_default='foobar'), self.mkcol('id', Text, DefaultClause('foobar'))) - - col = self.mkcol(server_default='foobar') - self.verify(['type'], col, self.mkcol('id', Text, DefaultClause('foobar')), alter_metadata=True) - self.assertTrue(isinstance(col.type, Text)) - - col = self.mkcol() - self.verify(['name', 'server_default', 'type'], col, self.mkcol('beep', Text, DefaultClause('foobar')), - alter_metadata=True) - self.assertTrue(isinstance(col.type, Text)) - self.assertEqual(col.name, 'beep') - self.assertEqual(col.server_default.arg, 'foobar') - - @fixture.usedb() - def test_deltas_zero_columns(self): - """Testing ColumnDelta with zero columns""" - - self.verify(['name'], 'ids', table=self.table, name='hey') - - # test reflection - self.verify(['type'], 'ids', table=self.table.name, type=String(80), engine=self.engine) - self.verify(['type'], 'ids', table=self.table.name, type=String(80), metadata=self.meta) - - self.meta.clear() - delta = self.verify(['type'], 'ids', table=self.table.name, type=String(80), metadata=self.meta, - alter_metadata=True) - self.assertTrue(self.table.name in self.meta) - self.assertEqual(delta.result_column.type.length, 80) - self.assertEqual(self.meta.tables.get(self.table.name).c.ids.type.length, 80) - - # test defaults - self.meta.clear() - self.verify(['server_default'], 'ids', table=self.table.name, server_default='foobar', - metadata=self.meta, - alter_metadata=True) - self.meta.tables.get(self.table.name).c.ids.server_default.arg == 'foobar' - - # test missing parameters - self.assertRaises(ValueError, ColumnDelta, table=self.table.name) - self.assertRaises(ValueError, ColumnDelta, 'ids', table=self.table.name, alter_metadata=True) - self.assertRaises(ValueError, ColumnDelta, 'ids', table=self.table.name, alter_metadata=False) - - def test_deltas_one_column(self): - """Testing ColumnDelta with one column""" - col_orig = self.mkcol(primary_key=True) - - self.verify([], col_orig) - self.verify(['name'], col_orig, 'ids') - # Parameters are always executed, even if they're 'unchanged' - # (We can't assume given column is up-to-date) - self.verify(['name', 'primary_key', 'type'], col_orig, 'id', Integer, primary_key=True) - self.verify(['name', 'primary_key', 'type'], col_orig, name='id', type=Integer, primary_key=True) - - # Change name, given an up-to-date definition and the current name - delta = self.verify(['name'], col_orig, name='blah') - self.assertEqual(delta.get('name'), 'blah') - self.assertEqual(delta.current_name, 'id') - - col_orig = self.mkcol(primary_key=True) - self.verify(['name', 'type'], col_orig, name='id12', type=Text, alter_metadata=True) - self.assertTrue(isinstance(col_orig.type, Text)) - self.assertEqual(col_orig.name, 'id12') - - # test server default - col_orig = self.mkcol(primary_key=True) - delta = self.verify(['server_default'], col_orig, DefaultClause('foobar')) - self.assertEqual(delta['server_default'].arg, 'foobar') - - delta = self.verify(['server_default'], col_orig, server_default=DefaultClause('foobar')) - self.assertEqual(delta['server_default'].arg, 'foobar') - - # no change - col_orig = self.mkcol(server_default=DefaultClause('foobar')) - delta = self.verify(['type'], col_orig, DefaultClause('foobar'), type=PickleType) - self.assertTrue(isinstance(delta.result_column.type, PickleType)) - - # TODO: test server on update - # TODO: test bind metadata diff --git a/migrate/tests/changeset/test_constraint.py b/migrate/tests/changeset/test_constraint.py deleted file mode 100644 index 325b3c0..0000000 --- a/migrate/tests/changeset/test_constraint.py +++ /dev/null @@ -1,299 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from sqlalchemy import * -from sqlalchemy.util import * -from sqlalchemy.exc import * - -from migrate.changeset.util import fk_column_names -from migrate.exceptions import * -from migrate.changeset import * - -from migrate.tests import fixture - - -class CommonTestConstraint(fixture.DB): - """helper functions to test constraints. - - we just create a fresh new table and make sure everything is - as required. - """ - - def _setup(self, url): - super(CommonTestConstraint, self)._setup(url) - self._create_table() - - def _teardown(self): - if hasattr(self, 'table') and self.engine.has_table(self.table.name): - self.table.drop() - super(CommonTestConstraint, self)._teardown() - - def _create_table(self): - self._connect(self.url) - self.meta = MetaData(self.engine) - self.tablename = 'mytable' - self.table = Table(self.tablename, self.meta, - Column(u'id', Integer, nullable=False), - Column(u'fkey', Integer, nullable=False), - mysql_engine='InnoDB') - if self.engine.has_table(self.table.name): - self.table.drop() - self.table.create() - - # make sure we start at zero - self.assertEqual(len(self.table.primary_key), 0) - self.assertTrue(isinstance(self.table.primary_key, - schema.PrimaryKeyConstraint), self.table.primary_key.__class__) - - -class TestConstraint(CommonTestConstraint): - level = fixture.DB.CONNECT - - def _define_pk(self, *cols): - # Add a pk by creating a PK constraint - if (self.engine.name in ('oracle', 'firebird')): - # Can't drop Oracle PKs without an explicit name - pk = PrimaryKeyConstraint(table=self.table, name='temp_pk_key', *cols) - else: - pk = PrimaryKeyConstraint(table=self.table, *cols) - self.compare_columns_equal(pk.columns, cols) - pk.create() - self.refresh_table() - if not self.url.startswith('sqlite'): - self.compare_columns_equal(self.table.primary_key, cols, ['type', 'autoincrement']) - - # Drop the PK constraint - #if (self.engine.name in ('oracle', 'firebird')): - # # Apparently Oracle PK names aren't introspected - # pk.name = self.table.primary_key.name - pk.drop() - self.refresh_table() - self.assertEqual(len(self.table.primary_key), 0) - self.assertTrue(isinstance(self.table.primary_key, schema.PrimaryKeyConstraint)) - return pk - - @fixture.usedb() - def test_define_fk(self): - """FK constraints can be defined, created, and dropped""" - # FK target must be unique - pk = PrimaryKeyConstraint(self.table.c.id, table=self.table, name="pkid") - pk.create() - - # Add a FK by creating a FK constraint - if SQLA_07: - self.assertEqual(list(self.table.c.fkey.foreign_keys), []) - else: - self.assertEqual(self.table.c.fkey.foreign_keys._list, []) - fk = ForeignKeyConstraint([self.table.c.fkey], - [self.table.c.id], - name="fk_id_fkey", - ondelete="CASCADE") - if SQLA_07: - self.assertTrue(list(self.table.c.fkey.foreign_keys) is not []) - else: - self.assertTrue(self.table.c.fkey.foreign_keys._list is not []) - for key in fk_column_names(fk): - self.assertEqual(key, self.table.c.fkey.name) - self.assertEqual([e.column for e in fk.elements], [self.table.c.id]) - self.assertEqual(list(fk.referenced), [self.table.c.id]) - - if self.url.startswith('mysql'): - # MySQL FKs need an index - index = Index('index_name', self.table.c.fkey) - index.create() - fk.create() - - # test for ondelete/onupdate - if SQLA_07: - fkey = list(self.table.c.fkey.foreign_keys)[0] - else: - fkey = self.table.c.fkey.foreign_keys._list[0] - self.assertEqual(fkey.ondelete, "CASCADE") - # TODO: test on real db if it was set - - self.refresh_table() - if SQLA_07: - self.assertTrue(list(self.table.c.fkey.foreign_keys) is not []) - else: - self.assertTrue(self.table.c.fkey.foreign_keys._list is not []) - - fk.drop() - self.refresh_table() - if SQLA_07: - self.assertEqual(list(self.table.c.fkey.foreign_keys), []) - else: - self.assertEqual(self.table.c.fkey.foreign_keys._list, []) - - @fixture.usedb() - def test_define_pk(self): - """PK constraints can be defined, created, and dropped""" - self._define_pk(self.table.c.fkey) - - @fixture.usedb() - def test_define_pk_multi(self): - """Multicolumn PK constraints can be defined, created, and dropped""" - self._define_pk(self.table.c.id, self.table.c.fkey) - - @fixture.usedb(not_supported=['firebird']) - def test_drop_cascade(self): - """Drop constraint cascaded""" - pk = PrimaryKeyConstraint('fkey', table=self.table, name="id_pkey") - pk.create() - self.refresh_table() - - # Drop the PK constraint forcing cascade - pk.drop(cascade=True) - - # TODO: add real assertion if it was added - - @fixture.usedb(supported=['mysql']) - def test_fail_mysql_check_constraints(self): - """Check constraints raise NotSupported for mysql on drop""" - cons = CheckConstraint('id > 3', name="id_check", table=self.table) - cons.create() - self.refresh_table() - - try: - cons.drop() - except NotSupportedError: - pass - else: - self.fail() - - @fixture.usedb(not_supported=['sqlite', 'mysql']) - def test_named_check_constraints(self): - """Check constraints can be defined, created, and dropped""" - self.assertRaises(InvalidConstraintError, CheckConstraint, 'id > 3') - cons = CheckConstraint('id > 3', name="id_check", table=self.table) - cons.create() - self.refresh_table() - - self.table.insert(values={'id': 4, 'fkey': 1}).execute() - try: - self.table.insert(values={'id': 1, 'fkey': 1}).execute() - except (IntegrityError, ProgrammingError): - pass - else: - self.fail() - - # Remove the name, drop the constraint; it should succeed - cons.drop() - self.refresh_table() - self.table.insert(values={'id': 2, 'fkey': 2}).execute() - self.table.insert(values={'id': 1, 'fkey': 2}).execute() - - -class TestAutoname(CommonTestConstraint): - """Every method tests for a type of constraint wether it can autoname - itself and if you can pass object instance and names to classes. - """ - level = fixture.DB.CONNECT - - @fixture.usedb(not_supported=['oracle', 'firebird']) - def test_autoname_pk(self): - """PrimaryKeyConstraints can guess their name if None is given""" - # Don't supply a name; it should create one - cons = PrimaryKeyConstraint(self.table.c.id) - cons.create() - self.refresh_table() - if not self.url.startswith('sqlite'): - # TODO: test for index for sqlite - self.compare_columns_equal(cons.columns, self.table.primary_key, ['autoincrement', 'type']) - - # Remove the name, drop the constraint; it should succeed - cons.name = None - cons.drop() - self.refresh_table() - self.assertEqual(list(), list(self.table.primary_key)) - - # test string names - cons = PrimaryKeyConstraint('id', table=self.table) - cons.create() - self.refresh_table() - if not self.url.startswith('sqlite'): - # TODO: test for index for sqlite - self.compare_columns_equal(cons.columns, self.table.primary_key) - cons.name = None - cons.drop() - - @fixture.usedb(not_supported=['oracle', 'sqlite', 'firebird']) - def test_autoname_fk(self): - """ForeignKeyConstraints can guess their name if None is given""" - cons = PrimaryKeyConstraint(self.table.c.id) - cons.create() - - cons = ForeignKeyConstraint([self.table.c.fkey], [self.table.c.id]) - cons.create() - self.refresh_table() - if SQLA_07: - list(self.table.c.fkey.foreign_keys)[0].column is self.table.c.id - else: - self.table.c.fkey.foreign_keys[0].column is self.table.c.id - - # Remove the name, drop the constraint; it should succeed - cons.name = None - cons.drop() - self.refresh_table() - if SQLA_07: - self.assertEqual(list(self.table.c.fkey.foreign_keys), list()) - else: - self.assertEqual(self.table.c.fkey.foreign_keys._list, list()) - - # test string names - cons = ForeignKeyConstraint(['fkey'], ['%s.id' % self.tablename], table=self.table) - cons.create() - self.refresh_table() - if SQLA_07: - list(self.table.c.fkey.foreign_keys)[0].column is self.table.c.id - else: - self.table.c.fkey.foreign_keys[0].column is self.table.c.id - - # Remove the name, drop the constraint; it should succeed - cons.name = None - cons.drop() - - @fixture.usedb(not_supported=['oracle', 'sqlite', 'mysql']) - def test_autoname_check(self): - """CheckConstraints can guess their name if None is given""" - cons = CheckConstraint('id > 3', columns=[self.table.c.id]) - cons.create() - self.refresh_table() - - if not self.engine.name == 'mysql': - self.table.insert(values={'id': 4, 'fkey': 1}).execute() - try: - self.table.insert(values={'id': 1, 'fkey': 2}).execute() - except (IntegrityError, ProgrammingError): - pass - else: - self.fail() - - # Remove the name, drop the constraint; it should succeed - cons.name = None - cons.drop() - self.refresh_table() - self.table.insert(values={'id': 2, 'fkey': 2}).execute() - self.table.insert(values={'id': 1, 'fkey': 3}).execute() - - @fixture.usedb(not_supported=['oracle']) - def test_autoname_unique(self): - """UniqueConstraints can guess their name if None is given""" - cons = UniqueConstraint(self.table.c.fkey) - cons.create() - self.refresh_table() - - self.table.insert(values={'fkey': 4, 'id': 1}).execute() - try: - self.table.insert(values={'fkey': 4, 'id': 2}).execute() - except (sqlalchemy.exc.IntegrityError, - sqlalchemy.exc.ProgrammingError): - pass - else: - self.fail() - - # Remove the name, drop the constraint; it should succeed - cons.name = None - cons.drop() - self.refresh_table() - self.table.insert(values={'fkey': 4, 'id': 2}).execute() - self.table.insert(values={'fkey': 4, 'id': 1}).execute() |