use std::marker::PhantomData;
use crate::interfaces::Model;
use crate::queries::{
__private::HasCols, Expr, IntoExpr, ModelTable, Predicate, many_to_many_exists,
relation_aggregate, relation_exists,
};
use super::{Backref, ManyBackref, ManyToMany};
#[doc(hidden)]
pub struct BackrefRef<R>
where
R: Backref,
{
_marker: PhantomData<fn() -> R>,
}
#[doc(hidden)]
pub struct ManyToManyRef<R>
where
R: ManyToMany,
{
_marker: PhantomData<fn() -> R>,
}
impl<R> BackrefRef<R>
where
R: Backref,
R::From: HasCols,
{
pub(crate) fn new(_source: &ModelTable<R::From>) -> Self {
Self {
_marker: PhantomData,
}
}
}
impl<R> ManyToManyRef<R>
where
R: ManyToMany,
R::From: HasCols,
{
pub(crate) fn new(_source: &ModelTable<R::From>) -> Self {
Self {
_marker: PhantomData,
}
}
}
impl<R> BackrefRef<R>
where
R: ManyBackref,
R::To: HasCols,
{
pub fn exists(self) -> Predicate {
let target = R::To::table();
relation_exists(R::meta(), target.table_source(), None, false)
}
pub fn any<F>(self, f: F) -> Predicate
where
F: FnOnce(&ModelTable<R::To>) -> Predicate,
{
let target = R::To::table();
relation_exists(R::meta(), target.table_source(), Some(f(&target)), false)
}
pub fn none(self) -> Predicate {
let target = R::To::table();
relation_exists(R::meta(), target.table_source(), None, true)
}
pub fn count(self) -> Expr<i64> {
let target = R::To::table();
relation_aggregate("COUNT", R::meta(), target.table_source(), None::<Expr<i64>>)
}
pub fn sum<T, F, E>(self, f: F) -> Expr<T>
where
F: FnOnce(&ModelTable<R::To>) -> E,
E: IntoExpr<T>,
T: 'static,
{
self.aggregate("SUM", Some(f))
}
pub fn avg<T, F, E>(self, f: F) -> Expr<f64>
where
F: FnOnce(&ModelTable<R::To>) -> E,
E: IntoExpr<T>,
T: 'static,
{
let target = R::To::table();
relation_aggregate(
"AVG",
R::meta(),
target.table_source(),
Some(f(&target).into_expr()),
)
}
pub fn min<T, F, E>(self, f: F) -> Expr<T>
where
F: FnOnce(&ModelTable<R::To>) -> E,
E: IntoExpr<T>,
T: 'static,
{
self.aggregate("MIN", Some(f))
}
pub fn max<T, F, E>(self, f: F) -> Expr<T>
where
F: FnOnce(&ModelTable<R::To>) -> E,
E: IntoExpr<T>,
T: 'static,
{
self.aggregate("MAX", Some(f))
}
fn aggregate<T, F, E>(self, function: &'static str, f: Option<F>) -> Expr<T>
where
F: FnOnce(&ModelTable<R::To>) -> E,
E: IntoExpr<T>,
T: 'static,
{
let target = R::To::table();
let expr = f.map(|f| f(&target).into_expr());
relation_aggregate(function, R::meta(), target.table_source(), expr)
}
}
impl<R> ManyToManyRef<R>
where
R: ManyToMany,
R::Through: HasCols,
R::To: HasCols,
{
pub fn any<F>(self, f: F) -> Predicate
where
F: FnOnce(&ModelTable<R::To>) -> Predicate,
{
let target = R::To::table();
let through = R::Through::table();
many_to_many_exists(
R::from_through(),
R::through_to(),
through.table_source(),
target.table_source(),
Some(f(&target)),
false,
)
}
pub fn none(self) -> Predicate {
let target = R::To::table();
let through = R::Through::table();
many_to_many_exists(
R::from_through(),
R::through_to(),
through.table_source(),
target.table_source(),
None,
true,
)
}
}