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