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