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}