diff options
-rw-r--r-- | doc/source/installation.rst | 27 | ||||
-rw-r--r-- | oslo.db/locale/oslo.db.pot | 97 | ||||
-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 | 1 | ||||
-rw-r--r-- | tests/sqlalchemy/test_utils.py | 32 |
6 files changed, 163 insertions, 9 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/locale/oslo.db.pot b/oslo.db/locale/oslo.db.pot new file mode 100644 index 0000000..d83de31 --- /dev/null +++ b/oslo.db/locale/oslo.db.pot @@ -0,0 +1,97 @@ +# Translations template for oslo.db. +# Copyright (C) 2014 ORGANIZATION +# This file is distributed under the same license as the oslo.db project. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2014. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: oslo.db 06224bc\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2014-06-05 22:17+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 1.3\n" + +#: oslo/db/exception.py:44 +msgid "Invalid Parameter: Unicode is not supported by the current database." +msgstr "" + +#: oslo/db/openstack/common/gettextutils.py:271 +msgid "Message objects do not support addition." +msgstr "" + +#: oslo/db/openstack/common/gettextutils.py:281 +msgid "" +"Message objects do not support str() because they may contain non-ascii " +"characters. Please use unicode() or translate() instead." +msgstr "" + +#: oslo/db/sqlalchemy/migration.py:72 +msgid "version should be an integer" +msgstr "" + +#: oslo/db/sqlalchemy/migration.py:108 +#, python-format +msgid "" +"Tables \"%s\" have non utf8 collation, please make sure all tables are " +"CHARSET=utf8" +msgstr "" + +#: oslo/db/sqlalchemy/migration.py:132 +msgid "" +"The database is not under version control, but has tables. Please stamp " +"the current version of the schema manually." +msgstr "" + +#: oslo/db/sqlalchemy/utils.py:58 +msgid "Sort key supplied was not valid." +msgstr "" + +#: oslo/db/sqlalchemy/utils.py:119 +msgid "Unknown sort direction, must be 'desc' or 'asc'" +msgstr "" + +#: oslo/db/sqlalchemy/utils.py:162 +#, python-format +msgid "" +"There is no `deleted` column in `%s` table. Project doesn't use soft-" +"deleted feature." +msgstr "" + +#: oslo/db/sqlalchemy/utils.py:174 +#, python-format +msgid "Unrecognized read_deleted value '%s'" +msgstr "" + +#: oslo/db/sqlalchemy/utils.py:181 +#, python-format +msgid "There is no `project_id` column in `%s` table." +msgstr "" + +#: oslo/db/sqlalchemy/utils.py:243 +msgid "model should be a subclass of ModelBase" +msgstr "" + +#: oslo/db/sqlalchemy/utils.py:294 +#, python-format +msgid "" +"Please specify column %s in col_name_col_instance param. It is required " +"because column has unsupported type by SQLite." +msgstr "" + +#: oslo/db/sqlalchemy/utils.py:300 +#, python-format +msgid "" +"col_name_col_instance param has wrong type of column instance for column " +"%s It should be instance of sqlalchemy.Column." +msgstr "" + +#: oslo/db/sqlalchemy/utils.py:408 +msgid "Unsupported id columns type" +msgstr "" + 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 6667095..f0a218c 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -4,6 +4,7 @@ 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' |