1use std::{marker::PhantomData, rc::Rc};
2
3use sea_query::{Alias, ExprTrait, IntoIden};
4
5use crate::{
6 CustomJoin, Expr, IntoExpr, Table, TableRow,
7 alias::{JoinableTable, MyAlias, TmpTable},
8 ast::MySelect,
9 joinable::IntoJoinable,
10 private::Joinable,
11 value::{DbTyp, DynTypedExpr, EqTyp, MyTableRef},
12};
13
14pub struct Rows<'inner, S> {
22 pub(crate) phantom: PhantomData<fn(&'inner ()) -> &'inner ()>,
24 pub(crate) _p: PhantomData<S>,
25 pub(crate) ast: Rc<MySelect>,
26}
27
28impl<'inner, S> Rows<'inner, S> {
29 pub fn join<T: DbTyp>(
40 &mut self,
41 j: impl IntoJoinable<'inner, S, Typ = T>,
42 ) -> Expr<'inner, S, T> {
43 let joinable = j.into_joinable();
44
45 let table_idx = self.ast.tables.len();
46 Rc::make_mut(&mut self.ast)
47 .tables
48 .push(joinable.table.clone());
49 for (name, val) in joinable.conds {
50 self.filter(Expr::adhoc(move |b| {
51 sea_query::Expr::col((MyAlias::new(table_idx), name)).eq((val.func)(b))
53 }));
54 }
55
56 let table_idx = MyTableRef {
57 scope_rc: self.ast.scope_rc.clone(),
58 idx: table_idx,
59 table_name: joinable.table,
60 };
61
62 Expr::adhoc_promise(
63 move |b| {
64 sea_query::Expr::col((
65 b.get_table(table_idx.clone()),
66 Alias::new(table_idx.table_name.main_column()),
67 ))
68 },
69 false, )
71 }
72
73 #[doc(hidden)]
74 pub fn join_private<T: Table<Schema = S>>(&mut self) -> Expr<'inner, S, TableRow<T>> {
75 self.join(Joinable::table())
76 }
77
78 pub(crate) fn join_custom<T: CustomJoin<Schema = S>>(
79 &mut self,
80 t: T,
81 ) -> Expr<'inner, S, TableRow<T>> {
82 self.join(Joinable::new(t.name()))
83 }
84
85 pub(crate) fn join_tmp<T: Table<Schema = S>>(
86 &mut self,
87 tmp: TmpTable,
88 ) -> Expr<'inner, S, TableRow<T>> {
89 let tmp_string = tmp.into_iden();
90 self.join(Joinable::new(JoinableTable::Normal(tmp_string)))
91 }
92
93 pub fn filter(&mut self, prop: impl IntoExpr<'inner, S, Typ = bool>) {
95 let prop = DynTypedExpr::erase(prop);
96 Rc::make_mut(&mut self.ast).filters.push(prop);
97 }
98
99 pub fn filter_some<Typ: EqTyp>(
103 &mut self,
104 val: impl IntoExpr<'inner, S, Typ = Option<Typ>>,
105 ) -> Expr<'inner, S, Typ> {
106 let val = val.into_expr();
107 Rc::make_mut(&mut self.ast)
108 .filters
109 .push(DynTypedExpr::erase(val.is_some()));
110
111 Expr::adhoc_promise(move |b| val.inner.build_expr(b), false)
113 }
114}