Skip to main content

diesel/expression/
sql_literal.rs

1use crate::expression::*;
2use crate::query_builder::*;
3use crate::query_dsl::RunQueryDslSupport;
4use crate::result::QueryResult;
5use crate::sql_types::DieselNumericOps;
6use alloc::string::String;
7use core::marker::PhantomData;
8
9#[derive(#[automatically_derived]impl<ST: ::core::fmt::Debug, T: ::core::fmt::Debug>
    ::core::fmt::Debug for SqlLiteral<ST, T> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f,
            "SqlLiteral sql inner _marker", &self.sql, &self.inner,
            &&self._marker)
    }
}Debug, #[automatically_derived]impl<ST: ::core::clone::Clone,
    T: ::core::clone::Clone> ::core::clone::Clone for SqlLiteral<ST, T> {
    #[inline]
    fn clone(&self) -> Self {
        SqlLiteral {
            sql: ::core::clone::Clone::clone(&self.sql),
            inner: ::core::clone::Clone::clone(&self.inner),
            _marker: ::core::clone::Clone::clone(&self._marker),
        }
    }
}Clone, const _: () =
    {
        use diesel;
        use diesel::internal::derives::numeric_ops as ops;
        use diesel::expression::{Expression, AsExpression};
        use diesel::sql_types::ops::{Add, Sub, Mul, Div};
        use diesel::sql_types::{SqlType, SingleValue};
        impl<ST, T, __Rhs> ::core::ops::Add<__Rhs> for SqlLiteral<ST, T> where
            Self: Expression, Self: Expression,
            <Self as Expression>::SqlType: Add,
            <<Self as Expression>::SqlType as Add>::Rhs: SqlType +
            SingleValue,
            __Rhs: AsExpression<<<Self as Expression>::SqlType as Add>::Rhs> {
            type Output = ops::Add<Self, __Rhs::Expression>;
            fn add(self, rhs: __Rhs) -> Self::Output {
                ops::Add::new(self, rhs.as_expression())
            }
        }
        impl<ST, T, __Rhs> ::core::ops::Sub<__Rhs> for SqlLiteral<ST, T> where
            Self: Expression, Self: Expression,
            <Self as Expression>::SqlType: Sub,
            <<Self as Expression>::SqlType as Sub>::Rhs: SqlType +
            SingleValue,
            __Rhs: AsExpression<<<Self as Expression>::SqlType as Sub>::Rhs> {
            type Output = ops::Sub<Self, __Rhs::Expression>;
            fn sub(self, rhs: __Rhs) -> Self::Output {
                ops::Sub::new(self, rhs.as_expression())
            }
        }
        impl<ST, T, __Rhs> ::core::ops::Mul<__Rhs> for SqlLiteral<ST, T> where
            Self: Expression, Self: Expression,
            <Self as Expression>::SqlType: Mul,
            <<Self as Expression>::SqlType as Mul>::Rhs: SqlType +
            SingleValue,
            __Rhs: AsExpression<<<Self as Expression>::SqlType as Mul>::Rhs> {
            type Output = ops::Mul<Self, __Rhs::Expression>;
            fn mul(self, rhs: __Rhs) -> Self::Output {
                ops::Mul::new(self, rhs.as_expression())
            }
        }
        impl<ST, T, __Rhs> ::core::ops::Div<__Rhs> for SqlLiteral<ST, T> where
            Self: Expression, Self: Expression,
            <Self as Expression>::SqlType: Div,
            <<Self as Expression>::SqlType as Div>::Rhs: SqlType +
            SingleValue,
            __Rhs: AsExpression<<<Self as Expression>::SqlType as Div>::Rhs> {
            type Output = ops::Div<Self, __Rhs::Expression>;
            fn div(self, rhs: __Rhs) -> Self::Output {
                ops::Div::new(self, rhs.as_expression())
            }
        }
    };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    /// # // Reading the query result requires reading memory allocated by the
83    /// # // native sqlite library, which miri cannot track provenance for.
84    /// # #[cfg(miri)]
85    /// # fn main() {}
86    /// # #[cfg(not(miri))]
87    /// # fn main() {
88    /// #     use self::users::dsl::*;
89    /// #     use diesel::dsl::sql;
90    /// #     use diesel::sql_types::{Integer, Text, Bool};
91    /// #     let connection = &mut establish_connection();
92    /// #     diesel::insert_into(users).values(name.eq("Ryan"))
93    /// #           .execute(connection).unwrap();
94    /// let query = users
95    ///     .select(name)
96    ///     .filter(
97    ///         sql::<Bool>("id > ")
98    ///             .bind::<Integer, _>(1)
99    ///             .sql(" AND name <> ")
100    ///             .bind::<Text, _>("Ryan"),
101    ///     )
102    ///     .get_results(connection);
103    /// let expected = vec!["Tess".to_string()];
104    /// assert_eq!(Ok(expected), query);
105    /// # }
106    /// ```
107    pub fn bind<BindST, U>(self, bind_value: U) -> UncheckedBind<Self, U::Expression>
108    where
109        BindST: SqlType + TypedExpressionType,
110        U: AsExpression<BindST>,
111    {
112        UncheckedBind::new(self, bind_value.as_expression())
113    }
114
115    /// Append raw SQL to this literal.
116    ///
117    /// The SQL built so far renders first, then the given SQL text. This
118    /// allows interleaving raw SQL fragments with [`bind`] calls when the
119    /// expression DSL cannot express the fragment.
120    ///
121    /// # Safety
122    ///
123    /// Diesel passes the given string to the database as written. It must
124    /// therefore never contain values that come from outside your own code,
125    /// because anything interpolated into the SQL text can carry an SQL
126    /// injection. Pass such values with [`bind`] instead.
127    ///
128    /// # Examples
129    ///
130    /// ```rust
131    /// # include!("../doctest_setup.rs");
132    /// #
133    /// # table! {
134    /// #    users {
135    /// #        id -> Integer,
136    /// #        name -> VarChar,
137    /// #    }
138    /// # }
139    /// #
140    /// # // Reading the query result requires reading memory allocated by the
141    /// # // native sqlite library, which miri cannot track provenance for.
142    /// # #[cfg(miri)]
143    /// # fn main() {}
144    /// # #[cfg(not(miri))]
145    /// # fn main() {
146    /// #     use self::users::dsl::*;
147    /// #     use diesel::dsl::sql;
148    /// #     use diesel::sql_types::Bool;
149    /// #     let connection = &mut establish_connection();
150    /// #     diesel::insert_into(users).values(name.eq("Ryan"))
151    /// #           .execute(connection).unwrap();
152    /// let query = users
153    ///     .select(name)
154    ///     .filter(sql::<Bool>("id > 1").sql(" AND name <> 'Ryan'"))
155    ///     .get_results(connection);
156    /// let expected = vec!["Tess".to_string()];
157    /// assert_eq!(Ok(expected), query);
158    /// # }
159    /// ```
160    ///
161    /// [`bind`]: Self::bind()
162    pub fn sql(self, sql: &str) -> SqlLiteral<ST, Self> {
163        SqlLiteral::new(sql.into(), self)
164    }
165}
166
167impl<ST, T> Expression for SqlLiteral<ST, T>
168where
169    ST: TypedExpressionType,
170{
171    type SqlType = ST;
172}
173
174impl<ST, T, DB> QueryFragment<DB> for SqlLiteral<ST, T>
175where
176    DB: Backend,
177    T: QueryFragment<DB>,
178{
179    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
180        out.unsafe_to_cache_prepared();
181        self.inner.walk_ast(out.reborrow())?;
182        out.push_sql(&self.sql);
183        Ok(())
184    }
185}
186
187impl<ST, T> QueryId for SqlLiteral<ST, T> {
188    type QueryId = ();
189
190    const HAS_STATIC_QUERY_ID: bool = false;
191}
192
193impl<ST, T> Query for SqlLiteral<ST, T>
194where
195    Self: Expression,
196{
197    type SqlType = ST;
198}
199
200impl<ST, T> RunQueryDslSupport for SqlLiteral<ST, T> {}
201
202impl<QS, ST, T> SelectableExpression<QS> for SqlLiteral<ST, T> where Self: Expression {}
203
204impl<QS, ST, T> AppearsOnTable<QS> for SqlLiteral<ST, T> where Self: Expression {}
205
206impl<ST, T, GB> ValidGrouping<GB> for SqlLiteral<ST, T> {
207    type IsAggregate = is_aggregate::Never;
208}
209
210/// Use literal SQL in the query builder.
211///
212/// Available for when you truly cannot represent something using the expression
213/// DSL. You will need to provide the SQL type of the expression, in addition to
214/// the SQL.
215///
216/// This function is intended for use when you need a small bit of raw SQL in
217/// your query. If you want to write the entire query using raw SQL, use
218/// [`sql_query`](crate::sql_query()) instead.
219///
220/// Query parameters can be bound into the literal SQL using [`SqlLiteral::bind()`].
221///
222/// # Safety
223///
224/// The compiler will be unable to verify the correctness of the annotated type.
225/// If you give the wrong type, it'll either return an error when deserializing
226/// the query result or produce unexpected values.
227///
228/// Diesel also passes the given string to the database as written. It must
229/// therefore never contain values that come from outside your own code,
230/// because anything interpolated into the SQL text can carry an SQL
231/// injection. Pass such values with [`SqlLiteral::bind()`] instead.
232///
233/// # Examples
234///
235/// ```rust
236/// # include!("../doctest_setup.rs");
237/// # // Reading the query result requires reading memory allocated by the
238/// # // native sqlite library, which miri cannot track provenance for.
239/// # #[cfg(miri)]
240/// # fn main() {}
241/// # #[cfg(not(miri))]
242/// # fn main() {
243/// #     run_test_1().unwrap();
244/// #     run_test_2().unwrap();
245/// # }
246/// #
247/// # fn run_test_1() -> QueryResult<()> {
248/// #     use schema::users::dsl::*;
249/// #     use diesel::sql_types::Bool;
250/// use diesel::dsl::sql;
251/// #     let connection = &mut establish_connection();
252/// let user = users
253///     .filter(sql::<Bool>("name = 'Sean'"))
254///     .first(connection)?;
255/// let expected = (1, String::from("Sean"));
256/// assert_eq!(expected, user);
257/// #     Ok(())
258/// # }
259/// #
260/// # fn run_test_2() -> QueryResult<()> {
261/// #     use crate::schema::users::dsl::*;
262/// #     use diesel::dsl::sql;
263/// #     use diesel::sql_types::{Bool, Integer, Text};
264/// #     let connection = &mut establish_connection();
265/// #     diesel::insert_into(users)
266/// #         .values(name.eq("Ryan"))
267/// #         .execute(connection).unwrap();
268/// let query = users
269///     .select(name)
270///     .filter(
271///         sql::<Bool>("id > ")
272///             .bind::<Integer, _>(1)
273///             .sql(" AND name <> ")
274///             .bind::<Text, _>("Ryan"),
275///     )
276///     .get_results(connection);
277/// let expected = vec!["Tess".to_string()];
278/// assert_eq!(Ok(expected), query);
279/// #     Ok(())
280/// # }
281/// ```
282/// [`SqlLiteral::bind()`]: crate::expression::SqlLiteral::bind()
283pub fn sql<ST>(sql: &str) -> SqlLiteral<ST>
284where
285    ST: TypedExpressionType,
286{
287    SqlLiteral::new(sql.into(), self::private::Empty)
288}
289
290#[derive(const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl<Query: diesel::query_builder::QueryId,
            Value: diesel::query_builder::QueryId>
            diesel::query_builder::QueryId for UncheckedBind<Query, Value> {
            type QueryId =
                UncheckedBind<<Query as
                diesel::query_builder::QueryId>::QueryId,
                <Value as diesel::query_builder::QueryId>::QueryId>;
            const HAS_STATIC_QUERY_ID: bool =
                <Query as diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID
                        &&
                        <Value as
                            diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID &&
                    true;
            const IS_WINDOW_FUNCTION: bool =
                <Query as diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION
                        ||
                        <Value as
                            diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION ||
                    false;
        }
    };QueryId, #[automatically_derived]impl<Query: ::core::fmt::Debug,
    Value: ::core::fmt::Debug> ::core::fmt::Debug for
    UncheckedBind<Query, Value> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "UncheckedBind query value", &self.query, &&self.value)
    }
}Debug, #[automatically_derived]impl<Query: ::core::clone::Clone,
    Value: ::core::clone::Clone> ::core::clone::Clone for
    UncheckedBind<Query, Value> {
    #[inline]
    fn clone(&self) -> Self {
        UncheckedBind {
            query: ::core::clone::Clone::clone(&self.query),
            value: ::core::clone::Clone::clone(&self.value),
        }
    }
}Clone, #[automatically_derived]impl<Query: ::core::marker::Copy,
    Value: ::core::marker::Copy> ::core::marker::Copy for
    UncheckedBind<Query, Value> {
}Copy)]
291#[must_use = "Queries are only executed when calling `load`, `get_result`, or similar."]
292/// Returned by the [`SqlLiteral::bind()`] method when binding a value to a fragment of SQL.
293pub struct UncheckedBind<Query, Value> {
294    query: Query,
295    value: Value,
296}
297
298impl<Query, Value> UncheckedBind<Query, Value>
299where
300    Query: Expression,
301{
302    pub(crate) fn new(query: Query, value: Value) -> Self {
303        UncheckedBind { query, value }
304    }
305
306    /// Append raw SQL after this literal and the values bound to it.
307    ///
308    /// The literal and its bound values render first, then the given SQL
309    /// text. This allows interleaving raw SQL fragments with
310    /// [`SqlLiteral::bind()`] calls when the expression DSL cannot express
311    /// the fragment.
312    ///
313    /// # Safety
314    ///
315    /// Diesel passes the given string to the database as written. It must
316    /// therefore never contain values that come from outside your own code,
317    /// because anything interpolated into the SQL text can carry an SQL
318    /// injection. Pass such values with [`SqlLiteral::bind()`] instead.
319    ///
320    /// # Examples
321    ///
322    /// ```rust
323    /// # include!("../doctest_setup.rs");
324    /// #
325    /// # table! {
326    /// #    users {
327    /// #        id -> Integer,
328    /// #        name -> VarChar,
329    /// #    }
330    /// # }
331    /// #
332    /// # // Reading the query result requires reading memory allocated by the
333    /// # // native sqlite library, which miri cannot track provenance for.
334    /// # #[cfg(miri)]
335    /// # fn main() {}
336    /// # #[cfg(not(miri))]
337    /// # fn main() {
338    /// #     use self::users::dsl::*;
339    /// #     use diesel::dsl::sql;
340    /// #     use diesel::sql_types::{Integer, Bool};
341    /// #     let connection = &mut establish_connection();
342    /// #     diesel::insert_into(users).values(name.eq("Ryan"))
343    /// #           .execute(connection).unwrap();
344    /// let query = users
345    ///     .select(name)
346    ///     .filter(
347    ///         sql::<Bool>("id > ")
348    ///             .bind::<Integer, _>(1)
349    ///             .sql(" AND name <> 'Ryan'"),
350    ///     )
351    ///     .get_results(connection);
352    /// let expected = vec!["Tess".to_string()];
353    /// assert_eq!(Ok(expected), query);
354    /// # }
355    /// ```
356    pub fn sql(self, sql: &str) -> SqlLiteral<Query::SqlType, Self> {
357        SqlLiteral::new(sql.into(), self)
358    }
359}
360
361impl<Query, Value> Expression for UncheckedBind<Query, Value>
362where
363    Query: Expression,
364{
365    type SqlType = Query::SqlType;
366}
367
368impl<Query, Value, DB> QueryFragment<DB> for UncheckedBind<Query, Value>
369where
370    DB: Backend,
371    Query: QueryFragment<DB>,
372    Value: QueryFragment<DB>,
373{
374    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
375        self.query.walk_ast(out.reborrow())?;
376        self.value.walk_ast(out.reborrow())?;
377        Ok(())
378    }
379}
380
381impl<Q, Value> Query for UncheckedBind<Q, Value>
382where
383    Q: Query,
384{
385    type SqlType = Q::SqlType;
386}
387
388impl<Query, Value, GB> ValidGrouping<GB> for UncheckedBind<Query, Value> {
389    type IsAggregate = is_aggregate::Never;
390}
391
392impl<QS, Query, Value> SelectableExpression<QS> for UncheckedBind<Query, Value> where
393    Self: AppearsOnTable<QS>
394{
395}
396
397impl<QS, Query, Value> AppearsOnTable<QS> for UncheckedBind<Query, Value> where Self: Expression {}
398
399impl<Query, Value> RunQueryDslSupport for UncheckedBind<Query, Value> {}
400
401mod private {
402    use crate::backend::{Backend, DieselReserveSpecialization};
403    use crate::query_builder::{QueryFragment, QueryId};
404
405    #[derive(#[automatically_derived]impl ::core::fmt::Debug for Empty {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "Empty")
    }
}Debug, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for Empty {
}
#[automatically_derived]impl ::core::clone::Clone for Empty {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]impl ::core::marker::Copy for Empty { }Copy, const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl diesel::query_builder::QueryId for Empty {
            type QueryId = Empty<>;
            const HAS_STATIC_QUERY_ID: bool = true;
            const IS_WINDOW_FUNCTION: bool = false;
        }
    };QueryId)]
406    pub struct Empty;
407
408    impl<DB> QueryFragment<DB> for Empty
409    where
410        DB: Backend + DieselReserveSpecialization,
411    {
412        fn walk_ast<'b>(
413            &'b self,
414            _pass: crate::query_builder::AstPass<'_, 'b, DB>,
415        ) -> crate::QueryResult<()> {
416            Ok(())
417        }
418    }
419}