diff options
-rw-r--r-- | doc/source/installation.rst | 27 | ||||
-rw-r--r-- | oslo/db/sqlalchemy/test_base.py | 2 | ||||
-rw-r--r-- | oslo/db/sqlalchemy/utils.py | 13 | ||||
-rw-r--r-- | test-requirements.txt | 3 | ||||
-rw-r--r-- | tests/sqlalchemy/test_utils.py | 32 | ||||
-rw-r--r-- | tox.ini | 2 |
6 files changed, 68 insertions, 11 deletions
diff --git a/doc/source/installation.rst b/doc/source/installation.rst index 5c01c7a..254bd9b 100644 --- a/doc/source/installation.rst +++ b/doc/source/installation.rst @@ -4,9 +4,30 @@ Installation At the command line:: - $ pip install + $ pip install oslo.db Or, if you have virtualenvwrapper installed:: - $ mkvirtualenv - $ pip install
\ No newline at end of file + $ mkvirtualenv + $ pip install oslo.db + +You will also need to install at least one SQL backend:: + + $ pip install MySQL-python + +Or:: + + $ pip install pysqlite + +Using with MySQL +---------------- + +If using MySQL make sure to install the MySQL client development package for +your distro. On Ubuntu this is done as follows:: + + $ sudo apt-get install libmysqlclient-dev + $ pip install MySQL-python + +The installation of MySQL-python will fail if libmysqlclient-dev is not +installed first. Note that even in a virtual environment the MySQL package will +be installed system wide.
\ No newline at end of file diff --git a/oslo/db/sqlalchemy/test_base.py b/oslo/db/sqlalchemy/test_base.py index 7664faa..544568e 100644 --- a/oslo/db/sqlalchemy/test_base.py +++ b/oslo/db/sqlalchemy/test_base.py @@ -151,10 +151,12 @@ class OpportunisticTestCase(DbTestCase): class MySQLOpportunisticFixture(OpportunisticFixture): DRIVER = 'mysql' + DBNAME = '' # connect to MySQL server, but not to the openstack_citest db class PostgreSQLOpportunisticFixture(OpportunisticFixture): DRIVER = 'postgresql' + DBNAME = 'postgres' # PostgreSQL requires the db name here,use service one class MySQLOpportunisticTestCase(OpportunisticTestCase): diff --git a/oslo/db/sqlalchemy/utils.py b/oslo/db/sqlalchemy/utils.py index 04eb7ce..83821f7 100644 --- a/oslo/db/sqlalchemy/utils.py +++ b/oslo/db/sqlalchemy/utils.py @@ -418,7 +418,7 @@ def drop_old_duplicate_entries_from_table(migrate_engine, table_name, columns_for_select, group_by=columns_for_group_by, having=func.count(table.c.id) > 1) - for row in migrate_engine.execute(duplicated_rows_select): + for row in migrate_engine.execute(duplicated_rows_select).fetchall(): # NOTE(boris-42): Do not remove row that has the biggest ID. delete_condition = table.c.id != row[0] is_none = None # workaround for pyflakes @@ -612,8 +612,15 @@ def _change_deleted_column_type_to_id_type_sqlite(migrate_engine, table_name, if not isinstance(constraint, CheckConstraint): return False sqltext = str(constraint.sqltext) - return (sqltext.endswith("deleted in (0, 1)") or - sqltext.endswith("deleted IN (:deleted_1, :deleted_2)")) + # NOTE(I159): in order to omit the CHECK constraint corresponding + # to `deleted` column we have to test these patterns which may + # vary depending on the SQLAlchemy version used. + constraint_markers = ( + "deleted in (0, 1)", + "deleted IN (:deleted_1, :deleted_2)", + "deleted IN (:param_1, :param_2)" + ) + return any(sqltext.endswith(marker) for marker in constraint_markers) constraints = [] for constraint in table.constraints: diff --git a/test-requirements.txt b/test-requirements.txt index c940f8c..f0a218c 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,9 +1,10 @@ -hacking>=0.8.0,<0.9 +hacking>=0.9.1,<0.10 coverage>=3.6 discover fixtures>=0.3.14 MySQL-python +psycopg2 python-subunit>=0.0.18 sphinx>=1.2.1,<1.3 oslosphinx diff --git a/tests/sqlalchemy/test_utils.py b/tests/sqlalchemy/test_utils.py index 36a2b14..a24a83a 100644 --- a/tests/sqlalchemy/test_utils.py +++ b/tests/sqlalchemy/test_utils.py @@ -183,9 +183,6 @@ class TestPaginateQuery(test_base.BaseTestCase): class TestMigrationUtils(test_migrations.BaseMigrationTestCase): """Class for testing utils that are used in db migrations.""" - def setUp(self): - super(TestMigrationUtils, self).setUp() - def _populate_db_for_drop_duplicate_entries(self, engine, meta, table_name): values = [ @@ -241,6 +238,18 @@ class TestMigrationUtils(test_migrations.BaseMigrationTestCase): for id_ in expected_ids: self.assertTrue(id_ in real_ids) + def test_drop_dup_entries_in_file_conn(self): + table_name = "__test_tmp_table__" + tmp_db_file = self.create_tempfiles([['name', '']], ext='.sql')[0] + in_file_engine = session.EngineFacade( + 'sqlite:///%s' % tmp_db_file).get_engine() + meta = MetaData() + meta.bind = in_file_engine + test_table, values = self._populate_db_for_drop_duplicate_entries( + in_file_engine, meta, table_name) + utils.drop_old_duplicate_entries_from_table( + in_file_engine, table_name, False, 'b', 'c') + def test_drop_old_duplicate_entries_from_table_soft_delete(self): table_name = "__test_tmp_table__" @@ -441,6 +450,23 @@ class TestMigrationUtils(test_migrations.BaseMigrationTestCase): self.assertTrue(isinstance(table.c.foo.type, NullType)) self.assertTrue(isinstance(table.c.deleted.type, Boolean)) + def test_change_deleted_column_type_drops_check_constraint(self): + table_name = 'abc' + meta = MetaData() + engine = self.engines['sqlite'] + meta.bind = engine + table = Table(table_name, meta, + Column('id', Integer, primary_key=True), + Column('deleted', Boolean)) + table.create() + + utils._change_deleted_column_type_to_id_type_sqlite(engine, + table_name) + table = Table(table_name, meta, autoload=True) + # NOTE(I159): if the CHECK constraint has been dropped (expected + # behavior), any integer value can be inserted, otherwise only 1 or 0. + engine.execute(table.insert({'deleted': 10})) + def test_utils_drop_unique_constraint(self): table_name = "__test_tmp_table__" uc_name = 'uniq_foo' @@ -35,7 +35,7 @@ commands = # E123, E125 skipped as they are invalid PEP-8. show-source = True -ignore = E123,E125,H803 +ignore = E123,E125,E128,E265,H305,H307,H402,H405,H703,H803,H904 builtins = _ exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build |