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> {}