use derive_builder::Builder; use serde::Serialize; use sqlx::{postgres::types::Oid, query_as}; use uuid::Uuid; use crate::client::AppDbClient; #[derive(Clone, Debug, Serialize)] pub struct Lens { pub id: Uuid, pub name: String, pub base_id: Uuid, pub class_oid: Oid, pub display_type: LensDisplayType, } impl Lens { pub fn insertable_builder() -> InsertableLensBuilder { InsertableLensBuilder::default() } pub fn with_id(id: Uuid) -> WithIdQuery { WithIdQuery { id } } pub fn belonging_to_base(base_id: Uuid) -> BelongingToBaseQuery { BelongingToBaseQuery { base_id } } } #[derive(Clone, Debug)] pub struct WithIdQuery { id: Uuid, } impl WithIdQuery { pub async fn fetch_optional( self, app_db: &mut AppDbClient, ) -> Result, sqlx::Error> { query_as!( Lens, r#" select id, name, base_id, class_oid, display_type as "display_type: LensDisplayType" from lenses where id = $1 "#, self.id ) .fetch_optional(&mut *app_db.conn) .await } pub async fn fetch_one(self, app_db: &mut AppDbClient) -> Result { query_as!( Lens, r#" select id, name, base_id, class_oid, display_type as "display_type: LensDisplayType" from lenses where id = $1 "#, self.id ) .fetch_one(&mut *app_db.conn) .await } } #[derive(Clone, Debug)] pub struct BelongingToBaseQuery { base_id: Uuid, } impl BelongingToBaseQuery { pub fn belonging_to_rel(self, rel_oid: Oid) -> BelongingToRelQuery { BelongingToRelQuery { base_id: self.base_id, rel_oid, } } } #[derive(Clone, Debug)] pub struct BelongingToRelQuery { base_id: Uuid, rel_oid: Oid, } impl BelongingToRelQuery { pub async fn fetch_all(self, app_db: &mut AppDbClient) -> Result, sqlx::Error> { query_as!( Lens, r#" select id, name, base_id, class_oid, display_type as "display_type: LensDisplayType" from lenses where base_id = $1 and class_oid = $2 "#, self.base_id, self.rel_oid ) .fetch_all(&mut *app_db.conn) .await } } #[derive(Clone, Debug, Serialize, sqlx::Type)] #[sqlx(type_name = "lens_display_type", rename_all = "lowercase")] pub enum LensDisplayType { Table, } #[derive(Builder, Clone, Debug)] pub struct InsertableLens { name: String, base_id: Uuid, class_oid: Oid, display_type: LensDisplayType, } impl InsertableLens { pub async fn insert(self, app_db: &mut AppDbClient) -> Result { query_as!( Lens, r#" insert into lenses (id, base_id, class_oid, name, display_type) values ($1, $2, $3, $4, $5) returning id, name, base_id, class_oid, display_type as "display_type: LensDisplayType" "#, Uuid::now_v7(), self.base_id, self.class_oid, self.name, self.display_type as LensDisplayType ) .fetch_one(&mut *app_db.conn) .await } }