Skip to content

Commit 0d0acb6

Browse files
jopemachineclaude
andcommitted
fix(BA-6915): drop the column default before retyping sessions.result
The downgrade recreates the plural sessionresults type and then retypes sessions.result into it. PostgreSQL cannot cast an existing column default across two unrelated enum types, so the ALTER aborts with DatatypeMismatchError before touching a row. The migration's try/except tolerates a list of expected divergence SQLSTATEs, and 42804 is not on it, so the whole downgrade chain stops here. Drop the default, retype, then restore it -- the order dec0deba5893 already uses for the same conversion. The upgrade path runs the mirror-image ALTER with the same omission, so it gets the same treatment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent c181663 commit 0d0acb6

1 file changed

Lines changed: 19 additions & 8 deletions

File tree

src/ai/backend/manager/models/alembic/versions/0b1efbb2db84_fix_sessionresult_enum_type_coexistence.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,23 @@ def _is_expected_divergence(exc: BaseException) -> bool:
4141
return _sqlstate_of(exc) in _EXPECTED_DIVERGENCE_SQLSTATES
4242

4343

44+
def _retype_result_column(conn: sa.engine.Connection, table: str, target_type: str) -> None:
45+
"""Change ``<table>.result`` to ``target_type``, carrying its default across.
46+
47+
PostgreSQL cannot cast an existing column default between two unrelated enum
48+
types, so ALTER COLUMN ... TYPE fails outright while a default is attached.
49+
Drop it, retype, then put it back -- the same order dec0deba5893 uses.
50+
"""
51+
conn.exec_driver_sql(f"ALTER TABLE {table} ALTER COLUMN result DROP DEFAULT")
52+
conn.exec_driver_sql(
53+
f"ALTER TABLE {table} ALTER COLUMN result"
54+
f" TYPE {target_type} USING result::text::{target_type}"
55+
)
56+
conn.exec_driver_sql(
57+
f"ALTER TABLE {table} ALTER COLUMN result SET DEFAULT 'UNDEFINED'::{target_type}"
58+
)
59+
60+
4461
def upgrade() -> None:
4562
conn = op.get_bind()
4663

@@ -62,10 +79,7 @@ def upgrade() -> None:
6279
# - "sessionresults" was created by b6b884fbae1f (2022, sessions.result)
6380
# - ffcf0ed13a26 skipped rename because both existed
6481
# Fix: alter sessions.result to use the singular type, then drop plural.
65-
conn.exec_driver_sql(
66-
"ALTER TABLE sessions ALTER COLUMN result"
67-
" TYPE sessionresult USING result::text::sessionresult"
68-
)
82+
_retype_result_column(conn, "sessions", "sessionresult")
6983
conn.exec_driver_sql("DROP TYPE sessionresults")
7084
elif has_plural and not has_singular:
7185
# Only plural exists (ffcf0ed13a26 was never applied, or was skipped).
@@ -102,10 +116,7 @@ def downgrade() -> None:
102116
conn.exec_driver_sql(
103117
"CREATE TYPE sessionresults AS ENUM ('UNDEFINED', 'SUCCESS', 'FAILURE')"
104118
)
105-
conn.exec_driver_sql(
106-
"ALTER TABLE sessions ALTER COLUMN result"
107-
" TYPE sessionresults USING result::text::sessionresults"
108-
)
119+
_retype_result_column(conn, "sessions", "sessionresults")
109120
except sa.exc.DBAPIError as e:
110121
if not _is_expected_divergence(e):
111122
raise

0 commit comments

Comments
 (0)