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 pub(super) scope: Scope,
25 pub(super) extra: MyMap<Source, MyAlias>,
27 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
130pub 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
146pub trait IntoExpr<'column, S>: Clone {
148 type Typ: MyTyp;
150
151 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#[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
423pub 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 #[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}