"""add durable Campaign child Run identity Revision ID: c2f4a6b8d0e1 Revises: 99dbae2a20da Create Date: 2026-08-06 """ from typing import Sequence, Union import sqlalchemy as sa import sqlmodel # noqa: F401 from alembic import op revision: str = "c2f4a6b8d0e1" down_revision: Union[str, Sequence[str], None] = "99dbae2a20da" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: """Add nullable identity columns without backfilling historical Runs.""" # Adding nullable columns directly avoids rebuilding ``eval_runs``. That # table participates in a foreign-key cycle with ``campaigns`` and # ``eval_targets``; SQLite batch recreation can otherwise fail while # topologically sorting the copied table. A unique index has the same # database-level idempotency semantics as a composite unique constraint. inspector = sa.inspect(op.get_bind()) columns = {column["name"] for column in inspector.get_columns("eval_runs")} if "campaign_plan_index" not in columns: op.add_column("eval_runs", sa.Column("campaign_plan_index", sa.Integer(), nullable=True)) if "campaign_occurrence_index" not in columns: op.add_column("eval_runs", sa.Column("campaign_occurrence_index", sa.Integer(), nullable=True)) index_names = {index["name"] for index in inspector.get_indexes("eval_runs")} if "uq_eval_runs_campaign_occurrence" not in index_names: op.create_index( "uq_eval_runs_campaign_occurrence", "eval_runs", ["campaign_id", "campaign_plan_index", "campaign_occurrence_index"], unique=True, ) def downgrade() -> None: """Remove the child identity fields and their uniqueness constraint.""" inspector = sa.inspect(op.get_bind()) index_names = {index["name"] for index in inspector.get_indexes("eval_runs")} if "uq_eval_runs_campaign_occurrence" in index_names: op.drop_index("uq_eval_runs_campaign_occurrence", table_name="eval_runs") columns = {column["name"] for column in inspector.get_columns("eval_runs")} if "campaign_occurrence_index" in columns: op.drop_column("eval_runs", "campaign_occurrence_index") if "campaign_plan_index" in columns: op.drop_column("eval_runs", "campaign_plan_index")