diesel/expression/
sql_literal.rs

1use std::marker::PhantomData;
2
3use backend::Backend;
4use expression::*;
5use query_builder::*;
6use query_dsl::RunQueryDsl;
7use result::QueryResult;
8
9#[derive(Debug, Clone, DieselNumericOps)]
10#[must_use = "Queries are only executed when calling `load`, `get_result`, or similar."]
11/// Returned by the [`sql()`] function.
12///
13/// [`sql()`]: ../dsl/fn.sql.html
14pub struct SqlLiteral<ST, T = ()> {
15    sql: String,
16    inner: T,
17    _marker: PhantomData<ST>,
18}
19
20impl<ST, T> SqlLiteral<ST, T> {
21    #[doc(hidden)]
22    pub fn new(sql: String, inner: T) -> Self {
23        SqlLiteral {
24            sql: sql,
25            inner: inner,
26            _marker: PhantomData,
27        }
28    }
29
30    /// Bind a value for use with this SQL query.
31    ///
32    /// # Safety
33    ///
34    /// This function should be used with care, as Diesel cannot validate that
35    /// the value is of the right type nor can it validate that you have passed
36    /// the correct number of parameters.
37    ///
38    /// # Examples
39    ///
40    /// ```rust
41    /// # #[macro_use] extern crate diesel;
42    /// # include!("../doctest_setup.rs");
43    /// #
44    /// # table! {
45    /// #    users {
46    /// #        id -> Integer,
47    /// #        name -> VarChar,
48    /// #    }
49    /// # }
50    /// #
51    /// # fn main() {
52    /// #     use self::users::dsl::*;
53    /// #     use diesel::dsl::sql;
54    /// #     use diesel::sql_types::{Integer, Text};
55    /// #     let connection = establish_connection();
56    /// let seans_id = users
57    ///     .select(id)
58    ///     .filter(sql("name = ").bind::<Text, _>("Sean"))
59    ///     .get_result(&connection);
60    /// assert_eq!(Ok(1), seans_id);
61    ///
62    /// let tess_id = sql::<Integer>("SELECT id FROM users WHERE name = ")
63    ///     .bind::<Text, _>("Tess")
64    ///     .get_result(&connection);
65    /// assert_eq!(Ok(2), tess_id);
66    /// # }
67    /// ```
68    ///
69    /// ### Multiple Bind Params
70    ///
71    /// ```rust
72    /// # #[macro_use] extern crate diesel;
73    /// # include!("../doctest_setup.rs");
74    ///
75    /// # table! {
76    /// #    users {
77    /// #        id -> Integer,
78    /// #        name -> VarChar,
79    /// #    }
80    /// # }
81    /// #
82    /// # fn main() {
83    /// #     use self::users::dsl::*;
84    /// #     use diesel::dsl::sql;
85    /// #     use diesel::sql_types::{Integer, Text};
86    /// #     let connection = establish_connection();
87    /// #     diesel::insert_into(users).values(name.eq("Ryan"))
88    /// #           .execute(&connection).unwrap();
89    /// let query = users
90    ///     .select(name)
91    ///     .filter(
92    ///         sql("id > ")
93    ///         .bind::<Integer,_>(1)
94    ///         .sql(" AND name <> ")
95    ///         .bind::<Text, _>("Ryan")
96    ///     )
97    ///     .get_results(&connection);
98    /// let expected = vec!["Tess".to_string()];
99    /// assert_eq!(Ok(expected), query);
100    /// # }
101    /// ```
102    pub fn bind<BindST, U>(self, bind_value: U) -> UncheckedBind<Self, U::Expression>
103    where
104        U: AsExpression<BindST>,
105    {
106        UncheckedBind::new(self, bind_value.as_expression())
107    }
108
109    /// Use literal SQL in the query builder
110    ///
111    /// This function is intended for use when you need a small bit of raw SQL in
112    /// your query. If you want to write the entire query using raw SQL, use
113    /// [`sql_query`](../fn.sql_query.html) instead.
114    ///
115    /// # Safety
116    ///
117    /// This function should be used with care, as Diesel cannot validate that
118    /// the value is of the right type nor can it validate that you have passed
119    /// the correct number of parameters.
120    ///
121    /// # Examples
122    ///
123    /// ```rust
124    /// # #[macro_use] extern crate diesel;
125    /// # include!("../doctest_setup.rs");
126    ///
127    /// # table! {
128    /// #    users {
129    /// #        id -> Integer,
130    /// #        name -> VarChar,
131    /// #    }
132    /// # }
133    /// #
134    /// # fn main() {
135    /// #     use self::users::dsl::*;
136    /// #     use diesel::dsl::sql;
137    /// #     use diesel::sql_types::{Integer, Text};
138    /// #     let connection = establish_connection();
139    /// #     diesel::insert_into(users).values(name.eq("Ryan"))
140    /// #           .execute(&connection).unwrap();
141    /// let query = users
142    ///     .select(name)
143    ///     .filter(
144    ///         sql("id > 1")
145    ///         .sql(" AND name <> 'Ryan'")
146    ///     )
147    ///     .get_results(&connection);
148    /// let expected = vec!["Tess".to_string()];
149    /// assert_eq!(Ok(expected), query);
150    /// # }
151    /// ```
152    pub fn sql(self, sql: &str) -> SqlLiteral<ST, Self> {
153        SqlLiteral::new(sql.into(), self)
154    }
155}
156
157impl<ST, T> Expression for SqlLiteral<ST, T> {
158    type SqlType = ST;
159}
160
161impl<ST, T, DB> QueryFragment<DB> for SqlLiteral<ST, T>
162where
163    DB: Backend,
164    T: QueryFragment<DB>,
165{
166    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
167        out.unsafe_to_cache_prepared();
168        self.inner.walk_ast(out.reborrow())?;
169        out.push_sql(&self.sql);
170        Ok(())
171    }
172}
173
174impl<ST, T> QueryId for SqlLiteral<ST, T> {
175    type QueryId = ();
176
177    const HAS_STATIC_QUERY_ID: bool = false;
178}
179
180impl<ST, T> Query for SqlLiteral<ST, T> {
181    type SqlType = ST;
182}
183
184impl<ST, T, Conn> RunQueryDsl<Conn> for SqlLiteral<ST, T> {}
185
186impl<QS, ST, T> SelectableExpression<QS> for SqlLiteral<ST, T> {}
187
188impl<QS, ST, T> AppearsOnTable<QS> for SqlLiteral<ST, T> {}
189
190impl<ST, T> NonAggregate for SqlLiteral<ST, T> {}
191
192/// Use literal SQL in the query builder
193///
194/// Available for when you truly cannot represent something using the expression
195/// DSL. You will need to provide the SQL type of the expression, in addition to
196/// the SQL.
197///
198/// This function is intended for use when you need a small bit of raw SQL in
199/// your query. If you want to write the entire query using raw SQL, use
200/// [`sql_query`](../fn.sql_query.html) instead.
201///
202/// # Safety
203///
204/// The compiler will be unable to verify the correctness of the annotated type.
205/// If you give the wrong type, it'll either return an error when deserializing
206/// the query result or produce unexpected values.
207///
208/// # Examples
209///
210/// ```rust
211/// # #[macro_use] extern crate diesel;
212/// # include!("../doctest_setup.rs");
213/// # fn main() {
214/// #     run_test().unwrap();
215/// # }
216/// #
217/// # fn run_test() -> QueryResult<()> {
218/// #     use schema::users::dsl::*;
219/// use diesel::dsl::sql;
220/// #     let connection = establish_connection();
221/// let user = users.filter(sql("name = 'Sean'")).first(&connection)?;
222/// let expected = (1, String::from("Sean"));
223/// assert_eq!(expected, user);
224/// #     Ok(())
225/// # }
226/// ```
227pub fn sql<ST>(sql: &str) -> SqlLiteral<ST> {
228    SqlLiteral::new(sql.into(), ())
229}
230
231#[derive(QueryId, Debug, Clone, Copy)]
232#[must_use = "Queries are only executed when calling `load`, `get_result`, or similar."]
233/// Returned by the [`SqlLiteral::bind()`] method when binding a value to a fragment of SQL.
234///
235/// [`bind()`]: ./struct.SqlLiteral.html#method.bind
236pub struct UncheckedBind<Query, Value> {
237    query: Query,
238    value: Value,
239}
240
241impl<Query, Value> UncheckedBind<Query, Value>
242where
243    Query: Expression,
244{
245    pub(crate) fn new(query: Query, value: Value) -> Self {
246        UncheckedBind { query, value }
247    }
248
249    /// Use literal SQL in the query builder
250    ///
251    /// This function is intended for use when you need a small bit of raw SQL in
252    /// your query. If you want to write the entire query using raw SQL, use
253    /// [`sql_query`](../fn.sql_query.html) instead.
254    ///
255    /// # Safety
256    ///
257    /// This function should be used with care, as Diesel cannot validate that
258    /// the value is of the right type nor can it validate that you have passed
259    /// the correct number of parameters.
260    ///
261    /// # Examples
262    ///
263    /// ```rust
264    /// # #[macro_use] extern crate diesel;
265    /// # include!("../doctest_setup.rs");
266    ///
267    /// # table! {
268    /// #    users {
269    /// #        id -> Integer,
270    /// #        name -> VarChar,
271    /// #    }
272    /// # }
273    /// #
274    /// # fn main() {
275    /// #     use self::users::dsl::*;
276    /// #     use diesel::dsl::sql;
277    /// #     use diesel::sql_types::{Integer, Text};
278    /// #     let connection = establish_connection();
279    /// #     diesel::insert_into(users).values(name.eq("Ryan"))
280    /// #           .execute(&connection).unwrap();
281    /// let query = users
282    ///     .select(name)
283    ///     .filter(
284    ///         sql("id > ")
285    ///         .bind::<Integer,_>(1)
286    ///         .sql(" AND name <> 'Ryan'")
287    ///     )
288    ///     .get_results(&connection);
289    /// let expected = vec!["Tess".to_string()];
290    /// assert_eq!(Ok(expected), query);
291    /// # }
292    /// ```
293    pub fn sql(self, sql: &str) -> SqlLiteral<Query::SqlType, Self> {
294        SqlLiteral::new(sql.into(), self)
295    }
296}
297
298impl<Query, Value> Expression for UncheckedBind<Query, Value>
299where
300    Query: Expression,
301{
302    type SqlType = Query::SqlType;
303}
304
305impl<Query, Value, DB> QueryFragment<DB> for UncheckedBind<Query, Value>
306where
307    DB: Backend,
308    Query: QueryFragment<DB>,
309    Value: QueryFragment<DB>,
310{
311    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
312        self.query.walk_ast(out.reborrow())?;
313        self.value.walk_ast(out.reborrow())?;
314        Ok(())
315    }
316}
317
318impl<Q, Value> Query for UncheckedBind<Q, Value>
319where
320    Q: Query,
321{
322    type SqlType = Q::SqlType;
323}
324
325impl<Query, Value> NonAggregate for UncheckedBind<Query, Value> where Self: Expression {}
326
327impl<QS, Query, Value> SelectableExpression<QS> for UncheckedBind<Query, Value> where
328    Self: AppearsOnTable<QS>
329{
330}
331
332impl<QS, Query, Value> AppearsOnTable<QS> for UncheckedBind<Query, Value> where Self: Expression {}
333
334impl<Query, Value, Conn> RunQueryDsl<Conn> for UncheckedBind<Query, Value> {}