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> { // 1. Create task_runs table manager .create_table( Table::create() .table(TaskRuns::Table) .if_not_exists() .col(ColumnDef::new(TaskRuns::Id).uuid().not_null().primary_key()) .col(ColumnDef::new(TaskRuns::TaskId).uuid().not_null()) .col(ColumnDef::new(TaskRuns::Status).string().not_null()) .col(ColumnDef::new(TaskRuns::Logs).text().not_null()) .col(ColumnDef::new(TaskRuns::Answer).text().null()) .col( ColumnDef::new(TaskRuns::CreatedAt) .timestamp_with_time_zone() .not_null(), ) .foreign_key( ForeignKey::create() .name("fk-task_runs-task_id") .from(TaskRuns::Table, TaskRuns::TaskId) .to(Tasks::Table, Tasks::Id) .on_delete(ForeignKeyAction::Cascade), ) .to_owned(), ) .await?; // 2. Migrate existing data from tasks to task_runs // We use raw SQL for simplicity in migration let db = manager.get_connection(); db.execute_unprepared( "INSERT INTO task_runs (id, task_id, status, logs, answer, created_at) SELECT id, id, status, logs, answer, created_at FROM tasks", ) .await?; // 3. Remove columns from tasks table (using a temp table for wider SQLite compatibility if needed, // but let's try alter table first as it's cleaner if supported) manager .alter_table( Table::alter() .table(Tasks::Table) .drop_column(Tasks::Status) .drop_column(Tasks::Logs) .drop_column(Tasks::Answer) .to_owned(), ) .await?; Ok(()) } async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { // Re-add columns to tasks manager .alter_table( Table::alter() .table(Tasks::Table) .add_column(ColumnDef::new(Tasks::Status).string().null()) .add_column(ColumnDef::new(Tasks::Logs).text().null()) .add_column(ColumnDef::new(Tasks::Answer).text().null()) .to_owned(), ) .await?; // Restore data from latest run if possible (best effort) let db = manager.get_connection(); db.execute_unprepared( "UPDATE tasks SET status = (SELECT status FROM task_runs WHERE task_id = tasks.id ORDER BY created_at DESC LIMIT 1), logs = (SELECT logs FROM task_runs WHERE task_id = tasks.id ORDER BY created_at DESC LIMIT 1), answer = (SELECT answer FROM task_runs WHERE task_id = tasks.id ORDER BY created_at DESC LIMIT 1)" ).await?; manager .drop_table(Table::drop().table(TaskRuns::Table).to_owned()) .await } } #[derive(DeriveIden)] enum TaskRuns { Table, Id, TaskId, Status, Logs, Answer, CreatedAt, } #[derive(DeriveIden)] enum Tasks { Table, Id, Status, Logs, Answer, }