rust_query/
rows.rs

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
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 most query functionality like joining tables and doing sub-queries.
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: 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    /// For convenience there is also [Table::join].
34    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    // Join a vector of values.
55    // pub fn vec<V: IntoExpr<'inner>>(&mut self, vec: Vec<V>) -> Join<'inner, V::Typ> {
56    //     todo!()
57    // }
58
59    /// Filter rows based on a column.
60    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    /// Filter out rows where this column is [None].
70    ///
71    /// Returns a new column with the unwrapped type.
72    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}