Skip to content

Commit 7445e29

Browse files
authored
Merge pull request #149 from cporcellijr/dev
Fix/missing-schema-migration
2 parents 883e260 + 316c2d0 commit 7445e29

File tree

1 file changed

+77
-0
lines changed

1 file changed

+77
-0
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
"""repair schema drift and missing tables
2+
3+
Revision ID: e4a1c2d9f7b3
4+
Revises: fix_original_filename
5+
Create Date: 2026-02-24
6+
"""
7+
8+
from typing import Sequence, Union
9+
10+
from alembic import op
11+
import sqlalchemy as sa
12+
13+
14+
# revision identifiers, used by Alembic.
15+
revision: str = 'e4a1c2d9f7b3'
16+
down_revision: Union[str, Sequence[str], None] = 'fix_original_filename'
17+
branch_labels: Union[str, Sequence[str], None] = None
18+
depends_on: Union[str, Sequence[str], None] = None
19+
20+
21+
def _get_columns(inspector, table_name: str) -> set:
22+
if table_name not in inspector.get_table_names():
23+
return set()
24+
return {c['name'] for c in inspector.get_columns(table_name)}
25+
26+
27+
def upgrade() -> None:
28+
bind = op.get_bind()
29+
inspector = sa.inspect(bind)
30+
31+
# 1. booklore_books
32+
if 'booklore_books' not in inspector.get_table_names():
33+
op.create_table(
34+
'booklore_books',
35+
sa.Column('id', sa.Integer(), primary_key=True, autoincrement=True),
36+
sa.Column('filename', sa.String(length=500), nullable=False),
37+
sa.Column('title', sa.String(length=500), nullable=True),
38+
sa.Column('authors', sa.String(length=500), nullable=True),
39+
sa.Column('raw_metadata', sa.Text(), nullable=True),
40+
sa.Column('last_updated', sa.DateTime(), nullable=True),
41+
sa.UniqueConstraint('filename', name='uq_booklore_books_filename'),
42+
)
43+
op.create_index(op.f('ix_booklore_books_filename'), 'booklore_books', ['filename'], unique=False)
44+
else:
45+
booklore_cols = _get_columns(inspector, 'booklore_books')
46+
if 'last_updated' not in booklore_cols:
47+
op.add_column('booklore_books', sa.Column('last_updated', sa.DateTime(), nullable=True))
48+
49+
# 2. pending_suggestions
50+
if 'pending_suggestions' not in inspector.get_table_names():
51+
op.create_table(
52+
'pending_suggestions',
53+
sa.Column('id', sa.Integer(), primary_key=True, autoincrement=True),
54+
sa.Column('source', sa.String(length=50), nullable=True, server_default='abs'),
55+
sa.Column('source_id', sa.String(length=255), nullable=True),
56+
sa.Column('title', sa.String(length=500), nullable=True),
57+
sa.Column('author', sa.String(length=500), nullable=True),
58+
sa.Column('cover_url', sa.String(length=500), nullable=True),
59+
sa.Column('matches_json', sa.Text(), nullable=True),
60+
sa.Column('status', sa.String(length=20), nullable=True, server_default='pending'),
61+
sa.Column('created_at', sa.DateTime(), nullable=True),
62+
)
63+
64+
# 3. book_alignments
65+
if 'book_alignments' not in inspector.get_table_names():
66+
op.create_table(
67+
'book_alignments',
68+
sa.Column('abs_id', sa.String(length=255), nullable=False),
69+
sa.Column('alignment_map_json', sa.Text(), nullable=False),
70+
sa.Column('last_updated', sa.DateTime(), nullable=True),
71+
sa.ForeignKeyConstraint(['abs_id'], ['books.abs_id'], ondelete='CASCADE'),
72+
sa.PrimaryKeyConstraint('abs_id'),
73+
)
74+
75+
76+
def downgrade() -> None:
77+
pass

0 commit comments

Comments
 (0)