use derive_builder::Builder; use serde::Serialize; use sqlx::{postgres::types::Oid, query, query_as, types::Json}; use uuid::Uuid; use crate::{client::AppDbClient, expression::PgExpressionAny}; #[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, pub filter: Json>, } impl Lens { pub fn insertable_builder() -> InsertableLensBuilder { InsertableLensBuilder::default() } pub fn update() -> LensUpdateBuilder { LensUpdateBuilder::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", filter as "filter: Json>" 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", filter as "filter: Json>" 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", filter as "filter: Json>" 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", filter as "filter: Json>" "#, Uuid::now_v7(), self.base_id, self.class_oid, self.name, self.display_type as LensDisplayType ) .fetch_one(&mut *app_db.conn) .await } } #[derive(Builder, Clone, Debug)] pub struct LensUpdate { id: Uuid, #[builder(setter(strip_option = true))] filter: Option>, } impl LensUpdate { pub async fn execute(self, app_db: &mut AppDbClient) -> Result<(), sqlx::Error> { if let Some(filter) = self.filter { query!( "update lenses set filter = $1 where id = $2", Json(filter) as Json>, self.id ) .execute(&mut *app_db.conn) .await?; } Ok(()) } }