use crate::connections::Row;
use crate::errors::WeldsError;
use crate::model_traits::{HasSchema, TableColumns, TableInfo, UniqueIdentifier};
use crate::query::builder::QueryBuilder;
use crate::query::clause::{AsFieldName, ClauseAdder};
use crate::relations::{HasRelations, Relationship};
mod exec;
pub(crate) mod related_query;
use related_query::{IncludeQuery, RelatedQuery};
#[cfg(test)]
mod tests;
pub struct IncludeBuilder<T> {
qb: QueryBuilder<T>,
related: Vec<Box<dyn RelatedQuery<T> + Sync + Send>>,
}
impl<T> IncludeBuilder<T>
where
T: Send + HasSchema,
{
pub fn new(qb: QueryBuilder<T>) -> Self {
Self {
qb,
related: Vec::default(),
}
}
pub fn include<R, Ship>(
mut self,
relationship: impl Fn(<T as HasRelations>::Relation) -> Ship,
) -> IncludeBuilder<T>
where
T: 'static + HasRelations,
Ship: 'static + Sync + Relationship<T, R>,
R: HasSchema,
R: 'static,
R: Send + Sync + HasSchema,
<R as HasSchema>::Schema: TableInfo + TableColumns + UniqueIdentifier,
<T as HasSchema>::Schema: TableInfo + TableColumns + UniqueIdentifier,
<T as HasRelations>::Relation: Default,
R: TryFrom<Row>,
WeldsError: From<<R as TryFrom<Row>>::Error>,
{
let ship = relationship(Default::default());
let out_col = ship.their_key();
let inner_tn = <T as HasSchema>::Schema::identifier();
let inner_col = ship.my_key();
let include_query: IncludeQuery<T, R, Ship> = IncludeQuery::<T, R, Ship> {
_t: Default::default(),
row_type: Default::default(),
out_col,
inner_tn,
inner_col,
ship: ship.clone(),
qb: QueryBuilder::new(),
};
self.related.push(Box::new(include_query));
self
}
pub fn include_where<R, Ship>(
mut self,
relationship: impl Fn(<T as HasRelations>::Relation) -> Ship,
qb: QueryBuilder<R>,
) -> IncludeBuilder<T>
where
T: 'static + HasRelations,
Ship: 'static + Sync + Relationship<T, R>,
R: HasSchema,
R: 'static,
R: Send + Sync + HasSchema,
<R as HasSchema>::Schema: TableInfo + TableColumns + UniqueIdentifier,
<T as HasSchema>::Schema: TableInfo + TableColumns + UniqueIdentifier,
<T as HasRelations>::Relation: Default,
R: TryFrom<Row>,
WeldsError: From<<R as TryFrom<Row>>::Error>,
{
let ship = relationship(Default::default());
let out_col = ship.their_key();
let inner_tn = <T as HasSchema>::Schema::identifier();
let inner_col = ship.my_key();
let include_query: IncludeQuery<T, R, Ship> = IncludeQuery::<T, R, Ship> {
_t: Default::default(),
row_type: Default::default(),
out_col,
inner_tn,
inner_col,
ship: ship.clone(),
qb,
};
self.related.push(Box::new(include_query));
self
}
pub fn where_col(
mut self,
lam: impl Fn(<T as HasSchema>::Schema) -> Box<dyn ClauseAdder>,
) -> Self
where
<T as HasSchema>::Schema: Default,
{
self.qb = self.qb.where_col(lam);
self
}
pub fn limit(mut self, x: i64) -> Self {
self.qb = self.qb.limit(x);
self
}
pub fn offset(mut self, x: i64) -> Self {
self.qb = self.qb.offset(x);
self
}
pub fn order_by_desc<V, FN: AsFieldName<V>>(
mut self,
lam: impl Fn(<T as HasSchema>::Schema) -> FN,
) -> Self {
self.qb = self.qb.order_by_desc(lam);
self
}
pub fn order_by_asc<V, FN: AsFieldName<V>>(
mut self,
lam: impl Fn(<T as HasSchema>::Schema) -> FN,
) -> Self {
self.qb = self.qb.order_by_asc(lam);
self
}
}