use std::collections::HashMap;
use crate::sample_dto_structs::SearchQuery;
use sea_orm::prelude::async_trait::async_trait;
use sea_orm::EntityTrait;
use sea_orm::FromQueryResult;
use sea_orm::QueryFilter;
use sea_orm::Select;
use sea_orm::{ConnectionTrait, DbErr};
use sea_orm::{QuerySelect, QueryTrait};
use crate::pebble_query_result::PebbleQueryResult;
use crate::pebble_utils::{
add_sort_to_select, get_query_pagination_numbers, query_to_seaorm_conditions,
};
pub fn query_to_select<E, M>(
query: &SearchQuery,
field_to_column_map: &HashMap<String, (E, <E as EntityTrait>::Column)>,
select_with_conditions: Select<E>,
) -> Select<E>
where
E: EntityTrait<Model = M>,
{
let (must_conditions, any_conditions) = query_to_seaorm_conditions(query, field_to_column_map);
let mut select_with_conditions = select_with_conditions
.apply_if(
if !must_conditions.is_empty() {
Some(must_conditions.clone())
} else {
None
},
|query, condition| query.filter(condition),
)
.apply_if(
if !any_conditions.is_empty() {
Some(any_conditions.clone())
} else {
None
},
|query, condition| query.filter(condition),
);
if query.length > 0 {
select_with_conditions = select_with_conditions.limit(query.length as u64)
}
if query.offset > 0 {
select_with_conditions = select_with_conditions.offset(query.offset as u64)
}
let query_sort = query.sort.clone();
if query_sort.is_some() {
select_with_conditions = add_sort_to_select(
select_with_conditions,
query_sort.unwrap(),
field_to_column_map,
);
};
select_with_conditions
}
pub async fn use_pebble_query<C, E, M>(
initial_select: Select<E>,
query: Option<SearchQuery>,
field_to_column_map: &HashMap<String, (E, <E as EntityTrait>::Column)>,
db: &C,
) -> Result<PebbleQueryResult<E>, DbErr>
where
C: ConnectionTrait,
E: EntityTrait<Model = M>,
M: FromQueryResult + Sized + Send + Sync,
{
let query = query.unwrap_or(SearchQuery {
find_all: true,
..Default::default()
});
let select_with_conditions = query_to_select(&query, field_to_column_map, initial_select);
let query_result: Vec<<E as EntityTrait>::Model>;
if query.find_one {
let result = select_with_conditions.clone().one(db).await?;
if result.is_some() {
let result = result.unwrap();
query_result = vec![result]
} else {
query_result = vec![]
}
} else {
let result = select_with_conditions.clone().all(db).await?;
query_result = result
}
let total_items_and_pages_number =
get_query_pagination_numbers(db, &query, select_with_conditions).await?;
let pebble_query_result =
PebbleQueryResult::from(query, query_result, total_items_and_pages_number);
Ok(pebble_query_result)
}
#[async_trait]
pub trait RunQueryExt<C, E, M>
where
C: ConnectionTrait,
E: EntityTrait<Model = M>,
M: Sized + Send + Sync + FromQueryResult,
{
async fn pebble_query(
self,
query: Option<SearchQuery>,
field_to_column_map: &HashMap<String, (E, <E as EntityTrait>::Column)>,
db: &C,
) -> Result<PebbleQueryResult<E>, DbErr>;
}
#[async_trait]
impl<C, E, M> RunQueryExt<C, E, M> for Select<E>
where
C: ConnectionTrait,
E: EntityTrait<Model = M>,
M: Sized + Send + Sync + FromQueryResult,
{
async fn pebble_query(
self,
query: Option<SearchQuery>,
field_to_column_map: &HashMap<String, (E, <E as EntityTrait>::Column)>,
db: &C,
) -> Result<PebbleQueryResult<E>, DbErr> {
use_pebble_query(self, query, field_to_column_map, db).await
}
}