Skip to main content

rust_query/value/
into_expr.rs

1use std::rc::Rc;
2
3use crate::{
4    Expr, Lazy, Table, TableRow,
5    lower::{self, ord_rc::OrdRc},
6    value::{DbTyp, EqTyp},
7};
8
9/// Trait for all values that can be used as expressions in queries.
10///
11/// There is a hierarchy of types that can be used to build queries.
12/// - [TableRow], [i64], [f64], [bool], `&[u8]`, `&str`:
13///   These are the base types for building expressions. They all
14///   implement [IntoExpr] and are [Copy]. Note that [TableRow] is special
15///   because it refers to a table row that is guaranteed to exist.
16/// - [Expr] is the type that all [IntoExpr] values can be converted into.
17///   It has a lot of methods to combine expressions into more complicated expressions.
18///   Next to those, it implements [std::ops::Deref], if the expression is a table expression.
19///   This can be used to get access to the columns of the table, which can themselves be table expressions.
20///   Note that combinators like [crate::optional] and [crate::aggregate] also have [Expr] as return type.
21///
22/// Note that while [Expr] implements [IntoExpr], you may want to use `&Expr` instead.
23/// Using a reference lets you reuse [Expr] without calling [Clone] explicitly.
24pub trait IntoExpr<'column, S> {
25    /// The type of the expression.
26    type Typ: DbTyp;
27
28    /// Turn this value into an [Expr].
29    fn into_expr(self) -> Expr<'column, S, Self::Typ>;
30}
31
32impl<'column, S, T: IntoExpr<'column, S, Typ = X>, X: EqTyp> IntoExpr<'column, S> for Option<T> {
33    type Typ = Option<X>;
34    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
35        let this = self.map(|x| x.into_expr().inner);
36
37        // TODO: check if the original expression is a parameter and then upgrade the parameter to be nullable instead
38        Expr::new(this.unwrap_or_else(|| Rc::new(lower::Expr::Constant("NULL"))))
39    }
40}
41
42impl<'column, S> IntoExpr<'column, S> for String {
43    type Typ = String;
44    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
45        Expr::adhoc(lower::Expr::Parameter(OrdRc::new(self)))
46    }
47}
48
49impl<'column, S> IntoExpr<'column, S> for &str {
50    type Typ = String;
51    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
52        self.to_owned().into_expr()
53    }
54}
55
56impl<'column, S> IntoExpr<'column, S> for Vec<u8> {
57    type Typ = Vec<u8>;
58    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
59        Expr::adhoc(lower::Expr::Parameter(OrdRc::new(self)))
60    }
61}
62
63impl<'column, S> IntoExpr<'column, S> for &[u8] {
64    type Typ = Vec<u8>;
65    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
66        self.to_owned().into_expr()
67    }
68}
69
70impl<'column, S> IntoExpr<'column, S> for bool {
71    type Typ = bool;
72    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
73        Expr::adhoc(lower::Expr::Parameter(OrdRc::new(self)))
74    }
75}
76
77impl<'column, S> IntoExpr<'column, S> for i64 {
78    type Typ = i64;
79    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
80        Expr::adhoc(lower::Expr::Parameter(OrdRc::new(self)))
81    }
82}
83impl<'column, S> IntoExpr<'column, S> for f64 {
84    type Typ = f64;
85    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
86        Expr::adhoc(lower::Expr::Parameter(OrdRc::new(self)))
87    }
88}
89
90#[cfg(feature = "jiff-02")]
91/// Note that timestamps before `0000-01-01 00:00:00` can not be used in an expression.
92/// The reason is that datetimes are represented in sqlite as strings and for negative
93/// years the sorting order is wrong.
94///
95/// The conversion is lossless, everything up to nanoseconds is preserved.
96impl<'column, S> IntoExpr<'column, S> for jiff::Timestamp {
97    type Typ = Self;
98    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
99        Expr::adhoc(lower::Expr::Parameter(OrdRc::new(self.out_to_value())))
100    }
101}
102
103#[cfg(feature = "jiff-02")]
104/// Note that dates before `0000-01-01` can not be used in an expression.
105/// The reason is that dates are represented in sqlite as strings and for negative
106/// years the sorting order is wrong.
107impl<'column, S> IntoExpr<'column, S> for jiff::civil::Date {
108    type Typ = Self;
109
110    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
111        Expr::adhoc(lower::Expr::Parameter(OrdRc::new(self.out_to_value())))
112    }
113}
114
115impl<'column, S, T> IntoExpr<'column, S> for &T
116where
117    T: IntoExpr<'column, S> + Clone,
118{
119    type Typ = T::Typ;
120    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
121        T::into_expr(self.clone())
122    }
123}
124
125impl<'column, T: Table> IntoExpr<'column, T::Schema> for TableRow<T> {
126    type Typ = Self;
127    fn into_expr(self) -> Expr<'static, T::Schema, Self::Typ> {
128        let idx = self.inner.idx;
129
130        Expr::adhoc(lower::Expr::Parameter(OrdRc::new(idx)))
131    }
132}
133
134impl<'column, T: Table> IntoExpr<'column, T::Schema> for Lazy<'_, T> {
135    type Typ = TableRow<T>;
136
137    fn into_expr(self) -> crate::Expr<'column, T::Schema, Self::Typ> {
138        self.id.into_expr()
139    }
140}
141
142impl<'column, S, T: DbTyp> IntoExpr<'column, S> for Expr<'column, S, T> {
143    type Typ = T;
144    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
145        self
146    }
147}