diesel/
deserialize.rs

1//! Types and traits related to deserializing values from the database
2
3use std::error::Error;
4use std::result;
5
6use backend::Backend;
7use row::{NamedRow, Row};
8
9/// A specialized result type representing the result of deserializing
10/// a value from the database.
11pub type Result<T> = result::Result<T, Box<dyn Error + Send + Sync>>;
12
13/// Trait indicating that a record can be queried from the database.
14///
15/// Types which implement `Queryable` represent the result of a SQL query. This
16/// does not necessarily mean they represent a single database table.
17///
18/// Diesel represents the return type of a query as a tuple. The purpose of this
19/// trait is to convert from a tuple of Rust values that have been deserialized
20/// into your struct.
21///
22/// # Deriving
23///
24/// This trait can be derived automatically using `#[derive(Queryable)]`. This
25/// trait can only be derived for structs, not enums.
26///
27/// When this trait is derived, it will assume that the order of fields on your
28/// struct match the order of the fields in the query. This means that field
29/// order is significant if you are using `#[derive(Queryable)]`. Field name has
30/// no effect.
31///
32/// To provide custom deserialization behavior for a field, you can use
33/// `#[diesel(deserialize_as = "Type")]`. If this attribute is present, Diesel
34/// will deserialize into that type, rather than the type on your struct and
35/// call `.into` to convert it. This can be used to add custom behavior for a
36/// single field, or use types that are otherwise unsupported by Diesel.
37///
38/// # Examples
39///
40/// If we just want to map a query to our struct, we can use `derive`.
41///
42/// ```rust
43/// # #[macro_use] extern crate diesel;
44/// # include!("doctest_setup.rs");
45/// #
46/// #[derive(Queryable, PartialEq, Debug)]
47/// struct User {
48///     id: i32,
49///     name: String,
50/// }
51///
52/// # fn main() {
53/// #     run_test();
54/// # }
55/// #
56/// # fn run_test() -> QueryResult<()> {
57/// #     use schema::users::dsl::*;
58/// #     let connection = establish_connection();
59/// let first_user = users.first(&connection)?;
60/// let expected = User { id: 1, name: "Sean".into() };
61/// assert_eq!(expected, first_user);
62/// #     Ok(())
63/// # }
64/// ```
65///
66/// If we want to do additional work during deserialization, we can use
67/// `deserialize_as` to use a different implementation.
68///
69/// ```rust
70/// # #[macro_use] extern crate diesel;
71/// # include!("doctest_setup.rs");
72/// #
73/// # use schema::users;
74/// # use diesel::backend::Backend;
75/// # use diesel::deserialize::Queryable;
76/// #
77/// struct LowercaseString(String);
78///
79/// impl Into<String> for LowercaseString {
80///     fn into(self) -> String {
81///         self.0
82///     }
83/// }
84///
85/// impl<DB, ST> Queryable<ST, DB> for LowercaseString
86/// where
87///     DB: Backend,
88///     String: Queryable<ST, DB>,
89/// {
90///     type Row = <String as Queryable<ST, DB>>::Row;
91///
92///     fn build(row: Self::Row) -> Self {
93///         LowercaseString(String::build(row).to_lowercase())
94///     }
95/// }
96///
97/// #[derive(Queryable, PartialEq, Debug)]
98/// struct User {
99///     id: i32,
100///     #[diesel(deserialize_as = "LowercaseString")]
101///     name: String,
102/// }
103///
104/// # fn main() {
105/// #     run_test();
106/// # }
107/// #
108/// # fn run_test() -> QueryResult<()> {
109/// #     use schema::users::dsl::*;
110/// #     let connection = establish_connection();
111/// let first_user = users.first(&connection)?;
112/// let expected = User { id: 1, name: "sean".into() };
113/// assert_eq!(expected, first_user);
114/// #     Ok(())
115/// # }
116/// ```
117///
118/// Alternatively, we can implement the trait for our struct manually.
119///
120/// ```rust
121/// # #[macro_use] extern crate diesel;
122/// # include!("doctest_setup.rs");
123/// #
124/// use schema::users;
125/// use diesel::deserialize::Queryable;
126///
127/// # /*
128/// type DB = diesel::sqlite::Sqlite;
129/// # */
130///
131/// #[derive(PartialEq, Debug)]
132/// struct User {
133///     id: i32,
134///     name: String,
135/// }
136///
137/// impl Queryable<users::SqlType, DB> for User {
138///     type Row = (i32, String);
139///
140///     fn build(row: Self::Row) -> Self {
141///         User {
142///             id: row.0,
143///             name: row.1.to_lowercase(),
144///         }
145///     }
146/// }
147///
148/// # fn main() {
149/// #     run_test();
150/// # }
151/// #
152/// # fn run_test() -> QueryResult<()> {
153/// #     use schema::users::dsl::*;
154/// #     let connection = establish_connection();
155/// let first_user = users.first(&connection)?;
156/// let expected = User { id: 1, name: "sean".into() };
157/// assert_eq!(expected, first_user);
158/// #     Ok(())
159/// # }
160/// ```
161pub trait Queryable<ST, DB>
162where
163    DB: Backend,
164{
165    /// The Rust type you'd like to map from.
166    ///
167    /// This is typically a tuple of all of your struct's fields.
168    type Row: FromSqlRow<ST, DB>;
169
170    /// Construct an instance of this type
171    fn build(row: Self::Row) -> Self;
172}
173
174/// Deserializes the result of a query constructed with [`sql_query`].
175///
176/// # Deriving
177///
178/// To derive this trait, Diesel needs to know the SQL type of each field. You
179/// can do this by either annotating your struct with `#[table_name =
180/// "some_table"]` (in which case the SQL type will be
181/// `diesel::dsl::SqlTypeOf<table_name::column_name>`), or by annotating each
182/// field with `#[sql_type = "SomeType"]`.
183///
184/// If you are using `#[table_name]`, the module for that table must be in
185/// scope. For example, to derive this for a struct called `User`, you will
186/// likely need a line such as `use schema::users;`
187///
188/// If the name of a field on your struct is different than the column in your
189/// `table!` declaration, or if you are deriving this trait on a tuple struct,
190/// you can annotate the field with `#[column_name = "some_column"]`. For tuple
191/// structs, all fields must have this annotation.
192///
193/// If a field is another struct which implements `QueryableByName`, instead of
194/// a column, you can annotate that struct with `#[diesel(embed)]`
195///
196/// To provide custom deserialization behavior for a field, you can use
197/// `#[diesel(deserialize_as = "Type")]`. If this attribute is present, Diesel
198/// will deserialize into that type, rather than the type on your struct and
199/// call `.into` to convert it. This can be used to add custom behavior for a
200/// single field, or use types that are otherwise unsupported by Diesel.
201///
202/// [`sql_query`]: ../fn.sql_query.html
203///
204/// # Examples
205///
206///
207/// If we just want to map a query to our struct, we can use `derive`.
208///
209/// ```rust
210/// # #[macro_use] extern crate diesel;
211/// # include!("doctest_setup.rs");
212/// # use schema::users;
213/// # use diesel::sql_query;
214/// #
215/// #[derive(QueryableByName, PartialEq, Debug)]
216/// #[table_name = "users"]
217/// struct User {
218///     id: i32,
219///     name: String,
220/// }
221///
222/// # fn main() {
223/// #     run_test();
224/// # }
225/// #
226/// # fn run_test() -> QueryResult<()> {
227/// #     let connection = establish_connection();
228/// let first_user = sql_query("SELECT * FROM users ORDER BY id LIMIT 1")
229///     .get_result(&connection)?;
230/// let expected = User { id: 1, name: "Sean".into() };
231/// assert_eq!(expected, first_user);
232/// #     Ok(())
233/// # }
234/// ```
235///
236/// If we want to do additional work during deserialization, we can use
237/// `deserialize_as` to use a different implementation.
238///
239/// ```rust
240/// # #[macro_use] extern crate diesel;
241/// # include!("doctest_setup.rs");
242/// # use diesel::sql_query;
243/// # use schema::users;
244/// # use diesel::backend::Backend;
245/// # use diesel::deserialize::{self, FromSql};
246/// #
247/// struct LowercaseString(String);
248///
249/// impl Into<String> for LowercaseString {
250///     fn into(self) -> String {
251///         self.0
252///     }
253/// }
254///
255/// impl<DB, ST> FromSql<ST, DB> for LowercaseString
256/// where
257///     DB: Backend,
258///     String: FromSql<ST, DB>,
259/// {
260///     fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
261///         String::from_sql(bytes)
262///             .map(|s| LowercaseString(s.to_lowercase()))
263///     }
264/// }
265///
266/// #[derive(QueryableByName, PartialEq, Debug)]
267/// #[table_name = "users"]
268/// struct User {
269///     id: i32,
270///     #[diesel(deserialize_as = "LowercaseString")]
271///     name: String,
272/// }
273///
274/// # fn main() {
275/// #     run_test();
276/// # }
277/// #
278/// # fn run_test() -> QueryResult<()> {
279/// #     let connection = establish_connection();
280/// let first_user = sql_query("SELECT * FROM users ORDER BY id LIMIT 1")
281///     .get_result(&connection)?;
282/// let expected = User { id: 1, name: "sean".into() };
283/// assert_eq!(expected, first_user);
284/// #     Ok(())
285/// # }
286/// ```
287pub trait QueryableByName<DB>
288where
289    Self: Sized,
290    DB: Backend,
291{
292    /// Construct an instance of `Self` from the database row
293    fn build<R: NamedRow<DB>>(row: &R) -> Result<Self>;
294}
295
296/// Deserialize a single field of a given SQL type.
297///
298/// When possible, implementations of this trait should prefer to use an
299/// existing implementation, rather than reading from `bytes`. (For example, if
300/// you are implementing this for an enum which is represented as an integer in
301/// the database, prefer `i32::from_sql(bytes)` over reading from `bytes`
302/// directly)
303///
304/// Types which implement this trait should also have `#[derive(FromSqlRow)]`
305///
306/// ### Backend specific details
307///
308/// - For PostgreSQL, the bytes will be sent using the binary protocol, not text.
309/// - For SQLite, the actual type of `DB::RawValue` is private API. All
310///   implementations of this trait must be written in terms of an existing
311///   primitive.
312/// - For MySQL, the value of `bytes` will depend on the return value of
313///   `type_metadata` for the given SQL type. See [`MysqlType`] for details.
314/// - For third party backends, consult that backend's documentation.
315///
316/// [`MysqlType`]: ../mysql/enum.MysqlType.html
317///
318/// ### Examples
319///
320/// Most implementations of this trait will be defined in terms of an existing
321/// implementation.
322///
323/// ```rust
324/// # use diesel::backend::Backend;
325/// # use diesel::sql_types::*;
326/// # use diesel::deserialize::{self, FromSql};
327/// #
328/// #[repr(i32)]
329/// #[derive(Debug, Clone, Copy)]
330/// pub enum MyEnum {
331///     A = 1,
332///     B = 2,
333/// }
334///
335/// impl<DB> FromSql<Integer, DB> for MyEnum
336/// where
337///     DB: Backend,
338///     i32: FromSql<Integer, DB>,
339/// {
340///     fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
341///         match i32::from_sql(bytes)? {
342///             1 => Ok(MyEnum::A),
343///             2 => Ok(MyEnum::B),
344///             x => Err(format!("Unrecognized variant {}", x).into()),
345///         }
346///     }
347/// }
348/// ```
349pub trait FromSql<A, DB: Backend>: Sized {
350    /// See the trait documentation.
351    fn from_sql(bytes: Option<&DB::RawValue>) -> Result<Self>;
352}
353
354/// Deserialize one or more fields.
355///
356/// All types which implement `FromSql` should also implement this trait. This
357/// trait differs from `FromSql` in that it is also implemented by tuples.
358/// Implementations of this trait are usually derived.
359///
360/// In the future, we hope to be able to provide a blanket impl of this trait
361/// for all types which implement `FromSql`. However, as of Diesel 1.0, such an
362/// impl would conflict with our impl for tuples.
363///
364/// ## Deriving
365///
366/// This trait can be automatically derived by Diesel
367/// for any type which implements `FromSql`.
368/// There are no options or special considerations needed for this derive.
369/// Note that `#[derive(FromSqlRow)]` will also generate a `Queryable` implementation.
370pub trait FromSqlRow<A, DB: Backend>: Sized {
371    /// The number of fields that this type will consume. Must be equal to
372    /// the number of times you would call `row.take()` in `build_from_row`
373    const FIELDS_NEEDED: usize = 1;
374
375    /// See the trait documentation.
376    fn build_from_row<T: Row<DB>>(row: &mut T) -> Result<Self>;
377}
378
379// Reasons we can't write this:
380//
381// impl<T, ST, DB> FromSqlRow<ST, DB> for T
382// where
383//     DB: Backend + HasSqlType<ST>,
384//     T: FromSql<ST, DB>,
385// {
386//     fn build_from_row<T: Row<DB>>(row: &mut T) -> Result<Self> {
387//         Self::from_sql(row.take())
388//     }
389// }
390//
391// (this is mostly here so @sgrif has a better reference every time he thinks
392// he's somehow had a breakthrough on solving this problem):
393//
394// - It conflicts with our impl for tuples, because `DB` is a bare type
395//   parameter, it could in theory be a local type for some other impl.
396//   - This is fixed by replacing our impl with 3 impls, where `DB` is changed
397//     concrete backends. This would mean that any third party crates adding new
398//     backends would need to add the tuple impls, which sucks but is fine.
399// - It conflicts with our impl for `Option`
400//   - So we could in theory fix this by both splitting the generic impl into
401//     backend specific impls, and removing the `FromSql` impls. In theory there
402//     is no reason that it needs to implement `FromSql`, since everything
403//     requires `FromSqlRow`, but it really feels like it should.
404//   - Specialization might also fix this one. The impl isn't quite a strict
405//     subset (the `FromSql` impl has `T: FromSql`, and the `FromSqlRow` impl
406//     has `T: FromSqlRow`), but if `FromSql` implies `FromSqlRow`,
407//     specialization might consider that a subset?
408// - I don't know that we really need it. `#[derive(FromSqlRow)]` is probably
409//   good enough. That won't improve our own codebase, since 99% of our
410//   `FromSqlRow` impls are for types from another crate, but it's almost
411//   certainly good enough for user types.
412//   - Still, it really feels like `FromSql` *should* be able to imply both
413//   `FromSqlRow` and `Queryable`