"""add core business indexes and contact submit_date Revision ID: n123456789ab Revises: c72a6f69e641 Create Date: 2026-06-29 14:00:00.000000 """ from typing import Sequence, Union from alembic import op import sqlalchemy as sa revision: str = "n123456789ab" down_revision: Union[str, None] = "c72a6f69e641" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: # 1. Add submit_date column to contact_requests op.add_column( "contact_requests", sa.Column("submit_date", sa.String(10), nullable=True) ) # Backfill submit_date from created_at for existing records op.execute( "UPDATE contact_requests SET submit_date = TO_CHAR(created_at AT TIME ZONE 'UTC', 'YYYY-MM-DD') WHERE submit_date IS NULL" ) # Set NOT NULL after backfill op.alter_column("contact_requests", "submit_date", nullable=False) # Create index on submit_date op.create_index( "ix_contact_requests_submit_date", "contact_requests", ["submit_date"], unique=False, ) # 2. Contact requests unique constraint: (user_id, submit_date) op.create_unique_constraint( "uq_contact_user_date", "contact_requests", ["user_id", "submit_date"], ) # 3. Contact requests composite indexes op.create_index( "idx_contact_handled_created", "contact_requests", ["is_handled", "created_at"], unique=False, ) op.create_index( "idx_contact_user_date_created", "contact_requests", ["user_id", "submit_date", "created_at"], unique=False, ) # 4. Generation records composite indexes op.create_index( "idx_genrec_user_status_created", "generation_records", ["user_id", "status", "created_at"], unique=False, ) op.create_index( "idx_genrec_project_status", "generation_records", ["project_id", "status"], unique=False, ) # 5. Payment orders composite indexes op.create_index( "idx_payorder_user_status_created", "payment_orders", ["user_id", "status", "created_at"], unique=False, ) op.create_index( "idx_payorder_status_created", "payment_orders", ["status", "created_at"], unique=False, ) # 6. Upload task composite indexes op.create_index( "idx_upload_user_status_created", "upload_task", ["user_id", "status", "created_at"], unique=False, ) op.create_index( "idx_upload_oauth_status", "upload_task", ["oauth_id", "status"], unique=False, ) # 7. Menu configs indexes op.create_index( op.f("ix_menu_configs_parent_id"), "menu_configs", ["parent_id"], unique=False, ) op.create_index( "idx_menu_target_active_sort", "menu_configs", ["menu_target", "is_active", "sort_order"], unique=False, ) # 8. Operation logs composite indexes op.create_index( "idx_oplog_user_created", "operation_logs", ["user_id", "created_at"], unique=False, ) op.create_index( "idx_oplog_created", "operation_logs", ["created_at"], unique=False, ) # 9. Notification indexes (from previous optimization) op.create_index( "idx_notif_user_isread_created", "notifications", ["user_id", "is_read", "created_at"], unique=False, ) # 10. Notification reads indexes op.create_index( "idx_notif_read_user_notif", "notification_reads", ["user_id", "notification_id"], unique=False, ) op.create_unique_constraint( "uq_notif_read_user", "notification_reads", ["notification_id", "user_id"], ) def downgrade() -> None: op.drop_constraint("uq_notif_read_user", "notification_reads", type_="unique") op.drop_index("idx_notif_read_user_notif", table_name="notification_reads") op.drop_index("idx_notif_user_isread_created", table_name="notifications") op.drop_index("idx_oplog_created", table_name="operation_logs") op.drop_index("idx_oplog_user_created", table_name="operation_logs") op.drop_index("idx_menu_target_active_sort", table_name="menu_configs") op.drop_index(op.f("ix_menu_configs_parent_id"), table_name="menu_configs") op.drop_index("idx_upload_oauth_status", table_name="upload_task") op.drop_index("idx_upload_user_status_created", table_name="upload_task") op.drop_index("idx_payorder_status_created", table_name="payment_orders") op.drop_index("idx_payorder_user_status_created", table_name="payment_orders") op.drop_index("idx_genrec_project_status", table_name="generation_records") op.drop_index("idx_genrec_user_status_created", table_name="generation_records") op.drop_index("idx_contact_user_date_created", table_name="contact_requests") op.drop_index("idx_contact_handled_created", table_name="contact_requests") op.drop_constraint("uq_contact_user_date", "contact_requests", type_="unique") op.drop_index("ix_contact_requests_submit_date", table_name="contact_requests") op.drop_column("contact_requests", "submit_date")