diesel/expression/sql_literal.rs
1use std::marker::PhantomData;
2
3use crate::expression::*;
4use crate::query_builder::*;
5use crate::query_dsl::RunQueryDsl;
6use crate::result::QueryResult;
7use crate::sql_types::DieselNumericOps;
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()`]: crate::dsl::sql()
14pub struct SqlLiteral<ST, T = self::private::Empty> {
15 sql: String,
16 inner: T,
17 _marker: PhantomData<ST>,
18}
19
20impl<ST, T> SqlLiteral<ST, T>
21where
22 ST: TypedExpressionType,
23{
24 pub(crate) fn new(sql: String, inner: T) -> Self {
25 SqlLiteral {
26 sql,
27 inner,
28 _marker: PhantomData,
29 }
30 }
31
32 /// Bind a value for use with this SQL query.
33 ///
34 /// # Safety
35 ///
36 /// This function should be used with care, as Diesel cannot validate that
37 /// the value is of the right type nor can it validate that you have passed
38 /// the correct number of parameters.
39 ///
40 /// # Examples
41 ///
42 /// ```rust
43 /// # include!("../doctest_setup.rs");
44 /// #
45 /// # table! {
46 /// # users {
47 /// # id -> Integer,
48 /// # name -> VarChar,
49 /// # }
50 /// # }
51 /// #
52 /// # fn main() {
53 /// # use self::users::dsl::*;
54 /// # use diesel::dsl::sql;
55 /// # use diesel::sql_types::{Integer, Text, Bool};
56 /// # let connection = &mut establish_connection();
57 /// let seans_id = users
58 /// .select(id)
59 /// .filter(sql::<Bool>("name = ").bind::<Text, _>("Sean"))
60 /// .get_result(connection);
61 /// assert_eq!(Ok(1), seans_id);
62 ///
63 /// let tess_id = sql::<Integer>("SELECT id FROM users WHERE name = ")
64 /// .bind::<Text, _>("Tess")
65 /// .get_result(connection);
66 /// assert_eq!(Ok(2), tess_id);
67 /// # }
68 /// ```
69 ///
70 /// ### Multiple Bind Params
71 ///
72 /// ```rust
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, Bool};
86 /// # let connection = &mut 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::<Bool>("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 BindST: SqlType + TypedExpressionType,
105 U: AsExpression<BindST>,
106 {
107 UncheckedBind::new(self, bind_value.as_expression())
108 }
109
110 /// Use literal SQL in the query builder
111 ///
112 /// This function is intended for use when you need a small bit of raw SQL in
113 /// your query. If you want to write the entire query using raw SQL, use
114 /// [`sql_query`](crate::sql_query()) instead.
115 ///
116 /// # Safety
117 ///
118 /// This function should be used with care, as Diesel cannot validate that
119 /// the value is of the right type nor can it validate that you have passed
120 /// the correct number of parameters.
121 ///
122 /// # Examples
123 ///
124 /// ```rust
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::Bool;
138 /// # let connection = &mut 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::<Bool>("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>
158where
159 ST: TypedExpressionType,
160{
161 type SqlType = ST;
162}
163
164impl<ST, T, DB> QueryFragment<DB> for SqlLiteral<ST, T>
165where
166 DB: Backend,
167 T: QueryFragment<DB>,
168{
169 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
170 out.unsafe_to_cache_prepared();
171 self.inner.walk_ast(out.reborrow())?;
172 out.push_sql(&self.sql);
173 Ok(())
174 }
175}
176
177impl<ST, T> QueryId for SqlLiteral<ST, T> {
178 type QueryId = ();
179
180 const HAS_STATIC_QUERY_ID: bool = false;
181}
182
183impl<ST, T> Query for SqlLiteral<ST, T>
184where
185 Self: Expression,
186{
187 type SqlType = ST;
188}
189
190impl<ST, T, Conn> RunQueryDsl<Conn> for SqlLiteral<ST, T> {}
191
192impl<QS, ST, T> SelectableExpression<QS> for SqlLiteral<ST, T> where Self: Expression {}
193
194impl<QS, ST, T> AppearsOnTable<QS> for SqlLiteral<ST, T> where Self: Expression {}
195
196impl<ST, T, GB> ValidGrouping<GB> for SqlLiteral<ST, T> {
197 type IsAggregate = is_aggregate::Never;
198}
199
200/// Use literal SQL in the query builder.
201///
202/// Available for when you truly cannot represent something using the expression
203/// DSL. You will need to provide the SQL type of the expression, in addition to
204/// the SQL.
205///
206/// This function is intended for use when you need a small bit of raw SQL in
207/// your query. If you want to write the entire query using raw SQL, use
208/// [`sql_query`](crate::sql_query()) instead.
209///
210/// Query parameters can be bound into the literal SQL using [`SqlLiteral::bind()`].
211///
212/// # Safety
213///
214/// The compiler will be unable to verify the correctness of the annotated type.
215/// If you give the wrong type, it'll either return an error when deserializing
216/// the query result or produce unexpected values.
217///
218/// # Examples
219///
220/// ```rust
221/// # include!("../doctest_setup.rs");
222/// # fn main() {
223/// # run_test_1().unwrap();
224/// # run_test_2().unwrap();
225/// # }
226/// #
227/// # fn run_test_1() -> QueryResult<()> {
228/// # use schema::users::dsl::*;
229/// # use diesel::sql_types::Bool;
230/// use diesel::dsl::sql;
231/// # let connection = &mut establish_connection();
232/// let user = users.filter(sql::<Bool>("name = 'Sean'")).first(connection)?;
233/// let expected = (1, String::from("Sean"));
234/// assert_eq!(expected, user);
235/// # Ok(())
236/// # }
237/// #
238/// # fn run_test_2() -> QueryResult<()> {
239/// # use crate::schema::users::dsl::*;
240/// # use diesel::dsl::sql;
241/// # use diesel::sql_types::{Bool, Integer, Text};
242/// # let connection = &mut establish_connection();
243/// # diesel::insert_into(users)
244/// # .values(name.eq("Ryan"))
245/// # .execute(connection).unwrap();
246/// let query = users
247/// .select(name)
248/// .filter(
249/// sql::<Bool>("id > ")
250/// .bind::<Integer,_>(1)
251/// .sql(" AND name <> ")
252/// .bind::<Text, _>("Ryan")
253/// )
254/// .get_results(connection);
255/// let expected = vec!["Tess".to_string()];
256/// assert_eq!(Ok(expected), query);
257/// # Ok(())
258/// # }
259/// ```
260/// [`SqlLiteral::bind()`]: crate::expression::SqlLiteral::bind()
261pub fn sql<ST>(sql: &str) -> SqlLiteral<ST>
262where
263 ST: TypedExpressionType,
264{
265 SqlLiteral::new(sql.into(), self::private::Empty)
266}
267
268#[derive(QueryId, Debug, Clone, Copy)]
269#[must_use = "Queries are only executed when calling `load`, `get_result`, or similar."]
270/// Returned by the [`SqlLiteral::bind()`] method when binding a value to a fragment of SQL.
271///
272pub struct UncheckedBind<Query, Value> {
273 query: Query,
274 value: Value,
275}
276
277impl<Query, Value> UncheckedBind<Query, Value>
278where
279 Query: Expression,
280{
281 pub(crate) fn new(query: Query, value: Value) -> Self {
282 UncheckedBind { query, value }
283 }
284
285 /// Use literal SQL in the query builder.
286 ///
287 /// This function is intended for use when you need a small bit of raw SQL in
288 /// your query. If you want to write the entire query using raw SQL, use
289 /// [`sql_query`](crate::sql_query()) instead.
290 ///
291 /// # Safety
292 ///
293 /// This function should be used with care, as Diesel cannot validate that
294 /// the value is of the right type nor can it validate that you have passed
295 /// the correct number of parameters.
296 ///
297 /// # Examples
298 ///
299 /// ```rust
300 /// # include!("../doctest_setup.rs");
301 /// #
302 /// # table! {
303 /// # users {
304 /// # id -> Integer,
305 /// # name -> VarChar,
306 /// # }
307 /// # }
308 /// #
309 /// # fn main() {
310 /// # use self::users::dsl::*;
311 /// # use diesel::dsl::sql;
312 /// # use diesel::sql_types::{Integer, Bool};
313 /// # let connection = &mut establish_connection();
314 /// # diesel::insert_into(users).values(name.eq("Ryan"))
315 /// # .execute(connection).unwrap();
316 /// let query = users
317 /// .select(name)
318 /// .filter(
319 /// sql::<Bool>("id > ")
320 /// .bind::<Integer,_>(1)
321 /// .sql(" AND name <> 'Ryan'")
322 /// )
323 /// .get_results(connection);
324 /// let expected = vec!["Tess".to_string()];
325 /// assert_eq!(Ok(expected), query);
326 /// # }
327 /// ```
328 pub fn sql(self, sql: &str) -> SqlLiteral<Query::SqlType, Self> {
329 SqlLiteral::new(sql.into(), self)
330 }
331}
332
333impl<Query, Value> Expression for UncheckedBind<Query, Value>
334where
335 Query: Expression,
336{
337 type SqlType = Query::SqlType;
338}
339
340impl<Query, Value, DB> QueryFragment<DB> for UncheckedBind<Query, Value>
341where
342 DB: Backend,
343 Query: QueryFragment<DB>,
344 Value: QueryFragment<DB>,
345{
346 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
347 self.query.walk_ast(out.reborrow())?;
348 self.value.walk_ast(out.reborrow())?;
349 Ok(())
350 }
351}
352
353impl<Q, Value> Query for UncheckedBind<Q, Value>
354where
355 Q: Query,
356{
357 type SqlType = Q::SqlType;
358}
359
360impl<Query, Value, GB> ValidGrouping<GB> for UncheckedBind<Query, Value> {
361 type IsAggregate = is_aggregate::Never;
362}
363
364impl<QS, Query, Value> SelectableExpression<QS> for UncheckedBind<Query, Value> where
365 Self: AppearsOnTable<QS>
366{
367}
368
369impl<QS, Query, Value> AppearsOnTable<QS> for UncheckedBind<Query, Value> where Self: Expression {}
370
371impl<Query, Value, Conn> RunQueryDsl<Conn> for UncheckedBind<Query, Value> {}
372
373mod private {
374 use crate::backend::{Backend, DieselReserveSpecialization};
375 use crate::query_builder::{QueryFragment, QueryId};
376
377 #[derive(Debug, Clone, Copy, QueryId)]
378 pub struct Empty;
379
380 impl<DB> QueryFragment<DB> for Empty
381 where
382 DB: Backend + DieselReserveSpecialization,
383 {
384 fn walk_ast<'b>(
385 &'b self,
386 _pass: crate::query_builder::AstPass<'_, 'b, DB>,
387 ) -> crate::QueryResult<()> {
388 Ok(())
389 }
390 }
391}