diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index c6bce2a00..b4e3af86e 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -38,6 +38,8 @@ from sqlalchemy import Table, MetaData, Column, types, create_engine from sqlalchemy.exc import SQLAlchemyError, InvalidRequestError, DBAPIError, OperationalError from sqlalchemy.orm import scoped_session, sessionmaker, mapper from sqlalchemy.pool import NullPool +from alembic.migration import MigrationContext +from alembic.operations import Operations from openlp.core.lib import translate, Settings from openlp.core.lib.ui import critical_error_message_box @@ -65,6 +67,17 @@ def init_db(url, auto_flush=True, auto_commit=False): return session, metadata +def get_upgrade_op(session): + """ + Create a migration context and an operations object for performing upgrades. + + ``session`` + The SQLAlchemy session object. + """ + context = MigrationContext(session.bind.connect()) + return Operations(context) + + def upgrade_db(url, upgrade): """ Upgrade a database. @@ -82,13 +95,7 @@ def upgrade_db(url, upgrade): Provides a class for the metadata table. """ pass - load_changes = False - tables = [] - try: - tables = upgrade.upgrade_setup(metadata) - load_changes = True - except (SQLAlchemyError, DBAPIError): - pass + metadata_table = Table(u'metadata', metadata, Column(u'key', types.Unicode(64), primary_key=True), Column(u'value', types.UnicodeText(), default=None) @@ -105,22 +112,22 @@ def upgrade_db(url, upgrade): if version > upgrade.__version__: return version, upgrade.__version__ version += 1 - if load_changes: + try: while hasattr(upgrade, u'upgrade_%d' % version): log.debug(u'Running upgrade_%d', version) try: upgrade_func = getattr(upgrade, u'upgrade_%d' % version) - upgrade_func(session, metadata, tables) + upgrade_func(session, metadata) session.commit() # Update the version number AFTER a commit so that we are sure the previous transaction happened version_meta.value = unicode(version) session.commit() version += 1 except (SQLAlchemyError, DBAPIError): - log.exception(u'Could not run database upgrade script ' - '"upgrade_%s", upgrade process has been halted.', version) + log.exception(u'Could not run database upgrade script "upgrade_%s", upgrade process has been halted.', + version) break - else: + except (SQLAlchemyError, DBAPIError): version_meta = Metadata.populate(key=u'version', value=int(upgrade.__version__)) session.commit() return int(version_meta.value), upgrade.__version__ diff --git a/openlp/plugins/bibles/lib/upgrade.py b/openlp/plugins/bibles/lib/upgrade.py index b4a358c45..a19582cd9 100644 --- a/openlp/plugins/bibles/lib/upgrade.py +++ b/openlp/plugins/bibles/lib/upgrade.py @@ -38,28 +38,13 @@ __version__ = 1 log = logging.getLogger(__name__) -def upgrade_setup(metadata): - """ - Set up the latest revision all tables, with reflection, needed for the - upgrade process. If you want to drop a table, you need to remove it from - here, and add it to your upgrade function. - """ - # Don't define the "metadata" table, as the upgrade mechanism already - # defines it. - tables = { - u'book': Table(u'book', metadata, autoload=True), - u'verse': Table(u'verse', metadata, autoload=True) - } - return tables - - -def upgrade_1(session, metadata, tables): +def upgrade_1(session, metadata): """ Version 1 upgrade. This upgrade renames a number of keys to a single naming convention. """ - metadata_table = metadata.tables[u'metadata'] + metadata_table = Table(u'metadata', metadata, autoload=True) # Copy "Version" to "name" ("version" used by upgrade system) # TODO: Clean up in a subsequent release of OpenLP (like 2.0 final) session.execute(insert(metadata_table).values( diff --git a/openlp/plugins/songs/lib/upgrade.py b/openlp/plugins/songs/lib/upgrade.py index edff8d9f3..47cf5df81 100644 --- a/openlp/plugins/songs/lib/upgrade.py +++ b/openlp/plugins/songs/lib/upgrade.py @@ -31,39 +31,14 @@ The :mod:`upgrade` module provides a way for the database and schema that is the backend for the Songs plugin """ -from sqlalchemy import Column, Table, types +from sqlalchemy import Column, types from sqlalchemy.sql.expression import func -#from migrate.changeset.constraint import ForeignKeyConstraint -from alembic.migration import MigrationContext -from alembic.operations import Operations +from openlp.core.lib.db import get_upgrade_op __version__ = 3 -def get_alembic_operation(session): - context = MigrationContext(session.bind.connect()) - return Operations(context) - - -def upgrade_setup(metadata): - """ - Set up the latest revision all tables, with reflection, needed for the - upgrade process. If you want to drop a table, you need to remove it from - here, and add it to your upgrade function. - """ - tables = { - u'authors': Table(u'authors', metadata, autoload=True), - u'media_files': Table(u'media_files', metadata, autoload=True), - u'song_books': Table(u'song_books', metadata, autoload=True), - u'songs': Table(u'songs', metadata, autoload=True), - u'topics': Table(u'topics', metadata, autoload=True), - u'authors_songs': Table(u'authors_songs', metadata, autoload=True), - u'songs_topics': Table(u'songs_topics', metadata, autoload=True) - } - return tables - - -def upgrade_1(session, metadata, tables): +def upgrade_1(session, metadata): """ Version 1 upgrade. @@ -75,14 +50,7 @@ def upgrade_1(session, metadata, tables): added to the media_files table, and a weight column so that the media files can be ordered. """ - #Table(u'media_files_songs', metadata, autoload=True).drop(checkfirst=True) - #Column(u'song_id', types.Integer(), default=None).create(table=tables[u'media_files']) - #Column(u'weight', types.Integer(), default=0).create(table=tables[u'media_files']) - #if metadata.bind.url.get_dialect().name != 'sqlite': - # # SQLite doesn't support ALTER TABLE ADD CONSTRAINT - # ForeignKeyConstraint([u'song_id'], [u'songs.id'], - # table=tables[u'media_files']).create() - op = get_alembic_operation(session) + op = get_upgrade_op(session) op.drop_table(u'media_files_songs') op.add_column(u'media_files', Column(u'song_id', types.Integer(), default=None)) op.add_column(u'media_files', Column(u'weight', types.Integer(), default=0)) @@ -91,26 +59,23 @@ def upgrade_1(session, metadata, tables): op.create_foreign_key(u'fk_media_files_song_id', u'media_files', u'songs', [u'song_id', u'id']) -def upgrade_2(session, metadata, tables): +def upgrade_2(session, metadata): """ Version 2 upgrade. This upgrade adds a create_date and last_modified date to the songs table """ - #Column(u'create_date', types.DateTime(), default=func.now()).create(table=tables[u'songs']) - #Column(u'last_modified', types.DateTime(), default=func.now()).create(table=tables[u'songs']) - op = get_alembic_operation(session) + op = get_upgrade_op(session) op.add_column(u'songs', Column(u'create_date', types.DateTime(), default=func.now())) op.add_column(u'songs', Column(u'last_modified', types.DateTime(), default=func.now())) -def upgrade_3(session, metadata, tables): +def upgrade_3(session, metadata): """ Version 3 upgrade. This upgrade adds a temporary song flag to the songs table """ - #Column(u'temporary', types.Boolean(), default=False).create(table=tables[u'songs']) - op = get_alembic_operation(session) + op = get_upgrade_op(session) op.add_column(u'songs', Column(u'temporary', types.Boolean(), default=False)) diff --git a/openlp/plugins/songusage/lib/upgrade.py b/openlp/plugins/songusage/lib/upgrade.py index a783ff8e3..9ea048261 100644 --- a/openlp/plugins/songusage/lib/upgrade.py +++ b/openlp/plugins/songusage/lib/upgrade.py @@ -30,30 +30,19 @@ The :mod:`upgrade` module provides a way for the database and schema that is the backend for the SongsUsage plugin """ +from openlp.core.lib.db import get_upgrade_op -from sqlalchemy import Column, Table, types +from sqlalchemy import Column, types __version__ = 1 -def upgrade_setup(metadata): - """ - Set up the latest revision all tables, with reflection, needed for the - upgrade process. If you want to drop a table, you need to remove it from - here, and add it to your upgrade function. - """ - tables = { - u'songusage_data': Table(u'songusage_data', metadata, autoload=True) - } - return tables - -def upgrade_1(session, metadata, tables): +def upgrade_1(session, metadata): """ Version 1 upgrade. This upgrade adds two new fields to the songusage database """ - Column(u'plugin_name', types.Unicode(20), default=u'') \ - .create(table=tables[u'songusage_data'], populate_default=True) - Column(u'source', types.Unicode(10), default=u'') \ - .create(table=tables[u'songusage_data'], populate_default=True) + op = get_upgrade_op(session) + op.add_column(u'songusage_data', Column(u'plugin_name', types.Unicode(20), server_default=u'')) + op.add_column(u'songusage_data', Column(u'source', types.Unicode(10), server_default=u'')) diff --git a/setup.py b/setup.py index a96259380..8ba2e0942 100755 --- a/setup.py +++ b/setup.py @@ -157,6 +157,8 @@ OpenLP (previously openlp.org) is free church presentation software, or lyrics p zip_safe=False, install_requires=[ # -*- Extra requirements: -*- + 'sqlalchemy', + 'alembic' ], entry_points=""" # -*- Entry points: -*-