🐸 Frogue(Fed)

~ololduck/Frogue

Raw

use sea_orm_migration::prelude::*;

#[derive(DeriveMigrationName)]
pub struct Migration;

#[async_trait::async_trait]
impl MigrationTrait for Migration {
    async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
        // SQLite does not support ADD CONSTRAINT, so the CHECK constraint
        // must live in the CREATE TABLE statement. Raw SQL it is.
        manager
            .get_connection()
            .execute_unprepared(
                "CREATE TABLE IF NOT EXISTS comments (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    uuid TEXT NOT NULL UNIQUE,
                    author_id INTEGER NOT NULL,
                    ticket_id INTEGER,
                    patch_proposal_id INTEGER,
                    content TEXT NOT NULL,
                    created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
                    updated_at TIMESTAMP WITH TIME ZONE,
                    FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE,
                    FOREIGN KEY (ticket_id) REFERENCES tickets(id) ON DELETE CASCADE,
                    FOREIGN KEY (patch_proposal_id) REFERENCES patch_proposals(id) ON DELETE CASCADE,
                    CHECK ((ticket_id IS NOT NULL) != (patch_proposal_id IS NOT NULL))
                )",
            )
            .await?;

        // The CHECK constraint above ensures exactly one of ticket_id or
        // patch_proposal_id is set: a comment must target either a ticket or
        // a patch proposal, never both, never neither.
        manager
            .get_connection()
            .execute_unprepared(
                "CREATE INDEX IF NOT EXISTS index_comments_on_ticket_id_and_created_at \
                 ON comments (ticket_id, created_at)",
            )
            .await?;
        manager
            .get_connection()
            .execute_unprepared(
                "CREATE INDEX IF NOT EXISTS index_comments_on_patch_proposal_id_and_created_at \
                 ON comments (patch_proposal_id, created_at)",
            )
            .await?;

        Ok(())
    }

    async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
        manager
            .get_connection()
            .execute_unprepared("DROP TABLE IF EXISTS comments")
            .await?;
        Ok(())
    }
}