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 Lazy, Select, Table, Transaction,
12 alias::{Field, MyAlias, Scope},
13 ast::{MySelect, Source},
14 db::{Join, TableRow, TableRowInner},
15 mutable::Mutable,
16 mymap::MyMap,
17 private::Joinable,
18 schema::canonical,
19};
20
21#[derive(Default)]
22pub struct ValueBuilder {
23 pub(crate) from: Rc<MySelect>,
24 pub(super) scope: Scope,
26 pub(super) extra: MyMap<Source, MyAlias>,
28 pub(super) forwarded: MyMap<MyTableRef, (&'static str, DynTypedExpr, MyAlias)>,
30}
31
32impl ValueBuilder {
33 pub(crate) fn get_aggr(
34 &mut self,
35 aggr: Rc<SelectStatement>,
36 conds: Vec<sea_query::Expr>,
37 ) -> MyAlias {
38 let source = Source {
39 kind: crate::ast::SourceKind::Aggregate(aggr),
40 conds: conds
41 .into_iter()
42 .enumerate()
43 .map(|(idx, expr)| (Field::U64(MyAlias::new(idx)), expr))
44 .collect(),
45 };
46 let new_alias = || self.scope.new_alias();
47 *self.extra.get_or_init(source, new_alias)
48 }
49
50 pub(crate) fn get_join<T: Table>(
51 &mut self,
52 expr: sea_query::Expr,
53 possible_null: bool,
54 ) -> MyAlias {
55 let join_type = if possible_null {
56 JoinType::LeftJoin
57 } else {
58 JoinType::Join
59 };
60 let source = Source {
61 kind: crate::ast::SourceKind::Implicit(T::NAME.to_owned(), join_type),
62 conds: vec![(Field::Str(T::ID), expr)],
63 };
64 let new_alias = || self.scope.new_alias();
65
66 *self.extra.get_or_init(source, new_alias)
69 }
70
71 pub fn get_unique<T: Table>(
72 &mut self,
73 conds: Box<[(&'static str, sea_query::Expr)]>,
74 ) -> sea_query::Expr {
75 let source = Source {
76 kind: crate::ast::SourceKind::Implicit(T::NAME.to_owned(), JoinType::LeftJoin),
77 conds: conds.into_iter().map(|x| (Field::Str(x.0), x.1)).collect(),
78 };
79
80 let new_alias = || self.scope.new_alias();
81 let table = self.extra.get_or_init(source, new_alias);
82 sea_query::Expr::col((*table, Alias::new(T::ID))).into()
83 }
84
85 pub fn get_table<T: Table>(&mut self, table: MyTableRef) -> MyAlias {
86 if Rc::ptr_eq(&self.from.scope_rc, &table.scope_rc) {
87 MyAlias::new(table.idx)
88 } else {
89 let join = Join::<T>::new(table.clone());
90 self.forwarded
91 .get_or_init(table, || {
92 (
93 T::NAME,
94 DynTypedExpr::new(move |b| join.build_expr(b)),
95 self.scope.new_alias(),
96 )
97 })
98 .2
99 }
100 }
101}
102
103#[derive(Clone)]
104pub struct MyTableRef {
105 pub(crate) scope_rc: Rc<()>,
106 pub(crate) idx: usize,
107}
108
109impl PartialEq for MyTableRef {
110 fn eq(&self, other: &Self) -> bool {
111 Rc::ptr_eq(&self.scope_rc, &other.scope_rc) && self.idx == other.idx
112 }
113}
114
115pub trait NumTyp: OrdTyp + Clone + Copy {
116 const ZERO: Self;
117 fn into_sea_value(self) -> sea_query::Value;
118}
119
120impl NumTyp for i64 {
121 const ZERO: Self = 0;
122 fn into_sea_value(self) -> sea_query::Value {
123 sea_query::Value::BigInt(Some(self))
124 }
125}
126impl NumTyp for f64 {
127 const ZERO: Self = 0.;
128 fn into_sea_value(self) -> sea_query::Value {
129 sea_query::Value::Double(Some(self))
130 }
131}
132
133pub trait OrdTyp: EqTyp {}
134impl OrdTyp for String {}
135impl OrdTyp for Vec<u8> {}
136impl OrdTyp for i64 {}
137impl OrdTyp for f64 {}
138impl OrdTyp for bool {}
139
140pub trait BuffTyp: MyTyp {}
141impl BuffTyp for String {}
142impl BuffTyp for Vec<u8> {}
143
144#[diagnostic::on_unimplemented(
145 message = "Columns with type `{Self}` can not be checked for equality",
146 note = "`EqTyp` is also implemented for all table types"
147)]
148pub trait EqTyp: MyTyp {}
149
150impl EqTyp for String {}
151impl EqTyp for Vec<u8> {}
152impl EqTyp for i64 {}
153impl EqTyp for f64 {}
154impl EqTyp for bool {}
155#[diagnostic::do_not_recommend]
156impl<T: Table> EqTyp for T {}
157
158pub trait Typed {
160 type Typ;
161
162 fn build_expr(&self, b: &mut ValueBuilder) -> sea_query::Expr;
163 fn maybe_optional(&self) -> bool {
164 true
165 }
166
167 fn build_table(&self, b: &mut ValueBuilder) -> MyAlias
168 where
169 Self::Typ: Table,
170 {
171 let expr = self.build_expr(b);
172 b.get_join::<Self::Typ>(expr, self.maybe_optional())
173 }
174}
175
176pub trait IntoExpr<'column, S> {
178 type Typ: MyTyp;
180
181 fn into_expr(self) -> Expr<'column, S, Self::Typ>;
183}
184
185impl<X: MyTyp<Sql: Nullable>> Typed for Option<Rc<dyn Typed<Typ = X>>> {
186 type Typ = Option<X>;
187
188 fn build_expr(&self, b: &mut ValueBuilder) -> sea_query::Expr {
189 self.as_ref()
190 .map(|x| x.build_expr(b))
191 .unwrap_or(X::Sql::null().into())
192 }
193}
194
195impl<'column, S, T: IntoExpr<'column, S, Typ = X>, X: MyTyp<Sql: Nullable>> IntoExpr<'column, S>
196 for Option<T>
197{
198 type Typ = Option<X>;
199 fn into_expr(self) -> Expr<'column, S, Self::Typ> {
200 Expr::new(self.map(|x| x.into_expr().inner))
201 }
202}
203
204impl Typed for String {
205 type Typ = String;
206 fn build_expr(&self, _: &mut ValueBuilder) -> sea_query::Expr {
207 sea_query::Expr::from(self)
208 }
209}
210
211impl<'column, S> IntoExpr<'column, S> for String {
212 type Typ = String;
213 fn into_expr(self) -> Expr<'column, S, Self::Typ> {
214 Expr::new(self)
215 }
216}
217
218impl<'column, S> IntoExpr<'column, S> for &str {
219 type Typ = String;
220 fn into_expr(self) -> Expr<'column, S, Self::Typ> {
221 Expr::new(self.to_owned())
222 }
223}
224
225impl Typed for Vec<u8> {
226 type Typ = Vec<u8>;
227 fn build_expr(&self, _: &mut ValueBuilder) -> sea_query::Expr {
228 sea_query::Expr::from(self.to_owned())
229 }
230}
231
232impl<'column, S> IntoExpr<'column, S> for Vec<u8> {
233 type Typ = Vec<u8>;
234 fn into_expr(self) -> Expr<'column, S, Self::Typ> {
235 Expr::new(self)
236 }
237}
238
239impl<'column, S> IntoExpr<'column, S> for &[u8] {
240 type Typ = Vec<u8>;
241 fn into_expr(self) -> Expr<'column, S, Self::Typ> {
242 Expr::new(self.to_owned())
243 }
244}
245
246impl Typed for bool {
247 type Typ = bool;
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 bool {
254 type Typ = bool;
255 fn into_expr(self) -> Expr<'column, S, Self::Typ> {
256 Expr::new(self)
257 }
258}
259
260impl Typed for i64 {
261 type Typ = i64;
262 fn build_expr(&self, _: &mut ValueBuilder) -> sea_query::Expr {
263 sea_query::Expr::from(*self)
264 }
265}
266
267impl<'column, S> IntoExpr<'column, S> for i64 {
268 type Typ = i64;
269 fn into_expr(self) -> Expr<'column, S, Self::Typ> {
270 Expr::new(self)
271 }
272}
273
274impl Typed for f64 {
275 type Typ = f64;
276 fn build_expr(&self, _: &mut ValueBuilder) -> sea_query::Expr {
277 sea_query::Expr::from(*self)
278 }
279}
280
281impl<'column, S> IntoExpr<'column, S> for f64 {
282 type Typ = f64;
283 fn into_expr(self) -> Expr<'column, S, Self::Typ> {
284 Expr::new(self)
285 }
286}
287
288impl<'column, S, T> IntoExpr<'column, S> for &T
289where
290 T: IntoExpr<'column, S> + Clone,
291{
292 type Typ = T::Typ;
293 fn into_expr(self) -> Expr<'column, S, Self::Typ> {
294 T::into_expr(self.clone())
295 }
296}
297
298#[derive(Clone, Copy)]
300#[deprecated = "Use `Expr::unix_epoch` instead"]
301pub struct UnixEpoch;
302
303#[expect(deprecated)]
304impl Typed for UnixEpoch {
305 type Typ = i64;
306 fn build_expr(&self, _: &mut ValueBuilder) -> sea_query::Expr {
307 sea_query::Expr::cust("unixepoch('now')").into()
308 }
309}
310
311#[expect(deprecated)]
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 OptTable: MyTyp {
320 type Schema;
321 type Select;
322 type Mutable<'t>;
323 fn select_opt_mutable(
324 val: Expr<'_, Self::Schema, Self>,
325 ) -> Select<'_, Self::Schema, Self::Select>;
326
327 fn into_mutable<'t>(val: Self::Select) -> Self::Mutable<'t>;
328}
329
330impl<T: Table> OptTable for T {
331 type Schema = T::Schema;
332 type Select = (T::Mutable, TableRow<T>);
333 type Mutable<'t> = Mutable<'t, T>;
334 fn select_opt_mutable(
335 val: Expr<'_, Self::Schema, Self>,
336 ) -> Select<'_, Self::Schema, Self::Select> {
337 T::select_mutable(val)
338 }
339
340 fn into_mutable<'t>((inner, row_id): Self::Select) -> Self::Mutable<'t> {
341 Mutable::new(inner, row_id)
342 }
343}
344
345impl<T: Table> OptTable for Option<T> {
346 type Schema = T::Schema;
347 type Select = Option<(T::Mutable, TableRow<T>)>;
348 type Mutable<'t> = Option<Mutable<'t, T>>;
349 fn select_opt_mutable(
350 val: Expr<'_, Self::Schema, Self>,
351 ) -> Select<'_, Self::Schema, Self::Select> {
352 crate::optional(|row| {
353 let val = row.and(val);
354 row.then_select(T::select_mutable(val))
355 })
356 }
357
358 fn into_mutable<'t>(val: Self::Select) -> Self::Mutable<'t> {
359 val.map(T::into_mutable)
360 }
361}
362
363pub trait MyTyp: Sized + 'static {
364 type Prev: MyTyp;
365 const NULLABLE: bool = false;
366 const TYP: canonical::ColumnType;
367 const FK: Option<(&'static str, &'static str)> = None;
368 type Out: SecretFromSql;
369 type Lazy<'t>;
370 type Ext<'t>;
371 type Sql;
372 fn out_to_lazy<'t>(val: Self::Out) -> Self::Lazy<'t>;
373}
374
375pub(crate) trait SecretFromSql: Sized {
376 fn from_sql(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self>;
377}
378
379#[diagnostic::do_not_recommend]
380impl<T: Table> MyTyp for T {
381 type Prev = T::MigrateFrom;
382 const TYP: canonical::ColumnType = canonical::ColumnType::Integer;
383 const FK: Option<(&'static str, &'static str)> = Some((T::NAME, T::ID));
384 type Out = TableRow<T>;
385 type Lazy<'t> = Lazy<'t, T>;
386 type Ext<'t> = T::Ext2<'t>;
387 type Sql = i64;
388 fn out_to_lazy<'t>(val: Self::Out) -> Self::Lazy<'t> {
389 Lazy {
390 id: val,
391 lazy: OnceCell::new(),
392 txn: Transaction::new_ref(),
393 }
394 }
395}
396
397impl<T: Table> SecretFromSql for TableRow<T> {
398 fn from_sql(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
399 Ok(TableRow {
400 _local: PhantomData,
401 inner: TableRowInner {
402 _p: PhantomData,
403 idx: value.as_i64()?,
404 },
405 })
406 }
407}
408
409impl MyTyp for i64 {
410 type Prev = Self;
411 const TYP: canonical::ColumnType = canonical::ColumnType::Integer;
412 type Out = Self;
413 type Lazy<'t> = Self;
414 type Ext<'t> = ();
415 type Sql = i64;
416 fn out_to_lazy<'t>(val: Self::Out) -> Self::Lazy<'t> {
417 val
418 }
419}
420
421impl SecretFromSql for i64 {
422 fn from_sql(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
423 value.as_i64()
424 }
425}
426
427impl MyTyp for f64 {
428 type Prev = Self;
429 const TYP: canonical::ColumnType = canonical::ColumnType::Real;
430 type Out = Self;
431 type Lazy<'t> = Self;
432 type Ext<'t> = ();
433 type Sql = f64;
434 fn out_to_lazy<'t>(val: Self::Out) -> Self::Lazy<'t> {
435 val
436 }
437}
438
439impl SecretFromSql for f64 {
440 fn from_sql(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
441 value.as_f64()
442 }
443}
444
445impl MyTyp for bool {
446 type Prev = Self;
447 const TYP: canonical::ColumnType = canonical::ColumnType::Integer;
448 type Out = Self;
449 type Lazy<'t> = Self;
450 type Ext<'t> = ();
451 type Sql = bool;
452 fn out_to_lazy<'t>(val: Self::Out) -> Self::Lazy<'t> {
453 val
454 }
455}
456
457impl SecretFromSql for bool {
458 fn from_sql(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
459 Ok(value.as_i64()? != 0)
460 }
461}
462
463impl MyTyp for String {
464 type Prev = Self;
465 const TYP: canonical::ColumnType = canonical::ColumnType::Text;
466 type Out = Self;
467 type Lazy<'t> = Self;
468 type Ext<'t> = ();
469 type Sql = String;
470 fn out_to_lazy<'t>(val: Self::Out) -> Self::Lazy<'t> {
471 val
472 }
473}
474assert_impl_all!(String: Nullable);
475
476impl SecretFromSql for String {
477 fn from_sql(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
478 Ok(value.as_str()?.to_owned())
479 }
480}
481
482impl MyTyp for Vec<u8> {
483 type Prev = Self;
484 const TYP: canonical::ColumnType = canonical::ColumnType::Blob;
485 type Out = Self;
486 type Lazy<'t> = Self;
487 type Ext<'t> = ();
488 type Sql = Vec<u8>;
489 fn out_to_lazy<'t>(val: Self::Out) -> Self::Lazy<'t> {
490 val
491 }
492}
493assert_impl_all!(Vec<u8>: Nullable);
494
495impl SecretFromSql for Vec<u8> {
496 fn from_sql(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
497 Ok(value.as_blob()?.to_owned())
498 }
499}
500
501impl<T: MyTyp> MyTyp for Option<T> {
502 type Prev = Option<T::Prev>;
503 const TYP: canonical::ColumnType = T::TYP;
504 const NULLABLE: bool = true;
505 const FK: Option<(&'static str, &'static str)> = T::FK;
506 type Out = Option<T::Out>;
507 type Lazy<'t> = Option<T::Lazy<'t>>;
508 type Ext<'t> = ();
509 type Sql = T::Sql;
510 fn out_to_lazy<'t>(val: Self::Out) -> Self::Lazy<'t> {
511 val.map(T::out_to_lazy)
512 }
513}
514
515impl<T: SecretFromSql> SecretFromSql for Option<T> {
516 fn from_sql(value: rusqlite::types::ValueRef<'_>) -> rusqlite::types::FromSqlResult<Self> {
517 if value.data_type() == rusqlite::types::Type::Null {
518 Ok(None)
519 } else {
520 Ok(Some(T::from_sql(value)?))
521 }
522 }
523}
524
525pub struct Expr<'column, S, T: MyTyp> {
533 pub(crate) _local: PhantomData<*const ()>,
534 pub(crate) inner: Rc<dyn Typed<Typ = T>>,
535 pub(crate) _p: PhantomData<&'column ()>,
536 pub(crate) _p2: PhantomData<S>,
537 pub(crate) ext: OnceCell<Box<T::Ext<'static>>>,
538}
539
540impl<S, T: MyTyp> Debug for Expr<'_, S, T> {
541 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
542 write!(f, "Expr of type {}", std::any::type_name::<T>())
543 }
544}
545
546impl<'column, S, T: MyTyp> Expr<'column, S, T> {
547 #[doc(hidden)]
549 pub fn _migrate<OldS>(prev: impl IntoExpr<'column, OldS>) -> Self {
550 Self::new(MigratedExpr {
551 prev: DynTypedExpr::erase(prev),
552 _p: PhantomData,
553 })
554 }
555}
556
557pub fn adhoc_expr<S, T: MyTyp>(
558 f: impl 'static + Fn(&mut ValueBuilder) -> sea_query::Expr,
559) -> Expr<'static, S, T> {
560 Expr::adhoc(f)
561}
562
563pub fn new_column<'x, S, C: MyTyp, T: Table>(
564 table: impl IntoExpr<'x, S, Typ = T>,
565 name: &'static str,
566) -> Expr<'x, S, C> {
567 let table = table.into_expr().inner;
568 let possible_null = table.maybe_optional();
569 Expr::adhoc_promise(
570 move |b| sea_query::Expr::col((table.build_table(b), Field::Str(name))).into(),
571 possible_null,
572 )
573}
574
575pub fn unique_from_joinable<'inner, T: Table>(
576 j: impl Joinable<'inner, Typ = T>,
577) -> Expr<'inner, T::Schema, Option<T>> {
578 let list = j.conds();
579 ::rust_query::private::adhoc_expr(move |_b| {
580 let list = list
581 .iter()
582 .map(|(name, col)| (*name, (col.func)(_b)))
583 .collect();
584 _b.get_unique::<T>(list)
585 })
586}
587
588struct AdHoc<F, T> {
589 func: F,
590 maybe_optional: bool,
591 _p: PhantomData<T>,
592}
593impl<F: Fn(&mut ValueBuilder) -> sea_query::Expr, T> Typed for AdHoc<F, T> {
594 type Typ = T;
595
596 fn build_expr(&self, b: &mut ValueBuilder) -> sea_query::Expr {
597 (self.func)(b)
598 }
599 fn maybe_optional(&self) -> bool {
600 self.maybe_optional
601 }
602}
603
604impl<S, T: MyTyp> Expr<'_, S, T> {
605 pub(crate) fn adhoc(f: impl 'static + Fn(&mut ValueBuilder) -> sea_query::Expr) -> Self {
606 Self::new(AdHoc {
607 func: f,
608 maybe_optional: true,
609 _p: PhantomData,
610 })
611 }
612
613 pub(crate) fn adhoc_promise(
618 f: impl 'static + Fn(&mut ValueBuilder) -> sea_query::Expr,
619 maybe_optional: bool,
620 ) -> Self {
621 Self::new(AdHoc {
622 func: f,
623 maybe_optional,
624 _p: PhantomData,
625 })
626 }
627
628 pub(crate) fn new(val: impl Typed<Typ = T> + 'static) -> Self {
629 Self {
630 _local: PhantomData,
631 inner: Rc::new(val),
632 _p: PhantomData,
633 _p2: PhantomData,
634 ext: OnceCell::new(),
635 }
636 }
637}
638
639impl<S, T: MyTyp> Clone for Expr<'_, S, T> {
640 fn clone(&self) -> Self {
641 Self {
642 _local: PhantomData,
643 inner: self.inner.clone(),
644 _p: self._p,
645 _p2: self._p2,
646 ext: OnceCell::new(),
647 }
648 }
649}
650
651#[derive(Clone)]
652pub struct DynTypedExpr {
653 pub func: Rc<dyn Fn(&mut ValueBuilder) -> sea_query::Expr>,
654}
655
656impl DynTypedExpr {
657 pub fn new(f: impl 'static + Fn(&mut ValueBuilder) -> sea_query::Expr) -> Self {
658 Self { func: Rc::new(f) }
659 }
660 pub fn erase<'x, S>(expr: impl IntoExpr<'x, S>) -> Self {
661 let typed = expr.into_expr().inner;
662 Self::new(move |b| typed.build_expr(b))
663 }
664}
665
666pub struct MigratedExpr<Typ> {
667 prev: DynTypedExpr,
668 _p: PhantomData<Typ>,
669}
670
671impl<Typ> Typed for MigratedExpr<Typ> {
672 type Typ = Typ;
673 fn build_expr(&self, b: &mut ValueBuilder) -> sea_query::Expr {
674 (self.prev.func)(b)
675 }
676}
677
678impl<'column, S, T: MyTyp> IntoExpr<'column, S> for Expr<'column, S, T> {
679 type Typ = T;
680 fn into_expr(self) -> Expr<'column, S, Self::Typ> {
681 self
682 }
683}
684
685impl<'t, T: Table> Deref for Expr<'t, T::Schema, T> {
686 type Target = T::Ext2<'t>;
687
688 fn deref(&self) -> &Self::Target {
689 T::covariant_ext(self.ext.get_or_init(|| {
690 let expr = Expr {
691 _local: PhantomData,
692 inner: self.inner.clone(),
693 _p: PhantomData::<&'static ()>,
694 _p2: PhantomData,
695 ext: OnceCell::new(),
696 };
697 Box::new(T::build_ext2(&expr))
698 }))
699 }
700}