"""Fix musehub_coord_reservations: composite PK (reservation_id, symbol_address). The original schema used reservation_id alone as PK, which prevented a single reservation from covering multiple symbol addresses — _materialize_reservation would create only the first row and skip all subsequent addresses because session.get(PK) found the first row on loop iteration 2+. The correct design: one row per (reservation_id, symbol_address) pair, with a composite PK. This matches the query pattern (conflict_check uses symbol_address IN filter) and enables proper multi-address reservations. Revision ID: 0023 Revises: 0022 """ from __future__ import annotations from alembic import op import sqlalchemy as sa revision = "0023" down_revision = "0022" branch_labels = None depends_on = None def upgrade() -> None: # Drop the old single-column PK op.drop_constraint("musehub_coord_reservations_pkey", "musehub_coord_reservations", type_="primary") # Add composite PK op.create_primary_key( "musehub_coord_reservations_pkey", "musehub_coord_reservations", ["reservation_id", "symbol_address"], ) # Add index on repo_id for the list_reservations query pattern op.create_index("ix_coord_reservations_repo_id", "musehub_coord_reservations", ["repo_id"]) def downgrade() -> None: from sqlalchemy import text op.execute(text("DROP INDEX IF EXISTS ix_coord_reservations_repo_id")) op.drop_constraint("musehub_coord_reservations_pkey", "musehub_coord_reservations", type_="primary") op.create_primary_key( "musehub_coord_reservations_pkey", "musehub_coord_reservations", ["reservation_id"], )