Skip to main content

rust_rel8/
lib.rs

1// `rustdoc_internals` is needed for `#[doc(fake_variadics)]`
2#![allow(internal_features)]
3#![cfg_attr(any(docsrs, docsrs_dep), feature(rustdoc_internals))]
4// #![deny(missing_docs)]
5
6/*!
7Welcome to Rust Rel8
8
9This is a port of Haskell's excellent
10[Rel8](https://rel8.readthedocs.io/en/latest/cookbook.html) library which
11provides a type safe and expressive interface for constructing SQL queries.
12
13Unlike other ORMs and query builders, this library does not provide a
14builder pattern on top of the AST for a SQL query, but instead allows you
15to write queries as if the tables themselves were just arrays in rust.
16
17# Overview
18
19The fundamental pieces of this crate are:
20
21 * [`Query<T>`]: A sql query which produces rows of type `T`.
22
23   The simplest usage is [`Query::each`] and [`Query::values`] which correspond
24   to `SELECT * FROM <table>` and `SELECT * FROM (VALUES <...>)` respectively.
25
26   You can use [Query::all] to perform the query and decode the results into a `Vec<T>`.
27
28 * [Q]: A type you get from [query], it allows for queries to be composed together.
29
30 * [query]: A function which gives you [Q] in a callback, which you can use to
31   compose together an filter queries.
32
33 * [`Expr<T>`]: Some SQL expression representing a scalar value.
34
35 * [Table]: A trait representing a row, can be one of:
36
37   - [`Expr<T>`]: each `Expr<T>` can be thought of as a singleton row.
38   - `(T, ...)` where `T: Table`: A tuple of tables is itself a tuple.
39   - Your type which uses the [TableStruct] derive macro.
40
41You have probably already noticed that this library is doing a lot of type level
42magick, but you'll get the hang of it quickly.
43
44The main thing is that every time you see `T` with bounds of
45[`ForLifetimeTable`] (or `T::WithLt<'...>`), you can think of `T` as being any
46[Table]. It's just that the library needs to be able to talk about the table
47with a different lifetime.
48
49Likewise with [TableHKT], which is needed for the library to mention some user
50defined table in different [TableMode]s.
51
52*/
53
54pub 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
146/// A trait abstracting the mode of a user defined table, which allows us to
147/// talk about the same table in two different modes.
148///
149/// ```rs
150/// impl<'scope, T: Column<'scope>> TableHKT<'scope> for MyTable<'scope, T> {
151///     type InMode<Mode: Column<'scope>> = MyTable<'scope, Mode>;
152///
153///     type Mode = T;
154/// }
155/// ```
156pub trait TableHKT {
157    /// The current mode of this table.
158    type Mode: TableMode;
159
160    /// Replace the mode with another.
161    type InMode<Mode: TableMode>;
162}
163
164#[cfg(feature = "sqlx")]
165/// Proxy module allowing us to have a supertrait conditional on feature flags.
166mod value_sqlx {
167    /// Proxy trait for [sqlx::Decode] that we can switch off if not enabled
168    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"))]
173/// Proxy module allowing us to have a supertrait conditional on feature flags.
174mod value_sqlx {
175    /// Proxy trait for [sqlx::Decode] that we can switch off if not enabled
176    pub trait Value {}
177    impl<T> Value for T where T: ?Sized {}
178}
179
180pub use value_sqlx::Value as SqlxValueIfEnabled;
181
182/// This trait represents values we know to encode and decode from their database type.
183///
184/// Depending on features, this will have supertraits of the encode/decode
185/// traits of the backends.
186pub 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
190/// This trait allows us to write a mapping function between two column modes.
191///
192/// We use a trait as we need this to work for all types of the type parameter `V`.
193pub trait ModeMapper<'scope, SrcMode: TableMode, DestMode: TableMode> {
194    /// Map from `SrcMode` to `DestMode`, consuming the value.
195    fn map_mode<V>(&mut self, src: SrcMode::T<'scope, V>) -> DestMode::T<'scope, V>
196    where
197        V: Value;
198}
199
200/// This trait allows us to write a mapping function between two column modes.
201///
202/// We use a trait as we need this to work for all types of the type parameter `V`.
203pub trait ModeMapperRef<'scope, SrcMode: TableMode, DestMode: TableMode> {
204    /// Map from `SrcMode` to `DestMode`, taking the value as a reference
205    fn map_mode_ref<V>(&mut self, src: &SrcMode::T<'scope, V>) -> DestMode::T<'scope, V>
206    where
207        V: Value;
208}
209
210/// This trait allows us to write a mapping function between two column modes.
211///
212/// We use a trait as we need this to work for all types of the type parameter `V`.
213pub trait ModeMapperMut<'scope, SrcMode: TableMode, DestMode: TableMode> {
214    /// Map from `SrcMode` to `DestMode`, taking the value as a mutable reference
215    fn map_mode_mut<V>(&mut self, src: &mut SrcMode::T<'scope, V>) -> DestMode::T<'scope, V>
216    where
217        V: Value;
218}
219
220/// This trait allows us to change the mode of a table by mapping all the fields
221/// with [ModeMapper], [ModeMapperRef], or [ModeMapperMut].
222pub trait MapTable<'scope>: TableHKT {
223    /// Map each field of the table
224    ///
225    /// The order and number of fields visited must always remain the same,
226    /// across: [Table::visit], [Table::visit_mut], and all methods of [MapTable].
227    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    /// Map each field of the table, with a reference
233    ///
234    /// The order and number of fields visited must always remain the same,
235    /// across: [Table::visit], [Table::visit_mut], and all methods of [MapTable].
236    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    /// Map each field of the table, with a mutable reference
242    ///
243    /// The order and number of fields visited must always remain the same,
244    /// across: [Table::visit], [Table::visit_mut], and all methods of [MapTable].
245    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
251/// A mapper which reads the column names of a table in [NameMode] and adds them to a select,
252/// then yields an expression referencing the column.
253struct 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
345/// A mapper which visits each expression of a table in [ExprMode].
346struct 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
373/// A mapper which mutably visits each expression of a table in [ExprMode].
374struct 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")]
402/// A mapper which decodes a table from a result row, turning it from [ExprMode] to [ValueMode].
403struct 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")]
424/// A mapper which decodes a table from a result row, turning it from [ExprMode] to [ValueMode].
425struct 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")]
447/// A mapper which skips loading a table from a result row.
448struct 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
499/// Trait for tables containing values which we can turn into literals
500pub trait LitTable: TableHKT<Mode = ValueMode> {
501    /// Lift a [ValueMode] table to an [ExprMode] table
502    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
511/// A table's name and column names.
512pub struct TableSchema<Table> {
513    /// The name of the table.
514    pub name: &'static str,
515
516    /// The table columns, this should be some table in [NameMode].
517    pub columns: Table,
518}
519
520/// The modes a table can be in
521pub mod table_modes {
522    /// Name mode, where all columns are [`&'static str`], representing the column names.
523    pub enum NameMode {}
524
525    #[derive(Debug, PartialEq)]
526    /// Value mode, representing a table row that has been loaded from the query.
527    ///
528    /// This enum implements [Debug] and [PartialEq] so that your types can
529    /// derive them without a baseless failure from a type parameter not
530    /// implementing trait despite not appearing in the data type.
531    pub enum ValueMode {}
532
533    pub enum ValueManyMode {}
534
535    // /// Value mode, but the value might be null.
536    // pub enum ValueNullifiedMode {}
537
538    /// Expr mode, the columns are [crate::Expr]s.
539    pub enum ExprMode {}
540
541    // /// Expr mode, but the value might be null, the columns are [crate::Expr]s.
542    // pub enum ExprNullifiedMode {}
543
544    /// Empty mode, all fields are `()`. This is used when a mapper doesn't
545    /// want to produce a value.
546    pub enum EmptyMode {}
547}
548
549pub use table_modes::*;
550
551/// Table modes, this trait is used to switch the types of a rust structs fields.
552///
553/// You should use it in table struct like so:
554///
555/// ```rust
556/// use rust_rel8::*;
557///
558/// struct MyTable<'scope, Mode: TableMode> {
559///   id: Mode::T<'scope, i32>,
560///   name: Mode::T<'scope, String>,
561///   age: Mode::T<'scope, i32>,
562/// }
563/// ```
564pub trait TableMode {
565    /// A Gat, the resultant type may or may not incorporate `V`.
566    type T<'scope, V>;
567}
568
569impl TableMode for NameMode {
570    /// a string representing the column name.
571    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)]
592/// A wrapper which implements [Table] for any type implementing [MapTable] in [ExprMode].
593pub 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    // sorry
652    <<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/// How to visit the columns in a table
682#[derive(Debug, Copy, Clone)]
683pub enum VisitTableMode {
684    /// Visit all the columns in the table
685    All,
686    /// Visit only the non-nullable columns in the table
687    NonNull,
688}
689
690/// A trait that represents a database result row.
691///
692/// If you implement [Table] on your type, you must also implement [ForLifetimeTable].
693pub trait Table {
694    /// The value a row of this table has when loaded from the database.
695    type Result;
696
697    /// Visit each expr in the table.
698    ///
699    /// The order and number of expressions visited must always remain the same,
700    /// across: [Table::visit], [Table::visit_mut], and all methods of [MapTable].
701    fn visit(&self, f: &mut impl FnMut(&ErasedExpr), mode: VisitTableMode);
702
703    /// Visit each expr in the table, with a mutable reference.
704    ///
705    /// The order and number of expressions visited must always remain the same,
706    /// across: [Table::visit], [Table::visit_mut], and all methods of [MapTable].
707    fn visit_mut(&mut self, f: &mut impl FnMut(&mut ErasedExpr), mode: VisitTableMode);
708}
709
710#[cfg(feature = "sqlx")]
711/// Trait allowing loading of [Table]s when using sqlx.
712pub trait TableLoaderSqlx: Table {
713    /// Load the table given an iterator over a row's values
714    fn load<'a>(
715        &self,
716        values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>,
717    ) -> Self::Result;
718
719    /// discard N columns from the iterator ofer a row
720    /// This is used when this value was discarded by a [MaybeTable].
721    fn skip<'a>(&self, values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>);
722}
723
724#[cfg(feature = "sqlx")]
725/// Trait allowing loading of many [Table]s when using sqlx.
726pub trait TableLoaderManySqlx: Table + TableLoaderSqlx {
727    /// Load the table given an iterator over a vec of row's values
728    fn load_many<'a>(
729        &self,
730        values: &mut impl Iterator<Item = sqlx::postgres::PgValueRef<'a>>,
731    ) -> Vec<Self::Result>;
732}
733
734/// attach each of the tables columns to the select, and renames the table to
735/// use the new names.
736///
737/// This embeds expressions, so after this the table contains only Column exprs.
738fn 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
761// not sure if we should do this by having `q` wrap the query and `subst_table` everything, or this
762fn 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/// Private type used to restrict calls of [ForLifetimeTable::with_lt] to the
797/// library.
798#[non_exhaustive]
799pub struct WithLtMarker {}
800
801impl WithLtMarker {
802    fn new() -> Self {
803        Self {}
804    }
805}
806
807/// A helper trait that allows us to talk about a [Table] with different
808/// lifetimes. Conceptually it is a type level function of `lt -> T where T:
809/// Table`.
810///
811/// If you implement [Table] on your type, you must also implement [ForLifetimeTable].
812pub trait ForLifetimeTable {
813    /// Substitute the lifetime of this table with `'lt`.
814    type WithLt<'lt>: ForLifetimeTable + Table + Sized;
815
816    /// Coerce the lifetime of this table. This is used internally by the library.
817    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
1018/// A table which contains a tag indicating whether a query returned rows.
1019/// Use [Query::optional] to construct this.
1020pub struct MaybeTable<'scope, T> {
1021    tag: Expr<'scope, Option<bool>>,
1022    inner: T,
1023}
1024
1025impl<'scope, T: Table> MaybeTable<'scope, T> {
1026    /// Project out an expression from the maybe table
1027    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    /// Test if the table is None, if it is, use the `fallback`, otherwise call
1045    /// `f`.
1046    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        // the tag
1147        values.next().unwrap();
1148        self.inner.skip(values);
1149    }
1150}
1151
1152/// A table wrapping another. This table's rows are assumed null if any of the
1153/// non-nullable columns in `T` are null.
1154///
1155/// Use [Query::nullable] to construct this.
1156pub struct NullTable<'scope, T> {
1157    // nulltable still has a tag, but it is derived from the non-null columns of
1158    // inner
1159    tag: Expr<'scope, Option<bool>>,
1160    inner: T,
1161}
1162
1163impl<'scope, T: Table> NullTable<'scope, T> {
1164    /// Project out an expression from the null table
1165    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    /// Test if the table is None, if it is, use the `fallback`, otherwise call
1175    /// `f`.
1176    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        // the tag
1277        values.next().unwrap();
1278        self.inner.skip(values);
1279    }
1280}
1281
1282/// A table representing an array aggregation.
1283///
1284/// Use [Query::many] or [Query::aggregate] to construct this.
1285pub 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/// A value representing a sql select statement which produces rows of type `T`.
1351#[derive(Clone)]
1352pub struct Query<T> {
1353    // Unique ID used to make the table name and columns unique
1354    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    /// Enter a context in which [A] can be used to build aggregations.
1393    ///
1394    /// The callback `f` will receive an [A], the methods of which can be used
1395    /// to build a table in the `'outer` scope.
1396    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    /// Construct a simple list aggregation for this query.
1426    ///
1427    /// That is, all rows of this query will be aggregated into an array.
1428    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    /// Enter a context in which [W] can be used to insert expressions using window functions.
1455    ///
1456    /// The callback `f` will receive an `F`, the methods of which can be used
1457    /// to build a table in the `'outer` scope.
1458    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    /// Lift a table into a query which ensures side effects happen and are not shared.
1495    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    /// Transform this query into one which produces rows of either [`Some<T>`] or [None].
1503    ///
1504    /// That is, this turns the query into a left join.
1505    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        // important: the tag must be the first column
1530        filler.expr_as(
1531            sea_query::Expr::column((table_name.clone(), tag.clone())),
1532            tag.clone(),
1533        );
1534
1535        // the rest can come later
1536        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    /// Make this table nullable. Unlike [MaybeTable], this isn't a left join,
1555    /// but instead considers the table null if any of the non-nullable columns
1556    /// are null.
1557    ///
1558    /// If the table only contains `Option<T>` then this table cannot distinguish.
1559    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        // important: the tag must be the first column
1585        query.expr_as(
1586            sea_query::Expr::column((table_name.clone(), tag.clone())),
1587            tag.clone(),
1588        );
1589
1590        // the rest can come later
1591        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    /// Add an order by clause to the query, the given function should return a
1629    /// table, the query will be ordered by each column of the table.
1630    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    /// Filter the results of this query. This is analagous to [Q::where_], but
1648    /// allows for chained usage.
1649    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    /// Given a [TableSchema], build a query that selects all columns of every row.
1679    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    /// Construct a query yielding the given rows
1694    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    /// Load all rows of the query
1742    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/// A publicly exposed opaque type that is used by [Table::visit] and
1769/// [Table::visit_mut]. Its purpose is to allow you to store [Expr]s in your
1770/// types which implement the [Table] trait.
1771#[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/// A type representing an expression in the query, can be passed around on the
1822/// rust side to wire things up
1823#[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    /// Construct a literal value from any value from any value that can be encoded.
1838    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    /// SQL equality
1858    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    /// generate `nextval('name')`, this must be used within [`Query::evaluate`]
1941    /// for it to behave properly.
1942    ///
1943    /// # Example
1944    ///
1945    /// ```rust
1946    /// use rust_rel8::{helper_tables::One, *};
1947    ///
1948    /// query::<(Expr<i32>, Expr<i32>)>(|q| {
1949    ///   let id = q.q(Query::evaluate(Expr::nextval("table_id_seq")));
1950    ///   let v = q.q(Query::values([1, 2, 3].map(|a| One { a })));
1951    ///   (id, v.a)
1952    /// });
1953    /// ```
1954    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
1961/// An opaque value you can use to compose together queries.
1962///
1963/// To get a value of this type, use [query].
1964pub 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    /// Bind a query and give you a value representing each row it produces.
1973    ///
1974    /// The `'scope` lifetime prevents this value leaking out of its context,
1975    /// which would result in invalid queries.
1976    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    /// Introduce a where clause for this query.
1986    ///
1987    /// If you introduce a clause that looks like `a.id = b.a_id` then you
1988    /// effectively create an inner join.
1989    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
1997/// Open a context allowing you to manipulate a query.
1998///
1999/// Inside you can use [`Q::q`] on as many [`Query<T>`] values as you wish, the
2000/// result of each call can be thought of as each value the query yields.
2001///
2002/// You can think of this as cross joining each query together, to create inner
2003/// joins or left joins, simply use [Q::where_] or [`Query<T>::optional`]
2004/// respectively.
2005///
2006/// Unfortunately, rustc isn't able to infer the return type of this function as
2007/// there seems to be no good way to express that `T::WithLt<'a>` is the same type
2008/// as `T::WithLt<'b>` modulo lifetimes.
2009pub 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    // if one of the selects needs the parents to have dummy columns to prevent
2022    // postgres evaluating it only once, we add to each query a `random() as dummy`.
2023    // Then, in those selects needing them,
2024    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            // normally a cross join, but sea_query doesn't support omitting the `ON` for cross joins (:
2054            // and CROSS JOIN is INNER JOIN ON TRUE
2055            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    // if we needed to add random calls, so do parents
2071    let mut q = Query::new(q.binder, table.to_owned(), e);
2072    q.siblings_need_random = needs_random;
2073    q
2074}
2075
2076/// Construct an insert statement, the result of the query `rows` will be inserted into `into`.
2077pub struct Insert<T: TableHKT<Mode = NameMode>> {
2078    /// The table to insert the rows into.
2079    pub into: TableSchema<T>,
2080    /// Query producing the rows to insert.
2081    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    /// Run the insert statement
2090    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
2115/// A struct allowing manipulation of an aggregation
2116///
2117/// # Lifetimes
2118///
2119/// The `'inner` lifetime represents the lifetime of the query you are aggregating on.
2120/// The `'outer` lifetime represents the lifetime of the aggregation query being build.
2121///
2122/// The two are separate to ensure that any expression in the output table is
2123/// either used in an aggregation function, or part of a group by clause.
2124pub struct A<'inner, 'outer> {
2125    group_by: Vec<ExprInner>,
2126    _phantom: PhantomData<(&'inner (), &'outer ())>,
2127}
2128
2129impl<'inner, 'outer> A<'inner, 'outer> {
2130    /// Group the aggregation by the given table.
2131    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    /// Aggregate rows of the given table into an array
2143    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    /// Average the values of this table in the group.
2190    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    /// Bit and the values of this table in the group.
2195    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    /// Bit or the values of this table in the group.
2200    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    /// Bit xor the values of this table in the group.
2205    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    /// Boolean and the values of this table in the group.
2210    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    /// Boolean or the values of this table in the group.
2215    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    /// Count the number of rows in the group, including nulls.
2220    pub fn count_star(&mut self) -> Expr<'outer, i32> {
2221        Expr::new(ExprInner::Raw(sea_query::Expr::cust("*").count()))
2222    }
2223
2224    /// Count the number of rows in the group, excluding where the table is null.
2225    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    /// Count the distinct number of rows in the group, excluding where the table is null.
2237    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    /// The maximum value of each column of this table in its group.
2249    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    /// The minimum value of each column of this table in its group.
2254    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    /// The summation of the values of each column of this table in its group.
2259    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/// A struct representing an `OVER` used by a window function.
2265#[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    /// Create a new [Over] for use with [W] in [Query::window]
2274    pub fn new() -> Self {
2275        Self {
2276            partitions: Vec::new(),
2277            orderings: Vec::new(),
2278            _phantom: PhantomData,
2279        }
2280    }
2281
2282    /// Add an `ORDER BY` clause to this `OVER`
2283    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    /// Add a `PARTITION BY` clause to this `OVER`
2292    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
2301/// A struct allowing insertion of window functions
2302///
2303/// # Lifetimes
2304///
2305/// The `'inner` lifetime represents the lifetime of the query you are starting with.
2306/// The `'outer` lifetime represents the lifetime of the the new query containing the window function expressions.
2307///
2308/// Ideally this would not be used and you would just use something like
2309/// `Expr::row_number().over(...)`, but the query builder being used requires
2310/// that `PARTITION BY` takes only column names, therefore to support any
2311/// arbitrary expression we need to place everything into a subquery in which we
2312/// just alias all expressions to single tables.
2313///
2314/// If you have a table in the `'inner` scope, you can freely use [W::id] to bring it to `'outer`.
2315pub struct W<'inner, 'outer> {
2316    // inner select, starts empty. when consuming a partition, or by use of
2317    // `id`, we add the contained expressions to this table.
2318    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    // needs some thought
2482    // pub fn nth_value<T: Table>(
2483    //     &mut self,
2484    //     value: T,
2485    //     offset: Option<Expr<'outer, i64>>,
2486    //     over: Over<'inner>,
2487    // ) -> NullTable {
2488    //     self.lag_lead_generic("lag", value, offset, None, over)
2489    // }
2490
2491    /// Bring a table in the `'inner` scope to the `'outer` scope.
2492    ///
2493    /// Ideally this wouldn't be needed, but the sql builder used internally
2494    /// doesn't support arbitrary expressions in window function partitions, so
2495    /// we have to move everything into a subquery. This function is then used
2496    /// to reselect the input table from this subquery.
2497    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
2508/// A set of helper tables that are equivalent to tuples.
2509///
2510/// We need these as an alternative to just tuples in order to be parameterised
2511/// by the [TableMode].
2512pub 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    /// A helper table with one field.
2520    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    /// A helper table with two fields.
2528    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    /// A helper table with three fields.
2537    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    /// A helper trait which implements `shorten_lifetime` for some common wrapper types.
2554    pub trait ShortenLifetime {
2555        type Shortened<'small>
2556        where
2557            Self: 'small;
2558
2559        /// Shorten a lifetime, normally rust does this automatically, but if
2560        /// the lifetime is invariant due to being used in a Gat or trait, we
2561        /// need to do it manually.
2562        ///
2563        /// If rust complains about a lifetime being invariant, you should call
2564        /// this method at the use site where the lifetime error is generated.
2565        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;