Skip to main content

diesel/
deserialize.rs

1//! Types and traits related to deserializing values from the database
2
3use crate::Selectable;
4use crate::backend::Backend;
5use crate::expression::select_by::SelectBy;
6use crate::row::{NamedRow, Row};
7use crate::sql_types::{SingleValue, SqlType, Untyped};
8use alloc::boxed::Box;
9use core::error::Error;
10use core::result;
11
12/// A specialized result type representing the result of deserializing
13/// a value from the database.
14pub type Result<T> = result::Result<T, Box<dyn Error + Send + Sync>>;
15
16/// Trait indicating that a record can be queried from the database.
17///
18/// Types which implement `Queryable` represent the result of a SQL query. This
19/// does not necessarily mean they represent a single database table.
20///
21/// Diesel represents the return type of a query as a tuple. The purpose of this
22/// trait is to convert from a tuple of Rust values that have been deserialized
23/// into your struct.
24///
25/// This trait can be [derived](derive@Queryable)
26///
27/// ## How to resolve compiler errors while loading data from the database
28///
29/// In case you getting uncomprehensable compiler errors while loading data
30/// from the database you might want to consider using
31/// [`#[derive(Selectable)]`](derive@crate::prelude::Selectable) +
32/// `#[diesel(check_for_backend(YourBackendType))]` to check for mismatching fields at compile
33/// time. This drastically improves the quality of the generated error messages by pointing
34/// to concrete mismatches at field level. You need to specify the concrete database backend
35/// this specific struct is indented to be used with, as otherwise rustc cannot correctly
36/// identify the required deserialization implementation.
37///
38/// ## Interaction with `NULL`/`Option`
39/// [`Nullable`][crate::sql_types::Nullable] types can be queried into `Option`.
40/// This is valid for single fields, tuples, and structures with `Queryable`.
41///
42/// With tuples and structs, the process for deserializing an `Option<(A,B,C)>` is
43/// to attempt to deserialize `A`, `B` and `C`, and if either of these return an
44/// [`UnexpectedNullError`](crate::result::UnexpectedNullError), the `Option` will be
45/// deserialized as `None`.
46/// If all succeed, the `Option` will be deserialized as `Some((a,b,c))`.
47///
48/// # Examples
49///
50/// ## Simple mapping from query to struct
51///
52/// If we just want to map a query to our struct, we can use `derive`.
53///
54/// ```rust
55/// # include!("doctest_setup.rs");
56/// #
57/// #[derive(Queryable, PartialEq, Debug)]
58/// struct User {
59///     id: i32,
60///     name: String,
61/// }
62///
63/// # fn main() {
64/// #     run_test();
65/// # }
66/// #
67/// # fn run_test() -> QueryResult<()> {
68/// #     use schema::users::dsl::*;
69/// #     let connection = &mut establish_connection();
70/// let first_user = users.order_by(id).first(connection)?;
71/// let expected = User {
72///     id: 1,
73///     name: "Sean".into(),
74/// };
75/// assert_eq!(expected, first_user);
76/// #     Ok(())
77/// # }
78/// ```
79///
80/// ## Interaction with `NULL`/`Option`
81///
82/// ### Single field
83/// ```rust
84/// # include!("doctest_setup.rs");
85/// # use diesel::sql_types::*;
86/// #
87/// table! {
88///     animals {
89///         id -> Integer,
90///         species -> VarChar,
91///         legs -> Integer,
92///         name -> Nullable<VarChar>,
93///     }
94/// }
95/// #
96/// #[derive(Queryable, PartialEq, Debug)]
97/// struct Animal {
98///     id: i32,
99///     name: Option<String>,
100/// }
101///
102/// # fn main() {
103/// #     run_test();
104/// # }
105/// #
106/// # fn run_test() -> QueryResult<()> {
107/// #     use schema::animals::dsl::*;
108/// #     let connection = &mut establish_connection();
109/// let all_animals = animals.select((id, name)).order_by(id).load(connection)?;
110/// let expected = vec![
111///     Animal {
112///         id: 1,
113///         name: Some("Jack".to_owned()),
114///     },
115///     Animal { id: 2, name: None },
116/// ];
117/// assert_eq!(expected, all_animals);
118/// #     Ok(())
119/// # }
120/// ```
121///
122/// ### Multiple fields
123/// ```rust
124/// # include!("doctest_setup.rs");
125/// #
126/// #[derive(Queryable, PartialEq, Debug)]
127/// struct UserWithPost {
128///     id: i32,
129///     post: Option<Post>,
130/// }
131/// #[derive(Queryable, PartialEq, Debug)]
132/// struct Post {
133///     id: i32,
134///     title: String,
135/// }
136///
137/// # fn main() {
138/// #     run_test();
139/// # }
140/// #
141/// # fn run_test() -> QueryResult<()> {
142/// #     use schema::{posts, users};
143/// #     let connection = &mut establish_connection();
144/// #     diesel::insert_into(users::table)
145/// #         .values(users::name.eq("Ruby"))
146/// #         .execute(connection)?;
147/// let all_posts = users::table
148///     .left_join(posts::table)
149///     .select((users::id, (posts::id, posts::title).nullable()))
150///     .order_by((users::id, posts::id))
151///     .load(connection)?;
152/// let expected = vec![
153///     UserWithPost {
154///         id: 1,
155///         post: Some(Post {
156///             id: 1,
157///             title: "My first post".to_owned(),
158///         }),
159///     },
160///     UserWithPost {
161///         id: 1,
162///         post: Some(Post {
163///             id: 2,
164///             title: "About Rust".to_owned(),
165///         }),
166///     },
167///     UserWithPost {
168///         id: 2,
169///         post: Some(Post {
170///             id: 3,
171///             title: "My first post too".to_owned(),
172///         }),
173///     },
174///     UserWithPost { id: 3, post: None },
175/// ];
176/// assert_eq!(expected, all_posts);
177/// #     Ok(())
178/// # }
179/// ```
180///
181/// ## `deserialize_as` attribute
182///
183/// If we want to do additional work during deserialization, we can use
184/// `deserialize_as` to use a different implementation.
185///
186/// ```rust
187/// # include!("doctest_setup.rs");
188/// #
189/// # use schema::users;
190/// # use diesel::backend::{self, Backend};
191/// # use diesel::deserialize::{self, Queryable, FromSql};
192/// # use diesel::sql_types::Text;
193/// #
194/// struct LowercaseString(String);
195///
196/// impl Into<String> for LowercaseString {
197///     fn into(self) -> String {
198///         self.0
199///     }
200/// }
201///
202/// impl<DB> Queryable<Text, DB> for LowercaseString
203/// where
204///     DB: Backend,
205///     String: FromSql<Text, DB>,
206/// {
207///     type Row = String;
208///
209///     fn build(s: String) -> deserialize::Result<Self> {
210///         Ok(LowercaseString(s.to_lowercase()))
211///     }
212/// }
213///
214/// #[derive(Queryable, PartialEq, Debug)]
215/// struct User {
216///     id: i32,
217///     #[diesel(deserialize_as = LowercaseString)]
218///     name: String,
219/// }
220///
221/// # fn main() {
222/// #     run_test();
223/// # }
224/// #
225/// # fn run_test() -> QueryResult<()> {
226/// #     use schema::users::dsl::*;
227/// #     let connection = &mut establish_connection();
228/// let first_user = users.first(connection)?;
229/// let expected = User {
230///     id: 1,
231///     name: "sean".into(),
232/// };
233/// assert_eq!(expected, first_user);
234/// #     Ok(())
235/// # }
236/// ```
237///
238/// ## Manual implementation
239///
240/// Alternatively, we can implement the trait for our struct manually.
241///
242/// ```rust
243/// # include!("doctest_setup.rs");
244/// #
245/// use diesel::deserialize::{self, Queryable};
246/// use schema::users;
247///
248/// # /*
249/// type DB = diesel::sqlite::Sqlite;
250/// # */
251/// #[derive(PartialEq, Debug)]
252/// struct User {
253///     id: i32,
254///     name: String,
255/// }
256///
257/// impl Queryable<users::SqlType, DB> for User {
258///     type Row = (i32, String);
259///
260///     fn build(row: Self::Row) -> deserialize::Result<Self> {
261///         Ok(User {
262///             id: row.0,
263///             name: row.1.to_lowercase(),
264///         })
265///     }
266/// }
267///
268/// # fn main() {
269/// #     run_test();
270/// # }
271/// #
272/// # fn run_test() -> QueryResult<()> {
273/// #     use schema::users::dsl::*;
274/// #     let connection = &mut establish_connection();
275/// let first_user = users.first(connection)?;
276/// let expected = User {
277///     id: 1,
278///     name: "sean".into(),
279/// };
280/// assert_eq!(expected, first_user);
281/// #     Ok(())
282/// # }
283/// ```
284pub trait Queryable<ST, DB>: Sized
285where
286    DB: Backend,
287{
288    /// The Rust type you'd like to map from.
289    ///
290    /// This is typically a tuple of all of your struct's fields.
291    type Row: FromStaticSqlRow<ST, DB>;
292
293    /// Construct an instance of this type
294    fn build(row: Self::Row) -> Result<Self>;
295}
296
297#[doc(inline)]
298pub use diesel_derives::Queryable;
299
300/// Deserializes the result of a query constructed with [`sql_query`].
301///
302/// This trait can be [derived](derive@QueryableByName)
303///
304/// [`sql_query`]: crate::sql_query()
305///
306/// # Examples
307///
308/// If we just want to map a query to our struct, we can use `derive`.
309///
310/// ```rust
311/// # include!("doctest_setup.rs");
312/// # use schema::users;
313/// # use diesel::sql_query;
314/// #
315/// #[derive(QueryableByName, PartialEq, Debug)]
316/// struct User {
317///     id: i32,
318///     name: String,
319/// }
320///
321/// # fn main() {
322/// #     run_test();
323/// # }
324/// #
325/// # fn run_test() -> QueryResult<()> {
326/// #     let connection = &mut establish_connection();
327/// let first_user = sql_query("SELECT * FROM users ORDER BY id LIMIT 1").get_result(connection)?;
328/// let expected = User {
329///     id: 1,
330///     name: "Sean".into(),
331/// };
332/// assert_eq!(expected, first_user);
333/// #     Ok(())
334/// # }
335/// ```
336///
337/// If we want to do additional work during deserialization, we can use
338/// `deserialize_as` to use a different implementation.
339///
340/// ```rust
341/// # include!("doctest_setup.rs");
342/// # use diesel::sql_query;
343/// # use schema::users;
344/// # use diesel::backend::{self, Backend};
345/// # use diesel::deserialize::{self, FromSql};
346/// #
347/// struct LowercaseString(String);
348///
349/// impl Into<String> for LowercaseString {
350///     fn into(self) -> String {
351///         self.0
352///     }
353/// }
354///
355/// impl<DB, ST> FromSql<ST, DB> for LowercaseString
356/// where
357///     DB: Backend,
358///     String: FromSql<ST, DB>,
359/// {
360///     fn from_sql(bytes: DB::RawValue<'_>) -> deserialize::Result<Self> {
361///         String::from_sql(bytes).map(|s| LowercaseString(s.to_lowercase()))
362///     }
363/// }
364///
365/// #[derive(QueryableByName, PartialEq, Debug)]
366/// struct User {
367///     id: i32,
368///     #[diesel(deserialize_as = LowercaseString)]
369///     name: String,
370/// }
371///
372/// # fn main() {
373/// #     run_test();
374/// # }
375/// #
376/// # fn run_test() -> QueryResult<()> {
377/// #     let connection = &mut establish_connection();
378/// let first_user = sql_query("SELECT * FROM users ORDER BY id LIMIT 1").get_result(connection)?;
379/// let expected = User {
380///     id: 1,
381///     name: "sean".into(),
382/// };
383/// assert_eq!(expected, first_user);
384/// #     Ok(())
385/// # }
386/// ```
387pub trait QueryableByName<DB>
388where
389    Self: Sized,
390    DB: Backend,
391{
392    /// Construct an instance of `Self` from the database row
393    fn build<'a>(row: &impl NamedRow<'a, DB>) -> Result<Self>;
394}
395
396#[doc(inline)]
397pub use diesel_derives::QueryableByName;
398
399/// Deserialize a single field of a given SQL type.
400///
401/// When possible, implementations of this trait should prefer to use an
402/// existing implementation, rather than reading from `bytes`. (For example, if
403/// you are implementing this for an enum which is represented as an integer in
404/// the database, prefer `i32::from_sql(bytes)` (or the explicit form
405/// `<i32 as FromSql<Integer, DB>>::from_sql(bytes)`) over reading from `bytes`
406/// directly)
407///
408/// Types which implement this trait should also have `#[derive(FromSqlRow)]`
409///
410/// ### Backend specific details
411///
412/// - For PostgreSQL, the bytes will be sent using the binary protocol, not text.
413/// - For SQLite, the actual type of `DB::RawValue` is private API. All
414///   implementations of this trait must be written in terms of an existing
415///   primitive.
416/// - For MySQL, the value of `bytes` will depend on the return value of
417///   `type_metadata` for the given SQL type. See [`MysqlType`] for details.
418/// - For third party backends, consult that backend's documentation.
419///
420/// [`MysqlType`]: ../mysql/enum.MysqlType.html
421///
422/// ### Examples
423///
424/// Most implementations of this trait will be defined in terms of an existing
425/// implementation.
426///
427/// ```rust
428/// # use diesel::backend::{self, Backend};
429/// # use diesel::sql_types::*;
430/// # use diesel::deserialize::{self, FromSql, FromSqlRow};
431/// #
432/// #[repr(i32)]
433/// #[derive(Debug, Clone, Copy, FromSqlRow)]
434/// pub enum MyEnum {
435///     A = 1,
436///     B = 2,
437/// }
438///
439/// impl<DB> FromSql<Integer, DB> for MyEnum
440/// where
441///     DB: Backend,
442///     i32: FromSql<Integer, DB>,
443/// {
444///     fn from_sql(bytes: DB::RawValue<'_>) -> deserialize::Result<Self> {
445///         match i32::from_sql(bytes)? {
446///             1 => Ok(MyEnum::A),
447///             2 => Ok(MyEnum::B),
448///             x => Err(format!("Unrecognized variant {}", x).into()),
449///         }
450///     }
451/// }
452/// ```
453#[diagnostic::on_unimplemented(
454    message = "cannot deserialize a value of the database type `{A}` as `{Self}`",
455    note = "double check your type mappings via the documentation of `{A}`"
456)]
457pub trait FromSql<A, DB: Backend>: Sized {
458    /// See the trait documentation.
459    fn from_sql(bytes: DB::RawValue<'_>) -> Result<Self>;
460
461    /// A specialized variant of `from_sql` for handling null values.
462    ///
463    /// The default implementation returns an `UnexpectedNullError` for
464    /// an encountered null value and calls `Self::from_sql` otherwise
465    ///
466    /// If your custom type supports null values you need to provide a
467    /// custom implementation.
468    #[inline(always)]
469    fn from_nullable_sql(bytes: Option<DB::RawValue<'_>>) -> Result<Self> {
470        match bytes {
471            Some(bytes) => Self::from_sql(bytes),
472            None => Err(Box::new(crate::result::UnexpectedNullError)),
473        }
474    }
475}
476
477/// A helper trait for deserializing data in a borrowed variant
478///
479/// This is mostly useful for getting a `&str` or `&[u8]` in your code
480#[doc = " A helper trait for deserializing data in a borrowed variant"]
#[doc = ""]
#[doc = " This is mostly useful for getting a `&str` or `&[u8]` in your code"]
pub trait FromSqlRef<'a, A, DB: Backend>: Sized {
    fn from_sql(bytes: DB::RawValue<'a>)
    -> Result<Self>;
}#[diesel_derives::__diesel_public_if(
481    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
482)]
483pub(crate) trait FromSqlRef<'a, A, DB: Backend>: Sized {
484    fn from_sql(bytes: DB::RawValue<'a>) -> Result<Self>;
485}
486
487/// Deserialize a database row into a rust data structure
488///
489/// Diesel provides wild card implementations of this trait for all types
490/// that implement one of the following traits:
491///    * [`Queryable`]
492///    * [`QueryableByName`]
493#[diagnostic::on_unimplemented(
494    note = "double check your type mappings via the documentation of `{ST}`",
495    note = "`diesel::sql_query` requires the loading target to column names for loading values.\n\
496             You need to provide a type that explicitly derives `diesel::deserialize::QueryableByName`"
497)]
498pub trait FromSqlRow<ST, DB: Backend>: Sized {
499    /// See the trait documentation.
500    fn build_from_row<'a>(row: &impl Row<'a, DB>) -> Result<Self>;
501}
502
503#[doc(inline)]
504pub use diesel_derives::FromSqlRow;
505
506/// A marker trait indicating that the corresponding type consumes a static at
507/// compile time known number of field
508///
509/// There is normally no need to implement this trait. Diesel provides
510/// wild card impls for all types that implement `FromSql<ST, DB>` or `Queryable<ST, DB>`
511/// where the size of `ST` is known
512pub trait StaticallySizedRow<ST, DB: Backend>: FromSqlRow<ST, DB> {
513    /// The number of fields that this type will consume.
514    const FIELD_COUNT: usize;
515}
516
517impl<DB, T> FromSqlRow<Untyped, DB> for T
518where
519    DB: Backend,
520    T: QueryableByName<DB>,
521{
522    fn build_from_row<'a>(row: &impl Row<'a, DB>) -> Result<Self> {
523        T::build(row)
524    }
525}
526
527/// A helper trait to deserialize a statically sized row into a tuple
528///
529/// **If you see an error message mentioning this trait you are likely trying to
530/// map the result of a query to a struct with mismatching field types. Recheck
531/// your field order and the concrete field types.**
532///
533/// You should not need to implement this trait directly.
534/// Diesel provides wild card implementations for any supported tuple size
535/// and for any type that implements `FromSql<ST, DB>`.
536// This is a distinct trait from `FromSqlRow` because otherwise we
537// are getting conflicting implementation errors for our `FromSqlRow`
538// implementation for tuples and our wild card impl for all types
539// implementing `Queryable`
540pub trait FromStaticSqlRow<ST, DB: Backend>: Sized {
541    /// See the trait documentation
542    fn build_from_row<'a>(row: &impl Row<'a, DB>) -> Result<Self>;
543}
544
545#[doc(hidden)]
546pub trait SqlTypeOrSelectable {}
547
548impl<ST> SqlTypeOrSelectable for ST where ST: SqlType + SingleValue {}
549impl<U, DB> SqlTypeOrSelectable for SelectBy<U, DB>
550where
551    U: Selectable<DB>,
552    DB: Backend,
553{
554}
555
556impl<T, ST, DB> FromSqlRow<ST, DB> for T
557where
558    T: Queryable<ST, DB>,
559    ST: SqlTypeOrSelectable,
560    DB: Backend,
561    T::Row: FromStaticSqlRow<ST, DB>,
562{
563    // This inline(always) attribute is here as benchmarks have shown
564    // up to 5% reduction in instruction count of having it here
565    //
566    // A plain inline attribute does not show similar improvements
567    #[inline(always)]
568    fn build_from_row<'a>(row: &impl Row<'a, DB>) -> Result<Self> {
569        let row = <T::Row as FromStaticSqlRow<ST, DB>>::build_from_row(row)?;
570        T::build(row)
571    }
572}
573
574impl<T, ST, DB> FromStaticSqlRow<ST, DB> for T
575where
576    DB: Backend,
577    T: FromSql<ST, DB>,
578    ST: SingleValue,
579{
580    fn build_from_row<'a>(row: &impl Row<'a, DB>) -> Result<Self> {
581        use crate::row::Field;
582
583        let field = row.get(0).ok_or(crate::result::UnexpectedEndOfRow)?;
584        T::from_nullable_sql(field.value()).map_err(|e| {
585            if e.is::<crate::result::UnexpectedNullError>() {
586                e
587            } else {
588                Box::new(crate::result::DeserializeFieldError::new(field, e))
589            }
590        })
591    }
592}
593
594// We cannot have this impl because rustc
595// then complains in third party crates that
596// diesel may implement `SingleValue` for tuples
597// in the future. While that is theoretically true,
598// that will likely not happen in practice.
599// If we get negative trait impls at some point in time
600// it should be possible to make this work.
601/*impl<T, ST, DB> Queryable<ST, DB> for T
602where
603    DB: Backend,
604    T: FromStaticSqlRow<ST, DB>,
605    ST: SingleValue,
606{
607    type Row = Self;
608
609    fn build(row: Self::Row) -> Self {
610        row
611    }
612}*/
613
614impl<T, ST, DB> StaticallySizedRow<ST, DB> for T
615where
616    ST: SqlTypeOrSelectable + crate::util::TupleSize,
617    T: Queryable<ST, DB>,
618    DB: Backend,
619{
620    const FIELD_COUNT: usize = <ST as crate::util::TupleSize>::SIZE;
621}
622
623/// A helper trait for giving a type a useful default value.
624///
625/// This is needed for types that can be used as range to represent the empty range as
626/// (Bound::Excluded(DEFAULT), Bound::Excluded(DEFAULT)).
627/// When possible, implementations of this trait should fall back to using std::default::Default.
628#[allow(dead_code)]
629pub(crate) trait Defaultable {
630    /// Returns the "default value" for a type.
631    fn default_value() -> Self;
632}
633
634// We cannot have this impl because rustc
635// then complains in third party crates that
636// diesel may implement `Default`in the future.
637// If we get negative trait impls at some point in time
638// it should be possible to make this work.
639//// Defaultable for types that has Default
640//impl<T: Default> Defaultable for T {
641//    fn default_value() -> Self {
642//        T::default()
643//    }
644//}