"""Initial schema Revision ID: 001 Revises: Create Date: 2025-01-30 """ from collections.abc import Sequence import sqlalchemy as sa from alembic import op from sqlalchemy.dialects import postgresql revision: str = "001" down_revision: str | None = None branch_labels: str | Sequence[str] | None = None depends_on: str | Sequence[str] | None = None def upgrade() -> None: # Create difficulty enum using raw SQL to avoid SQLAlchemy auto-creation issues op.execute("CREATE TYPE difficulty_enum AS ENUM ('easy', 'medium', 'hard')") # Create questions table op.create_table( "questions", sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True), sa.Column("title", sa.String(255), nullable=False), sa.Column("slug", sa.String(255), unique=True, nullable=False), sa.Column( "difficulty", postgresql.ENUM("easy", "medium", "hard", name="difficulty_enum", create_type=False), nullable=False, ), sa.Column("description", sa.Text, nullable=False), sa.Column("constraints", sa.Text, nullable=True), sa.Column("examples", postgresql.JSONB, nullable=True), sa.Column("leetcode_id", sa.Integer, unique=True, nullable=True), sa.Column("leetcode_url", sa.String(512), nullable=True), sa.Column( "created_at", sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False, ), sa.Column( "updated_at", sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False, ), ) op.create_index("ix_questions_slug", "questions", ["slug"]) op.create_index("ix_questions_difficulty", "questions", ["difficulty"]) # Create explanations table op.create_table( "explanations", sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True), sa.Column( "question_id", postgresql.UUID(as_uuid=True), sa.ForeignKey("questions.id", ondelete="CASCADE"), unique=True, nullable=False, ), sa.Column("approach", sa.Text, nullable=False), sa.Column("intuition", sa.Text, nullable=False), sa.Column("common_pitfalls", postgresql.JSONB, nullable=True), sa.Column("key_takeaways", postgresql.JSONB, nullable=True), sa.Column("time_complexity", sa.String(50), nullable=False), sa.Column("space_complexity", sa.String(50), nullable=False), sa.Column("complexity_explanation", sa.Text, nullable=True), ) # Create solutions table op.create_table( "solutions", sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True), sa.Column( "question_id", postgresql.UUID(as_uuid=True), sa.ForeignKey("questions.id", ondelete="CASCADE"), nullable=False, ), sa.Column("approach_name", sa.String(100), nullable=False), sa.Column("code", sa.Text, nullable=False), sa.Column("language", sa.String(20), server_default="python", nullable=False), sa.Column("is_optimal", sa.Boolean, server_default="false", nullable=False), sa.Column("explanation", sa.Text, nullable=True), ) op.create_index("ix_solutions_question_id", "solutions", ["question_id"]) # Create categories table op.create_table( "categories", sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True), sa.Column("name", sa.String(100), unique=True, nullable=False), sa.Column("slug", sa.String(100), unique=True, nullable=False), sa.Column("description", sa.Text, nullable=True), ) op.create_index("ix_categories_slug", "categories", ["slug"]) # Create patterns table op.create_table( "patterns", sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True), sa.Column("name", sa.String(100), unique=True, nullable=False), sa.Column("slug", sa.String(100), unique=True, nullable=False), sa.Column("description", sa.Text, nullable=True), sa.Column("when_to_use", sa.Text, nullable=True), ) op.create_index("ix_patterns_slug", "patterns", ["slug"]) # Create question_categories junction table op.create_table( "question_categories", sa.Column( "question_id", postgresql.UUID(as_uuid=True), sa.ForeignKey("questions.id", ondelete="CASCADE"), primary_key=True, ), sa.Column( "category_id", postgresql.UUID(as_uuid=True), sa.ForeignKey("categories.id", ondelete="CASCADE"), primary_key=True, ), ) # Create question_patterns junction table op.create_table( "question_patterns", sa.Column( "question_id", postgresql.UUID(as_uuid=True), sa.ForeignKey("questions.id", ondelete="CASCADE"), primary_key=True, ), sa.Column( "pattern_id", postgresql.UUID(as_uuid=True), sa.ForeignKey("patterns.id", ondelete="CASCADE"), primary_key=True, ), ) def downgrade() -> None: op.drop_table("question_patterns") op.drop_table("question_categories") op.drop_table("patterns") op.drop_table("categories") op.drop_table("solutions") op.drop_table("explanations") op.drop_table("questions") op.execute("DROP TYPE IF EXISTS difficulty_enum")