Skip to content

Commit

Permalink
feat(migration): configurable migration table name
Browse files Browse the repository at this point in the history
  • Loading branch information
billy1624 committed Feb 27, 2023
1 parent 97b09b7 commit 7dec07f
Show file tree
Hide file tree
Showing 14 changed files with 152 additions and 26 deletions.
84 changes: 73 additions & 11 deletions sea-orm-migration/src/migrator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ use std::time::SystemTime;
use tracing::info;

use sea_orm::sea_query::{
self, extension::postgres::Type, Alias, Expr, ForeignKey, Iden, JoinType, Query,
SelectStatement, SimpleExpr, Table,
self, extension::postgres::Type, Alias, Expr, ForeignKey, Iden, IntoIden, JoinType, Order,
Query, SelectStatement, SimpleExpr, Table,
};
use sea_orm::{
ActiveModelTrait, ActiveValue, ColumnTrait, Condition, ConnectionTrait, DbBackend, DbErr,
EntityTrait, QueryFilter, QueryOrder, Schema, Statement, TransactionTrait,
ActiveModelTrait, ActiveValue, Condition, ConnectionTrait, DbBackend, DbErr, EntityTrait,
FromQueryResult, Iterable, QueryFilter, Schema, Statement, TransactionTrait,
};
use sea_schema::{mysql::MySql, postgres::Postgres, probe::SchemaProbe, sqlite::Sqlite};

Expand Down Expand Up @@ -47,6 +47,11 @@ pub trait MigratorTrait: Send {
/// Vector of migrations in time sequence
fn migrations() -> Vec<Box<dyn MigrationTrait>>;

/// Name of the migration table, it is `seaql_migrations` by default
fn migration_table_name() -> &'static str {
"seaql_migrations"
}

/// Get list of migrations wrapped in `Migration` struct
fn get_migration_files() -> Vec<Migration> {
Self::migrations()
Expand All @@ -64,8 +69,13 @@ pub trait MigratorTrait: Send {
C: ConnectionTrait,
{
Self::install(db).await?;
seaql_migrations::Entity::find()
.order_by_asc(seaql_migrations::Column::Version)
let stmt = Query::select()
.table_name(Self::migration_table_name())
.columns(seaql_migrations::Column::iter().map(IntoIden::into_iden))
.order_by(seaql_migrations::Column::Version, Order::Asc)
.to_owned();
let builder = db.get_database_backend();
seaql_migrations::Model::find_by_statement(builder.build(&stmt))
.all(db)
.await
}
Expand Down Expand Up @@ -142,7 +152,9 @@ pub trait MigratorTrait: Send {
{
let builder = db.get_database_backend();
let schema = Schema::new(builder);
let mut stmt = schema.create_table_from_entity(seaql_migrations::Entity);
let mut stmt = schema
.create_table_from_entity(seaql_migrations::Entity)
.table_name(Self::migration_table_name());
stmt.if_not_exists();
db.execute(builder.build(&stmt)).await.map(|_| ())
}
Expand Down Expand Up @@ -362,11 +374,12 @@ where
let now = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.expect("SystemTime before UNIX EPOCH!");
seaql_migrations::ActiveModel {
seaql_migrations::Entity::insert(seaql_migrations::ActiveModel {
version: ActiveValue::Set(migration.name().to_owned()),
applied_at: ActiveValue::Set(now.as_secs() as i64),
}
.insert(db)
})
.table_name(M::migration_table_name())
.exec(db)
.await?;
}

Expand Down Expand Up @@ -402,7 +415,8 @@ where
migration.down(manager).await?;
info!("Migration '{}' has been rollbacked", migration.name());
seaql_migrations::Entity::delete_many()
.filter(seaql_migrations::Column::Version.eq(migration.name()))
.filter(Expr::col(seaql_migrations::Column::Version).eq(migration.name()))
.table_name(M::migration_table_name())
.exec(db)
.await?;
}
Expand Down Expand Up @@ -513,3 +527,51 @@ where
);
stmt
}

trait QueryTable {
type Statement;

fn table_name(self, table_name: &str) -> Self::Statement;
}

impl QueryTable for SelectStatement {
type Statement = SelectStatement;

fn table_name(mut self, table_name: &str) -> SelectStatement {
self.from(Alias::new(table_name));
self
}
}

impl QueryTable for sea_query::TableCreateStatement {
type Statement = sea_query::TableCreateStatement;

fn table_name(mut self, table_name: &str) -> sea_query::TableCreateStatement {
self.table(Alias::new(table_name));
self
}
}

impl<A> QueryTable for sea_orm::Insert<A>
where
A: ActiveModelTrait,
{
type Statement = sea_orm::Insert<A>;

fn table_name(mut self, table_name: &str) -> sea_orm::Insert<A> {
sea_orm::QueryTrait::query(&mut self).into_table(Alias::new(table_name));
self
}
}

impl<E> QueryTable for sea_orm::DeleteMany<E>
where
E: EntityTrait,
{
type Statement = sea_orm::DeleteMany<E>;

fn table_name(mut self, table_name: &str) -> sea_orm::DeleteMany<E> {
sea_orm::QueryTrait::query(&mut self).from_table(Alias::new(table_name));
self
}
}
1 change: 1 addition & 0 deletions sea-orm-migration/src/seaql_migrations.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use sea_orm::entity::prelude::*;

#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
// One should override the name of migration table via `MigratorTrait::migration_table_name` method
#[sea_orm(table_name = "seaql_migrations")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
Expand Down
6 changes: 6 additions & 0 deletions sea-orm-migration/tests/common/migration/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pub mod m20220118_000001_create_cake_table;
pub mod m20220118_000002_create_fruit_table;
pub mod m20220118_000003_seed_cake_table;
pub mod m20220118_000004_create_tea_enum;
pub mod m20220923_000001_seed_cake_table;
pub mod m20230109_000001_seed_cake_table;
18 changes: 18 additions & 0 deletions sea-orm-migration/tests/common/migrator/default.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use crate::common::migration::*;
use sea_orm_migration::prelude::*;

pub struct Migrator;

#[async_trait::async_trait]
impl MigratorTrait for Migrator {
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
vec![
Box::new(m20220118_000001_create_cake_table::Migration),
Box::new(m20220118_000002_create_fruit_table::Migration),
Box::new(m20220118_000003_seed_cake_table::Migration),
Box::new(m20220118_000004_create_tea_enum::Migration),
Box::new(m20220923_000001_seed_cake_table::Migration),
Box::new(m20230109_000001_seed_cake_table::Migration),
]
}
}
2 changes: 2 additions & 0 deletions sea-orm-migration/tests/common/migrator/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod default;
pub mod override_migration_table_name;
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
use crate::common::migration::*;
use sea_orm_migration::prelude::*;

mod m20220118_000001_create_cake_table;
mod m20220118_000002_create_fruit_table;
mod m20220118_000003_seed_cake_table;
mod m20220118_000004_create_tea_enum;
mod m20220923_000001_seed_cake_table;
mod m20230109_000001_seed_cake_table;

pub struct Migrator;

#[async_trait::async_trait]
Expand All @@ -21,4 +15,8 @@ impl MigratorTrait for Migrator {
Box::new(m20230109_000001_seed_cake_table::Migration),
]
}

fn migration_table_name() -> &'static str {
"override_migration_table_name"
}
}
2 changes: 2 additions & 0 deletions sea-orm-migration/tests/common/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod migration;
pub mod migrator;
53 changes: 45 additions & 8 deletions sea-orm-migration/tests/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod migrator;
use migrator::Migrator;
mod common;

use common::migrator::*;
use sea_orm::{ConnectOptions, ConnectionTrait, Database, DbBackend, DbErr, Statement};
use sea_orm_migration::prelude::*;

Expand All @@ -13,14 +13,42 @@ async fn main() -> Result<(), DbErr> {

let url = &std::env::var("DATABASE_URL").expect("Environment variable 'DATABASE_URL' not set");

run_migration(url, "sea_orm_migration", "public").await?;

run_migration(url, "sea_orm_migration_schema", "my_schema").await?;
run_migration(url, default::Migrator, "sea_orm_migration", "public").await?;
run_migration(
url,
default::Migrator,
"sea_orm_migration_schema",
"my_schema",
)
.await?;

run_migration(
url,
override_migration_table_name::Migrator,
"sea_orm_migration_table_name",
"public",
)
.await?;
run_migration(
url,
override_migration_table_name::Migrator,
"sea_orm_migration_table_name_schema",
"my_schema",
)
.await?;

Ok(())
}

async fn run_migration(url: &str, db_name: &str, schema: &str) -> Result<(), DbErr> {
async fn run_migration<Migrator>(
url: &str,
_: Migrator,
db_name: &str,
schema: &str,
) -> Result<(), DbErr>
where
Migrator: MigratorTrait,
{
let db_connect = |url: String| async {
let connect_options = ConnectOptions::new(url)
.set_schema_search_path(schema.to_owned())
Expand Down Expand Up @@ -75,7 +103,11 @@ async fn run_migration(url: &str, db_name: &str, schema: &str) -> Result<(), DbE
println!("\nMigrator::install");
Migrator::install(db).await?;

assert!(manager.has_table("seaql_migrations").await?);
let migration_table_name = Migrator::migration_table_name();
assert!(manager.has_table(migration_table_name).await?);
if migration_table_name != "seaql_migrations" {
assert!(!manager.has_table("seaql_migrations").await?);
}

println!("\nMigrator::reset");
Migrator::reset(db).await?;
Expand Down Expand Up @@ -176,7 +208,12 @@ async fn run_migration(url: &str, db_name: &str, schema: &str) -> Result<(), DbE
println!("\nMigrator::down");
Migrator::down(db, None).await?;

assert!(manager.has_table("seaql_migrations").await?);
let migration_table_name = Migrator::migration_table_name();
assert!(manager.has_table(migration_table_name).await?);
if migration_table_name != "seaql_migrations" {
assert!(!manager.has_table("seaql_migrations").await?);
}

assert!(!manager.has_table("cake").await?);
assert!(!manager.has_table("fruit").await?);

Expand Down

0 comments on commit 7dec07f

Please sign in to comment.