From 73b72e3a31b4990c70a9284ecae57535b897cf7a Mon Sep 17 00:00:00 2001 From: Sam Samai Date: Tue, 17 Aug 2021 22:37:28 +1000 Subject: [PATCH] WIP --- examples/rocket_example/db/sqlx/db.sqlite | Bin 20480 -> 24576 bytes examples/rocket_example/db/sqlx/db.sqlite-shm | Bin 0 -> 32768 bytes examples/rocket_example/db/sqlx/db.sqlite-wal | 0 examples/rocket_example/src/sqlx.rs | 90 -------------- examples/rocket_example/src/sqlx/mod.rs | 113 ++++++++++++++++++ examples/rocket_example/src/sqlx/post.rs | 51 ++++++++ examples/rocket_example/src/tests.rs | 26 ++-- 7 files changed, 175 insertions(+), 105 deletions(-) create mode 100644 examples/rocket_example/db/sqlx/db.sqlite-shm create mode 100644 examples/rocket_example/db/sqlx/db.sqlite-wal delete mode 100644 examples/rocket_example/src/sqlx.rs create mode 100644 examples/rocket_example/src/sqlx/mod.rs create mode 100644 examples/rocket_example/src/sqlx/post.rs diff --git a/examples/rocket_example/db/sqlx/db.sqlite b/examples/rocket_example/db/sqlx/db.sqlite index a961169b0be0cf84bbad7a806bb1f0e842f1469c..362447f5c77269de04bcdc876be3d77e0012ecbe 100644 GIT binary patch literal 24576 zcmeI4L2TPp7{~3lX`7-FG_*w%5_$+tTeYUV=jZs@(*#RL*a~UWr718?C3?1>*RV9{ zVh43XXkv`RG$c+)8wYmffVd*D0~aJF!461Vci_Mk35g*jK=7QbWv{s5(1=6%UhFi_ zpa0)`-_KwCZ0n^m_Oq}!G74&kUa`JScf)jKDOQXZzHV zTLY6Cj0e7xCl)cOjV;F}f{?%#)bwS|Bc{oWnTs9KzBG8Zz6iZ`-4!!ltI=6&hAZgB zrSihSdcEa-owxa#h(tS_snpM}Mk{D;p*r|xnw>@?K0<03)H7_y=Z?+fF<_h!;t<~z zzL)oy?c0{bZ*j|~7GuN>giDNoQo>!2TLyEyUaAwDy*{MGv)%e2v^V5P zF2!he?o>RGKNMaspk9ux#|@xr@l_d*5>veyM!X@fq-wE!ZoarwEzB=&?X=bVlgpKg zgjCzwrRP2Dc=9lY|A@M0^;U&<{0%_4)D4 z&nG5iTzcjgO)gM?01yBIKmZ5;0U!VbfB+Bx0zd!=0D(P4AU&K)_ns?EX1>>kGIzAh z51BiU{P^#$J%s^+0Rlh(2mk>f00e*l5C8&uoWRJwLubb4FQG*_FC68Nfy;8HIqIy- z`OO@~bB(8w{2j1?54VulXn7ZAW@h9sf$u3I;v|ZQql!LOMRu~tRz;yIV#y+=ik?+P zR|WKeTKHxx;7DyW&D{i#Tj6G6=b?HfgsoCazZ zXg3u}auTRHpaqH~IR%Wv@{IN5!R&#QcJR=6JU;*#yxEFYMH|I6X&pJZUmB;mia0@0xq_|L<#=`+NMv2jKw$AOHk_01yBIKmZ5;0U!VbfB+EqzY$35!&yCk8W0|c l@BigL{euDofB+Bx0zd!=00AHX1b_e#00KY&2<%}3e*uejcHaO1 delta 134 zcmZoTz}T>Wae}lU69WSSD-go~(?lI(Q6>gG{~BKY9}FzK^$dL7{M&gi^44z_6yWCF zT+iF2#12v{z`!tBz(8TLf&s^71B1!@GWiP0Ir+)idU|?5Sz~2?4&O?Jfc)YT1ziQh U$&5ClJcjBBC7T@n^D~M701Y}FsQ>@~ diff --git a/examples/rocket_example/db/sqlx/db.sqlite-shm b/examples/rocket_example/db/sqlx/db.sqlite-shm new file mode 100644 index 0000000000000000000000000000000000000000..fe9ac2845eca6fe6da8a63cd096d9cf9e24ece10 GIT binary patch literal 32768 zcmeIuAr62r3> = std::result::Result; - -#[derive(Debug, Clone, Deserialize, Serialize)] -#[serde(crate = "rocket::serde")] -struct Post { - #[serde(skip_deserializing, skip_serializing_if = "Option::is_none")] - id: Option, - title: String, - text: String, -} - -#[post("/", data = "")] -async fn create(mut db: Connection, post: Json) -> Result>> { - // There is no support for `RETURNING`. - sqlx::query!("INSERT INTO posts (title, text) VALUES (?, ?)", post.title, post.text) - .execute(&mut *db) - .await?; - - Ok(Created::new("/").body(post)) -} - -#[get("/")] -async fn list(mut db: Connection) -> Result>> { - let ids = sqlx::query!("SELECT id FROM posts") - .fetch(&mut *db) - .map_ok(|record| record.id) - .try_collect::>() - .await?; - - Ok(Json(ids)) -} - -#[get("/")] -async fn read(mut db: Connection, id: i64) -> Option> { - sqlx::query!("SELECT id, title, text FROM posts WHERE id = ?", id) - .fetch_one(&mut *db) - .map_ok(|r| Json(Post { id: Some(r.id), title: r.title, text: r.text })) - .await - .ok() -} - -#[delete("/")] -async fn delete(mut db: Connection, id: i64) -> Result> { - let result = sqlx::query!("DELETE FROM posts WHERE id = ?", id) - .execute(&mut *db) - .await?; - - Ok((result.rows_affected() == 1).then(|| ())) -} - -#[delete("/")] -async fn destroy(mut db: Connection) -> Result<()> { - sqlx::query!("DELETE FROM posts").execute(&mut *db).await?; - - Ok(()) -} - -async fn run_migrations(rocket: Rocket) -> fairing::Result { - match Db::fetch(&rocket) { - Some(db) => match sqlx::migrate!("db/sqlx/migrations").run(&**db).await { - Ok(_) => Ok(rocket), - Err(e) => { - error!("Failed to initialize SQLx database: {}", e); - Err(rocket) - } - } - None => Err(rocket), - } -} - -pub fn stage() -> AdHoc { - AdHoc::on_ignite("SQLx Stage", |rocket| async { - rocket.attach(Db::init()) - .attach(AdHoc::try_on_ignite("SQLx Migrations", run_migrations)) - .mount("/sqlx", routes![list, create, read, delete, destroy]) - }) -} diff --git a/examples/rocket_example/src/sqlx/mod.rs b/examples/rocket_example/src/sqlx/mod.rs new file mode 100644 index 00000000..178bb3ef --- /dev/null +++ b/examples/rocket_example/src/sqlx/mod.rs @@ -0,0 +1,113 @@ +use rocket::fairing::{self, AdHoc}; +use rocket::response::status::Created; +use rocket::serde::{json::Json, Deserialize, Serialize}; +use rocket::{futures, Build, Rocket}; + +use rocket_db_pools::{sqlx, Connection, Database}; + +use futures::{future::TryFutureExt, stream::TryStreamExt}; + +// use post::*; +mod post; +pub use post::Entity as Post; + +#[derive(Database)] +#[database("sqlx")] +struct Db(sqlx::SqlitePool); + +type Result> = std::result::Result; + +// #[derive(Debug, Clone, Deserialize, Serialize)] +// #[serde(crate = "rocket::serde")] +// struct Post { +// #[serde(skip_deserializing, skip_serializing_if = "Option::is_none")] +// id: Option, +// title: String, +// text: String, +// } + +// #[post("/", data = "")] +// async fn create(mut db: Connection, post: Json) -> Result>> { +// // There is no support for `RETURNING`. +// sqlx::query!( +// "INSERT INTO posts (title, text) VALUES (?, ?)", +// post.title, +// post.text +// ) +// .execute(&mut *db) +// .await?; + +// Ok(Created::new("/").body(post)) +// } + +#[get("/")] +async fn list(mut db: Connection) -> Result>> { + // let ids = sqlx::query!("SELECT id FROM posts") + // .fetch(&mut *db) + // .map_ok(|record| record.id) + // .try_collect::>() + // .await?; + let ids = vec![]; + Ok(Json(ids)) +} + +#[get("/")] +async fn read(mut db: Connection, id: i64) -> Option> { + let post: Option = Post::find_by_id(id) + .one(db) + .await + .expect("could not find baker"); + println!("post: {:#?}", post); + + // sqlx::query!("SELECT id, title, text FROM posts WHERE id = ?", id) + // .fetch_one(&mut *db) + // .map_ok(|r| { + // Json(Post { + // id: Some(r.id), + // title: r.title, + // text: r.text, + // }) + // }) + // .await + // .ok() + + None +} + +// #[delete("/")] +// async fn delete(mut db: Connection, id: i64) -> Result> { +// let result = sqlx::query!("DELETE FROM posts WHERE id = ?", id) +// .execute(&mut *db) +// .await?; + +// Ok((result.rows_affected() == 1).then(|| ())) +// } + +// #[delete("/")] +// async fn destroy(mut db: Connection) -> Result<()> { +// sqlx::query!("DELETE FROM posts").execute(&mut *db).await?; + +// Ok(()) +// } + +async fn run_migrations(rocket: Rocket) -> fairing::Result { + match Db::fetch(&rocket) { + Some(db) => match sqlx::migrate!("db/sqlx/migrations").run(&**db).await { + Ok(_) => Ok(rocket), + Err(e) => { + error!("Failed to initialize SQLx database: {}", e); + Err(rocket) + } + }, + None => Err(rocket), + } +} + +pub fn stage() -> AdHoc { + AdHoc::on_ignite("SQLx Stage", |rocket| async { + rocket + .attach(Db::init()) + .attach(AdHoc::try_on_ignite("SQLx Migrations", run_migrations)) + .mount("/sqlx", routes![list, read]) + }) +} diff --git a/examples/rocket_example/src/sqlx/post.rs b/examples/rocket_example/src/sqlx/post.rs new file mode 100644 index 00000000..360792e1 --- /dev/null +++ b/examples/rocket_example/src/sqlx/post.rs @@ -0,0 +1,51 @@ +use rocket::serde::{json::Json, Deserialize, Serialize}; +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "post" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel, Deserialize, Serialize)] +#[serde(crate = "rocket::serde")] +pub struct Model { + pub id: Option, + pub title: String, + pub text: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + Title, + Text, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + Id, +} + +impl PrimaryKeyTrait for PrimaryKey { + fn auto_increment() -> bool { + true + } +} + +impl ColumnTrait for Column { + type EntityName = Entity; + + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Title => ColumnType::String(None).def(), + Self::Text => ColumnType::String(None).def(), + } + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/examples/rocket_example/src/tests.rs b/examples/rocket_example/src/tests.rs index 98457e7f..6d88b1c0 100644 --- a/examples/rocket_example/src/tests.rs +++ b/examples/rocket_example/src/tests.rs @@ -1,7 +1,7 @@ use rocket::fairing::AdHoc; -use rocket::local::blocking::Client; -use rocket::serde::{Serialize, Deserialize}; use rocket::http::Status; +use rocket::local::blocking::Client; +use rocket::serde::{Deserialize, Serialize}; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] #[serde(crate = "rocket::serde")] @@ -20,13 +20,19 @@ fn test(base: &str, stage: AdHoc) { // Clear everything from the database. assert_eq!(client.delete(base).dispatch().status(), Status::Ok); - assert_eq!(client.get(base).dispatch().into_json::>(), Some(vec![])); + assert_eq!( + client.get(base).dispatch().into_json::>(), + Some(vec![]) + ); // Add some random posts, ensure they're listable and readable. - for i in 1..=N{ + for i in 1..=N { let title = format!("My Post - {}", i); let text = format!("Once upon a time, at {}'o clock...", i); - let post = Post { title: title.clone(), text: text.clone() }; + let post = Post { + title: title.clone(), + text: text.clone(), + }; // Create a new post. let response = client.post(base).json(&post).dispatch().into_json::(); @@ -66,13 +72,3 @@ fn test(base: &str, stage: AdHoc) { fn test_sqlx() { test("/sqlx", crate::sqlx::stage()) } - -#[test] -fn test_diesel() { - test("/diesel", crate::diesel_sqlite::stage()) -} - -#[test] -fn test_rusqlite() { - test("/rusqlite", crate::rusqlite::stage()) -}