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(sql::<Bool>("id > 1").sql(" AND name <> 'Ryan'"))
144 /// .get_results(connection);
145 /// let expected = vec!["Tess".to_string()];
146 /// assert_eq!(Ok(expected), query);
147 /// # }
148 /// ```
149 pub fn sql(self, sql: &str) -> SqlLiteral<ST, Self> {
150 SqlLiteral::new(sql.into(), self)
151 }
152}
153
154impl<ST, T> Expression for SqlLiteral<ST, T>
155where
156 ST: TypedExpressionType,
157{
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<'b>(&'b self, mut out: AstPass<'_, 'b, 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>
181where
182 Self: Expression,
183{
184 type SqlType = ST;
185}
186
187impl<ST, T, Conn> RunQueryDsl<Conn> for SqlLiteral<ST, T> {}
188
189impl<QS, ST, T> SelectableExpression<QS> for SqlLiteral<ST, T> where Self: Expression {}
190
191impl<QS, ST, T> AppearsOnTable<QS> for SqlLiteral<ST, T> where Self: Expression {}
192
193impl<ST, T, GB> ValidGrouping<GB> for SqlLiteral<ST, T> {
194 type IsAggregate = is_aggregate::Never;
195}
196
197/// Use literal SQL in the query builder.
198///
199/// Available for when you truly cannot represent something using the expression
200/// DSL. You will need to provide the SQL type of the expression, in addition to
201/// the SQL.
202///
203/// This function is intended for use when you need a small bit of raw SQL in
204/// your query. If you want to write the entire query using raw SQL, use
205/// [`sql_query`](crate::sql_query()) instead.
206///
207/// Query parameters can be bound into the literal SQL using [`SqlLiteral::bind()`].
208///
209/// # Safety
210///
211/// The compiler will be unable to verify the correctness of the annotated type.
212/// If you give the wrong type, it'll either return an error when deserializing
213/// the query result or produce unexpected values.
214///
215/// # Examples
216///
217/// ```rust
218/// # include!("../doctest_setup.rs");
219/// # fn main() {
220/// # run_test_1().unwrap();
221/// # run_test_2().unwrap();
222/// # }
223/// #
224/// # fn run_test_1() -> QueryResult<()> {
225/// # use schema::users::dsl::*;
226/// # use diesel::sql_types::Bool;
227/// use diesel::dsl::sql;
228/// # let connection = &mut establish_connection();
229/// let user = users
230/// .filter(sql::<Bool>("name = 'Sean'"))
231/// .first(connection)?;
232/// let expected = (1, String::from("Sean"));
233/// assert_eq!(expected, user);
234/// # Ok(())
235/// # }
236/// #
237/// # fn run_test_2() -> QueryResult<()> {
238/// # use crate::schema::users::dsl::*;
239/// # use diesel::dsl::sql;
240/// # use diesel::sql_types::{Bool, Integer, Text};
241/// # let connection = &mut establish_connection();
242/// # diesel::insert_into(users)
243/// # .values(name.eq("Ryan"))
244/// # .execute(connection).unwrap();
245/// let query = users
246/// .select(name)
247/// .filter(
248/// sql::<Bool>("id > ")
249/// .bind::<Integer, _>(1)
250/// .sql(" AND name <> ")
251/// .bind::<Text, _>("Ryan"),
252/// )
253/// .get_results(connection);
254/// let expected = vec!["Tess".to_string()];
255/// assert_eq!(Ok(expected), query);
256/// # Ok(())
257/// # }
258/// ```
259/// [`SqlLiteral::bind()`]: crate::expression::SqlLiteral::bind()
260pub fn sql<ST>(sql: &str) -> SqlLiteral<ST>
261where
262 ST: TypedExpressionType,
263{
264 SqlLiteral::new(sql.into(), self::private::Empty)
265}
266
267#[derive(QueryId, Debug, Clone, Copy)]
268#[must_use = "Queries are only executed when calling `load`, `get_result`, or similar."]
269/// Returned by the [`SqlLiteral::bind()`] method when binding a value to a fragment of SQL.
270pub struct UncheckedBind<Query, Value> {
271 query: Query,
272 value: Value,
273}
274
275impl<Query, Value> UncheckedBind<Query, Value>
276where
277 Query: Expression,
278{
279 pub(crate) fn new(query: Query, value: Value) -> Self {
280 UncheckedBind { query, value }
281 }
282
283 /// Use literal SQL in the query builder.
284 ///
285 /// This function is intended for use when you need a small bit of raw SQL in
286 /// your query. If you want to write the entire query using raw SQL, use
287 /// [`sql_query`](crate::sql_query()) instead.
288 ///
289 /// # Safety
290 ///
291 /// This function should be used with care, as Diesel cannot validate that
292 /// the value is of the right type nor can it validate that you have passed
293 /// the correct number of parameters.
294 ///
295 /// # Examples
296 ///
297 /// ```rust
298 /// # include!("../doctest_setup.rs");
299 /// #
300 /// # table! {
301 /// # users {
302 /// # id -> Integer,
303 /// # name -> VarChar,
304 /// # }
305 /// # }
306 /// #
307 /// # fn main() {
308 /// # use self::users::dsl::*;
309 /// # use diesel::dsl::sql;
310 /// # use diesel::sql_types::{Integer, Bool};
311 /// # let connection = &mut establish_connection();
312 /// # diesel::insert_into(users).values(name.eq("Ryan"))
313 /// # .execute(connection).unwrap();
314 /// let query = users
315 /// .select(name)
316 /// .filter(
317 /// sql::<Bool>("id > ")
318 /// .bind::<Integer, _>(1)
319 /// .sql(" AND name <> 'Ryan'"),
320 /// )
321 /// .get_results(connection);
322 /// let expected = vec!["Tess".to_string()];
323 /// assert_eq!(Ok(expected), query);
324 /// # }
325 /// ```
326 pub fn sql(self, sql: &str) -> SqlLiteral<Query::SqlType, Self> {
327 SqlLiteral::new(sql.into(), self)
328 }
329}
330
331impl<Query, Value> Expression for UncheckedBind<Query, Value>
332where
333 Query: Expression,
334{
335 type SqlType = Query::SqlType;
336}
337
338impl<Query, Value, DB> QueryFragment<DB> for UncheckedBind<Query, Value>
339where
340 DB: Backend,
341 Query: QueryFragment<DB>,
342 Value: QueryFragment<DB>,
343{
344 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
345 self.query.walk_ast(out.reborrow())?;
346 self.value.walk_ast(out.reborrow())?;
347 Ok(())
348 }
349}
350
351impl<Q, Value> Query for UncheckedBind<Q, Value>
352where
353 Q: Query,
354{
355 type SqlType = Q::SqlType;
356}
357
358impl<Query, Value, GB> ValidGrouping<GB> for UncheckedBind<Query, Value> {
359 type IsAggregate = is_aggregate::Never;
360}
361
362impl<QS, Query, Value> SelectableExpression<QS> for UncheckedBind<Query, Value> where
363 Self: AppearsOnTable<QS>
364{
365}
366
367impl<QS, Query, Value> AppearsOnTable<QS> for UncheckedBind<Query, Value> where Self: Expression {}
368
369impl<Query, Value, Conn> RunQueryDsl<Conn> for UncheckedBind<Query, Value> {}
370
371mod private {
372 use crate::backend::{Backend, DieselReserveSpecialization};
373 use crate::query_builder::{QueryFragment, QueryId};
374
375 #[derive(Debug, Clone, Copy, QueryId)]
376 pub struct Empty;
377
378 impl<DB> QueryFragment<DB> for Empty
379 where
380 DB: Backend + DieselReserveSpecialization,
381 {
382 fn walk_ast<'b>(
383 &'b self,
384 _pass: crate::query_builder::AstPass<'_, 'b, DB>,
385 ) -> crate::QueryResult<()> {
386 Ok(())
387 }
388 }
389}