summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/source/installation.rst27
-rw-r--r--oslo.db/locale/oslo.db.pot97
-rw-r--r--oslo/db/sqlalchemy/test_base.py2
-rw-r--r--oslo/db/sqlalchemy/utils.py13
-rw-r--r--test-requirements.txt1
-rw-r--r--tests/sqlalchemy/test_utils.py32
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'