drizzle_postgres/builder.rs
1//! Query builders for `PostgreSQL` statements.
2//!
3//! [`QueryBuilder`] builds `SELECT`, `INSERT`, `UPDATE`, `DELETE`, `WITH` and
4//! `REFRESH MATERIALIZED VIEW` statements as SQL text plus bound parameters,
5//! without a connection. The driver integrations in the `drizzle` crate wrap
6//! it to run the statements. Each statement kind has a submodule with its
7//! builder states.
8
9use drizzle_core::Token;
10// Re-export common enums and traits from core
11pub use drizzle_core::builder::{BuilderInit, ExecutableState};
12pub use drizzle_core::{
13 OrderBy, SQL, ToSQL,
14 traits::{SQLSchema, SQLTable},
15};
16
17// Local imports
18use crate::{common::PostgresSchemaType, traits::PostgresTable, values::PostgresValue};
19use core::{fmt::Debug, marker::PhantomData};
20
21// Import modules - these provide specific builder types
22pub mod cte;
23pub mod delete;
24pub mod insert;
25pub mod prepared;
26pub mod refresh;
27pub mod select;
28pub mod update;
29
30// Re-export CTE types
31pub use cte::{CTEDefinition, CTEView};
32
33// Export state markers for easier use
34pub use delete::{DeleteInitial, DeleteReturningSet, DeleteWhereSet};
35pub use insert::{
36 InsertColumnsSet, InsertDoUpdateSet, InsertInitial, InsertOnConflictSet, InsertReturningSet,
37 InsertValuesSet, OnConflictBuilder,
38};
39pub use refresh::{
40 RefreshConcurrently, RefreshInitial, RefreshMaterializedView, RefreshWithNoData,
41 refresh_materialized_view,
42};
43pub use select::{
44 SelectForSet, SelectFromSet, SelectGroupSet, SelectInitial, SelectJoinSet, SelectLimitSet,
45 SelectOffsetSet, SelectOrderSet, SelectSetOpSet, SelectWhereSet,
46};
47pub use update::{
48 UpdateFromSet, UpdateInitial, UpdateReturningSet, UpdateSetClauseSet, UpdateWhereSet,
49};
50
51// Re-export SQLViewInfo for convenience when using refresh_materialized_view
52pub use drizzle_core::traits::SQLViewInfo;
53
54/// Builder state after `.with(cte)`: the next call starts the main statement.
55#[derive(Debug, Clone)]
56pub struct CTEInit;
57
58impl ExecutableState for CTEInit {}
59
60/// Builds `PostgreSQL` statements as SQL plus bound parameters, without a connection.
61///
62/// Create one with [`QueryBuilder::new`], then start a statement with
63/// [`select`](QueryBuilder::select), [`insert`](QueryBuilder::insert),
64/// [`update`](QueryBuilder::update), [`delete`](QueryBuilder::delete) or
65/// [`with`](QueryBuilder::with). Each call returns a builder whose type
66/// tracks the clauses added so far, so out-of-order clauses (such as
67/// `.where()` before `.from()`) do not compile. Call `.to_sql()` to get the
68/// statement. The driver crates wrap this builder to run the query.
69///
70/// `Schema` is the schema type from `#[derive(PostgresSchema)]`. The other
71/// type parameters are builder state and are inferred.
72///
73/// # Examples
74///
75/// ```rust
76/// # extern crate self as drizzle;
77/// # mod _drizzle {
78/// # pub mod core { pub use drizzle_core::*; }
79/// # pub mod error { pub use drizzle_core::error::*; }
80/// # pub mod types { pub use drizzle_types::*; }
81/// # pub mod migrations { pub use drizzle_migrations::*; }
82/// # pub use drizzle_types::Dialect;
83/// # pub use drizzle_types as ddl;
84/// # pub mod postgres {
85/// # pub mod values { pub use drizzle_postgres::values::*; }
86/// # pub mod traits { pub use drizzle_postgres::traits::*; }
87/// # pub mod common { pub use drizzle_postgres::common::*; }
88/// # pub mod attrs { pub use drizzle_postgres::attrs::*; }
89/// # pub mod builder { pub use drizzle_postgres::builder::*; }
90/// # pub mod helpers { pub use drizzle_postgres::helpers::*; }
91/// # pub mod expr { pub use drizzle_postgres::expr::*; }
92/// # pub mod types { pub use drizzle_postgres::types::*; }
93/// # #[cfg(feature = "aws-data-api")]
94/// # pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
95/// # pub struct Row;
96/// # impl Row {
97/// # pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
98/// # pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
99/// # }
100/// # pub mod prelude {
101/// # pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
102/// # pub use drizzle_postgres::attrs::*;
103/// # pub use drizzle_postgres::common::PostgresSchemaType;
104/// # pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
105/// # pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
106/// # pub use drizzle_core::*;
107/// # }
108/// # }
109/// # }
110/// # pub use _drizzle::*;
111/// # pub use const_format;
112/// # fn main() {
113/// # use drizzle::postgres::prelude::*;
114/// # use drizzle::postgres::builder::QueryBuilder;
115/// # #[PostgresTable(name = "users")]
116/// # struct User {
117/// # #[column(serial, primary)]
118/// # id: i32,
119/// # name: String,
120/// # email: Option<String>,
121/// # }
122/// # #[PostgresTable(name = "posts")]
123/// # struct Post {
124/// # #[column(serial, primary)]
125/// # id: i32,
126/// # #[column(references = User::id)]
127/// # author_id: i32,
128/// # title: String,
129/// # }
130/// # #[derive(PostgresSchema)]
131/// # struct Schema {
132/// # user: User,
133/// # post: Post,
134/// # }
135/// # let db = QueryBuilder::new::<Schema>();
136/// # let Schema { user, post } = Schema::new();
137/// use drizzle::core::expr::eq;
138///
139/// let query = db
140/// .select((user.id, user.name))
141/// .from(user)
142/// .r#where(eq(user.name, "Alice"));
143///
144/// assert_eq!(
145/// query.to_sql().sql(),
146/// r#"SELECT "users"."id", "users"."name" FROM "users" WHERE "users"."name" = $1"#
147/// );
148/// # }
149/// ```
150#[derive(Debug, Clone, Default)]
151pub struct QueryBuilder<
152 'a,
153 Schema = (),
154 State = (),
155 Table = (),
156 Marker = (),
157 Row = (),
158 Grouped = (),
159> {
160 /// The SQL built so far.
161 pub sql: SQL<'a, PostgresValue<'a>>,
162 schema: PhantomData<Schema>,
163 state: PhantomData<State>,
164 table: PhantomData<Table>,
165 marker: PhantomData<Marker>,
166 row: PhantomData<Row>,
167 grouped: PhantomData<Grouped>,
168}
169
170//------------------------------------------------------------------------------
171// QueryBuilder Implementation
172//------------------------------------------------------------------------------
173
174impl<'a, Schema, State, Table, Marker, Row, Grouped> ToSQL<'a, PostgresValue<'a>>
175 for QueryBuilder<'a, Schema, State, Table, Marker, Row, Grouped>
176{
177 fn to_sql(&self) -> SQL<'a, PostgresValue<'a>> {
178 self.sql.clone()
179 }
180}
181
182impl<'a, Schema, State, Table, Marker, Row, Grouped>
183 QueryBuilder<'a, Schema, State, Table, Marker, Row, Grouped>
184where
185 State: ExecutableState,
186{
187 /// Prepends a [sqlcommenter](https://google.github.io/sqlcommenter/) comment
188 /// to the statement.
189 ///
190 /// The text is wrapped in `/* ... */`. Any `/*` or `*/` in the input is
191 /// neutralised so it cannot end the comment early. Empty text adds nothing.
192 ///
193 /// # Examples
194 ///
195 /// ```rust
196 /// # extern crate self as drizzle;
197 /// # mod _drizzle {
198 /// # pub mod core { pub use drizzle_core::*; }
199 /// # pub mod error { pub use drizzle_core::error::*; }
200 /// # pub mod types { pub use drizzle_types::*; }
201 /// # pub mod migrations { pub use drizzle_migrations::*; }
202 /// # pub use drizzle_types::Dialect;
203 /// # pub use drizzle_types as ddl;
204 /// # pub mod postgres {
205 /// # pub mod values { pub use drizzle_postgres::values::*; }
206 /// # pub mod traits { pub use drizzle_postgres::traits::*; }
207 /// # pub mod common { pub use drizzle_postgres::common::*; }
208 /// # pub mod attrs { pub use drizzle_postgres::attrs::*; }
209 /// # pub mod builder { pub use drizzle_postgres::builder::*; }
210 /// # pub mod helpers { pub use drizzle_postgres::helpers::*; }
211 /// # pub mod expr { pub use drizzle_postgres::expr::*; }
212 /// # pub mod types { pub use drizzle_postgres::types::*; }
213 /// # #[cfg(feature = "aws-data-api")]
214 /// # pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
215 /// # pub struct Row;
216 /// # impl Row {
217 /// # pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
218 /// # pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
219 /// # }
220 /// # pub mod prelude {
221 /// # pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
222 /// # pub use drizzle_postgres::attrs::*;
223 /// # pub use drizzle_postgres::common::PostgresSchemaType;
224 /// # pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
225 /// # pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
226 /// # pub use drizzle_core::*;
227 /// # }
228 /// # }
229 /// # }
230 /// # pub use _drizzle::*;
231 /// # pub use const_format;
232 /// # fn main() {
233 /// # use drizzle::postgres::prelude::*;
234 /// # use drizzle::postgres::builder::QueryBuilder;
235 /// # #[PostgresTable(name = "users")]
236 /// # struct User {
237 /// # #[column(serial, primary)]
238 /// # id: i32,
239 /// # name: String,
240 /// # email: Option<String>,
241 /// # }
242 /// # #[PostgresTable(name = "posts")]
243 /// # struct Post {
244 /// # #[column(serial, primary)]
245 /// # id: i32,
246 /// # #[column(references = User::id)]
247 /// # author_id: i32,
248 /// # title: String,
249 /// # }
250 /// # #[derive(PostgresSchema)]
251 /// # struct Schema {
252 /// # user: User,
253 /// # post: Post,
254 /// # }
255 /// # let db = QueryBuilder::new::<Schema>();
256 /// # let Schema { user, post } = Schema::new();
257 /// let query = db.select(user.id).from(user).comment("list-users");
258 /// assert_eq!(query.to_sql().sql(), r#"/*list-users*/ SELECT "users"."id" FROM "users""#);
259 /// # }
260 /// ```
261 #[must_use]
262 pub fn comment(mut self, text: impl AsRef<str>) -> Self {
263 let fragment = drizzle_core::sql::comment::<PostgresValue<'a>>(text);
264 if fragment.chunks.is_empty() {
265 return self;
266 }
267 let existing = core::mem::replace(&mut self.sql, fragment);
268 self.sql.append_mut(existing);
269 self
270 }
271
272 /// Prepends a key-value [sqlcommenter](https://google.github.io/sqlcommenter/)
273 /// comment to the statement.
274 ///
275 /// Each pair renders as `key='value'`, URL-encoded. Pairs are sorted by
276 /// key, joined with `,` and wrapped in `/* ... */`. Pairs with an empty
277 /// value are skipped; if none remain, nothing is added.
278 ///
279 /// # Examples
280 ///
281 /// ```rust
282 /// # extern crate self as drizzle;
283 /// # mod _drizzle {
284 /// # pub mod core { pub use drizzle_core::*; }
285 /// # pub mod error { pub use drizzle_core::error::*; }
286 /// # pub mod types { pub use drizzle_types::*; }
287 /// # pub mod migrations { pub use drizzle_migrations::*; }
288 /// # pub use drizzle_types::Dialect;
289 /// # pub use drizzle_types as ddl;
290 /// # pub mod postgres {
291 /// # pub mod values { pub use drizzle_postgres::values::*; }
292 /// # pub mod traits { pub use drizzle_postgres::traits::*; }
293 /// # pub mod common { pub use drizzle_postgres::common::*; }
294 /// # pub mod attrs { pub use drizzle_postgres::attrs::*; }
295 /// # pub mod builder { pub use drizzle_postgres::builder::*; }
296 /// # pub mod helpers { pub use drizzle_postgres::helpers::*; }
297 /// # pub mod expr { pub use drizzle_postgres::expr::*; }
298 /// # pub mod types { pub use drizzle_postgres::types::*; }
299 /// # #[cfg(feature = "aws-data-api")]
300 /// # pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
301 /// # pub struct Row;
302 /// # impl Row {
303 /// # pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
304 /// # pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
305 /// # }
306 /// # pub mod prelude {
307 /// # pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
308 /// # pub use drizzle_postgres::attrs::*;
309 /// # pub use drizzle_postgres::common::PostgresSchemaType;
310 /// # pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
311 /// # pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
312 /// # pub use drizzle_core::*;
313 /// # }
314 /// # }
315 /// # }
316 /// # pub use _drizzle::*;
317 /// # pub use const_format;
318 /// # fn main() {
319 /// # use drizzle::postgres::prelude::*;
320 /// # use drizzle::postgres::builder::QueryBuilder;
321 /// # #[PostgresTable(name = "users")]
322 /// # struct User {
323 /// # #[column(serial, primary)]
324 /// # id: i32,
325 /// # name: String,
326 /// # email: Option<String>,
327 /// # }
328 /// # #[PostgresTable(name = "posts")]
329 /// # struct Post {
330 /// # #[column(serial, primary)]
331 /// # id: i32,
332 /// # #[column(references = User::id)]
333 /// # author_id: i32,
334 /// # title: String,
335 /// # }
336 /// # #[derive(PostgresSchema)]
337 /// # struct Schema {
338 /// # user: User,
339 /// # post: Post,
340 /// # }
341 /// # let db = QueryBuilder::new::<Schema>();
342 /// # let Schema { user, post } = Schema::new();
343 /// let query = db
344 /// .select(user.id)
345 /// .from(user)
346 /// .comment_tags([("route", "/users"), ("action", "list")]);
347 /// let sql = query.to_sql().sql();
348 /// assert!(sql.starts_with("/*action='list',route='%2Fusers'*/"));
349 /// # }
350 /// ```
351 #[must_use]
352 pub fn comment_tags<I, K, V>(mut self, pairs: I) -> Self
353 where
354 I: IntoIterator<Item = (K, V)>,
355 K: AsRef<str>,
356 V: AsRef<str>,
357 {
358 let fragment = drizzle_core::sql::comment_tags::<PostgresValue<'a>, _, _, _>(pairs);
359 if fragment.chunks.is_empty() {
360 return self;
361 }
362 let existing = core::mem::replace(&mut self.sql, fragment);
363 self.sql.append_mut(existing);
364 self
365 }
366}
367
368impl<'a> QueryBuilder<'a> {
369 /// Creates a query builder for schema `S`.
370 ///
371 /// # Examples
372 ///
373 /// ```rust
374 /// # extern crate self as drizzle;
375 /// # mod _drizzle {
376 /// # pub mod core { pub use drizzle_core::*; }
377 /// # pub mod error { pub use drizzle_core::error::*; }
378 /// # pub mod types { pub use drizzle_types::*; }
379 /// # pub mod migrations { pub use drizzle_migrations::*; }
380 /// # pub use drizzle_types::Dialect;
381 /// # pub use drizzle_types as ddl;
382 /// # pub mod postgres {
383 /// # pub mod values { pub use drizzle_postgres::values::*; }
384 /// # pub mod traits { pub use drizzle_postgres::traits::*; }
385 /// # pub mod common { pub use drizzle_postgres::common::*; }
386 /// # pub mod attrs { pub use drizzle_postgres::attrs::*; }
387 /// # pub mod builder { pub use drizzle_postgres::builder::*; }
388 /// # pub mod helpers { pub use drizzle_postgres::helpers::*; }
389 /// # pub mod expr { pub use drizzle_postgres::expr::*; }
390 /// # pub mod types { pub use drizzle_postgres::types::*; }
391 /// # #[cfg(feature = "aws-data-api")]
392 /// # pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
393 /// # pub struct Row;
394 /// # impl Row {
395 /// # pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
396 /// # pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
397 /// # }
398 /// # pub mod prelude {
399 /// # pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
400 /// # pub use drizzle_postgres::attrs::*;
401 /// # pub use drizzle_postgres::common::PostgresSchemaType;
402 /// # pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
403 /// # pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
404 /// # pub use drizzle_core::*;
405 /// # }
406 /// # }
407 /// # }
408 /// # pub use _drizzle::*;
409 /// # pub use const_format;
410 /// # fn main() {
411 /// # use drizzle::postgres::prelude::*;
412 /// # use drizzle::postgres::builder::QueryBuilder;
413 /// # #[PostgresTable(name = "users")]
414 /// # struct User {
415 /// # #[column(serial, primary)]
416 /// # id: i32,
417 /// # name: String,
418 /// # email: Option<String>,
419 /// # }
420 /// # #[PostgresTable(name = "posts")]
421 /// # struct Post {
422 /// # #[column(serial, primary)]
423 /// # id: i32,
424 /// # #[column(references = User::id)]
425 /// # author_id: i32,
426 /// # title: String,
427 /// # }
428 /// # #[derive(PostgresSchema)]
429 /// # struct Schema {
430 /// # user: User,
431 /// # post: Post,
432 /// # }
433 /// # let Schema { user, post } = Schema::new();
434 /// let db = QueryBuilder::new::<Schema>();
435 /// let query = db.select(()).from(user);
436 /// assert_eq!(
437 /// query.to_sql().sql(),
438 /// r#"SELECT "users"."id", "users"."name", "users"."email" FROM "users""#
439 /// );
440 /// # }
441 /// ```
442 #[must_use]
443 pub const fn new<S>() -> QueryBuilder<'a, S, BuilderInit> {
444 QueryBuilder {
445 sql: SQL::empty(),
446 schema: PhantomData,
447 state: PhantomData,
448 table: PhantomData,
449 marker: PhantomData,
450 row: PhantomData,
451 grouped: PhantomData,
452 }
453 }
454}
455
456impl<'a, Schema> QueryBuilder<'a, Schema, BuilderInit> {
457 /// Starts a `SELECT` of the given columns.
458 ///
459 /// Pass one column or expression, a tuple of them, or `()` for every
460 /// column of the `FROM` table. Continue with `.from(table)`.
461 ///
462 /// # Examples
463 ///
464 /// ```rust
465 /// # extern crate self as drizzle;
466 /// # mod _drizzle {
467 /// # pub mod core { pub use drizzle_core::*; }
468 /// # pub mod error { pub use drizzle_core::error::*; }
469 /// # pub mod types { pub use drizzle_types::*; }
470 /// # pub mod migrations { pub use drizzle_migrations::*; }
471 /// # pub use drizzle_types::Dialect;
472 /// # pub use drizzle_types as ddl;
473 /// # pub mod postgres {
474 /// # pub mod values { pub use drizzle_postgres::values::*; }
475 /// # pub mod traits { pub use drizzle_postgres::traits::*; }
476 /// # pub mod common { pub use drizzle_postgres::common::*; }
477 /// # pub mod attrs { pub use drizzle_postgres::attrs::*; }
478 /// # pub mod builder { pub use drizzle_postgres::builder::*; }
479 /// # pub mod helpers { pub use drizzle_postgres::helpers::*; }
480 /// # pub mod expr { pub use drizzle_postgres::expr::*; }
481 /// # pub mod types { pub use drizzle_postgres::types::*; }
482 /// # #[cfg(feature = "aws-data-api")]
483 /// # pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
484 /// # pub struct Row;
485 /// # impl Row {
486 /// # pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
487 /// # pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
488 /// # }
489 /// # pub mod prelude {
490 /// # pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
491 /// # pub use drizzle_postgres::attrs::*;
492 /// # pub use drizzle_postgres::common::PostgresSchemaType;
493 /// # pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
494 /// # pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
495 /// # pub use drizzle_core::*;
496 /// # }
497 /// # }
498 /// # }
499 /// # pub use _drizzle::*;
500 /// # pub use const_format;
501 /// # fn main() {
502 /// # use drizzle::postgres::prelude::*;
503 /// # use drizzle::postgres::builder::QueryBuilder;
504 /// # #[PostgresTable(name = "users")]
505 /// # struct User {
506 /// # #[column(serial, primary)]
507 /// # id: i32,
508 /// # name: String,
509 /// # email: Option<String>,
510 /// # }
511 /// # #[PostgresTable(name = "posts")]
512 /// # struct Post {
513 /// # #[column(serial, primary)]
514 /// # id: i32,
515 /// # #[column(references = User::id)]
516 /// # author_id: i32,
517 /// # title: String,
518 /// # }
519 /// # #[derive(PostgresSchema)]
520 /// # struct Schema {
521 /// # user: User,
522 /// # post: Post,
523 /// # }
524 /// # let db = QueryBuilder::new::<Schema>();
525 /// # let Schema { user, post } = Schema::new();
526 /// use drizzle::core::expr::eq;
527 ///
528 /// let query = db
529 /// .select((user.name, post.title))
530 /// .from(user)
531 /// .join((post, eq(post.author_id, user.id)));
532 /// assert_eq!(
533 /// query.to_sql().sql(),
534 /// r#"SELECT "users"."name", "posts"."title" FROM "users" JOIN "posts" ON "posts"."author_id" = "users"."id""#
535 /// );
536 /// # }
537 /// ```
538 pub fn select<T>(
539 &self,
540 columns: T,
541 ) -> select::SelectBuilder<'a, Schema, select::SelectInitial, (), T::Marker>
542 where
543 T: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
544 {
545 let sql = crate::helpers::select(columns);
546 select::SelectBuilder {
547 sql,
548 schema: PhantomData,
549 state: PhantomData,
550 table: PhantomData,
551 marker: PhantomData,
552 row: PhantomData,
553 grouped: PhantomData,
554 }
555 }
556
557 /// Starts a `SELECT DISTINCT`, which drops duplicate rows.
558 ///
559 /// # Examples
560 ///
561 /// ```rust
562 /// # extern crate self as drizzle;
563 /// # mod _drizzle {
564 /// # pub mod core { pub use drizzle_core::*; }
565 /// # pub mod error { pub use drizzle_core::error::*; }
566 /// # pub mod types { pub use drizzle_types::*; }
567 /// # pub mod migrations { pub use drizzle_migrations::*; }
568 /// # pub use drizzle_types::Dialect;
569 /// # pub use drizzle_types as ddl;
570 /// # pub mod postgres {
571 /// # pub mod values { pub use drizzle_postgres::values::*; }
572 /// # pub mod traits { pub use drizzle_postgres::traits::*; }
573 /// # pub mod common { pub use drizzle_postgres::common::*; }
574 /// # pub mod attrs { pub use drizzle_postgres::attrs::*; }
575 /// # pub mod builder { pub use drizzle_postgres::builder::*; }
576 /// # pub mod helpers { pub use drizzle_postgres::helpers::*; }
577 /// # pub mod expr { pub use drizzle_postgres::expr::*; }
578 /// # pub mod types { pub use drizzle_postgres::types::*; }
579 /// # #[cfg(feature = "aws-data-api")]
580 /// # pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
581 /// # pub struct Row;
582 /// # impl Row {
583 /// # pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
584 /// # pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
585 /// # }
586 /// # pub mod prelude {
587 /// # pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
588 /// # pub use drizzle_postgres::attrs::*;
589 /// # pub use drizzle_postgres::common::PostgresSchemaType;
590 /// # pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
591 /// # pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
592 /// # pub use drizzle_core::*;
593 /// # }
594 /// # }
595 /// # }
596 /// # pub use _drizzle::*;
597 /// # pub use const_format;
598 /// # fn main() {
599 /// # use drizzle::postgres::prelude::*;
600 /// # use drizzle::postgres::builder::QueryBuilder;
601 /// # #[PostgresTable(name = "users")]
602 /// # struct User {
603 /// # #[column(serial, primary)]
604 /// # id: i32,
605 /// # name: String,
606 /// # email: Option<String>,
607 /// # }
608 /// # #[PostgresTable(name = "posts")]
609 /// # struct Post {
610 /// # #[column(serial, primary)]
611 /// # id: i32,
612 /// # #[column(references = User::id)]
613 /// # author_id: i32,
614 /// # title: String,
615 /// # }
616 /// # #[derive(PostgresSchema)]
617 /// # struct Schema {
618 /// # user: User,
619 /// # post: Post,
620 /// # }
621 /// # let db = QueryBuilder::new::<Schema>();
622 /// # let Schema { user, post } = Schema::new();
623 /// let query = db.select_distinct(user.name).from(user);
624 /// assert_eq!(query.to_sql().sql(), r#"SELECT DISTINCT "users"."name" FROM "users""#);
625 /// # }
626 /// ```
627 pub fn select_distinct<T>(
628 &self,
629 columns: T,
630 ) -> select::SelectBuilder<'a, Schema, select::SelectInitial, (), T::Marker>
631 where
632 T: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
633 {
634 let sql = crate::helpers::select_distinct(columns);
635 select::SelectBuilder {
636 sql,
637 schema: PhantomData,
638 state: PhantomData,
639 table: PhantomData,
640 marker: PhantomData,
641 row: PhantomData,
642 grouped: PhantomData,
643 }
644 }
645
646 /// Starts a `SELECT DISTINCT ON (...)`, which keeps one row per distinct
647 /// value of `on`.
648 ///
649 /// The first row of each group wins, so add an `order_by` that starts
650 /// with the `on` columns to choose which row is kept.
651 ///
652 /// # Examples
653 ///
654 /// ```rust
655 /// # extern crate self as drizzle;
656 /// # mod _drizzle {
657 /// # pub mod core { pub use drizzle_core::*; }
658 /// # pub mod error { pub use drizzle_core::error::*; }
659 /// # pub mod types { pub use drizzle_types::*; }
660 /// # pub mod migrations { pub use drizzle_migrations::*; }
661 /// # pub use drizzle_types::Dialect;
662 /// # pub use drizzle_types as ddl;
663 /// # pub mod postgres {
664 /// # pub mod values { pub use drizzle_postgres::values::*; }
665 /// # pub mod traits { pub use drizzle_postgres::traits::*; }
666 /// # pub mod common { pub use drizzle_postgres::common::*; }
667 /// # pub mod attrs { pub use drizzle_postgres::attrs::*; }
668 /// # pub mod builder { pub use drizzle_postgres::builder::*; }
669 /// # pub mod helpers { pub use drizzle_postgres::helpers::*; }
670 /// # pub mod expr { pub use drizzle_postgres::expr::*; }
671 /// # pub mod types { pub use drizzle_postgres::types::*; }
672 /// # #[cfg(feature = "aws-data-api")]
673 /// # pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
674 /// # pub struct Row;
675 /// # impl Row {
676 /// # pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
677 /// # pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
678 /// # }
679 /// # pub mod prelude {
680 /// # pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
681 /// # pub use drizzle_postgres::attrs::*;
682 /// # pub use drizzle_postgres::common::PostgresSchemaType;
683 /// # pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
684 /// # pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
685 /// # pub use drizzle_core::*;
686 /// # }
687 /// # }
688 /// # }
689 /// # pub use _drizzle::*;
690 /// # pub use const_format;
691 /// # fn main() {
692 /// # use drizzle::postgres::prelude::*;
693 /// # use drizzle::postgres::builder::QueryBuilder;
694 /// # #[PostgresTable(name = "users")]
695 /// # struct User {
696 /// # #[column(serial, primary)]
697 /// # id: i32,
698 /// # name: String,
699 /// # email: Option<String>,
700 /// # }
701 /// # #[PostgresTable(name = "posts")]
702 /// # struct Post {
703 /// # #[column(serial, primary)]
704 /// # id: i32,
705 /// # #[column(references = User::id)]
706 /// # author_id: i32,
707 /// # title: String,
708 /// # }
709 /// # #[derive(PostgresSchema)]
710 /// # struct Schema {
711 /// # user: User,
712 /// # post: Post,
713 /// # }
714 /// # let db = QueryBuilder::new::<Schema>();
715 /// # let Schema { user, post } = Schema::new();
716 /// let query = db
717 /// .select_distinct_on(user.email, (user.id, user.email))
718 /// .from(user)
719 /// .order_by(user.email);
720 /// assert_eq!(
721 /// query.to_sql().sql(),
722 /// r#"SELECT DISTINCT ON ("users"."email") "users"."id", "users"."email" FROM "users" ORDER BY "users"."email""#
723 /// );
724 /// # }
725 /// ```
726 pub fn select_distinct_on<On, Columns>(
727 &self,
728 on: On,
729 columns: Columns,
730 ) -> select::SelectBuilder<'a, Schema, select::SelectInitial, (), Columns::Marker>
731 where
732 On: ToSQL<'a, PostgresValue<'a>>,
733 Columns: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
734 {
735 let sql = crate::helpers::select_distinct_on(on, columns);
736 select::SelectBuilder {
737 sql,
738 schema: PhantomData,
739 state: PhantomData,
740 table: PhantomData,
741 marker: PhantomData,
742 row: PhantomData,
743 grouped: PhantomData,
744 }
745 }
746}
747
748impl<'a, Schema> QueryBuilder<'a, Schema, CTEInit> {
749 /// Starts the main `SELECT` after `WITH ...`. See [`QueryBuilder::with`].
750 pub fn select<T>(
751 &self,
752 columns: T,
753 ) -> select::SelectBuilder<'a, Schema, select::SelectInitial, (), T::Marker>
754 where
755 T: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
756 {
757 let sql = self.sql.clone().append(crate::helpers::select(columns));
758 select::SelectBuilder {
759 sql,
760 schema: PhantomData,
761 state: PhantomData,
762 table: PhantomData,
763 marker: PhantomData,
764 row: PhantomData,
765 grouped: PhantomData,
766 }
767 }
768
769 /// Starts the main `SELECT DISTINCT` after `WITH ...`.
770 pub fn select_distinct<T>(
771 &self,
772 columns: T,
773 ) -> select::SelectBuilder<'a, Schema, select::SelectInitial, (), T::Marker>
774 where
775 T: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
776 {
777 let sql = self
778 .sql
779 .clone()
780 .append(crate::helpers::select_distinct(columns));
781 select::SelectBuilder {
782 sql,
783 schema: PhantomData,
784 state: PhantomData,
785 table: PhantomData,
786 marker: PhantomData,
787 row: PhantomData,
788 grouped: PhantomData,
789 }
790 }
791
792 /// Starts the main `SELECT DISTINCT ON (...)` after `WITH ...`.
793 pub fn select_distinct_on<On, Columns>(
794 &self,
795 on: On,
796 columns: Columns,
797 ) -> select::SelectBuilder<'a, Schema, select::SelectInitial, (), Columns::Marker>
798 where
799 On: ToSQL<'a, PostgresValue<'a>>,
800 Columns: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
801 {
802 let sql = self
803 .sql
804 .clone()
805 .append(crate::helpers::select_distinct_on(on, columns));
806 select::SelectBuilder {
807 sql,
808 schema: PhantomData,
809 state: PhantomData,
810 table: PhantomData,
811 marker: PhantomData,
812 row: PhantomData,
813 grouped: PhantomData,
814 }
815 }
816
817 /// Starts the main `INSERT` after `WITH ...`.
818 pub fn insert<Table>(
819 &self,
820 table: Table,
821 ) -> insert::InsertBuilder<'a, Schema, insert::InsertInitial, Table>
822 where
823 Table: PostgresTable<'a>,
824 {
825 let sql = self
826 .sql
827 .clone()
828 .append(crate::helpers::insert::<Table>(&table));
829
830 insert::InsertBuilder {
831 sql,
832 schema: PhantomData,
833 state: PhantomData,
834 table: PhantomData,
835 marker: PhantomData,
836 row: PhantomData,
837 grouped: PhantomData,
838 }
839 }
840
841 /// Starts the main `UPDATE` after `WITH ...`.
842 pub fn update<Table>(
843 &self,
844 table: Table,
845 ) -> update::UpdateBuilder<'a, Schema, update::UpdateInitial, Table>
846 where
847 Table: PostgresTable<'a>,
848 {
849 let sql = self.sql.clone().append(crate::helpers::update::<
850 Table,
851 PostgresSchemaType,
852 PostgresValue<'a>,
853 >(&table));
854
855 update::UpdateBuilder {
856 sql,
857 schema: PhantomData,
858 state: PhantomData,
859 table: PhantomData,
860 marker: PhantomData,
861 row: PhantomData,
862 grouped: PhantomData,
863 }
864 }
865
866 /// Starts the main `DELETE` after `WITH ...`.
867 pub fn delete<Table>(
868 &self,
869 table: Table,
870 ) -> delete::DeleteBuilder<'a, Schema, delete::DeleteInitial, Table>
871 where
872 Table: PostgresTable<'a>,
873 {
874 let sql = self.sql.clone().append(crate::helpers::delete::<
875 Table,
876 PostgresSchemaType,
877 PostgresValue<'a>,
878 >(&table));
879
880 delete::DeleteBuilder {
881 sql,
882 schema: PhantomData,
883 state: PhantomData,
884 table: PhantomData,
885 marker: PhantomData,
886 row: PhantomData,
887 grouped: PhantomData,
888 }
889 }
890
891 /// Adds another common table expression to the `WITH` list.
892 #[must_use]
893 pub fn with<C>(&self, cte: &C) -> Self
894 where
895 C: CTEDefinition<'a>,
896 {
897 let sql = self
898 .sql
899 .clone()
900 .push(Token::COMMA)
901 .append(cte.cte_definition());
902 QueryBuilder {
903 sql,
904 schema: PhantomData,
905 state: PhantomData,
906 table: PhantomData,
907 marker: PhantomData,
908 row: PhantomData,
909 grouped: PhantomData,
910 }
911 }
912}
913
914impl<'a, Schema> QueryBuilder<'a, Schema, BuilderInit> {
915 /// Starts an `INSERT INTO table`. Continue with `.values(...)` or `.select(...)`.
916 ///
917 /// # Examples
918 ///
919 /// ```rust
920 /// # extern crate self as drizzle;
921 /// # mod _drizzle {
922 /// # pub mod core { pub use drizzle_core::*; }
923 /// # pub mod error { pub use drizzle_core::error::*; }
924 /// # pub mod types { pub use drizzle_types::*; }
925 /// # pub mod migrations { pub use drizzle_migrations::*; }
926 /// # pub use drizzle_types::Dialect;
927 /// # pub use drizzle_types as ddl;
928 /// # pub mod postgres {
929 /// # pub mod values { pub use drizzle_postgres::values::*; }
930 /// # pub mod traits { pub use drizzle_postgres::traits::*; }
931 /// # pub mod common { pub use drizzle_postgres::common::*; }
932 /// # pub mod attrs { pub use drizzle_postgres::attrs::*; }
933 /// # pub mod builder { pub use drizzle_postgres::builder::*; }
934 /// # pub mod helpers { pub use drizzle_postgres::helpers::*; }
935 /// # pub mod expr { pub use drizzle_postgres::expr::*; }
936 /// # pub mod types { pub use drizzle_postgres::types::*; }
937 /// # #[cfg(feature = "aws-data-api")]
938 /// # pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
939 /// # pub struct Row;
940 /// # impl Row {
941 /// # pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
942 /// # pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
943 /// # }
944 /// # pub mod prelude {
945 /// # pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
946 /// # pub use drizzle_postgres::attrs::*;
947 /// # pub use drizzle_postgres::common::PostgresSchemaType;
948 /// # pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
949 /// # pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
950 /// # pub use drizzle_core::*;
951 /// # }
952 /// # }
953 /// # }
954 /// # pub use _drizzle::*;
955 /// # pub use const_format;
956 /// # fn main() {
957 /// # use drizzle::postgres::prelude::*;
958 /// # use drizzle::postgres::builder::QueryBuilder;
959 /// # #[PostgresTable(name = "users")]
960 /// # struct User {
961 /// # #[column(serial, primary)]
962 /// # id: i32,
963 /// # name: String,
964 /// # email: Option<String>,
965 /// # }
966 /// # #[PostgresTable(name = "posts")]
967 /// # struct Post {
968 /// # #[column(serial, primary)]
969 /// # id: i32,
970 /// # #[column(references = User::id)]
971 /// # author_id: i32,
972 /// # title: String,
973 /// # }
974 /// # #[derive(PostgresSchema)]
975 /// # struct Schema {
976 /// # user: User,
977 /// # post: Post,
978 /// # }
979 /// # let db = QueryBuilder::new::<Schema>();
980 /// # let Schema { user, post } = Schema::new();
981 /// let query = db.insert(user).values([InsertUser::new("Alice")]);
982 /// assert_eq!(query.to_sql().sql(), r#"INSERT INTO "users" ("name") VALUES ($1)"#);
983 /// # }
984 /// ```
985 pub fn insert<Table>(
986 &self,
987 table: Table,
988 ) -> insert::InsertBuilder<'a, Schema, insert::InsertInitial, Table>
989 where
990 Table: PostgresTable<'a>,
991 {
992 let sql = crate::helpers::insert::<Table>(&table);
993
994 insert::InsertBuilder {
995 sql,
996 schema: PhantomData,
997 state: PhantomData,
998 table: PhantomData,
999 marker: PhantomData,
1000 row: PhantomData,
1001 grouped: PhantomData,
1002 }
1003 }
1004
1005 /// Starts an `UPDATE table`. Continue with `.set(...)`.
1006 ///
1007 /// # Examples
1008 ///
1009 /// ```rust
1010 /// # extern crate self as drizzle;
1011 /// # mod _drizzle {
1012 /// # pub mod core { pub use drizzle_core::*; }
1013 /// # pub mod error { pub use drizzle_core::error::*; }
1014 /// # pub mod types { pub use drizzle_types::*; }
1015 /// # pub mod migrations { pub use drizzle_migrations::*; }
1016 /// # pub use drizzle_types::Dialect;
1017 /// # pub use drizzle_types as ddl;
1018 /// # pub mod postgres {
1019 /// # pub mod values { pub use drizzle_postgres::values::*; }
1020 /// # pub mod traits { pub use drizzle_postgres::traits::*; }
1021 /// # pub mod common { pub use drizzle_postgres::common::*; }
1022 /// # pub mod attrs { pub use drizzle_postgres::attrs::*; }
1023 /// # pub mod builder { pub use drizzle_postgres::builder::*; }
1024 /// # pub mod helpers { pub use drizzle_postgres::helpers::*; }
1025 /// # pub mod expr { pub use drizzle_postgres::expr::*; }
1026 /// # pub mod types { pub use drizzle_postgres::types::*; }
1027 /// # #[cfg(feature = "aws-data-api")]
1028 /// # pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
1029 /// # pub struct Row;
1030 /// # impl Row {
1031 /// # pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
1032 /// # pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
1033 /// # }
1034 /// # pub mod prelude {
1035 /// # pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
1036 /// # pub use drizzle_postgres::attrs::*;
1037 /// # pub use drizzle_postgres::common::PostgresSchemaType;
1038 /// # pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
1039 /// # pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
1040 /// # pub use drizzle_core::*;
1041 /// # }
1042 /// # }
1043 /// # }
1044 /// # pub use _drizzle::*;
1045 /// # pub use const_format;
1046 /// # fn main() {
1047 /// # use drizzle::postgres::prelude::*;
1048 /// # use drizzle::postgres::builder::QueryBuilder;
1049 /// # #[PostgresTable(name = "users")]
1050 /// # struct User {
1051 /// # #[column(serial, primary)]
1052 /// # id: i32,
1053 /// # name: String,
1054 /// # email: Option<String>,
1055 /// # }
1056 /// # #[PostgresTable(name = "posts")]
1057 /// # struct Post {
1058 /// # #[column(serial, primary)]
1059 /// # id: i32,
1060 /// # #[column(references = User::id)]
1061 /// # author_id: i32,
1062 /// # title: String,
1063 /// # }
1064 /// # #[derive(PostgresSchema)]
1065 /// # struct Schema {
1066 /// # user: User,
1067 /// # post: Post,
1068 /// # }
1069 /// # let db = QueryBuilder::new::<Schema>();
1070 /// # let Schema { user, post } = Schema::new();
1071 /// use drizzle::core::expr::eq;
1072 ///
1073 /// let query = db
1074 /// .update(user)
1075 /// .set(UpdateUser::default().with_name("Bob"))
1076 /// .r#where(eq(user.id, 1));
1077 /// assert_eq!(
1078 /// query.to_sql().sql(),
1079 /// r#"UPDATE "users" SET "name" = $1 WHERE "users"."id" = $2"#
1080 /// );
1081 /// # }
1082 /// ```
1083 pub fn update<Table>(
1084 &self,
1085 table: Table,
1086 ) -> update::UpdateBuilder<'a, Schema, update::UpdateInitial, Table>
1087 where
1088 Table: PostgresTable<'a>,
1089 {
1090 let sql = crate::helpers::update::<Table, PostgresSchemaType, PostgresValue<'a>>(&table);
1091
1092 update::UpdateBuilder {
1093 sql,
1094 schema: PhantomData,
1095 state: PhantomData,
1096 table: PhantomData,
1097 marker: PhantomData,
1098 row: PhantomData,
1099 grouped: PhantomData,
1100 }
1101 }
1102
1103 /// Starts a `DELETE FROM table`.
1104 ///
1105 /// Without `.where(...)` the statement deletes every row.
1106 ///
1107 /// # Examples
1108 ///
1109 /// ```rust
1110 /// # extern crate self as drizzle;
1111 /// # mod _drizzle {
1112 /// # pub mod core { pub use drizzle_core::*; }
1113 /// # pub mod error { pub use drizzle_core::error::*; }
1114 /// # pub mod types { pub use drizzle_types::*; }
1115 /// # pub mod migrations { pub use drizzle_migrations::*; }
1116 /// # pub use drizzle_types::Dialect;
1117 /// # pub use drizzle_types as ddl;
1118 /// # pub mod postgres {
1119 /// # pub mod values { pub use drizzle_postgres::values::*; }
1120 /// # pub mod traits { pub use drizzle_postgres::traits::*; }
1121 /// # pub mod common { pub use drizzle_postgres::common::*; }
1122 /// # pub mod attrs { pub use drizzle_postgres::attrs::*; }
1123 /// # pub mod builder { pub use drizzle_postgres::builder::*; }
1124 /// # pub mod helpers { pub use drizzle_postgres::helpers::*; }
1125 /// # pub mod expr { pub use drizzle_postgres::expr::*; }
1126 /// # pub mod types { pub use drizzle_postgres::types::*; }
1127 /// # #[cfg(feature = "aws-data-api")]
1128 /// # pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
1129 /// # pub struct Row;
1130 /// # impl Row {
1131 /// # pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
1132 /// # pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
1133 /// # }
1134 /// # pub mod prelude {
1135 /// # pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
1136 /// # pub use drizzle_postgres::attrs::*;
1137 /// # pub use drizzle_postgres::common::PostgresSchemaType;
1138 /// # pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
1139 /// # pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
1140 /// # pub use drizzle_core::*;
1141 /// # }
1142 /// # }
1143 /// # }
1144 /// # pub use _drizzle::*;
1145 /// # pub use const_format;
1146 /// # fn main() {
1147 /// # use drizzle::postgres::prelude::*;
1148 /// # use drizzle::postgres::builder::QueryBuilder;
1149 /// # #[PostgresTable(name = "users")]
1150 /// # struct User {
1151 /// # #[column(serial, primary)]
1152 /// # id: i32,
1153 /// # name: String,
1154 /// # email: Option<String>,
1155 /// # }
1156 /// # #[PostgresTable(name = "posts")]
1157 /// # struct Post {
1158 /// # #[column(serial, primary)]
1159 /// # id: i32,
1160 /// # #[column(references = User::id)]
1161 /// # author_id: i32,
1162 /// # title: String,
1163 /// # }
1164 /// # #[derive(PostgresSchema)]
1165 /// # struct Schema {
1166 /// # user: User,
1167 /// # post: Post,
1168 /// # }
1169 /// # let db = QueryBuilder::new::<Schema>();
1170 /// # let Schema { user, post } = Schema::new();
1171 /// use drizzle::core::expr::gt;
1172 ///
1173 /// let query = db.delete(user).r#where(gt(user.id, 10));
1174 /// assert_eq!(query.to_sql().sql(), r#"DELETE FROM "users" WHERE "users"."id" > $1"#);
1175 /// # }
1176 /// ```
1177 pub fn delete<Table>(
1178 &self,
1179 table: Table,
1180 ) -> delete::DeleteBuilder<'a, Schema, delete::DeleteInitial, Table>
1181 where
1182 Table: PostgresTable<'a>,
1183 {
1184 let sql = crate::helpers::delete::<Table, PostgresSchemaType, PostgresValue<'a>>(&table);
1185
1186 delete::DeleteBuilder {
1187 sql,
1188 schema: PhantomData,
1189 state: PhantomData,
1190 table: PhantomData,
1191 marker: PhantomData,
1192 row: PhantomData,
1193 grouped: PhantomData,
1194 }
1195 }
1196
1197 /// Starts a `WITH` clause from a common table expression (CTE).
1198 ///
1199 /// Build the CTE with `SelectBuilder::into_cte::<Tag>()`, then reference
1200 /// it in the main statement through its `.table` field. Chain more
1201 /// `.with(...)` calls to add more CTEs.
1202 ///
1203 /// # Examples
1204 ///
1205 /// ```rust
1206 /// # extern crate self as drizzle;
1207 /// # mod _drizzle {
1208 /// # pub mod core { pub use drizzle_core::*; }
1209 /// # pub mod error { pub use drizzle_core::error::*; }
1210 /// # pub mod types { pub use drizzle_types::*; }
1211 /// # pub mod migrations { pub use drizzle_migrations::*; }
1212 /// # pub use drizzle_types::Dialect;
1213 /// # pub use drizzle_types as ddl;
1214 /// # pub mod postgres {
1215 /// # pub mod values { pub use drizzle_postgres::values::*; }
1216 /// # pub mod traits { pub use drizzle_postgres::traits::*; }
1217 /// # pub mod common { pub use drizzle_postgres::common::*; }
1218 /// # pub mod attrs { pub use drizzle_postgres::attrs::*; }
1219 /// # pub mod builder { pub use drizzle_postgres::builder::*; }
1220 /// # pub mod helpers { pub use drizzle_postgres::helpers::*; }
1221 /// # pub mod expr { pub use drizzle_postgres::expr::*; }
1222 /// # pub mod types { pub use drizzle_postgres::types::*; }
1223 /// # #[cfg(feature = "aws-data-api")]
1224 /// # pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
1225 /// # pub struct Row;
1226 /// # impl Row {
1227 /// # pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
1228 /// # pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
1229 /// # }
1230 /// # pub mod prelude {
1231 /// # pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
1232 /// # pub use drizzle_postgres::attrs::*;
1233 /// # pub use drizzle_postgres::common::PostgresSchemaType;
1234 /// # pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
1235 /// # pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
1236 /// # pub use drizzle_core::*;
1237 /// # }
1238 /// # }
1239 /// # }
1240 /// # pub use _drizzle::*;
1241 /// # pub use const_format;
1242 /// # fn main() {
1243 /// # use drizzle::postgres::prelude::*;
1244 /// # use drizzle::postgres::builder::QueryBuilder;
1245 /// # #[PostgresTable(name = "users")]
1246 /// # struct User {
1247 /// # #[column(serial, primary)]
1248 /// # id: i32,
1249 /// # name: String,
1250 /// # email: Option<String>,
1251 /// # }
1252 /// # #[PostgresTable(name = "posts")]
1253 /// # struct Post {
1254 /// # #[column(serial, primary)]
1255 /// # id: i32,
1256 /// # #[column(references = User::id)]
1257 /// # author_id: i32,
1258 /// # title: String,
1259 /// # }
1260 /// # #[derive(PostgresSchema)]
1261 /// # struct Schema {
1262 /// # user: User,
1263 /// # post: Post,
1264 /// # }
1265 /// # let db = QueryBuilder::new::<Schema>();
1266 /// # let Schema { user, post } = Schema::new();
1267 /// use drizzle::core::expr::gt;
1268 ///
1269 /// struct Recent;
1270 /// impl drizzle::core::Tag for Recent {
1271 /// const NAME: &'static str = "recent";
1272 /// }
1273 ///
1274 /// let recent = db
1275 /// .select((user.id, user.name))
1276 /// .from(user)
1277 /// .r#where(gt(user.id, 100))
1278 /// .into_cte::<Recent>();
1279 /// let r = recent.table;
1280 ///
1281 /// let query = db.with(&recent).select(r.name).from(&recent);
1282 /// assert_eq!(
1283 /// query.to_sql().sql(),
1284 /// r#"WITH "recent" AS (SELECT "users"."id", "users"."name" FROM "users" WHERE "users"."id" > $1) SELECT "recent"."name" FROM "recent""#
1285 /// );
1286 /// # }
1287 /// ```
1288 pub fn with<C>(&self, cte: &C) -> QueryBuilder<'a, Schema, CTEInit>
1289 where
1290 C: CTEDefinition<'a>,
1291 {
1292 let sql = SQL::from(Token::WITH).append(cte.cte_definition());
1293 QueryBuilder {
1294 sql,
1295 schema: PhantomData,
1296 state: PhantomData,
1297 table: PhantomData,
1298 marker: PhantomData,
1299 row: PhantomData,
1300 grouped: PhantomData,
1301 }
1302 }
1303}
1304
1305#[cfg(test)]
1306mod tests {
1307 use super::*;
1308
1309 #[test]
1310 fn test_query_builder_new() {
1311 let qb = QueryBuilder::new::<()>();
1312 let sql = qb.to_sql();
1313 assert_eq!(sql.sql(), "");
1314 assert_eq!(sql.params().count(), 0);
1315 }
1316
1317 #[test]
1318 fn test_builder_init_type() {
1319 let _state = BuilderInit;
1320 }
1321}