rust_query/
rows.rs

1use std::{marker::PhantomData, rc::Rc};
2
3use sea_query::IntoIden;
4
5use crate::{
6    Expr, Table,
7    alias::{JoinableTable, TmpTable},
8    ast::MySelect,
9    db::Join,
10    value::{IntoExpr, MyTableRef, MyTyp, Typed},
11};
12
13/// [Rows] keeps track of all rows in the current query.
14///
15/// This is the base type for other query types like [crate::args::Aggregate] and [crate::args::Query].
16/// It contains basic query functionality like joining tables and filters.
17///
18/// [Rows] mutability is only about which rows are included.
19/// Adding new columns does not require mutating [Rows].
20pub struct Rows<'inner, S> {
21    // we might store 'inner
22    pub(crate) phantom: PhantomData<fn(&'inner ()) -> &'inner ()>,
23    pub(crate) _p: PhantomData<S>,
24    pub(crate) ast: Rc<MySelect>,
25}
26
27impl<'inner, S> Rows<'inner, S> {
28    /// Join a table, this is like a super simple [Iterator::flat_map] but for queries.
29    ///
30    /// After this operation [Rows] has rows for the combinations of each original row with each row of the table.
31    /// (Also called the "Carthesian product")
32    ///
33    /// The expression that is returned refers to the joined table.
34    pub fn join<T: Table<Schema = S>>(&mut self, _: T) -> Expr<'inner, S, T> {
35        self.join_inner(JoinableTable::Normal(T::NAME.into()))
36    }
37
38    pub(crate) fn join_custom<T: Table<Schema = S>>(&mut self, t: T) -> Expr<'inner, S, T> {
39        self.join_inner(t.name())
40    }
41
42    pub(crate) fn join_tmp<T: Table<Schema = S>>(&mut self, tmp: TmpTable) -> Expr<'inner, S, T> {
43        let tmp_string = tmp.into_iden();
44        self.join_inner(JoinableTable::Normal(tmp_string))
45    }
46
47    fn join_inner<T: Table<Schema = S>>(&mut self, name: JoinableTable) -> Expr<'inner, S, T> {
48        let table_idx = self.ast.tables.len();
49        Rc::make_mut(&mut self.ast).tables.push(name);
50        Expr::new(Join::new(MyTableRef {
51            scope_rc: self.ast.scope_rc.clone(),
52            idx: table_idx,
53        }))
54    }
55
56    // Join a vector of values.
57    // pub fn vec<V: IntoExpr<'inner>>(&mut self, vec: Vec<V>) -> Join<'inner, V::Typ> {
58    //     todo!()
59    // }
60
61    /// Filter rows based on an expression.
62    pub fn filter(&mut self, prop: impl IntoExpr<'inner, S, Typ = bool>) {
63        let prop = prop.into_expr();
64        Rc::make_mut(&mut self.ast).filters.push(prop.inner);
65    }
66
67    /// Filter out rows where this expression is [None].
68    ///
69    /// Returns a new expression with the unwrapped type.
70    pub fn filter_some<Typ: MyTyp>(
71        &mut self,
72        val: impl IntoExpr<'inner, S, Typ = Option<Typ>>,
73    ) -> Expr<'inner, S, Typ> {
74        let val = val.into_expr();
75        Rc::make_mut(&mut self.ast)
76            .filters
77            .push(val.is_some().inner);
78
79        Expr::adhoc(move |b| val.inner.build_expr(b))
80    }
81}