Make Alembic migrations idempotent for SQLite
Check if columns/tables exist before adding them so migrations don't fail on re-run when schema was applied out of band.
This commit is contained in:
parent
b6739fff70
commit
8d836dae34
2 changed files with 51 additions and 20 deletions
|
|
@ -16,14 +16,26 @@ from alembic import op
|
|||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def _column_exists(table, column):
|
||||
"""Check if a column exists in a SQLite table."""
|
||||
conn = op.get_bind()
|
||||
result = conn.execute(sa.text("PRAGMA table_info('{}')".format(table)))
|
||||
return any(row[1] == column for row in result)
|
||||
|
||||
|
||||
def upgrade():
|
||||
# T4: customizable button text and comment labels
|
||||
op.add_column('rb_namespace', sa.Column('submit_button_text', sa.Unicode(length=256), nullable=True))
|
||||
op.add_column('rb_namespace', sa.Column('comment_label_singular', sa.Unicode(length=256), nullable=True))
|
||||
op.add_column('rb_namespace', sa.Column('comment_label_plural', sa.Unicode(length=256), nullable=True))
|
||||
if not _column_exists('rb_namespace', 'submit_button_text'):
|
||||
op.add_column('rb_namespace', sa.Column('submit_button_text', sa.Unicode(length=256), nullable=True))
|
||||
if not _column_exists('rb_namespace', 'comment_label_singular'):
|
||||
op.add_column('rb_namespace', sa.Column('comment_label_singular', sa.Unicode(length=256), nullable=True))
|
||||
if not _column_exists('rb_namespace', 'comment_label_plural'):
|
||||
op.add_column('rb_namespace', sa.Column('comment_label_plural', sa.Unicode(length=256), nullable=True))
|
||||
# T8: nesting depth settings
|
||||
op.add_column('rb_namespace', sa.Column('max_nesting_depth', sa.Integer(), nullable=True))
|
||||
op.add_column('rb_namespace', sa.Column('collapse_depth', sa.Integer(), nullable=True))
|
||||
if not _column_exists('rb_namespace', 'max_nesting_depth'):
|
||||
op.add_column('rb_namespace', sa.Column('max_nesting_depth', sa.Integer(), nullable=True))
|
||||
if not _column_exists('rb_namespace', 'collapse_depth'):
|
||||
op.add_column('rb_namespace', sa.Column('collapse_depth', sa.Integer(), nullable=True))
|
||||
|
||||
|
||||
def downgrade():
|
||||
|
|
|
|||
|
|
@ -18,25 +18,44 @@ import sqlalchemy as sa
|
|||
from remarkbox.models.meta import UUIDType
|
||||
|
||||
|
||||
def _column_exists(table, column):
|
||||
"""Check if a column exists in a SQLite table."""
|
||||
conn = op.get_bind()
|
||||
result = conn.execute(sa.text("PRAGMA table_info('{}')".format(table)))
|
||||
return any(row[1] == column for row in result)
|
||||
|
||||
|
||||
def _table_exists(table):
|
||||
"""Check if a table exists in SQLite."""
|
||||
conn = op.get_bind()
|
||||
result = conn.execute(sa.text(
|
||||
"SELECT name FROM sqlite_master WHERE type='table' AND name='{}'".format(table)
|
||||
))
|
||||
return result.fetchone() is not None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# T10: push notification preferences on user
|
||||
op.add_column('rb_user', sa.Column('notification_preference', sa.Unicode(length=5), server_default='email', nullable=False))
|
||||
op.add_column('rb_user', sa.Column('push_subscriptions', sa.UnicodeText(), nullable=True))
|
||||
if not _column_exists('rb_user', 'notification_preference'):
|
||||
op.add_column('rb_user', sa.Column('notification_preference', sa.Unicode(length=5), server_default='email', nullable=False))
|
||||
if not _column_exists('rb_user', 'push_subscriptions'):
|
||||
op.add_column('rb_user', sa.Column('push_subscriptions', sa.UnicodeText(), nullable=True))
|
||||
|
||||
# T7: webmention table
|
||||
op.create_table(
|
||||
'rb_webmention',
|
||||
sa.Column('id', UUIDType, primary_key=True, index=True),
|
||||
sa.Column('source', sa.Unicode(2048), nullable=False),
|
||||
sa.Column('target', sa.Unicode(2048), nullable=False),
|
||||
sa.Column('node_id', UUIDType, sa.ForeignKey('rb_node.id'), index=True, nullable=True),
|
||||
sa.Column('verified', sa.Boolean(), default=False, nullable=False),
|
||||
sa.Column('author_name', sa.Unicode(256), nullable=True),
|
||||
sa.Column('author_url', sa.Unicode(2048), nullable=True),
|
||||
sa.Column('content', sa.UnicodeText(), nullable=True),
|
||||
sa.Column('created_timestamp', sa.BigInteger(), nullable=False),
|
||||
sa.Column('updated_timestamp', sa.BigInteger(), nullable=False),
|
||||
)
|
||||
if not _table_exists('rb_webmention'):
|
||||
op.create_table(
|
||||
'rb_webmention',
|
||||
sa.Column('id', UUIDType, primary_key=True, index=True),
|
||||
sa.Column('source', sa.Unicode(2048), nullable=False),
|
||||
sa.Column('target', sa.Unicode(2048), nullable=False),
|
||||
sa.Column('node_id', UUIDType, sa.ForeignKey('rb_node.id'), index=True, nullable=True),
|
||||
sa.Column('verified', sa.Boolean(), default=False, nullable=False),
|
||||
sa.Column('author_name', sa.Unicode(256), nullable=True),
|
||||
sa.Column('author_url', sa.Unicode(2048), nullable=True),
|
||||
sa.Column('content', sa.UnicodeText(), nullable=True),
|
||||
sa.Column('created_timestamp', sa.BigInteger(), nullable=False),
|
||||
sa.Column('updated_timestamp', sa.BigInteger(), nullable=False),
|
||||
)
|
||||
|
||||
|
||||
def downgrade():
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue