From 85c18b876d654b971c14fc94f86df312638989ce Mon Sep 17 00:00:00 2001 From: Gyubong Date: Thu, 16 Jul 2026 11:59:52 +0900 Subject: [PATCH 1/2] 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) --- ...fix_sessionresult_enum_type_coexistence.py | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/ai/backend/manager/models/alembic/versions/0b1efbb2db84_fix_sessionresult_enum_type_coexistence.py b/src/ai/backend/manager/models/alembic/versions/0b1efbb2db84_fix_sessionresult_enum_type_coexistence.py index c2572b453ab..c9840e85280 100644 --- a/src/ai/backend/manager/models/alembic/versions/0b1efbb2db84_fix_sessionresult_enum_type_coexistence.py +++ b/src/ai/backend/manager/models/alembic/versions/0b1efbb2db84_fix_sessionresult_enum_type_coexistence.py @@ -41,6 +41,23 @@ def _is_expected_divergence(exc: BaseException) -> bool: return _sqlstate_of(exc) in _EXPECTED_DIVERGENCE_SQLSTATES +def _retype_result_column(conn: sa.engine.Connection, table: str, target_type: str) -> None: + """Change ``.result`` to ``target_type``, carrying its default across. + + PostgreSQL cannot cast an existing column default between two unrelated enum + types, so ALTER COLUMN ... TYPE fails outright while a default is attached. + Drop it, retype, then put it back -- the same order dec0deba5893 uses. + """ + conn.exec_driver_sql(f"ALTER TABLE {table} ALTER COLUMN result DROP DEFAULT") + conn.exec_driver_sql( + f"ALTER TABLE {table} ALTER COLUMN result" + f" TYPE {target_type} USING result::text::{target_type}" + ) + conn.exec_driver_sql( + f"ALTER TABLE {table} ALTER COLUMN result SET DEFAULT 'UNDEFINED'::{target_type}" + ) + + def upgrade() -> None: conn = op.get_bind() @@ -62,10 +79,7 @@ def upgrade() -> None: # - "sessionresults" was created by b6b884fbae1f (2022, sessions.result) # - ffcf0ed13a26 skipped rename because both existed # Fix: alter sessions.result to use the singular type, then drop plural. - conn.exec_driver_sql( - "ALTER TABLE sessions ALTER COLUMN result" - " TYPE sessionresult USING result::text::sessionresult" - ) + _retype_result_column(conn, "sessions", "sessionresult") conn.exec_driver_sql("DROP TYPE sessionresults") elif has_plural and not has_singular: # Only plural exists (ffcf0ed13a26 was never applied, or was skipped). @@ -102,10 +116,7 @@ def downgrade() -> None: conn.exec_driver_sql( "CREATE TYPE sessionresults AS ENUM ('UNDEFINED', 'SUCCESS', 'FAILURE')" ) - conn.exec_driver_sql( - "ALTER TABLE sessions ALTER COLUMN result" - " TYPE sessionresults USING result::text::sessionresults" - ) + _retype_result_column(conn, "sessions", "sessionresults") except sa.exc.DBAPIError as e: if not _is_expected_divergence(e): raise From 24220386db48dc70e3e3008ffd2c08ffd84c9593 Mon Sep 17 00:00:00 2001 From: Gyubong Date: Thu, 16 Jul 2026 12:06:00 +0900 Subject: [PATCH 2/2] docs: add news fragment Co-Authored-By: Claude Opus 4.8 (1M context) --- changes/12912.fix.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changes/12912.fix.md diff --git a/changes/12912.fix.md b/changes/12912.fix.md new file mode 100644 index 00000000000..d15350ab8b2 --- /dev/null +++ b/changes/12912.fix.md @@ -0,0 +1 @@ +Fix the session result enum downgrade aborting when the column default cannot be cast to the recreated type