use std::collections::HashMap;
use std::future::Future;
use reinhardt_query::{InsertStatement, SelectStatement};
use super::annotation::Annotation;
use super::composite_pk::PkValue;
use super::connection::{DatabaseBackend, DatabaseConnection};
use super::cte::CTE;
use super::manager::Manager;
use super::model::Model;
use super::query::{Filter, FilterOperator, FilterValue, QuerySet};
pub trait CustomManager: Sized + Send + Sync {
type Model: Model;
fn new() -> Self;
fn all(&self) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().all()
}
fn filter<F: Into<String>>(
&self,
field: F,
operator: FilterOperator,
value: FilterValue,
) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().filter(field, operator, value)
}
fn filter_by(&self, filter: Filter) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().filter_by(filter)
}
fn get(&self, pk: <Self::Model as Model>::PrimaryKey) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().get(pk)
}
fn limit(&self, limit: usize) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().limit(limit)
}
fn order_by(&self, fields: &[&str]) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().order_by(fields)
}
fn annotate(&self, annotation: Annotation) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().annotate(annotation)
}
fn defer(&self, fields: &[&str]) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().defer(fields)
}
fn only(&self, fields: &[&str]) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().only(fields)
}
fn values(&self, fields: &[&str]) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().values(fields)
}
fn select_related(&self, fields: &[&str]) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().select_related(fields)
}
fn offset(&self, offset: usize) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().offset(offset)
}
fn paginate(&self, page: usize, page_size: usize) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().paginate(page, page_size)
}
fn prefetch_related(&self, fields: &[&str]) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().prefetch_related(fields)
}
fn values_list(&self, fields: &[&str]) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().values_list(fields)
}
fn filter_array_overlap(&self, field: &str, values: &[&str]) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().filter_array_overlap(field, values)
}
fn filter_array_contains(&self, field: &str, values: &[&str]) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().filter_array_contains(field, values)
}
fn filter_jsonb_contains(&self, field: &str, json: &str) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().filter_jsonb_contains(field, json)
}
fn filter_jsonb_key_exists(&self, field: &str, key: &str) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().filter_jsonb_key_exists(field, key)
}
fn filter_range_contains(&self, field: &str, value: &str) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().filter_range_contains(field, value)
}
fn filter_in_subquery<R: Model, F>(&self, field: &str, subquery_fn: F) -> QuerySet<Self::Model>
where
F: FnOnce(QuerySet<R>) -> QuerySet<R>,
{
Manager::<Self::Model>::new().filter_in_subquery(field, subquery_fn)
}
fn filter_not_in_subquery<R: Model, F>(
&self,
field: &str,
subquery_fn: F,
) -> QuerySet<Self::Model>
where
F: FnOnce(QuerySet<R>) -> QuerySet<R>,
{
Manager::<Self::Model>::new().filter_not_in_subquery(field, subquery_fn)
}
fn filter_exists<R: Model, F>(&self, subquery_fn: F) -> QuerySet<Self::Model>
where
F: FnOnce(QuerySet<R>) -> QuerySet<R>,
{
Manager::<Self::Model>::new().filter_exists(subquery_fn)
}
fn filter_not_exists<R: Model, F>(&self, subquery_fn: F) -> QuerySet<Self::Model>
where
F: FnOnce(QuerySet<R>) -> QuerySet<R>,
{
Manager::<Self::Model>::new().filter_not_exists(subquery_fn)
}
fn with_cte(&self, cte: CTE) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().with_cte(cte)
}
fn full_text_search(&self, field: &str, query: &str) -> QuerySet<Self::Model> {
Manager::<Self::Model>::new().full_text_search(field, query)
}
fn annotate_subquery<R, F>(&self, name: &str, builder: F) -> QuerySet<Self::Model>
where
R: Model + 'static,
F: FnOnce(QuerySet<R>) -> QuerySet<R>,
{
Manager::<Self::Model>::new().annotate_subquery(name, builder)
}
fn get_composite<'a>(
&'a self,
pk_values: &'a HashMap<String, PkValue>,
) -> impl Future<Output = reinhardt_core::exception::Result<Self::Model>> + Send + 'a
where
Self::Model: Clone + serde::de::DeserializeOwned,
{
async move { Manager::<Self::Model>::new().get_composite(pk_values).await }
}
fn create<'a>(
&'a self,
model: &'a Self::Model,
) -> impl Future<Output = reinhardt_core::exception::Result<Self::Model>> + Send + 'a {
async move { Manager::<Self::Model>::new().create(model).await }
}
fn create_with_conn<'a>(
&'a self,
conn: &'a DatabaseConnection,
model: &'a Self::Model,
) -> impl Future<Output = reinhardt_core::exception::Result<Self::Model>> + Send + 'a {
async move {
Manager::<Self::Model>::new()
.create_with_conn(conn, model)
.await
}
}
fn update<'a>(
&'a self,
model: &'a Self::Model,
) -> impl Future<Output = reinhardt_core::exception::Result<Self::Model>> + Send + 'a {
async move { Manager::<Self::Model>::new().update(model).await }
}
fn update_with_conn<'a>(
&'a self,
conn: &'a DatabaseConnection,
model: &'a Self::Model,
) -> impl Future<Output = reinhardt_core::exception::Result<Self::Model>> + Send + 'a {
async move {
Manager::<Self::Model>::new()
.update_with_conn(conn, model)
.await
}
}
fn delete<'a>(
&'a self,
pk: <Self::Model as Model>::PrimaryKey,
) -> impl Future<Output = reinhardt_core::exception::Result<()>> + Send + 'a {
async move { Manager::<Self::Model>::new().delete(pk).await }
}
fn delete_with_conn<'a>(
&'a self,
conn: &'a DatabaseConnection,
pk: <Self::Model as Model>::PrimaryKey,
) -> impl Future<Output = reinhardt_core::exception::Result<()>> + Send + 'a {
async move {
Manager::<Self::Model>::new()
.delete_with_conn(conn, pk)
.await
}
}
fn count<'a>(
&'a self,
) -> impl Future<Output = reinhardt_core::exception::Result<i64>> + Send + 'a {
async move { Manager::<Self::Model>::new().count().await }
}
fn count_with_conn<'a>(
&'a self,
conn: &'a DatabaseConnection,
) -> impl Future<Output = reinhardt_core::exception::Result<i64>> + Send + 'a {
async move { Manager::<Self::Model>::new().count_with_conn(conn).await }
}
fn get_or_create<'a>(
&'a self,
lookup_fields: HashMap<String, String>,
defaults: Option<HashMap<String, String>>,
) -> impl Future<Output = reinhardt_core::exception::Result<(Self::Model, bool)>> + Send + 'a {
async move {
Manager::<Self::Model>::new()
.get_or_create(lookup_fields, defaults)
.await
}
}
fn bulk_create<'a>(
&'a self,
models: Vec<Self::Model>,
batch_size: Option<usize>,
ignore_conflicts: bool,
update_conflicts: bool,
) -> impl Future<Output = reinhardt_core::exception::Result<Vec<Self::Model>>> + Send + 'a
where
Self::Model: 'a,
{
async move {
Manager::<Self::Model>::new()
.bulk_create(models, batch_size, ignore_conflicts, update_conflicts)
.await
}
}
fn bulk_update<'a>(
&'a self,
models: Vec<Self::Model>,
fields: Vec<String>,
batch_size: Option<usize>,
) -> impl Future<Output = reinhardt_core::exception::Result<usize>> + Send + 'a
where
Self::Model: 'a,
{
async move {
Manager::<Self::Model>::new()
.bulk_update(models, fields, batch_size)
.await
}
}
fn bulk_create_query(&self, models: &[Self::Model]) -> Option<InsertStatement> {
Manager::<Self::Model>::new().bulk_create_query(models)
}
fn bulk_create_sql(&self, models: &[Self::Model], backend: DatabaseBackend) -> String {
Manager::<Self::Model>::new().bulk_create_sql(models, backend)
}
fn update_queryset(
&self,
queryset: &QuerySet<Self::Model>,
updates: &[(&str, &str)],
) -> (String, Vec<String>) {
Manager::<Self::Model>::new().update_queryset(queryset, updates)
}
fn delete_queryset(&self, queryset: &QuerySet<Self::Model>) -> (String, Vec<String>) {
Manager::<Self::Model>::new().delete_queryset(queryset)
}
fn get_or_create_queries(
&self,
lookup_fields: &HashMap<String, String>,
defaults: &HashMap<String, String>,
) -> (SelectStatement, InsertStatement) {
Manager::<Self::Model>::new().get_or_create_queries(lookup_fields, defaults)
}
fn get_or_create_sql(
&self,
lookup_fields: &HashMap<String, String>,
defaults: &HashMap<String, String>,
backend: DatabaseBackend,
) -> (String, String) {
Manager::<Self::Model>::new().get_or_create_sql(lookup_fields, defaults, backend)
}
fn bulk_create_sql_detailed(
&self,
field_names: &[String],
value_rows: &[Vec<serde_json::Value>],
ignore_conflicts: bool,
) -> String {
Manager::<Self::Model>::new().bulk_create_sql_detailed(
field_names,
value_rows,
ignore_conflicts,
)
}
#[allow(clippy::type_complexity)]
fn bulk_update_sql_detailed(
&self,
updates: &[(
<Self::Model as Model>::PrimaryKey,
HashMap<String, serde_json::Value>,
)],
fields: &[String],
backend: DatabaseBackend,
) -> String
where
<Self::Model as Model>::PrimaryKey: std::fmt::Display + Clone,
{
Manager::<Self::Model>::new().bulk_update_sql_detailed(updates, fields, backend)
}
fn before_save(&self, _model: &mut Self::Model) -> reinhardt_core::exception::Result<()> {
Ok(())
}
fn before_delete(&self, _model: &Self::Model) -> reinhardt_core::exception::Result<()> {
Ok(())
}
fn before_bulk_update(
&self,
_models: &mut [Self::Model],
) -> reinhardt_core::exception::Result<()> {
Ok(())
}
}
impl<M: Model> CustomManager for Manager<M> {
type Model = M;
fn new() -> Self {
Manager::new()
}
}
pub trait HasCustomManager: Model + Sized {
type Manager: CustomManager<Model = Self> + Default;
fn custom_manager() -> Self::Manager {
Self::Manager::default()
}
}