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