fix(migrations): add _table_exists guard to migrations touching create_all()-only tables
- 2df63b7ce038: was checking _column_exists but not _table_exists. If llm_providers/validation_policies/llm_validation_results don't exist (fresh DB), _column_exists returns False and add_column crashes. Now checks _table_exists first. - a1b2c3d4e5f6 (20260603_add_token_limits_to_llm_providers): no guard at all. llm_providers is created by create_all() at runtime. Guard matches pattern used by ed28d34edde7, 9f8e7d6c5b4a and others.
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
"""Add context_window and max_output_tokens to llm_providers
|
||||
|
||||
@RATIONALE llm_providers is created at runtime by init_db() →
|
||||
Base.metadata.create_all(), not by any Alembic migration. On a fresh
|
||||
database, the table doesn't exist when migrations run. Guard with
|
||||
_table_exists() — create_all() will create the table with the model's
|
||||
columns (which already include context_window and max_output_tokens).
|
||||
|
||||
Revision ID: a1b2c3d4e5f6
|
||||
Revises: f1a2b3c4d5e6
|
||||
Create Date: 2026-06-03
|
||||
@@ -12,6 +18,7 @@ Both NULL = use PROVIDER_DEFAULTS fallback from model name.
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
from sqlalchemy import inspect
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
@@ -22,7 +29,15 @@ branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def _table_exists(table_name: str) -> bool:
|
||||
conn = op.get_bind()
|
||||
inspector = inspect(conn)
|
||||
return inspector.has_table(table_name)
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
if not _table_exists("llm_providers"):
|
||||
return
|
||||
op.add_column(
|
||||
"llm_providers",
|
||||
sa.Column(
|
||||
@@ -44,5 +59,7 @@ def upgrade() -> None:
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
if not _table_exists("llm_providers"):
|
||||
return
|
||||
op.drop_column("llm_providers", "max_output_tokens")
|
||||
op.drop_column("llm_providers", "context_window")
|
||||
|
||||
@@ -18,6 +18,7 @@ from collections.abc import Sequence
|
||||
import sqlalchemy as sa
|
||||
|
||||
from alembic import op
|
||||
from sqlalchemy import inspect
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '2df63b7ce038'
|
||||
@@ -26,27 +27,35 @@ branch_labels: str | Sequence[str] | None = None
|
||||
depends_on: str | Sequence[str] | None = None
|
||||
|
||||
|
||||
def _table_exists(table: str) -> bool:
|
||||
"""Check if a table exists in the current database connection."""
|
||||
conn = op.get_bind()
|
||||
inspector = inspect(conn)
|
||||
return inspector.has_table(table)
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# Use IF NOT EXISTS — this is a catch-up migration for columns that
|
||||
# may already exist (inserted by out-of-band schema changes).
|
||||
conn = op.get_bind()
|
||||
|
||||
# Add is_multimodal to llm_providers (from 9f8e7d6c5b4a)
|
||||
if not _column_exists(conn, "llm_providers", "is_multimodal"):
|
||||
# llm_providers is created by create_all() at runtime — skip if not exist
|
||||
if _table_exists("llm_providers") and not _column_exists(conn, "llm_providers", "is_multimodal"):
|
||||
op.add_column("llm_providers",
|
||||
sa.Column("is_multimodal", sa.Boolean(), nullable=False, server_default="false")
|
||||
)
|
||||
op.alter_column("llm_providers", "is_multimodal", server_default=None)
|
||||
|
||||
# Add provider_id to validation_policies (from a7b1c2d3e4f5)
|
||||
if not _column_exists(conn, "validation_policies", "provider_id"):
|
||||
# validation_policies is created by create_all() at runtime — skip if not exist
|
||||
if _table_exists("validation_policies") and not _column_exists(conn, "validation_policies", "provider_id"):
|
||||
op.add_column("validation_policies",
|
||||
sa.Column("provider_id", sa.String(), nullable=True)
|
||||
)
|
||||
|
||||
# Add policy_id to llm_validation_results (from b1c2d3e4f5a6)
|
||||
if not _column_exists(conn, "llm_validation_results", "policy_id"):
|
||||
# llm_validation_results is created by create_all() at runtime — skip if not exist
|
||||
if _table_exists("llm_validation_results") and not _column_exists(conn, "llm_validation_results", "policy_id"):
|
||||
op.add_column("llm_validation_results",
|
||||
sa.Column("policy_id", sa.String(), nullable=True, index=True)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user