Merge pull request #666 from SeaQL/sea-schema/dump-sea-orm-dep
Dump SeaORM Dependency from SeaSchema's Migrator
This commit is contained in:
commit
25f3db731b
24
.github/workflows/rust.yml
vendored
24
.github/workflows/rust.yml
vendored
@ -383,6 +383,14 @@ jobs:
|
|||||||
--test '*'
|
--test '*'
|
||||||
--features default,sqlx-sqlite,runtime-${{ matrix.runtime }}-${{ matrix.tls }}
|
--features default,sqlx-sqlite,runtime-${{ matrix.runtime }}-${{ matrix.tls }}
|
||||||
|
|
||||||
|
- uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: test
|
||||||
|
args: >
|
||||||
|
--manifest-path sea-orm-migration/Cargo.toml
|
||||||
|
--test '*'
|
||||||
|
--features sqlx-sqlite,runtime-${{ matrix.runtime }}-${{ matrix.tls }}
|
||||||
|
|
||||||
mysql:
|
mysql:
|
||||||
name: MySQL
|
name: MySQL
|
||||||
needs:
|
needs:
|
||||||
@ -444,6 +452,14 @@ jobs:
|
|||||||
--test '*'
|
--test '*'
|
||||||
--features default,sqlx-mysql,runtime-${{ matrix.runtime }}-${{ matrix.tls }}
|
--features default,sqlx-mysql,runtime-${{ matrix.runtime }}-${{ matrix.tls }}
|
||||||
|
|
||||||
|
- uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: test
|
||||||
|
args: >
|
||||||
|
--manifest-path sea-orm-migration/Cargo.toml
|
||||||
|
--test '*'
|
||||||
|
--features sqlx-mysql,runtime-${{ matrix.runtime }}-${{ matrix.tls }}
|
||||||
|
|
||||||
mariadb:
|
mariadb:
|
||||||
name: MariaDB
|
name: MariaDB
|
||||||
needs:
|
needs:
|
||||||
@ -562,3 +578,11 @@ jobs:
|
|||||||
args: >
|
args: >
|
||||||
--test '*'
|
--test '*'
|
||||||
--features default,sqlx-postgres,runtime-${{ matrix.runtime }}-${{ matrix.tls }}
|
--features default,sqlx-postgres,runtime-${{ matrix.runtime }}-${{ matrix.tls }}
|
||||||
|
|
||||||
|
- uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: test
|
||||||
|
args: >
|
||||||
|
--manifest-path sea-orm-migration/Cargo.toml
|
||||||
|
--test '*'
|
||||||
|
--features sqlx-postgres,runtime-${{ matrix.runtime }}-${{ matrix.tls }}
|
||||||
|
@ -44,7 +44,7 @@ once_cell = "1.8"
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
smol = { version = "^1.2" }
|
smol = { version = "^1.2" }
|
||||||
smol-potat = { version = "^1.1" }
|
smol-potat = { version = "^1.1" }
|
||||||
async-std = { version = "^1.9", features = ["attributes", "tokio1"] }
|
async-std = { version = "^1", features = ["attributes", "tokio1"] }
|
||||||
tokio = { version = "^1.6", features = ["full"] }
|
tokio = { version = "^1.6", features = ["full"] }
|
||||||
actix-rt = { version = "2.2.0" }
|
actix-rt = { version = "2.2.0" }
|
||||||
maplit = { version = "^1" }
|
maplit = { version = "^1" }
|
||||||
|
@ -12,7 +12,7 @@ path = "src/lib.rs"
|
|||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|
||||||
[dependencies.sea-orm]
|
[dependencies.sea-orm]
|
||||||
# path = "../../../" # remove this line in your own project
|
path = "../../../" # remove this line in your own project
|
||||||
version = "^0.7.0"
|
version = "^0.7.0"
|
||||||
features = [
|
features = [
|
||||||
"macros",
|
"macros",
|
||||||
|
@ -9,5 +9,8 @@ name = "migration"
|
|||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sea-schema = { version = "^0.7.0", default-features = false, features = [ "migration", "debug-print" ] }
|
|
||||||
entity = { path = "../entity" }
|
entity = { path = "../entity" }
|
||||||
|
|
||||||
|
[dependencies.sea-orm-migration]
|
||||||
|
path = "../../../sea-orm-migration" # remove this line in your own project
|
||||||
|
version = "^0.7.0"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
pub use sea_schema::migration::prelude::*;
|
pub use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
mod m20220120_000001_create_post_table;
|
mod m20220120_000001_create_post_table;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use entity::post::*;
|
use entity::post::*;
|
||||||
use sea_schema::migration::prelude::*;
|
use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
pub struct Migration;
|
pub struct Migration;
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use migration::Migrator;
|
use sea_orm_migration::prelude::*;
|
||||||
use sea_schema::migration::*;
|
|
||||||
|
|
||||||
#[async_std::main]
|
#[async_std::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
cli::run_cli(Migrator).await;
|
cli::run_cli(migration::Migrator).await;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ path = "src/lib.rs"
|
|||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|
||||||
[dependencies.sea-orm]
|
[dependencies.sea-orm]
|
||||||
# path = "../../../" # remove this line in your own project
|
path = "../../../" # remove this line in your own project
|
||||||
version = "^0.7.0"
|
version = "^0.7.0"
|
||||||
features = [
|
features = [
|
||||||
"macros",
|
"macros",
|
||||||
|
@ -9,5 +9,8 @@ name = "migration"
|
|||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sea-schema = { version = "^0.7.0", default-features = false, features = [ "migration", "debug-print" ] }
|
|
||||||
entity = { path = "../entity" }
|
entity = { path = "../entity" }
|
||||||
|
|
||||||
|
[dependencies.sea-orm-migration]
|
||||||
|
path = "../../../sea-orm-migration" # remove this line in your own project
|
||||||
|
version = "^0.7.0"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
pub use sea_schema::migration::prelude::*;
|
pub use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
mod m20220120_000001_create_post_table;
|
mod m20220120_000001_create_post_table;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use entity::post::*;
|
use entity::post::*;
|
||||||
use sea_schema::migration::prelude::*;
|
use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
pub struct Migration;
|
pub struct Migration;
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use migration::Migrator;
|
use sea_orm_migration::prelude::*;
|
||||||
use sea_schema::migration::*;
|
|
||||||
|
|
||||||
#[async_std::main]
|
#[async_std::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
cli::run_cli(Migrator).await;
|
cli::run_cli(migration::Migrator).await;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use actix_files::Files as Fs;
|
use actix_files::Files as Fs;
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
error, get, middleware, post, web, App, Error, HttpRequest, HttpResponse, HttpServer, Result
|
error, get, middleware, post, web, App, Error, HttpRequest, HttpResponse, HttpServer, Result,
|
||||||
};
|
};
|
||||||
|
|
||||||
use entity::post;
|
use entity::post;
|
||||||
|
@ -12,7 +12,7 @@ path = "src/lib.rs"
|
|||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|
||||||
[dependencies.sea-orm]
|
[dependencies.sea-orm]
|
||||||
# path = "../../../" # remove this line in your own project
|
path = "../../../" # remove this line in your own project
|
||||||
version = "^0.7.0"
|
version = "^0.7.0"
|
||||||
features = [
|
features = [
|
||||||
"macros",
|
"macros",
|
||||||
|
@ -9,5 +9,8 @@ name = "migration"
|
|||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sea-schema = { version = "^0.7.0", default-features = false, features = [ "migration", "debug-print" ] }
|
|
||||||
entity = { path = "../entity" }
|
entity = { path = "../entity" }
|
||||||
|
|
||||||
|
[dependencies.sea-orm-migration]
|
||||||
|
path = "../../../sea-orm-migration" # remove this line in your own project
|
||||||
|
version = "^0.7.0"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
pub use sea_schema::migration::prelude::*;
|
pub use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
mod m20220120_000001_create_post_table;
|
mod m20220120_000001_create_post_table;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use entity::post::*;
|
use entity::post::*;
|
||||||
use sea_schema::migration::prelude::*;
|
use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
pub struct Migration;
|
pub struct Migration;
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use migration::Migrator;
|
use sea_orm_migration::prelude::*;
|
||||||
use sea_schema::migration::*;
|
|
||||||
|
|
||||||
#[async_std::main]
|
#[async_std::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
cli::run_cli(Migrator).await;
|
cli::run_cli(migration::Migrator).await;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ serde = { version = "1", features = ["derive"] }
|
|||||||
version = "^3.0.38"
|
version = "^3.0.38"
|
||||||
|
|
||||||
[dependencies.sea-orm]
|
[dependencies.sea-orm]
|
||||||
|
path = "../../../" # remove this line in your own project
|
||||||
version = "^0.7.0"
|
version = "^0.7.0"
|
||||||
features = [
|
features = [
|
||||||
"macros",
|
"macros",
|
||||||
|
@ -9,6 +9,9 @@ name = "migration"
|
|||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sea-schema = { version = "^0.7.0", default-features = false, features = [ "migration", "debug-print" ] }
|
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
entity = { path = "../entity" }
|
entity = { path = "../entity" }
|
||||||
|
|
||||||
|
[dependencies.sea-orm-migration]
|
||||||
|
path = "../../../sea-orm-migration" # remove this line in your own project
|
||||||
|
version = "^0.7.0"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
pub use sea_schema::migration::*;
|
pub use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
mod m20220101_000001_create_table;
|
mod m20220101_000001_create_table;
|
||||||
|
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
|
use sea_orm_migration::prelude::*;
|
||||||
use entity::{
|
use entity::{
|
||||||
note,
|
note,
|
||||||
sea_orm::{DbBackend, EntityTrait, Schema},
|
sea_orm::{DbBackend, EntityTrait, Schema},
|
||||||
};
|
};
|
||||||
use sea_schema::migration::{
|
|
||||||
sea_query::*,
|
|
||||||
*,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct Migration;
|
pub struct Migration;
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use migration::Migrator;
|
use sea_orm_migration::prelude::*;
|
||||||
use sea_schema::migration::*;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
@ -22,5 +21,5 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
cli::run_cli(Migrator).await;
|
cli::run_cli(migration::Migrator).await;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ path = "src/lib.rs"
|
|||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|
||||||
[dependencies.sea-orm]
|
[dependencies.sea-orm]
|
||||||
# path = "../../../" # remove this line in your own project
|
path = "../../../" # remove this line in your own project
|
||||||
version = "^0.7.0"
|
version = "^0.7.0"
|
||||||
features = [
|
features = [
|
||||||
"macros",
|
"macros",
|
||||||
|
@ -9,5 +9,8 @@ name = "migration"
|
|||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sea-schema = { version = "^0.7.0", default-features = false, features = [ "migration", "debug-print" ] }
|
|
||||||
entity = { path = "../entity" }
|
entity = { path = "../entity" }
|
||||||
|
|
||||||
|
[dependencies.sea-orm-migration]
|
||||||
|
path = "../../../sea-orm-migration" # remove this line in your own project
|
||||||
|
version = "^0.7.0"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
pub use sea_schema::migration::prelude::*;
|
pub use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
mod m20220120_000001_create_post_table;
|
mod m20220120_000001_create_post_table;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use entity::post::*;
|
use entity::post::*;
|
||||||
use sea_schema::migration::prelude::*;
|
use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
pub struct Migration;
|
pub struct Migration;
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use migration::Migrator;
|
use sea_orm_migration::prelude::*;
|
||||||
use sea_schema::migration::*;
|
|
||||||
|
|
||||||
#[async_std::main]
|
#[async_std::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
cli::run_cli(Migrator).await;
|
cli::run_cli(migration::Migrator).await;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ path = "src/lib.rs"
|
|||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|
||||||
[dependencies.sea-orm]
|
[dependencies.sea-orm]
|
||||||
# path = "../../../" # remove this line in your own project
|
path = "../../../" # remove this line in your own project
|
||||||
version = "^0.7.0"
|
version = "^0.7.0"
|
||||||
features = [
|
features = [
|
||||||
"macros",
|
"macros",
|
||||||
|
@ -9,5 +9,8 @@ name = "migration"
|
|||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sea-schema = { version = "^0.7.0", default-features = false, features = [ "migration", "debug-print" ] }
|
|
||||||
entity = { path = "../entity" }
|
entity = { path = "../entity" }
|
||||||
|
|
||||||
|
[dependencies.sea-orm-migration]
|
||||||
|
path = "../../../sea-orm-migration" # remove this line in your own project
|
||||||
|
version = "^0.7.0"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
pub use sea_schema::migration::prelude::*;
|
pub use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
mod m20220120_000001_create_post_table;
|
mod m20220120_000001_create_post_table;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use entity::post::*;
|
use entity::post::*;
|
||||||
use sea_schema::migration::prelude::*;
|
use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
pub struct Migration;
|
pub struct Migration;
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use migration::Migrator;
|
use sea_orm_migration::prelude::*;
|
||||||
use sea_schema::migration::*;
|
|
||||||
|
|
||||||
#[async_std::main]
|
#[async_std::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
cli::run_cli(Migrator).await;
|
cli::run_cli(migration::Migrator).await;
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ rocket = { version = "0.5.0-rc.1", features = [
|
|||||||
] }
|
] }
|
||||||
|
|
||||||
[dependencies.sea-orm]
|
[dependencies.sea-orm]
|
||||||
# path = "../../../" # remove this line in your own project
|
path = "../../../" # remove this line in your own project
|
||||||
version = "^0.7.0"
|
version = "^0.7.0"
|
||||||
features = [
|
features = [
|
||||||
"macros",
|
"macros",
|
||||||
|
@ -9,6 +9,9 @@ name = "migration"
|
|||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sea-schema = { version = "^0.7.0", default-features = false, features = [ "migration", "debug-print" ] }
|
|
||||||
entity = { path = "../entity" }
|
entity = { path = "../entity" }
|
||||||
|
|
||||||
|
[dependencies.sea-orm-migration]
|
||||||
|
path = "../../../sea-orm-migration" # remove this line in your own project
|
||||||
|
version = "^0.7.0"
|
||||||
rocket = { version = "0.5.0-rc.1" }
|
rocket = { version = "0.5.0-rc.1" }
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
pub use sea_schema::migration::prelude::*;
|
pub use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
mod m20220120_000001_create_post_table;
|
mod m20220120_000001_create_post_table;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use entity::post::*;
|
use entity::post::*;
|
||||||
use sea_schema::migration::prelude::*;
|
use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
pub struct Migration;
|
pub struct Migration;
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use migration::Migrator;
|
use sea_orm_migration::prelude::*;
|
||||||
use sea_schema::migration::prelude::*;
|
|
||||||
|
|
||||||
#[async_std::main]
|
#[async_std::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
@ -14,5 +13,5 @@ async fn main() {
|
|||||||
std::env::set_var(key, database_url);
|
std::env::set_var(key, database_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
cli::run_cli(Migrator).await;
|
cli::run_cli(migration::Migrator).await;
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@ tonic = "0.7"
|
|||||||
tokio = { version = "1.17", features = ["macros", "rt-multi-thread", "full"] }
|
tokio = { version = "1.17", features = ["macros", "rt-multi-thread", "full"] }
|
||||||
entity = { path = "entity" }
|
entity = { path = "entity" }
|
||||||
migration = { path = "migration" }
|
migration = { path = "migration" }
|
||||||
sea-orm = { version = "0.7.1", features = [ "sqlx-postgres", "runtime-tokio-rustls", "macros" ] }
|
|
||||||
prost = "0.10.0"
|
prost = "0.10.0"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ path = "src/lib.rs"
|
|||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
|
||||||
[dependencies.sea-orm]
|
[dependencies.sea-orm]
|
||||||
# path = "../../../" # remove this line in your own project
|
path = "../../../" # remove this line in your own project
|
||||||
version = "^0.7.0"
|
version = "^0.7.0"
|
||||||
features = [
|
features = [
|
||||||
"macros",
|
"macros",
|
||||||
|
@ -9,5 +9,8 @@ name = "migration"
|
|||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sea-schema = { version = "^0.7.0", default-features = false, features = [ "migration", "debug-print" ] }
|
|
||||||
entity = { path = "../entity" }
|
entity = { path = "../entity" }
|
||||||
|
|
||||||
|
[dependencies.sea-orm-migration]
|
||||||
|
path = "../../../sea-orm-migration" # remove this line in your own project
|
||||||
|
version = "^0.7.0"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
pub use sea_schema::migration::prelude::*;
|
pub use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
mod m20220120_000001_create_post_table;
|
mod m20220120_000001_create_post_table;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use entity::post::*;
|
use entity::post::*;
|
||||||
use sea_schema::migration::prelude::*;
|
use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
pub struct Migration;
|
pub struct Migration;
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use migration::Migrator;
|
use sea_orm_migration::prelude::*;
|
||||||
use sea_schema::migration::*;
|
|
||||||
|
|
||||||
#[async_std::main]
|
#[async_std::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
cli::run_cli(Migrator).await;
|
cli::run_cli(migration::Migrator).await;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ use sea_orm_tonic_example::post::{
|
|||||||
|
|
||||||
use entity::{
|
use entity::{
|
||||||
post::{self, Entity as PostEntity},
|
post::{self, Entity as PostEntity},
|
||||||
sea_orm::{entity::*, query::*, DatabaseConnection},
|
sea_orm::{self, entity::*, query::*, DatabaseConnection},
|
||||||
};
|
};
|
||||||
use migration::{Migrator, MigratorTrait};
|
use migration::{Migrator, MigratorTrait};
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@ categories = [ "database" ]
|
|||||||
keywords = ["async", "orm", "mysql", "postgres", "sqlite"]
|
keywords = ["async", "orm", "mysql", "postgres", "sqlite"]
|
||||||
default-run = "sea-orm-cli"
|
default-run = "sea-orm-cli"
|
||||||
|
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "sea_orm_cli"
|
name = "sea_orm_cli"
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
@ -22,26 +21,20 @@ path = "src/lib.rs"
|
|||||||
[[bin]]
|
[[bin]]
|
||||||
name = "sea-orm-cli"
|
name = "sea-orm-cli"
|
||||||
path = "src/bin/main.rs"
|
path = "src/bin/main.rs"
|
||||||
|
required-features = ["codegen"]
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "sea"
|
name = "sea"
|
||||||
path = "src/bin/sea.rs"
|
path = "src/bin/sea.rs"
|
||||||
|
required-features = ["codegen"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "^2.33.3" }
|
clap = { version = "^2.33.3" }
|
||||||
dotenv = { version = "^0.15" }
|
dotenv = { version = "^0.15" }
|
||||||
async-std = { version = "^1.9", features = [ "attributes", "tokio1" ] }
|
async-std = { version = "^1.9", features = [ "attributes", "tokio1" ] }
|
||||||
sea-orm-codegen = { version = "^0.7.0", path = "../sea-orm-codegen" }
|
sea-orm-codegen = { version = "^0.7.0", path = "../sea-orm-codegen", optional = true }
|
||||||
sea-schema = { version = "^0.7.0", default-features = false, features = [
|
sea-schema = { git = "https://github.com/SeaQL/sea-schema", branch = "master" }
|
||||||
"debug-print",
|
sqlx = { version = "^0.5", default-features = false, features = [ "mysql", "postgres" ], optional = true }
|
||||||
"sqlx-mysql",
|
|
||||||
"sqlx-sqlite",
|
|
||||||
"sqlx-postgres",
|
|
||||||
"discovery",
|
|
||||||
"writer",
|
|
||||||
"migration",
|
|
||||||
] }
|
|
||||||
sqlx = { version = "^0.5", default-features = false, features = [ "mysql", "postgres" ] }
|
|
||||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||||
tracing = { version = "0.1" }
|
tracing = { version = "0.1" }
|
||||||
url = "^2.2"
|
url = "^2.2"
|
||||||
@ -50,28 +43,11 @@ url = "^2.2"
|
|||||||
smol = "1.2.5"
|
smol = "1.2.5"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = [ "runtime-async-std-native-tls" ]
|
default = [ "codegen", "runtime-async-std-native-tls" ]
|
||||||
runtime-actix-native-tls = [
|
codegen = [ "sea-schema/sqlx-all", "sea-orm-codegen" ]
|
||||||
"sqlx/runtime-actix-native-tls",
|
runtime-actix-native-tls = [ "sqlx/runtime-actix-native-tls", "sea-schema/runtime-actix-native-tls" ]
|
||||||
"sea-schema/runtime-actix-native-tls",
|
runtime-async-std-native-tls = [ "sqlx/runtime-async-std-native-tls", "sea-schema/runtime-async-std-native-tls" ]
|
||||||
]
|
runtime-tokio-native-tls = [ "sqlx/runtime-tokio-native-tls", "sea-schema/runtime-tokio-native-tls" ]
|
||||||
runtime-async-std-native-tls = [
|
runtime-actix-rustls = [ "sqlx/runtime-actix-rustls", "sea-schema/runtime-actix-rustls" ]
|
||||||
"sqlx/runtime-async-std-native-tls",
|
runtime-async-std-rustls = [ "sqlx/runtime-async-std-rustls", "sea-schema/runtime-async-std-rustls" ]
|
||||||
"sea-schema/runtime-async-std-native-tls",
|
runtime-tokio-rustls = [ "sqlx/runtime-tokio-rustls", "sea-schema/runtime-tokio-rustls" ]
|
||||||
]
|
|
||||||
runtime-tokio-native-tls = [
|
|
||||||
"sqlx/runtime-tokio-native-tls",
|
|
||||||
"sea-schema/runtime-tokio-native-tls",
|
|
||||||
]
|
|
||||||
runtime-actix-rustls = [
|
|
||||||
"sqlx/runtime-actix-rustls",
|
|
||||||
"sea-schema/runtime-actix-rustls",
|
|
||||||
]
|
|
||||||
runtime-async-std-rustls = [
|
|
||||||
"sqlx/runtime-async-std-rustls",
|
|
||||||
"sea-schema/runtime-async-std-rustls",
|
|
||||||
]
|
|
||||||
runtime-tokio-rustls = [
|
|
||||||
"sqlx/runtime-tokio-rustls",
|
|
||||||
"sea-schema/runtime-tokio-rustls",
|
|
||||||
]
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::migration::get_subcommands;
|
||||||
use clap::{App, AppSettings, Arg, SubCommand};
|
use clap::{App, AppSettings, Arg, SubCommand};
|
||||||
|
|
||||||
pub fn build_cli() -> App<'static, 'static> {
|
pub fn build_cli() -> App<'static, 'static> {
|
||||||
@ -95,7 +96,7 @@ pub fn build_cli() -> App<'static, 'static> {
|
|||||||
.arg(arg_migration_dir.clone()),
|
.arg(arg_migration_dir.clone()),
|
||||||
)
|
)
|
||||||
.arg(arg_migration_dir.clone());
|
.arg(arg_migration_dir.clone());
|
||||||
for subcommand in sea_schema::migration::get_subcommands() {
|
for subcommand in get_subcommands() {
|
||||||
migrate_subcommands =
|
migrate_subcommands =
|
||||||
migrate_subcommands.subcommand(subcommand.arg(arg_migration_dir.clone()));
|
migrate_subcommands.subcommand(subcommand.arg(arg_migration_dir.clone()));
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ pub async fn run_generate_command(matches: &ArgMatches<'_>) -> Result<(), Box<dy
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
"sqlite" => {
|
"sqlite" => {
|
||||||
use sea_schema::sqlite::SchemaDiscovery;
|
use sea_schema::sqlite::discovery::SchemaDiscovery;
|
||||||
use sqlx::Sqlite;
|
use sqlx::Sqlite;
|
||||||
|
|
||||||
let connection = connect::<Sqlite>(max_connections, url.as_str()).await?;
|
let connection = connect::<Sqlite>(max_connections, url.as_str()).await?;
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
pub mod cli;
|
pub mod cli;
|
||||||
|
#[cfg(feature = "codegen")]
|
||||||
pub mod commands;
|
pub mod commands;
|
||||||
|
pub mod migration;
|
||||||
|
|
||||||
pub use cli::*;
|
pub use cli::*;
|
||||||
|
#[cfg(feature = "codegen")]
|
||||||
pub use commands::*;
|
pub use commands::*;
|
||||||
|
49
sea-orm-cli/src/migration.rs
Normal file
49
sea-orm-cli/src/migration.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
use clap::{App, AppSettings, Arg, SubCommand};
|
||||||
|
|
||||||
|
pub fn build_cli() -> App<'static, 'static> {
|
||||||
|
let mut app = App::new("sea-schema-migration")
|
||||||
|
.version(env!("CARGO_PKG_VERSION"))
|
||||||
|
.setting(AppSettings::VersionlessSubcommands)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("VERBOSE")
|
||||||
|
.long("verbose")
|
||||||
|
.short("v")
|
||||||
|
.help("Show debug messages")
|
||||||
|
.takes_value(false)
|
||||||
|
.global(true),
|
||||||
|
);
|
||||||
|
for subcommand in get_subcommands() {
|
||||||
|
app = app.subcommand(subcommand);
|
||||||
|
}
|
||||||
|
app
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_subcommands() -> Vec<App<'static, 'static>> {
|
||||||
|
vec![
|
||||||
|
SubCommand::with_name("fresh")
|
||||||
|
.about("Drop all tables from the database, then reapply all migrations"),
|
||||||
|
SubCommand::with_name("refresh")
|
||||||
|
.about("Rollback all applied migrations, then reapply all migrations"),
|
||||||
|
SubCommand::with_name("reset").about("Rollback all applied migrations"),
|
||||||
|
SubCommand::with_name("status").about("Check the status of all migrations"),
|
||||||
|
SubCommand::with_name("up")
|
||||||
|
.about("Apply pending migrations")
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("NUM_MIGRATION")
|
||||||
|
.long("num")
|
||||||
|
.short("n")
|
||||||
|
.help("Number of pending migrations to be applied")
|
||||||
|
.takes_value(true),
|
||||||
|
),
|
||||||
|
SubCommand::with_name("down")
|
||||||
|
.about("Rollback applied migrations")
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("NUM_MIGRATION")
|
||||||
|
.long("num")
|
||||||
|
.short("n")
|
||||||
|
.help("Number of pending migrations to be rolled back")
|
||||||
|
.takes_value(true)
|
||||||
|
.default_value("1"),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
}
|
@ -9,4 +9,8 @@ name = "migration"
|
|||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sea-schema = { version = "^0.7.0", default-features = false, features = [ "migration", "debug-print" ] }
|
entity = { path = "../entity" }
|
||||||
|
|
||||||
|
[dependencies.sea-orm-migration]
|
||||||
|
path = "../../../sea-orm-migration" # remove this line in your own project
|
||||||
|
version = "^0.7.0"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
pub use sea_schema::migration::prelude::*;
|
pub use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
mod m20220101_000001_create_table;
|
mod m20220101_000001_create_table;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use sea_schema::migration::prelude::*;
|
use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
pub struct Migration;
|
pub struct Migration;
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use migration::Migrator;
|
use sea_orm_migration::prelude::*;
|
||||||
use sea_schema::migration::prelude::*;
|
|
||||||
|
|
||||||
#[async_std::main]
|
#[async_std::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
cli::run_cli(Migrator).await;
|
cli::run_cli(migration::Migrator).await;
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ name = "sea_orm_codegen"
|
|||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
sea-query = { version = "0.22.0" }
|
sea-query = { version = "^0.24.0" }
|
||||||
syn = { version = "^1", default-features = false, features = [
|
syn = { version = "^1", default-features = false, features = [
|
||||||
"derive",
|
"derive",
|
||||||
"parsing",
|
"parsing",
|
||||||
|
40
sea-orm-migration/Cargo.toml
Normal file
40
sea-orm-migration/Cargo.toml
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[workspace]
|
||||||
|
# A separate workspace
|
||||||
|
|
||||||
|
[package]
|
||||||
|
name = "sea-orm-migration"
|
||||||
|
version = "0.7.2"
|
||||||
|
authors = [ "Billy Chan <ccw.billy.123@gmail.com>" ]
|
||||||
|
edition = "2021"
|
||||||
|
description = "Migration utility for SeaORM"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
documentation = "https://docs.rs/sea-orm"
|
||||||
|
repository = "https://github.com/SeaQL/sea-orm"
|
||||||
|
categories = [ "database" ]
|
||||||
|
keywords = ["async", "orm", "mysql", "postgres", "sqlite"]
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "sea_orm_migration"
|
||||||
|
path = "src/lib.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
async-std = { version = "^1", features = ["attributes", "tokio1"] }
|
||||||
|
async-trait = { version = "^0.1" }
|
||||||
|
clap = { version = "^2.33" }
|
||||||
|
dotenv = { version = "^0.15" }
|
||||||
|
sea-orm = { path = "../", default-features = false, features = ["macros"] }
|
||||||
|
sea-orm-cli = { path = "../sea-orm-cli", default-features = false }
|
||||||
|
sea-schema = { git = "https://github.com/SeaQL/sea-schema", branch = "master" }
|
||||||
|
tracing = { version = "0.1", features = ["log"] }
|
||||||
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
sqlx-mysql = ["sea-orm/sqlx-mysql"]
|
||||||
|
sqlx-postgres = ["sea-orm/sqlx-postgres"]
|
||||||
|
sqlx-sqlite = ["sea-orm/sqlx-sqlite"]
|
||||||
|
runtime-actix-native-tls = [ "sea-orm/runtime-actix-native-tls" ]
|
||||||
|
runtime-async-std-native-tls = [ "sea-orm/runtime-async-std-native-tls" ]
|
||||||
|
runtime-tokio-native-tls = [ "sea-orm/runtime-tokio-native-tls" ]
|
||||||
|
runtime-actix-rustls = [ "sea-orm/runtime-actix-rustls" ]
|
||||||
|
runtime-async-std-rustls = [ "sea-orm/runtime-async-std-rustls" ]
|
||||||
|
runtime-tokio-rustls = [ "sea-orm/runtime-tokio-rustls" ]
|
77
sea-orm-migration/README.md
Normal file
77
sea-orm-migration/README.md
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
# SeaORM CLI
|
||||||
|
|
||||||
|
Install and Usage:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
> cargo install sea-orm-cli
|
||||||
|
> sea-orm-cli help
|
||||||
|
```
|
||||||
|
|
||||||
|
Or:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
> cargo install --bin sea
|
||||||
|
> sea help
|
||||||
|
```
|
||||||
|
|
||||||
|
Getting Help:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo run -- -h
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running Entity Generator:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# MySQL (`--database-schema` option is ignored)
|
||||||
|
cargo run -- generate entity -u mysql://sea:sea@localhost/bakery -o out
|
||||||
|
|
||||||
|
# SQLite (`--database-schema` option is ignored)
|
||||||
|
cargo run -- generate entity -u sqlite://bakery.db -o out
|
||||||
|
|
||||||
|
# PostgreSQL
|
||||||
|
cargo run -- generate entity -u postgres://sea:sea@localhost/bakery -s public -o out
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running Migration:
|
||||||
|
|
||||||
|
- Initialize migration directory
|
||||||
|
```sh
|
||||||
|
cargo run -- migrate init
|
||||||
|
```
|
||||||
|
- Apply all pending migrations
|
||||||
|
```sh
|
||||||
|
cargo run -- migrate
|
||||||
|
```
|
||||||
|
```sh
|
||||||
|
cargo run -- migrate up
|
||||||
|
```
|
||||||
|
- Apply first 10 pending migrations
|
||||||
|
```sh
|
||||||
|
cargo run -- migrate up -n 10
|
||||||
|
```
|
||||||
|
- Rollback last applied migrations
|
||||||
|
```sh
|
||||||
|
cargo run -- migrate down
|
||||||
|
```
|
||||||
|
- Rollback last 10 applied migrations
|
||||||
|
```sh
|
||||||
|
cargo run -- migrate down -n 10
|
||||||
|
```
|
||||||
|
- Drop all tables from the database, then reapply all migrations
|
||||||
|
```sh
|
||||||
|
cargo run -- migrate fresh
|
||||||
|
```
|
||||||
|
- Rollback all applied migrations, then reapply all migrations
|
||||||
|
```sh
|
||||||
|
cargo run -- migrate refresh
|
||||||
|
```
|
||||||
|
- Rollback all applied migrations
|
||||||
|
```sh
|
||||||
|
cargo run -- migrate reset
|
||||||
|
```
|
||||||
|
- Check the status of all migrations
|
||||||
|
```sh
|
||||||
|
cargo run -- migrate status
|
||||||
|
```
|
||||||
|
|
83
sea-orm-migration/src/cli.rs
Normal file
83
sea-orm-migration/src/cli.rs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
use clap::App;
|
||||||
|
use dotenv::dotenv;
|
||||||
|
use std::{fmt::Display, process::exit};
|
||||||
|
use tracing_subscriber::{prelude::*, EnvFilter};
|
||||||
|
|
||||||
|
use sea_orm::{Database, DbConn};
|
||||||
|
use sea_orm_cli::build_cli;
|
||||||
|
|
||||||
|
use super::MigratorTrait;
|
||||||
|
|
||||||
|
pub async fn run_cli<M>(migrator: M)
|
||||||
|
where
|
||||||
|
M: MigratorTrait,
|
||||||
|
{
|
||||||
|
dotenv().ok();
|
||||||
|
let url = std::env::var("DATABASE_URL").expect("Environment variable 'DATABASE_URL' not set");
|
||||||
|
let db = &Database::connect(&url).await.unwrap();
|
||||||
|
let app = build_cli();
|
||||||
|
get_matches(migrator, db, app).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_matches<M>(_: M, db: &DbConn, app: App<'static, 'static>)
|
||||||
|
where
|
||||||
|
M: MigratorTrait,
|
||||||
|
{
|
||||||
|
let matches = app.get_matches();
|
||||||
|
let mut verbose = false;
|
||||||
|
let filter = match matches.subcommand() {
|
||||||
|
(_, None) => "sea_schema::migration=info",
|
||||||
|
(_, Some(args)) => match args.is_present("VERBOSE") {
|
||||||
|
true => {
|
||||||
|
verbose = true;
|
||||||
|
"debug"
|
||||||
|
}
|
||||||
|
false => "sea_schema::migration=info",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let filter_layer = EnvFilter::try_new(filter).unwrap();
|
||||||
|
if verbose {
|
||||||
|
let fmt_layer = tracing_subscriber::fmt::layer();
|
||||||
|
tracing_subscriber::registry()
|
||||||
|
.with(filter_layer)
|
||||||
|
.with(fmt_layer)
|
||||||
|
.init()
|
||||||
|
} else {
|
||||||
|
let fmt_layer = tracing_subscriber::fmt::layer()
|
||||||
|
.with_target(false)
|
||||||
|
.with_level(false)
|
||||||
|
.without_time();
|
||||||
|
tracing_subscriber::registry()
|
||||||
|
.with(filter_layer)
|
||||||
|
.with(fmt_layer)
|
||||||
|
.init()
|
||||||
|
};
|
||||||
|
match matches.subcommand() {
|
||||||
|
("fresh", _) => M::fresh(db).await,
|
||||||
|
("refresh", _) => M::refresh(db).await,
|
||||||
|
("reset", _) => M::reset(db).await,
|
||||||
|
("status", _) => M::status(db).await,
|
||||||
|
("up", None) => M::up(db, None).await,
|
||||||
|
("down", None) => M::down(db, Some(1)).await,
|
||||||
|
("up", Some(args)) => {
|
||||||
|
let str = args.value_of("NUM_MIGRATION").unwrap_or_default();
|
||||||
|
let steps = str.parse().ok();
|
||||||
|
M::up(db, steps).await
|
||||||
|
}
|
||||||
|
("down", Some(args)) => {
|
||||||
|
let str = args.value_of("NUM_MIGRATION").unwrap();
|
||||||
|
let steps = str.parse().ok().unwrap_or(1);
|
||||||
|
M::down(db, Some(steps)).await
|
||||||
|
}
|
||||||
|
_ => M::up(db, None).await,
|
||||||
|
}
|
||||||
|
.unwrap_or_else(handle_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_error<E>(error: E)
|
||||||
|
where
|
||||||
|
E: Display,
|
||||||
|
{
|
||||||
|
eprintln!("{}", error);
|
||||||
|
exit(1);
|
||||||
|
}
|
28
sea-orm-migration/src/lib.rs
Normal file
28
sea-orm-migration/src/lib.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
pub mod cli;
|
||||||
|
pub mod manager;
|
||||||
|
pub mod migrator;
|
||||||
|
pub mod prelude;
|
||||||
|
pub mod seaql_migrations;
|
||||||
|
|
||||||
|
pub use manager::*;
|
||||||
|
pub use migrator::*;
|
||||||
|
|
||||||
|
pub use async_std;
|
||||||
|
pub use async_trait;
|
||||||
|
pub use sea_orm;
|
||||||
|
pub use sea_orm::sea_query;
|
||||||
|
pub use sea_orm::DbErr;
|
||||||
|
|
||||||
|
pub trait MigrationName {
|
||||||
|
fn name(&self) -> &str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The migration definition
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
pub trait MigrationTrait: MigrationName + Send + Sync {
|
||||||
|
/// Define actions to perform when applying the migration
|
||||||
|
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr>;
|
||||||
|
|
||||||
|
/// Define actions to perform when rolling back the migration
|
||||||
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr>;
|
||||||
|
}
|
133
sea-orm-migration/src/manager.rs
Normal file
133
sea-orm-migration/src/manager.rs
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
use sea_orm::sea_query::{
|
||||||
|
extension::postgres::{TypeAlterStatement, TypeCreateStatement, TypeDropStatement},
|
||||||
|
Alias, Expr, ForeignKeyCreateStatement, ForeignKeyDropStatement, IndexCreateStatement,
|
||||||
|
IndexDropStatement, Query, TableAlterStatement, TableCreateStatement, TableDropStatement,
|
||||||
|
TableRenameStatement, TableTruncateStatement,
|
||||||
|
};
|
||||||
|
use sea_orm::{Condition, ConnectionTrait, DbBackend, DbConn, DbErr, Statement, StatementBuilder};
|
||||||
|
use sea_schema::{mysql::MySql, postgres::Postgres, probe::SchemaProbe, sqlite::Sqlite};
|
||||||
|
|
||||||
|
/// Helper struct for writing migration scripts in migration file
|
||||||
|
pub struct SchemaManager<'c> {
|
||||||
|
conn: &'c DbConn,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'c> SchemaManager<'c> {
|
||||||
|
pub fn new(conn: &'c DbConn) -> Self {
|
||||||
|
Self { conn }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn exec_stmt<S>(&self, stmt: S) -> Result<(), DbErr>
|
||||||
|
where
|
||||||
|
S: StatementBuilder,
|
||||||
|
{
|
||||||
|
let builder = self.conn.get_database_backend();
|
||||||
|
self.conn.execute(builder.build(&stmt)).await.map(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_database_backend(&self) -> DbBackend {
|
||||||
|
self.conn.get_database_backend()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_connection(&self) -> &'c DbConn {
|
||||||
|
self.conn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Schema Creation
|
||||||
|
impl<'c> SchemaManager<'c> {
|
||||||
|
pub async fn create_table(&self, stmt: TableCreateStatement) -> Result<(), DbErr> {
|
||||||
|
self.exec_stmt(stmt).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn create_index(&self, stmt: IndexCreateStatement) -> Result<(), DbErr> {
|
||||||
|
self.exec_stmt(stmt).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn create_foreign_key(&self, stmt: ForeignKeyCreateStatement) -> Result<(), DbErr> {
|
||||||
|
self.exec_stmt(stmt).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn create_type(&self, stmt: TypeCreateStatement) -> Result<(), DbErr> {
|
||||||
|
self.exec_stmt(stmt).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Schema Mutation
|
||||||
|
impl<'c> SchemaManager<'c> {
|
||||||
|
pub async fn alter_table(&self, stmt: TableAlterStatement) -> Result<(), DbErr> {
|
||||||
|
self.exec_stmt(stmt).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn drop_table(&self, stmt: TableDropStatement) -> Result<(), DbErr> {
|
||||||
|
self.exec_stmt(stmt).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn rename_table(&self, stmt: TableRenameStatement) -> Result<(), DbErr> {
|
||||||
|
self.exec_stmt(stmt).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn truncate_table(&self, stmt: TableTruncateStatement) -> Result<(), DbErr> {
|
||||||
|
self.exec_stmt(stmt).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn drop_index(&self, stmt: IndexDropStatement) -> Result<(), DbErr> {
|
||||||
|
self.exec_stmt(stmt).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn drop_foreign_key(&self, stmt: ForeignKeyDropStatement) -> Result<(), DbErr> {
|
||||||
|
self.exec_stmt(stmt).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn alter_type(&self, stmt: TypeAlterStatement) -> Result<(), DbErr> {
|
||||||
|
self.exec_stmt(stmt).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn drop_type(&self, stmt: TypeDropStatement) -> Result<(), DbErr> {
|
||||||
|
self.exec_stmt(stmt).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Schema Inspection
|
||||||
|
impl<'c> SchemaManager<'c> {
|
||||||
|
pub async fn has_table<T>(&self, table: T) -> Result<bool, DbErr>
|
||||||
|
where
|
||||||
|
T: AsRef<str>,
|
||||||
|
{
|
||||||
|
let stmt = match self.conn.get_database_backend() {
|
||||||
|
DbBackend::MySql => MySql::has_table(table),
|
||||||
|
DbBackend::Postgres => Postgres::has_table(table),
|
||||||
|
DbBackend::Sqlite => Sqlite::has_table(table),
|
||||||
|
};
|
||||||
|
|
||||||
|
let builder = self.conn.get_database_backend();
|
||||||
|
let res = self
|
||||||
|
.conn
|
||||||
|
.query_one(builder.build(&stmt))
|
||||||
|
.await?
|
||||||
|
.ok_or_else(|| DbErr::Custom("Failed to check table exists".to_owned()))?;
|
||||||
|
|
||||||
|
Ok(res.try_get("", "has_table")?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn has_column<T, C>(&self, table: T, column: C) -> Result<bool, DbErr>
|
||||||
|
where
|
||||||
|
T: AsRef<str>,
|
||||||
|
C: AsRef<str>,
|
||||||
|
{
|
||||||
|
let stmt = match self.conn.get_database_backend() {
|
||||||
|
DbBackend::MySql => MySql::has_column(table, column),
|
||||||
|
DbBackend::Postgres => Postgres::has_column(table, column),
|
||||||
|
DbBackend::Sqlite => Sqlite::has_column(table, column),
|
||||||
|
};
|
||||||
|
|
||||||
|
let builder = self.conn.get_database_backend();
|
||||||
|
let res = self
|
||||||
|
.conn
|
||||||
|
.query_one(builder.build(&stmt))
|
||||||
|
.await?
|
||||||
|
.ok_or_else(|| DbErr::Custom("Failed to check column exists".to_owned()))?;
|
||||||
|
|
||||||
|
Ok(res.try_get("", "has_column")?)
|
||||||
|
}
|
||||||
|
}
|
308
sea-orm-migration/src/migrator.rs
Normal file
308
sea-orm-migration/src/migrator.rs
Normal file
@ -0,0 +1,308 @@
|
|||||||
|
use std::fmt::Display;
|
||||||
|
use std::time::SystemTime;
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
|
use sea_orm::sea_query::{Alias, Expr, ForeignKey, Query, SelectStatement, SimpleExpr, Table};
|
||||||
|
use sea_orm::{
|
||||||
|
ActiveModelTrait, ActiveValue, ColumnTrait, Condition, ConnectionTrait, DbBackend, DbConn,
|
||||||
|
DbErr, EntityTrait, QueryFilter, QueryOrder, Schema, Statement,
|
||||||
|
};
|
||||||
|
use sea_schema::{mysql::MySql, postgres::Postgres, probe::SchemaProbe, sqlite::Sqlite};
|
||||||
|
|
||||||
|
use super::{seaql_migrations, MigrationTrait, SchemaManager};
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
/// Status of migration
|
||||||
|
pub enum MigrationStatus {
|
||||||
|
/// Not yet applied
|
||||||
|
Pending,
|
||||||
|
/// Applied
|
||||||
|
Applied,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Migration {
|
||||||
|
migration: Box<dyn MigrationTrait>,
|
||||||
|
status: MigrationStatus,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for MigrationStatus {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let status = match self {
|
||||||
|
MigrationStatus::Pending => "Pending",
|
||||||
|
MigrationStatus::Applied => "Applied",
|
||||||
|
};
|
||||||
|
write!(f, "{}", status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performing migrations on a database
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
pub trait MigratorTrait: Send {
|
||||||
|
/// Vector of migrations in time sequence
|
||||||
|
fn migrations() -> Vec<Box<dyn MigrationTrait>>;
|
||||||
|
|
||||||
|
/// Get list of migrations wrapped in `Migration` struct
|
||||||
|
fn get_migration_files() -> Vec<Migration> {
|
||||||
|
Self::migrations()
|
||||||
|
.into_iter()
|
||||||
|
.map(|migration| Migration {
|
||||||
|
migration,
|
||||||
|
status: MigrationStatus::Pending,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get list of applied migrations from database
|
||||||
|
async fn get_migration_models(db: &DbConn) -> Result<Vec<seaql_migrations::Model>, DbErr> {
|
||||||
|
Self::install(db).await?;
|
||||||
|
seaql_migrations::Entity::find()
|
||||||
|
.order_by_asc(seaql_migrations::Column::Version)
|
||||||
|
.all(db)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get list of migrations with status
|
||||||
|
async fn get_migration_with_status(db: &DbConn) -> Result<Vec<Migration>, DbErr> {
|
||||||
|
Self::install(db).await?;
|
||||||
|
let mut migration_files = Self::get_migration_files();
|
||||||
|
let migration_models = Self::get_migration_models(db).await?;
|
||||||
|
for (i, migration_model) in migration_models.into_iter().enumerate() {
|
||||||
|
if let Some(migration_file) = migration_files.get_mut(i) {
|
||||||
|
if migration_file.migration.name() == migration_model.version.as_str() {
|
||||||
|
migration_file.status = MigrationStatus::Applied;
|
||||||
|
} else {
|
||||||
|
return Err(DbErr::Custom(format!("Migration mismatch: applied migration != migration file, '{0}' != '{1}'\nMigration '{0}' has been applied but its corresponding migration file is missing.", migration_file.migration.name(), migration_model.version)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(DbErr::Custom(format!("Migration file of version '{}' is missing, this migration has been applied but its file is missing", migration_model.version)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(migration_files)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get list of pending migrations
|
||||||
|
async fn get_pending_migrations(db: &DbConn) -> Result<Vec<Migration>, DbErr> {
|
||||||
|
Self::install(db).await?;
|
||||||
|
Ok(Self::get_migration_with_status(db)
|
||||||
|
.await?
|
||||||
|
.into_iter()
|
||||||
|
.filter(|file| file.status == MigrationStatus::Pending)
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get list of applied migrations
|
||||||
|
async fn get_applied_migrations(db: &DbConn) -> Result<Vec<Migration>, DbErr> {
|
||||||
|
Self::install(db).await?;
|
||||||
|
Ok(Self::get_migration_with_status(db)
|
||||||
|
.await?
|
||||||
|
.into_iter()
|
||||||
|
.filter(|file| file.status == MigrationStatus::Applied)
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create migration table `seaql_migrations` in the database
|
||||||
|
async fn install(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
let builder = db.get_database_backend();
|
||||||
|
let schema = Schema::new(builder);
|
||||||
|
let mut stmt = schema.create_table_from_entity(seaql_migrations::Entity);
|
||||||
|
stmt.if_not_exists();
|
||||||
|
db.execute(builder.build(&stmt)).await.map(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Drop all tables from the database, then reapply all migrations
|
||||||
|
async fn fresh(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
Self::install(db).await?;
|
||||||
|
let db_backend = db.get_database_backend();
|
||||||
|
|
||||||
|
// Temporarily disable the foreign key check
|
||||||
|
if db_backend == DbBackend::Sqlite {
|
||||||
|
info!("Disabling foreign key check");
|
||||||
|
db.execute(Statement::from_string(
|
||||||
|
db_backend,
|
||||||
|
"PRAGMA foreign_keys = OFF".to_owned(),
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
info!("Foreign key check disabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drop all foreign keys
|
||||||
|
if db_backend == DbBackend::MySql {
|
||||||
|
info!("Dropping all foreign keys");
|
||||||
|
let mut stmt = Query::select();
|
||||||
|
stmt.columns([Alias::new("TABLE_NAME"), Alias::new("CONSTRAINT_NAME")])
|
||||||
|
.from((
|
||||||
|
Alias::new("information_schema"),
|
||||||
|
Alias::new("table_constraints"),
|
||||||
|
))
|
||||||
|
.cond_where(
|
||||||
|
Condition::all()
|
||||||
|
.add(
|
||||||
|
Expr::expr(get_current_schema(db)).equals(
|
||||||
|
Alias::new("table_constraints"),
|
||||||
|
Alias::new("table_schema"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.add(Expr::expr(Expr::value("FOREIGN KEY")).equals(
|
||||||
|
Alias::new("table_constraints"),
|
||||||
|
Alias::new("constraint_type"),
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
let rows = db.query_all(db_backend.build(&stmt)).await?;
|
||||||
|
for row in rows.into_iter() {
|
||||||
|
let constraint_name: String = row.try_get("", "CONSTRAINT_NAME")?;
|
||||||
|
let table_name: String = row.try_get("", "TABLE_NAME")?;
|
||||||
|
info!(
|
||||||
|
"Dropping foreign key '{}' from table '{}'",
|
||||||
|
constraint_name, table_name
|
||||||
|
);
|
||||||
|
let mut stmt = ForeignKey::drop();
|
||||||
|
stmt.table(Alias::new(table_name.as_str()))
|
||||||
|
.name(constraint_name.as_str());
|
||||||
|
db.execute(db_backend.build(&stmt)).await?;
|
||||||
|
info!("Foreign key '{}' has been dropped", constraint_name);
|
||||||
|
}
|
||||||
|
info!("All foreign keys dropped");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drop all tables
|
||||||
|
let stmt = query_tables(db);
|
||||||
|
let rows = db.query_all(db_backend.build(&stmt)).await?;
|
||||||
|
for row in rows.into_iter() {
|
||||||
|
let table_name: String = row.try_get("", "table_name")?;
|
||||||
|
info!("Dropping table '{}'", table_name);
|
||||||
|
let mut stmt = Table::drop();
|
||||||
|
stmt.table(Alias::new(table_name.as_str()))
|
||||||
|
.if_exists()
|
||||||
|
.cascade();
|
||||||
|
db.execute(db_backend.build(&stmt)).await?;
|
||||||
|
info!("Table '{}' has been dropped", table_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore the foreign key check
|
||||||
|
if db_backend == DbBackend::Sqlite {
|
||||||
|
info!("Restoring foreign key check");
|
||||||
|
db.execute(Statement::from_string(
|
||||||
|
db_backend,
|
||||||
|
"PRAGMA foreign_keys = ON".to_owned(),
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
info!("Foreign key check restored");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reapply all migrations
|
||||||
|
Self::up(db, None).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Rollback all applied migrations, then reapply all migrations
|
||||||
|
async fn refresh(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
Self::down(db, None).await?;
|
||||||
|
Self::up(db, None).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Rollback all applied migrations
|
||||||
|
async fn reset(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
Self::down(db, None).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check the status of all migrations
|
||||||
|
async fn status(db: &DbConn) -> Result<(), DbErr> {
|
||||||
|
Self::install(db).await?;
|
||||||
|
|
||||||
|
info!("Checking migration status");
|
||||||
|
|
||||||
|
for Migration { migration, status } in Self::get_migration_with_status(db).await? {
|
||||||
|
info!("Migration '{}'... {}", migration.name(), status);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Apply pending migrations
|
||||||
|
async fn up(db: &DbConn, mut steps: Option<u32>) -> Result<(), DbErr> {
|
||||||
|
Self::install(db).await?;
|
||||||
|
let manager = SchemaManager::new(db);
|
||||||
|
|
||||||
|
if let Some(steps) = steps {
|
||||||
|
info!("Applying {} pending migrations", steps);
|
||||||
|
} else {
|
||||||
|
info!("Applying all pending migrations");
|
||||||
|
}
|
||||||
|
|
||||||
|
let migrations = Self::get_pending_migrations(db).await?.into_iter();
|
||||||
|
if migrations.len() == 0 {
|
||||||
|
info!("No pending migrations");
|
||||||
|
}
|
||||||
|
for Migration { migration, .. } in migrations {
|
||||||
|
if let Some(steps) = steps.as_mut() {
|
||||||
|
if steps == &0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*steps -= 1;
|
||||||
|
}
|
||||||
|
info!("Applying migration '{}'", migration.name());
|
||||||
|
migration.up(&manager).await?;
|
||||||
|
info!("Migration '{}' has been applied", migration.name());
|
||||||
|
let now = SystemTime::now()
|
||||||
|
.duration_since(SystemTime::UNIX_EPOCH)
|
||||||
|
.expect("SystemTime before UNIX EPOCH!");
|
||||||
|
seaql_migrations::ActiveModel {
|
||||||
|
version: ActiveValue::Set(migration.name().to_owned()),
|
||||||
|
applied_at: ActiveValue::Set(now.as_secs() as i64),
|
||||||
|
}
|
||||||
|
.insert(db)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Rollback applied migrations
|
||||||
|
async fn down(db: &DbConn, mut steps: Option<u32>) -> Result<(), DbErr> {
|
||||||
|
Self::install(db).await?;
|
||||||
|
let manager = SchemaManager::new(db);
|
||||||
|
|
||||||
|
if let Some(steps) = steps {
|
||||||
|
info!("Rolling back {} applied migrations", steps);
|
||||||
|
} else {
|
||||||
|
info!("Rolling back all applied migrations");
|
||||||
|
}
|
||||||
|
|
||||||
|
let migrations = Self::get_applied_migrations(db).await?.into_iter().rev();
|
||||||
|
if migrations.len() == 0 {
|
||||||
|
info!("No applied migrations");
|
||||||
|
}
|
||||||
|
for Migration { migration, .. } in migrations {
|
||||||
|
if let Some(steps) = steps.as_mut() {
|
||||||
|
if steps == &0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*steps -= 1;
|
||||||
|
}
|
||||||
|
info!("Rolling back migration '{}'", migration.name());
|
||||||
|
migration.down(&manager).await?;
|
||||||
|
info!("Migration '{}' has been rollbacked", migration.name());
|
||||||
|
seaql_migrations::Entity::delete_many()
|
||||||
|
.filter(seaql_migrations::Column::Version.eq(migration.name()))
|
||||||
|
.exec(db)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn query_tables(db: &DbConn) -> SelectStatement {
|
||||||
|
match db.get_database_backend() {
|
||||||
|
DbBackend::MySql => MySql::query_tables(),
|
||||||
|
DbBackend::Postgres => Postgres::query_tables(),
|
||||||
|
DbBackend::Sqlite => Sqlite::query_tables(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_current_schema(db: &DbConn) -> SimpleExpr {
|
||||||
|
match db.get_database_backend() {
|
||||||
|
DbBackend::MySql => MySql::get_current_schema(),
|
||||||
|
DbBackend::Postgres => Postgres::get_current_schema(),
|
||||||
|
DbBackend::Sqlite => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
11
sea-orm-migration/src/prelude.rs
Normal file
11
sea-orm-migration/src/prelude.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
pub use sea_orm_cli::migration as cli;
|
||||||
|
|
||||||
|
pub use super::manager::SchemaManager;
|
||||||
|
pub use super::migrator::MigratorTrait;
|
||||||
|
pub use super::{MigrationName, MigrationTrait};
|
||||||
|
pub use async_std;
|
||||||
|
pub use async_trait;
|
||||||
|
pub use sea_orm;
|
||||||
|
pub use sea_orm::sea_query;
|
||||||
|
pub use sea_orm::sea_query::*;
|
||||||
|
pub use sea_orm::DbErr;
|
14
sea-orm-migration/src/seaql_migrations.rs
Normal file
14
sea-orm-migration/src/seaql_migrations.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
||||||
|
#[sea_orm(table_name = "seaql_migrations")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key, auto_increment = false)]
|
||||||
|
pub version: String,
|
||||||
|
pub applied_at: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
121
sea-orm-migration/tests/main.rs
Normal file
121
sea-orm-migration/tests/main.rs
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
mod migrator;
|
||||||
|
use migrator::Migrator;
|
||||||
|
|
||||||
|
use sea_orm::{ConnectionTrait, Database, DbBackend, DbErr, Statement};
|
||||||
|
use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
|
#[async_std::test]
|
||||||
|
async fn main() -> Result<(), DbErr> {
|
||||||
|
let url = std::env::var("DATABASE_URL").expect("Environment variable 'DATABASE_URL' not set");
|
||||||
|
let db_name = "sea_orm_migration";
|
||||||
|
let db = Database::connect(&url).await?;
|
||||||
|
let db = &match db.get_database_backend() {
|
||||||
|
DbBackend::MySql => {
|
||||||
|
db.execute(Statement::from_string(
|
||||||
|
db.get_database_backend(),
|
||||||
|
format!("CREATE DATABASE IF NOT EXISTS `{}`;", db_name),
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let url = format!("{}/{}", url, db_name);
|
||||||
|
Database::connect(&url).await?
|
||||||
|
}
|
||||||
|
DbBackend::Postgres => {
|
||||||
|
db.execute(Statement::from_string(
|
||||||
|
db.get_database_backend(),
|
||||||
|
format!("DROP DATABASE IF EXISTS \"{}\";", db_name),
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
db.execute(Statement::from_string(
|
||||||
|
db.get_database_backend(),
|
||||||
|
format!("CREATE DATABASE \"{}\";", db_name),
|
||||||
|
))
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let url = format!("{}/{}", url, db_name);
|
||||||
|
Database::connect(&url).await?
|
||||||
|
}
|
||||||
|
DbBackend::Sqlite => db,
|
||||||
|
};
|
||||||
|
let manager = SchemaManager::new(db);
|
||||||
|
|
||||||
|
println!("\nMigrator::status");
|
||||||
|
Migrator::status(db).await?;
|
||||||
|
|
||||||
|
println!("\nMigrator::install");
|
||||||
|
Migrator::install(db).await?;
|
||||||
|
|
||||||
|
assert!(manager.has_table("seaql_migrations").await?);
|
||||||
|
|
||||||
|
println!("\nMigrator::reset");
|
||||||
|
Migrator::reset(db).await?;
|
||||||
|
|
||||||
|
assert!(!manager.has_table("cake").await?);
|
||||||
|
assert!(!manager.has_table("fruit").await?);
|
||||||
|
|
||||||
|
println!("\nMigrator::up");
|
||||||
|
Migrator::up(db, Some(0)).await?;
|
||||||
|
|
||||||
|
assert!(!manager.has_table("cake").await?);
|
||||||
|
assert!(!manager.has_table("fruit").await?);
|
||||||
|
|
||||||
|
println!("\nMigrator::up");
|
||||||
|
Migrator::up(db, Some(1)).await?;
|
||||||
|
|
||||||
|
assert!(manager.has_table("cake").await?);
|
||||||
|
assert!(!manager.has_table("fruit").await?);
|
||||||
|
|
||||||
|
println!("\nMigrator::down");
|
||||||
|
Migrator::down(db, Some(0)).await?;
|
||||||
|
|
||||||
|
assert!(manager.has_table("cake").await?);
|
||||||
|
assert!(!manager.has_table("fruit").await?);
|
||||||
|
|
||||||
|
println!("\nMigrator::down");
|
||||||
|
Migrator::down(db, Some(1)).await?;
|
||||||
|
|
||||||
|
assert!(!manager.has_table("cake").await?);
|
||||||
|
assert!(!manager.has_table("fruit").await?);
|
||||||
|
|
||||||
|
println!("\nMigrator::up");
|
||||||
|
Migrator::up(db, None).await?;
|
||||||
|
|
||||||
|
println!("\nMigrator::status");
|
||||||
|
Migrator::status(db).await?;
|
||||||
|
|
||||||
|
assert!(manager.has_table("cake").await?);
|
||||||
|
assert!(manager.has_table("fruit").await?);
|
||||||
|
|
||||||
|
assert!(manager.has_column("cake", "name").await?);
|
||||||
|
assert!(manager.has_column("fruit", "cake_id").await?);
|
||||||
|
|
||||||
|
println!("\nMigrator::down");
|
||||||
|
Migrator::down(db, None).await?;
|
||||||
|
|
||||||
|
assert!(manager.has_table("seaql_migrations").await?);
|
||||||
|
assert!(!manager.has_table("cake").await?);
|
||||||
|
assert!(!manager.has_table("fruit").await?);
|
||||||
|
|
||||||
|
println!("\nMigrator::fresh");
|
||||||
|
Migrator::fresh(db).await?;
|
||||||
|
|
||||||
|
assert!(manager.has_table("cake").await?);
|
||||||
|
assert!(manager.has_table("fruit").await?);
|
||||||
|
|
||||||
|
println!("\nMigrator::refresh");
|
||||||
|
Migrator::refresh(db).await?;
|
||||||
|
|
||||||
|
assert!(manager.has_table("cake").await?);
|
||||||
|
assert!(manager.has_table("fruit").await?);
|
||||||
|
|
||||||
|
println!("\nMigrator::reset");
|
||||||
|
Migrator::reset(db).await?;
|
||||||
|
|
||||||
|
assert!(!manager.has_table("cake").await?);
|
||||||
|
assert!(!manager.has_table("fruit").await?);
|
||||||
|
|
||||||
|
println!("\nMigrator::status");
|
||||||
|
Migrator::status(db).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
|
pub struct Migration;
|
||||||
|
|
||||||
|
impl MigrationName for Migration {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"m20220118_000001_create_cake_table"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl MigrationTrait for Migration {
|
||||||
|
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
manager
|
||||||
|
.create_table(
|
||||||
|
Table::create()
|
||||||
|
.table(Cake::Table)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Cake::Id)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.auto_increment()
|
||||||
|
.primary_key(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(Cake::Name).string().not_null())
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
manager
|
||||||
|
.drop_table(Table::drop().table(Cake::Table).to_owned())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Iden)]
|
||||||
|
pub enum Cake {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
Name,
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
use super::m20220118_000001_create_cake_table::Cake;
|
||||||
|
use sea_orm::DbBackend;
|
||||||
|
use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
|
pub struct Migration;
|
||||||
|
|
||||||
|
impl MigrationName for Migration {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"m20220118_000002_create_fruit_table"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl MigrationTrait for Migration {
|
||||||
|
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
manager
|
||||||
|
.create_table(
|
||||||
|
Table::create()
|
||||||
|
.table(Fruit::Table)
|
||||||
|
.col(
|
||||||
|
ColumnDef::new(Fruit::Id)
|
||||||
|
.integer()
|
||||||
|
.not_null()
|
||||||
|
.auto_increment()
|
||||||
|
.primary_key(),
|
||||||
|
)
|
||||||
|
.col(ColumnDef::new(Fruit::Name).string().not_null())
|
||||||
|
.col(ColumnDef::new(Fruit::CakeId).integer().not_null())
|
||||||
|
.foreign_key(
|
||||||
|
ForeignKey::create()
|
||||||
|
.name("fk-fruit-cake_id")
|
||||||
|
.from(Fruit::Table, Fruit::CakeId)
|
||||||
|
.to(Cake::Table, Cake::Id),
|
||||||
|
)
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
if manager.get_database_backend() != DbBackend::Sqlite {
|
||||||
|
manager
|
||||||
|
.drop_foreign_key(
|
||||||
|
ForeignKey::drop()
|
||||||
|
.table(Fruit::Table)
|
||||||
|
.name("fk-fruit-cake_id")
|
||||||
|
.to_owned(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
manager
|
||||||
|
.drop_table(Table::drop().table(Fruit::Table).to_owned())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Iden)]
|
||||||
|
pub enum Fruit {
|
||||||
|
Table,
|
||||||
|
Id,
|
||||||
|
Name,
|
||||||
|
CakeId,
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
use sea_orm::{entity::prelude::*, Set};
|
||||||
|
use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
|
pub struct Migration;
|
||||||
|
|
||||||
|
impl MigrationName for Migration {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"m20220118_000003_seed_cake_table"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait::async_trait]
|
||||||
|
impl MigrationTrait for Migration {
|
||||||
|
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
let db = manager.get_connection();
|
||||||
|
|
||||||
|
cake::ActiveModel {
|
||||||
|
name: Set("Cheesecake".to_owned()),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.insert(db)
|
||||||
|
.await
|
||||||
|
.map(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
|
||||||
|
let db = manager.get_connection();
|
||||||
|
|
||||||
|
cake::Entity::delete_many()
|
||||||
|
.filter(cake::Column::Name.eq("Cheesecake"))
|
||||||
|
.exec(db)
|
||||||
|
.await
|
||||||
|
.map(|_| ())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod cake {
|
||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
||||||
|
#[sea_orm(table_name = "cake")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
pub id: i32,
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
pub enum Relation {}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
}
|
18
sea-orm-migration/tests/migrator/mod.rs
Normal file
18
sea-orm-migration/tests/migrator/mod.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
use sea_orm_migration::prelude::*;
|
||||||
|
|
||||||
|
mod m20220118_000001_create_cake_table;
|
||||||
|
mod m20220118_000002_create_fruit_table;
|
||||||
|
mod m20220118_000003_seed_cake_table;
|
||||||
|
|
||||||
|
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),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,8 @@ pub enum DbErr {
|
|||||||
Type(String),
|
Type(String),
|
||||||
/// Error occurred while parsing json value as target type
|
/// Error occurred while parsing json value as target type
|
||||||
Json(String),
|
Json(String),
|
||||||
|
/// A migration error
|
||||||
|
Migration(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::error::Error for DbErr {}
|
impl std::error::Error for DbErr {}
|
||||||
@ -29,6 +31,7 @@ impl std::fmt::Display for DbErr {
|
|||||||
Self::Custom(s) => write!(f, "Custom Error: {}", s),
|
Self::Custom(s) => write!(f, "Custom Error: {}", s),
|
||||||
Self::Type(s) => write!(f, "Type Error: {}", s),
|
Self::Type(s) => write!(f, "Type Error: {}", s),
|
||||||
Self::Json(s) => write!(f, "Json Error: {}", s),
|
Self::Json(s) => write!(f, "Json Error: {}", s),
|
||||||
|
Self::Migration(s) => write!(f, "Migration Error: {}", s),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user