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