From 51e12788c34a902a6d237930246ab72df649c19e Mon Sep 17 00:00:00 2001 From: cahe Date: Sat, 15 Oct 2022 19:05:13 -0300 Subject: [PATCH] Demonstrate UUID support --- Cargo.toml | 3 ++- src/app/forms.rs | 4 ++-- src/app/robots.rs | 20 ++++++++++---------- src/base/robots.rs | 6 +++--- src/data/robots/postgres.rs | 37 ++++++++++++++++++++----------------- src/http/robots.rs | 16 ++++++++-------- 6 files changed, 45 insertions(+), 41 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e8d9d56..cf116d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,4 +11,5 @@ warp = "0.2" tokio = { version = "0.2", features = ["macros"] } serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0" } -sqlx = { version = "0.4.0-beta.1", default-features = false, features = [ "postgres", "runtime-tokio-rustls", "macros" ] } +sqlx = { version = "0.4.0-beta.1", default-features = false, features = [ "postgres", "runtime-tokio-rustls", "macros", "uuid" ] } +uuid = { version = "1.2.1", features = [ "serde" ] } \ No newline at end of file diff --git a/src/app/forms.rs b/src/app/forms.rs index fde36b9..56f7a5a 100644 --- a/src/app/forms.rs +++ b/src/app/forms.rs @@ -5,14 +5,14 @@ use crate::base::robots; #[derive(Serialize, Deserialize)] pub struct GetRobot { #[serde(skip_deserializing)] - pub id: Option, + pub uuid: Option, pub name: String, } impl std::convert::From for GetRobot { fn from(r: robots::Robot) -> GetRobot { GetRobot { - id: Some(r.id), + uuid: Some(r.uuid), name: r.name, } } diff --git a/src/app/robots.rs b/src/app/robots.rs index 2de1aa2..e87d4ce 100644 --- a/src/app/robots.rs +++ b/src/app/robots.rs @@ -14,9 +14,9 @@ pub async fn add_robot( let pool = shared.find::().unwrap(); let mut tx = pool.begin().await?; - let model = robots::Robot::new(0, r.name).try_into()?; - let id = postgres::add(tx.as_mut(), model).await?; - let robot = postgres::get_by_id(tx.as_mut(), id).await?; + let model = robots::Robot::new(uuid::Uuid::nil(), r.name).try_into()?; + let uuid = postgres::add(tx.as_mut(), model).await?; + let robot = postgres::get_by_id(tx.as_mut(), uuid).await?; tx.commit().await.map_err(|e| HandlingError::DBError(e))?; @@ -25,11 +25,11 @@ pub async fn add_robot( pub async fn get_robot( shared: std::sync::Arc>, - id: i64, + uuid: uuid::Uuid, ) -> Result { let pool = shared.find::().unwrap(); let mut tx = pool.begin().await?; - Ok(postgres::get_by_id(tx.as_mut(), id).await?.into()) + Ok(postgres::get_by_id(tx.as_mut(), uuid).await?.into()) } pub async fn get_all( @@ -50,15 +50,15 @@ pub async fn get_all( pub async fn update_robot( shared: std::sync::Arc>, - id: i64, + uuid: uuid::Uuid, r: GetRobot, ) -> Result { let pool = shared.find::().unwrap(); let mut tx = pool.begin().await?; - let model = robots::Robot::new(id, r.name).try_into()?; + let model = robots::Robot::new(uuid, r.name).try_into()?; postgres::update(tx.as_mut(), model).await?; - let robot = postgres::get_by_id(tx.as_mut(), id).await?; + let robot = postgres::get_by_id(tx.as_mut(), uuid).await?; tx.commit().await.map_err(HandlingError::DBError)?; @@ -67,12 +67,12 @@ pub async fn update_robot( pub async fn delete_robot( shared: std::sync::Arc>, - id: i64, + uuid: uuid::Uuid, ) -> Result<(), HandlingError> { let pool = shared.find::().unwrap(); let mut tx = pool.begin().await?; - postgres::delete(tx.as_mut(), id).await?; + postgres::delete(tx.as_mut(), uuid).await?; tx.commit().await.map_err(HandlingError::DBError)?; Ok(()) diff --git a/src/base/robots.rs b/src/base/robots.rs index a9000d5..ea6c641 100644 --- a/src/base/robots.rs +++ b/src/base/robots.rs @@ -2,13 +2,13 @@ use crate::simple::HandlingError; use std::convert::TryFrom; pub struct Robot { - pub id: i64, + pub uuid: uuid::Uuid, pub name: String, } impl Robot { - pub fn new(id: i64, name: String) -> Self { - Self { id: id, name: name } + pub fn new(uuid : uuid::Uuid, name: String) -> Self { + Self { uuid: uuid, name: name } } } diff --git a/src/data/robots/postgres.rs b/src/data/robots/postgres.rs index ab56e12..0b94cf9 100644 --- a/src/data/robots/postgres.rs +++ b/src/data/robots/postgres.rs @@ -19,7 +19,7 @@ where { pub fn new(tx: &'c mut Box) -> Collection<'c, E> { let all = sqlx::query::( - "SELECT id, name + "SELECT id, name, uuid FROM robots WHERE (CASE WHEN $1::BOOLEAN THEN (id = $2::INTEGER) ELSE TRUE END) @@ -54,8 +54,8 @@ where Ok(v) => v .into_iter() .map(|d| { - let (id, name) = <(i64, String)>::from_row(&d)?; - Ok(robots::Robot { id: id, name: name }) + let (_, name, uuid) = <(i64, String, sqlx::types::Uuid)>::from_row(&d)?; + Ok(robots::Robot { uuid: uuid::Uuid::from_u128(uuid.as_u128()), name: name }) }) .collect(), Err(e) => Err(HandlingError::DBError(e)), @@ -80,16 +80,16 @@ where pub async fn add( tx: impl sqlx::Executor<'_, Database = sqlx::Postgres>, m: robots::RobotModel, -) -> Result { +) -> Result { let r: robots::Robot = m.into(); - let result = sqlx::query("INSERT INTO robots (name) VALUES ($1::TEXT) RETURNING id") + let result = sqlx::query("INSERT INTO robots (name) VALUES ($1::TEXT) RETURNING id, uuid") .bind(r.name) .fetch_one(tx) .await; match result { Ok(v) => { - let (id,) = <(i64,)>::from_row(&v)?; - Ok(id) + let (_, uuid) = <(i64, sqlx::types::Uuid,)>::from_row(&v)?; + Ok(uuid::Uuid::from_u128(uuid.as_u128())) } Err(sqlx::Error::RowNotFound) => Err(HandlingError::NotFound), Err(e) => Err(HandlingError::DBError(e)), @@ -98,16 +98,17 @@ pub async fn add( pub async fn get_by_id( tx: impl sqlx::Executor<'_, Database = sqlx::Postgres>, - id: i64, + uuid: uuid::Uuid, ) -> Result { - let result = sqlx::query("SELECT * FROM robots WHERE id = $1::INTEGER") - .bind(id) + let db_uuid = sqlx::types::Uuid::from_u128(uuid.as_u128()); + let result = sqlx::query("SELECT id, name, uuid FROM robots WHERE uuid = $1::UUID") + .bind(db_uuid) .fetch_one(tx) .await; match result { Ok(v) => { - let (id, name) = <(i64, String)>::from_row(&v)?; - Ok(robots::Robot { id: id, name: name }) + let (_, name, uuid) = <(i64, String, sqlx::types::Uuid)>::from_row(&v)?; + Ok(robots::Robot { uuid: uuid::Uuid::from_u128(uuid.as_u128()), name: name }) } Err(sqlx::Error::RowNotFound) => Err(HandlingError::NotFound), Err(e) => Err(HandlingError::DBError(e)), @@ -119,9 +120,10 @@ pub async fn update( m: robots::RobotModel, ) -> Result<(), HandlingError> { let r: robots::Robot = m.into(); - let result = sqlx::query("UPDATE robots SET name = $1::TEXT WHERE id = $2::INTEGER") + let db_uuid = sqlx::types::Uuid::from_u128(r.uuid.as_u128()); + let result = sqlx::query("UPDATE robots SET name = $1::TEXT WHERE uuid = $2::UUID") .bind(r.name) - .bind(r.id) + .bind(db_uuid) .execute(tx) .await; match result { @@ -137,10 +139,11 @@ pub async fn update( pub async fn delete( tx: impl sqlx::Executor<'_, Database = sqlx::Postgres>, - id: i64, + uuid: uuid::Uuid, ) -> Result<(), HandlingError> { - let result = sqlx::query("DELETE FROM robots WHERE id = $1::INTEGER") - .bind(id) + let db_uuid = sqlx::types::Uuid::from_u128(uuid.as_u128()); + let result = sqlx::query("DELETE FROM robots WHERE uuid = $1::UUID") + .bind(db_uuid) .execute(tx) .await; match result { diff --git a/src/http/robots.rs b/src/http/robots.rs index 4bd5d3e..6237d8b 100644 --- a/src/http/robots.rs +++ b/src/http/robots.rs @@ -1,4 +1,3 @@ -use crate::simple::database::PgSharedPool; use crate::simple::http::reply_json; use warp::{Filter, Rejection, Reply}; @@ -7,6 +6,7 @@ use warp::filters::{body, method, query as params}; use warp::http::StatusCode; use serde::{Deserialize, Serialize}; +use uuid::Uuid; use crate::app; @@ -33,18 +33,18 @@ async fn create( // retrieve information of a single robot async fn get( shared: std::sync::Arc>, - id: i64, + uuid: Uuid, ) -> Result { - reply_json(app::robots::get_robot(shared, id).await) + reply_json(app::robots::get_robot(shared, uuid).await) } // updates robot information async fn update( pool: std::sync::Arc>, - id: i64, + uuid: Uuid, r: app::forms::GetRobot, ) -> Result { - reply_json(app::robots::update_robot(pool, id, r).await) + reply_json(app::robots::update_robot(pool, uuid, r).await) } // returns a pagination of all robots @@ -65,9 +65,9 @@ async fn get_all( // will delete the requested robot async fn delete( pool: std::sync::Arc>, - id: i64, + uuid: Uuid, ) -> Result { - match app::robots::delete_robot(pool, id).await { + match app::robots::delete_robot(pool, uuid).await { Ok(_) => Ok(warp::reply::with_status( warp::reply(), StatusCode::NO_CONTENT, @@ -118,7 +118,7 @@ pub fn with_id( // we create a prefix containing the id of a robot and a shared database connection // every filter is added after the prefix // so it receives a robot's id and a database connection - let prefix = warp::path!("robot" / i64) + let prefix = warp::path!("robot" / Uuid) .map(move |id| (pool.clone(), id)) .untuple_one();