rust_query/
writable.rs

1use std::marker::PhantomData;
2
3use ref_cast::{RefCastCustom, ref_cast_custom};
4
5use crate::{
6    Expr, IntoExpr, Table,
7    alias::Field,
8    ast::MySelect,
9    value::{DynTypedExpr, NumTyp},
10};
11
12/// Defines a column update.
13pub struct Update<'t, S, Typ> {
14    inner: Box<dyn 't + Fn(Expr<'t, S, Typ>) -> Expr<'t, S, Typ>>,
15}
16
17impl<'t, S, Typ> Default for Update<'t, S, Typ> {
18    fn default() -> Self {
19        Self {
20            inner: Box::new(|x| x),
21        }
22    }
23}
24
25impl<'t, S: 't, Typ: 't> Update<'t, S, Typ> {
26    /// Set the new value of the column.
27    pub fn set(val: impl IntoExpr<'t, S, Typ = Typ>) -> Self {
28        let val = val.into_expr();
29        Self {
30            inner: Box::new(move |_| val.clone()),
31        }
32    }
33
34    #[doc(hidden)]
35    pub fn apply(&self, val: impl IntoExpr<'t, S, Typ = Typ>) -> Expr<'t, S, Typ> {
36        (self.inner)(val.into_expr())
37    }
38}
39
40impl<'t, S: 't, Typ: NumTyp> Update<'t, S, Typ> {
41    /// Update the column value to the old value plus some new value.
42    pub fn add(val: impl IntoExpr<'t, S, Typ = Typ>) -> Self {
43        let val = val.into_expr();
44        Self {
45            inner: Box::new(move |old| old.add(&val)),
46        }
47    }
48}
49
50/// this trait has to be implemented by the `schema` macro.
51pub trait TableInsert<'t> {
52    type T: Table;
53    fn into_insert(self) -> <Self::T as Table>::Insert<'t>;
54}
55
56#[derive(RefCastCustom)]
57#[repr(transparent)]
58pub struct Reader<'t, S> {
59    pub(crate) ast: MySelect,
60    pub(crate) _p: PhantomData<S>,
61    pub(crate) _p2: PhantomData<fn(&'t ()) -> &'t ()>,
62}
63
64impl<'t, S> Reader<'t, S> {
65    #[ref_cast_custom]
66    pub(crate) fn new(select: &MySelect) -> &Self;
67}
68
69impl<'t, S> Reader<'t, S> {
70    pub fn col(&self, name: &'static str, val: impl IntoExpr<'t, S>) {
71        self.col_erased(name, val.into_expr().inner.erase());
72    }
73
74    pub(crate) fn col_erased(&self, name: &'static str, val: DynTypedExpr) {
75        let field = Field::Str(name);
76        let expr = (val.0)(self.ast.builder());
77        self.ast.select.push(Box::new((expr, field)))
78    }
79}