Skip to main content

rust_query/value/
from_expr.rs

1use crate::{IntoExpr, IntoSelect, Table, TableRow, optional, select::Select, value::EqTyp};
2
3/// Trait for values that can be retrieved from the database using one expression.
4///
5/// This is most likely the trait that you want to implement for your custom datatype.
6/// Together with the [crate::IntoExpr] trait.
7///
8/// Note that this trait can also be implemented using the [derive@rust_query::FromExpr] derive macro.
9pub trait FromExpr<S, From>: 'static + Sized {
10    /// How to turn the expression into a [Select].
11    fn from_expr<'columns>(
12        col: impl IntoExpr<'columns, S, Typ = From>,
13    ) -> Select<'columns, S, Self>;
14}
15
16macro_rules! from_expr {
17    ($typ:ty) => {
18        impl<S> FromExpr<S, $typ> for $typ {
19            fn from_expr<'columns>(
20                col: impl IntoExpr<'columns, S, Typ = $typ>,
21            ) -> Select<'columns, S, Self> {
22                col.into_expr().into_select()
23            }
24        }
25    };
26}
27
28from_expr! {String}
29from_expr! {Vec<u8>}
30from_expr! {i64}
31from_expr! {f64}
32from_expr! {bool}
33#[cfg(feature = "jiff-02")]
34from_expr! {jiff::Timestamp}
35#[cfg(feature = "jiff-02")]
36from_expr! {jiff::civil::Date}
37
38impl<T: Table> FromExpr<T::Schema, TableRow<T>> for TableRow<T> {
39    fn from_expr<'columns>(
40        col: impl IntoExpr<'columns, T::Schema, Typ = TableRow<T>>,
41    ) -> Select<'columns, T::Schema, Self> {
42        col.into_expr().into_select()
43    }
44}
45
46impl<S, T, From: EqTyp> FromExpr<S, Option<From>> for Option<T>
47where
48    T: FromExpr<S, From>,
49{
50    fn from_expr<'columns>(
51        col: impl IntoExpr<'columns, S, Typ = Option<From>>,
52    ) -> Select<'columns, S, Self> {
53        let col = col.into_expr();
54        optional(|row| {
55            let col = row.and(col);
56            row.then_select(T::from_expr(col))
57        })
58    }
59}
60
61impl<S, From> FromExpr<S, From> for () {
62    fn from_expr<'columns>(
63        _col: impl IntoExpr<'columns, S, Typ = From>,
64    ) -> Select<'columns, S, Self> {
65        ().into_select()
66    }
67}