Skip to main content

drizzle_postgres/builder/
select.rs

1//! `SELECT` builder states and clause methods.
2//!
3//! [`SelectBuilder`] is the builder returned by `QueryBuilder::select`. Its
4//! state parameter only allows clauses in SQL order: `FROM`, joins, `WHERE`,
5//! `GROUP BY`, `HAVING`, `ORDER BY`, `LIMIT`, `OFFSET`, then row locks.
6
7use crate::common::PostgresSchemaType;
8use crate::helpers;
9use crate::traits::PostgresTable;
10use crate::values::PostgresValue;
11use core::marker::PhantomData;
12use drizzle_core::ToSQL;
13use drizzle_core::traits::SQLTable;
14use pastey::paste;
15
16// Import the ExecutableState trait
17use super::ExecutableState;
18
19//------------------------------------------------------------------------------
20// Type State Markers
21//------------------------------------------------------------------------------
22
23pub use drizzle_core::builder::{
24    SelectFromSet, SelectGroupSet, SelectInitial, SelectJoinSet, SelectLimitSet, SelectOffsetSet,
25    SelectOrderSet, SelectSetOpSet, SelectWhereSet,
26};
27
28/// Clause gate for SELECT methods whose names collide with INSERT/UPDATE/DELETE
29/// builder methods on the shared `QueryBuilder` type.
30///
31/// Coherence can only rule out overlapping inherent impls through a trait
32/// local to this crate, so these clauses use this trait instead of
33/// [`drizzle_core::ClauseAllowed`].
34#[doc(hidden)]
35#[diagnostic::on_unimplemented(
36    message = "builder state `{Self}` does not allow `{C}`",
37    label = "not available at this point of the query",
38    note = "SELECT clauses go in order: FROM, JOIN, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET",
39    note = "only a SELECT can be a set operand, a subquery, a derived table, or an INSERT source"
40)]
41pub trait SelectClause<C> {}
42
43impl SelectClause<drizzle_core::clause::Where> for SelectFromSet {}
44impl SelectClause<drizzle_core::clause::Where> for SelectJoinSet {}
45impl SelectClause<drizzle_core::clause::OrderBy> for SelectFromSet {}
46impl SelectClause<drizzle_core::clause::OrderBy> for SelectJoinSet {}
47impl SelectClause<drizzle_core::clause::OrderBy> for SelectWhereSet {}
48impl SelectClause<drizzle_core::clause::OrderBy> for SelectGroupSet {}
49// `SelectSetOpSet` takes no plain ORDER BY: a compound query orders by its
50// output columns, which the dedicated `order_by` on that state renders.
51
52/// Builder state after a row-locking clause (`FOR UPDATE`, `FOR SHARE`, ...).
53///
54/// Only `.nowait()` and `.skip_locked()` can follow.
55#[derive(Debug, Clone, Copy, Default)]
56pub struct SelectForSet;
57
58//------------------------------------------------------------------------------
59// Join macros (generates all join variants)
60//------------------------------------------------------------------------------
61
62#[doc(hidden)]
63macro_rules! join_impl {
64    () => {
65        join_impl!(@natural natural, Join::new().natural(), drizzle_core::InnerJoin);
66        join_impl!(@natural natural_left, Join::new().natural().left(), drizzle_core::LeftJoin);
67        join_impl!(left, Join::new().left(), drizzle_core::LeftJoin);
68        join_impl!(left_outer, Join::new().left().outer(), drizzle_core::LeftJoin);
69        join_impl!(@natural natural_left_outer, Join::new().natural().left().outer(), drizzle_core::LeftJoin);
70        join_impl!(@natural natural_right, Join::new().natural().right(), drizzle_core::RightJoin);
71        join_impl!(right, Join::new().right(), drizzle_core::RightJoin);
72        join_impl!(right_outer, Join::new().right().outer(), drizzle_core::RightJoin);
73        join_impl!(@natural natural_right_outer, Join::new().natural().right().outer(), drizzle_core::RightJoin);
74        join_impl!(@natural natural_full, Join::new().natural().full(), drizzle_core::FullJoin);
75        join_impl!(full, Join::new().full(), drizzle_core::FullJoin);
76        join_impl!(full_outer, Join::new().full().outer(), drizzle_core::FullJoin);
77        join_impl!(@natural natural_full_outer, Join::new().natural().full().outer(), drizzle_core::FullJoin);
78        join_impl!(inner, Join::new().inner(), drizzle_core::InnerJoin);
79        // USING variants only for non-natural, non-cross joins
80        join_using_impl!(left, drizzle_core::LeftJoin);
81        join_using_impl!(left_outer, drizzle_core::LeftJoin);
82        join_using_impl!(right, drizzle_core::RightJoin);
83        join_using_impl!(right_outer, drizzle_core::RightJoin);
84        join_using_impl!(full, drizzle_core::FullJoin);
85        join_using_impl!(full_outer, drizzle_core::FullJoin);
86        join_using_impl!(inner, drizzle_core::InnerJoin);
87        join_using_impl!(); // Plain JOIN
88    };
89    (@natural $type:ident, $join_expr:expr, $kind:ty) => {
90        paste! {
91            /// Adds a `NATURAL` join of the kind named by the method.
92            ///
93            /// The database joins on every column name both sides share, so
94            /// this takes only a table or other source, with no `ON` condition.
95            #[allow(clippy::type_complexity)]
96            pub fn [<$type _join>]<J: crate::helpers::JoinSource<'a>>(
97                self,
98                source: J,
99            ) -> SelectBuilder<'a, S, SelectJoinSet, J::JoinedTable, <M as drizzle_core::JoinStep<R, J::JoinedTable, $kind>>::Marker, <M as drizzle_core::JoinStep<R, J::JoinedTable, $kind>>::Row, G>
100            where
101                M: drizzle_core::JoinStep<R, J::JoinedTable, $kind>,
102            {
103                use drizzle_core::{Join, ToSQL};
104                SelectBuilder {
105                    sql: self
106                        .sql
107                        .append($join_expr.to_sql())
108                        .append(drizzle_core::SQL::raw(" "))
109                        .append(source.into_join_source_sql()),
110                    schema: PhantomData,
111                    state: PhantomData,
112                    table: PhantomData,
113                    marker: PhantomData,
114                    row: PhantomData,
115                    grouped: PhantomData,
116                }
117            }
118        }
119    };
120    ($type:ident, $join_expr:expr, $kind:ty) => {
121        paste! {
122            /// Adds a join of the kind named by the method, with an `ON` condition.
123            ///
124            /// Pass `(source, condition)`, or a bare table to join on its
125            /// foreign key to the previous table. An outer join makes the
126            /// columns of its nullable side (the joined source for `LEFT`,
127            /// the earlier sources for `RIGHT`, both for `FULL`) decode as
128            /// `Option`.
129            pub fn [<$type _join>]<J: crate::helpers::JoinArg<'a, T, Via>, Via>(
130                self,
131                arg: J,
132            ) -> SelectBuilder<'a, S, SelectJoinSet, J::JoinedTable, <M as drizzle_core::JoinStep<R, J::JoinedTable, $kind, J::OnSources>>::Marker, <M as drizzle_core::JoinStep<R, J::JoinedTable, $kind, J::OnSources>>::Row, G>
133            where
134                M: drizzle_core::JoinStep<R, J::JoinedTable, $kind, J::OnSources>,
135            {
136                use drizzle_core::Join;
137                SelectBuilder {
138                    sql: self.sql.append(arg.into_join_sql($join_expr)),
139                    schema: PhantomData,
140                    state: PhantomData,
141                    table: PhantomData,
142                    marker: PhantomData,
143                    row: PhantomData,
144                    grouped: PhantomData,
145                }
146            }
147        }
148    };
149}
150
151macro_rules! join_using_impl {
152    () => {
153        /// Adds `JOIN table USING (columns)`, joining on equal values of
154        /// same-named columns.
155        ///
156        /// `columns` is rendered as given, and `PostgreSQL` requires bare
157        /// names here: pass `SQL::ident("id")`, not a table column, which
158        /// renders qualified.
159        pub fn join_using<U: PostgresTable<'a>>(
160            self,
161            table: U,
162            columns: impl ToSQL<'a, PostgresValue<'a>>,
163        ) -> SelectBuilder<
164            'a,
165            S,
166            SelectJoinSet,
167            U,
168            <M as drizzle_core::JoinStep<R, U, drizzle_core::InnerJoin>>::Marker,
169            <M as drizzle_core::JoinStep<R, U, drizzle_core::InnerJoin>>::Row,
170            G,
171        >
172        where
173            M: drizzle_core::JoinStep<R, U, drizzle_core::InnerJoin>,
174        {
175            SelectBuilder {
176                sql: self.sql.append(helpers::join_using(table, columns)),
177                schema: PhantomData,
178                state: PhantomData,
179                table: PhantomData,
180                marker: PhantomData,
181                row: PhantomData,
182                grouped: PhantomData,
183            }
184        }
185    };
186    ($type:ident, $kind:ty) => {
187        paste! {
188            /// Adds a join of the kind named by the method, with
189            /// `USING (columns)`: joins on equal values of same-named columns.
190            ///
191            /// Pass bare column names, such as `SQL::ident("id")`; see
192            /// [`join_using`](Self::join_using).
193            pub fn [<$type _join_using>]<U: PostgresTable<'a>>(
194                self,
195                table: U,
196                columns: impl ToSQL<'a, PostgresValue<'a>>,
197            ) -> SelectBuilder<
198                'a,
199                S,
200                SelectJoinSet,
201                U,
202                <M as drizzle_core::JoinStep<R, U, $kind>>::Marker,
203                <M as drizzle_core::JoinStep<R, U, $kind>>::Row,
204                G,
205            >
206            where
207                M: drizzle_core::JoinStep<R, U, $kind>,
208            {
209                SelectBuilder {
210                    sql: self.sql.append(helpers::[<$type _join_using>](table, columns)),
211                    schema: PhantomData,
212                    state: PhantomData,
213                    table: PhantomData,
214                    marker: PhantomData,
215                    row: PhantomData,
216                    grouped: PhantomData,
217                }
218            }
219        }
220    };
221}
222
223//------------------------------------------------------------------------------
224// Capability trait impls for each state
225//------------------------------------------------------------------------------
226
227impl ExecutableState for SelectForSet {
228    type Rows<R: drizzle_core::row::RowCount> = drizzle_core::row::ZeroOrMore;
229}
230// A locking SELECT still feeds a derived table or INSERT ... SELECT, but
231// cannot be a set operand.
232impl drizzle_core::ClauseAllowed<drizzle_core::clause::Source> for SelectForSet {}
233
234//------------------------------------------------------------------------------
235// SelectBuilder Definition
236//------------------------------------------------------------------------------
237
238/// A `PostgreSQL` `SELECT` being built: a [`QueryBuilder`](super::QueryBuilder)
239/// in one of the `Select*` states.
240///
241/// `State` limits which clause can come next. `Table` is the source added
242/// last (a bare-table `.join(...)` derives its `ON` condition from it).
243/// `Marker` records the selection, the FROM/JOIN scope and the sources each
244/// clause reads; `Row` is the decoded row type; `Grouped` lists the
245/// `GROUP BY` columns. With these the compiler rejects columns that are not
246/// in scope or not grouped, at the method that runs the query.
247///
248/// # Examples
249///
250/// ```rust
251/// # extern crate self as drizzle;
252/// # mod _drizzle {
253/// #     pub mod core { pub use drizzle_core::*; }
254/// #     pub mod error { pub use drizzle_core::error::*; }
255/// #     pub mod types { pub use drizzle_types::*; }
256/// #     pub mod migrations { pub use drizzle_migrations::*; }
257/// #     pub use drizzle_types::Dialect;
258/// #     pub use drizzle_types as ddl;
259/// #     pub mod postgres {
260/// #         pub mod values { pub use drizzle_postgres::values::*; }
261/// #         pub mod traits { pub use drizzle_postgres::traits::*; }
262/// #         pub mod common { pub use drizzle_postgres::common::*; }
263/// #         pub mod attrs { pub use drizzle_postgres::attrs::*; }
264/// #         pub mod builder { pub use drizzle_postgres::builder::*; }
265/// #         pub mod helpers { pub use drizzle_postgres::helpers::*; }
266/// #         pub mod expr { pub use drizzle_postgres::expr::*; }
267/// #         pub mod types { pub use drizzle_postgres::types::*; }
268/// #         #[cfg(feature = "aws-data-api")]
269/// #         pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
270/// #         pub struct Row;
271/// #         impl Row {
272/// #             pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
273/// #             pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
274/// #             pub fn len(&self) -> usize { unimplemented!() }
275/// #         }
276/// #         pub mod prelude {
277/// #             pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
278/// #             pub use drizzle_postgres::attrs::*;
279/// #             pub use drizzle_postgres::common::PostgresSchemaType;
280/// #             pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
281/// #             pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
282/// #             pub use drizzle_core::*;
283/// #         }
284/// #     }
285/// # }
286/// # pub use _drizzle::*;
287/// # pub use const_format;
288/// # fn main() {
289/// # use drizzle::postgres::prelude::*;
290/// # use drizzle::postgres::builder::QueryBuilder;
291/// # #[PostgresTable(name = "users")]
292/// # struct User {
293/// #     #[column(serial, primary)]
294/// #     id: i32,
295/// #     name: String,
296/// #     email: Option<String>,
297/// # }
298/// # #[PostgresTable(name = "posts")]
299/// # struct Post {
300/// #     #[column(serial, primary)]
301/// #     id: i32,
302/// #     #[column(references = User::id)]
303/// #     author_id: i32,
304/// #     title: String,
305/// # }
306/// # #[derive(PostgresSchema)]
307/// # struct Schema {
308/// #     user: User,
309/// #     post: Post,
310/// # }
311/// # let db = QueryBuilder::new::<Schema>();
312/// # let Schema { user, post } = Schema::new();
313/// use drizzle::core::desc;
314/// use drizzle::core::expr::eq;
315///
316/// let query = db
317///     .select((user.id, user.name))
318///     .from(user)
319///     .r#where(eq(user.name, "Alice"))
320///     .order_by(desc(user.id))
321///     .limit(10)
322///     .offset(20);
323/// assert_eq!(
324///     query.to_sql().sql(),
325///     r#"SELECT "users"."id", "users"."name" FROM "users" WHERE "users"."name" = $1 ORDER BY "users"."id" DESC LIMIT $2 OFFSET $3"#
326/// );
327/// # }
328/// ```
329pub type SelectBuilder<'a, Schema, State, Table = (), Marker = (), Row = (), Grouped = ()> =
330    super::QueryBuilder<'a, Schema, State, Table, Marker, Row, Grouped>;
331
332//------------------------------------------------------------------------------
333// Initial State: .from()
334//------------------------------------------------------------------------------
335
336impl<'a, S, M> SelectBuilder<'a, S, SelectInitial, (), M> {
337    /// Sets the `FROM` source: a table, a view, an aliased table, a derived
338    /// table (`.alias(...)`), or a CTE.
339    ///
340    /// # Examples
341    ///
342    /// ```rust
343    /// # extern crate self as drizzle;
344    /// # mod _drizzle {
345    /// #     pub mod core { pub use drizzle_core::*; }
346    /// #     pub mod error { pub use drizzle_core::error::*; }
347    /// #     pub mod types { pub use drizzle_types::*; }
348    /// #     pub mod migrations { pub use drizzle_migrations::*; }
349    /// #     pub use drizzle_types::Dialect;
350    /// #     pub use drizzle_types as ddl;
351    /// #     pub mod postgres {
352    /// #         pub mod values { pub use drizzle_postgres::values::*; }
353    /// #         pub mod traits { pub use drizzle_postgres::traits::*; }
354    /// #         pub mod common { pub use drizzle_postgres::common::*; }
355    /// #         pub mod attrs { pub use drizzle_postgres::attrs::*; }
356    /// #         pub mod builder { pub use drizzle_postgres::builder::*; }
357    /// #         pub mod helpers { pub use drizzle_postgres::helpers::*; }
358    /// #         pub mod expr { pub use drizzle_postgres::expr::*; }
359    /// #         pub mod types { pub use drizzle_postgres::types::*; }
360    /// #         #[cfg(feature = "aws-data-api")]
361    /// #         pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
362    /// #         pub struct Row;
363    /// #         impl Row {
364    /// #             pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
365    /// #             pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
366    /// #             pub fn len(&self) -> usize { unimplemented!() }
367    /// #         }
368    /// #         pub mod prelude {
369    /// #             pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
370    /// #             pub use drizzle_postgres::attrs::*;
371    /// #             pub use drizzle_postgres::common::PostgresSchemaType;
372    /// #             pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
373    /// #             pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
374    /// #             pub use drizzle_core::*;
375    /// #         }
376    /// #     }
377    /// # }
378    /// # pub use _drizzle::*;
379    /// # pub use const_format;
380    /// # fn main() {
381    /// # use drizzle::postgres::prelude::*;
382    /// # use drizzle::postgres::builder::QueryBuilder;
383    /// # #[PostgresTable(name = "users")]
384    /// # struct User {
385    /// #     #[column(serial, primary)]
386    /// #     id: i32,
387    /// #     name: String,
388    /// #     email: Option<String>,
389    /// # }
390    /// # #[PostgresTable(name = "posts")]
391    /// # struct Post {
392    /// #     #[column(serial, primary)]
393    /// #     id: i32,
394    /// #     #[column(references = User::id)]
395    /// #     author_id: i32,
396    /// #     title: String,
397    /// # }
398    /// # #[derive(PostgresSchema)]
399    /// # struct Schema {
400    /// #     user: User,
401    /// #     post: Post,
402    /// # }
403    /// # let db = QueryBuilder::new::<Schema>();
404    /// # let Schema { user, post } = Schema::new();
405    /// let query = db.select(()).from(user);
406    /// assert_eq!(
407    ///     query.to_sql().sql(),
408    ///     r#"SELECT "users"."id", "users"."name", "users"."email" FROM "users""#
409    /// );
410    /// # }
411    /// ```
412    #[inline]
413    #[allow(clippy::type_complexity)]
414    pub fn from<T>(
415        self,
416        query: T,
417    ) -> SelectBuilder<
418        'a,
419        S,
420        SelectFromSet,
421        T,
422        drizzle_core::FromMarker<M, T>,
423        <M as drizzle_core::ResolveRow<T>>::Row,
424    >
425    where
426        T: ToSQL<'a, PostgresValue<'a>> + drizzle_core::ScopeEntry,
427        M: drizzle_core::ResolveRow<T>,
428    {
429        SelectBuilder {
430            sql: self.sql.append(helpers::from(query)),
431            schema: PhantomData,
432            state: PhantomData,
433            table: PhantomData,
434            marker: PhantomData,
435            row: PhantomData,
436            grouped: PhantomData,
437        }
438    }
439}
440
441//------------------------------------------------------------------------------
442// Capability-gated methods (generic over State)
443//------------------------------------------------------------------------------
444
445// JOIN (available from SelectFromSet and SelectJoinSet)
446impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
447where
448    State: drizzle_core::ClauseAllowed<drizzle_core::clause::Join>,
449{
450    /// Adds an inner `JOIN ... ON ...`.
451    ///
452    /// Pass `(source, condition)`, or a bare table to join on its foreign key
453    /// to the previous table. The tables the condition reads are checked
454    /// against the query's scope at compile time, where the query is run
455    /// (`.all()`, `.get()`, `.rows()`).
456    /// Other join kinds have their own methods:
457    /// `left_join`, `right_join`, `full_join`, `inner_join`, their `_outer`
458    /// forms, `natural_*` joins, `*_join_using`, and the `*_lateral` joins.
459    ///
460    /// # Examples
461    ///
462    /// ```rust
463    /// # extern crate self as drizzle;
464    /// # mod _drizzle {
465    /// #     pub mod core { pub use drizzle_core::*; }
466    /// #     pub mod error { pub use drizzle_core::error::*; }
467    /// #     pub mod types { pub use drizzle_types::*; }
468    /// #     pub mod migrations { pub use drizzle_migrations::*; }
469    /// #     pub use drizzle_types::Dialect;
470    /// #     pub use drizzle_types as ddl;
471    /// #     pub mod postgres {
472    /// #         pub mod values { pub use drizzle_postgres::values::*; }
473    /// #         pub mod traits { pub use drizzle_postgres::traits::*; }
474    /// #         pub mod common { pub use drizzle_postgres::common::*; }
475    /// #         pub mod attrs { pub use drizzle_postgres::attrs::*; }
476    /// #         pub mod builder { pub use drizzle_postgres::builder::*; }
477    /// #         pub mod helpers { pub use drizzle_postgres::helpers::*; }
478    /// #         pub mod expr { pub use drizzle_postgres::expr::*; }
479    /// #         pub mod types { pub use drizzle_postgres::types::*; }
480    /// #         #[cfg(feature = "aws-data-api")]
481    /// #         pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
482    /// #         pub struct Row;
483    /// #         impl Row {
484    /// #             pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
485    /// #             pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
486    /// #             pub fn len(&self) -> usize { unimplemented!() }
487    /// #         }
488    /// #         pub mod prelude {
489    /// #             pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
490    /// #             pub use drizzle_postgres::attrs::*;
491    /// #             pub use drizzle_postgres::common::PostgresSchemaType;
492    /// #             pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
493    /// #             pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
494    /// #             pub use drizzle_core::*;
495    /// #         }
496    /// #     }
497    /// # }
498    /// # pub use _drizzle::*;
499    /// # pub use const_format;
500    /// # fn main() {
501    /// # use drizzle::postgres::prelude::*;
502    /// # use drizzle::postgres::builder::QueryBuilder;
503    /// # #[PostgresTable(name = "users")]
504    /// # struct User {
505    /// #     #[column(serial, primary)]
506    /// #     id: i32,
507    /// #     name: String,
508    /// #     email: Option<String>,
509    /// # }
510    /// # #[PostgresTable(name = "posts")]
511    /// # struct Post {
512    /// #     #[column(serial, primary)]
513    /// #     id: i32,
514    /// #     #[column(references = User::id)]
515    /// #     author_id: i32,
516    /// #     title: String,
517    /// # }
518    /// # #[derive(PostgresSchema)]
519    /// # struct Schema {
520    /// #     user: User,
521    /// #     post: Post,
522    /// # }
523    /// # let db = QueryBuilder::new::<Schema>();
524    /// # let Schema { user, post } = Schema::new();
525    /// use drizzle::core::expr::eq;
526    ///
527    /// let query = db
528    ///     .select((user.name, post.title))
529    ///     .from(user)
530    ///     .join((post, eq(post.author_id, user.id)));
531    /// assert_eq!(
532    ///     query.to_sql().sql(),
533    ///     r#"SELECT "users"."name", "posts"."title" FROM "users" JOIN "posts" ON "posts"."author_id" = "users"."id""#
534    /// );
535    /// # }
536    /// ```
537    #[inline]
538    #[allow(clippy::type_complexity)]
539    pub fn join<J: crate::helpers::JoinArg<'a, T, Via>, Via>(
540        self,
541        arg: J,
542    ) -> SelectBuilder<
543        'a,
544        S,
545        SelectJoinSet,
546        J::JoinedTable,
547        <M as drizzle_core::JoinStep<R, J::JoinedTable, drizzle_core::InnerJoin, J::OnSources>>::Marker,
548        <M as drizzle_core::JoinStep<R, J::JoinedTable, drizzle_core::InnerJoin, J::OnSources>>::Row,
549        G,
550    >
551    where
552        M: drizzle_core::JoinStep<R, J::JoinedTable, drizzle_core::InnerJoin, J::OnSources>,
553{
554        use drizzle_core::Join;
555        SelectBuilder {
556            sql: self.sql.append(arg.into_join_sql(Join::new())),
557            schema: PhantomData,
558            state: PhantomData,
559            table: PhantomData,
560            marker: PhantomData,
561            row: PhantomData,
562            grouped: PhantomData,
563        }
564    }
565
566    join_impl!();
567
568    /// Adds a `CROSS JOIN`: every row of the left side paired with every row
569    /// of `source`.
570    ///
571    /// For backwards compatibility, `(source, condition)` is also accepted and
572    /// renders the equivalent `INNER JOIN ... ON ...`.
573    ///
574    /// # Examples
575    ///
576    /// ```rust
577    /// # extern crate self as drizzle;
578    /// # mod _drizzle {
579    /// #     pub mod core { pub use drizzle_core::*; }
580    /// #     pub mod error { pub use drizzle_core::error::*; }
581    /// #     pub mod types { pub use drizzle_types::*; }
582    /// #     pub mod migrations { pub use drizzle_migrations::*; }
583    /// #     pub use drizzle_types::Dialect;
584    /// #     pub use drizzle_types as ddl;
585    /// #     pub mod postgres {
586    /// #         pub mod values { pub use drizzle_postgres::values::*; }
587    /// #         pub mod traits { pub use drizzle_postgres::traits::*; }
588    /// #         pub mod common { pub use drizzle_postgres::common::*; }
589    /// #         pub mod attrs { pub use drizzle_postgres::attrs::*; }
590    /// #         pub mod builder { pub use drizzle_postgres::builder::*; }
591    /// #         pub mod helpers { pub use drizzle_postgres::helpers::*; }
592    /// #         pub mod expr { pub use drizzle_postgres::expr::*; }
593    /// #         pub mod types { pub use drizzle_postgres::types::*; }
594    /// #         #[cfg(feature = "aws-data-api")]
595    /// #         pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
596    /// #         pub struct Row;
597    /// #         impl Row {
598    /// #             pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
599    /// #             pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
600    /// #             pub fn len(&self) -> usize { unimplemented!() }
601    /// #         }
602    /// #         pub mod prelude {
603    /// #             pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
604    /// #             pub use drizzle_postgres::attrs::*;
605    /// #             pub use drizzle_postgres::common::PostgresSchemaType;
606    /// #             pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
607    /// #             pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
608    /// #             pub use drizzle_core::*;
609    /// #         }
610    /// #     }
611    /// # }
612    /// # pub use _drizzle::*;
613    /// # pub use const_format;
614    /// # fn main() {
615    /// # use drizzle::postgres::prelude::*;
616    /// # use drizzle::postgres::builder::QueryBuilder;
617    /// # #[PostgresTable(name = "users")]
618    /// # struct User {
619    /// #     #[column(serial, primary)]
620    /// #     id: i32,
621    /// #     name: String,
622    /// #     email: Option<String>,
623    /// # }
624    /// # #[PostgresTable(name = "posts")]
625    /// # struct Post {
626    /// #     #[column(serial, primary)]
627    /// #     id: i32,
628    /// #     #[column(references = User::id)]
629    /// #     author_id: i32,
630    /// #     title: String,
631    /// # }
632    /// # #[derive(PostgresSchema)]
633    /// # struct Schema {
634    /// #     user: User,
635    /// #     post: Post,
636    /// # }
637    /// # let db = QueryBuilder::new::<Schema>();
638    /// # let Schema { user, post } = Schema::new();
639    /// let query = db.select((user.name, post.title)).from(user).cross_join(post);
640    /// assert_eq!(
641    ///     query.to_sql().sql(),
642    ///     r#"SELECT "users"."name", "posts"."title" FROM "users" CROSS JOIN "posts""#
643    /// );
644    /// # }
645    /// ```
646    #[inline]
647    #[allow(clippy::type_complexity)]
648    pub fn cross_join<Arg: crate::helpers::CrossJoinArg<'a, T>>(
649        self,
650        arg: Arg,
651    ) -> SelectBuilder<
652        'a,
653        S,
654        SelectJoinSet,
655        Arg::JoinedTable,
656        <M as drizzle_core::JoinStep<
657            R,
658            Arg::JoinedTable,
659            drizzle_core::InnerJoin,
660            Arg::OnSources,
661        >>::Marker,
662        <M as drizzle_core::JoinStep<
663            R,
664            Arg::JoinedTable,
665            drizzle_core::InnerJoin,
666            Arg::OnSources,
667        >>::Row,
668        G,
669    >
670    where
671        M: drizzle_core::JoinStep<R, Arg::JoinedTable, drizzle_core::InnerJoin, Arg::OnSources>,
672    {
673        SelectBuilder {
674            sql: self.sql.append(arg.into_cross_join_sql()),
675            schema: PhantomData,
676            state: PhantomData,
677            table: PhantomData,
678            marker: PhantomData,
679            row: PhantomData,
680            grouped: PhantomData,
681        }
682    }
683
684    /// Adds `INNER JOIN LATERAL (subquery) AS alias ON condition`.
685    ///
686    /// A lateral subquery can refer to columns of the sources joined before
687    /// it. Pass `(derived_table, condition)`, where the derived table comes
688    /// from `.alias(tag)` on a `SELECT`.
689    #[inline]
690    #[allow(clippy::type_complexity)]
691    pub fn inner_join_lateral<J>(
692        self,
693        arg: J,
694    ) -> SelectBuilder<
695        'a,
696        S,
697        SelectJoinSet,
698        J::JoinedTable,
699        <M as drizzle_core::JoinStep<
700            R,
701            J::JoinedTable,
702            drizzle_core::Lateral<drizzle_core::InnerJoin>,
703            J::OnSources,
704        >>::Marker,
705        <M as drizzle_core::JoinStep<
706            R,
707            J::JoinedTable,
708            drizzle_core::Lateral<drizzle_core::InnerJoin>,
709            J::OnSources,
710        >>::Row,
711        G,
712    >
713    where
714        J: drizzle_core::LateralArg<'a, PostgresValue<'a>>,
715        M: drizzle_core::JoinStep<
716                R,
717                J::JoinedTable,
718                drizzle_core::Lateral<drizzle_core::InnerJoin>,
719                J::OnSources,
720            >,
721    {
722        use drizzle_core::Join;
723        SelectBuilder {
724            sql: self.sql.append(arg.into_lateral_sql(Join::new().inner())),
725            schema: PhantomData,
726            state: PhantomData,
727            table: PhantomData,
728            marker: PhantomData,
729            row: PhantomData,
730            grouped: PhantomData,
731        }
732    }
733
734    /// Adds `LEFT JOIN LATERAL (subquery) AS alias ON condition`.
735    ///
736    /// Like [`inner_join_lateral`](Self::inner_join_lateral), but keeps
737    /// left rows with no match. With `select(())` the lateral source decodes
738    /// as an `Option` of its row; an explicit column list may only read
739    /// sources joined before the lateral join.
740    #[inline]
741    #[allow(clippy::type_complexity)]
742    pub fn left_join_lateral<J, SelectionProof>(
743        self,
744        arg: J,
745    ) -> SelectBuilder<
746        'a,
747        S,
748        SelectJoinSet,
749        J::JoinedTable,
750        <M as drizzle_core::JoinStep<
751            R,
752            J::JoinedTable,
753            drizzle_core::Lateral<drizzle_core::LeftJoin>,
754            J::OnSources,
755        >>::Marker,
756        <M as drizzle_core::JoinStep<
757            R,
758            J::JoinedTable,
759            drizzle_core::Lateral<drizzle_core::LeftJoin>,
760            J::OnSources,
761        >>::Row,
762        G,
763    >
764    where
765        J: drizzle_core::LateralArg<'a, PostgresValue<'a>>,
766        M: drizzle_core::JoinStep<
767                R,
768                J::JoinedTable,
769                drizzle_core::Lateral<drizzle_core::LeftJoin>,
770                J::OnSources,
771            > + drizzle_core::LeftLateralSelection<SelectionProof>,
772    {
773        use drizzle_core::Join;
774        SelectBuilder {
775            sql: self.sql.append(arg.into_lateral_sql(Join::new().left())),
776            schema: PhantomData,
777            state: PhantomData,
778            table: PhantomData,
779            marker: PhantomData,
780            row: PhantomData,
781            grouped: PhantomData,
782        }
783    }
784
785    /// Adds `CROSS JOIN LATERAL (subquery) AS alias`, with no `ON` condition.
786    ///
787    /// The subquery runs once per left row and can refer to its columns.
788    #[inline]
789    #[allow(clippy::type_complexity)]
790    pub fn cross_join_lateral<Source>(
791        self,
792        source: Source,
793    ) -> SelectBuilder<
794        'a,
795        S,
796        SelectJoinSet,
797        Source::JoinedTable,
798        <M as drizzle_core::JoinStep<
799            R,
800            Source::JoinedTable,
801            drizzle_core::Lateral<drizzle_core::InnerJoin>,
802        >>::Marker,
803        <M as drizzle_core::JoinStep<
804            R,
805            Source::JoinedTable,
806            drizzle_core::Lateral<drizzle_core::InnerJoin>,
807        >>::Row,
808        G,
809    >
810    where
811        Source: drizzle_core::LateralSource<'a, PostgresValue<'a>>,
812        M: drizzle_core::JoinStep<
813                R,
814                Source::JoinedTable,
815                drizzle_core::Lateral<drizzle_core::InnerJoin>,
816            >,
817    {
818        SelectBuilder {
819            sql: self.sql.append(source.into_cross_lateral_sql()),
820            schema: PhantomData,
821            state: PhantomData,
822            table: PhantomData,
823            marker: PhantomData,
824            row: PhantomData,
825            grouped: PhantomData,
826        }
827    }
828}
829
830// WHERE (available from SelectFromSet and SelectJoinSet)
831impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
832where
833    State: SelectClause<drizzle_core::clause::Where>,
834{
835    /// Adds a `WHERE` condition.
836    ///
837    /// The condition must be boolean, such as `eq(...)`, `and(...)` or a
838    /// `boolean` column. Every column it uses must come from a source in
839    /// `FROM` or a join. The compiler checks this where the query is run
840    /// (`.all()`, `.get()`, `.rows()`): a column of another table fails there
841    /// with "`X` is not in this query's FROM/JOIN scope".
842    ///
843    /// # Examples
844    ///
845    /// ```rust
846    /// # extern crate self as drizzle;
847    /// # mod _drizzle {
848    /// #     pub mod core { pub use drizzle_core::*; }
849    /// #     pub mod error { pub use drizzle_core::error::*; }
850    /// #     pub mod types { pub use drizzle_types::*; }
851    /// #     pub mod migrations { pub use drizzle_migrations::*; }
852    /// #     pub use drizzle_types::Dialect;
853    /// #     pub use drizzle_types as ddl;
854    /// #     pub mod postgres {
855    /// #         pub mod values { pub use drizzle_postgres::values::*; }
856    /// #         pub mod traits { pub use drizzle_postgres::traits::*; }
857    /// #         pub mod common { pub use drizzle_postgres::common::*; }
858    /// #         pub mod attrs { pub use drizzle_postgres::attrs::*; }
859    /// #         pub mod builder { pub use drizzle_postgres::builder::*; }
860    /// #         pub mod helpers { pub use drizzle_postgres::helpers::*; }
861    /// #         pub mod expr { pub use drizzle_postgres::expr::*; }
862    /// #         pub mod types { pub use drizzle_postgres::types::*; }
863    /// #         #[cfg(feature = "aws-data-api")]
864    /// #         pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
865    /// #         pub struct Row;
866    /// #         impl Row {
867    /// #             pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
868    /// #             pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
869    /// #             pub fn len(&self) -> usize { unimplemented!() }
870    /// #         }
871    /// #         pub mod prelude {
872    /// #             pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
873    /// #             pub use drizzle_postgres::attrs::*;
874    /// #             pub use drizzle_postgres::common::PostgresSchemaType;
875    /// #             pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
876    /// #             pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
877    /// #             pub use drizzle_core::*;
878    /// #         }
879    /// #     }
880    /// # }
881    /// # pub use _drizzle::*;
882    /// # pub use const_format;
883    /// # fn main() {
884    /// # use drizzle::postgres::prelude::*;
885    /// # use drizzle::postgres::builder::QueryBuilder;
886    /// # #[PostgresTable(name = "users")]
887    /// # struct User {
888    /// #     #[column(serial, primary)]
889    /// #     id: i32,
890    /// #     name: String,
891    /// #     email: Option<String>,
892    /// # }
893    /// # #[PostgresTable(name = "posts")]
894    /// # struct Post {
895    /// #     #[column(serial, primary)]
896    /// #     id: i32,
897    /// #     #[column(references = User::id)]
898    /// #     author_id: i32,
899    /// #     title: String,
900    /// # }
901    /// # #[derive(PostgresSchema)]
902    /// # struct Schema {
903    /// #     user: User,
904    /// #     post: Post,
905    /// # }
906    /// # let db = QueryBuilder::new::<Schema>();
907    /// # let Schema { user, post } = Schema::new();
908    /// use drizzle::core::expr::{and, eq, gt};
909    ///
910    /// let query = db
911    ///     .select(user.id)
912    ///     .from(user)
913    ///     .r#where(and(eq(user.name, "Alice"), gt(user.id, 10)));
914    /// assert_eq!(
915    ///     query.to_sql().sql(),
916    ///     r#"SELECT "users"."id" FROM "users" WHERE ("users"."name" = $1 AND "users"."id" > $2)"#
917    /// );
918    /// # }
919    /// ```
920    #[inline]
921    #[allow(clippy::type_complexity)]
922    pub fn r#where<E>(
923        self,
924        condition: E,
925    ) -> SelectBuilder<
926        'a,
927        S,
928        SelectWhereSet,
929        T,
930        <M as drizzle_core::HasScope>::With<E::Sources>,
931        R,
932        G,
933    >
934    where
935        M: drizzle_core::HasScope,
936        E: drizzle_core::expr::Expr<'a, PostgresValue<'a>>,
937        E::SQLType: drizzle_core::types::BooleanLike,
938    {
939        SelectBuilder {
940            sql: self.sql.append(helpers::r#where(condition)),
941            schema: PhantomData,
942            state: PhantomData,
943            table: PhantomData,
944            marker: PhantomData,
945            row: PhantomData,
946            grouped: PhantomData,
947        }
948    }
949}
950
951// GROUP BY (available from SelectFromSet, SelectJoinSet, SelectWhereSet)
952impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
953where
954    State: drizzle_core::ClauseAllowed<drizzle_core::clause::GroupBy>,
955{
956    /// Adds a `GROUP BY` list: one expression or a tuple of them.
957    ///
958    /// Non-aggregate columns in the `SELECT` list must appear in the
959    /// `GROUP BY` list, with one exception: grouping by a table's
960    /// single-column primary key determines the whole row, so any column of
961    /// that table may be selected without being listed (`PostgreSQL` allows
962    /// this too).
963    ///
964    /// # Examples
965    ///
966    /// ```rust
967    /// # extern crate self as drizzle;
968    /// # mod _drizzle {
969    /// #     pub mod core { pub use drizzle_core::*; }
970    /// #     pub mod error { pub use drizzle_core::error::*; }
971    /// #     pub mod types { pub use drizzle_types::*; }
972    /// #     pub mod migrations { pub use drizzle_migrations::*; }
973    /// #     pub use drizzle_types::Dialect;
974    /// #     pub use drizzle_types as ddl;
975    /// #     pub mod postgres {
976    /// #         pub mod values { pub use drizzle_postgres::values::*; }
977    /// #         pub mod traits { pub use drizzle_postgres::traits::*; }
978    /// #         pub mod common { pub use drizzle_postgres::common::*; }
979    /// #         pub mod attrs { pub use drizzle_postgres::attrs::*; }
980    /// #         pub mod builder { pub use drizzle_postgres::builder::*; }
981    /// #         pub mod helpers { pub use drizzle_postgres::helpers::*; }
982    /// #         pub mod expr { pub use drizzle_postgres::expr::*; }
983    /// #         pub mod types { pub use drizzle_postgres::types::*; }
984    /// #         #[cfg(feature = "aws-data-api")]
985    /// #         pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
986    /// #         pub struct Row;
987    /// #         impl Row {
988    /// #             pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
989    /// #             pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
990    /// #             pub fn len(&self) -> usize { unimplemented!() }
991    /// #         }
992    /// #         pub mod prelude {
993    /// #             pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
994    /// #             pub use drizzle_postgres::attrs::*;
995    /// #             pub use drizzle_postgres::common::PostgresSchemaType;
996    /// #             pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
997    /// #             pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
998    /// #             pub use drizzle_core::*;
999    /// #         }
1000    /// #     }
1001    /// # }
1002    /// # pub use _drizzle::*;
1003    /// # pub use const_format;
1004    /// # fn main() {
1005    /// # use drizzle::postgres::prelude::*;
1006    /// # use drizzle::postgres::builder::QueryBuilder;
1007    /// # #[PostgresTable(name = "users")]
1008    /// # struct User {
1009    /// #     #[column(serial, primary)]
1010    /// #     id: i32,
1011    /// #     name: String,
1012    /// #     email: Option<String>,
1013    /// # }
1014    /// # #[PostgresTable(name = "posts")]
1015    /// # struct Post {
1016    /// #     #[column(serial, primary)]
1017    /// #     id: i32,
1018    /// #     #[column(references = User::id)]
1019    /// #     author_id: i32,
1020    /// #     title: String,
1021    /// # }
1022    /// # #[derive(PostgresSchema)]
1023    /// # struct Schema {
1024    /// #     user: User,
1025    /// #     post: Post,
1026    /// # }
1027    /// # let db = QueryBuilder::new::<Schema>();
1028    /// # let Schema { user, post } = Schema::new();
1029    /// use drizzle::core::expr::{count, gt};
1030    ///
1031    /// let query = db
1032    ///     .select((post.author_id, count(post.id)))
1033    ///     .from(post)
1034    ///     .group_by(post.author_id)
1035    ///     .having(gt(count(post.id), 5));
1036    /// assert_eq!(
1037    ///     query.to_sql().sql(),
1038    ///     r#"SELECT "posts"."author_id", COUNT ("posts"."id") FROM "posts" GROUP BY "posts"."author_id" HAVING COUNT ("posts"."id")> $1"#
1039    /// );
1040    /// # }
1041    /// ```
1042    #[allow(clippy::type_complexity)]
1043    pub fn group_by<Gr>(
1044        self,
1045        columns: Gr,
1046    ) -> SelectBuilder<
1047        'a,
1048        S,
1049        SelectGroupSet,
1050        T,
1051        <M as drizzle_core::HasScope>::With<Gr::Sources>,
1052        R,
1053        Gr::Columns,
1054    >
1055    where
1056        M: drizzle_core::HasScope,
1057        Gr: drizzle_core::IntoGroupBy<'a, PostgresValue<'a>>,
1058    {
1059        SelectBuilder {
1060            sql: self.sql.append(helpers::group_by_expr(columns)),
1061            schema: PhantomData,
1062            state: PhantomData,
1063            table: PhantomData,
1064            marker: PhantomData,
1065            row: PhantomData,
1066            grouped: PhantomData,
1067        }
1068    }
1069}
1070
1071// HAVING (available only from SelectGroupSet)
1072impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
1073where
1074    State: drizzle_core::ClauseAllowed<drizzle_core::clause::Having>,
1075{
1076    /// Adds a `HAVING` condition, which filters groups after `GROUP BY`.
1077    ///
1078    /// See [`group_by`](Self::group_by) for an example.
1079    #[allow(clippy::type_complexity)]
1080    pub fn having<E>(
1081        self,
1082        condition: E,
1083    ) -> SelectBuilder<
1084        'a,
1085        S,
1086        SelectGroupSet,
1087        T,
1088        <M as drizzle_core::HasScope>::With<E::Sources>,
1089        R,
1090        G,
1091    >
1092    where
1093        M: drizzle_core::HasScope,
1094        E: drizzle_core::expr::Expr<'a, PostgresValue<'a>>,
1095        E::SQLType: drizzle_core::types::BooleanLike,
1096    {
1097        SelectBuilder {
1098            sql: self.sql.append(helpers::having(condition)),
1099            schema: PhantomData,
1100            state: PhantomData,
1101            table: PhantomData,
1102            marker: PhantomData,
1103            row: PhantomData,
1104            grouped: PhantomData,
1105        }
1106    }
1107}
1108
1109// ORDER BY (available from many states)
1110impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
1111where
1112    State: SelectClause<drizzle_core::clause::OrderBy>,
1113{
1114    /// Adds `ORDER BY`.
1115    ///
1116    /// Pass a column (ascending by default), `asc(col)` / `desc(col)`, or a
1117    /// tuple of them. An array also works when every term reads the same
1118    /// table; terms over different tables go in a tuple.
1119    ///
1120    /// # Examples
1121    ///
1122    /// ```rust
1123    /// # extern crate self as drizzle;
1124    /// # mod _drizzle {
1125    /// #     pub mod core { pub use drizzle_core::*; }
1126    /// #     pub mod error { pub use drizzle_core::error::*; }
1127    /// #     pub mod types { pub use drizzle_types::*; }
1128    /// #     pub mod migrations { pub use drizzle_migrations::*; }
1129    /// #     pub use drizzle_types::Dialect;
1130    /// #     pub use drizzle_types as ddl;
1131    /// #     pub mod postgres {
1132    /// #         pub mod values { pub use drizzle_postgres::values::*; }
1133    /// #         pub mod traits { pub use drizzle_postgres::traits::*; }
1134    /// #         pub mod common { pub use drizzle_postgres::common::*; }
1135    /// #         pub mod attrs { pub use drizzle_postgres::attrs::*; }
1136    /// #         pub mod builder { pub use drizzle_postgres::builder::*; }
1137    /// #         pub mod helpers { pub use drizzle_postgres::helpers::*; }
1138    /// #         pub mod expr { pub use drizzle_postgres::expr::*; }
1139    /// #         pub mod types { pub use drizzle_postgres::types::*; }
1140    /// #         #[cfg(feature = "aws-data-api")]
1141    /// #         pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
1142    /// #         pub struct Row;
1143    /// #         impl Row {
1144    /// #             pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
1145    /// #             pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
1146    /// #             pub fn len(&self) -> usize { unimplemented!() }
1147    /// #         }
1148    /// #         pub mod prelude {
1149    /// #             pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
1150    /// #             pub use drizzle_postgres::attrs::*;
1151    /// #             pub use drizzle_postgres::common::PostgresSchemaType;
1152    /// #             pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
1153    /// #             pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
1154    /// #             pub use drizzle_core::*;
1155    /// #         }
1156    /// #     }
1157    /// # }
1158    /// # pub use _drizzle::*;
1159    /// # pub use const_format;
1160    /// # fn main() {
1161    /// # use drizzle::postgres::prelude::*;
1162    /// # use drizzle::postgres::builder::QueryBuilder;
1163    /// # #[PostgresTable(name = "users")]
1164    /// # struct User {
1165    /// #     #[column(serial, primary)]
1166    /// #     id: i32,
1167    /// #     name: String,
1168    /// #     email: Option<String>,
1169    /// # }
1170    /// # #[PostgresTable(name = "posts")]
1171    /// # struct Post {
1172    /// #     #[column(serial, primary)]
1173    /// #     id: i32,
1174    /// #     #[column(references = User::id)]
1175    /// #     author_id: i32,
1176    /// #     title: String,
1177    /// # }
1178    /// # #[derive(PostgresSchema)]
1179    /// # struct Schema {
1180    /// #     user: User,
1181    /// #     post: Post,
1182    /// # }
1183    /// # let db = QueryBuilder::new::<Schema>();
1184    /// # let Schema { user, post } = Schema::new();
1185    /// use drizzle::core::{asc, desc};
1186    ///
1187    /// let query = db
1188    ///     .select(user.name)
1189    ///     .from(user)
1190    ///     .order_by([asc(user.name), desc(user.id)]);
1191    /// assert_eq!(
1192    ///     query.to_sql().sql(),
1193    ///     r#"SELECT "users"."name" FROM "users" ORDER BY "users"."name" ASC, "users"."id" DESC"#
1194    /// );
1195    /// # }
1196    /// ```
1197    #[inline]
1198    pub fn order_by<TOrderBy>(
1199        self,
1200        expressions: TOrderBy,
1201    ) -> SelectBuilder<
1202        'a,
1203        S,
1204        SelectOrderSet,
1205        T,
1206        <M as drizzle_core::HasScope>::With<TOrderBy::Sources>,
1207        R,
1208        G,
1209    >
1210    where
1211        M: drizzle_core::HasScope,
1212        TOrderBy: ToSQL<'a, PostgresValue<'a>> + drizzle_core::expr::ExprSources,
1213    {
1214        SelectBuilder {
1215            sql: self.sql.append(helpers::order_by(expressions)),
1216            schema: PhantomData,
1217            state: PhantomData,
1218            table: PhantomData,
1219            marker: PhantomData,
1220            row: PhantomData,
1221            grouped: PhantomData,
1222        }
1223    }
1224}
1225
1226// ORDER BY on a compound query: the combined rows carry no table scope, so the
1227// ordering terms are rendered as output column names.
1228impl<'a, S, T, M, R, G> SelectBuilder<'a, S, SelectSetOpSet, T, M, R, G> {
1229    /// Adds `ORDER BY` to a compound (`UNION` / `INTERSECT` / `EXCEPT`) query.
1230    ///
1231    /// The terms sort the combined output, so column references render
1232    /// unqualified (`"name"`, not `"users"."name"`), as `PostgreSQL` requires.
1233    ///
1234    /// # Examples
1235    ///
1236    /// ```rust
1237    /// # extern crate self as drizzle;
1238    /// # mod _drizzle {
1239    /// #     pub mod core { pub use drizzle_core::*; }
1240    /// #     pub mod error { pub use drizzle_core::error::*; }
1241    /// #     pub mod types { pub use drizzle_types::*; }
1242    /// #     pub mod migrations { pub use drizzle_migrations::*; }
1243    /// #     pub use drizzle_types::Dialect;
1244    /// #     pub use drizzle_types as ddl;
1245    /// #     pub mod postgres {
1246    /// #         pub mod values { pub use drizzle_postgres::values::*; }
1247    /// #         pub mod traits { pub use drizzle_postgres::traits::*; }
1248    /// #         pub mod common { pub use drizzle_postgres::common::*; }
1249    /// #         pub mod attrs { pub use drizzle_postgres::attrs::*; }
1250    /// #         pub mod builder { pub use drizzle_postgres::builder::*; }
1251    /// #         pub mod helpers { pub use drizzle_postgres::helpers::*; }
1252    /// #         pub mod expr { pub use drizzle_postgres::expr::*; }
1253    /// #         pub mod types { pub use drizzle_postgres::types::*; }
1254    /// #         #[cfg(feature = "aws-data-api")]
1255    /// #         pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
1256    /// #         pub struct Row;
1257    /// #         impl Row {
1258    /// #             pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
1259    /// #             pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
1260    /// #             pub fn len(&self) -> usize { unimplemented!() }
1261    /// #         }
1262    /// #         pub mod prelude {
1263    /// #             pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
1264    /// #             pub use drizzle_postgres::attrs::*;
1265    /// #             pub use drizzle_postgres::common::PostgresSchemaType;
1266    /// #             pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
1267    /// #             pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
1268    /// #             pub use drizzle_core::*;
1269    /// #         }
1270    /// #     }
1271    /// # }
1272    /// # pub use _drizzle::*;
1273    /// # pub use const_format;
1274    /// # fn main() {
1275    /// # use drizzle::postgres::prelude::*;
1276    /// # use drizzle::postgres::builder::QueryBuilder;
1277    /// # #[PostgresTable(name = "users")]
1278    /// # struct User {
1279    /// #     #[column(serial, primary)]
1280    /// #     id: i32,
1281    /// #     name: String,
1282    /// #     email: Option<String>,
1283    /// # }
1284    /// # #[PostgresTable(name = "posts")]
1285    /// # struct Post {
1286    /// #     #[column(serial, primary)]
1287    /// #     id: i32,
1288    /// #     #[column(references = User::id)]
1289    /// #     author_id: i32,
1290    /// #     title: String,
1291    /// # }
1292    /// # #[derive(PostgresSchema)]
1293    /// # struct Schema {
1294    /// #     user: User,
1295    /// #     post: Post,
1296    /// # }
1297    /// # let db = QueryBuilder::new::<Schema>();
1298    /// # let Schema { user, post } = Schema::new();
1299    /// let query = db
1300    ///     .select(user.name)
1301    ///     .from(user)
1302    ///     .union_all(db.select(post.title).from(post))
1303    ///     .order_by(user.name);
1304    /// assert_eq!(
1305    ///     query.to_sql().sql(),
1306    ///     r#"SELECT "users"."name" FROM "users" UNION ALL SELECT "posts"."title" FROM "posts" ORDER BY "name""#
1307    /// );
1308    /// # }
1309    /// ```
1310    #[inline]
1311    pub fn order_by<TOrderBy>(
1312        self,
1313        expressions: TOrderBy,
1314    ) -> SelectBuilder<'a, S, SelectOrderSet, T, M, R, G>
1315    where
1316        TOrderBy: ToSQL<'a, PostgresValue<'a>>,
1317    {
1318        SelectBuilder {
1319            sql: self
1320                .sql
1321                .append(drizzle_core::helpers::set_order_by(expressions)),
1322            schema: PhantomData,
1323            state: PhantomData,
1324            table: PhantomData,
1325            marker: PhantomData,
1326            row: PhantomData,
1327            grouped: PhantomData,
1328        }
1329    }
1330}
1331
1332// LIMIT (available from many states)
1333impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
1334where
1335    State: drizzle_core::ClauseAllowed<drizzle_core::clause::Limit>,
1336{
1337    /// Adds `LIMIT n`, returning at most `n` rows.
1338    ///
1339    /// `n` is a non-negative integer (bound as a parameter) or a placeholder.
1340    ///
1341    /// # Examples
1342    ///
1343    /// ```rust
1344    /// # extern crate self as drizzle;
1345    /// # mod _drizzle {
1346    /// #     pub mod core { pub use drizzle_core::*; }
1347    /// #     pub mod error { pub use drizzle_core::error::*; }
1348    /// #     pub mod types { pub use drizzle_types::*; }
1349    /// #     pub mod migrations { pub use drizzle_migrations::*; }
1350    /// #     pub use drizzle_types::Dialect;
1351    /// #     pub use drizzle_types as ddl;
1352    /// #     pub mod postgres {
1353    /// #         pub mod values { pub use drizzle_postgres::values::*; }
1354    /// #         pub mod traits { pub use drizzle_postgres::traits::*; }
1355    /// #         pub mod common { pub use drizzle_postgres::common::*; }
1356    /// #         pub mod attrs { pub use drizzle_postgres::attrs::*; }
1357    /// #         pub mod builder { pub use drizzle_postgres::builder::*; }
1358    /// #         pub mod helpers { pub use drizzle_postgres::helpers::*; }
1359    /// #         pub mod expr { pub use drizzle_postgres::expr::*; }
1360    /// #         pub mod types { pub use drizzle_postgres::types::*; }
1361    /// #         #[cfg(feature = "aws-data-api")]
1362    /// #         pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
1363    /// #         pub struct Row;
1364    /// #         impl Row {
1365    /// #             pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
1366    /// #             pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
1367    /// #             pub fn len(&self) -> usize { unimplemented!() }
1368    /// #         }
1369    /// #         pub mod prelude {
1370    /// #             pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
1371    /// #             pub use drizzle_postgres::attrs::*;
1372    /// #             pub use drizzle_postgres::common::PostgresSchemaType;
1373    /// #             pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
1374    /// #             pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
1375    /// #             pub use drizzle_core::*;
1376    /// #         }
1377    /// #     }
1378    /// # }
1379    /// # pub use _drizzle::*;
1380    /// # pub use const_format;
1381    /// # fn main() {
1382    /// # use drizzle::postgres::prelude::*;
1383    /// # use drizzle::postgres::builder::QueryBuilder;
1384    /// # #[PostgresTable(name = "users")]
1385    /// # struct User {
1386    /// #     #[column(serial, primary)]
1387    /// #     id: i32,
1388    /// #     name: String,
1389    /// #     email: Option<String>,
1390    /// # }
1391    /// # #[PostgresTable(name = "posts")]
1392    /// # struct Post {
1393    /// #     #[column(serial, primary)]
1394    /// #     id: i32,
1395    /// #     #[column(references = User::id)]
1396    /// #     author_id: i32,
1397    /// #     title: String,
1398    /// # }
1399    /// # #[derive(PostgresSchema)]
1400    /// # struct Schema {
1401    /// #     user: User,
1402    /// #     post: Post,
1403    /// # }
1404    /// # let db = QueryBuilder::new::<Schema>();
1405    /// # let Schema { user, post } = Schema::new();
1406    /// let query = db.select(user.id).from(user).limit(5);
1407    /// assert_eq!(query.to_sql().sql(), r#"SELECT "users"."id" FROM "users" LIMIT $1"#);
1408    /// # }
1409    /// ```
1410    ///
1411    /// # Panics
1412    ///
1413    /// Panics when a signed numeric argument is negative or a numeric value
1414    /// does not fit in `usize`.
1415    #[inline]
1416    #[must_use]
1417    #[track_caller]
1418    pub fn limit<P>(self, limit: P) -> SelectBuilder<'a, S, SelectLimitSet, T, M, R, G>
1419    where
1420        P: drizzle_core::PaginationArg<'a, PostgresValue<'a>>,
1421    {
1422        SelectBuilder {
1423            sql: self.sql.append(helpers::limit(limit)),
1424            schema: PhantomData,
1425            state: PhantomData,
1426            table: PhantomData,
1427            marker: PhantomData,
1428            row: PhantomData,
1429            grouped: PhantomData,
1430        }
1431    }
1432}
1433
1434// OFFSET (available from SelectFromSet, SelectLimitSet, SelectSetOpSet)
1435impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
1436where
1437    State: drizzle_core::ClauseAllowed<drizzle_core::clause::Offset>,
1438{
1439    /// Adds `OFFSET n`, skipping the first `n` rows.
1440    ///
1441    /// `n` is a non-negative integer (bound as a parameter) or a placeholder.
1442    ///
1443    /// # Examples
1444    ///
1445    /// ```rust
1446    /// # extern crate self as drizzle;
1447    /// # mod _drizzle {
1448    /// #     pub mod core { pub use drizzle_core::*; }
1449    /// #     pub mod error { pub use drizzle_core::error::*; }
1450    /// #     pub mod types { pub use drizzle_types::*; }
1451    /// #     pub mod migrations { pub use drizzle_migrations::*; }
1452    /// #     pub use drizzle_types::Dialect;
1453    /// #     pub use drizzle_types as ddl;
1454    /// #     pub mod postgres {
1455    /// #         pub mod values { pub use drizzle_postgres::values::*; }
1456    /// #         pub mod traits { pub use drizzle_postgres::traits::*; }
1457    /// #         pub mod common { pub use drizzle_postgres::common::*; }
1458    /// #         pub mod attrs { pub use drizzle_postgres::attrs::*; }
1459    /// #         pub mod builder { pub use drizzle_postgres::builder::*; }
1460    /// #         pub mod helpers { pub use drizzle_postgres::helpers::*; }
1461    /// #         pub mod expr { pub use drizzle_postgres::expr::*; }
1462    /// #         pub mod types { pub use drizzle_postgres::types::*; }
1463    /// #         #[cfg(feature = "aws-data-api")]
1464    /// #         pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
1465    /// #         pub struct Row;
1466    /// #         impl Row {
1467    /// #             pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
1468    /// #             pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
1469    /// #             pub fn len(&self) -> usize { unimplemented!() }
1470    /// #         }
1471    /// #         pub mod prelude {
1472    /// #             pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
1473    /// #             pub use drizzle_postgres::attrs::*;
1474    /// #             pub use drizzle_postgres::common::PostgresSchemaType;
1475    /// #             pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
1476    /// #             pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
1477    /// #             pub use drizzle_core::*;
1478    /// #         }
1479    /// #     }
1480    /// # }
1481    /// # pub use _drizzle::*;
1482    /// # pub use const_format;
1483    /// # fn main() {
1484    /// # use drizzle::postgres::prelude::*;
1485    /// # use drizzle::postgres::builder::QueryBuilder;
1486    /// # #[PostgresTable(name = "users")]
1487    /// # struct User {
1488    /// #     #[column(serial, primary)]
1489    /// #     id: i32,
1490    /// #     name: String,
1491    /// #     email: Option<String>,
1492    /// # }
1493    /// # #[PostgresTable(name = "posts")]
1494    /// # struct Post {
1495    /// #     #[column(serial, primary)]
1496    /// #     id: i32,
1497    /// #     #[column(references = User::id)]
1498    /// #     author_id: i32,
1499    /// #     title: String,
1500    /// # }
1501    /// # #[derive(PostgresSchema)]
1502    /// # struct Schema {
1503    /// #     user: User,
1504    /// #     post: Post,
1505    /// # }
1506    /// # let db = QueryBuilder::new::<Schema>();
1507    /// # let Schema { user, post } = Schema::new();
1508    /// let query = db.select(user.id).from(user).limit(10).offset(20);
1509    /// assert_eq!(
1510    ///     query.to_sql().sql(),
1511    ///     r#"SELECT "users"."id" FROM "users" LIMIT $1 OFFSET $2"#
1512    /// );
1513    /// # }
1514    /// ```
1515    ///
1516    /// # Panics
1517    ///
1518    /// Panics when a signed numeric argument is negative or a numeric value
1519    /// does not fit in `usize`.
1520    #[inline]
1521    #[must_use]
1522    #[track_caller]
1523    pub fn offset<P>(self, offset: P) -> SelectBuilder<'a, S, SelectOffsetSet, T, M, R, G>
1524    where
1525        P: drizzle_core::PaginationArg<'a, PostgresValue<'a>>,
1526    {
1527        SelectBuilder {
1528            sql: self.sql.append(helpers::offset(offset)),
1529            schema: PhantomData,
1530            state: PhantomData,
1531            table: PhantomData,
1532            marker: PhantomData,
1533            row: PhantomData,
1534            grouped: PhantomData,
1535        }
1536    }
1537}
1538
1539//------------------------------------------------------------------------------
1540// CTE support
1541//------------------------------------------------------------------------------
1542
1543impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
1544where
1545    State: drizzle_core::ClauseAllowed<drizzle_core::clause::Source>,
1546{
1547    /// Turns this `SELECT` into a derived table, `(SELECT ...) AS tag`.
1548    ///
1549    /// The result can be used in `.from(...)` or a lateral join; read its
1550    /// columns with `.fields()`.
1551    ///
1552    /// # Panics
1553    ///
1554    /// Panics when the projection contains duplicate output names. Name a
1555    /// computed expression with [`drizzle_core::expr::AliasExt::named`] to
1556    /// make each output unique.
1557    #[inline]
1558    #[must_use]
1559    pub fn alias<Tag, AggProof>(
1560        self,
1561        _tag: Tag,
1562    ) -> drizzle_core::Derived<
1563        'a,
1564        PostgresValue<'a>,
1565        Tag,
1566        <M as drizzle_core::DerivedSelection<
1567            'a,
1568            PostgresValue<'a>,
1569            PostgresSchemaType,
1570            T,
1571        >>::Projection,
1572        Self,
1573    >
1574    where
1575        Tag: drizzle_core::Tag,
1576        M: drizzle_core::DerivedSelection<'a, PostgresValue<'a>, PostgresSchemaType, T>
1577            + drizzle_core::row::MarkerAggValidFor<G, AggProof>,
1578        <M as drizzle_core::DerivedSelection<
1579            'a,
1580            PostgresValue<'a>,
1581            PostgresSchemaType,
1582            T,
1583        >>::Projection: drizzle_core::DerivedProjection<Tag>,
1584{
1585        // SAFETY: The executable-state, aggregate, and projection bounds
1586        // above prove that this query matches the derived projection; its
1587        // scope travels in `Self`'s sources and is checked where it is used.
1588        unsafe { drizzle_core::Derived::new_unchecked(self) }
1589    }
1590}
1591
1592impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
1593where
1594    State: drizzle_core::ClauseAllowed<drizzle_core::clause::Simple>,
1595    T: SQLTable<'a, PostgresSchemaType, PostgresValue<'a>>,
1596{
1597    /// Turns this `SELECT` into a common table expression named `Tag::NAME`.
1598    ///
1599    /// The result has the same columns as the `FROM` table. Pass it to
1600    /// `QueryBuilder::with`, and read its columns through its `.table` field;
1601    /// see [`QueryBuilder::with`](super::QueryBuilder::with) for an example.
1602    #[inline]
1603    #[must_use]
1604    pub fn into_cte<Tag: drizzle_core::Tag + 'static>(
1605        self,
1606    ) -> super::CTEView<
1607        'a,
1608        <T as SQLTable<'a, PostgresSchemaType, PostgresValue<'a>>>::Aliased<Tag>,
1609        Self,
1610    > {
1611        let name = Tag::NAME;
1612        super::CTEView::new(
1613            <T as SQLTable<'a, PostgresSchemaType, PostgresValue<'a>>>::alias::<Tag>(),
1614            name,
1615            self,
1616        )
1617    }
1618}
1619
1620//------------------------------------------------------------------------------
1621// Set operation support (UNION / INTERSECT / EXCEPT)
1622//------------------------------------------------------------------------------
1623
1624impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
1625where
1626    State: drizzle_core::ClauseAllowed<drizzle_core::clause::Compound>,
1627{
1628    /// Combines this query with `other` using `UNION`, which drops duplicate rows.
1629    ///
1630    /// Both queries must decode to the same row type, which the compiler
1631    /// checks. The `union_all`, `intersect`, `intersect_all`, `except` and
1632    /// `except_all` methods work the same way.
1633    ///
1634    /// # Examples
1635    ///
1636    /// ```rust
1637    /// # extern crate self as drizzle;
1638    /// # mod _drizzle {
1639    /// #     pub mod core { pub use drizzle_core::*; }
1640    /// #     pub mod error { pub use drizzle_core::error::*; }
1641    /// #     pub mod types { pub use drizzle_types::*; }
1642    /// #     pub mod migrations { pub use drizzle_migrations::*; }
1643    /// #     pub use drizzle_types::Dialect;
1644    /// #     pub use drizzle_types as ddl;
1645    /// #     pub mod postgres {
1646    /// #         pub mod values { pub use drizzle_postgres::values::*; }
1647    /// #         pub mod traits { pub use drizzle_postgres::traits::*; }
1648    /// #         pub mod common { pub use drizzle_postgres::common::*; }
1649    /// #         pub mod attrs { pub use drizzle_postgres::attrs::*; }
1650    /// #         pub mod builder { pub use drizzle_postgres::builder::*; }
1651    /// #         pub mod helpers { pub use drizzle_postgres::helpers::*; }
1652    /// #         pub mod expr { pub use drizzle_postgres::expr::*; }
1653    /// #         pub mod types { pub use drizzle_postgres::types::*; }
1654    /// #         #[cfg(feature = "aws-data-api")]
1655    /// #         pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
1656    /// #         pub struct Row;
1657    /// #         impl Row {
1658    /// #             pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
1659    /// #             pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
1660    /// #             pub fn len(&self) -> usize { unimplemented!() }
1661    /// #         }
1662    /// #         pub mod prelude {
1663    /// #             pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
1664    /// #             pub use drizzle_postgres::attrs::*;
1665    /// #             pub use drizzle_postgres::common::PostgresSchemaType;
1666    /// #             pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
1667    /// #             pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
1668    /// #             pub use drizzle_core::*;
1669    /// #         }
1670    /// #     }
1671    /// # }
1672    /// # pub use _drizzle::*;
1673    /// # pub use const_format;
1674    /// # fn main() {
1675    /// # use drizzle::postgres::prelude::*;
1676    /// # use drizzle::postgres::builder::QueryBuilder;
1677    /// # #[PostgresTable(name = "users")]
1678    /// # struct User {
1679    /// #     #[column(serial, primary)]
1680    /// #     id: i32,
1681    /// #     name: String,
1682    /// #     email: Option<String>,
1683    /// # }
1684    /// # #[PostgresTable(name = "posts")]
1685    /// # struct Post {
1686    /// #     #[column(serial, primary)]
1687    /// #     id: i32,
1688    /// #     #[column(references = User::id)]
1689    /// #     author_id: i32,
1690    /// #     title: String,
1691    /// # }
1692    /// # #[derive(PostgresSchema)]
1693    /// # struct Schema {
1694    /// #     user: User,
1695    /// #     post: Post,
1696    /// # }
1697    /// # let db = QueryBuilder::new::<Schema>();
1698    /// # let Schema { user, post } = Schema::new();
1699    /// let query = db
1700    ///     .select(user.name)
1701    ///     .from(user)
1702    ///     .union(db.select(post.title).from(post));
1703    /// assert_eq!(
1704    ///     query.to_sql().sql(),
1705    ///     r#"SELECT "users"."name" FROM "users" UNION SELECT "posts"."title" FROM "posts""#
1706    /// );
1707    /// # }
1708    /// ```
1709    #[allow(clippy::type_complexity)]
1710    pub fn union<M2>(
1711        self,
1712        other: impl IntoSelect<'a, S, M2, R>,
1713    ) -> SelectBuilder<'a, S, SelectSetOpSet, T, <M as drizzle_core::SetOperand<M2>>::Combined, R, G>
1714    where
1715        M: drizzle_core::SetOperand<M2>,
1716    {
1717        SelectBuilder {
1718            sql: helpers::union(self.sql, other.into_select()),
1719            schema: PhantomData,
1720            state: PhantomData,
1721            table: PhantomData,
1722            marker: PhantomData,
1723            row: PhantomData,
1724            grouped: PhantomData,
1725        }
1726    }
1727
1728    /// Combines this query with `other` using `UNION ALL`, which keeps duplicates.
1729    #[allow(clippy::type_complexity)]
1730    pub fn union_all<M2>(
1731        self,
1732        other: impl IntoSelect<'a, S, M2, R>,
1733    ) -> SelectBuilder<'a, S, SelectSetOpSet, T, <M as drizzle_core::SetOperand<M2>>::Combined, R, G>
1734    where
1735        M: drizzle_core::SetOperand<M2>,
1736    {
1737        SelectBuilder {
1738            sql: helpers::union_all(self.sql, other.into_select()),
1739            schema: PhantomData,
1740            state: PhantomData,
1741            table: PhantomData,
1742            marker: PhantomData,
1743            row: PhantomData,
1744            grouped: PhantomData,
1745        }
1746    }
1747
1748    /// Keeps the rows present in both queries (`INTERSECT`), without duplicates.
1749    #[allow(clippy::type_complexity)]
1750    pub fn intersect<M2>(
1751        self,
1752        other: impl IntoSelect<'a, S, M2, R>,
1753    ) -> SelectBuilder<'a, S, SelectSetOpSet, T, <M as drizzle_core::SetOperand<M2>>::Combined, R, G>
1754    where
1755        M: drizzle_core::SetOperand<M2>,
1756    {
1757        SelectBuilder {
1758            sql: helpers::intersect(self.sql, other.into_select()),
1759            schema: PhantomData,
1760            state: PhantomData,
1761            table: PhantomData,
1762            marker: PhantomData,
1763            row: PhantomData,
1764            grouped: PhantomData,
1765        }
1766    }
1767
1768    /// Keeps the rows present in both queries (`INTERSECT ALL`), with duplicates.
1769    #[allow(clippy::type_complexity)]
1770    pub fn intersect_all<M2>(
1771        self,
1772        other: impl IntoSelect<'a, S, M2, R>,
1773    ) -> SelectBuilder<'a, S, SelectSetOpSet, T, <M as drizzle_core::SetOperand<M2>>::Combined, R, G>
1774    where
1775        M: drizzle_core::SetOperand<M2>,
1776    {
1777        SelectBuilder {
1778            sql: helpers::intersect_all(self.sql, other.into_select()),
1779            schema: PhantomData,
1780            state: PhantomData,
1781            table: PhantomData,
1782            marker: PhantomData,
1783            row: PhantomData,
1784            grouped: PhantomData,
1785        }
1786    }
1787
1788    /// Keeps the rows of this query that are not in `other` (`EXCEPT`), without duplicates.
1789    #[allow(clippy::type_complexity)]
1790    pub fn except<M2>(
1791        self,
1792        other: impl IntoSelect<'a, S, M2, R>,
1793    ) -> SelectBuilder<'a, S, SelectSetOpSet, T, <M as drizzle_core::SetOperand<M2>>::Combined, R, G>
1794    where
1795        M: drizzle_core::SetOperand<M2>,
1796    {
1797        SelectBuilder {
1798            sql: helpers::except(self.sql, other.into_select()),
1799            schema: PhantomData,
1800            state: PhantomData,
1801            table: PhantomData,
1802            marker: PhantomData,
1803            row: PhantomData,
1804            grouped: PhantomData,
1805        }
1806    }
1807
1808    /// Keeps the rows of this query that are not in `other` (`EXCEPT ALL`), with duplicates.
1809    #[allow(clippy::type_complexity)]
1810    pub fn except_all<M2>(
1811        self,
1812        other: impl IntoSelect<'a, S, M2, R>,
1813    ) -> SelectBuilder<'a, S, SelectSetOpSet, T, <M as drizzle_core::SetOperand<M2>>::Combined, R, G>
1814    where
1815        M: drizzle_core::SetOperand<M2>,
1816    {
1817        SelectBuilder {
1818            sql: helpers::except_all(self.sql, other.into_select()),
1819            schema: PhantomData,
1820            state: PhantomData,
1821            table: PhantomData,
1822            marker: PhantomData,
1823            row: PhantomData,
1824            grouped: PhantomData,
1825        }
1826    }
1827}
1828
1829//------------------------------------------------------------------------------
1830// Expr impl for subquery usage
1831//------------------------------------------------------------------------------
1832
1833impl<'a, S, State, T, M, R, G> drizzle_core::expr::Expr<'a, PostgresValue<'a>>
1834    for SelectBuilder<'a, S, State, T, M, R, G>
1835where
1836    State: drizzle_core::ClauseAllowed<drizzle_core::clause::Source>,
1837    M: drizzle_core::expr::SubqueryType<'a, PostgresValue<'a>> + drizzle_core::SelectSources,
1838{
1839    type SQLType = <M as drizzle_core::expr::SubqueryType<'a, PostgresValue<'a>>>::SQLType;
1840    type Nullable = drizzle_core::expr::Null;
1841    type Aggregate = drizzle_core::expr::Scalar;
1842}
1843
1844impl<S, State: drizzle_core::ClauseAllowed<drizzle_core::clause::Source>, T, M, R, G>
1845    drizzle_core::expr::SelectQuery for SelectBuilder<'_, S, State, T, M, R, G>
1846{
1847}
1848
1849impl<S, State, T, M, R, G> drizzle_core::expr::ExprSources
1850    for SelectBuilder<'_, S, State, T, M, R, G>
1851where
1852    M: drizzle_core::SelectSources,
1853{
1854    type Sources = M::Sources;
1855}
1856
1857//------------------------------------------------------------------------------
1858// IntoSelect conversion trait
1859//------------------------------------------------------------------------------
1860
1861/// A query that can be the right-hand side of `UNION`, `INTERSECT` or `EXCEPT`.
1862///
1863/// Implemented by [`SelectBuilder`] and by the driver crates' query wrappers.
1864#[diagnostic::on_unimplemented(
1865    message = "this query does not select the columns the set operation needs",
1866    label = "it selects different columns from the other side",
1867    note = "both sides of UNION, INTERSECT and EXCEPT select the same number of columns, of matching types, in the same order"
1868)]
1869pub trait IntoSelect<'a, S, M, R> {
1870    /// The builder state of the converted query.
1871    type State: drizzle_core::ClauseAllowed<drizzle_core::clause::Compound>;
1872    /// The `FROM` table of the converted query.
1873    type Table;
1874    /// Returns the query as a [`SelectBuilder`].
1875    fn into_select(self) -> SelectBuilder<'a, S, Self::State, Self::Table, M, R>;
1876}
1877
1878impl<'a, S, State: drizzle_core::ClauseAllowed<drizzle_core::clause::Compound>, T, M, R, G>
1879    IntoSelect<'a, S, M, R> for SelectBuilder<'a, S, State, T, M, R, G>
1880{
1881    type State = State;
1882    type Table = T;
1883    fn into_select(self) -> SelectBuilder<'a, S, State, T, M, R> {
1884        SelectBuilder {
1885            sql: self.sql,
1886            schema: PhantomData,
1887            state: PhantomData,
1888            table: PhantomData,
1889            marker: PhantomData,
1890            row: PhantomData,
1891            grouped: PhantomData,
1892        }
1893    }
1894}
1895
1896mod insert_select_private {
1897    pub trait Sealed {}
1898}
1899
1900/// A complete `SELECT` that can supply rows to `INSERT ... SELECT`.
1901#[doc(hidden)]
1902pub trait CompletedSelect<'a, S, R>: insert_select_private::Sealed {
1903    type Marker;
1904    type Grouped;
1905
1906    fn into_select_sql(self) -> drizzle_core::SQL<'a, PostgresValue<'a>>;
1907}
1908
1909/// Converts a complete `SELECT`, or a driver wrapper around one, into a
1910/// [`CompletedSelect`].
1911#[doc(hidden)]
1912pub trait IntoSelectQuery<'a, S, R> {
1913    type Marker;
1914    type Grouped;
1915    type Select: CompletedSelect<'a, S, R, Marker = Self::Marker, Grouped = Self::Grouped>;
1916
1917    fn into_select_query(self) -> Self::Select;
1918}
1919
1920impl<'a, S, State, T, M, R, G> insert_select_private::Sealed
1921    for SelectBuilder<'a, S, State, T, M, R, G>
1922where
1923    State: drizzle_core::ClauseAllowed<drizzle_core::clause::Source>,
1924{
1925}
1926
1927impl<'a, S, State, T, M, R, G> CompletedSelect<'a, S, R> for SelectBuilder<'a, S, State, T, M, R, G>
1928where
1929    State: drizzle_core::ClauseAllowed<drizzle_core::clause::Source>,
1930{
1931    type Marker = M;
1932    type Grouped = G;
1933
1934    fn into_select_sql(self) -> drizzle_core::SQL<'a, PostgresValue<'a>> {
1935        self.sql
1936    }
1937}
1938
1939impl<'a, S, State, T, M, R, G> IntoSelectQuery<'a, S, R> for SelectBuilder<'a, S, State, T, M, R, G>
1940where
1941    State: drizzle_core::ClauseAllowed<drizzle_core::clause::Source>,
1942{
1943    type Marker = M;
1944    type Grouped = G;
1945    type Select = Self;
1946
1947    fn into_select_query(self) -> Self::Select {
1948        self
1949    }
1950}
1951
1952//------------------------------------------------------------------------------
1953// FOR UPDATE/SHARE Row Locking (PostgreSQL-specific)
1954//------------------------------------------------------------------------------
1955
1956impl<'a, S, State, T, M, R, G> SelectBuilder<'a, S, State, T, M, R, G>
1957where
1958    State: drizzle_core::ClauseAllowed<drizzle_core::clause::Simple>,
1959{
1960    /// Adds `FOR UPDATE`, locking the selected rows against updates and
1961    /// deletes by other transactions until this one ends.
1962    ///
1963    /// Follow with [`nowait`](Self::nowait) or [`skip_locked`](Self::skip_locked)
1964    /// to change what happens when a row is already locked.
1965    ///
1966    /// # Examples
1967    ///
1968    /// ```rust
1969    /// # extern crate self as drizzle;
1970    /// # mod _drizzle {
1971    /// #     pub mod core { pub use drizzle_core::*; }
1972    /// #     pub mod error { pub use drizzle_core::error::*; }
1973    /// #     pub mod types { pub use drizzle_types::*; }
1974    /// #     pub mod migrations { pub use drizzle_migrations::*; }
1975    /// #     pub use drizzle_types::Dialect;
1976    /// #     pub use drizzle_types as ddl;
1977    /// #     pub mod postgres {
1978    /// #         pub mod values { pub use drizzle_postgres::values::*; }
1979    /// #         pub mod traits { pub use drizzle_postgres::traits::*; }
1980    /// #         pub mod common { pub use drizzle_postgres::common::*; }
1981    /// #         pub mod attrs { pub use drizzle_postgres::attrs::*; }
1982    /// #         pub mod builder { pub use drizzle_postgres::builder::*; }
1983    /// #         pub mod helpers { pub use drizzle_postgres::helpers::*; }
1984    /// #         pub mod expr { pub use drizzle_postgres::expr::*; }
1985    /// #         pub mod types { pub use drizzle_postgres::types::*; }
1986    /// #         #[cfg(feature = "aws-data-api")]
1987    /// #         pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
1988    /// #         pub struct Row;
1989    /// #         impl Row {
1990    /// #             pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
1991    /// #             pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
1992    /// #             pub fn len(&self) -> usize { unimplemented!() }
1993    /// #         }
1994    /// #         pub mod prelude {
1995    /// #             pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
1996    /// #             pub use drizzle_postgres::attrs::*;
1997    /// #             pub use drizzle_postgres::common::PostgresSchemaType;
1998    /// #             pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
1999    /// #             pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
2000    /// #             pub use drizzle_core::*;
2001    /// #         }
2002    /// #     }
2003    /// # }
2004    /// # pub use _drizzle::*;
2005    /// # pub use const_format;
2006    /// # fn main() {
2007    /// # use drizzle::postgres::prelude::*;
2008    /// # use drizzle::postgres::builder::QueryBuilder;
2009    /// # #[PostgresTable(name = "users")]
2010    /// # struct User {
2011    /// #     #[column(serial, primary)]
2012    /// #     id: i32,
2013    /// #     name: String,
2014    /// #     email: Option<String>,
2015    /// # }
2016    /// # #[PostgresTable(name = "posts")]
2017    /// # struct Post {
2018    /// #     #[column(serial, primary)]
2019    /// #     id: i32,
2020    /// #     #[column(references = User::id)]
2021    /// #     author_id: i32,
2022    /// #     title: String,
2023    /// # }
2024    /// # #[derive(PostgresSchema)]
2025    /// # struct Schema {
2026    /// #     user: User,
2027    /// #     post: Post,
2028    /// # }
2029    /// # let db = QueryBuilder::new::<Schema>();
2030    /// # let Schema { user, post } = Schema::new();
2031    /// let query = db.select(user.id).from(user).for_update().skip_locked();
2032    /// assert_eq!(
2033    ///     query.to_sql().sql(),
2034    ///     r#"SELECT "users"."id" FROM "users" FOR UPDATE SKIP LOCKED"#
2035    /// );
2036    /// # }
2037    /// ```
2038    #[must_use]
2039    pub fn for_update(self) -> SelectBuilder<'a, S, SelectForSet, T, M, R, G> {
2040        SelectBuilder {
2041            sql: self.sql.append(helpers::for_update()),
2042            schema: PhantomData,
2043            state: PhantomData,
2044            table: PhantomData,
2045            marker: PhantomData,
2046            row: PhantomData,
2047            grouped: PhantomData,
2048        }
2049    }
2050
2051    /// Adds `FOR SHARE`: other transactions can still read and share-lock the
2052    /// rows, but cannot update or delete them.
2053    #[must_use]
2054    pub fn for_share(self) -> SelectBuilder<'a, S, SelectForSet, T, M, R, G> {
2055        SelectBuilder {
2056            sql: self.sql.append(helpers::for_share()),
2057            schema: PhantomData,
2058            state: PhantomData,
2059            table: PhantomData,
2060            marker: PhantomData,
2061            row: PhantomData,
2062            grouped: PhantomData,
2063        }
2064    }
2065
2066    /// Adds `FOR NO KEY UPDATE`: like `FOR UPDATE`, but does not block
2067    /// `FOR KEY SHARE` locks (for example, foreign-key checks).
2068    #[must_use]
2069    pub fn for_no_key_update(self) -> SelectBuilder<'a, S, SelectForSet, T, M, R, G> {
2070        SelectBuilder {
2071            sql: self.sql.append(helpers::for_no_key_update()),
2072            schema: PhantomData,
2073            state: PhantomData,
2074            table: PhantomData,
2075            marker: PhantomData,
2076            row: PhantomData,
2077            grouped: PhantomData,
2078        }
2079    }
2080
2081    /// Adds `FOR KEY SHARE`: blocks deletes and key changes, but allows other
2082    /// updates.
2083    #[must_use]
2084    pub fn for_key_share(self) -> SelectBuilder<'a, S, SelectForSet, T, M, R, G> {
2085        SelectBuilder {
2086            sql: self.sql.append(helpers::for_key_share()),
2087            schema: PhantomData,
2088            state: PhantomData,
2089            table: PhantomData,
2090            marker: PhantomData,
2091            row: PhantomData,
2092            grouped: PhantomData,
2093        }
2094    }
2095
2096    /// Adds `FOR UPDATE OF table`, locking rows of that table only.
2097    ///
2098    /// # Examples
2099    ///
2100    /// ```rust
2101    /// # extern crate self as drizzle;
2102    /// # mod _drizzle {
2103    /// #     pub mod core { pub use drizzle_core::*; }
2104    /// #     pub mod error { pub use drizzle_core::error::*; }
2105    /// #     pub mod types { pub use drizzle_types::*; }
2106    /// #     pub mod migrations { pub use drizzle_migrations::*; }
2107    /// #     pub use drizzle_types::Dialect;
2108    /// #     pub use drizzle_types as ddl;
2109    /// #     pub mod postgres {
2110    /// #         pub mod values { pub use drizzle_postgres::values::*; }
2111    /// #         pub mod traits { pub use drizzle_postgres::traits::*; }
2112    /// #         pub mod common { pub use drizzle_postgres::common::*; }
2113    /// #         pub mod attrs { pub use drizzle_postgres::attrs::*; }
2114    /// #         pub mod builder { pub use drizzle_postgres::builder::*; }
2115    /// #         pub mod helpers { pub use drizzle_postgres::helpers::*; }
2116    /// #         pub mod expr { pub use drizzle_postgres::expr::*; }
2117    /// #         pub mod types { pub use drizzle_postgres::types::*; }
2118    /// #         #[cfg(feature = "aws-data-api")]
2119    /// #         pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
2120    /// #         pub struct Row;
2121    /// #         impl Row {
2122    /// #             pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
2123    /// #             pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
2124    /// #             pub fn len(&self) -> usize { unimplemented!() }
2125    /// #         }
2126    /// #         pub mod prelude {
2127    /// #             pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
2128    /// #             pub use drizzle_postgres::attrs::*;
2129    /// #             pub use drizzle_postgres::common::PostgresSchemaType;
2130    /// #             pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
2131    /// #             pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
2132    /// #             pub use drizzle_core::*;
2133    /// #         }
2134    /// #     }
2135    /// # }
2136    /// # pub use _drizzle::*;
2137    /// # pub use const_format;
2138    /// # fn main() {
2139    /// # use drizzle::postgres::prelude::*;
2140    /// # use drizzle::postgres::builder::QueryBuilder;
2141    /// # #[PostgresTable(name = "users")]
2142    /// # struct User {
2143    /// #     #[column(serial, primary)]
2144    /// #     id: i32,
2145    /// #     name: String,
2146    /// #     email: Option<String>,
2147    /// # }
2148    /// # #[PostgresTable(name = "posts")]
2149    /// # struct Post {
2150    /// #     #[column(serial, primary)]
2151    /// #     id: i32,
2152    /// #     #[column(references = User::id)]
2153    /// #     author_id: i32,
2154    /// #     title: String,
2155    /// # }
2156    /// # #[derive(PostgresSchema)]
2157    /// # struct Schema {
2158    /// #     user: User,
2159    /// #     post: Post,
2160    /// # }
2161    /// # let db = QueryBuilder::new::<Schema>();
2162    /// # let Schema { user, post } = Schema::new();
2163    /// use drizzle::core::expr::eq;
2164    ///
2165    /// let query = db
2166    ///     .select((user.id, post.id))
2167    ///     .from(user)
2168    ///     .join((post, eq(post.author_id, user.id)))
2169    ///     .for_update_of(user);
2170    /// assert!(query.to_sql().sql().ends_with(r#"FOR UPDATE OF "users""#));
2171    /// # }
2172    /// ```
2173    pub fn for_update_of<U: PostgresTable<'a>>(
2174        self,
2175        table: U,
2176    ) -> SelectBuilder<'a, S, SelectForSet, T, M, R, G> {
2177        SelectBuilder {
2178            sql: self.sql.append(helpers::for_update_of(table.name())),
2179            schema: PhantomData,
2180            state: PhantomData,
2181            table: PhantomData,
2182            marker: PhantomData,
2183            row: PhantomData,
2184            grouped: PhantomData,
2185        }
2186    }
2187
2188    /// Adds `FOR SHARE OF table`, locking rows of that table only.
2189    pub fn for_share_of<U: PostgresTable<'a>>(
2190        self,
2191        table: U,
2192    ) -> SelectBuilder<'a, S, SelectForSet, T, M, R, G> {
2193        SelectBuilder {
2194            sql: self.sql.append(helpers::for_share_of(table.name())),
2195            schema: PhantomData,
2196            state: PhantomData,
2197            table: PhantomData,
2198            marker: PhantomData,
2199            row: PhantomData,
2200            grouped: PhantomData,
2201        }
2202    }
2203}
2204
2205//------------------------------------------------------------------------------
2206// Post-FOR State Implementation (NOWAIT / SKIP LOCKED)
2207//------------------------------------------------------------------------------
2208
2209impl<S, T, M, R, G> SelectBuilder<'_, S, SelectForSet, T, M, R, G> {
2210    /// Adds `NOWAIT`: the query fails at once instead of waiting when a row
2211    /// is already locked.
2212    #[must_use]
2213    pub fn nowait(self) -> Self {
2214        SelectBuilder {
2215            sql: self.sql.append(helpers::nowait()),
2216            schema: PhantomData,
2217            state: PhantomData,
2218            table: PhantomData,
2219            marker: PhantomData,
2220            row: PhantomData,
2221            grouped: PhantomData,
2222        }
2223    }
2224
2225    /// Adds `SKIP LOCKED`: rows already locked by another transaction are
2226    /// left out of the result instead of waited for.
2227    #[must_use]
2228    pub fn skip_locked(self) -> Self {
2229        SelectBuilder {
2230            sql: self.sql.append(helpers::skip_locked()),
2231            schema: PhantomData,
2232            state: PhantomData,
2233            table: PhantomData,
2234            marker: PhantomData,
2235            row: PhantomData,
2236            grouped: PhantomData,
2237        }
2238    }
2239}
2240
2241#[cfg(test)]
2242mod tests {
2243    use super::*;
2244    use drizzle_core::{SQL, ToSQL};
2245
2246    #[test]
2247    fn test_select_builder_creation() {
2248        let builder = SelectBuilder::<(), SelectInitial> {
2249            sql: SQL::raw("SELECT *"),
2250            schema: PhantomData,
2251            state: PhantomData,
2252            table: PhantomData,
2253            marker: PhantomData,
2254            row: PhantomData,
2255            grouped: PhantomData,
2256        };
2257
2258        assert_eq!(builder.to_sql().sql(), "SELECT *");
2259    }
2260}