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