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(())
}
}