use sea_orm_migration::{prelude::*, sea_orm::ConnectionTrait, sea_query::Expr}; #[derive(DeriveMigrationName)] pub struct Migration; #[derive(DeriveIden)] enum UserRoles { Table, UserId, Role, AssignedBy, AssignedAt, } #[derive(DeriveIden)] enum Users { Table, Id, } #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(&self, m: &SchemaManager) -> Result<(), DbErr> { m.create_table( Table::create() .table(UserRoles::Table) .if_not_exists() .col(ColumnDef::new(UserRoles::UserId).integer().not_null()) .col(ColumnDef::new(UserRoles::Role).string_len(50).not_null()) .col(ColumnDef::new(UserRoles::AssignedBy).integer().null()) .col( ColumnDef::new(UserRoles::AssignedAt) .timestamp_with_time_zone() .not_null() .default(Expr::current_timestamp()), ) .primary_key( Index::create() .name("pk-user_roles") .col(UserRoles::UserId) .col(UserRoles::Role), ) .foreign_key( ForeignKey::create() .name("fk-user_roles-user_id-to-users") .from(UserRoles::Table, UserRoles::UserId) .to(Users::Table, Users::Id) .on_delete(ForeignKeyAction::Cascade) .on_update(ForeignKeyAction::Cascade), ) .foreign_key( ForeignKey::create() .name("fk-user_roles-assigned_by-to-users") .from(UserRoles::Table, UserRoles::AssignedBy) .to(Users::Table, Users::Id) .on_delete(ForeignKeyAction::SetNull) .on_update(ForeignKeyAction::NoAction), ) .to_owned(), ) .await?; m.create_index( Index::create() .name("idx-user_roles-user_id") .table(UserRoles::Table) .col(UserRoles::UserId) .to_owned(), ) .await?; let sql = match m.get_database_backend() { sea_orm_migration::sea_orm::DatabaseBackend::Postgres => { "INSERT INTO user_roles (user_id, role, assigned_at) \ SELECT id, 'user', CURRENT_TIMESTAMP FROM users \ ON CONFLICT (user_id, role) DO NOTHING" } sea_orm_migration::sea_orm::DatabaseBackend::Sqlite => { "INSERT OR IGNORE INTO user_roles (user_id, role, assigned_at) \ SELECT id, 'user', CURRENT_TIMESTAMP FROM users" } sea_orm_migration::sea_orm::DatabaseBackend::MySql => { "INSERT IGNORE INTO user_roles (user_id, role, assigned_at) \ SELECT id, 'user', CURRENT_TIMESTAMP FROM users" } }; m.get_connection().execute_unprepared(sql).await?; Ok(()) } async fn down(&self, m: &SchemaManager) -> Result<(), DbErr> { m.drop_table(Table::drop().table(UserRoles::Table).to_owned()) .await?; Ok(()) } }