rust_query/
value.rs

1pub mod aggregate;
2mod operations;
3pub mod optional;
4pub mod trivial;
5
6use std::{fmt::Debug, marker::PhantomData, ops::Deref, rc::Rc};
7
8use ref_cast::RefCast;
9use sea_query::{Alias, Nullable, SelectStatement, SimpleExpr};
10
11use crate::{
12    IntoSelect, Select, Table,
13    alias::{Field, MyAlias, RawAlias, Scope},
14    ast::{MySelect, Source},
15    db::{Join, TableRow, TableRowInner},
16    hash,
17    mymap::MyMap,
18};
19
20#[derive(Default)]
21pub struct ValueBuilder {
22    pub(crate) from: Rc<MySelect>,
23    // only used for tables
24    pub(super) scope: Scope,
25    // implicit joins
26    pub(super) extra: MyMap<Source, MyAlias>,
27    // calculating these results
28    pub(super) forwarded: MyMap<MyTableRef, (&'static str, DynTypedExpr, MyAlias)>,
29}
30
31impl ValueBuilder {
32    pub(crate) fn get_aggr(
33        &mut self,
34        aggr: Rc<SelectStatement>,
35        conds: Vec<SimpleExpr>,
36    ) -> MyAlias {
37        let source = Source {
38            kind: crate::ast::SourceKind::Aggregate(aggr),
39            conds: conds
40                .into_iter()
41                .enumerate()
42                .map(|(idx, expr)| (Field::U64(MyAlias::new(idx)), expr))
43                .collect(),
44        };
45        let new_alias = || self.scope.new_alias();
46        *self.extra.get_or_init(source, new_alias)
47    }
48
49    pub(crate) fn get_join<T: Table>(&mut self, expr: SimpleExpr) -> MyAlias {
50        let source = Source {
51            kind: crate::ast::SourceKind::Implicit(T::NAME.to_owned()),
52            conds: vec![(Field::Str(T::ID), expr)],
53        };
54        let new_alias = || self.scope.new_alias();
55        *self.extra.get_or_init(source, new_alias)
56    }
57
58    pub fn get_unique<T: Table>(&mut self, conds: Box<[(&'static str, SimpleExpr)]>) -> SimpleExpr {
59        let source = Source {
60            kind: crate::ast::SourceKind::Implicit(T::NAME.to_owned()),
61            conds: conds.into_iter().map(|x| (Field::Str(x.0), x.1)).collect(),
62        };
63
64        let new_alias = || self.scope.new_alias();
65        let table = self.extra.get_or_init(source, new_alias);
66        sea_query::Expr::col((*table, Alias::new(T::ID))).into()
67    }
68
69    pub fn get_table<T: Table>(&mut self, table: MyTableRef) -> MyAlias {
70        if Rc::ptr_eq(&self.from.scope_rc, &table.scope_rc) {
71            MyAlias::new(table.idx)
72        } else {
73            self.forwarded
74                .get_or_init(table.clone(), || {
75                    (
76                        T::NAME,
77                        DynTyped::new(Join::<T>::new(table)).erase(),
78                        self.scope.new_alias(),
79                    )
80                })
81                .2
82        }
83    }
84}
85
86#[derive(Clone)]
87pub struct MyTableRef {
88    pub(crate) scope_rc: Rc<()>,
89    pub(crate) idx: usize,
90}
91
92impl PartialEq for MyTableRef {
93    fn eq(&self, other: &Self) -> bool {
94        Rc::ptr_eq(&self.scope_rc, &other.scope_rc) && self.idx == other.idx
95    }
96}
97
98pub trait NumTyp: MyTyp + Clone + Copy {
99    const ZERO: Self;
100    fn into_sea_value(self) -> sea_query::Value;
101}
102
103impl NumTyp for i64 {
104    const ZERO: Self = 0;
105    fn into_sea_value(self) -> sea_query::Value {
106        sea_query::Value::BigInt(Some(self))
107    }
108}
109impl NumTyp for f64 {
110    const ZERO: Self = 0.;
111    fn into_sea_value(self) -> sea_query::Value {
112        sea_query::Value::Double(Some(self))
113    }
114}
115
116#[diagnostic::on_unimplemented(
117    message = "Columns with type `{Self}` can not be checked for equality",
118    note = "`EqTyp` is also implemented for all table types"
119)]
120pub trait EqTyp: MyTyp {}
121
122impl EqTyp for String {}
123impl EqTyp for Vec<u8> {}
124impl EqTyp for i64 {}
125impl EqTyp for f64 {}
126impl EqTyp for bool {}
127#[diagnostic::do_not_recommend]
128impl<T: Table> EqTyp for T {}
129
130/// Typ does not depend on scope, so it gets its own trait
131pub trait Typed {
132    type Typ;
133
134    #[doc(hidden)]
135    fn build_expr(&self, b: &mut ValueBuilder) -> SimpleExpr;
136    #[doc(hidden)]
137    fn build_table(&self, b: &mut ValueBuilder) -> MyAlias
138    where
139        Self::Typ: Table,
140    {
141        let expr = self.build_expr(b);
142        b.get_join::<Self::Typ>(expr)
143    }
144}
145
146/// Trait for all values that can be used as expressions in queries.
147pub trait IntoExpr<'column, S>: Clone {
148    /// The type of the expression.
149    type Typ: MyTyp;
150
151    /// Turn this value into an [Expr].
152    fn into_expr(self) -> Expr<'column, S, Self::Typ>;
153}
154
155impl<T: Typed<Typ = X>, X: MyTyp<Sql: Nullable>> Typed for Option<T> {
156    type Typ = Option<T::Typ>;
157
158    fn build_expr(&self, b: &mut ValueBuilder) -> SimpleExpr {
159        self.as_ref()
160            .map(|x| T::build_expr(x, b))
161            .unwrap_or(X::Sql::null().into())
162    }
163}
164
165impl<'column, S, T: IntoExpr<'column, S, Typ = X>, X: MyTyp<Sql: Nullable>> IntoExpr<'column, S>
166    for Option<T>
167{
168    type Typ = Option<X>;
169    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
170        Expr::new(self.map(|x| x.into_expr().inner))
171    }
172}
173
174impl Typed for String {
175    type Typ = String;
176    fn build_expr(&self, _: &mut ValueBuilder) -> SimpleExpr {
177        SimpleExpr::from(self)
178    }
179}
180
181impl<'column, S> IntoExpr<'column, S> for String {
182    type Typ = String;
183    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
184        Expr::new(self)
185    }
186}
187
188impl<'column, S> IntoExpr<'column, S> for &str {
189    type Typ = String;
190    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
191        Expr::new(self.to_owned())
192    }
193}
194
195impl Typed for Vec<u8> {
196    type Typ = Vec<u8>;
197    fn build_expr(&self, _: &mut ValueBuilder) -> SimpleExpr {
198        SimpleExpr::from(self.to_owned())
199    }
200}
201
202impl<'column, S> IntoExpr<'column, S> for Vec<u8> {
203    type Typ = Vec<u8>;
204    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
205        Expr::new(self)
206    }
207}
208
209impl<'column, S> IntoExpr<'column, S> for &[u8] {
210    type Typ = Vec<u8>;
211    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
212        Expr::new(self.to_owned())
213    }
214}
215
216impl Typed for bool {
217    type Typ = bool;
218    fn build_expr(&self, _: &mut ValueBuilder) -> SimpleExpr {
219        SimpleExpr::from(*self)
220    }
221}
222
223impl<'column, S> IntoExpr<'column, S> for bool {
224    type Typ = bool;
225    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
226        Expr::new(self)
227    }
228}
229
230impl Typed for i64 {
231    type Typ = i64;
232    fn build_expr(&self, _: &mut ValueBuilder) -> SimpleExpr {
233        SimpleExpr::from(*self)
234    }
235}
236
237impl<'column, S> IntoExpr<'column, S> for i64 {
238    type Typ = i64;
239    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
240        Expr::new(self)
241    }
242}
243
244impl Typed for f64 {
245    type Typ = f64;
246    fn build_expr(&self, _: &mut ValueBuilder) -> SimpleExpr {
247        SimpleExpr::from(*self)
248    }
249}
250
251impl<'column, S> IntoExpr<'column, S> for f64 {
252    type Typ = f64;
253    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
254        Expr::new(self)
255    }
256}
257
258impl<T> Typed for &T
259where
260    T: Typed,
261{
262    type Typ = T::Typ;
263    fn build_expr(&self, b: &mut ValueBuilder) -> SimpleExpr {
264        T::build_expr(self, b)
265    }
266    fn build_table(&self, b: &mut ValueBuilder) -> MyAlias
267    where
268        Self::Typ: Table,
269    {
270        T::build_table(self, b)
271    }
272}
273
274impl<'column, S, T> IntoExpr<'column, S> for &T
275where
276    T: IntoExpr<'column, S>,
277{
278    type Typ = T::Typ;
279    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
280        T::into_expr(self.clone())
281    }
282}
283
284/// Use this a value in a query to get the current datetime as a number.
285#[derive(Clone, Copy)]
286pub struct UnixEpoch;
287
288impl Typed for UnixEpoch {
289    type Typ = i64;
290    fn build_expr(&self, _: &mut ValueBuilder) -> SimpleExpr {
291        sea_query::Expr::col(RawAlias("unixepoch('now')".to_owned())).into()
292    }
293}
294
295impl<'column, S> IntoExpr<'column, S> for UnixEpoch {
296    type Typ = i64;
297    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
298        Expr::new(self)
299    }
300}
301
302pub trait MyTyp: 'static {
303    type Prev: MyTyp;
304    const NULLABLE: bool = false;
305    const TYP: hash::ColumnType;
306    const FK: Option<(&'static str, &'static str)> = None;
307    type Out<'t>: SecretFromSql<'t>;
308    type Sql;
309}
310
311pub(crate) trait SecretFromSql<'t>: Sized {
312    fn from_sql(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self>;
313}
314
315#[diagnostic::do_not_recommend]
316impl<T: Table> MyTyp for T {
317    type Prev = T::MigrateFrom;
318    const TYP: hash::ColumnType = hash::ColumnType::Integer;
319    const FK: Option<(&'static str, &'static str)> = Some((T::NAME, T::ID));
320    type Out<'t> = TableRow<'t, Self>;
321    type Sql = i64;
322}
323
324impl<'t, T> SecretFromSql<'t> for TableRow<'t, T> {
325    fn from_sql(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
326        Ok(TableRow {
327            _p: PhantomData,
328            _local: PhantomData,
329            inner: TableRowInner {
330                _p: PhantomData,
331                idx: value.as_i64()?,
332            },
333        })
334    }
335}
336
337impl MyTyp for i64 {
338    type Prev = Self;
339    const TYP: hash::ColumnType = hash::ColumnType::Integer;
340    type Out<'t> = Self;
341    type Sql = i64;
342}
343
344impl SecretFromSql<'_> for i64 {
345    fn from_sql(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
346        value.as_i64()
347    }
348}
349
350impl MyTyp for f64 {
351    type Prev = Self;
352    const TYP: hash::ColumnType = hash::ColumnType::Float;
353    type Out<'t> = Self;
354    type Sql = f64;
355}
356
357impl SecretFromSql<'_> for f64 {
358    fn from_sql(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
359        value.as_f64()
360    }
361}
362
363impl MyTyp for bool {
364    type Prev = Self;
365    const TYP: hash::ColumnType = hash::ColumnType::Integer;
366    type Out<'t> = Self;
367    type Sql = bool;
368}
369
370impl SecretFromSql<'_> for bool {
371    fn from_sql(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
372        Ok(value.as_i64()? != 0)
373    }
374}
375
376impl MyTyp for String {
377    type Prev = Self;
378    const TYP: hash::ColumnType = hash::ColumnType::String;
379    type Out<'t> = Self;
380    type Sql = String;
381}
382assert_impl_all!(String: Nullable);
383
384impl SecretFromSql<'_> for String {
385    fn from_sql(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
386        Ok(value.as_str()?.to_owned())
387    }
388}
389
390impl MyTyp for Vec<u8> {
391    type Prev = Self;
392    const TYP: hash::ColumnType = hash::ColumnType::Blob;
393    type Out<'t> = Self;
394    type Sql = Vec<u8>;
395}
396assert_impl_all!(Vec<u8>: Nullable);
397
398impl SecretFromSql<'_> for Vec<u8> {
399    fn from_sql(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
400        Ok(value.as_blob()?.to_owned())
401    }
402}
403
404impl<T: MyTyp> MyTyp for Option<T> {
405    type Prev = Option<T::Prev>;
406    const TYP: hash::ColumnType = T::TYP;
407    const NULLABLE: bool = true;
408    const FK: Option<(&'static str, &'static str)> = T::FK;
409    type Out<'t> = Option<T::Out<'t>>;
410    type Sql = T::Sql;
411}
412
413impl<'t, T: SecretFromSql<'t>> SecretFromSql<'t> for Option<T> {
414    fn from_sql(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
415        if value.data_type() == rusqlite::types::Type::Null {
416            Ok(None)
417        } else {
418            Ok(Some(T::from_sql(value)?))
419        }
420    }
421}
422
423/// This is an expression that can be used in queries.
424///
425/// - The lifetime parameter `'column` specifies which columns need to be in scope.
426/// - The type parameter `S` specifies the expected schema of the query.
427/// - And finally the type paramter `T` specifies the type of the expression.
428///
429/// [Expr] implements [Deref] to have table extension methods in case the type is a table type.
430pub struct Expr<'column, S, T> {
431    pub(crate) inner: DynTyped<T>,
432    pub(crate) _p: PhantomData<&'column ()>,
433    pub(crate) _p2: PhantomData<S>,
434}
435
436impl<S, T> Debug for Expr<'_, S, T> {
437    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
438        write!(f, "Expr of type {}", std::any::type_name::<T>())
439    }
440}
441
442impl<'column, S, T: 'static> Expr<'column, S, T> {
443    /// Extremely easy to use API. Should only be used by the macro to implement migrations.
444    #[doc(hidden)]
445    pub fn _migrate<OldS>(prev: impl IntoExpr<'column, OldS>) -> Self {
446        Self::new(MigratedExpr {
447            prev: prev.into_expr().inner.erase(),
448            _p: PhantomData,
449        })
450    }
451}
452
453pub fn adhoc_expr<S, T: 'static>(
454    f: impl 'static + Fn(&mut ValueBuilder) -> SimpleExpr,
455) -> Expr<'static, S, T> {
456    Expr::adhoc(f)
457}
458
459pub fn new_column<'x, S, C: MyTyp, T: Table>(
460    table: impl IntoExpr<'x, S, Typ = T>,
461    name: &'static str,
462) -> Expr<'x, S, C> {
463    let table = table.into_expr().inner;
464    Expr::adhoc(move |b| sea_query::Expr::col((table.build_table(b), Field::Str(name))).into())
465}
466
467pub fn assume_expr<S, T: 'static>(e: Expr<S, Option<T>>) -> Expr<S, T> {
468    let inner = e.inner;
469    Expr::adhoc(move |b| inner.build_expr(b))
470}
471
472pub fn new_dummy<'x, S, T: MyTyp>(
473    val: impl Typed<Typ = T> + 'static,
474) -> Select<'x, 'x, S, T::Out<'x>> {
475    IntoSelect::into_select(Expr::new(val))
476}
477
478pub fn into_owned<'x, S, T>(val: impl IntoExpr<'x, S, Typ = T>) -> DynTyped<T> {
479    val.into_expr().inner
480}
481
482struct AdHoc<F, T>(F, PhantomData<T>);
483impl<F: Fn(&mut ValueBuilder) -> SimpleExpr, T> Typed for AdHoc<F, T> {
484    type Typ = T;
485
486    fn build_expr(&self, b: &mut ValueBuilder) -> SimpleExpr {
487        (self.0)(b)
488    }
489}
490
491impl<S, T: 'static> Expr<'_, S, T> {
492    pub(crate) fn adhoc(f: impl 'static + Fn(&mut ValueBuilder) -> SimpleExpr) -> Self {
493        Self::new(AdHoc(f, PhantomData))
494    }
495
496    pub(crate) fn new(val: impl Typed<Typ = T> + 'static) -> Self {
497        Self {
498            inner: DynTyped(Rc::new(val)),
499            _p: PhantomData,
500            _p2: PhantomData,
501        }
502    }
503}
504
505impl<S, T> Clone for Expr<'_, S, T> {
506    fn clone(&self) -> Self {
507        Self {
508            inner: self.inner.clone(),
509            _p: self._p,
510            _p2: self._p2,
511        }
512    }
513}
514
515#[derive(Clone)]
516pub struct DynTypedExpr(pub(crate) Rc<dyn Fn(&mut ValueBuilder) -> SimpleExpr>);
517
518impl DynTypedExpr {
519    pub fn new(f: impl 'static + Fn(&mut ValueBuilder) -> SimpleExpr) -> Self {
520        Self(Rc::new(f))
521    }
522}
523
524impl<Typ: 'static> DynTyped<Typ> {
525    pub fn erase(self) -> DynTypedExpr {
526        DynTypedExpr(Rc::new(move |b| self.build_expr(b)))
527    }
528}
529
530pub struct MigratedExpr<Typ> {
531    prev: DynTypedExpr,
532    _p: PhantomData<Typ>,
533}
534
535impl<Typ> Typed for MigratedExpr<Typ> {
536    type Typ = Typ;
537    fn build_expr(&self, b: &mut ValueBuilder) -> SimpleExpr {
538        self.prev.0(b)
539    }
540}
541
542pub struct DynTyped<Typ>(pub(crate) Rc<dyn Typed<Typ = Typ>>);
543
544impl<Typ> DynTyped<Typ> {
545    pub fn new(val: impl 'static + Typed<Typ = Typ>) -> Self {
546        Self(Rc::new(val))
547    }
548}
549
550impl<T> Clone for DynTyped<T> {
551    fn clone(&self) -> Self {
552        Self(self.0.clone())
553    }
554}
555
556impl<Typ: 'static> Typed for DynTyped<Typ> {
557    type Typ = Typ;
558
559    fn build_expr(&self, b: &mut ValueBuilder) -> SimpleExpr {
560        self.0.build_expr(b)
561    }
562
563    fn build_table(&self, b: &mut ValueBuilder) -> MyAlias
564    where
565        Self::Typ: Table,
566    {
567        self.0.build_table(b)
568    }
569}
570
571impl<'column, S, T: MyTyp> IntoExpr<'column, S> for Expr<'column, S, T> {
572    type Typ = T;
573    fn into_expr(self) -> Expr<'column, S, Self::Typ> {
574        self
575    }
576}
577
578impl<S, T: Table> Deref for Expr<'_, S, T> {
579    type Target = T::Ext<Self>;
580
581    fn deref(&self) -> &Self::Target {
582        RefCast::ref_cast(self)
583    }
584}