use quokka::{
helper::database::{
execute, query_all, query_one, query_optional, BaseRepository, PaginationOrder,
},
state::{Database, FromState},
};
#[derive(Clone, sqlx::FromRow, serde::Deserialize, serde::Serialize)]
pub struct Group {
pub id: i32,
pub name: String,
pub created_at: time::OffsetDateTime,
pub updated_at: time::OffsetDateTime,
}
#[derive(Clone, sqlx::FromRow, serde::Deserialize, serde::Serialize)]
pub struct UserGroup {
pub user_id: i32,
pub group_id: i32,
pub created_at: time::OffsetDateTime,
pub updated_at: time::OffsetDateTime,
}
#[derive(Clone, FromState)]
pub struct GroupRepository {
database: Database,
}
#[derive(Clone, FromState)]
pub struct UserGroupRepository {
database: Database,
}
impl GroupRepository {
#[query_optional(query = "SELECT * FROM \"group\" WHERE name = {name}")]
pub async fn get_group_by_name(&self, name: &str) -> quokka::Result<Option<Group>>;
}
impl BaseRepository for GroupRepository {
type Entity = Group;
type PkType = i32;
#[query_all(
query = "SELECT * FROM \"group\" ORDER BY {#order_by} {#direction.to_string()} LIMIT {#page_size} OFFSET {#page_size * page}"
)]
async fn get_entities(
&self,
page: i32,
page_size: i32,
order_by: &'static str,
direction: PaginationOrder,
) -> quokka::Result<Vec<Self::Entity>>;
#[query_one(query = "SELECT * FROM \"group\" WHERE id = {pk}")]
fn get_entity(&self, pk: Self::PkType) -> quokka::Result<Self::Entity>;
#[execute(
query = "UPDATE \"group\" SET name = {entity.name}, updated_at = NOW() WHERE id = {entity.id}",
write
)]
fn update_entity(&self, entity: Self::Entity) -> quokka::Result<u64>;
#[query_one(
query = "INSERT INTO \"group\" (id, name) VALUES ({entity.id}, {entity.name}) RETURNING *",
write
)]
fn create_entity(&self, entity: Self::Entity) -> quokka::Result<Self::Entity>;
#[execute(query = "DELETE FROM \"group\" WHERE id = {pk}", write)]
fn delete_entity(&self, pk: Self::PkType) -> quokka::Result<u64>;
}
impl GroupRepository {
#[query_all(query = r#"SELECT "group".*
FROM "group"
INNER JOIN "user_group" gu
ON "group".id = gu.group_id
INNER JOIN "user"
ON "user".id = gu.user_id
WHERE
"user".username = {username}"#)]
pub async fn get_group_of_user(&self, username: &str) -> quokka::Result<Vec<Group>>;
}
impl BaseRepository for UserGroupRepository {
type Entity = UserGroup;
type PkType = (i32, i32);
#[query_all(
query = "SELECT * FROM \"user_group\" ORDER BY {#order_by} {#direction.to_string()} LIMIT {#page_size} OFFSET {#page_size * page}"
)]
async fn get_entities(
&self,
page: i32,
page_size: i32,
order_by: &'static str,
direction: PaginationOrder,
) -> quokka::Result<Vec<Self::Entity>>;
#[query_one(
query = "SELECT * FROM \"user_group\" WHERE user_id = {pk.0} AND group_id = {pk.1}"
)]
fn get_entity(&self, pk: Self::PkType) -> quokka::Result<Self::Entity>;
#[execute(
query = "UPDATE \"user_group\" SET updated_at = NOW() WHERE user_id = {entity.user_id} AND group_id = {entity.group_id}",
write
)]
fn update_entity(&self, entity: Self::Entity) -> quokka::Result<u64>;
#[query_one(
query = "INSERT INTO \"user_group\" (user_id, group_id) VALUES ({entity.user_id}, {entity.group_id}) RETURNING *",
write
)]
fn create_entity(&self, entity: Self::Entity) -> quokka::Result<Self::Entity>;
#[execute(
query = "DELETE FROM \"user_group\" WHERE user_id = {pk.0} AND group_id = {pk.1}",
write
)]
fn delete_entity(&self, pk: Self::PkType) -> quokka::Result<u64>;
}