use diesel::{insert_into, prelude::*, Insertable, PgConnection, Queryable}; use rb::errors::{RbError, RbOption, RbResult}; use serde::{Deserialize, Serialize}; use uuid::Uuid; use crate::schema::{posts, posts::dsl::*}; /// A post inside the database. #[derive(Queryable, Serialize)] pub struct Post { pub id: Uuid, pub section_id: Uuid, pub is_private: bool, pub is_archived: bool, } /// A new post to be added to the database. #[derive(Deserialize, Insertable)] #[table_name = "posts"] #[serde(rename_all = "camelCase")] pub struct NewPost { pub section_id: Uuid, pub is_private: Option, pub is_archived: Option, } /// A patch to be applied to a row in the database. #[derive(Deserialize, AsChangeset)] #[table_name = "posts"] pub struct PatchPost { pub section_id: Option, pub is_private: Option, pub is_archived: Option, } /// Get a list of posts, specified by the offset & a limit. The maximum for `limit_` is determined /// by `super::MAX_POSTS`. pub fn get(conn: &PgConnection, offset_: u32, limit_: u32) -> RbResult> { Ok(posts .offset(offset_.into()) .limit(std::cmp::min(limit_, super::MAX_POSTS).into()) .load(conn) .map_err(|_| RbError::DbError("Couldn't query posts."))?) } /// Try to find a post given its id (primary key). pub fn find(conn: &PgConnection, id_: &Uuid) -> RbOption { match posts.find(id_).first(conn) { Ok(val) => Ok(Some(val)), Err(diesel::NotFound) => Ok(None), _ => Err(RbError::DbError("Couldn't find post.")), } } /// Create a new post & store it in the database. pub fn create(conn: &PgConnection, new_post: &NewPost) -> RbResult { Ok(insert_into(posts) .values(new_post) .get_result(conn) .map_err(|_| RbError::DbError("Couldn't insert post."))?) // TODO check for conflict? } /// Update a post in the database with a given ID, returning the updated row. pub fn update(conn: &PgConnection, post_id: &Uuid, patch_post: &PatchPost) -> RbResult { Ok(diesel::update(posts.filter(id.eq(post_id))) .set(patch_post) .get_result(conn) .map_err(|_| RbError::DbError("Couldn't update post."))?) } /// Delete a post with a given ID. pub fn delete(conn: &PgConnection, post_id: &Uuid) -> RbResult<()> { diesel::delete(posts.filter(id.eq(post_id))) .execute(conn) .map_err(|_| RbError::DbError("Couldn't delete post."))?; Ok(()) }