feat(migration): configurable migration table name (#1511)
This commit is contained in:
parent
473b769386
commit
a806898f74
@ -6,12 +6,12 @@ use std::time::SystemTime;
|
|||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
use sea_orm::sea_query::{
|
use sea_orm::sea_query::{
|
||||||
self, extension::postgres::Type, Alias, Expr, ForeignKey, Iden, JoinType, Query,
|
self, extension::postgres::Type, Alias, Expr, ForeignKey, Iden, IntoIden, JoinType, Order,
|
||||||
SelectStatement, SimpleExpr, Table,
|
Query, SelectStatement, SimpleExpr, Table,
|
||||||
};
|
};
|
||||||
use sea_orm::{
|
use sea_orm::{
|
||||||
ActiveModelTrait, ActiveValue, ColumnTrait, Condition, ConnectionTrait, DbBackend, DbErr,
|
ActiveModelTrait, ActiveValue, Condition, ConnectionTrait, DbBackend, DbErr, DynIden,
|
||||||
EntityTrait, QueryFilter, QueryOrder, Schema, Statement, TransactionTrait,
|
EntityTrait, FromQueryResult, Iterable, QueryFilter, Schema, Statement, TransactionTrait,
|
||||||
};
|
};
|
||||||
use sea_schema::{mysql::MySql, postgres::Postgres, probe::SchemaProbe, sqlite::Sqlite};
|
use sea_schema::{mysql::MySql, postgres::Postgres, probe::SchemaProbe, sqlite::Sqlite};
|
||||||
|
|
||||||
@ -59,6 +59,11 @@ pub trait MigratorTrait: Send {
|
|||||||
/// Vector of migrations in time sequence
|
/// Vector of migrations in time sequence
|
||||||
fn migrations() -> Vec<Box<dyn MigrationTrait>>;
|
fn migrations() -> Vec<Box<dyn MigrationTrait>>;
|
||||||
|
|
||||||
|
/// Name of the migration table, it is `seaql_migrations` by default
|
||||||
|
fn migration_table_name() -> DynIden {
|
||||||
|
seaql_migrations::Entity.into_iden()
|
||||||
|
}
|
||||||
|
|
||||||
/// Get list of migrations wrapped in `Migration` struct
|
/// Get list of migrations wrapped in `Migration` struct
|
||||||
fn get_migration_files() -> Vec<Migration> {
|
fn get_migration_files() -> Vec<Migration> {
|
||||||
Self::migrations()
|
Self::migrations()
|
||||||
@ -76,8 +81,13 @@ pub trait MigratorTrait: Send {
|
|||||||
C: ConnectionTrait,
|
C: ConnectionTrait,
|
||||||
{
|
{
|
||||||
Self::install(db).await?;
|
Self::install(db).await?;
|
||||||
seaql_migrations::Entity::find()
|
let stmt = Query::select()
|
||||||
.order_by_asc(seaql_migrations::Column::Version)
|
.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)
|
.all(db)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -154,7 +164,9 @@ pub trait MigratorTrait: Send {
|
|||||||
{
|
{
|
||||||
let builder = db.get_database_backend();
|
let builder = db.get_database_backend();
|
||||||
let schema = Schema::new(builder);
|
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();
|
stmt.if_not_exists();
|
||||||
db.execute(builder.build(&stmt)).await.map(|_| ())
|
db.execute(builder.build(&stmt)).await.map(|_| ())
|
||||||
}
|
}
|
||||||
@ -374,11 +386,12 @@ where
|
|||||||
let now = SystemTime::now()
|
let now = SystemTime::now()
|
||||||
.duration_since(SystemTime::UNIX_EPOCH)
|
.duration_since(SystemTime::UNIX_EPOCH)
|
||||||
.expect("SystemTime before UNIX EPOCH!");
|
.expect("SystemTime before UNIX EPOCH!");
|
||||||
seaql_migrations::ActiveModel {
|
seaql_migrations::Entity::insert(seaql_migrations::ActiveModel {
|
||||||
version: ActiveValue::Set(migration.name().to_owned()),
|
version: ActiveValue::Set(migration.name().to_owned()),
|
||||||
applied_at: ActiveValue::Set(now.as_secs() as i64),
|
applied_at: ActiveValue::Set(now.as_secs() as i64),
|
||||||
}
|
})
|
||||||
.insert(db)
|
.table_name(M::migration_table_name())
|
||||||
|
.exec(db)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,7 +427,8 @@ where
|
|||||||
migration.down(manager).await?;
|
migration.down(manager).await?;
|
||||||
info!("Migration '{}' has been rollbacked", migration.name());
|
info!("Migration '{}' has been rollbacked", migration.name());
|
||||||
seaql_migrations::Entity::delete_many()
|
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)
|
.exec(db)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
@ -525,3 +539,51 @@ where
|
|||||||
);
|
);
|
||||||
stmt
|
stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait QueryTable {
|
||||||
|
type Statement;
|
||||||
|
|
||||||
|
fn table_name(self, table_name: DynIden) -> Self::Statement;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QueryTable for SelectStatement {
|
||||||
|
type Statement = SelectStatement;
|
||||||
|
|
||||||
|
fn table_name(mut self, table_name: DynIden) -> SelectStatement {
|
||||||
|
self.from(table_name);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QueryTable for sea_query::TableCreateStatement {
|
||||||
|
type Statement = sea_query::TableCreateStatement;
|
||||||
|
|
||||||
|
fn table_name(mut self, table_name: DynIden) -> sea_query::TableCreateStatement {
|
||||||
|
self.table(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: DynIden) -> sea_orm::Insert<A> {
|
||||||
|
sea_orm::QueryTrait::query(&mut self).into_table(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: DynIden) -> sea_orm::DeleteMany<E> {
|
||||||
|
sea_orm::QueryTrait::query(&mut self).from_table(table_name);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
#[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")]
|
#[sea_orm(table_name = "seaql_migrations")]
|
||||||
pub struct Model {
|
pub struct Model {
|
||||||
#[sea_orm(primary_key, auto_increment = false)]
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
|
6
sea-orm-migration/tests/common/migration/mod.rs
Normal file
6
sea-orm-migration/tests/common/migration/mod.rs
Normal file
@ -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
sea-orm-migration/tests/common/migrator/default.rs
Normal file
18
sea-orm-migration/tests/common/migrator/default.rs
Normal file
@ -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
sea-orm-migration/tests/common/migrator/mod.rs
Normal file
2
sea-orm-migration/tests/common/migrator/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod default;
|
||||||
|
pub mod override_migration_table_name;
|
@ -1,12 +1,6 @@
|
|||||||
|
use crate::common::migration::*;
|
||||||
use sea_orm_migration::prelude::*;
|
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;
|
pub struct Migrator;
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
@ -21,4 +15,8 @@ impl MigratorTrait for Migrator {
|
|||||||
Box::new(m20230109_000001_seed_cake_table::Migration),
|
Box::new(m20230109_000001_seed_cake_table::Migration),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn migration_table_name() -> sea_orm::DynIden {
|
||||||
|
Alias::new("override_migration_table_name").into_iden()
|
||||||
|
}
|
||||||
}
|
}
|
2
sea-orm-migration/tests/common/mod.rs
Normal file
2
sea-orm-migration/tests/common/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod migration;
|
||||||
|
pub mod migrator;
|
@ -1,6 +1,6 @@
|
|||||||
mod migrator;
|
mod common;
|
||||||
use migrator::Migrator;
|
|
||||||
|
|
||||||
|
use common::migrator::*;
|
||||||
use sea_orm::{ConnectOptions, ConnectionTrait, Database, DbBackend, DbErr, Statement};
|
use sea_orm::{ConnectOptions, ConnectionTrait, Database, DbBackend, DbErr, Statement};
|
||||||
use sea_orm_migration::{migrator::MigrationStatus, prelude::*};
|
use sea_orm_migration::{migrator::MigrationStatus, prelude::*};
|
||||||
|
|
||||||
@ -13,14 +13,42 @@ async fn main() -> Result<(), DbErr> {
|
|||||||
|
|
||||||
let url = &std::env::var("DATABASE_URL").expect("Environment variable 'DATABASE_URL' not set");
|
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, default::Migrator, "sea_orm_migration", "public").await?;
|
||||||
|
run_migration(
|
||||||
|
url,
|
||||||
|
default::Migrator,
|
||||||
|
"sea_orm_migration_schema",
|
||||||
|
"my_schema",
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
run_migration(url, "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(())
|
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 db_connect = |url: String| async {
|
||||||
let connect_options = ConnectOptions::new(url)
|
let connect_options = ConnectOptions::new(url)
|
||||||
.set_schema_search_path(schema.to_owned())
|
.set_schema_search_path(schema.to_owned())
|
||||||
@ -75,7 +103,12 @@ async fn run_migration(url: &str, db_name: &str, schema: &str) -> Result<(), DbE
|
|||||||
println!("\nMigrator::install");
|
println!("\nMigrator::install");
|
||||||
Migrator::install(db).await?;
|
Migrator::install(db).await?;
|
||||||
|
|
||||||
assert!(manager.has_table("seaql_migrations").await?);
|
let migration_table_name = Migrator::migration_table_name().to_string();
|
||||||
|
let migration_table_name = migration_table_name.as_str();
|
||||||
|
assert!(manager.has_table(migration_table_name).await?);
|
||||||
|
if migration_table_name != "seaql_migrations" {
|
||||||
|
assert!(!manager.has_table("seaql_migrations").await?);
|
||||||
|
}
|
||||||
|
|
||||||
println!("\nMigrator::reset");
|
println!("\nMigrator::reset");
|
||||||
Migrator::reset(db).await?;
|
Migrator::reset(db).await?;
|
||||||
@ -192,7 +225,11 @@ async fn run_migration(url: &str, db_name: &str, schema: &str) -> Result<(), DbE
|
|||||||
println!("\nMigrator::down");
|
println!("\nMigrator::down");
|
||||||
Migrator::down(db, None).await?;
|
Migrator::down(db, None).await?;
|
||||||
|
|
||||||
assert!(manager.has_table("seaql_migrations").await?);
|
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("cake").await?);
|
||||||
assert!(!manager.has_table("fruit").await?);
|
assert!(!manager.has_table("fruit").await?);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user