rust_query/
rows.rs

1use std::marker::PhantomData;
2
3use sea_query::{Expr, SimpleExpr};
4
5use crate::{
6    ast::MySelect,
7    db::Join,
8    value::{operations::Assume, IntoColumn},
9    Column, Table,
10};
11
12/// [Rows] keeps track of all rows in the current query.
13///
14/// This is the base type for other query types like [crate::args::Aggregate] and [crate::args::Query].
15/// It contains most query functionality like joining tables and doing sub-queries.
16///
17/// [Rows] mutability is only about which rows are included.
18/// Adding new columns does not require mutating [Rows].
19pub struct Rows<'inner, S> {
20    // we might store 'inner
21    pub(crate) phantom: PhantomData<fn(&'inner S) -> &'inner S>,
22    pub(crate) ast: MySelect,
23}
24
25impl<'inner, S> Rows<'inner, S> {
26    /// Join a table, this is like a super simple [Iterator::flat_map] but for queries.
27    ///
28    /// After this operation [Rows] has rows for the combinations of each original row with each row of the table.
29    /// (Also called the "Carthesian product")
30    ///
31    /// For convenience there is also [Table::join].
32    pub fn join<T: Table<Schema = S>>(&mut self) -> Column<'inner, S, T> {
33        let alias = self.ast.scope.new_alias();
34        self.ast.tables.push((T::NAME.to_owned(), alias));
35        IntoColumn::into_column(Join::new(alias))
36    }
37
38    pub(crate) fn join_custom<T: Table>(&mut self, t: T) -> Join<'inner, T> {
39        let alias = self.ast.scope.new_alias();
40        self.ast.tables.push((t.name(), alias));
41        Join::new(alias)
42    }
43
44    // Join a vector of values.
45    // pub fn vec<V: Column<'inner>>(&mut self, vec: Vec<V>) -> Join<'inner, V::Typ> {
46    //     todo!()
47    // }
48
49    /// Filter rows based on a column.
50    pub fn filter(&mut self, prop: impl IntoColumn<'inner, S, Typ = bool>) {
51        self.filter_private(prop.build_expr(self.ast.builder()));
52    }
53
54    fn filter_private(&mut self, prop: SimpleExpr) {
55        self.ast.filters.push(Box::new(prop));
56    }
57
58    /// Filter out rows where this column is [None].
59    ///
60    /// Returns a new column with the unwrapped type.
61    pub fn filter_some<Typ>(
62        &mut self,
63        val: impl IntoColumn<'inner, S, Typ = Option<Typ>>,
64    ) -> Column<'inner, S, Typ> {
65        self.filter_private(Expr::expr(val.build_expr(self.ast.builder())).is_not_null());
66        Assume(val).into_column()
67    }
68}