From 51c7bce0da7f31f1c8777e3930a4ea6da6e4f15d Mon Sep 17 00:00:00 2001 From: Samuel-Tefera Date: Sat, 21 Mar 2026 11:11:28 +0300 Subject: [PATCH] fix(db): ensure PostgreSQL enum types match SQLAlchemy models in migration --- .../6e2d1d2b7c4a_add_ai_interactions.py | 18 ++++++++++-------- backend/app/models/ai_interaction.py | 4 ++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/backend/alembic/versions/6e2d1d2b7c4a_add_ai_interactions.py b/backend/alembic/versions/6e2d1d2b7c4a_add_ai_interactions.py index 6656cb4..6357e58 100644 --- a/backend/alembic/versions/6e2d1d2b7c4a_add_ai_interactions.py +++ b/backend/alembic/versions/6e2d1d2b7c4a_add_ai_interactions.py @@ -19,16 +19,19 @@ def upgrade() -> None: - # Create Enum types - # Note: Using sa.Enum in create_table will automatically create the type if it doesn't exist, - # but for PostgreSQL it's often better to create it explicitly if we want to be safe. + # Safely create enum types if they don't exist + op.execute("DO $$ BEGIN CREATE TYPE ai_interaction_type AS ENUM ('highlight', 'question', 'summary', 'quiz'); EXCEPTION WHEN duplicate_object THEN null; END $$;") + op.execute("DO $$ BEGIN CREATE TYPE ai_action_type AS ENUM ('explain_simple', 'define', 'analogy', 'example', 'expand_acronym'); EXCEPTION WHEN duplicate_object THEN null; END $$;") + + # Add new value 'answer_question' to ai_action_type if it doesn't already exist + op.execute("ALTER TYPE ai_action_type ADD VALUE IF NOT EXISTS 'answer_question'") op.create_table('ai_interactions', sa.Column('id', sa.UUID(), nullable=False), sa.Column('user_id', sa.UUID(), nullable=False), sa.Column('document_id', sa.UUID(), nullable=False), - sa.Column('interaction_type', sa.Enum('highlight', 'question', 'summary', 'quiz', name='aiinteractiontype'), nullable=False), - sa.Column('action', sa.Enum('explain_simple', 'define', 'analogy', 'example', 'expand_acronym', 'answer_question', name='aiactiontype'), nullable=False), + sa.Column('interaction_type', sa.Enum('highlight', 'question', 'summary', 'quiz', name='ai_interaction_type'), nullable=False), + sa.Column('action', sa.Enum('explain_simple', 'define', 'analogy', 'example', 'expand_acronym', 'answer_question', name='ai_action_type'), nullable=False), sa.Column('input_text', sa.Text(), nullable=False), sa.Column('response_text', sa.Text(), nullable=False), sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False), @@ -49,6 +52,5 @@ def downgrade() -> None: op.drop_table('ai_interactions') # Drop types - # Note: Be careful with dropping types if they are used elsewhere, but here they are specific to this table. - sa.Enum(name='aiinteractiontype').drop(op.get_bind()) - sa.Enum(name='aiactiontype').drop(op.get_bind()) + sa.Enum(name='ai_interaction_type').drop(op.get_bind()) + sa.Enum(name='ai_action_type').drop(op.get_bind()) diff --git a/backend/app/models/ai_interaction.py b/backend/app/models/ai_interaction.py index 34d373f..e72ce12 100644 --- a/backend/app/models/ai_interaction.py +++ b/backend/app/models/ai_interaction.py @@ -50,12 +50,12 @@ class AIInteraction(Base): ) interaction_type = Column( - Enum(AIInteractionType), + Enum(AIInteractionType, name="ai_interaction_type", create_type=False), nullable=False ) action = Column( - Enum(AIActionType), + Enum(AIActionType, name="ai_action_type", create_type=False), nullable=False )