diff --git a/sea-orm-migration/src/migrator.rs b/sea-orm-migration/src/migrator.rs index c62041b83..737c65646 100644 --- a/sea-orm-migration/src/migrator.rs +++ b/sea-orm-migration/src/migrator.rs @@ -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, DynIden, + EntityTrait, FromQueryResult, Iterable, QueryFilter, Schema, Statement, TransactionTrait, }; use sea_schema::{mysql::MySql, postgres::Postgres, probe::SchemaProbe, sqlite::Sqlite}; @@ -47,6 +47,11 @@ pub trait MigratorTrait: Send { /// Vector of migrations in time sequence fn migrations() -> Vec>; + /// 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 fn get_migration_files() -> Vec { Self::migrations() @@ -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 } @@ -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(|_| ()) } @@ -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?; } @@ -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?; } @@ -513,3 +527,51 @@ where ); 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 QueryTable for sea_orm::Insert +where + A: ActiveModelTrait, +{ + type Statement = sea_orm::Insert; + + fn table_name(mut self, table_name: DynIden) -> sea_orm::Insert { + sea_orm::QueryTrait::query(&mut self).into_table(table_name); + self + } +} + +impl QueryTable for sea_orm::DeleteMany +where + E: EntityTrait, +{ + type Statement = sea_orm::DeleteMany; + + fn table_name(mut self, table_name: DynIden) -> sea_orm::DeleteMany { + sea_orm::QueryTrait::query(&mut self).from_table(table_name); + self + } +} diff --git a/sea-orm-migration/src/seaql_migrations.rs b/sea-orm-migration/src/seaql_migrations.rs index 9926ea9c5..51da93009 100644 --- a/sea-orm-migration/src/seaql_migrations.rs +++ b/sea-orm-migration/src/seaql_migrations.rs @@ -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)] diff --git a/sea-orm-migration/tests/migrator/m20220118_000001_create_cake_table.rs b/sea-orm-migration/tests/common/migration/m20220118_000001_create_cake_table.rs similarity index 100% rename from sea-orm-migration/tests/migrator/m20220118_000001_create_cake_table.rs rename to sea-orm-migration/tests/common/migration/m20220118_000001_create_cake_table.rs diff --git a/sea-orm-migration/tests/migrator/m20220118_000002_create_fruit_table.rs b/sea-orm-migration/tests/common/migration/m20220118_000002_create_fruit_table.rs similarity index 100% rename from sea-orm-migration/tests/migrator/m20220118_000002_create_fruit_table.rs rename to sea-orm-migration/tests/common/migration/m20220118_000002_create_fruit_table.rs diff --git a/sea-orm-migration/tests/migrator/m20220118_000003_seed_cake_table.rs b/sea-orm-migration/tests/common/migration/m20220118_000003_seed_cake_table.rs similarity index 100% rename from sea-orm-migration/tests/migrator/m20220118_000003_seed_cake_table.rs rename to sea-orm-migration/tests/common/migration/m20220118_000003_seed_cake_table.rs diff --git a/sea-orm-migration/tests/migrator/m20220118_000004_create_tea_enum.rs b/sea-orm-migration/tests/common/migration/m20220118_000004_create_tea_enum.rs similarity index 100% rename from sea-orm-migration/tests/migrator/m20220118_000004_create_tea_enum.rs rename to sea-orm-migration/tests/common/migration/m20220118_000004_create_tea_enum.rs diff --git a/sea-orm-migration/tests/migrator/m20220923_000001_seed_cake_table.rs b/sea-orm-migration/tests/common/migration/m20220923_000001_seed_cake_table.rs similarity index 100% rename from sea-orm-migration/tests/migrator/m20220923_000001_seed_cake_table.rs rename to sea-orm-migration/tests/common/migration/m20220923_000001_seed_cake_table.rs diff --git a/sea-orm-migration/tests/migrator/m20230109_000001_seed_cake_table.rs b/sea-orm-migration/tests/common/migration/m20230109_000001_seed_cake_table.rs similarity index 100% rename from sea-orm-migration/tests/migrator/m20230109_000001_seed_cake_table.rs rename to sea-orm-migration/tests/common/migration/m20230109_000001_seed_cake_table.rs diff --git a/sea-orm-migration/tests/common/migration/mod.rs b/sea-orm-migration/tests/common/migration/mod.rs new file mode 100644 index 000000000..4e85a13ec --- /dev/null +++ b/sea-orm-migration/tests/common/migration/mod.rs @@ -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; diff --git a/sea-orm-migration/tests/common/migrator/default.rs b/sea-orm-migration/tests/common/migrator/default.rs new file mode 100644 index 000000000..284b0e81f --- /dev/null +++ b/sea-orm-migration/tests/common/migrator/default.rs @@ -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> { + 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), + ] + } +} diff --git a/sea-orm-migration/tests/common/migrator/mod.rs b/sea-orm-migration/tests/common/migrator/mod.rs new file mode 100644 index 000000000..772da4927 --- /dev/null +++ b/sea-orm-migration/tests/common/migrator/mod.rs @@ -0,0 +1,2 @@ +pub mod default; +pub mod override_migration_table_name; diff --git a/sea-orm-migration/tests/migrator/mod.rs b/sea-orm-migration/tests/common/migrator/override_migration_table_name.rs similarity index 72% rename from sea-orm-migration/tests/migrator/mod.rs rename to sea-orm-migration/tests/common/migrator/override_migration_table_name.rs index 7e7f68023..745122a9b 100644 --- a/sea-orm-migration/tests/migrator/mod.rs +++ b/sea-orm-migration/tests/common/migrator/override_migration_table_name.rs @@ -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] @@ -21,4 +15,8 @@ impl MigratorTrait for Migrator { Box::new(m20230109_000001_seed_cake_table::Migration), ] } + + fn migration_table_name() -> sea_orm::DynIden { + Alias::new("override_migration_table_name").into_iden() + } } diff --git a/sea-orm-migration/tests/common/mod.rs b/sea-orm-migration/tests/common/mod.rs new file mode 100644 index 000000000..f4ab07bae --- /dev/null +++ b/sea-orm-migration/tests/common/mod.rs @@ -0,0 +1,2 @@ +pub mod migration; +pub mod migrator; diff --git a/sea-orm-migration/tests/main.rs b/sea-orm-migration/tests/main.rs index 022ff8a53..815836e65 100644 --- a/sea-orm-migration/tests/main.rs +++ b/sea-orm-migration/tests/main.rs @@ -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::*; @@ -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( + 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()) @@ -75,7 +103,12 @@ 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().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"); Migrator::reset(db).await?; @@ -176,7 +209,11 @@ 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?); + 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?);