diff options
Diffstat (limited to 'crates/rocie-server/src/storage/sql/get')
6 files changed, 202 insertions, 19 deletions
diff --git a/crates/rocie-server/src/storage/sql/get/mod.rs b/crates/rocie-server/src/storage/sql/get/mod.rs index 92b34aa..a6ee0e1 100644 --- a/crates/rocie-server/src/storage/sql/get/mod.rs +++ b/crates/rocie-server/src/storage/sql/get/mod.rs @@ -2,6 +2,7 @@ pub(crate) mod barcode; pub(crate) mod product; pub(crate) mod product_amount; pub(crate) mod product_parent; +pub(crate) mod recipe_parent; pub(crate) mod recipe; pub(crate) mod unit; pub(crate) mod unit_property; diff --git a/crates/rocie-server/src/storage/sql/get/product/mod.rs b/crates/rocie-server/src/storage/sql/get/product/mod.rs index 915da81..3d8b6e6 100644 --- a/crates/rocie-server/src/storage/sql/get/product/mod.rs +++ b/crates/rocie-server/src/storage/sql/get/product/mod.rs @@ -66,7 +66,7 @@ impl Product { } } - pub(crate) async fn from_name(app: &App, name: String) -> Result<Option<Self>, from_id::Error> { + pub(crate) async fn from_name(app: &App, name: &str) -> Result<Option<Self>, from_id::Error> { let record = query!( " SELECT name, id, unit_property, description, parent diff --git a/crates/rocie-server/src/storage/sql/get/product_parent/mod.rs b/crates/rocie-server/src/storage/sql/get/product_parent/mod.rs index 5b85b62..243ae1e 100644 --- a/crates/rocie-server/src/storage/sql/get/product_parent/mod.rs +++ b/crates/rocie-server/src/storage/sql/get/product_parent/mod.rs @@ -10,7 +10,7 @@ impl ProductParent { let records = query!( " SELECT id, parent, name, description - FROM parents + FROM product_parents " ) .fetch_all(&app.db) @@ -40,7 +40,7 @@ impl ProductParent { let record = query!( " SELECT parent, name, description - FROM parents + FROM product_parents WHERE id = ? ", id diff --git a/crates/rocie-server/src/storage/sql/get/recipe/mod.rs b/crates/rocie-server/src/storage/sql/get/recipe/mod.rs index 9d6dc79..f433541 100644 --- a/crates/rocie-server/src/storage/sql/get/recipe/mod.rs +++ b/crates/rocie-server/src/storage/sql/get/recipe/mod.rs @@ -1,15 +1,38 @@ use crate::{ app::App, - storage::sql::recipe::{Recipe, RecipeId}, + storage::sql::{ + recipe::{CooklangRecipe, Recipe, RecipeId}, + recipe_parent::RecipeParentId, + }, }; use sqlx::query; +pub(crate) mod parse { + use crate::storage::sql::recipe::conversion; + + #[derive(thiserror::Error, Debug)] + pub(crate) enum Error { + #[error("Failed to convert from cooklang recipe to our own struct")] + Conversion(#[from] conversion::Error), + } +} + +async fn recipe_from_content(app: &App, content: &str) -> Result<CooklangRecipe, parse::Error> { + // NOTE: We can ignore warnings here, as we should already have handled them at the recipe + // insert point. <2026-01-31> + let (output, _warnings) = cooklang::parse(content) + .into_result() + .expect("The values in the db should always be valid, as we checked before inserting them"); + + Ok(CooklangRecipe::from(app, output).await?) +} + impl Recipe { pub(crate) async fn from_id(app: &App, id: RecipeId) -> Result<Option<Self>, from_id::Error> { let record = query!( " - SELECT content, path + SELECT name, parent, content FROM recipies WHERE id = ? ", @@ -21,11 +44,33 @@ impl Recipe { if let Some(record) = record { Ok(Some(Self { id, - path: record - .path - .parse() - .expect("Was a path before, should still be one"), - content: record.content, + content: recipe_from_content(app, &record.content).await?, + name: record.name, + parent: record.parent.map(|id| RecipeParentId::from_db(&id)), + })) + } else { + Ok(None) + } + } + + pub(crate) async fn from_name(app: &App, name: String) -> Result<Option<Self>, from_id::Error> { + let record = query!( + " + SELECT id, parent, content + FROM recipies + WHERE name = ? +", + name + ) + .fetch_optional(&app.db) + .await?; + + if let Some(record) = record { + Ok(Some(Self { + id: RecipeId::from_db(&record.id), + content: recipe_from_content(app, &record.content).await?, + name, + parent: record.parent.map(|id| RecipeParentId::from_db(&id)), })) } else { Ok(None) @@ -35,31 +80,39 @@ impl Recipe { pub(crate) async fn get_all(app: &App) -> Result<Vec<Self>, get_all::Error> { let records = query!( " - SELECT id, content, path + SELECT id, name, parent, content FROM recipies ", ) .fetch_all(&app.db) .await?; - Ok(records - .into_iter() - .map(|record| Self { + let mut output = vec![]; + for record in records { + output.push(Self { id: RecipeId::from_db(&record.id), - path: record.path.parse().expect("Is still valid"), - content: record.content, - }) - .collect()) + content: recipe_from_content(app, &record.content).await?, + name: record.name, + parent: record.parent.map(|id| RecipeParentId::from_db(&id)), + }); + } + + Ok(output) } } pub(crate) mod from_id { use actix_web::ResponseError; + use crate::storage::sql::get::recipe::parse; + #[derive(thiserror::Error, Debug)] pub(crate) enum Error { - #[error("Failed to execute the sql query")] + #[error("Failed to execute the sql query: `{0}`")] SqlError(#[from] sqlx::Error), + + #[error("Failed to parse the recipe content as cooklang recipe: `{0}`")] + RecipeParse(#[from] parse::Error), } impl ResponseError for Error {} @@ -68,10 +121,15 @@ pub(crate) mod from_id { pub(crate) mod get_all { use actix_web::ResponseError; + use crate::storage::sql::get::recipe::parse; + #[derive(thiserror::Error, Debug)] pub(crate) enum Error { #[error("Failed to execute the sql query")] SqlError(#[from] sqlx::Error), + + #[error("Failed to parse the recipe content as cooklang recipe")] + RecipeParse(#[from] parse::Error), } impl ResponseError for Error {} diff --git a/crates/rocie-server/src/storage/sql/get/recipe_parent/mod.rs b/crates/rocie-server/src/storage/sql/get/recipe_parent/mod.rs new file mode 100644 index 0000000..d53e853 --- /dev/null +++ b/crates/rocie-server/src/storage/sql/get/recipe_parent/mod.rs @@ -0,0 +1,85 @@ +use crate::{ + app::App, + storage::sql::{ + recipe_parent::{RecipeParent, RecipeParentId}, + }, +}; + +use sqlx::query; + +impl RecipeParent { + pub(crate) async fn get_all(app: &App) -> Result<Vec<Self>, get_all::Error> { + let records = query!( + " + SELECT id, parent, name, description + FROM recipe_parents +" + ) + .fetch_all(&app.db) + .await?; + + let mut all = Vec::with_capacity(records.len()); + for record in records { + let parent = Self { + id: RecipeParentId::from_db(&record.id), + parent: record.parent.map(|parent| RecipeParentId::from_db(&parent)), + name: record.name, + description: record.description, + }; + + all.push(parent); + } + + Ok(all) + } + + pub(crate) async fn from_id( + app: &App, + id: RecipeParentId, + ) -> Result<Option<Self>, from_id::Error> { + let record = query!( + " + SELECT parent, name, description + FROM recipe_parents + WHERE id = ? +", + id + ) + .fetch_optional(&app.db) + .await?; + + match record { + Some(record) => Ok(Some(Self { + id, + parent: record.parent.map(|parent| RecipeParentId::from_db(&parent)), + name: record.name, + description: record.description, + })), + None => Ok(None), + } + } +} + +pub(crate) mod from_id { + use actix_web::ResponseError; + + #[derive(thiserror::Error, Debug)] + pub(crate) enum Error { + #[error("Failed to execute the sql query")] + SqlError(#[from] sqlx::Error), + } + + impl ResponseError for Error {} +} + +pub(crate) mod get_all { + use actix_web::ResponseError; + + #[derive(thiserror::Error, Debug)] + pub(crate) enum Error { + #[error("Failed to execute the sql query")] + SqlError(#[from] sqlx::Error), + } + + impl ResponseError for Error {} +} diff --git a/crates/rocie-server/src/storage/sql/get/user/mod.rs b/crates/rocie-server/src/storage/sql/get/user/mod.rs index e36c6cf..e09ef67 100644 --- a/crates/rocie-server/src/storage/sql/get/user/mod.rs +++ b/crates/rocie-server/src/storage/sql/get/user/mod.rs @@ -50,6 +50,33 @@ impl User { Ok(None) } } + + pub(crate) async fn from_name( + app: &App, + name: String, + ) -> Result<Option<Self>, from_name::Error> { + let record = query!( + " + SELECT id, name, password_hash, description + FROM users + WHERE name = ? +", + name + ) + .fetch_optional(&app.db) + .await?; + + if let Some(record) = record { + Ok(Some(Self { + name: record.name, + description: record.description, + id: UserId::from_db(&record.id), + password_hash: PasswordHash::from_db(record.password_hash), + })) + } else { + Ok(None) + } + } } pub(crate) mod get_all { @@ -75,3 +102,15 @@ pub(crate) mod from_id { impl ResponseError for Error {} } + +pub(crate) mod from_name { + use actix_web::ResponseError; + + #[derive(thiserror::Error, Debug)] + pub(crate) enum Error { + #[error("Failed to execute the sql query")] + SqlError(#[from] sqlx::Error), + } + + impl ResponseError for Error {} +} |
