1#![allow(internal_features)]
3#![cfg_attr(any(docsrs, docsrs_dep), feature(rustdoc_internals))]
4pub mod is_nullable;
55
56use std::{
57 borrow::Cow,
58 marker::PhantomData,
59 sync::{Arc, atomic::AtomicU32},
60};
61
62use bytemuck::TransparentWrapper as _;
63use sea_query::{ExprTrait, OverStatement};
64
65#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Ord, Eq, Hash)]
66struct Binder(u32);
67
68static BINDER_COUNT: AtomicU32 = AtomicU32::new(0);
69impl Binder {
70 fn new() -> Self {
71 Self(BINDER_COUNT.fetch_add(1, std::sync::atomic::Ordering::SeqCst))
72 }
73
74 #[allow(unused)]
75 fn reset() {
76 BINDER_COUNT.store(0, std::sync::atomic::Ordering::SeqCst);
77 }
78}
79
80#[derive(Clone, Eq, PartialEq)]
81struct TableName {
82 binder: Binder,
83 name: String,
84}
85
86impl std::fmt::Debug for TableName {
87 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88 write!(f, "{}", self.name)
89 }
90}
91
92impl<'a> From<TableName> for Cow<'a, str> {
93 fn from(val: TableName) -> Self {
94 format!("t{}", val.binder.0).into()
95 }
96}
97
98impl TableName {
99 fn new(binder: Binder) -> Self {
100 Self {
101 binder,
102 name: format!("t{}", binder.0),
103 }
104 }
105}
106
107impl sea_query::Iden for TableName {
108 fn unquoted(&self) -> &str {
109 &self.name
110 }
111}
112
113#[derive(Clone, PartialEq, Eq, Hash)]
114struct ColumnName {
115 name: String,
116 rendered: String,
117}
118
119impl std::fmt::Display for ColumnName {
120 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
121 write!(f, "{}", self.rendered)
122 }
123}
124
125impl std::fmt::Debug for ColumnName {
126 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127 write!(f, "{}", self.rendered)
128 }
129}
130
131impl sea_query::Iden for ColumnName {
132 fn unquoted(&self) -> &str {
133 &self.rendered
134 }
135}
136
137impl ColumnName {
138 fn new(binder: Binder, name: String) -> Self {
139 Self {
140 rendered: format!("{}{}", name, binder.0),
141 name,
142 }
143 }
144}
145
146pub trait TableHKT {
157 type Mode: TableMode;
159
160 type InMode<Mode: TableMode>;
162}
163
164#[cfg(feature = "sqlx")]
165mod value_sqlx {
167 pub trait Value: for<'r> sqlx::Decode<'r, sqlx::Postgres> + sqlx::Type<sqlx::Postgres> {}
169 impl<T> Value for T where T: for<'r> sqlx::Decode<'r, sqlx::Postgres> + sqlx::Type<sqlx::Postgres> {}
170}
171
172#[cfg(not(feature = "sqlx"))]
173mod value_sqlx {
175 pub trait Value {}
177 impl<T> Value for T where T: ?Sized {}
178}
179
180pub use value_sqlx::Value as SqlxValueIfEnabled;
181
182pub trait Value: Into<sea_query::Value> + SqlxValueIfEnabled + IsNullable {}
187
188impl<T> Value for T where T: Into<sea_query::Value> + value_sqlx::Value + IsNullable {}
189
190pub trait ModeMapper<'scope, SrcMode: TableMode, DestMode: TableMode> {
194 fn map_mode<V>(&mut self, src: SrcMode::T<'scope, V>) -> DestMode::T<'scope, V>
196 where
197 V: Value;
198}
199
200pub trait ModeMapperRef<'scope, SrcMode: TableMode, DestMode: TableMode> {
204 fn map_mode_ref<V>(&mut self, src: &SrcMode::T<'scope, V>) -> DestMode::T<'scope, V>
206 where
207 V: Value;
208}
209
210pub trait ModeMapperMut<'scope, SrcMode: TableMode, DestMode: TableMode> {
214 fn map_mode_mut<V>(&mut self, src: &mut SrcMode::T<'scope, V>) -> DestMode::T<'scope, V>
216 where
217 V: Value;
218}
219
220pub trait MapTable<'scope>: TableHKT {
223 fn map_modes<Mapper, DestMode>(self, mapper: &mut Mapper) -> Self::InMode<DestMode>
228 where
229 Mapper: ModeMapper<'scope, Self::Mode, DestMode>,
230 DestMode: TableMode;
231
232 fn map_modes_ref<Mapper, DestMode>(&self, mapper: &mut Mapper) -> Self::InMode<DestMode>
237 where
238 Mapper: ModeMapperRef<'scope, Self::Mode, DestMode>,
239 DestMode: TableMode;
240
241 fn map_modes_mut<Mapper, DestMode>(&mut self, mapper: &mut Mapper) -> Self::InMode<DestMode>
246 where
247 Mapper: ModeMapperMut<'scope, Self::Mode, DestMode>,
248 DestMode: TableMode;
249}
250
251struct NameToExprMapper {
254 binder: Binder,
255 query: sea_query::SelectStatement,
256}
257
258impl<'scope> ModeMapperRef<'scope, NameMode, ExprMode> for NameToExprMapper {
259 fn map_mode_ref<V>(
260 &mut self,
261 src: &<NameMode as TableMode>::T<'scope, V>,
262 ) -> <ExprMode as TableMode>::T<'scope, V> {
263 let col_name = ColumnName::new(self.binder, src.to_string());
264 self.query
265 .expr_as(sea_query::Expr::column(*src), col_name.clone());
266
267 Expr::new(ExprInner::Column(TableName::new(self.binder), col_name))
268 }
269}
270
271struct LitMapper {}
272
273impl<'scope> ModeMapper<'scope, ValueMode, ExprMode> for LitMapper {
274 fn map_mode<V>(
275 &mut self,
276 src: <ValueMode as TableMode>::T<'scope, V>,
277 ) -> <ExprMode as TableMode>::T<'scope, V>
278 where
279 V: Value,
280 {
281 Expr::new(ExprInner::Raw(sea_query::Expr::value(src.into())))
282 }
283}
284
285struct ExprCollectorMapper {
286 idx: usize,
287 table_binder: Binder,
288 columns: Vec<ColumnName>,
289 values: Vec<sea_query::Value>,
290}
291
292impl<'scope> ModeMapper<'scope, ValueMode, ExprMode> for ExprCollectorMapper {
293 fn map_mode<V>(
294 &mut self,
295 src: <ValueMode as TableMode>::T<'scope, V>,
296 ) -> <ExprMode as TableMode>::T<'scope, V>
297 where
298 V: Value,
299 {
300 let idx = self.idx;
301 self.idx += 1;
302
303 self.values.push(src.into());
304
305 let column_name = ColumnName::new(self.table_binder, format!("values_{idx}_"));
306
307 self.columns.push(column_name.clone());
308
309 Expr::new(ExprInner::Column(
310 TableName::new(self.table_binder),
311 column_name,
312 ))
313 }
314}
315
316struct ExprCollectorRemainingMapper {
317 values: Vec<sea_query::Value>,
318}
319
320impl<'scope> ModeMapper<'scope, ValueMode, EmptyMode> for ExprCollectorRemainingMapper {
321 fn map_mode<V>(
322 &mut self,
323 src: <ValueMode as TableMode>::T<'scope, V>,
324 ) -> <EmptyMode as TableMode>::T<'scope, V>
325 where
326 V: Value,
327 {
328 self.values.push(src.into());
329 }
330}
331
332struct NameCollectorMapper {
333 names: Vec<&'static str>,
334}
335
336impl<'scope> ModeMapperRef<'scope, NameMode, EmptyMode> for NameCollectorMapper {
337 fn map_mode_ref<V>(
338 &mut self,
339 src: &<NameMode as TableMode>::T<'scope, V>,
340 ) -> <EmptyMode as TableMode>::T<'scope, V> {
341 self.names.push(*src);
342 }
343}
344
345struct VisitTableMapper<'a, F> {
347 f: &'a mut F,
348 mode: VisitTableMode,
349}
350
351impl<'a, 'scope, F> ModeMapperRef<'scope, ExprMode, EmptyMode> for VisitTableMapper<'a, F>
352where
353 F: FnMut(&ErasedExpr),
354{
355 fn map_mode_ref<V>(
356 &mut self,
357 src: &<ExprMode as TableMode>::T<'scope, V>,
358 ) -> <EmptyMode as TableMode>::T<'scope, V>
359 where
360 V: Value,
361 {
362 match self.mode {
363 VisitTableMode::All => (self.f)(src.as_erased()),
364 VisitTableMode::NonNull => {
365 if !<V as IsNullable>::IS_NULLABLE {
366 (self.f)(src.as_erased());
367 }
368 }
369 }
370 }
371}
372
373struct VisitTableMapperMut<'a, F> {
375 f: &'a mut F,
376 mode: VisitTableMode,
377}
378
379impl<'a, 'scope, F> ModeMapperMut<'scope, ExprMode, EmptyMode> for VisitTableMapperMut<'a, F>
380where
381 F: FnMut(&mut ErasedExpr),
382{
383 fn map_mode_mut<V>(
384 &mut self,
385 src: &mut <ExprMode as TableMode>::T<'scope, V>,
386 ) -> <EmptyMode as TableMode>::T<'scope, V>
387 where
388 V: Value,
389 {
390 match self.mode {
391 VisitTableMode::All => (self.f)(src.as_erased_mut()),
392 VisitTableMode::NonNull => {
393 if !<V as IsNullable>::IS_NULLABLE {
394 (self.f)(src.as_erased_mut());
395 }
396 }
397 }
398 }
399}
400
401#[cfg(feature = "sqlx")]
402struct LoadingMapper<'a, IT> {
404 it: &'a mut IT,
405}
406
407#[cfg(feature = "sqlx")]
408impl<'a, 'b, 'scope, IT> ModeMapperRef<'scope, ExprMode, ValueMode> for LoadingMapper<'a, IT>
409where
410 IT: Iterator<Item = sqlx::postgres::PgValueRef<'b>>,
411{
412 fn map_mode_ref<V>(
413 &mut self,
414 _src: &<ExprMode as TableMode>::T<'scope, V>,
415 ) -> <ValueMode as TableMode>::T<'scope, V>
416 where
417 V: Value,
418 {
419 <_ as sqlx::Decode<sqlx::Postgres>>::decode(self.it.next().unwrap()).unwrap()
420 }
421}
422
423#[cfg(feature = "sqlx")]
424struct LoadingManyMapper<'a, IT> {
426 it: &'a mut IT,
427}
428
429#[cfg(feature = "sqlx")]
430impl<'a, 'b, 'scope, IT> ModeMapperRef<'scope, ExprMode, ValueManyMode>
431 for LoadingManyMapper<'a, IT>
432where
433 IT: Iterator<Item = sqlx::postgres::PgValueRef<'b>>,
434{
435 fn map_mode_ref<V>(
436 &mut self,
437 _src: &<ExprMode as TableMode>::T<'scope, V>,
438 ) -> <ValueManyMode as TableMode>::T<'scope, V>
439 where
440 V: Value,
441 {
442 <Vec<V> as sqlx::Decode<sqlx::Postgres>>::decode(self.it.next().unwrap()).unwrap()
443 }
444}
445
446#[cfg(feature = "sqlx")]
447struct SkippingMapper<'a, IT> {
449 it: &'a mut IT,
450}
451
452#[cfg(feature = "sqlx")]
453impl<'a, 'b, 'scope, IT> ModeMapperRef<'scope, ExprMode, EmptyMode> for SkippingMapper<'a, IT>
454where
455 IT: Iterator<Item = sqlx::postgres::PgValueRef<'b>>,
456{
457 fn map_mode_ref<V>(
458 &mut self,
459 _src: &<ExprMode as TableMode>::T<'scope, V>,
460 ) -> <EmptyMode as TableMode>::T<'scope, V> {
461 self.it.next().unwrap();
462 }
463}
464
465#[cfg(feature = "sqlx")]
466struct ManyRemainingMapper {
467 is_empty: bool,
468}
469
470#[cfg(feature = "sqlx")]
471impl<'scope> ModeMapperRef<'scope, ValueManyMode, EmptyMode> for ManyRemainingMapper {
472 fn map_mode_ref<V>(
473 &mut self,
474 src: &<ValueManyMode as TableMode>::T<'scope, V>,
475 ) -> <EmptyMode as TableMode>::T<'scope, V>
476 where
477 V: Value,
478 {
479 self.is_empty &= src.is_empty();
480 }
481}
482
483#[cfg(feature = "sqlx")]
484struct SpreadingManyMapper {}
485
486#[cfg(feature = "sqlx")]
487impl<'a, 'scope> ModeMapperMut<'scope, ValueManyMode, ValueMode> for SpreadingManyMapper {
488 fn map_mode_mut<V>(
489 &mut self,
490 src: &mut <ValueManyMode as TableMode>::T<'scope, V>,
491 ) -> <ValueMode as TableMode>::T<'scope, V>
492 where
493 V: Value,
494 {
495 src.pop().unwrap()
496 }
497}
498
499pub trait LitTable: TableHKT<Mode = ValueMode> {
501 fn lit(self) -> Self::InMode<ExprMode>;
503}
504
505impl<'scope, T: TableHKT<Mode = ValueMode> + MapTable<'scope>> LitTable for T {
506 fn lit(self) -> Self::InMode<ExprMode> {
507 self.map_modes(&mut LitMapper {})
508 }
509}
510
511pub struct TableSchema<Table> {
513 pub name: &'static str,
515
516 pub columns: Table,
518}
519
520pub mod table_modes {
522 pub enum NameMode {}
524
525 #[derive(Debug, PartialEq)]
526 pub enum ValueMode {}
532
533 pub enum ValueManyMode {}
534
535 pub enum ExprMode {}
540
541 pub enum EmptyMode {}
547}
548
549pub use table_modes::*;
550
551pub trait TableMode {
565 type T<'scope, V>;
567}
568
569impl TableMode for NameMode {
570 type T<'scope, V> = &'static str;
572}
573
574impl TableMode for ValueMode {
575 type T<'scope, V> = V;
576}
577
578impl TableMode for ValueManyMode {
579 type T<'scope, V> = Vec<V>;
580}
581
582impl TableMode for ExprMode {
583 type T<'scope, V> = Expr<'scope, V>;
584}
585
586impl TableMode for EmptyMode {
587 type T<'scope, V> = ();
588}
589
590#[derive(bytemuck::TransparentWrapper)]
591#[repr(transparent)]
592pub struct TableUsingMapper<T>(pub T);
594
595#[allow(missing_docs)]
596impl<T> TableUsingMapper<T> {
597 pub fn wrap(t: T) -> Self {
598 <Self as bytemuck::TransparentWrapper<T>>::wrap(t)
599 }
600
601 pub fn wrap_ref(t: &T) -> &Self {
602 <Self as bytemuck::TransparentWrapper<T>>::wrap_ref(t)
603 }
604
605 pub fn wrap_mut(t: &mut T) -> &mut Self {
606 <Self as bytemuck::TransparentWrapper<T>>::wrap_mut(t)
607 }
608}
609
610impl<'scope, T> Table for TableUsingMapper<T>
611where
612 T: Table + MapTable<'scope> + TableHKT<Mode = ExprMode>,
613{
614 type Result = T::InMode<ValueMode>;
615
616 fn visit(&self, f: &mut impl FnMut(&ErasedExpr), mode: VisitTableMode) {
617 let mut mapper = VisitTableMapper { f, mode };
618 self.0.map_modes_ref(&mut mapper);
619 }
620
621 fn visit_mut(&mut self, f: &mut impl FnMut(&mut ErasedExpr), mode: VisitTableMode) {
622 let mut mapper = VisitTableMapperMut { f, mode };
623 self.0.map_modes_mut(&mut mapper);
624 }
625}
626
627#[cfg(feature = "sqlx")]
628impl<T> TableLoaderSqlx for TableUsingMapper<T>
629where
630 T: Table + MapTable<'static> + TableHKT<Mode = ExprMode>,
631{
632 fn load<'a>(
633 &self,
634 values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>,
635 ) -> Self::Result {
636 let mut mapper = LoadingMapper { it: values };
637 self.0.map_modes_ref(&mut mapper)
638 }
639
640 fn skip<'a>(&self, values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>) {
641 let mut mapper = SkippingMapper { it: values };
642 self.0.map_modes_ref(&mut mapper);
643 }
644}
645
646#[cfg(feature = "sqlx")]
647impl<T> TableLoaderManySqlx for TableUsingMapper<T>
648where
649 T: Table + MapTable<'static> + TableHKT<Mode = ExprMode>,
650 T::InMode<ValueManyMode>: MapTable<'static> + TableHKT<Mode = ValueManyMode>,
651 <<T as TableHKT>::InMode<table_modes::ValueManyMode> as TableHKT>::InMode<
653 table_modes::ValueMode,
654 >: type_equalities::IsEqual<Self::Result>,
655{
656 fn load_many<'a>(
657 &self,
658 values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>,
659 ) -> Vec<Self::Result> {
660 let mut mapper = LoadingManyMapper { it: values };
661 let mut collected = self.0.map_modes_ref(&mut mapper);
662
663 let mut results: Vec<Self::Result> = vec![];
664
665 while {
666 let mut mapper = ManyRemainingMapper { is_empty: true };
667 collected.map_modes_ref(&mut mapper);
668 !mapper.is_empty
669 } {
670 let mut mapper = SpreadingManyMapper {};
671 results.push(type_equalities::coerce(
672 collected.map_modes_mut(&mut mapper),
673 type_equalities::trivial_eq(),
674 ));
675 }
676
677 results
678 }
679}
680
681#[derive(Debug, Copy, Clone)]
683pub enum VisitTableMode {
684 All,
686 NonNull,
688}
689
690pub trait Table {
694 type Result;
696
697 fn visit(&self, f: &mut impl FnMut(&ErasedExpr), mode: VisitTableMode);
702
703 fn visit_mut(&mut self, f: &mut impl FnMut(&mut ErasedExpr), mode: VisitTableMode);
708}
709
710#[cfg(feature = "sqlx")]
711pub trait TableLoaderSqlx: Table {
713 fn load<'a>(
715 &self,
716 values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>,
717 ) -> Self::Result;
718
719 fn skip<'a>(&self, values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>);
722}
723
724#[cfg(feature = "sqlx")]
725pub trait TableLoaderManySqlx: Table + TableLoaderSqlx {
727 fn load_many<'a>(
729 &self,
730 values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>,
731 ) -> Vec<Self::Result>;
732}
733
734fn subst_table<'scope, T: Table>(
739 table: &mut T,
740 table_name: TableName,
741 dest_select: &mut sea_query::SelectStatement,
742) {
743 table.visit_mut(
744 &mut |ErasedExpr(inner)| {
745 let new_column_name = match inner {
746 ExprInner::Raw(..) => ColumnName::new(Binder::new(), "lit".to_owned()),
747 ExprInner::Column(_table_name, column_name) => {
748 ColumnName::new(Binder::new(), column_name.name.clone())
749 }
750 ExprInner::BinOp(..) => ColumnName::new(Binder::new(), "expr".to_owned()),
751 ExprInner::NOp(..) => ColumnName::new(Binder::new(), "expr".to_owned()),
752 };
753 let r = inner.render();
754 dest_select.expr_as(r, new_column_name.clone());
755 *inner = ExprInner::Column(table_name.clone(), new_column_name);
756 },
757 VisitTableMode::All,
758 )
759}
760
761fn insert_table_name<'scope, T: Table>(table: &mut T, new_table_name: TableName) {
763 table.visit_mut(
764 &mut |ErasedExpr(inner)| match inner {
765 ExprInner::Raw(_) => {}
766 ExprInner::Column(table_name, _column_name) => {
767 *table_name = new_table_name.clone();
768 }
769 ExprInner::BinOp(_, expr_inner, expr_inner1) => {
770 expr_inner.visit_mut(&mut |table_name, _| *table_name = new_table_name.clone());
771 expr_inner1.visit_mut(&mut |table_name, _| *table_name = new_table_name.clone());
772 }
773 ExprInner::NOp(_, expr_inners) => {
774 for expr_inner in expr_inners {
775 expr_inner.visit_mut(&mut |table_name, _| *table_name = new_table_name.clone());
776 }
777 }
778 },
779 VisitTableMode::All,
780 )
781}
782
783fn collect_exprs<'scope, T: Table>(table: &T) -> Vec<ExprInner> {
784 let mut exprs = vec![];
785
786 table.visit(
787 &mut |ErasedExpr(e)| {
788 exprs.push(e.clone());
789 },
790 VisitTableMode::All,
791 );
792
793 exprs
794}
795
796#[non_exhaustive]
799pub struct WithLtMarker {}
800
801impl WithLtMarker {
802 fn new() -> Self {
803 Self {}
804 }
805}
806
807pub trait ForLifetimeTable {
813 type WithLt<'lt>: ForLifetimeTable + Table + Sized;
815
816 fn with_lt<'lt>(self, marker: &mut WithLtMarker) -> Self::WithLt<'lt>;
818 fn unwith_lt<'lt>(with_lt: Self::WithLt<'lt>, marker: &mut WithLtMarker) -> Self;
819}
820
821impl<'scope, T> Table for Expr<'scope, T>
822where
823 T: Value,
824{
825 type Result = T;
826
827 fn visit(&self, f: &mut impl FnMut(&ErasedExpr), mode: VisitTableMode) {
828 match mode {
829 VisitTableMode::All => f(self.as_erased()),
830 VisitTableMode::NonNull => {
831 if !<T as IsNullable>::IS_NULLABLE {
832 f(self.as_erased());
833 }
834 }
835 }
836 }
837
838 fn visit_mut(&mut self, f: &mut impl FnMut(&mut ErasedExpr), mode: VisitTableMode) {
839 match mode {
840 VisitTableMode::All => f(self.as_erased_mut()),
841 VisitTableMode::NonNull => {
842 if !<T as IsNullable>::IS_NULLABLE {
843 f(self.as_erased_mut());
844 }
845 }
846 }
847 }
848}
849
850impl<'scope, T: Value> ForLifetimeTable for Expr<'scope, T> {
851 type WithLt<'lt> = Expr<'lt, T>;
852
853 fn with_lt<'lt>(self, _marker: &mut WithLtMarker) -> Self::WithLt<'lt> {
854 Expr::new(self.expr)
855 }
856
857 fn unwith_lt<'lt>(with_lt: Self::WithLt<'lt>, _marker: &mut WithLtMarker) -> Self {
858 Expr::new(with_lt.expr)
859 }
860}
861
862impl<'scope, T> ShortenLifetime for Expr<'scope, T> {
863 type Shortened<'small>
864 = Expr<'small, T>
865 where
866 Self: 'small;
867
868 fn shorten_lifetime<'small, 'large: 'small>(self) -> Self::Shortened<'small>
869 where
870 Self: 'large,
871 {
872 Expr::new(self.expr)
873 }
874}
875
876#[cfg(feature = "sqlx")]
877impl<T: Value> TableLoaderSqlx for Expr<'static, T> {
878 fn load<'a>(
879 &self,
880 values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>,
881 ) -> Self::Result {
882 T::decode(values.next().unwrap()).unwrap()
883 }
884
885 fn skip<'a>(&self, values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>) {
886 let _ = values.next().unwrap();
887 }
888}
889
890#[cfg(feature = "sqlx")]
891impl<T: Value> TableLoaderManySqlx for Expr<'static, T> {
892 fn load_many<'a>(
893 &self,
894 values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>,
895 ) -> Vec<Self::Result> {
896 <Vec<T> as sqlx::Decode<'_, sqlx::Postgres>>::decode(values.next().unwrap())
897 .unwrap_or_default()
898 }
899}
900
901macro_rules! izip_priv {
902 ( @closure $p:pat => $tup:expr ) => {
903 |$p| $tup
904 };
905
906 ( @closure $p:pat => ( $($tup:tt)* ) , $_iter:expr $( , $tail:expr )* ) => {
907 izip_priv!(@closure ($p, b) => ( $($tup)*, b ) $( , $tail )*)
908 };
909
910 ($first:expr $(,)*) => {
911 $first.into_iter().map(|a| (a,))
912 };
913
914 ( $first:expr $( , $rest:expr )* $(,)* ) => {
915 {
916 let iter = $first.into_iter();
917 $(
918 let iter = iter.zip($rest);
919 )*
920 iter.map(izip_priv!(@closure a => (a) $( , $rest )*))
921 }
922 };
923}
924
925macro_rules! impl_tuples {
926 ($(#[$meta:meta])* $(($idx:tt, $ty:ident)),*) => {
927
928 $(#[$meta])*
929 impl<'scope, $($ty,)*> Table for ($($ty,)*)
930 where $($ty: Table,)*
931 {
932 type Result = ($($ty::Result,)*);
933
934 fn visit(&self, f: &mut impl FnMut(&ErasedExpr), mode: VisitTableMode) {
935 $(self.$idx.visit(f, mode);)*
936 }
937
938 fn visit_mut(&mut self, f: &mut impl FnMut(&mut ErasedExpr), mode: VisitTableMode) {
939 $(self.$idx.visit_mut(f, mode);)*
940 }
941 }
942
943 $(#[$meta])*
944 impl<$($ty,)*> ShortenLifetime for ($($ty,)*)
945 where $($ty: ShortenLifetime,)*
946 {
947 type Shortened<'small>
948 = ($($ty::Shortened<'small>,)*)
949 where
950 Self: 'small;
951
952 fn shorten_lifetime<'small, 'large: 'small>(self) -> Self::Shortened<'small>
953 where
954 Self: 'large,
955 {
956 ($(self.$idx.shorten_lifetime(),)*)
957 }
958 }
959
960 $(#[$meta])*
961 impl<$($ty,)*> ForLifetimeTable for ($($ty,)*)
962 where $($ty: ForLifetimeTable,)*
963 {
964 type WithLt<'lt>
965 = ($($ty::WithLt<'lt>,)*);
966
967 fn with_lt<'lt>(self, marker: &mut WithLtMarker) -> Self::WithLt<'lt> {
968 ($(self.$idx.with_lt(marker),)*)
969 }
970
971 fn unwith_lt<'lt>(with_lt: Self::WithLt<'lt>, marker: &mut WithLtMarker) -> Self {
972 ($(<$ty>::unwith_lt(with_lt.$idx, marker),)*)
973 }
974 }
975
976 #[cfg(feature = "sqlx")]
977 $(#[$meta])*
978 impl<$($ty,)*> TableLoaderSqlx for ($($ty,)*)
979 where $($ty: TableLoaderSqlx,)*
980 {
981 fn load<'a>(
982 &self,
983 values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>,
984 ) -> Self::Result {
985 (
986 $(self.$idx.load(values),)*
987 )
988 }
989
990 fn skip<'a>(&self, values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>) {
991 $(self.$idx.skip(values);)*
992 }
993 }
994
995 #[cfg(feature = "sqlx")]
996 $(#[$meta])*
997 impl<$($ty,)*> TableLoaderManySqlx for ($($ty,)*)
998 where $($ty: TableLoaderManySqlx,)*
999 {
1000 fn load_many<'a>(
1001 &self,
1002 values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>,
1003 ) -> Vec<Self::Result> {
1004 izip_priv!($(self.$idx.load_many(values),)*).collect()
1005 }
1006 }
1007}
1008}
1009
1010variadics_please::all_tuples_enumerated!(
1011 #[doc(fake_variadic)]
1012 impl_tuples,
1013 1,
1014 15,
1015 T
1016);
1017
1018pub struct MaybeTable<'scope, T> {
1021 tag: Expr<'scope, Option<bool>>,
1022 inner: T,
1023}
1024
1025impl<'scope, T: Table> MaybeTable<'scope, T> {
1026 pub fn project<U, F>(&self, f: F) -> Expr<'scope, Option<U>>
1028 where
1029 F: FnOnce(&T) -> Expr<U>,
1030 {
1031 let tag = self.tag.clone();
1032 let e = f(&self.inner);
1033
1034 let cb = Arc::new(|cond: sea_query::SimpleExpr, expr: sea_query::SimpleExpr| {
1035 sea_query::CaseStatement::new()
1036 .case(cond.is_not_null(), expr)
1037 .finally(sea_query::Expr::null())
1038 .into()
1039 });
1040
1041 Expr::new(ExprInner::BinOp(cb, Box::new(tag.expr), Box::new(e.expr)))
1042 }
1043
1044 pub fn maybe<U: Table, F>(self, fallback: U, f: F) -> U
1047 where
1048 F: FnOnce(T) -> U,
1049 {
1050 let tag = self.tag.clone();
1051 let mut e = f(self.inner);
1052
1053 let mut defaults = collect_exprs(&fallback).into_iter();
1054
1055 e.visit_mut(
1056 &mut |ErasedExpr(inner)| {
1057 let tag = tag.expr.clone();
1058 let default = defaults.next().unwrap();
1059 let cb = Arc::new(|exprs: Vec<sea_query::Expr>| {
1060 let [tag, expr, default] = exprs.try_into().unwrap();
1061 sea_query::CaseStatement::new()
1062 .case(tag.is_not_null(), expr)
1063 .finally(default)
1064 .into()
1065 });
1066
1067 *inner = ExprInner::NOp(cb, vec![tag, inner.clone(), default]);
1068 },
1069 VisitTableMode::All,
1070 );
1071
1072 e
1073 }
1074}
1075
1076impl<'scope, T: Table> Table for MaybeTable<'scope, T> {
1077 type Result = Option<T::Result>;
1078
1079 fn visit(&self, f: &mut impl FnMut(&ErasedExpr), mode: VisitTableMode) {
1080 self.tag.visit(f, mode);
1081 self.inner.visit(f, mode);
1082 }
1083
1084 fn visit_mut(&mut self, f: &mut impl FnMut(&mut ErasedExpr), mode: VisitTableMode) {
1085 self.tag.visit_mut(f, mode);
1086 self.inner.visit_mut(f, mode);
1087 }
1088}
1089
1090impl<'scope, T: ForLifetimeTable + Table> ForLifetimeTable for MaybeTable<'scope, T>
1091where
1092 for<'lt> T::WithLt<'lt>: Table,
1093{
1094 type WithLt<'lt> = MaybeTable<'lt, T::WithLt<'lt>>;
1095
1096 fn with_lt<'lt>(self, marker: &mut WithLtMarker) -> Self::WithLt<'lt> {
1097 MaybeTable {
1098 tag: self.tag.with_lt(marker),
1099 inner: self.inner.with_lt(marker),
1100 }
1101 }
1102
1103 fn unwith_lt<'lt>(with_lt: Self::WithLt<'lt>, marker: &mut WithLtMarker) -> Self {
1104 MaybeTable {
1105 tag: ForLifetimeTable::unwith_lt(with_lt.tag, marker),
1106 inner: ForLifetimeTable::unwith_lt(with_lt.inner, marker),
1107 }
1108 }
1109}
1110
1111impl<'scope, T: ShortenLifetime> ShortenLifetime for MaybeTable<'scope, T> {
1112 type Shortened<'small>
1113 = MaybeTable<'small, T::Shortened<'small>>
1114 where
1115 Self: 'small;
1116
1117 fn shorten_lifetime<'small, 'large: 'small>(self) -> Self::Shortened<'small>
1118 where
1119 Self: 'large,
1120 {
1121 MaybeTable {
1122 tag: self.tag.shorten_lifetime(),
1123 inner: self.inner.shorten_lifetime(),
1124 }
1125 }
1126}
1127
1128#[cfg(feature = "sqlx")]
1129impl<T: TableLoaderSqlx> TableLoaderSqlx for MaybeTable<'static, T> {
1130 fn load<'a>(
1131 &self,
1132 values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>,
1133 ) -> Self::Result {
1134 let tag =
1135 <Option<bool> as sqlx::Decode<sqlx::Postgres>>::decode(values.next().unwrap()).unwrap();
1136
1137 if tag == Some(true) {
1138 Some(self.inner.load(values))
1139 } else {
1140 self.inner.skip(values);
1141 None
1142 }
1143 }
1144
1145 fn skip<'a>(&self, values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>) {
1146 values.next().unwrap();
1148 self.inner.skip(values);
1149 }
1150}
1151
1152pub struct NullTable<'scope, T> {
1157 tag: Expr<'scope, Option<bool>>,
1160 inner: T,
1161}
1162
1163impl<'scope, T: Table> NullTable<'scope, T> {
1164 pub fn project<U, F>(&self, f: F) -> Expr<'scope, Option<U>>
1166 where
1167 F: FnOnce(&T) -> Expr<U>,
1168 {
1169 let e = f(&self.inner);
1170
1171 Expr::new(e.expr)
1172 }
1173
1174 pub fn maybe<U: Table, F>(self, fallback: U, f: F) -> U
1177 where
1178 F: FnOnce(T) -> U,
1179 {
1180 let tag = self.tag.clone();
1181 let mut e = f(self.inner);
1182
1183 let mut defaults = collect_exprs(&fallback).into_iter();
1184
1185 e.visit_mut(
1186 &mut |ErasedExpr(inner)| {
1187 let tag = tag.expr.clone();
1188 let default = defaults.next().unwrap();
1189 let cb = Arc::new(|exprs: Vec<sea_query::Expr>| {
1190 let [tag, expr, default] = exprs.try_into().unwrap();
1191 sea_query::CaseStatement::new()
1192 .case(tag.is_not_null(), expr)
1193 .finally(default)
1194 .into()
1195 });
1196
1197 *inner = ExprInner::NOp(cb, vec![tag, inner.clone(), default]);
1198 },
1199 VisitTableMode::All,
1200 );
1201
1202 e
1203 }
1204}
1205
1206impl<'scope, T: Table> Table for NullTable<'scope, T> {
1207 type Result = Option<T::Result>;
1208
1209 fn visit(&self, f: &mut impl FnMut(&ErasedExpr), mode: VisitTableMode) {
1210 self.tag.visit(f, mode);
1211 self.inner.visit(f, mode);
1212 }
1213
1214 fn visit_mut(&mut self, f: &mut impl FnMut(&mut ErasedExpr), mode: VisitTableMode) {
1215 self.tag.visit_mut(f, mode);
1216 self.inner.visit_mut(f, mode);
1217 }
1218}
1219
1220impl<'scope, T: ForLifetimeTable + Table> ForLifetimeTable for NullTable<'scope, T>
1221where
1222 for<'lt> T::WithLt<'lt>: Table,
1223{
1224 type WithLt<'lt> = NullTable<'lt, T::WithLt<'lt>>;
1225
1226 fn with_lt<'lt>(self, marker: &mut WithLtMarker) -> Self::WithLt<'lt> {
1227 NullTable {
1228 tag: self.tag.with_lt(marker),
1229 inner: self.inner.with_lt(marker),
1230 }
1231 }
1232
1233 fn unwith_lt<'lt>(with_lt: Self::WithLt<'lt>, marker: &mut WithLtMarker) -> Self {
1234 NullTable {
1235 tag: ForLifetimeTable::unwith_lt(with_lt.tag, marker),
1236 inner: ForLifetimeTable::unwith_lt(with_lt.inner, marker),
1237 }
1238 }
1239}
1240
1241impl<'scope, T: ShortenLifetime> ShortenLifetime for NullTable<'scope, T> {
1242 type Shortened<'small>
1243 = NullTable<'small, T::Shortened<'small>>
1244 where
1245 Self: 'small;
1246
1247 fn shorten_lifetime<'small, 'large: 'small>(self) -> Self::Shortened<'small>
1248 where
1249 Self: 'large,
1250 {
1251 NullTable {
1252 tag: self.tag.shorten_lifetime(),
1253 inner: self.inner.shorten_lifetime(),
1254 }
1255 }
1256}
1257
1258#[cfg(feature = "sqlx")]
1259impl<T: TableLoaderSqlx> TableLoaderSqlx for NullTable<'static, T> {
1260 fn load<'a>(
1261 &self,
1262 values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>,
1263 ) -> Self::Result {
1264 let tag =
1265 <Option<bool> as sqlx::Decode<sqlx::Postgres>>::decode(values.next().unwrap()).unwrap();
1266
1267 if tag == Some(true) {
1268 Some(self.inner.load(values))
1269 } else {
1270 self.inner.skip(values);
1271 None
1272 }
1273 }
1274
1275 fn skip<'a>(&self, values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>) {
1276 values.next().unwrap();
1278 self.inner.skip(values);
1279 }
1280}
1281
1282pub struct ListTable<T> {
1286 inner: T,
1287}
1288
1289impl<'scope, T: Table> Table for ListTable<T> {
1290 type Result = Vec<T::Result>;
1291
1292 fn visit(&self, f: &mut impl FnMut(&ErasedExpr), mode: VisitTableMode) {
1293 self.inner.visit(f, mode);
1294 }
1295
1296 fn visit_mut(&mut self, f: &mut impl FnMut(&mut ErasedExpr), mode: VisitTableMode) {
1297 self.inner.visit_mut(f, mode);
1298 }
1299}
1300
1301impl<'scope, T: ForLifetimeTable + Table> ForLifetimeTable for ListTable<T>
1302where
1303 for<'lt> T::WithLt<'lt>: Table,
1304{
1305 type WithLt<'lt> = ListTable<T::WithLt<'lt>>;
1306
1307 fn with_lt<'lt>(self, marker: &mut WithLtMarker) -> Self::WithLt<'lt> {
1308 ListTable {
1309 inner: self.inner.with_lt(marker),
1310 }
1311 }
1312
1313 fn unwith_lt<'lt>(with_lt: Self::WithLt<'lt>, marker: &mut WithLtMarker) -> Self {
1314 ListTable {
1315 inner: ForLifetimeTable::unwith_lt(with_lt.inner, marker),
1316 }
1317 }
1318}
1319
1320impl<T: ShortenLifetime> ShortenLifetime for ListTable<T> {
1321 type Shortened<'small>
1322 = ListTable<T::Shortened<'small>>
1323 where
1324 Self: 'small;
1325
1326 fn shorten_lifetime<'small, 'large: 'small>(self) -> Self::Shortened<'small>
1327 where
1328 Self: 'large,
1329 {
1330 ListTable {
1331 inner: self.inner.shorten_lifetime(),
1332 }
1333 }
1334}
1335
1336#[cfg(feature = "sqlx")]
1337impl<T: TableLoaderManySqlx> TableLoaderSqlx for ListTable<T> {
1338 fn load<'a>(
1339 &self,
1340 values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>,
1341 ) -> Self::Result {
1342 self.inner.load_many(values)
1343 }
1344
1345 fn skip<'a>(&self, values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>) {
1346 self.inner.skip(values);
1347 }
1348}
1349
1350#[derive(Clone)]
1352pub struct Query<T> {
1353 binder: Binder,
1355 expr: sea_query::SelectStatement,
1356 inner: T,
1357 siblings_need_random: bool,
1358}
1359
1360impl<'scope, T> Query<T>
1361where
1362 T: Table + ForLifetimeTable,
1363{
1364 fn new(binder: Binder, expr: sea_query::SelectStatement, inner: T) -> Self {
1365 Self {
1366 binder,
1367 expr,
1368 inner,
1369 siblings_need_random: false,
1370 }
1371 }
1372
1373 fn into_volatile(mut self) -> Self {
1374 self.siblings_need_random = true;
1375 self
1376 }
1377
1378 fn with_volatile(mut self, volatility: bool) -> Self {
1379 self.siblings_need_random = volatility;
1380 self
1381 }
1382
1383 fn erased(self) -> (ErasedQuery, T) {
1384 let r = ErasedQuery {
1385 expr: self.expr,
1386 siblings_need_random: self.siblings_need_random,
1387 };
1388
1389 (r, self.inner)
1390 }
1391
1392 pub fn aggregate<U>(
1397 self,
1398 f: impl for<'inner, 'outer> FnOnce(
1399 &mut A<'inner, 'outer>,
1400 T::WithLt<'inner>,
1401 ) -> U::WithLt<'outer>,
1402 ) -> Query<U::WithLt<'scope>>
1403 where
1404 U: ForLifetimeTable,
1405 {
1406 let mut a = A {
1407 group_by: vec![],
1408 _phantom: PhantomData,
1409 };
1410
1411 let mut r = f(&mut a, self.inner.with_lt(&mut WithLtMarker::new()));
1412
1413 let binder = Binder::new();
1414 let mut expr = sea_query::SelectStatement::new();
1415
1416 expr.from_subquery(self.expr, TableName::new(self.binder));
1417
1418 subst_table(&mut r, TableName::new(binder), &mut expr);
1419
1420 expr.add_group_by(a.group_by.iter().map(ExprInner::render));
1421
1422 Query::new(binder, expr, r)
1423 }
1424
1425 pub fn many(mut self) -> Query<ListTable<T>> {
1429 let binder = Binder::new();
1430 let mut expr = sea_query::SelectStatement::new();
1431
1432 expr.from_subquery(self.expr, TableName::new(self.binder));
1433
1434 self.inner.visit_mut(
1435 &mut |ErasedExpr(inner)| {
1436 *inner = ExprInner::NOp(
1437 Arc::new(|inners| {
1438 let [inner] = inners.try_into().unwrap();
1439
1440 sea_query::PgFunc::array_agg(inner).into()
1441 }),
1442 vec![inner.clone()],
1443 )
1444 },
1445 VisitTableMode::All,
1446 );
1447
1448 subst_table(&mut self.inner, TableName::new(binder), &mut expr);
1449
1450 Query::new(binder, expr, ListTable { inner: self.inner })
1451 .with_volatile(self.siblings_need_random)
1452 }
1453
1454 pub fn window<U>(
1459 self,
1460 f: impl for<'inner, 'outer> FnOnce(
1461 &mut W<'inner, 'outer>,
1462 T::WithLt<'inner>,
1463 ) -> U::WithLt<'outer>,
1464 ) -> Query<U::WithLt<'scope>>
1465 where
1466 U: ForLifetimeTable + Table,
1467 {
1468 let inner_binder = Binder::new();
1469 let middle_binder = Binder::new();
1470 let outer_binder = Binder::new();
1471
1472 let mut w = W {
1473 inner_query: sea_query::SelectStatement::new(),
1474 inner_table: TableName::new(inner_binder),
1475 middle_query: sea_query::SelectStatement::new(),
1476 middle_table: TableName::new(middle_binder),
1477 _phantom: PhantomData,
1478 };
1479
1480 let mut r = f(&mut w, self.inner.with_lt(&mut WithLtMarker::new()));
1481
1482 w.inner_query
1483 .from_subquery(self.expr, TableName::new(self.binder));
1484 w.middle_query.from_subquery(w.inner_query, w.inner_table);
1485
1486 let mut outer_query = sea_query::SelectStatement::new();
1487 outer_query.from_subquery(w.middle_query, w.middle_table.clone());
1488
1489 subst_table(&mut r, w.middle_table, &mut outer_query);
1490
1491 Query::new(outer_binder, outer_query, r)
1492 }
1493
1494 pub fn evaluate(mut table: T) -> Self {
1496 let binder = Binder::new();
1497 let mut expr = sea_query::SelectStatement::new();
1498 subst_table(&mut table, TableName::new(binder), &mut expr);
1499 Self::new(binder, expr, table).into_volatile()
1500 }
1501
1502 pub fn optional(mut self) -> Query<MaybeTable<'scope, T>> {
1506 let binder = Binder::new();
1507
1508 let mut filler = sea_query::Query::select()
1509 .from_values(
1510 vec![sea_query::ValueTuple::One(true.into())],
1511 TableName::new(binder),
1512 )
1513 .to_owned();
1514
1515 let tag = ColumnName::new(binder, "tag".to_owned());
1516
1517 let mut expr = self.expr;
1518 expr.expr_as(sea_query::Value::Bool(Some(true)), tag.clone());
1519
1520 let table_name = TableName::new(self.binder);
1521
1522 filler.join_subquery(
1523 sea_query::JoinType::LeftJoin,
1524 expr,
1525 table_name.clone(),
1526 sea_query::Condition::all(),
1527 );
1528
1529 filler.expr_as(
1531 sea_query::Expr::column((table_name.clone(), tag.clone())),
1532 tag.clone(),
1533 );
1534
1535 subst_table(&mut self.inner, table_name, &mut filler);
1537
1538 let maybe_table = MaybeTable {
1539 inner: self.inner,
1540 tag: Expr {
1541 expr: ExprInner::Column(TableName::new(binder), tag),
1542 _phantom: PhantomData,
1543 },
1544 };
1545
1546 Query {
1547 binder,
1548 expr: filler,
1549 inner: maybe_table,
1550 siblings_need_random: self.siblings_need_random,
1551 }
1552 }
1553
1554 pub fn nullable(mut self) -> Query<NullTable<'scope, T>> {
1560 let binder = Binder::new();
1561
1562 let tag = ColumnName::new(binder, "tag".to_owned());
1563
1564 let mut non_null_exprs = vec![];
1565 self.inner.visit(
1566 &mut |ErasedExpr(e)| {
1567 non_null_exprs.push(e.render().is_not_null());
1568 },
1569 VisitTableMode::NonNull,
1570 );
1571
1572 let non_null_expr = non_null_exprs
1573 .into_iter()
1574 .fold(sea_query::Condition::all(), |a, b| a.add(b));
1575
1576 let mut expr = self.expr;
1577 expr.expr_as(non_null_expr, tag.clone());
1578
1579 let table_name = TableName::new(self.binder);
1580
1581 let mut query = sea_query::Query::select();
1582 query.from_subquery(expr, table_name.clone());
1583
1584 query.expr_as(
1586 sea_query::Expr::column((table_name.clone(), tag.clone())),
1587 tag.clone(),
1588 );
1589
1590 subst_table(&mut self.inner, table_name, &mut query);
1592
1593 let null_table = NullTable {
1594 inner: self.inner,
1595 tag: Expr::new(ExprInner::Column(TableName::new(binder), tag)),
1596 };
1597
1598 Query {
1599 binder,
1600 expr: query,
1601 inner: null_table,
1602 siblings_need_random: self.siblings_need_random,
1603 }
1604 }
1605
1606 fn map<F>(self, f: F) -> Self
1607 where
1608 F: FnOnce(&T, &mut sea_query::SelectStatement),
1609 {
1610 let binder = Binder::new();
1611
1612 let mut outer = sea_query::Query::select();
1613 outer.from_subquery(self.expr, TableName::new(self.binder));
1614
1615 f(&self.inner, &mut outer);
1616
1617 let mut e = self.inner;
1618 subst_table(&mut e, TableName::new(binder), &mut outer);
1619
1620 Query {
1621 binder,
1622 expr: outer,
1623 inner: e,
1624 siblings_need_random: self.siblings_need_random,
1625 }
1626 }
1627
1628 pub fn order_by<U, F>(self, f: F) -> Self
1631 where
1632 U: Table,
1633 F: FnOnce(&T) -> (U, sea_query::Order),
1634 {
1635 self.map(|expr, select| {
1636 let (order_expr, order) = f(expr);
1637
1638 order_expr.visit(
1639 &mut |ErasedExpr(e)| {
1640 select.order_by_expr(e.render(), order.clone());
1641 },
1642 VisitTableMode::All,
1643 );
1644 })
1645 }
1646
1647 pub fn filter<F>(self, f: F) -> Self
1650 where
1651 F: FnOnce(&T) -> Expr<bool>,
1652 {
1653 self.map(|expr, select| {
1654 let bool_expr = f(expr);
1655
1656 select.and_where(bool_expr.expr.render());
1657 })
1658 }
1659
1660 pub fn limit(self, n: u64) -> Self {
1661 self.map(|_expr, select| {
1662 select.limit(n);
1663 })
1664 }
1665
1666 pub fn offset(self, n: u64) -> Self {
1667 self.map(|_expr, select| {
1668 select.offset(n);
1669 })
1670 }
1671}
1672
1673impl<'scope, T> Query<T>
1674where
1675 T: MapTable<'scope> + TableHKT<Mode = NameMode>,
1676 T::InMode<ExprMode>: ForLifetimeTable + Table,
1677{
1678 pub fn each(schema: &TableSchema<T>) -> Query<T::InMode<ExprMode>> {
1680 let binder = Binder::new();
1681 let mut query = sea_query::Query::select();
1682 query.from(schema.name);
1683
1684 let mut mapper = NameToExprMapper { binder, query };
1685
1686 let expr = schema.columns.map_modes_ref(&mut mapper);
1687
1688 Query::new(binder, mapper.query, expr)
1689 }
1690}
1691
1692impl<'scope, T: TableHKT<Mode = ValueMode>> Query<T> {
1693 pub fn values(vals: impl IntoIterator<Item = T>) -> Query<T::InMode<ExprMode>>
1695 where
1696 T: MapTable<'scope>,
1697 T::InMode<ExprMode>: ForLifetimeTable + Table,
1698 {
1699 let binder = Binder::new();
1700 let mut iter = vals.into_iter();
1701
1702 let Some(first) = iter.next() else {
1703 panic!("Nein danke");
1704 };
1705
1706 let mut mapper = ExprCollectorMapper {
1707 idx: 0,
1708 table_binder: binder,
1709 columns: Vec::new(),
1710 values: Vec::new(),
1711 };
1712
1713 let result_expr = first.map_modes(&mut mapper);
1714
1715 let mut all_values = vec![mapper.values];
1716
1717 for v in iter {
1718 let mut mapper = ExprCollectorRemainingMapper { values: Vec::new() };
1719 v.map_modes(&mut mapper);
1720 all_values.push(mapper.values);
1721 }
1722
1723 let mut select = sea_query::Query::select();
1724 for (idx, col) in mapper.columns.into_iter().enumerate() {
1725 select.expr_as(sea_query::Expr::column(format!("column{}", idx + 1)), col);
1726 }
1727
1728 select.from_values(
1729 all_values
1730 .into_iter()
1731 .map(|v| sea_query::ValueTuple::Many(v)),
1732 TableName::new(binder),
1733 );
1734
1735 Query::new(binder, select, result_expr)
1736 }
1737}
1738
1739#[cfg(feature = "sqlx")]
1740impl<T: TableLoaderSqlx> Query<T> {
1741 pub async fn all(&self, pool: &mut sqlx::PgConnection) -> sqlx::Result<Vec<T::Result>> {
1743 use sea_query::PostgresQueryBuilder;
1744 use sea_query_sqlx::SqlxBinder as _;
1745 use sqlx::Row as _;
1746
1747 let (sql, values) = self.expr.build_sqlx(PostgresQueryBuilder);
1748
1749 let all = sqlx::query_with(&sql, values).fetch_all(pool).await?;
1750
1751 Ok(all
1752 .into_iter()
1753 .map(|row| {
1754 let len = row.len();
1755 let mut it = (0..len).map(|x| row.try_get_raw(x).unwrap());
1756 self.inner.load(&mut it)
1757 })
1758 .collect::<Vec<_>>())
1759 }
1760}
1761
1762#[derive(Debug)]
1763struct ErasedQuery {
1764 expr: sea_query::SelectStatement,
1765 siblings_need_random: bool,
1766}
1767
1768#[derive(bytemuck::TransparentWrapper)]
1772#[repr(transparent)]
1773pub struct ErasedExpr(ExprInner);
1774
1775#[derive(Clone)]
1776enum ExprInner {
1777 Raw(sea_query::Expr),
1778 Column(TableName, ColumnName),
1779 BinOp(
1780 Arc<dyn Fn(sea_query::SimpleExpr, sea_query::SimpleExpr) -> sea_query::SimpleExpr>,
1781 Box<ExprInner>,
1782 Box<ExprInner>,
1783 ),
1784 NOp(
1785 Arc<dyn Fn(Vec<sea_query::SimpleExpr>) -> sea_query::SimpleExpr>,
1786 Vec<ExprInner>,
1787 ),
1788}
1789
1790impl ExprInner {
1791 fn visit_mut(&mut self, f: &mut impl FnMut(&mut TableName, &mut ColumnName)) {
1792 match self {
1793 ExprInner::Column(table_name, column_name) => f(table_name, column_name),
1794 ExprInner::BinOp(_, expr_inner, expr_inner1) => {
1795 expr_inner.visit_mut(f);
1796 expr_inner1.visit_mut(f);
1797 }
1798 ExprInner::NOp(_, inners) => {
1799 for inner in inners {
1800 inner.visit_mut(f);
1801 }
1802 }
1803 ExprInner::Raw(_) => {}
1804 }
1805 }
1806
1807 fn render(&self) -> sea_query::SimpleExpr {
1808 match self {
1809 ExprInner::Raw(value) => value.clone(),
1810 ExprInner::Column(table_name, column_name) => {
1811 sea_query::Expr::column((table_name.clone(), column_name.clone()))
1812 }
1813 ExprInner::BinOp(cb, expr_inner, expr_inner1) => {
1814 cb(expr_inner.render(), expr_inner1.render())
1815 }
1816 ExprInner::NOp(cb, inners) => cb(inners.into_iter().map(|n| n.render()).collect()),
1817 }
1818 }
1819}
1820
1821#[derive(Clone)]
1824pub struct Expr<'scope, T> {
1825 expr: ExprInner,
1826 _phantom: PhantomData<(&'scope (), T)>,
1827}
1828
1829impl<'scope, T> Expr<'scope, T> {
1830 fn new(expr: ExprInner) -> Self {
1831 Self {
1832 expr,
1833 _phantom: PhantomData,
1834 }
1835 }
1836
1837 pub fn lit(value: T) -> Self
1839 where
1840 T: Into<sea_query::Value>,
1841 {
1842 Self::new(ExprInner::Raw(sea_query::Expr::value(value.into())))
1843 }
1844
1845 fn binop<U>(
1846 self,
1847 other: Self,
1848 binop: Arc<dyn Fn(sea_query::SimpleExpr, sea_query::SimpleExpr) -> sea_query::SimpleExpr>,
1849 ) -> Expr<'scope, U> {
1850 Expr::new(ExprInner::BinOp(
1851 binop,
1852 Box::new(self.expr),
1853 Box::new(other.expr),
1854 ))
1855 }
1856
1857 pub fn equals(self, other: Self) -> Expr<'scope, bool> {
1859 self.binop(
1860 other,
1861 Arc::new(|a, b| a.binary(sea_query::BinOper::Equal, b)),
1862 )
1863 }
1864
1865 fn as_erased(&self) -> &ErasedExpr {
1866 ErasedExpr::wrap_ref(&self.expr)
1867 }
1868
1869 fn as_erased_mut(&mut self) -> &mut ErasedExpr {
1870 ErasedExpr::wrap_mut(&mut self.expr)
1871 }
1872}
1873
1874pub trait DBNum {}
1875impl DBNum for i32 {}
1876impl DBNum for i64 {}
1877impl DBNum for f32 {}
1878
1879macro_rules! binop {
1880 ($name:ident, $oper:tt) => {
1881 pub fn $name(self, other: Self) -> Self {
1882 self.binop(
1883 other,
1884 Arc::new(|a, b| a.binary(sea_query::BinOper::$oper, b)),
1885 )
1886 }
1887 };
1888}
1889
1890impl<'scope, T: DBNum> Expr<'scope, T> {
1891 binop!(add, Add);
1892 binop!(sub, Sub);
1893 binop!(mul, Mul);
1894 binop!(div, Div);
1895 binop!(modulo, Mod);
1896}
1897
1898pub trait DBBool {}
1899impl DBNum for bool {}
1900
1901impl<'scope, T: DBBool> Expr<'scope, T> {
1902 binop!(and, And);
1903 binop!(or, Or);
1904}
1905
1906pub trait DBLike {}
1907impl DBLike for String {}
1908
1909impl<'scope, T: DBLike> Expr<'scope, T> {
1910 binop!(like, Like);
1911 binop!(not_like, NotLike);
1912}
1913
1914pub trait DBOrd {}
1915impl DBOrd for i32 {}
1916impl DBOrd for i64 {}
1917impl DBOrd for f32 {}
1918impl DBOrd for bool {}
1919impl DBOrd for String {}
1920
1921impl<'scope, T: DBOrd> Expr<'scope, T> {
1922 binop!(lt, SmallerThan);
1923 binop!(leq, SmallerThanOrEqual);
1924 binop!(gt, GreaterThan);
1925 binop!(geq, GreaterThanOrEqual);
1926}
1927
1928pub trait DBBit {}
1929impl DBBit for i32 {}
1930impl DBBit for i64 {}
1931
1932impl<'scope, T: DBBit> Expr<'scope, T> {
1933 binop!(bit_and, BitAnd);
1934 binop!(bit_or, BitOr);
1935 binop!(lshift, LShift);
1936 binop!(rshift, RShift);
1937}
1938
1939impl<'scope> Expr<'scope, i32> {
1940 pub fn nextval(name: &str) -> Self {
1955 Self::new(ExprInner::Raw(
1956 sea_query::Func::cust("nextval").arg(name.to_owned()).into(),
1957 ))
1958 }
1959}
1960
1961pub struct Q<'scope> {
1965 queries: Vec<(TableName, ErasedQuery)>,
1966 filters: Vec<ExprInner>,
1967 binder: Binder,
1968 _phantom: PhantomData<&'scope ()>,
1969}
1970
1971impl<'scope> Q<'scope> {
1972 pub fn q<T: ForLifetimeTable + Table>(&mut self, query: Query<T>) -> T::WithLt<'scope> {
1977 let binder = Binder::new();
1978 let name = TableName::new(binder);
1979 let (erased, mut inner) = query.erased();
1980 self.queries.push((name.clone(), erased));
1981 insert_table_name(&mut inner, name);
1982 inner.with_lt(&mut WithLtMarker {})
1983 }
1984
1985 pub fn where_<'a>(&mut self, expr: Expr<'a, bool>)
1990 where
1991 'scope: 'a,
1992 {
1993 self.filters.push(expr.expr);
1994 }
1995}
1996
1997pub fn query<'outer, T: ForLifetimeTable + Table + 'outer>(
2010 f: impl for<'scope> FnOnce(&mut Q<'scope>) -> T::WithLt<'scope>,
2011) -> Query<T> {
2012 let mut q = Q {
2013 binder: Binder::new(),
2014 filters: Vec::new(),
2015 queries: Vec::new(),
2016 _phantom: PhantomData,
2017 };
2018
2019 let mut e = f(&mut q);
2020
2021 let needs_random = q.queries.iter().any(|(_, q)| q.siblings_need_random);
2025
2026 let mut random_binders: Vec<sea_query::Expr> = Vec::new();
2027
2028 let mut insert_dummy = |mut stmt: sea_query::SelectStatement, table: &TableName| {
2029 if needs_random {
2030 stmt.expr_as(sea_query::Func::random(), "dummy");
2031
2032 for binder in &random_binders {
2033 stmt.and_where(binder.clone());
2034 }
2035
2036 random_binders
2037 .push(sea_query::Expr::column((table.clone(), "dummy".to_string())).is_not_null())
2038 }
2039 stmt
2040 };
2041
2042 let mut iter = q.queries.into_iter();
2043 let mut table = sea_query::Query::select();
2044
2045 if let Some((first_table_name, first)) = iter.next() {
2046 let expr = insert_dummy(first.expr, &first_table_name);
2047 table.from_subquery(expr, first_table_name);
2048 };
2049
2050 for (table_name, q) in iter {
2051 let expr = insert_dummy(q.expr, &table_name);
2052 table.join_lateral(
2053 sea_query::JoinType::InnerJoin,
2056 expr,
2057 table_name,
2058 sea_query::Condition::all(),
2059 );
2060 }
2061
2062 for filter in q.filters {
2063 table.and_where(filter.render());
2064 }
2065
2066 subst_table(&mut e, TableName::new(q.binder), &mut table);
2067
2068 let e = ForLifetimeTable::unwith_lt(e, &mut WithLtMarker {});
2069
2070 let mut q = Query::new(q.binder, table.to_owned(), e);
2072 q.siblings_need_random = needs_random;
2073 q
2074}
2075
2076pub struct Insert<T: TableHKT<Mode = NameMode>> {
2078 pub into: TableSchema<T>,
2080 pub rows: Query<T::InMode<ExprMode>>,
2082}
2083
2084#[cfg(feature = "sqlx")]
2085impl<T: TableHKT<Mode = NameMode>> Insert<T>
2086where
2087 T: MapTable<'static>,
2088{
2089 pub async fn run(
2091 &self,
2092 pool: &mut sqlx::PgConnection,
2093 ) -> sqlx::Result<sqlx::postgres::PgQueryResult> {
2094 use sea_query::PostgresQueryBuilder;
2095 use sea_query_sqlx::SqlxBinder as _;
2096
2097 let mut insert = sea_query::Query::insert()
2098 .into_table(self.into.name)
2099 .to_owned();
2100
2101 let mut mapper = NameCollectorMapper { names: Vec::new() };
2102 self.into.columns.map_modes_ref(&mut mapper);
2103
2104 insert.columns(mapper.names);
2105 insert.select_from(self.rows.expr.clone()).unwrap();
2106
2107 let (sql, values) = insert.build_sqlx(PostgresQueryBuilder);
2108
2109 let all = sqlx::query_with(&sql, values).execute(pool).await?;
2110
2111 Ok(all)
2112 }
2113}
2114
2115pub struct A<'inner, 'outer> {
2125 group_by: Vec<ExprInner>,
2126 _phantom: PhantomData<(&'inner (), &'outer ())>,
2127}
2128
2129impl<'inner, 'outer> A<'inner, 'outer> {
2130 pub fn group_by<T: Table + ForLifetimeTable>(&mut self, expr: T) -> T::WithLt<'outer> {
2132 expr.visit(
2133 &mut |ErasedExpr(e)| {
2134 self.group_by.push(e.clone());
2135 },
2136 VisitTableMode::All,
2137 );
2138
2139 expr.with_lt(&mut WithLtMarker::new())
2140 }
2141
2142 pub fn array_agg<T: Table + ForLifetimeTable>(
2144 &mut self,
2145 mut expr: T,
2146 ) -> ListTable<T::WithLt<'outer>> {
2147 expr.visit_mut(
2148 &mut |ErasedExpr(inner)| {
2149 *inner = ExprInner::NOp(
2150 Arc::new(|inners| {
2151 let [inner] = inners.try_into().unwrap();
2152
2153 sea_query::PgFunc::array_agg(inner).into()
2154 }),
2155 vec![inner.clone()],
2156 )
2157 },
2158 VisitTableMode::All,
2159 );
2160
2161 ListTable {
2162 inner: expr.with_lt(&mut WithLtMarker::new()),
2163 }
2164 }
2165
2166 fn simple_agg_fn<T: Table + ForLifetimeTable>(
2167 &mut self,
2168 mut expr: T,
2169 f: impl Fn(sea_query::Expr) -> sea_query::Expr + Clone + 'static,
2170 ) -> T::WithLt<'outer> {
2171 expr.visit_mut(
2172 &mut |ErasedExpr(inner)| {
2173 let f = f.clone();
2174 *inner = ExprInner::NOp(
2175 Arc::new(move |inners| {
2176 let [inner] = inners.try_into().unwrap();
2177
2178 f(inner)
2179 }),
2180 vec![inner.clone()],
2181 )
2182 },
2183 VisitTableMode::All,
2184 );
2185
2186 expr.with_lt(&mut WithLtMarker::new())
2187 }
2188
2189 pub fn avg<T: Table + ForLifetimeTable>(&mut self, expr: T) -> T::WithLt<'outer> {
2191 self.simple_agg_fn(expr, |e| e.avg())
2192 }
2193
2194 pub fn bit_and<T: Table + ForLifetimeTable>(&mut self, expr: T) -> T::WithLt<'outer> {
2196 self.simple_agg_fn(expr, |e| sea_query::Func::bit_and(e).into())
2197 }
2198
2199 pub fn bit_or<T: Table + ForLifetimeTable>(&mut self, expr: T) -> T::WithLt<'outer> {
2201 self.simple_agg_fn(expr, |e| sea_query::Func::bit_or(e).into())
2202 }
2203
2204 pub fn bit_xor<T: Table + ForLifetimeTable>(&mut self, expr: T) -> T::WithLt<'outer> {
2206 self.simple_agg_fn(expr, |e| sea_query::Func::cust("BIT_XOR").arg(e).into())
2207 }
2208
2209 pub fn bool_and<T: Table + ForLifetimeTable>(&mut self, expr: T) -> T::WithLt<'outer> {
2211 self.simple_agg_fn(expr, |e| sea_query::Func::cust("BOOL_AND").arg(e).into())
2212 }
2213
2214 pub fn bool_or<T: Table + ForLifetimeTable>(&mut self, expr: T) -> T::WithLt<'outer> {
2216 self.simple_agg_fn(expr, |e| sea_query::Func::cust("BOOL_OR").arg(e).into())
2217 }
2218
2219 pub fn count_star(&mut self) -> Expr<'outer, i32> {
2221 Expr::new(ExprInner::Raw(sea_query::Expr::cust("*").count()))
2222 }
2223
2224 pub fn count<T>(&mut self, expr: Expr<'inner, T>) -> Expr<'outer, i32> {
2226 Expr::new(ExprInner::NOp(
2227 Arc::new(|inners| {
2228 let [inner] = inners.try_into().unwrap();
2229
2230 inner.count()
2231 }),
2232 vec![expr.expr],
2233 ))
2234 }
2235
2236 pub fn count_distinct<T>(&mut self, expr: Expr<'inner, T>) -> Expr<'outer, i32> {
2238 Expr::new(ExprInner::NOp(
2239 Arc::new(|inners| {
2240 let [inner] = inners.try_into().unwrap();
2241
2242 inner.count_distinct()
2243 }),
2244 vec![expr.expr],
2245 ))
2246 }
2247
2248 pub fn max<T: Table + ForLifetimeTable>(&mut self, expr: T) -> T::WithLt<'outer> {
2250 self.simple_agg_fn(expr, |e| e.max())
2251 }
2252
2253 pub fn min<T: Table + ForLifetimeTable>(&mut self, expr: T) -> T::WithLt<'outer> {
2255 self.simple_agg_fn(expr, |e| e.min())
2256 }
2257
2258 pub fn sum<T: Table + ForLifetimeTable>(&mut self, expr: T) -> T::WithLt<'outer> {
2260 self.simple_agg_fn(expr, |e| e.sum())
2261 }
2262}
2263
2264#[derive(Clone)]
2266pub struct Over<'scope> {
2267 partitions: Vec<ExprInner>,
2268 orderings: Vec<(ExprInner, sea_query::Order)>,
2269 _phantom: PhantomData<&'scope ()>,
2270}
2271
2272impl<'scope> Over<'scope> {
2273 pub fn new() -> Self {
2275 Self {
2276 partitions: Vec::new(),
2277 orderings: Vec::new(),
2278 _phantom: PhantomData,
2279 }
2280 }
2281
2282 pub fn order_by<T: Table>(mut self, expr: T, order: sea_query::Order) -> Self {
2284 expr.visit(
2285 &mut |ErasedExpr(e)| self.orderings.push((e.clone(), order.clone())),
2286 VisitTableMode::All,
2287 );
2288 self
2289 }
2290
2291 pub fn partition_by<T: Table>(mut self, expr: T) -> Self {
2293 expr.visit(
2294 &mut |ErasedExpr(e)| self.partitions.push(e.clone()),
2295 VisitTableMode::All,
2296 );
2297 self
2298 }
2299}
2300
2301pub struct W<'inner, 'outer> {
2316 inner_query: sea_query::SelectStatement,
2319 inner_table: TableName,
2320 middle_query: sea_query::SelectStatement,
2321 middle_table: TableName,
2322 _phantom: PhantomData<(&'inner (), &'outer ())>,
2323}
2324
2325impl<'inner, 'outer> W<'inner, 'outer> {
2326 fn generic_window(&mut self, expr: sea_query::Expr, over: Over<'inner>) -> ExprInner {
2327 let mut window_statement = sea_query::WindowStatement::new();
2328
2329 for expr in over.partitions {
2330 let name = ColumnName::new(Binder::new(), "part".to_owned());
2331 self.inner_query.expr_as(expr.render(), name.clone());
2332 window_statement.partition_by((self.inner_table.clone(), name));
2333 }
2334
2335 for (expr, order) in over.orderings {
2336 let name = ColumnName::new(Binder::new(), "ord".to_owned());
2337 self.inner_query.expr_as(expr.render(), name.clone());
2338 window_statement.order_by((self.inner_table.clone(), name), order);
2339 }
2340
2341 let column = ColumnName::new(Binder::new(), "win".to_owned());
2342
2343 self.middle_query
2344 .expr_window_as(expr, window_statement, column.clone());
2345
2346 ExprInner::Column(self.middle_table.clone(), column)
2347 }
2348
2349 pub fn row_number(&mut self, over: Over<'inner>) -> Expr<'outer, i64> {
2350 Expr::new(self.generic_window(sea_query::Func::cust("row_number").into(), over))
2351 }
2352
2353 pub fn rank(&mut self, over: Over<'inner>) -> Expr<'outer, i64> {
2354 Expr::new(self.generic_window(sea_query::Func::cust("rank").into(), over))
2355 }
2356
2357 pub fn dense_rank(&mut self, over: Over<'inner>) -> Expr<'outer, i64> {
2358 Expr::new(self.generic_window(sea_query::Func::cust("dense_rank").into(), over))
2359 }
2360
2361 pub fn percent_rank(&mut self, over: Over<'inner>) -> Expr<'outer, f64> {
2362 Expr::new(self.generic_window(sea_query::Func::cust("percent_rank").into(), over))
2363 }
2364
2365 pub fn cume_dist(&mut self, over: Over<'inner>) -> Expr<'outer, f64> {
2366 Expr::new(self.generic_window(sea_query::Func::cust("cume_dist").into(), over))
2367 }
2368
2369 pub fn ntile(
2370 &mut self,
2371 num_buckets: Expr<'outer, i64>,
2372 over: Over<'inner>,
2373 ) -> Expr<'outer, f64> {
2374 Expr::new(
2375 self.generic_window(
2376 sea_query::Func::cust("ntlile")
2377 .arg(num_buckets.expr.render())
2378 .into(),
2379 over,
2380 ),
2381 )
2382 }
2383
2384 fn lag_lead_generic<T: Table + ForLifetimeTable>(
2385 &mut self,
2386 fn_: &'static str,
2387 mut value: T,
2388 offset: Option<Expr<'outer, i64>>,
2389 default: Option<T>,
2390 over: Over<'inner>,
2391 ) -> T::WithLt<'outer> {
2392 let mut default_exprs = default.as_ref().map(collect_exprs).map(|x| x.into_iter());
2393
2394 let mut window_statement = sea_query::WindowStatement::new();
2395
2396 for expr in over.partitions {
2397 let name = ColumnName::new(Binder::new(), "part".to_owned());
2398 self.inner_query.expr_as(expr.render(), name.clone());
2399 window_statement.partition_by((self.inner_table.clone(), name));
2400 }
2401
2402 for (expr, order) in over.orderings {
2403 let name = ColumnName::new(Binder::new(), "ord".to_owned());
2404 self.inner_query.expr_as(expr.render(), name.clone());
2405 window_statement.order_by((self.inner_table.clone(), name), order);
2406 }
2407
2408 subst_table(&mut value, self.inner_table.clone(), &mut self.inner_query);
2409
2410 value.visit_mut(
2411 &mut |ErasedExpr(inner)| {
2412 let offset = offset.clone();
2413 let default = default_exprs.as_mut().map(|x| x.next().unwrap());
2414
2415 let r = sea_query::Func::cust(fn_).arg(inner.clone().render());
2416 let (r, set_default) = if let Some(offset) = offset {
2417 (r.arg(offset.expr.render()), true)
2418 } else {
2419 (r, false)
2420 };
2421 let r = if let Some(default) = default {
2422 let r = if !set_default {
2423 r.arg(sea_query::Expr::value(1))
2424 } else {
2425 r
2426 };
2427 r.arg(default.render())
2428 } else {
2429 r
2430 };
2431
2432 let column = ColumnName::new(Binder::new(), "win".to_owned());
2433
2434 self.middle_query
2435 .expr_window_as(r, window_statement.clone(), column.clone());
2436
2437 *inner = ExprInner::Column(self.middle_table.clone(), column);
2438 },
2439 VisitTableMode::All,
2440 );
2441
2442 value.with_lt(&mut WithLtMarker::new())
2443 }
2444
2445 pub fn lag<T: Table + ForLifetimeTable>(
2446 &mut self,
2447 value: T,
2448 offset: Option<Expr<'outer, i64>>,
2449 default: Option<T>,
2450 over: Over<'inner>,
2451 ) -> T::WithLt<'outer> {
2452 self.lag_lead_generic("lag", value, offset, default, over)
2453 }
2454
2455 pub fn lead<T: Table + ForLifetimeTable>(
2456 &mut self,
2457 value: T,
2458 offset: Option<Expr<'outer, i64>>,
2459 default: Option<T>,
2460 over: Over<'inner>,
2461 ) -> T::WithLt<'outer> {
2462 self.lag_lead_generic("lead", value, offset, default, over)
2463 }
2464
2465 pub fn first_value<T: Table + ForLifetimeTable>(
2466 &mut self,
2467 value: T,
2468 over: Over<'inner>,
2469 ) -> T::WithLt<'outer> {
2470 self.lag_lead_generic("first_value", value, None, None, over)
2471 }
2472
2473 pub fn last_value<T: Table + ForLifetimeTable>(
2474 &mut self,
2475 value: T,
2476 over: Over<'inner>,
2477 ) -> T::WithLt<'outer> {
2478 self.lag_lead_generic("first_value", value, None, None, over)
2479 }
2480
2481 pub fn id<T: Table + ForLifetimeTable>(&mut self, mut table: T) -> T::WithLt<'outer> {
2498 subst_table(&mut table, self.inner_table.clone(), &mut self.inner_query);
2499 subst_table(
2500 &mut table,
2501 self.middle_table.clone(),
2502 &mut self.middle_query,
2503 );
2504 table.with_lt(&mut WithLtMarker::new())
2505 }
2506}
2507
2508pub mod helper_tables {
2513 use super::*;
2514 use rust_rel8_derive::TableStruct;
2515
2516 #[derive(TableStruct)]
2517 #[table(crate = "crate")]
2518 #[perfect_derive::perfect_derive(Debug, PartialEq, Clone)]
2519 pub struct One<'scope, Mode: TableMode, #[table(proxy)] A: Value> {
2521 pub a: Mode::T<'scope, A>,
2522 }
2523
2524 #[derive(TableStruct)]
2525 #[table(crate = "crate")]
2526 #[perfect_derive::perfect_derive(Debug, PartialEq, Clone)]
2527 pub struct Two<'scope, Mode: TableMode, #[table(proxy)] A: Value, #[table(proxy)] B: Value> {
2529 pub a: Mode::T<'scope, A>,
2530 pub b: Mode::T<'scope, B>,
2531 }
2532
2533 #[derive(TableStruct)]
2534 #[table(crate = "crate")]
2535 #[perfect_derive::perfect_derive(Debug, PartialEq, Clone)]
2536 pub struct Three<
2538 'scope,
2539 Mode: TableMode,
2540 #[table(proxy)] A: Value,
2541 #[table(proxy)] B: Value,
2542 #[table(proxy)] C: Value,
2543 > {
2544 pub a: Mode::T<'scope, A>,
2545 pub b: Mode::T<'scope, B>,
2546 pub c: Mode::T<'scope, C>,
2547 }
2548}
2549
2550pub mod helper_utilities {
2551 use std::{collections::HashMap, hash::Hash};
2552
2553 pub trait ShortenLifetime {
2555 type Shortened<'small>
2556 where
2557 Self: 'small;
2558
2559 fn shorten_lifetime<'small, 'large: 'small>(self) -> Self::Shortened<'small>
2566 where
2567 Self: 'large;
2568 }
2569
2570 impl<T: ShortenLifetime, const N: usize> ShortenLifetime for [T; N] {
2571 type Shortened<'small>
2572 = [T::Shortened<'small>; N]
2573 where
2574 Self: 'small;
2575
2576 fn shorten_lifetime<'small, 'large: 'small>(self) -> Self::Shortened<'small>
2577 where
2578 Self: 'large,
2579 {
2580 self.map(ShortenLifetime::shorten_lifetime)
2581 }
2582 }
2583
2584 impl<T: ShortenLifetime> ShortenLifetime for Vec<T> {
2585 type Shortened<'small>
2586 = Vec<T::Shortened<'small>>
2587 where
2588 Self: 'small;
2589
2590 fn shorten_lifetime<'small, 'large: 'small>(self) -> Self::Shortened<'small>
2591 where
2592 Self: 'large,
2593 {
2594 self.into_iter()
2595 .map(ShortenLifetime::shorten_lifetime)
2596 .collect::<Vec<_>>()
2597 }
2598 }
2599
2600 impl<K: Hash + Eq, T: ShortenLifetime> ShortenLifetime for HashMap<K, T> {
2601 type Shortened<'small>
2602 = HashMap<K, T::Shortened<'small>>
2603 where
2604 Self: 'small;
2605
2606 fn shorten_lifetime<'small, 'large: 'small>(self) -> Self::Shortened<'small>
2607 where
2608 Self: 'large,
2609 {
2610 self.into_iter()
2611 .map(|(k, v)| (k, v.shorten_lifetime()))
2612 .collect::<HashMap<_, _>>()
2613 }
2614 }
2615}
2616
2617pub use helper_utilities::ShortenLifetime;
2618
2619#[cfg(feature = "derive")]
2620pub use rust_rel8_derive::TableStruct;
2621
2622use self::is_nullable::IsNullable;