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`