// SPDX-FileCopyrightText: 2024 Simon Bruder // // SPDX-License-Identifier: AGPL-3.0-or-later use std::collections::HashMap; use sqlx::{query, query_as, query_scalar, PgPool}; use uuid::Uuid; use crate::models::{Item, NewItem}; pub async fn add(pool: &PgPool, new_item: NewItem) -> Result { query_as!( Item, "INSERT INTO items (name, parent, class) VALUES ($1, $2, $3) RETURNING *", new_item.name, new_item.parent, new_item.class ) .fetch_one(pool) .await } pub async fn get(pool: &PgPool, id: Uuid) -> Result { query_as!(Item, "SELECT * FROM items WHERE id = $1", id) .fetch_one(pool) .await } pub async fn get_by_short_id(pool: &PgPool, short_id: i32) -> Result { query_as!(Item, "SELECT * FROM items WHERE short_id = $1", short_id) .fetch_one(pool) .await } pub async fn get_all(pool: &PgPool) -> Result, sqlx::Error> { query_as!(Item, "SELECT * FROM items ORDER BY created_at") .fetch_all(pool) .await } pub async fn get_multiple(pool: &PgPool, ids: &[Uuid]) -> Result, sqlx::Error> { query_as!(Item, "SELECT * FROM items WHERE id = ANY ($1)", ids) .fetch_all(pool) .await } pub async fn get_all_as_map(pool: &PgPool) -> Result, sqlx::Error> { Ok(get_all(pool) .await? .into_iter() .map(|i| (i.id, i)) .collect()) } pub async fn update(pool: &PgPool, id: Uuid, modified_item: NewItem) -> Result { query_as!( Item, "UPDATE items SET name = $2, parent = $3, class = $4 WHERE id = $1 RETURNING *", id, modified_item.name, modified_item.parent, modified_item.class ) .fetch_one(pool) .await } pub async fn delete(pool: &PgPool, id: Uuid) -> Result<(), sqlx::Error> { let res = query!("DELETE FROM items WHERE id = $1", id) .execute(pool) .await?; assert_eq!(res.rows_affected(), 1); Ok(()) } pub async fn get_parents(pool: &PgPool, id: Uuid) -> Result, sqlx::Error> { // force nullable is required for all columns in views query_scalar!( r#"SELECT unnest(parents) as "parents!" FROM item_tree WHERE id = $1"#, id ) .fetch_all(pool) .await } pub async fn get_all_parents(pool: &PgPool) -> Result>, sqlx::Error> { let mut parents = HashMap::new(); for row in query!(r#"SELECT id as "id!", parents as "parents!" FROM item_tree"#) .fetch_all(pool) .await? { parents.insert(row.id, row.parents); } Ok(parents) } pub async fn get_parents_details(pool: &PgPool, id: Uuid) -> Result, sqlx::Error> { query_as!( Item, "SELECT * FROM items WHERE id = ANY (SELECT unnest(parents) FROM item_tree WHERE id = $1)", id ) .fetch_all(pool) .await } pub async fn get_children(pool: &PgPool, id: Uuid) -> Result, sqlx::Error> { query_as!(Item, "SELECT * FROM items WHERE parent = $1", id) .fetch_all(pool) .await }