diff --git a/examples/actix4_example/.env b/examples/actix4_example/.env index d89d9e63..010295bc 100644 --- a/examples/actix4_example/.env +++ b/examples/actix4_example/.env @@ -1,3 +1,3 @@ HOST=127.0.0.1 PORT=8000 -DATABASE_URL="mysql://root:@localhost/actix_example" +DATABASE_URL="mysql://root:root@localhost/actix_example" diff --git a/examples/actix4_example/Cargo.toml b/examples/actix4_example/Cargo.toml index 5477447c..bbb75c96 100644 --- a/examples/actix4_example/Cargo.toml +++ b/examples/actix4_example/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" publish = false [workspace] +members = [".", "entity", "migration"] [dependencies] actix-files = "0.6.0-beta.4" @@ -19,14 +20,5 @@ dotenv = "0.15" listenfd = "0.3.3" serde = "1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } - -[dependencies.sea-orm] -path = "../../" # remove this line in your own project -version = "^0.6.0" -features = ["macros", "runtime-actix-native-tls", "debug-print"] -default-features = false - -[features] -default = ["sqlx-mysql"] -sqlx-mysql = ["sea-orm/sqlx-mysql"] -sqlx-postgres = ["sea-orm/sqlx-postgres"] +entity = { path = "entity" } +migration = { path = "migration" } diff --git a/examples/actix4_example/README.md b/examples/actix4_example/README.md index 9eb73ea6..f754d132 100644 --- a/examples/actix4_example/README.md +++ b/examples/actix4_example/README.md @@ -1,13 +1,14 @@ +![screenshot](Screenshot.png) + # Actix 4 Beta with SeaORM example app -Edit `Cargo.toml` to use `sqlx-mysql` or `sqlx-postgres`. +1. Modify the `DATABASE_URL` var in `.env` to point to your chosen database -```toml -[features] -default = ["sqlx-$DATABASE"] -``` +1. Turn on the appropriate database feature for your chosen db in `entity/Cargo.toml` (the `"sqlx-mysql",` line) -Edit `.env` to point to your database. +1. Execute `cargo run` to start the server + +1. Visit [localhost:8000](http://localhost:8000) in browser Run server with auto-reloading: diff --git a/examples/actix4_example/Screenshot.png b/examples/actix4_example/Screenshot.png new file mode 100644 index 00000000..8846f70f Binary files /dev/null and b/examples/actix4_example/Screenshot.png differ diff --git a/examples/actix4_example/entity/Cargo.toml b/examples/actix4_example/entity/Cargo.toml new file mode 100644 index 00000000..90659cdc --- /dev/null +++ b/examples/actix4_example/entity/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "entity" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +name = "entity" +path = "src/lib.rs" + +[dependencies] +serde = { version = "1", features = ["derive"] } + +[dependencies.sea-orm] +# path = "../../../" # remove this line in your own project +version = "^0.6.0" +features = [ + "macros", + "debug-print", + "runtime-actix-native-tls", + "sqlx-mysql", + # "sqlx-postgres", + # "sqlx-sqlite", +] +default-features = false \ No newline at end of file diff --git a/examples/actix4_example/entity/src/lib.rs b/examples/actix4_example/entity/src/lib.rs new file mode 100644 index 00000000..263f05b4 --- /dev/null +++ b/examples/actix4_example/entity/src/lib.rs @@ -0,0 +1,3 @@ +pub mod post; + +pub use sea_orm; diff --git a/examples/actix4_example/src/post.rs b/examples/actix4_example/entity/src/post.rs similarity index 100% rename from examples/actix4_example/src/post.rs rename to examples/actix4_example/entity/src/post.rs diff --git a/examples/actix4_example/migration/Cargo.toml b/examples/actix4_example/migration/Cargo.toml new file mode 100644 index 00000000..9a7c338f --- /dev/null +++ b/examples/actix4_example/migration/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "migration" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +name = "migration" +path = "src/lib.rs" + +[dependencies] +sea-schema = { version = "^0.5.0", default-features = false, features = [ "migration", "debug-print" ] } +entity = { path = "../entity" } diff --git a/examples/actix4_example/migration/README.md b/examples/actix4_example/migration/README.md new file mode 100644 index 00000000..963caaeb --- /dev/null +++ b/examples/actix4_example/migration/README.md @@ -0,0 +1,37 @@ +# Running Migrator CLI + +- Apply all pending migrations + ```sh + cargo run + ``` + ```sh + cargo run -- up + ``` +- Apply first 10 pending migrations + ```sh + cargo run -- up -n 10 + ``` +- Rollback last applied migrations + ```sh + cargo run -- down + ``` +- Rollback last 10 applied migrations + ```sh + cargo run -- down -n 10 + ``` +- Drop all tables from the database, then reapply all migrations + ```sh + cargo run -- fresh + ``` +- Rollback all applied migrations, then reapply all migrations + ```sh + cargo run -- refresh + ``` +- Rollback all applied migrations + ```sh + cargo run -- reset + ``` +- Check the status of all migrations + ```sh + cargo run -- status + ``` diff --git a/examples/actix4_example/migration/src/lib.rs b/examples/actix4_example/migration/src/lib.rs new file mode 100644 index 00000000..3679d81f --- /dev/null +++ b/examples/actix4_example/migration/src/lib.rs @@ -0,0 +1,12 @@ +pub use sea_schema::migration::prelude::*; + +mod m20220120_000001_create_post_table; + +pub struct Migrator; + +#[async_trait::async_trait] +impl MigratorTrait for Migrator { + fn migrations() -> Vec> { + vec![Box::new(m20220120_000001_create_post_table::Migration)] + } +} diff --git a/examples/actix4_example/migration/src/m20220120_000001_create_post_table.rs b/examples/actix4_example/migration/src/m20220120_000001_create_post_table.rs new file mode 100644 index 00000000..0fe872c4 --- /dev/null +++ b/examples/actix4_example/migration/src/m20220120_000001_create_post_table.rs @@ -0,0 +1,39 @@ +use entity::post::*; +use sea_schema::migration::prelude::*; + +pub struct Migration; + +impl MigrationName for Migration { + fn name(&self) -> &str { + "m20220120_000001_create_post_table" + } +} + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(Entity) + .if_not_exists() + .col( + ColumnDef::new(Column::Id) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col(ColumnDef::new(Column::Title).string().not_null()) + .col(ColumnDef::new(Column::Text).string().not_null()) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop().table(Entity).to_owned()) + .await + } +} diff --git a/examples/actix4_example/migration/src/main.rs b/examples/actix4_example/migration/src/main.rs new file mode 100644 index 00000000..7e5e996d --- /dev/null +++ b/examples/actix4_example/migration/src/main.rs @@ -0,0 +1,7 @@ +use migration::Migrator; +use sea_schema::migration::*; + +#[async_std::main] +async fn main() { + cli::run_cli(Migrator).await; +} diff --git a/examples/actix4_example/src/main.rs b/examples/actix4_example/src/main.rs index 43ec4336..201d22d9 100644 --- a/examples/actix4_example/src/main.rs +++ b/examples/actix4_example/src/main.rs @@ -3,17 +3,17 @@ use actix_web::{ error, get, middleware, post, web, App, Error, HttpRequest, HttpResponse, HttpServer, Result, }; +use entity::post; +use entity::post::Entity as Post; +use entity::sea_orm; use listenfd::ListenFd; +use migration::{Migrator, MigratorTrait}; use sea_orm::DatabaseConnection; use sea_orm::{entity::*, query::*}; use serde::{Deserialize, Serialize}; use std::env; use tera::Tera; -mod post; -pub use post::Entity as Post; -mod setup; - const DEFAULT_POSTS_PER_PAGE: usize = 5; #[derive(Debug, Clone)] @@ -92,7 +92,9 @@ async fn create( .await .expect("could not insert post"); - Ok(HttpResponse::Found().append_header(("location", "/")).finish()) + Ok(HttpResponse::Found() + .append_header(("location", "/")) + .finish()) } #[get("/{id}")] @@ -133,7 +135,9 @@ async fn update( .await .expect("could not edit post"); - Ok(HttpResponse::Found().append_header(("location", "/")).finish()) + Ok(HttpResponse::Found() + .append_header(("location", "/")) + .finish()) } #[post("/delete/{id}")] @@ -149,7 +153,9 @@ async fn delete(data: web::Data, id: web::Path) -> Result std::io::Result<()> { // create post table if not exists let conn = sea_orm::Database::connect(&db_url).await.unwrap(); - let _ = setup::create_post_table(&conn).await; + Migrator::up(&conn, None).await.unwrap(); let templates = Tera::new(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")).unwrap(); let state = AppState { templates, conn }; diff --git a/examples/actix4_example/src/setup.rs b/examples/actix4_example/src/setup.rs deleted file mode 100644 index 04677af4..00000000 --- a/examples/actix4_example/src/setup.rs +++ /dev/null @@ -1,33 +0,0 @@ -use sea_orm::sea_query::{ColumnDef, TableCreateStatement}; -use sea_orm::{error::*, sea_query, ConnectionTrait, DbConn, ExecResult}; - -async fn create_table(db: &DbConn, stmt: &TableCreateStatement) -> Result { - let builder = db.get_database_backend(); - db.execute(builder.build(stmt)).await -} - -pub async fn create_post_table(db: &DbConn) -> Result { - let stmt = sea_query::Table::create() - .table(super::post::Entity) - .if_not_exists() - .col( - ColumnDef::new(super::post::Column::Id) - .integer() - .not_null() - .auto_increment() - .primary_key(), - ) - .col( - ColumnDef::new(super::post::Column::Title) - .string() - .not_null(), - ) - .col( - ColumnDef::new(super::post::Column::Text) - .string() - .not_null(), - ) - .to_owned(); - - create_table(db, &stmt).await -} diff --git a/examples/actix_example/.env b/examples/actix_example/.env index 94ec74e3..1a12a183 100644 --- a/examples/actix_example/.env +++ b/examples/actix_example/.env @@ -1,3 +1,3 @@ HOST=127.0.0.1 PORT=8000 -DATABASE_URL="sql://root:@localhost/actix_example" \ No newline at end of file +DATABASE_URL="mysql://root:root@localhost/actix_example" \ No newline at end of file diff --git a/examples/actix_example/Cargo.toml b/examples/actix_example/Cargo.toml index 39bb9e53..11d2915a 100644 --- a/examples/actix_example/Cargo.toml +++ b/examples/actix_example/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" publish = false [workspace] +members = [".", "entity", "migration"] [dependencies] actix-http = "2" @@ -19,14 +20,5 @@ dotenv = "0.15" listenfd = "0.3.3" serde = "1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } - -[dependencies.sea-orm] -path = "../../" # remove this line in your own project -version = "^0.6.0" -features = ["macros", "runtime-async-std-native-tls", "debug-print"] -default-features = false - -[features] -default = ["sqlx-mysql"] -sqlx-mysql = ["sea-orm/sqlx-mysql"] -sqlx-postgres = ["sea-orm/sqlx-postgres"] +entity = { path = "entity" } +migration = { path = "migration" } diff --git a/examples/actix_example/README.md b/examples/actix_example/README.md index d1ba90bf..71b4722a 100644 --- a/examples/actix_example/README.md +++ b/examples/actix_example/README.md @@ -1,13 +1,14 @@ +![screenshot](Screenshot.png) + # Actix with SeaORM example app -Edit `Cargo.toml` to use `sqlx-mysql` or `sqlx-postgres`. +1. Modify the `DATABASE_URL` var in `.env` to point to your chosen database -```toml -[features] -default = ["sqlx-$DATABASE"] -``` +1. Turn on the appropriate database feature for your chosen db in `entity/Cargo.toml` (the `"sqlx-mysql",` line) -Edit `.env` to point to your database. +1. Execute `cargo run` to start the server + +1. Visit [localhost:8000](http://localhost:8000) in browser Run server with auto-reloading: diff --git a/examples/actix_example/Screenshot.png b/examples/actix_example/Screenshot.png new file mode 100644 index 00000000..8846f70f Binary files /dev/null and b/examples/actix_example/Screenshot.png differ diff --git a/examples/actix_example/entity/Cargo.toml b/examples/actix_example/entity/Cargo.toml new file mode 100644 index 00000000..e70b7d6d --- /dev/null +++ b/examples/actix_example/entity/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "entity" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +name = "entity" +path = "src/lib.rs" + +[dependencies] +serde = { version = "1", features = ["derive"] } + +[dependencies.sea-orm] +# path = "../../../" # remove this line in your own project +version = "^0.6.0" +features = [ + "macros", + "debug-print", + "runtime-async-std-native-tls", + "sqlx-mysql", + # "sqlx-postgres", + # "sqlx-sqlite", +] +default-features = false \ No newline at end of file diff --git a/examples/actix_example/entity/src/lib.rs b/examples/actix_example/entity/src/lib.rs new file mode 100644 index 00000000..263f05b4 --- /dev/null +++ b/examples/actix_example/entity/src/lib.rs @@ -0,0 +1,3 @@ +pub mod post; + +pub use sea_orm; diff --git a/examples/actix_example/src/post.rs b/examples/actix_example/entity/src/post.rs similarity index 100% rename from examples/actix_example/src/post.rs rename to examples/actix_example/entity/src/post.rs diff --git a/examples/actix_example/migration/Cargo.toml b/examples/actix_example/migration/Cargo.toml new file mode 100644 index 00000000..9a7c338f --- /dev/null +++ b/examples/actix_example/migration/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "migration" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +name = "migration" +path = "src/lib.rs" + +[dependencies] +sea-schema = { version = "^0.5.0", default-features = false, features = [ "migration", "debug-print" ] } +entity = { path = "../entity" } diff --git a/examples/actix_example/migration/README.md b/examples/actix_example/migration/README.md new file mode 100644 index 00000000..963caaeb --- /dev/null +++ b/examples/actix_example/migration/README.md @@ -0,0 +1,37 @@ +# Running Migrator CLI + +- Apply all pending migrations + ```sh + cargo run + ``` + ```sh + cargo run -- up + ``` +- Apply first 10 pending migrations + ```sh + cargo run -- up -n 10 + ``` +- Rollback last applied migrations + ```sh + cargo run -- down + ``` +- Rollback last 10 applied migrations + ```sh + cargo run -- down -n 10 + ``` +- Drop all tables from the database, then reapply all migrations + ```sh + cargo run -- fresh + ``` +- Rollback all applied migrations, then reapply all migrations + ```sh + cargo run -- refresh + ``` +- Rollback all applied migrations + ```sh + cargo run -- reset + ``` +- Check the status of all migrations + ```sh + cargo run -- status + ``` diff --git a/examples/actix_example/migration/src/lib.rs b/examples/actix_example/migration/src/lib.rs new file mode 100644 index 00000000..3679d81f --- /dev/null +++ b/examples/actix_example/migration/src/lib.rs @@ -0,0 +1,12 @@ +pub use sea_schema::migration::prelude::*; + +mod m20220120_000001_create_post_table; + +pub struct Migrator; + +#[async_trait::async_trait] +impl MigratorTrait for Migrator { + fn migrations() -> Vec> { + vec![Box::new(m20220120_000001_create_post_table::Migration)] + } +} diff --git a/examples/actix_example/migration/src/m20220120_000001_create_post_table.rs b/examples/actix_example/migration/src/m20220120_000001_create_post_table.rs new file mode 100644 index 00000000..0fe872c4 --- /dev/null +++ b/examples/actix_example/migration/src/m20220120_000001_create_post_table.rs @@ -0,0 +1,39 @@ +use entity::post::*; +use sea_schema::migration::prelude::*; + +pub struct Migration; + +impl MigrationName for Migration { + fn name(&self) -> &str { + "m20220120_000001_create_post_table" + } +} + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(Entity) + .if_not_exists() + .col( + ColumnDef::new(Column::Id) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col(ColumnDef::new(Column::Title).string().not_null()) + .col(ColumnDef::new(Column::Text).string().not_null()) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop().table(Entity).to_owned()) + .await + } +} diff --git a/examples/actix_example/migration/src/main.rs b/examples/actix_example/migration/src/main.rs new file mode 100644 index 00000000..7e5e996d --- /dev/null +++ b/examples/actix_example/migration/src/main.rs @@ -0,0 +1,7 @@ +use migration::Migrator; +use sea_schema::migration::*; + +#[async_std::main] +async fn main() { + cli::run_cli(Migrator).await; +} diff --git a/examples/actix_example/src/main.rs b/examples/actix_example/src/main.rs index d532174f..b3f44a78 100644 --- a/examples/actix_example/src/main.rs +++ b/examples/actix_example/src/main.rs @@ -2,17 +2,18 @@ use actix_files as fs; use actix_web::{ error, get, middleware, post, web, App, Error, HttpRequest, HttpResponse, HttpServer, Result, }; + +use entity::post; +use entity::post::Entity as Post; +use entity::sea_orm; use listenfd::ListenFd; +use migration::{Migrator, MigratorTrait}; use sea_orm::DatabaseConnection; use sea_orm::{entity::*, query::*}; use serde::{Deserialize, Serialize}; use std::env; use tera::Tera; -mod post; -pub use post::Entity as Post; -mod setup; - const DEFAULT_POSTS_PER_PAGE: usize = 5; #[derive(Debug, Clone)] @@ -192,7 +193,7 @@ async fn main() -> std::io::Result<()> { // create post table if not exists let conn = sea_orm::Database::connect(&db_url).await.unwrap(); - let _ = setup::create_post_table(&conn).await; + Migrator::up(&conn, None).await.unwrap(); let templates = Tera::new(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")).unwrap(); let state = AppState { templates, conn }; diff --git a/examples/actix_example/src/setup.rs b/examples/actix_example/src/setup.rs deleted file mode 100644 index 04677af4..00000000 --- a/examples/actix_example/src/setup.rs +++ /dev/null @@ -1,33 +0,0 @@ -use sea_orm::sea_query::{ColumnDef, TableCreateStatement}; -use sea_orm::{error::*, sea_query, ConnectionTrait, DbConn, ExecResult}; - -async fn create_table(db: &DbConn, stmt: &TableCreateStatement) -> Result { - let builder = db.get_database_backend(); - db.execute(builder.build(stmt)).await -} - -pub async fn create_post_table(db: &DbConn) -> Result { - let stmt = sea_query::Table::create() - .table(super::post::Entity) - .if_not_exists() - .col( - ColumnDef::new(super::post::Column::Id) - .integer() - .not_null() - .auto_increment() - .primary_key(), - ) - .col( - ColumnDef::new(super::post::Column::Title) - .string() - .not_null(), - ) - .col( - ColumnDef::new(super::post::Column::Text) - .string() - .not_null(), - ) - .to_owned(); - - create_table(db, &stmt).await -} diff --git a/examples/axum_example/.env b/examples/axum_example/.env index fb7fcfb5..375cab79 100644 --- a/examples/axum_example/.env +++ b/examples/axum_example/.env @@ -1,3 +1,3 @@ HOST=127.0.0.1 PORT=8000 -DATABASE_URL="postgres://postgres:password@localhost/axum_exmaple" \ No newline at end of file +DATABASE_URL="postgres://root:root@localhost/axum_exmaple" \ No newline at end of file diff --git a/examples/axum_example/Cargo.toml b/examples/axum_example/Cargo.toml index a46e8352..3e81d995 100644 --- a/examples/axum_example/Cargo.toml +++ b/examples/axum_example/Cargo.toml @@ -7,6 +7,7 @@ publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [workspace] +members = [".", "entity", "migration"] [dependencies] tokio = { version = "1.14", features = ["full"] } @@ -20,14 +21,5 @@ serde = "1" serde_json = "1" tera = "1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } - -[dependencies.sea-orm] -path = "../../" # remove this line in your own project -version = "^0.6.0" -features = ["macros", "runtime-tokio-native-tls", "debug-print"] -default-features = false - -[features] -default = ["sqlx-postgres"] -sqlx-mysql = ["sea-orm/sqlx-mysql"] -sqlx-postgres = ["sea-orm/sqlx-postgres"] +entity = { path = "entity" } +migration = { path = "migration" } diff --git a/examples/axum_example/README.md b/examples/axum_example/README.md index 3b04a53e..8ed1e789 100644 --- a/examples/axum_example/README.md +++ b/examples/axum_example/README.md @@ -1,10 +1,11 @@ +![screenshot](Screenshot.png) + # Axum with SeaORM example app -Edit `Cargo.toml` to use `sqlx-mysql` or `sqlx-postgres`. +1. Modify the `DATABASE_URL` var in `.env` to point to your chosen database -```toml -[features] -default = ["sqlx-$DATABASE"] -``` +1. Turn on the appropriate database feature for your chosen db in `entity/Cargo.toml` (the `"sqlx-postgres",` line) -Edit `.env` to point to your database. \ No newline at end of file +1. Execute `cargo run` to start the server + +1. Visit [localhost:8000](http://localhost:8000) in browser diff --git a/examples/axum_example/Screenshot.png b/examples/axum_example/Screenshot.png new file mode 100644 index 00000000..478048ec Binary files /dev/null and b/examples/axum_example/Screenshot.png differ diff --git a/examples/axum_example/entity/Cargo.toml b/examples/axum_example/entity/Cargo.toml new file mode 100644 index 00000000..388df043 --- /dev/null +++ b/examples/axum_example/entity/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "entity" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +name = "entity" +path = "src/lib.rs" + +[dependencies] +serde = { version = "1", features = ["derive"] } + +[dependencies.sea-orm] +# path = "../../../" # remove this line in your own project +version = "^0.6.0" +features = [ + "macros", + "debug-print", + "runtime-tokio-native-tls", + "sqlx-postgres", + # "sqlx-mysql", + # "sqlx-sqlite", +] +default-features = false \ No newline at end of file diff --git a/examples/axum_example/entity/src/lib.rs b/examples/axum_example/entity/src/lib.rs new file mode 100644 index 00000000..263f05b4 --- /dev/null +++ b/examples/axum_example/entity/src/lib.rs @@ -0,0 +1,3 @@ +pub mod post; + +pub use sea_orm; diff --git a/examples/axum_example/src/post.rs b/examples/axum_example/entity/src/post.rs similarity index 100% rename from examples/axum_example/src/post.rs rename to examples/axum_example/entity/src/post.rs diff --git a/examples/axum_example/migration/Cargo.toml b/examples/axum_example/migration/Cargo.toml new file mode 100644 index 00000000..9a7c338f --- /dev/null +++ b/examples/axum_example/migration/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "migration" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +name = "migration" +path = "src/lib.rs" + +[dependencies] +sea-schema = { version = "^0.5.0", default-features = false, features = [ "migration", "debug-print" ] } +entity = { path = "../entity" } diff --git a/examples/axum_example/migration/README.md b/examples/axum_example/migration/README.md new file mode 100644 index 00000000..963caaeb --- /dev/null +++ b/examples/axum_example/migration/README.md @@ -0,0 +1,37 @@ +# Running Migrator CLI + +- Apply all pending migrations + ```sh + cargo run + ``` + ```sh + cargo run -- up + ``` +- Apply first 10 pending migrations + ```sh + cargo run -- up -n 10 + ``` +- Rollback last applied migrations + ```sh + cargo run -- down + ``` +- Rollback last 10 applied migrations + ```sh + cargo run -- down -n 10 + ``` +- Drop all tables from the database, then reapply all migrations + ```sh + cargo run -- fresh + ``` +- Rollback all applied migrations, then reapply all migrations + ```sh + cargo run -- refresh + ``` +- Rollback all applied migrations + ```sh + cargo run -- reset + ``` +- Check the status of all migrations + ```sh + cargo run -- status + ``` diff --git a/examples/axum_example/migration/src/lib.rs b/examples/axum_example/migration/src/lib.rs new file mode 100644 index 00000000..3679d81f --- /dev/null +++ b/examples/axum_example/migration/src/lib.rs @@ -0,0 +1,12 @@ +pub use sea_schema::migration::prelude::*; + +mod m20220120_000001_create_post_table; + +pub struct Migrator; + +#[async_trait::async_trait] +impl MigratorTrait for Migrator { + fn migrations() -> Vec> { + vec![Box::new(m20220120_000001_create_post_table::Migration)] + } +} diff --git a/examples/axum_example/migration/src/m20220120_000001_create_post_table.rs b/examples/axum_example/migration/src/m20220120_000001_create_post_table.rs new file mode 100644 index 00000000..0fe872c4 --- /dev/null +++ b/examples/axum_example/migration/src/m20220120_000001_create_post_table.rs @@ -0,0 +1,39 @@ +use entity::post::*; +use sea_schema::migration::prelude::*; + +pub struct Migration; + +impl MigrationName for Migration { + fn name(&self) -> &str { + "m20220120_000001_create_post_table" + } +} + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(Entity) + .if_not_exists() + .col( + ColumnDef::new(Column::Id) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col(ColumnDef::new(Column::Title).string().not_null()) + .col(ColumnDef::new(Column::Text).string().not_null()) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop().table(Entity).to_owned()) + .await + } +} diff --git a/examples/axum_example/migration/src/main.rs b/examples/axum_example/migration/src/main.rs new file mode 100644 index 00000000..7e5e996d --- /dev/null +++ b/examples/axum_example/migration/src/main.rs @@ -0,0 +1,7 @@ +use migration::Migrator; +use sea_schema::migration::*; + +#[async_std::main] +async fn main() { + cli::run_cli(Migrator).await; +} diff --git a/examples/axum_example/src/main.rs b/examples/axum_example/src/main.rs index c35e180a..35b07976 100644 --- a/examples/axum_example/src/main.rs +++ b/examples/axum_example/src/main.rs @@ -1,15 +1,16 @@ mod flash; -mod post; -mod setup; use axum::{ extract::{Extension, Form, Path, Query}, http::StatusCode, response::Html, - routing::{get, post, get_service}, + routing::{get, get_service, post}, AddExtensionLayer, Router, Server, }; +use entity::post; +use entity::sea_orm; use flash::{get_flash_cookie, post_response, PostResponse}; +use migration::{Migrator, MigratorTrait}; use post::Entity as Post; use sea_orm::{prelude::*, Database, QueryOrder, Set}; use serde::{Deserialize, Serialize}; @@ -34,7 +35,7 @@ async fn main() -> anyhow::Result<()> { let conn = Database::connect(db_url) .await .expect("Database connection failed"); - let _ = setup::create_post_table(&conn).await; + Migrator::up(&conn, None).await.unwrap(); let templates = Tera::new(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")) .expect("Tera initialization failed"); // let state = AppState { templates, conn }; diff --git a/examples/axum_example/src/setup.rs b/examples/axum_example/src/setup.rs deleted file mode 100644 index 04677af4..00000000 --- a/examples/axum_example/src/setup.rs +++ /dev/null @@ -1,33 +0,0 @@ -use sea_orm::sea_query::{ColumnDef, TableCreateStatement}; -use sea_orm::{error::*, sea_query, ConnectionTrait, DbConn, ExecResult}; - -async fn create_table(db: &DbConn, stmt: &TableCreateStatement) -> Result { - let builder = db.get_database_backend(); - db.execute(builder.build(stmt)).await -} - -pub async fn create_post_table(db: &DbConn) -> Result { - let stmt = sea_query::Table::create() - .table(super::post::Entity) - .if_not_exists() - .col( - ColumnDef::new(super::post::Column::Id) - .integer() - .not_null() - .auto_increment() - .primary_key(), - ) - .col( - ColumnDef::new(super::post::Column::Title) - .string() - .not_null(), - ) - .col( - ColumnDef::new(super::post::Column::Text) - .string() - .not_null(), - ) - .to_owned(); - - create_table(db, &stmt).await -} diff --git a/examples/poem_example/Cargo.toml b/examples/poem_example/Cargo.toml index 5f7dea00..7b109792 100644 --- a/examples/poem_example/Cargo.toml +++ b/examples/poem_example/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [workspace] +members = [".", "entity", "migration"] [dependencies] tokio = { version = "1.15.0", features = ["macros", "rt-multi-thread"] } @@ -13,15 +14,5 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] } serde = { version = "1", features = ["derive"] } tera = "1.8.0" dotenv = "0.15" - -[dependencies.sea-orm] -path = "../../" # remove this line in your own project -version = "^0.6.0" -features = ["macros", "runtime-tokio-native-tls", "debug-print"] -default-features = false - -[features] -default = ["sqlx-sqlite"] -sqlx-mysql = ["sea-orm/sqlx-mysql"] -sqlx-postgres = ["sea-orm/sqlx-postgres"] -sqlx-sqlite = ["sea-orm/sqlx-sqlite"] +entity = { path = "entity" } +migration = { path = "migration" } diff --git a/examples/poem_example/README.md b/examples/poem_example/README.md index 65eb8428..b9ec2d3e 100644 --- a/examples/poem_example/README.md +++ b/examples/poem_example/README.md @@ -1,10 +1,11 @@ +![screenshot](Screenshot.png) + # Poem with SeaORM example app -Edit `Cargo.toml` to use `sqlx-mysql` or `sqlx-postgres`. +1. Modify the `DATABASE_URL` var in `.env` to point to your chosen database -```toml -[features] -default = ["sqlx-$DATABASE"] -``` +1. Turn on the appropriate database feature for your chosen db in `entity/Cargo.toml` (the `"sqlx-sqlite",` line) -Edit `.env` to point to your database. +1. Execute `cargo run` to start the server + +1. Visit [localhost:8000](http://localhost:8000) in browser after seeing the `server started` line diff --git a/examples/poem_example/Screenshot.png b/examples/poem_example/Screenshot.png new file mode 100644 index 00000000..7ddc244a Binary files /dev/null and b/examples/poem_example/Screenshot.png differ diff --git a/examples/poem_example/entity/Cargo.toml b/examples/poem_example/entity/Cargo.toml new file mode 100644 index 00000000..7a6ac369 --- /dev/null +++ b/examples/poem_example/entity/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "entity" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +name = "entity" +path = "src/lib.rs" + +[dependencies] +serde = { version = "1", features = ["derive"] } + +[dependencies.sea-orm] +# path = "../../../" # remove this line in your own project +version = "^0.6.0" +features = [ + "macros", + "debug-print", + "runtime-tokio-native-tls", + "sqlx-sqlite", + # "sqlx-postgres", + # "sqlx-mysql", +] +default-features = false \ No newline at end of file diff --git a/examples/poem_example/entity/src/lib.rs b/examples/poem_example/entity/src/lib.rs new file mode 100644 index 00000000..263f05b4 --- /dev/null +++ b/examples/poem_example/entity/src/lib.rs @@ -0,0 +1,3 @@ +pub mod post; + +pub use sea_orm; diff --git a/examples/poem_example/src/post.rs b/examples/poem_example/entity/src/post.rs similarity index 100% rename from examples/poem_example/src/post.rs rename to examples/poem_example/entity/src/post.rs diff --git a/examples/poem_example/migration/Cargo.toml b/examples/poem_example/migration/Cargo.toml new file mode 100644 index 00000000..9a7c338f --- /dev/null +++ b/examples/poem_example/migration/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "migration" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +name = "migration" +path = "src/lib.rs" + +[dependencies] +sea-schema = { version = "^0.5.0", default-features = false, features = [ "migration", "debug-print" ] } +entity = { path = "../entity" } diff --git a/examples/poem_example/migration/README.md b/examples/poem_example/migration/README.md new file mode 100644 index 00000000..963caaeb --- /dev/null +++ b/examples/poem_example/migration/README.md @@ -0,0 +1,37 @@ +# Running Migrator CLI + +- Apply all pending migrations + ```sh + cargo run + ``` + ```sh + cargo run -- up + ``` +- Apply first 10 pending migrations + ```sh + cargo run -- up -n 10 + ``` +- Rollback last applied migrations + ```sh + cargo run -- down + ``` +- Rollback last 10 applied migrations + ```sh + cargo run -- down -n 10 + ``` +- Drop all tables from the database, then reapply all migrations + ```sh + cargo run -- fresh + ``` +- Rollback all applied migrations, then reapply all migrations + ```sh + cargo run -- refresh + ``` +- Rollback all applied migrations + ```sh + cargo run -- reset + ``` +- Check the status of all migrations + ```sh + cargo run -- status + ``` diff --git a/examples/poem_example/migration/src/lib.rs b/examples/poem_example/migration/src/lib.rs new file mode 100644 index 00000000..3679d81f --- /dev/null +++ b/examples/poem_example/migration/src/lib.rs @@ -0,0 +1,12 @@ +pub use sea_schema::migration::prelude::*; + +mod m20220120_000001_create_post_table; + +pub struct Migrator; + +#[async_trait::async_trait] +impl MigratorTrait for Migrator { + fn migrations() -> Vec> { + vec![Box::new(m20220120_000001_create_post_table::Migration)] + } +} diff --git a/examples/poem_example/migration/src/m20220120_000001_create_post_table.rs b/examples/poem_example/migration/src/m20220120_000001_create_post_table.rs new file mode 100644 index 00000000..0fe872c4 --- /dev/null +++ b/examples/poem_example/migration/src/m20220120_000001_create_post_table.rs @@ -0,0 +1,39 @@ +use entity::post::*; +use sea_schema::migration::prelude::*; + +pub struct Migration; + +impl MigrationName for Migration { + fn name(&self) -> &str { + "m20220120_000001_create_post_table" + } +} + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(Entity) + .if_not_exists() + .col( + ColumnDef::new(Column::Id) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col(ColumnDef::new(Column::Title).string().not_null()) + .col(ColumnDef::new(Column::Text).string().not_null()) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop().table(Entity).to_owned()) + .await + } +} diff --git a/examples/poem_example/migration/src/main.rs b/examples/poem_example/migration/src/main.rs new file mode 100644 index 00000000..7e5e996d --- /dev/null +++ b/examples/poem_example/migration/src/main.rs @@ -0,0 +1,7 @@ +use migration::Migrator; +use sea_schema::migration::*; + +#[async_std::main] +async fn main() { + cli::run_cli(Migrator).await; +} diff --git a/examples/poem_example/src/main.rs b/examples/poem_example/src/main.rs index be883bde..f2a826ab 100644 --- a/examples/poem_example/src/main.rs +++ b/examples/poem_example/src/main.rs @@ -1,5 +1,8 @@ use std::env; +use entity::post; +use entity::sea_orm; +use migration::{Migrator, MigratorTrait}; use poem::endpoint::StaticFilesEndpoint; use poem::error::{BadRequest, InternalServerError}; use poem::http::StatusCode; @@ -10,9 +13,6 @@ use sea_orm::{entity::*, query::*, DatabaseConnection}; use serde::Deserialize; use tera::Tera; -mod post; -mod setup; - const DEFAULT_POSTS_PER_PAGE: usize = 5; #[derive(Debug, Clone)] @@ -142,7 +142,7 @@ async fn main() -> std::io::Result<()> { // create post table if not exists let conn = sea_orm::Database::connect(&db_url).await.unwrap(); - let _ = setup::create_post_table(&conn).await; + Migrator::up(&conn, None).await.unwrap(); let templates = Tera::new(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")).unwrap(); let state = AppState { templates, conn }; diff --git a/examples/poem_example/src/setup.rs b/examples/poem_example/src/setup.rs deleted file mode 100644 index 04677af4..00000000 --- a/examples/poem_example/src/setup.rs +++ /dev/null @@ -1,33 +0,0 @@ -use sea_orm::sea_query::{ColumnDef, TableCreateStatement}; -use sea_orm::{error::*, sea_query, ConnectionTrait, DbConn, ExecResult}; - -async fn create_table(db: &DbConn, stmt: &TableCreateStatement) -> Result { - let builder = db.get_database_backend(); - db.execute(builder.build(stmt)).await -} - -pub async fn create_post_table(db: &DbConn) -> Result { - let stmt = sea_query::Table::create() - .table(super::post::Entity) - .if_not_exists() - .col( - ColumnDef::new(super::post::Column::Id) - .integer() - .not_null() - .auto_increment() - .primary_key(), - ) - .col( - ColumnDef::new(super::post::Column::Title) - .string() - .not_null(), - ) - .col( - ColumnDef::new(super::post::Column::Text) - .string() - .not_null(), - ) - .to_owned(); - - create_table(db, &stmt).await -} diff --git a/examples/poem_example/templates/layout.html.tera b/examples/poem_example/templates/layout.html.tera index c930afcc..50ae5885 100644 --- a/examples/poem_example/templates/layout.html.tera +++ b/examples/poem_example/templates/layout.html.tera @@ -2,7 +2,7 @@ - Actix Example + Poem Example diff --git a/examples/rocket_example/README.md b/examples/rocket_example/README.md index b3a50db6..6ef30ea6 100644 --- a/examples/rocket_example/README.md +++ b/examples/rocket_example/README.md @@ -6,6 +6,6 @@ 1. Turn on the appropriate database feature for your chosen db in `entity/Cargo.toml` (the `"sqlx-postgres",` line) -1. `cargo run` to start the server +1. Execute `cargo run` to start the server -1. Open in browser after seeing the `🚀 Rocket has launched from http://localhost:8000` line +1. Visit [localhost:8000](http://localhost:8000) in browser after seeing the `🚀 Rocket has launched from http://localhost:8000` line diff --git a/examples/rocket_example/entity/Cargo.toml b/examples/rocket_example/entity/Cargo.toml index 43af7486..0f0fbcce 100644 --- a/examples/rocket_example/entity/Cargo.toml +++ b/examples/rocket_example/entity/Cargo.toml @@ -21,5 +21,6 @@ features = [ "runtime-tokio-native-tls", "sqlx-postgres", # "sqlx-mysql", + # "sqlx-sqlite", ] default-features = false \ No newline at end of file