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.
67#[macro_use]
8mod query_id;
9#[macro_use]
10mod clause_macro;
1112pub(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;
3738#[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;
5960#[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};
6667#[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#[cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")]
74pub use self::order_clause::{NoOrderClause, OrderClause};
7576#[diesel_derives::__diesel_public_if(
77 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
78)]
79#[doc(inline)]
80pub(crate) use self::insert_statement::batch_insert::BatchInsert;
81#[diesel_derives::__diesel_public_if(
82 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
83)]
84pub(crate) use self::insert_statement::{UndecoratedInsertRecord, ValuesClause};
8586#[cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")]
87#[doc(inline)]
88pub use self::insert_statement::DefaultValues;
8990#[cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")]
91#[doc(inline)]
92pub use self::returning_clause::ReturningClause;
9394#[doc(inline)]
95#[diesel_derives::__diesel_public_if(
96 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
97)]
98pub(crate) use self::ast_pass::AstPassToSqlOptions;
99100#[doc(inline)]
101#[diesel_derives::__diesel_public_if(
102 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
103)]
104pub(crate) use self::select_clause::SelectClauseExpression;
105106#[doc(inline)]
107#[diesel_derives::__diesel_public_if(
108 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
109)]
110pub(crate) use self::from_clause::{FromClause, NoFromClause};
111#[diesel_derives::__diesel_public_if(
112 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
113)]
114#[doc(inline)]
115pub(crate) use self::select_statement::BoxedSelectStatement;
116117#[diesel_derives::__diesel_public_if(
118 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
119)]
120#[doc(inline)]
121pub(crate) use self::select_statement::SelectStatement;
122123pub(crate) use self::insert_statement::ColumnList;
124125#[cfg(feature = "postgres_backend")]
126pub use crate::pg::query_builder::only::Only;
127128#[cfg(feature = "postgres_backend")]
129pub use crate::pg::query_builder::tablesample::{Tablesample, TablesampleMethod};
130131#[cfg(feature = "postgres_backend")]
132pub(crate) use self::bind_collector::ByteWrapper;
133use crate::backend::Backend;
134use crate::result::QueryResult;
135use std::error::Error;
136137#[doc(hidden)]
138pub type Binds = Vec<Option<Vec<u8>>>;
139/// A specialized Result type used with the query builder.
140pub type BuildQueryResult = Result<(), Box<dyn Error + Send + Sync>>;
141142/// Constructs a SQL query from a Diesel AST.
143///
144/// The only reason you should ever need to interact with this trait is if you
145/// are extending Diesel with support for a new backend. Plugins which extend
146/// the query builder with new capabilities will interact with [`AstPass`]
147/// instead.
148///
149pub trait QueryBuilder<DB: Backend> {
150/// Add `sql` to the end of the query being constructed.
151fn push_sql(&mut self, sql: &str);
152153/// Quote `identifier`, and add it to the end of the query being
154 /// constructed.
155fn push_identifier(&mut self, identifier: &str) -> QueryResult<()>;
156157/// Add a placeholder for a bind parameter to the end of the query being
158 /// constructed.
159fn push_bind_param(&mut self);
160161/// Increases the internal counter for bind parameters without adding the
162 /// bind parameter itself to the query
163fn push_bind_param_value_only(&mut self) {}
164165/// Returns the constructed SQL query.
166fn finish(self) -> String;
167}
168169/// A complete SQL query with a return type.
170///
171/// This can be a select statement, or a command such as `update` or `insert`
172/// with a `RETURNING` clause. Unlike [`Expression`], types implementing this
173/// trait are guaranteed to be executable on their own.
174///
175/// A type which doesn't implement this trait may still represent a complete SQL
176/// query. For example, an `INSERT` statement without a `RETURNING` clause will
177/// not implement this trait, but can still be executed.
178///
179/// [`Expression`]: crate::expression::Expression
180pub trait Query {
181/// The SQL type that this query represents.
182 ///
183 /// This is the SQL type of the `SELECT` clause for select statements, and
184 /// the SQL type of the `RETURNING` clause for insert, update, or delete
185 /// statements.
186type SqlType;
187}
188189impl<T: Query> Query for &T {
190type SqlType = T::SqlType;
191}
192193/// Indicates that a type is a `SELECT` statement.
194///
195/// This trait differs from `Query` in two ways:
196/// - It is implemented only for select statements, rather than all queries
197/// which return a value.
198/// - It has looser constraints. A type implementing `SelectQuery` is known to
199/// be potentially valid if used as a subselect, but it is not necessarily
200/// able to be executed.
201pub trait SelectQuery {
202/// The SQL type of the `SELECT` clause
203type SqlType;
204}
205206/// An untyped fragment of SQL.
207///
208/// This may be a complete SQL command (such as an update statement without a
209/// `RETURNING` clause), or a subsection (such as our internal types used to
210/// represent a `WHERE` clause). Implementations of [`ExecuteDsl`] and
211/// [`LoadQuery`] will generally require that this trait be implemented.
212///
213/// [`ExecuteDsl`]: crate::query_dsl::methods::ExecuteDsl
214/// [`LoadQuery`]: crate::query_dsl::methods::LoadQuery
215#[diagnostic::on_unimplemented(
216 message = "`{Self}` is no valid SQL fragment for the `{DB}` backend",
217 note = "this usually means that the `{DB}` database system does not support \n\
218 this SQL syntax"
219)]
220pub trait QueryFragment<DB: Backend, SP = self::private::NotSpecialized> {
221/// Walk over this `QueryFragment` for all passes.
222 ///
223 /// This method is where the actual behavior of an AST node is implemented.
224 /// This method will contain the behavior required for all possible AST
225 /// passes. See [`AstPass`] for more details.
226 ///
227fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()>;
228229/// Converts this `QueryFragment` to its SQL representation.
230 ///
231 /// This method should only be called by implementations of `Connection`.
232#[diesel_derives::__diesel_public_if(
233 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
234)]
235fn to_sql(&self, out: &mut DB::QueryBuilder, backend: &DB) -> QueryResult<()> {
236let mut options = AstPassToSqlOptions::default();
237self.walk_ast(AstPass::to_sql(out, &mut options, backend))
238 }
239240/// Serializes all bind parameters in this query.
241 ///
242 /// A bind parameter is a value which is sent separately from the query
243 /// itself. It is represented in SQL with a placeholder such as `?` or `$1`.
244 ///
245 /// This method should only be called by implementations of `Connection`.
246#[diesel_derives::__diesel_public_if(
247 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
248)]
249fn collect_binds<'b>(
250&'b self,
251 out: &mut DB::BindCollector<'b>,
252 metadata_lookup: &mut DB::MetadataLookup,
253 backend: &'b DB,
254 ) -> QueryResult<()> {
255self.walk_ast(AstPass::collect_binds(out, metadata_lookup, backend))
256 }
257258/// Is this query safe to store in the prepared statement cache?
259 ///
260 /// In order to keep our prepared statement cache at a reasonable size, we
261 /// avoid caching any queries which represent a potentially unbounded number
262 /// of SQL queries. Generally this will only return `true` for queries for
263 /// which `to_sql` will always construct exactly identical SQL.
264 ///
265 /// Some examples of where this method will return `false` are:
266 ///
267 /// - `SqlLiteral` (We don't know if the SQL was constructed dynamically, so
268 /// we must assume that it was)
269 /// - `In` and `NotIn` (Each value requires a separate bind param
270 /// placeholder)
271 ///
272 /// This method should only be called by implementations of `Connection`.
273#[diesel_derives::__diesel_public_if(
274 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
275)]
276fn is_safe_to_cache_prepared(&self, backend: &DB) -> QueryResult<bool> {
277let mut result = true;
278self.walk_ast(AstPass::is_safe_to_cache_prepared(&mut result, backend))?;
279Ok(result)
280 }
281282/// Does walking this AST have any effect?
283#[diesel_derives::__diesel_public_if(
284 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
285)]
286fn is_noop(&self, backend: &DB) -> QueryResult<bool> {
287let mut result = true;
288self.walk_ast(AstPass::is_noop(&mut result, backend))?;
289Ok(result)
290 }
291}
292293impl<T: ?Sized, DB> QueryFragment<DB> for Box<T>
294where
295DB: Backend,
296 T: QueryFragment<DB>,
297{
298fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
299 QueryFragment::walk_ast(&**self, pass)
300 }
301}
302303impl<T: ?Sized, DB> QueryFragment<DB> for &T
304where
305DB: Backend,
306 T: QueryFragment<DB>,
307{
308fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
309 QueryFragment::walk_ast(&**self, pass)
310 }
311}
312313impl<DB: Backend> QueryFragment<DB> for () {
314fn walk_ast<'b>(&'b self, _: AstPass<'_, 'b, DB>) -> QueryResult<()> {
315Ok(())
316 }
317}
318319impl<T, DB> QueryFragment<DB> for Option<T>
320where
321DB: Backend,
322 T: QueryFragment<DB>,
323{
324fn walk_ast<'b>(&'b self, out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
325match *self {
326Some(ref c) => c.walk_ast(out),
327None => Ok(()),
328 }
329 }
330}
331332/// A trait used to construct type erased boxed variant of the current query node
333///
334/// Mainly useful for implementing third party backends
335pub trait IntoBoxedClause<'a, DB> {
336/// Resulting type
337type BoxedClause;
338339/// Convert the given query node in it's boxed representation
340fn into_boxed(self) -> Self::BoxedClause;
341}
342343/// Types that can be converted into a complete, typed SQL query.
344///
345/// This is used internally to automatically add the right select clause when
346/// none is specified, or to automatically add `RETURNING *` in certain contexts.
347///
348/// A type which implements this trait is guaranteed to be valid for execution.
349pub trait AsQuery {
350/// The SQL type of `Self::Query`
351type SqlType;
352353/// What kind of query does this type represent?
354type Query: Query<SqlType = Self::SqlType>;
355356/// Converts a type which semantically represents a SQL query into the
357 /// actual query being executed. See the trait level docs for more.
358// This method is part of our public API,
359 // so we won't change the name to just appease clippy
360 // (Also the trait is literally named `AsQuery` so
361 // naming the method similarity is fine)
362#[allow(clippy::wrong_self_convention)]
363fn as_query(self) -> Self::Query;
364}
365366impl<T: Query> AsQuery for T {
367type SqlType = <T as Query>::SqlType;
368type Query = T;
369370fn as_query(self) -> <T as AsQuery>::Query {
371self
372}
373}
374375/// Takes a query `QueryFragment` expression as an argument and returns a type
376/// that implements `fmt::Display` and `fmt::Debug` to show the query.
377///
378/// The `Display` implementation will show the exact query being sent to the
379/// server, with a comment showing the values of the bind parameters. The
380/// `Debug` implementation will include the same information in a more
381/// structured form, and respects pretty printing.
382///
383/// # Example
384///
385/// ### Returning SQL from a count statement:
386///
387/// ```rust
388/// # include!("../doctest_setup.rs");
389/// #
390/// # use diesel::*;
391/// # use schema::*;
392/// #
393/// # fn main() {
394/// # use schema::users::dsl::*;
395/// let sql = debug_query::<DB, _>(&users.count()).to_string();
396/// # if cfg!(feature = "postgres") {
397/// # assert_eq!(sql, r#"SELECT COUNT(*) FROM "users" -- binds: []"#);
398/// # } else {
399/// assert_eq!(sql, "SELECT COUNT(*) FROM `users` -- binds: []");
400/// # }
401///
402/// let query = users.find(1);
403/// let debug = debug_query::<DB, _>(&query);
404/// # if cfg!(feature = "postgres") {
405/// # assert_eq!(debug.to_string(), "SELECT \"users\".\"id\", \"users\".\"name\" \
406/// # FROM \"users\" WHERE (\"users\".\"id\" = $1) -- binds: [1]");
407/// # } else {
408/// assert_eq!(debug.to_string(), "SELECT `users`.`id`, `users`.`name` FROM `users` \
409/// WHERE (`users`.`id` = ?) -- binds: [1]");
410/// # }
411///
412/// let debug = format!("{:?}", debug);
413/// # if !cfg!(feature = "postgres") { // Escaping that string is a pain
414/// let expected = "Query { \
415/// sql: \"SELECT `users`.`id`, `users`.`name` FROM `users` WHERE \
416/// (`users`.`id` = ?)\", \
417/// binds: [1] \
418/// }";
419/// assert_eq!(debug, expected);
420/// # }
421/// # }
422/// ```
423pub fn debug_query<DB, T>(query: &T) -> DebugQuery<'_, T, DB> {
424 DebugQuery::new(query)
425}
426427mod private {
428#[allow(missing_debug_implementations, missing_copy_implementations)]
429pub struct NotSpecialized;
430}