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