Skip to main content

diesel/query_builder/
mod.rs

1//! Contains traits responsible for the actual construction of SQL statements
2//!
3//! The types in this module are part of Diesel's public API, but are generally
4//! only useful for implementing Diesel plugins. Applications should generally
5//! not need to care about the types inside of this module.
6
7#[macro_use]
8mod query_id;
9#[macro_use]
10mod clause_macro;
11
12pub(crate) mod ast_pass;
13pub mod bind_collector;
14mod collected_query;
15pub(crate) mod combination_clause;
16mod debug_query;
17mod delete_statement;
18mod distinct_clause;
19pub(crate) mod from_clause;
20pub(crate) mod functions;
21pub(crate) mod group_by_clause;
22mod having_clause;
23pub(crate) mod insert_statement;
24pub(crate) mod limit_clause;
25pub(crate) mod limit_offset_clause;
26pub(crate) mod locking_clause;
27pub(crate) mod nodes;
28pub(crate) mod offset_clause;
29pub(crate) mod order_clause;
30pub(crate) mod select_clause;
31pub(crate) mod select_statement;
32mod sql_query;
33pub(crate) mod update_statement;
34pub(crate) mod upsert;
35pub(crate) mod where_clause;
36
37#[doc(inline)]
38pub use self::ast_pass::AstPass;
39#[doc(inline)]
40pub use self::bind_collector::{BindCollector, MoveableBindCollector};
41#[doc(inline)]
42pub use self::collected_query::CollectedQuery;
43#[doc(inline)]
44pub use self::debug_query::DebugQuery;
45#[doc(inline)]
46pub use self::delete_statement::{
47    BoxedCloneDeleteStatement, BoxedDeleteStatement, DeleteStatement,
48};
49#[cfg(any(feature = "mysql_backend", feature = "mariadb_backend"))]
50#[doc(inline)]
51pub use self::insert_statement::SingleRowInsertValues;
52#[doc(inline)]
53pub use self::insert_statement::{
54    IncompleteInsertOrIgnoreStatement, IncompleteInsertStatement, IncompleteReplaceStatement,
55    InsertOrIgnoreStatement, InsertStatement, ReplaceStatement,
56};
57#[doc(inline)]
58pub use self::query_id::QueryId;
59#[doc(inline)]
60pub use self::sql_query::{BoxedCloneSqlQuery, BoxedSqlQuery, SqlQuery};
61#[doc(inline)]
62pub use self::upsert::into_conflict_clause::IntoConflictValueClause;
63#[doc(inline)]
64pub use self::upsert::on_conflict_target::{ConflictTarget, OnConflictTarget};
65#[doc(inline)]
66pub use self::upsert::on_conflict_target_decorations::DecoratableTarget;
67
68#[doc(inline)]
69pub use self::update_statement::changeset::AsChangeset;
70#[doc(inline)]
71pub use self::update_statement::target::{IntoUpdateTarget, UpdateTarget};
72#[doc(inline)]
73pub use self::update_statement::{
74    BoxedCloneUpdateStatement, BoxedUpdateStatement, UpdateStatement,
75};
76
77#[cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")]
78pub use self::combination_clause::{
79    All, Distinct, Except, Intersect, ParenthesisWrapper, SupportsCombinationClause, Union,
80};
81#[cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")]
82pub use self::limit_clause::{LimitClause, NoLimitClause};
83#[cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")]
84pub use self::limit_offset_clause::{
85    BoxedCloneLimitOffsetClause, BoxedLimitOffsetClause, LimitOffsetClause,
86};
87#[cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")]
88pub use self::offset_clause::{NoOffsetClause, OffsetClause};
89#[cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")]
90pub use self::order_clause::{NoOrderClause, OrderClause};
91
92#[doc(inline)]
pub use self::insert_statement::batch_insert::BatchInsert;#[diesel_derives::__diesel_public_if(
93    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
94)]
95#[doc(inline)]
96pub(crate) use self::insert_statement::batch_insert::BatchInsert;
97pub use self::insert_statement::{UndecoratedInsertRecord, ValuesClause};#[diesel_derives::__diesel_public_if(
98    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
99)]
100pub(crate) use self::insert_statement::{UndecoratedInsertRecord, ValuesClause};
101
102#[cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")]
103#[doc(inline)]
104pub use self::insert_statement::{DefaultValues, InsertOrIgnore, Replace};
105
106#[cfg(not(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"))]
107pub(crate) mod returning;
108#[cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")]
109pub mod returning;
110
111#[doc(inline)]
112#[doc(inline)]
pub use self::ast_pass::AstPassToSqlOptions;#[diesel_derives::__diesel_public_if(
113    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
114)]
115pub(crate) use self::ast_pass::AstPassToSqlOptions;
116
117#[doc(inline)]
118#[doc(inline)]
pub use self::select_clause::SelectClauseExpression;#[diesel_derives::__diesel_public_if(
119    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
120)]
121pub(crate) use self::select_clause::SelectClauseExpression;
122
123#[doc(inline)]
124#[doc(inline)]
pub use self::from_clause::{FromClause, NoFromClause};#[diesel_derives::__diesel_public_if(
125    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
126)]
127pub(crate) use self::from_clause::{FromClause, NoFromClause};
128#[doc(inline)]
pub use self::select_statement::BoxedCloneSelectStatement;#[diesel_derives::__diesel_public_if(
129    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
130)]
131#[doc(inline)]
132pub(crate) use self::select_statement::BoxedCloneSelectStatement;
133#[doc(inline)]
pub use self::select_statement::BoxedSelectStatement;#[diesel_derives::__diesel_public_if(
134    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
135)]
136#[doc(inline)]
137pub(crate) use self::select_statement::BoxedSelectStatement;
138
139#[doc(inline)]
pub use self::select_statement::SelectStatement;#[diesel_derives::__diesel_public_if(
140    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
141)]
142#[doc(inline)]
143pub(crate) use self::select_statement::SelectStatement;
144
145pub(crate) use self::insert_statement::ColumnList;
146
147#[cfg(feature = "postgres_backend")]
148pub use crate::pg::query_builder::only::Only;
149
150#[cfg(feature = "postgres_backend")]
151pub use crate::pg::query_builder::tablesample::{Tablesample, TablesampleMethod};
152
153#[cfg(feature = "postgres_backend")]
154pub(crate) use self::bind_collector::ByteWrapper;
155use crate::backend::Backend;
156use crate::result::QueryResult;
157use alloc::boxed::Box;
158use alloc::string::String;
159use alloc::vec::Vec;
160use core::error::Error;
161
162pub(crate) use self::private::NotSpecialized;
163
164#[doc(hidden)]
165pub type Binds = Vec<Option<Vec<u8>>>;
166/// A specialized Result type used with the query builder.
167pub type BuildQueryResult = Result<(), Box<dyn Error + Send + Sync>>;
168
169/// Constructs a SQL query from a Diesel AST.
170///
171/// The only reason you should ever need to interact with this trait is if you
172/// are extending Diesel with support for a new backend. Plugins which extend
173/// the query builder with new capabilities will interact with [`AstPass`]
174/// instead.
175pub trait QueryBuilder<DB: Backend> {
176    /// Add `sql` to the end of the query being constructed.
177    fn push_sql(&mut self, sql: &str);
178
179    /// Quote `identifier`, and add it to the end of the query being
180    /// constructed.
181    fn push_identifier(&mut self, identifier: &str) -> QueryResult<()>;
182
183    /// Add a placeholder for a bind parameter to the end of the query being
184    /// constructed.
185    fn push_bind_param(&mut self);
186
187    /// Increases the internal counter for bind parameters without adding the
188    /// bind parameter itself to the query
189    fn push_bind_param_value_only(&mut self) {}
190
191    /// Returns the constructed SQL query.
192    fn finish(self) -> String;
193}
194
195/// A complete SQL query with a return type.
196///
197/// This can be a select statement, or a command such as `update` or `insert`
198/// with a `RETURNING` clause. Unlike [`Expression`], types implementing this
199/// trait are guaranteed to be executable on their own.
200///
201/// A type which doesn't implement this trait may still represent a complete SQL
202/// query. For example, an `INSERT` statement without a `RETURNING` clause will
203/// not implement this trait, but can still be executed.
204///
205/// [`Expression`]: crate::expression::Expression
206pub trait Query {
207    /// The SQL type that this query represents.
208    ///
209    /// This is the SQL type of the `SELECT` clause for select statements, and
210    /// the SQL type of the `RETURNING` clause for insert, update, or delete
211    /// statements.
212    type SqlType;
213}
214
215impl<T: Query> Query for &T {
216    type SqlType = T::SqlType;
217}
218
219/// Indicates that a type is a `SELECT` statement.
220///
221/// This trait differs from `Query` in two ways:
222/// - It is implemented only for select statements, rather than all queries
223///   which return a value.
224/// - It has looser constraints. A type implementing `SelectQuery` is known to
225///   be potentially valid if used as a subselect, but it is not necessarily
226///   able to be executed.
227pub trait SelectQuery {
228    /// The SQL type of the `SELECT` clause
229    type SqlType;
230}
231
232/// An untyped fragment of SQL.
233///
234/// This may be a complete SQL command (such as an update statement without a
235/// `RETURNING` clause), or a subsection (such as our internal types used to
236/// represent a `WHERE` clause). Implementations of [`ExecuteDsl`] and
237/// [`LoadQuery`] will generally require that this trait be implemented.
238///
239/// [`ExecuteDsl`]: crate::query_dsl::methods::ExecuteDsl
240/// [`LoadQuery`]: crate::query_dsl::methods::LoadQuery
241#[diagnostic::on_unimplemented(
242    message = "`{Self}` is no valid SQL fragment for the `{DB}` backend",
243    note = "this usually means that the `{DB}` database system does not support \n\
244            this SQL syntax"
245)]
246pub trait QueryFragment<DB: Backend, SP = self::private::NotSpecialized> {
247    /// Walk over this `QueryFragment` for all passes.
248    ///
249    /// This method is where the actual behavior of an AST node is implemented.
250    /// This method will contain the behavior required for all possible AST
251    /// passes. See [`AstPass`] for more details.
252    fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()>;
253
254    /// Converts this `QueryFragment` to its SQL representation.
255    ///
256    /// This method should only be called by implementations of `Connection`.
257    #[diesel_derives::__diesel_public_if(
258        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
259    )]
260    fn to_sql(&self, out: &mut DB::QueryBuilder, backend: &DB) -> QueryResult<()> {
261        let mut options = AstPassToSqlOptions::default();
262        self.walk_ast(AstPass::to_sql(out, &mut options, backend))
263    }
264
265    /// Serializes all bind parameters in this query.
266    ///
267    /// A bind parameter is a value which is sent separately from the query
268    /// itself. It is represented in SQL with a placeholder such as `?` or `$1`.
269    ///
270    /// This method should only be called by implementations of `Connection`.
271    #[diesel_derives::__diesel_public_if(
272        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
273    )]
274    fn collect_binds<'b>(
275        &'b self,
276        out: &mut DB::BindCollector<'b>,
277        metadata_lookup: &mut DB::MetadataLookup,
278        backend: &'b DB,
279    ) -> QueryResult<()> {
280        self.walk_ast(AstPass::collect_binds(out, metadata_lookup, backend))
281    }
282
283    /// Is this query safe to store in the prepared statement cache?
284    ///
285    /// In order to keep our prepared statement cache at a reasonable size, we
286    /// avoid caching any queries which represent a potentially unbounded number
287    /// of SQL queries. Generally this will only return `true` for queries for
288    /// which `to_sql` will always construct exactly identical SQL.
289    ///
290    /// Some examples of where this method will return `false` are:
291    ///
292    /// - `SqlLiteral` (We don't know if the SQL was constructed dynamically, so
293    ///   we must assume that it was)
294    /// - `In` and `NotIn` (Each value requires a separate bind param
295    ///   placeholder)
296    ///
297    /// This method should only be called by implementations of `Connection`.
298    #[diesel_derives::__diesel_public_if(
299        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
300    )]
301    fn is_safe_to_cache_prepared(&self, backend: &DB) -> QueryResult<bool> {
302        let mut result = true;
303        self.walk_ast(AstPass::is_safe_to_cache_prepared(&mut result, backend))?;
304        Ok(result)
305    }
306
307    /// Does walking this AST have any effect?
308    #[diesel_derives::__diesel_public_if(
309        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
310    )]
311    fn is_noop(&self, backend: &DB) -> QueryResult<bool> {
312        let mut result = true;
313        self.walk_ast(AstPass::is_noop(&mut result, backend))?;
314        Ok(result)
315    }
316}
317
318impl<T: ?Sized, DB> QueryFragment<DB> for Box<T>
319where
320    DB: Backend,
321    T: QueryFragment<DB>,
322{
323    fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
324        QueryFragment::walk_ast(&**self, pass)
325    }
326}
327
328impl<T: ?Sized, DB> QueryFragment<DB> for alloc::rc::Rc<T>
329where
330    DB: Backend,
331    T: QueryFragment<DB>,
332{
333    fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
334        QueryFragment::walk_ast(&**self, pass)
335    }
336}
337
338impl<T: ?Sized, DB> QueryFragment<DB> for alloc::sync::Arc<T>
339where
340    DB: Backend,
341    T: QueryFragment<DB>,
342{
343    fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
344        QueryFragment::walk_ast(&**self, pass)
345    }
346}
347
348impl<T: ?Sized, DB> QueryFragment<DB> for &T
349where
350    DB: Backend,
351    T: QueryFragment<DB>,
352{
353    fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
354        QueryFragment::walk_ast(&**self, pass)
355    }
356}
357
358impl<DB: Backend> QueryFragment<DB> for () {
359    fn walk_ast<'b>(&'b self, _: AstPass<'_, 'b, DB>) -> QueryResult<()> {
360        Ok(())
361    }
362}
363
364impl<T, DB> QueryFragment<DB> for Option<T>
365where
366    DB: Backend,
367    T: QueryFragment<DB>,
368{
369    fn walk_ast<'b>(&'b self, out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
370        match *self {
371            Some(ref c) => c.walk_ast(out),
372            None => Ok(()),
373        }
374    }
375}
376
377/// A trait used to construct type erased boxed variant of the current query node
378///
379/// Mainly useful for implementing third party backends
380#[diagnostic::on_unimplemented(
381    note = "this usually means that `{Self}` is no valid SQL for `{DB}`"
382)]
383pub trait IntoBoxedClause<'a, DB> {
384    /// Resulting type
385    type BoxedClause;
386
387    /// Convert the given query node in it's boxed representation
388    fn into_boxed(self) -> Self::BoxedClause;
389}
390
391/// A trait used to construct type erased boxed cloneable variant of the current query node
392///
393/// Mainly useful for implementing third party backends
394#[diagnostic::on_unimplemented(
395    note = "this usually means that `{Self}` is no valid SQL for `{DB}`"
396)]
397pub trait IntoBoxedCloneClause<'a, DB> {
398    /// Resulting type
399    type BoxedCloneClause;
400
401    /// Convert the given query node in it's boxed cloneable representation
402    fn into_boxed_clone(self) -> Self::BoxedCloneClause;
403}
404
405/// Types that can be converted into a complete, typed SQL query.
406///
407/// This is used internally to automatically add the right select clause when
408/// none is specified, or to automatically add `RETURNING *` in certain contexts.
409///
410/// A type which implements this trait is guaranteed to be valid for execution.
411pub trait AsQuery {
412    /// The SQL type of `Self::Query`
413    type SqlType;
414
415    /// What kind of query does this type represent?
416    type Query: Query<SqlType = Self::SqlType>;
417
418    /// Converts a type which semantically represents a SQL query into the
419    /// actual query being executed. See the trait level docs for more.
420    // This method is part of our public API,
421    // so we won't change the name to just appease clippy
422    // (Also the trait is literally named `AsQuery` so
423    // naming the method similarity is fine)
424    #[allow(clippy::wrong_self_convention)]
425    fn as_query(self) -> Self::Query;
426}
427
428impl<T: Query> AsQuery for T {
429    type SqlType = <T as Query>::SqlType;
430    type Query = T;
431
432    fn as_query(self) -> <T as AsQuery>::Query {
433        self
434    }
435}
436
437/// Takes a query `QueryFragment` expression as an argument and returns a type
438/// that implements `fmt::Display` and `fmt::Debug` to show the query.
439///
440/// The `Display` implementation will show the exact query being sent to the
441/// server, with a comment showing the values of the bind parameters. The
442/// `Debug` implementation will include the same information in a more
443/// structured form, and respects pretty printing.
444///
445/// # Example
446///
447/// ### Returning SQL from a count statement:
448///
449/// ```rust
450/// # include!("../doctest_setup.rs");
451/// #
452/// # use diesel::*;
453/// # use schema::*;
454/// #
455/// # fn main() {
456/// #   use schema::users::dsl::*;
457/// let sql = debug_query::<DB, _>(&users.count()).to_string();
458/// # if cfg!(feature = "postgres") {
459/// #     assert_eq!(sql, r#"SELECT COUNT(*) FROM "users" -- binds: []"#);
460/// # } else {
461/// assert_eq!(sql, "SELECT COUNT(*) FROM `users` -- binds: []");
462/// # }
463///
464/// let query = users.find(1);
465/// let debug = debug_query::<DB, _>(&query);
466/// # if cfg!(feature = "postgres") {
467/// #     assert_eq!(debug.to_string(), "SELECT \"users\".\"id\", \"users\".\"name\" \
468/// #         FROM \"users\" WHERE (\"users\".\"id\" = $1) -- binds: [1]");
469/// # } else {
470/// assert_eq!(
471///     debug.to_string(),
472///     "SELECT `users`.`id`, `users`.`name` FROM `users` \
473///     WHERE (`users`.`id` = ?) -- binds: [1]"
474/// );
475/// # }
476///
477/// let debug = format!("{:?}", debug);
478/// # if !cfg!(feature = "postgres") { // Escaping that string is a pain
479/// let expected = "Query { \
480///     sql: \"SELECT `users`.`id`, `users`.`name` FROM `users` WHERE \
481///         (`users`.`id` = ?)\", \
482///     binds: [1] \
483/// }";
484/// assert_eq!(debug, expected);
485/// # }
486/// # }
487/// ```
488pub fn debug_query<DB, T>(query: &T) -> DebugQuery<'_, T, DB> {
489    DebugQuery::new(query)
490}
491
492mod private {
493    #[allow(missing_debug_implementations, missing_copy_implementations)]
494    pub struct NotSpecialized;
495}
496
497pub(crate) mod has_query;