1use std::marker::PhantomData;
2
3use sea_query::{Iden, SimpleExpr};
4
5use crate::{
6    Expr, Table,
7    alias::TmpTable,
8    ast::MySelect,
9    db::Join,
10    value::{IntoExpr, Typed},
11};
12
13pub struct Rows<'inner, S> {
21    pub(crate) phantom: PhantomData<fn(&'inner ()) -> &'inner ()>,
23    pub(crate) _p: PhantomData<S>,
24    pub(crate) ast: MySelect,
25}
26
27impl<'inner, S> Rows<'inner, S> {
28    pub fn join<T: Table<Schema = S>>(&mut self) -> Expr<'inner, S, T> {
35        let alias = self.ast.scope.new_alias();
36        self.ast.tables.push((T::NAME.to_owned(), alias));
37        Expr::new(Join::new(alias))
38    }
39
40    pub(crate) fn join_custom<T: Table<Schema = S>>(&mut self, t: T) -> Expr<'inner, S, T> {
41        let alias = self.ast.scope.new_alias();
42        self.ast.tables.push((t.name(), alias));
43        Expr::new(Join::new(alias))
44    }
45
46    pub(crate) fn join_tmp<T: Table<Schema = S>>(&mut self, tmp: TmpTable) -> Expr<'inner, S, T> {
47        let mut tmp_string = String::new();
48        tmp.unquoted(&mut tmp_string);
49        let alias = self.ast.scope.new_alias();
50        self.ast.tables.push((tmp_string, alias));
51        Expr::new(Join::new(alias))
52    }
53
54    pub fn filter(&mut self, prop: impl IntoExpr<'inner, S, Typ = bool>) {
61        let prop = prop.into_expr().inner;
62        self.filter_private(prop.build_expr(self.ast.builder()));
63    }
64
65    fn filter_private(&mut self, prop: SimpleExpr) {
66        self.ast.filters.push(Box::new(prop));
67    }
68
69    pub fn filter_some<Typ: 'static>(
73        &mut self,
74        val: impl IntoExpr<'inner, S, Typ = Option<Typ>>,
75    ) -> Expr<'inner, S, Typ> {
76        let val = val.into_expr().inner;
77        self.filter_private(
78            sea_query::Expr::expr(val.build_expr(self.ast.builder())).is_not_null(),
79        );
80        Expr::adhoc(move |b| val.build_expr(b))
81    }
82}