repertory-api/migrations/versions/d7e3b19f0a2c_add_reference_sites.py

69 lines
2.4 KiB
Python
Raw Normal View History

"""add reference_sites and migrate references.site to FK
Revision ID: d7e3b19f0a2c
Revises: c3f8a1e924d5
Create Date: 2026-06-09
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.sql import table, column, select
revision = "d7e3b19f0a2c"
down_revision = "c3f8a1e924d5"
branch_labels = None
depends_on = None
def upgrade() -> None:
# 1. Create reference_sites table
op.create_table(
"reference_sites",
sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True),
sa.Column("name", sa.String(), nullable=False, unique=True),
)
# 2. Add site_id FK column (nullable)
op.add_column(
"references",
sa.Column("site_id", sa.Integer(),
sa.ForeignKey("reference_sites.id", ondelete="SET NULL"),
nullable=True),
)
# 3. Migrate existing site string data
conn = op.get_bind()
refs_t = table("references", column("id", sa.Integer), column("site", sa.String), column("site_id", sa.Integer))
sites_t = table("reference_sites", column("id", sa.Integer), column("name", sa.String))
# Collect distinct non-null site strings
existing = conn.execute(
select(refs_t.c.site).where(refs_t.c.site.isnot(None)).distinct()
).fetchall()
for (name,) in existing:
# Insert into reference_sites (ignore duplicates)
result = conn.execute(
sites_t.insert().returning(sites_t.c.id).values(name=name)
)
site_id = result.fetchone()[0]
# Update references rows with this site string
conn.execute(
refs_t.update().where(refs_t.c.site == name).values(site_id=site_id)
)
# 4. Drop old site string column
op.drop_column("references", "site")
def downgrade() -> None:
op.add_column("references", sa.Column("site", sa.String(), nullable=True))
# best-effort: restore site name from FK
conn = op.get_bind()
refs_t = table("references", column("id", sa.Integer), column("site", sa.String), column("site_id", sa.Integer))
sites_t = table("reference_sites", column("id", sa.Integer), column("name", sa.String))
rows = conn.execute(select(refs_t.c.id, sites_t.c.name).join(sites_t, refs_t.c.site_id == sites_t.c.id)).fetchall()
for ref_id, name in rows:
conn.execute(refs_t.update().where(refs_t.c.id == ref_id).values(site=name))
op.drop_column("references", "site_id")
op.drop_table("reference_sites")