"""create dataset_review_sessions table Previously this table was created at runtime by init_db() → Base.metadata.create_all(). Migration f0e9d8c7b6a5 references it (altering the environment_id FK to add ondelete='CASCADE'), so the table must exist when that migration runs. This migration creates dataset_review_sessions with the FK already having ondelete='CASCADE' (matching the model). On fresh databases, f0e9d8c7b6a5's drop+recreate of this FK is a no-op. On databases upgraded from before the FK had CASCADE, f0e9d8c7b6a5 still applies the change. Revision ID: e1f2a3b4c5d6 Revises: a5b6c7d8e9f0 Create Date: 2026-06-11 17:10:00.000000 """ from collections.abc import Sequence import sqlalchemy as sa from alembic import op # revision identifiers, used by Alembic. revision: str = 'e1f2a3b4c5d6' down_revision: str | Sequence[str] | None = 'a5b6c7d8e9f0' branch_labels: str | Sequence[str] | None = None depends_on: str | Sequence[str] | None = None def upgrade() -> None: """Create dataset_review_sessions table.""" op.create_table( 'dataset_review_sessions', sa.Column('session_id', sa.String(), nullable=False), sa.Column('user_id', sa.String(), nullable=False), sa.Column('environment_id', sa.String(), nullable=False), sa.Column('source_kind', sa.String(), nullable=False), sa.Column('source_input', sa.String(), nullable=False), sa.Column('dataset_ref', sa.String(), nullable=False), sa.Column('dataset_id', sa.Integer(), nullable=True), sa.Column('dashboard_id', sa.Integer(), nullable=True), sa.Column('readiness_state', sa.Enum( 'empty', 'importing', 'review_ready', 'semantic_source_review_needed', 'clarification_needed', 'clarification_active', 'mapping_review_needed', 'compiled_preview_ready', 'partially_ready', 'run_ready', 'run_in_progress', 'completed', 'recovery_required', name='readinessstate', create_type=False, ), nullable=False), sa.Column('recommended_action', sa.Enum( 'import_from_superset', 'review_documentation', 'apply_semantic_source', 'start_clarification', 'answer_next_question', 'approve_mapping', 'generate_sql_preview', 'complete_required_values', 'launch_dataset', 'resume_session', 'export_outputs', name='recommendedaction', create_type=False, ), nullable=False), sa.Column('version', sa.Integer(), nullable=False, server_default=sa.text('0')), sa.Column('status', sa.Enum( 'active', 'paused', 'completed', 'archived', 'cancelled', name='sessionstatus', create_type=False, ), nullable=False), sa.Column('current_phase', sa.Enum( 'intake', 'recovery', 'review', 'semantic_review', 'clarification', 'mapping_review', 'preview', 'launch', 'post_run', name='sessionphase', create_type=False, ), nullable=False), sa.Column('active_task_id', sa.String(), nullable=True), sa.Column('last_preview_id', sa.String(), nullable=True), sa.Column('last_run_context_id', sa.String(), nullable=True), sa.Column('created_at', sa.DateTime(), nullable=False), sa.Column('updated_at', sa.DateTime(), nullable=False), sa.Column('last_activity_at', sa.DateTime(), nullable=False), sa.Column('closed_at', sa.DateTime(), nullable=True), sa.ForeignKeyConstraint( ['environment_id'], ['environments.id'], ondelete='CASCADE', name='dataset_review_sessions_environment_id_fkey', ), sa.ForeignKeyConstraint( ['user_id'], ['users.id'], name='dataset_review_sessions_user_id_fkey', ), sa.PrimaryKeyConstraint('session_id'), ) def downgrade() -> None: """Drop dataset_review_sessions table.""" op.drop_table('dataset_review_sessions') op.execute('DROP TYPE IF EXISTS readinessstate') op.execute('DROP TYPE IF EXISTS recommendedaction') op.execute('DROP TYPE IF EXISTS sessionstatus') op.execute('DROP TYPE IF EXISTS sessionphase')