Migrated to Alembic (if you'll excuse the pun)

This commit is contained in:
Raoul Snyman 2013-04-03 21:46:41 +02:00
parent d42f64e044
commit d88e8a0b02
5 changed files with 37 additions and 89 deletions

View File

@ -38,6 +38,8 @@ from sqlalchemy import Table, MetaData, Column, types, create_engine
from sqlalchemy.exc import SQLAlchemyError, InvalidRequestError, DBAPIError, OperationalError from sqlalchemy.exc import SQLAlchemyError, InvalidRequestError, DBAPIError, OperationalError
from sqlalchemy.orm import scoped_session, sessionmaker, mapper from sqlalchemy.orm import scoped_session, sessionmaker, mapper
from sqlalchemy.pool import NullPool 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 import translate, Settings
from openlp.core.lib.ui import critical_error_message_box 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 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): def upgrade_db(url, upgrade):
""" """
Upgrade a database. Upgrade a database.
@ -82,13 +95,7 @@ def upgrade_db(url, upgrade):
Provides a class for the metadata table. Provides a class for the metadata table.
""" """
pass pass
load_changes = False
tables = []
try:
tables = upgrade.upgrade_setup(metadata)
load_changes = True
except (SQLAlchemyError, DBAPIError):
pass
metadata_table = Table(u'metadata', metadata, metadata_table = Table(u'metadata', metadata,
Column(u'key', types.Unicode(64), primary_key=True), Column(u'key', types.Unicode(64), primary_key=True),
Column(u'value', types.UnicodeText(), default=None) Column(u'value', types.UnicodeText(), default=None)
@ -105,22 +112,22 @@ def upgrade_db(url, upgrade):
if version > upgrade.__version__: if version > upgrade.__version__:
return version, upgrade.__version__ return version, upgrade.__version__
version += 1 version += 1
if load_changes: try:
while hasattr(upgrade, u'upgrade_%d' % version): while hasattr(upgrade, u'upgrade_%d' % version):
log.debug(u'Running upgrade_%d', version) log.debug(u'Running upgrade_%d', version)
try: try:
upgrade_func = getattr(upgrade, u'upgrade_%d' % version) upgrade_func = getattr(upgrade, u'upgrade_%d' % version)
upgrade_func(session, metadata, tables) upgrade_func(session, metadata)
session.commit() session.commit()
# Update the version number AFTER a commit so that we are sure the previous transaction happened # Update the version number AFTER a commit so that we are sure the previous transaction happened
version_meta.value = unicode(version) version_meta.value = unicode(version)
session.commit() session.commit()
version += 1 version += 1
except (SQLAlchemyError, DBAPIError): except (SQLAlchemyError, DBAPIError):
log.exception(u'Could not run database upgrade script ' log.exception(u'Could not run database upgrade script "upgrade_%s", upgrade process has been halted.',
'"upgrade_%s", upgrade process has been halted.', version) version)
break break
else: except (SQLAlchemyError, DBAPIError):
version_meta = Metadata.populate(key=u'version', value=int(upgrade.__version__)) version_meta = Metadata.populate(key=u'version', value=int(upgrade.__version__))
session.commit() session.commit()
return int(version_meta.value), upgrade.__version__ return int(version_meta.value), upgrade.__version__

View File

@ -38,28 +38,13 @@ __version__ = 1
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
def upgrade_setup(metadata): def upgrade_1(session, 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):
""" """
Version 1 upgrade. Version 1 upgrade.
This upgrade renames a number of keys to a single naming convention. 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) # Copy "Version" to "name" ("version" used by upgrade system)
# TODO: Clean up in a subsequent release of OpenLP (like 2.0 final) # TODO: Clean up in a subsequent release of OpenLP (like 2.0 final)
session.execute(insert(metadata_table).values( session.execute(insert(metadata_table).values(

View File

@ -31,39 +31,14 @@ The :mod:`upgrade` module provides a way for the database and schema that is the
backend for the Songs plugin backend for the Songs plugin
""" """
from sqlalchemy import Column, Table, types from sqlalchemy import Column, types
from sqlalchemy.sql.expression import func from sqlalchemy.sql.expression import func
#from migrate.changeset.constraint import ForeignKeyConstraint from openlp.core.lib.db import get_upgrade_op
from alembic.migration import MigrationContext
from alembic.operations import Operations
__version__ = 3 __version__ = 3
def get_alembic_operation(session): def upgrade_1(session, metadata):
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):
""" """
Version 1 upgrade. 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 added to the media_files table, and a weight column so that the media
files can be ordered. files can be ordered.
""" """
#Table(u'media_files_songs', metadata, autoload=True).drop(checkfirst=True) op = get_upgrade_op(session)
#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.drop_table(u'media_files_songs') 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'song_id', types.Integer(), default=None))
op.add_column(u'media_files', Column(u'weight', types.Integer(), default=0)) 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']) 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. Version 2 upgrade.
This upgrade adds a create_date and last_modified date to the songs table 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']) op = get_upgrade_op(session)
#Column(u'last_modified', types.DateTime(), default=func.now()).create(table=tables[u'songs'])
op = get_alembic_operation(session)
op.add_column(u'songs', Column(u'create_date', types.DateTime(), default=func.now())) 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())) 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. Version 3 upgrade.
This upgrade adds a temporary song flag to the songs table 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_upgrade_op(session)
op = get_alembic_operation(session)
op.add_column(u'songs', Column(u'temporary', types.Boolean(), default=False)) op.add_column(u'songs', Column(u'temporary', types.Boolean(), default=False))

View File

@ -30,30 +30,19 @@
The :mod:`upgrade` module provides a way for the database and schema that is the The :mod:`upgrade` module provides a way for the database and schema that is the
backend for the SongsUsage plugin 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 __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):
def upgrade_1(session, metadata, tables):
""" """
Version 1 upgrade. Version 1 upgrade.
This upgrade adds two new fields to the songusage database This upgrade adds two new fields to the songusage database
""" """
Column(u'plugin_name', types.Unicode(20), default=u'') \ op = get_upgrade_op(session)
.create(table=tables[u'songusage_data'], populate_default=True) op.add_column(u'songusage_data', Column(u'plugin_name', types.Unicode(20), server_default=u''))
Column(u'source', types.Unicode(10), default=u'') \ op.add_column(u'songusage_data', Column(u'source', types.Unicode(10), server_default=u''))
.create(table=tables[u'songusage_data'], populate_default=True)

View File

@ -157,6 +157,8 @@ OpenLP (previously openlp.org) is free church presentation software, or lyrics p
zip_safe=False, zip_safe=False,
install_requires=[ install_requires=[
# -*- Extra requirements: -*- # -*- Extra requirements: -*-
'sqlalchemy',
'alembic'
], ],
entry_points=""" entry_points="""
# -*- Entry points: -*- # -*- Entry points: -*-