"""add account_id to AI branching tables Revision ID: 478c159e5654 Revises: cc214c63aa30 Create Date: 2026-04-09 00:00:00.000000 """ from typing import Sequence, Union from alembic import op import sqlalchemy as sa revision: str = '478c159e5654' down_revision: Union[str, None] = 'cc214c63aa30' branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: ai_tables = ('session_branches', 'session_handoffs', 'fork_points', 'ai_session_steps') # Step 1: ADD COLUMN (nullable) for table in ai_tables: op.add_column(table, sa.Column('account_id', sa.UUID(), nullable=True)) op.create_foreign_key( f'fk_{table}_account_id', table, 'accounts', ['account_id'], ['id'], ondelete='CASCADE', ) op.add_column('ai_suggestions', sa.Column('account_id', sa.UUID(), nullable=True)) op.create_foreign_key( 'fk_ai_suggestions_account_id', 'ai_suggestions', 'accounts', ['account_id'], ['id'], ondelete='CASCADE', ) # Step 2: BACKFILL for table in ai_tables: op.execute(f""" UPDATE {table} t SET account_id = ai.account_id FROM ai_sessions ai WHERE t.session_id = ai.id AND t.account_id IS NULL """) op.execute(""" UPDATE ai_suggestions s SET account_id = u.account_id FROM users u WHERE s.user_id = u.id AND s.account_id IS NULL """) # Step 3: VERIFY zero NULLs for table in ai_tables + ('ai_suggestions',): result = op.get_bind().execute( sa.text(f"SELECT COUNT(*) FROM {table} WHERE account_id IS NULL") ) count = result.scalar() if count > 0: raise RuntimeError( f"ROLLBACK: {count} NULL account_id rows in {table}." ) # Step 4: SET NOT NULL for table in ai_tables + ('ai_suggestions',): op.alter_column(table, 'account_id', nullable=False) # Step 5: CREATE INDEX for table in ai_tables + ('ai_suggestions',): op.create_index(f'ix_{table}_account_id', table, ['account_id']) def downgrade() -> None: for table in ('session_branches', 'session_handoffs', 'fork_points', 'ai_session_steps', 'ai_suggestions'): op.drop_index(f'ix_{table}_account_id', table_name=table) op.drop_constraint(f'fk_{table}_account_id', table, type_='foreignkey') op.drop_column(table, 'account_id')