🐸 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> {
        // Drop the old ticket-specific attachments table
        manager
            .drop_table(Table::drop().table(TicketAttachments::Table).to_owned())
            .await?;

        // Create the generic attachments table
        manager
            .create_table(
                Table::create()
                    .table(Attachments::Table)
                    .if_not_exists()
                    .col(
                        ColumnDef::new(Attachments::Id)
                            .integer()
                            .not_null()
                            .auto_increment()
                            .primary_key(),
                    )
                    .col(
                        ColumnDef::new(Attachments::Uuid)
                            .uuid()
                            .not_null()
                            .unique_key(),
                    )
                    .col(ColumnDef::new(Attachments::OwnerKind).text().not_null())
                    .col(ColumnDef::new(Attachments::OwnerId).integer().not_null())
                    .col(ColumnDef::new(Attachments::Filename).text().not_null())
                    .col(ColumnDef::new(Attachments::ContentType).text().not_null())
                    .col(ColumnDef::new(Attachments::Size).integer().not_null())
                    .col(ColumnDef::new(Attachments::RemoteUrl).text())
                    .col(
                        ColumnDef::new(Attachments::CreatedAt)
                            .timestamp_with_time_zone()
                            .not_null()
                            .default(Expr::current_timestamp()),
                    )
                    .col(ColumnDef::new(Attachments::TicketId).integer())
                    .col(ColumnDef::new(Attachments::CommentId).integer())
                    .col(ColumnDef::new(Attachments::ApNoteId).integer())
                    .foreign_key(
                        ForeignKey::create()
                            .name("fk_attachments_ticket_id")
                            .from(Attachments::Table, Attachments::TicketId)
                            .to(Tickets::Table, Tickets::Id)
                            .on_delete(ForeignKeyAction::Cascade),
                    )
                    .foreign_key(
                        ForeignKey::create()
                            .name("fk_attachments_comment_id")
                            .from(Attachments::Table, Attachments::CommentId)
                            .to(Comments::Table, Comments::Id)
                            .on_delete(ForeignKeyAction::Cascade),
                    )
                    .foreign_key(
                        ForeignKey::create()
                            .name("fk_attachments_ap_note_id")
                            .from(Attachments::Table, Attachments::ApNoteId)
                            .to(ApNotes::Table, ApNotes::Id)
                            .on_delete(ForeignKeyAction::Cascade),
                    )
                    .check(
                        Expr::expr(
                            Expr::col(Attachments::OwnerKind)
                                .eq("ticket")
                                .and(Expr::col(Attachments::TicketId).is_not_null())
                                .and(Expr::col(Attachments::CommentId).is_null())
                                .and(Expr::col(Attachments::ApNoteId).is_null()),
                        )
                        .or(Expr::col(Attachments::OwnerKind)
                            .eq("comment")
                            .and(Expr::col(Attachments::TicketId).is_null())
                            .and(Expr::col(Attachments::CommentId).is_not_null())
                            .and(Expr::col(Attachments::ApNoteId).is_null()))
                        .or(Expr::col(Attachments::OwnerKind)
                            .eq("ap_note")
                            .and(Expr::col(Attachments::TicketId).is_null())
                            .and(Expr::col(Attachments::CommentId).is_null())
                            .and(Expr::col(Attachments::ApNoteId).is_not_null())),
                    )
                    .to_owned(),
            )
            .await?;

        // Create indexes
        manager
            .create_index(
                Index::create()
                    .name("idx_attachments_ticket")
                    .table(Attachments::Table)
                    .col(Attachments::TicketId)
                    .col(Attachments::CreatedAt)
                    .to_owned(),
            )
            .await?;

        manager
            .create_index(
                Index::create()
                    .name("idx_attachments_comment")
                    .table(Attachments::Table)
                    .col(Attachments::CommentId)
                    .col(Attachments::CreatedAt)
                    .to_owned(),
            )
            .await?;

        manager
            .create_index(
                Index::create()
                    .name("idx_attachments_ap_note")
                    .table(Attachments::Table)
                    .col(Attachments::ApNoteId)
                    .col(Attachments::CreatedAt)
                    .to_owned(),
            )
            .await?;

        Ok(())
    }

    async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
        manager
            .drop_table(Table::drop().table(Attachments::Table).to_owned())
            .await?;

        // Recreate the old ticket_attachments table
        manager
            .create_table(
                Table::create()
                    .table(TicketAttachments::Table)
                    .if_not_exists()
                    .col(
                        ColumnDef::new(TicketAttachments::Id)
                            .integer()
                            .not_null()
                            .auto_increment()
                            .primary_key(),
                    )
                    .col(
                        ColumnDef::new(TicketAttachments::Uuid)
                            .text()
                            .not_null()
                            .unique_key(),
                    )
                    .col(
                        ColumnDef::new(TicketAttachments::TicketId)
                            .integer()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(TicketAttachments::Filename)
                            .text()
                            .not_null(),
                    )
                    .col(
                        ColumnDef::new(TicketAttachments::ContentType)
                            .text()
                            .not_null(),
                    )
                    .col(ColumnDef::new(TicketAttachments::Size).integer().not_null())
                    .col(ColumnDef::new(TicketAttachments::Data).blob().not_null())
                    .col(
                        ColumnDef::new(TicketAttachments::CreatedAt)
                            .timestamp_with_time_zone()
                            .not_null()
                            .default(Expr::current_timestamp()),
                    )
                    .foreign_key(
                        ForeignKey::create()
                            .name("fk_ticket_attachments_ticket_id")
                            .from(TicketAttachments::Table, TicketAttachments::TicketId)
                            .to(Tickets::Table, Tickets::Id)
                            .on_delete(ForeignKeyAction::Cascade),
                    )
                    .to_owned(),
            )
            .await?;

        Ok(())
    }
}

#[derive(Iden)]
enum Tickets {
    Table,
    Id,
}

#[derive(Iden)]
enum Comments {
    Table,
    Id,
}

#[derive(Iden)]
enum ApNotes {
    Table,
    Id,
}

#[derive(Iden)]
enum Attachments {
    Table,
    Id,
    Uuid,
    OwnerKind,
    OwnerId,
    Filename,
    ContentType,
    Size,
    RemoteUrl,
    CreatedAt,
    TicketId,
    CommentId,
    ApNoteId,
}

#[derive(Iden)]
enum TicketAttachments {
    Table,
    Id,
    Uuid,
    TicketId,
    Filename,
    ContentType,
    Size,
    Data,
    CreatedAt,
}