Skip to main content

rust_query/value/
into_expr.rs

1use sea_query::Nullable;
2
3use crate::{
4    Expr, Lazy, Table, TableRow,
5    value::{DbTyp, EqTyp},
6};
7
8/// Trait for all values that can be used as expressions in queries.
9///
10/// There is a hierarchy of types that can be used to build queries.
11/// - [TableRow], [i64], [f64], [bool], `&[u8]`, `&str`:
12///   These are the base types for building expressions. They all
13///   implement [IntoExpr] and are [Copy]. Note that [TableRow] is special
14///   because it refers to a table row that is guaranteed to exist.
15/// - [Expr] is the type that all [IntoExpr] values can be converted into.
16///   It has a lot of methods to combine expressions into more complicated expressions.
17///   Next to those, it implements [std::ops::Deref], if the expression is a table expression.
18///   This can be used to get access to the columns of the table, which can themselves be table expressions.
19///   Note that combinators like [crate::optional] and [crate::aggregate] also have [Expr] as return type.
20///
21/// Note that while [Expr] implements [IntoExpr], you may want to use `&Expr` instead.
22/// Using a reference lets you reuse [Expr] without calling [Clone] explicitly.
23pub trait IntoExpr<'column, S> {
24    /// The type of the expression.
25    type Typ: DbTyp;
26
27    /// Turn this value into an [Expr].
28    fn into_expr(self) -> Expr<'column, S, Self::Typ>;
29}
30
31impl<'column, S, T: IntoExpr<'column, S, Typ = X>, X: EqTyp> IntoExpr<'column, S> for Option<T> {
32    type Typ = Option<X>;
33    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
34        let this = self.map(|x| x.into_expr().inner);
35        Expr::adhoc(move |b| {
36            this.as_ref()
37                .map(|x| (x.func)(b))
38                .unwrap_or(<X::Sql as Nullable>::null().into())
39        })
40    }
41}
42
43impl<'column, S> IntoExpr<'column, S> for String {
44    type Typ = String;
45    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
46        Expr::adhoc(move |_| sea_query::Expr::from(self.clone()))
47    }
48}
49
50impl<'column, S> IntoExpr<'column, S> for &str {
51    type Typ = String;
52    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
53        self.to_owned().into_expr()
54    }
55}
56
57impl<'column, S> IntoExpr<'column, S> for Vec<u8> {
58    type Typ = Vec<u8>;
59    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
60        Expr::adhoc(move |_| sea_query::Expr::from(self.clone()))
61    }
62}
63
64impl<'column, S> IntoExpr<'column, S> for &[u8] {
65    type Typ = Vec<u8>;
66    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
67        self.to_owned().into_expr()
68    }
69}
70
71impl<'column, S> IntoExpr<'column, S> for bool {
72    type Typ = bool;
73    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
74        Expr::adhoc(move |_| sea_query::Expr::from(self))
75    }
76}
77
78impl<'column, S> IntoExpr<'column, S> for i64 {
79    type Typ = i64;
80    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
81        Expr::adhoc(move |_| sea_query::Expr::from(self))
82    }
83}
84impl<'column, S> IntoExpr<'column, S> for f64 {
85    type Typ = f64;
86    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
87        Expr::adhoc(move |_| sea_query::Expr::from(self))
88    }
89}
90
91impl<'column, S, T> IntoExpr<'column, S> for &T
92where
93    T: IntoExpr<'column, S> + Clone,
94{
95    type Typ = T::Typ;
96    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
97        T::into_expr(self.clone())
98    }
99}
100
101impl<'column, T: Table> IntoExpr<'column, T::Schema> for TableRow<T> {
102    type Typ = Self;
103    fn into_expr(self) -> Expr<'static, T::Schema, Self::Typ> {
104        let idx = self.inner.idx;
105
106        Expr::adhoc_promise(
107            move |_| sea_query::Expr::val(idx),
108            false, // table row is proof of existence
109        )
110    }
111}
112
113impl<'column, T: Table> IntoExpr<'column, T::Schema> for Lazy<'_, T> {
114    type Typ = TableRow<T>;
115
116    fn into_expr(self) -> crate::Expr<'column, T::Schema, Self::Typ> {
117        self.id.into_expr()
118    }
119}
120
121impl<'column, S, T: DbTyp> IntoExpr<'column, S> for Expr<'column, S, T> {
122    type Typ = T;
123    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
124        self
125    }
126}