1use std::{marker::PhantomData, rc::Rc};
2
3use sea_query::{ExprTrait, IntoIden};
4
5use crate::{
6 CustomJoin, Expr, Table,
7 alias::{Field, JoinableTable, TmpTable},
8 ast::MySelect,
9 db::Join,
10 joinable::IntoJoinable,
11 private::Joinable,
12 value::{DynTypedExpr, IntoExpr, MyTableRef, MyTyp},
13};
14
15pub struct Rows<'inner, S> {
23 pub(crate) phantom: PhantomData<fn(&'inner ()) -> &'inner ()>,
25 pub(crate) _p: PhantomData<S>,
26 pub(crate) ast: Rc<MySelect>,
27}
28
29impl<'inner, S> Rows<'inner, S> {
30 pub fn join<T: Table>(
41 &mut self,
42 j: impl IntoJoinable<'inner, S, Typ = T>,
43 ) -> Expr<'inner, S, T> {
44 let joinable = j.into_joinable();
45 let out = self.join_inner(joinable.table);
46 for (name, val) in joinable.conds {
47 let out = out.inner.clone();
48 self.filter(Expr::adhoc(move |b| {
49 sea_query::Expr::col((out.build_table(b), Field::Str(name))).eq((val.func)(b))
50 }));
51 }
52 out
53 }
54
55 #[doc(hidden)]
56 pub fn join_private<T: Table<Schema = S>>(&mut self) -> Expr<'inner, S, T> {
57 self.join(Joinable::table())
58 }
59
60 pub(crate) fn join_custom<T: CustomJoin<Schema = S>>(&mut self, t: T) -> Expr<'inner, S, T> {
61 self.join_inner(t.name())
62 }
63
64 pub(crate) fn join_tmp<T: Table<Schema = S>>(&mut self, tmp: TmpTable) -> Expr<'inner, S, T> {
65 let tmp_string = tmp.into_iden();
66 self.join_inner(JoinableTable::Normal(tmp_string))
67 }
68
69 fn join_inner<T: Table>(&mut self, name: JoinableTable) -> Expr<'inner, S, T> {
70 let table_idx = self.ast.tables.len();
71 Rc::make_mut(&mut self.ast).tables.push(name.clone());
72 Expr::new(Join::new(MyTableRef {
73 scope_rc: self.ast.scope_rc.clone(),
74 idx: table_idx,
75 table_name: name,
76 }))
77 }
78
79 pub fn filter(&mut self, prop: impl IntoExpr<'inner, S, Typ = bool>) {
86 let prop = DynTypedExpr::erase(prop);
87 Rc::make_mut(&mut self.ast).filters.push(prop);
88 }
89
90 pub fn filter_some<Typ: MyTyp>(
94 &mut self,
95 val: impl IntoExpr<'inner, S, Typ = Option<Typ>>,
96 ) -> Expr<'inner, S, Typ> {
97 let val = val.into_expr();
98 Rc::make_mut(&mut self.ast)
99 .filters
100 .push(DynTypedExpr::erase(val.is_some()));
101
102 Expr::adhoc_promise(move |b| val.inner.build_expr(b), false)
104 }
105}