diesel/
row.rs

1//! Contains the `Row` trait
2
3use crate::backend::Backend;
4use crate::deserialize;
5use deserialize::FromSql;
6use std::default::Default;
7use std::ops::Range;
8
9#[cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")]
10#[doc(inline)]
11pub use self::private::{PartialRow, RowSealed};
12
13#[cfg(not(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"))]
14#[allow(unused_imports)]
15pub(crate) use self::private::{PartialRow, RowSealed};
16
17/// Representing a way to index into database rows
18///
19/// * Crates using existing backends should use existing implementations of
20///   this traits. Diesel provides `RowIndex<usize>` and `RowIndex<&str>` for
21///   all built-in backends
22///
23/// * Crates implementing custom backends need to provide `RowIndex<usize>` and
24///   `RowIndex<&str>` impls for their [`Row`] type.
25pub trait RowIndex<I> {
26    /// Get the numeric index inside the current row for the provided index value
27    fn idx(&self, idx: I) -> Option<usize>;
28}
29
30#[doc(hidden)]
31#[cfg(all(feature = "with-deprecated", not(feature = "without-deprecated")))]
32#[deprecated(note = "Use `Row::Field` directly instead")]
33pub type FieldRet<'a, R, DB> = <R as self::private::RowLifetimeHelper<DB>>::Field<'a>;
34
35/// Represents a single database row.
36///
37/// This trait is used as an argument to [`FromSqlRow`].
38///
39/// [`FromSqlRow`]: crate::deserialize::FromSqlRow
40pub trait Row<'a, DB: Backend>:
41    RowIndex<usize> + for<'b> RowIndex<&'b str> + self::private::RowSealed + Sized
42{
43    /// Field type returned by a `Row` implementation
44    ///
45    /// * Crates using existing backends should not concern themself with the
46    ///   concrete type of this associated type.
47    ///
48    /// * Crates implementing custom backends should provide their own type
49    ///   meeting the required trait bounds
50    type Field<'f>: Field<'f, DB>
51    where
52        'a: 'f,
53        Self: 'f;
54
55    /// Return type of `PartialRow`
56    ///
57    /// For all implementations, beside of the `Row` implementation on `PartialRow` itself
58    /// this should be `Self`.
59    #[cfg_attr(
60        not(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"),
61        doc(hidden)
62    )]
63    type InnerPartialRow: Row<'a, DB>;
64
65    /// Get the number of fields in the current row
66    fn field_count(&self) -> usize;
67
68    /// Get the field with the provided index from the row.
69    ///
70    /// Returns `None` if there is no matching field for the given index
71    fn get<'b, I>(&'b self, idx: I) -> Option<Self::Field<'b>>
72    where
73        'a: 'b,
74        Self: RowIndex<I>;
75
76    /// Get a deserialized value with the provided index from the row.
77    fn get_value<ST, T, I>(&self, idx: I) -> crate::deserialize::Result<T>
78    where
79        Self: RowIndex<I>,
80        T: FromSql<ST, DB>,
81    {
82        let field = self.get(idx).ok_or(crate::result::UnexpectedEndOfRow)?;
83        <T as FromSql<ST, DB>>::from_nullable_sql(field.value())
84    }
85
86    /// Returns a wrapping row that allows only to access fields, where the index is part of
87    /// the provided range.
88    #[cfg_attr(
89        not(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"),
90        doc(hidden)
91    )]
92    fn partial_row(&self, range: Range<usize>) -> PartialRow<'_, Self::InnerPartialRow>;
93}
94
95/// Represents a single field in a database row.
96///
97/// This trait allows retrieving information on the name of the column and on the value of the
98/// field.
99pub trait Field<'a, DB: Backend> {
100    /// The name of the current field
101    ///
102    /// Returns `None` if it's an unnamed field
103    fn field_name(&self) -> Option<&str>;
104
105    /// Get the value representing the current field in the raw representation
106    /// as it is transmitted by the database
107    fn value(&self) -> Option<DB::RawValue<'_>>;
108
109    /// Checks whether this field is null or not.
110    fn is_null(&self) -> bool {
111        self.value().is_none()
112    }
113}
114
115/// Represents a row of a SQL query, where the values are accessed by name
116/// rather than by index.
117///
118/// This trait is used by implementations of
119/// [`QueryableByName`](crate::deserialize::QueryableByName)
120pub trait NamedRow<'a, DB: Backend>: Row<'a, DB> {
121    /// Retrieve and deserialize a single value from the query
122    ///
123    /// Note that `ST` *must* be the exact type of the value with that name in
124    /// the query. The compiler will not be able to verify that you have
125    /// provided the correct type. If there is a mismatch, you may receive an
126    /// incorrect value, or a runtime error.
127    ///
128    /// If two or more fields in the query have the given name, the result of
129    /// this function is undefined.
130    fn get<ST, T>(&self, column_name: &str) -> deserialize::Result<T>
131    where
132        T: FromSql<ST, DB>;
133}
134
135impl<'a, R, DB> NamedRow<'a, DB> for R
136where
137    R: Row<'a, DB>,
138    DB: Backend,
139{
140    fn get<ST, T>(&self, column_name: &str) -> deserialize::Result<T>
141    where
142        T: FromSql<ST, DB>,
143    {
144        let field = Row::get(self, column_name)
145            .ok_or_else(|| format!("Column `{column_name}` was not present in query"))?;
146
147        T::from_nullable_sql(field.value())
148    }
149}
150
151/// A row that can be turned into an owned version
152#[diesel_derives::__diesel_public_if(
153    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
154)]
155pub trait IntoOwnedRow<'a, DB: Backend>: Row<'a, DB> {
156    /// The owned version of the row
157    type OwnedRow: Row<'a, DB> + Send + 'static;
158
159    /// A store for cached information between rows for faster access
160    type Cache: Default + 'static;
161
162    /// Turn the row into its owned version
163    fn into_owned(self, cache: &mut Self::Cache) -> Self::OwnedRow;
164}
165
166// These traits are not part of the public API
167// because:
168// * we want to control who can implement `Row` (for `RowSealed`)
169// * `PartialRow` is an implementation detail
170// * `RowLifetimeHelper` is an internal backward compatibility helper
171pub(crate) mod private {
172    use super::*;
173
174    /// This trait restricts who can implement `Row`
175    #[cfg_attr(
176        docsrs,
177        doc(cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"))
178    )]
179    pub trait RowSealed {}
180
181    /// A row type that wraps an inner row
182    ///
183    /// This type only allows to access fields of the inner row, whose index is
184    /// part of `range`. This type is used by diesel internally to implement
185    /// [`FromStaticSqlRow`](crate::deserialize::FromStaticSqlRow).
186    ///
187    /// Indexing via `usize` starts with 0 for this row type. The index is then shifted
188    /// by `self.range.start` to match the corresponding field in the underlying row.
189    #[derive(Debug)]
190    #[cfg_attr(
191        feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
192        cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")
193    )]
194    pub struct PartialRow<'a, R> {
195        inner: &'a R,
196        range: Range<usize>,
197    }
198
199    impl<'a, R> PartialRow<'a, R> {
200        /// Create a new [`PartialRow`] instance based on an inner
201        /// row and a range of field that should be part of the constructed
202        /// wrapper.
203        ///
204        /// See the documentation of [`PartialRow`] for details.
205        pub fn new<'b, DB>(inner: &'a R, range: Range<usize>) -> Self
206        where
207            R: Row<'b, DB>,
208            DB: Backend,
209        {
210            let range_lower = std::cmp::min(range.start, inner.field_count());
211            let range_upper = std::cmp::min(range.end, inner.field_count());
212            Self {
213                inner,
214                range: range_lower..range_upper,
215            }
216        }
217    }
218
219    impl<R> RowSealed for PartialRow<'_, R> {}
220
221    impl<'a, DB, R> Row<'a, DB> for PartialRow<'_, R>
222    where
223        DB: Backend,
224        R: Row<'a, DB>,
225    {
226        type Field<'f>
227            = R::Field<'f>
228        where
229            'a: 'f,
230            R: 'f,
231            Self: 'f;
232        type InnerPartialRow = R;
233
234        fn field_count(&self) -> usize {
235            self.range.len()
236        }
237
238        fn get<'c, I>(&'c self, idx: I) -> Option<Self::Field<'c>>
239        where
240            'a: 'c,
241            Self: RowIndex<I>,
242        {
243            let idx = self.idx(idx)?;
244            self.inner.get(idx)
245        }
246
247        fn partial_row(&self, range: Range<usize>) -> PartialRow<'_, R> {
248            let range_upper_bound = std::cmp::min(self.range.end, self.range.start + range.end);
249            let range = (self.range.start + range.start)..range_upper_bound;
250            PartialRow {
251                inner: self.inner,
252                range,
253            }
254        }
255    }
256
257    impl<'a, R> RowIndex<&'a str> for PartialRow<'_, R>
258    where
259        R: RowIndex<&'a str>,
260    {
261        fn idx(&self, idx: &'a str) -> Option<usize> {
262            let idx = self.inner.idx(idx)?;
263            if self.range.contains(&idx) {
264                Some(idx)
265            } else {
266                None
267            }
268        }
269    }
270
271    impl<R> RowIndex<usize> for PartialRow<'_, R>
272    where
273        R: RowIndex<usize>,
274    {
275        fn idx(&self, idx: usize) -> Option<usize> {
276            let idx = self.inner.idx(idx + self.range.start)?;
277            if self.range.contains(&idx) {
278                Some(idx)
279            } else {
280                None
281            }
282        }
283    }
284
285    // These impls are only there for backward compatibility reasons
286    // Remove them on the next breaking release
287    #[cfg(all(feature = "with-deprecated", not(feature = "without-deprecated")))]
288    #[allow(unreachable_pub)]
289    pub trait RowLifetimeHelper<DB>: for<'a> super::Row<'a, DB>
290    where
291        DB: Backend,
292    {
293        type Field<'f>
294        where
295            Self: 'f;
296    }
297
298    #[cfg(all(feature = "with-deprecated", not(feature = "without-deprecated")))]
299    impl<R, DB> RowLifetimeHelper<DB> for R
300    where
301        DB: Backend,
302        for<'a> R: super::Row<'a, DB>,
303    {
304        type Field<'f>
305            = <R as super::Row<'f, DB>>::Field<'f>
306        where
307            R: 'f;
308    }
309}