fix(migration049): use COMMIT/BEGIN instead of execution_options AUTOCOMMIT

asyncpg+alembic keeps a transaction open via begin_transaction(); calling
execution_options(isolation_level=AUTOCOMMIT) on an already-begun connection
raises InvalidRequestError. Replace with explicit COMMIT before ALTER TYPE
and BEGIN before the backfill UPDATE.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 20:26:57 +01:00
parent 1409be171c
commit da9014831a
@@ -18,15 +18,20 @@ depends_on = None
def upgrade() -> None:
# PostgreSQL requires ALTER TYPE ADD VALUE to be committed in its own transaction
# before the new value can be used. Execute each ADD VALUE with AUTOCOMMIT.
# PostgreSQL requires ALTER TYPE ADD VALUE to be committed before the new value
# can be referenced in the same session. With asyncpg + alembic the connection
# already has an open transaction (begin_transaction), so we cannot change
# isolation level via execution_options. Instead we manually COMMIT the outer
# transaction, run the DDL, then open a new transaction for the DML backfill.
conn = op.get_bind()
with conn.execution_options(isolation_level="AUTOCOMMIT"):
# Commit the alembic-managed transaction so ALTER TYPE runs outside a tx block
conn.execute(sa.text("COMMIT"))
conn.execute(sa.text("ALTER TYPE userrole ADD VALUE IF NOT EXISTS 'global_admin'"))
conn.execute(sa.text("ALTER TYPE userrole ADD VALUE IF NOT EXISTS 'tenant_admin'"))
# Now in a normal transaction: backfill existing 'admin' → 'global_admin'
# Start a new transaction for the backfill DML
conn.execute(sa.text("BEGIN"))
conn.execute(
sa.text("UPDATE users SET role = 'global_admin'::userrole WHERE role = 'admin'::userrole")
)