1//! Contains the `Row` trait
23use crate::backend::Backend;
4use crate::deserialize;
5use deserialize::FromSql;
6use std::default::Default;
7use std::ops::Range;
89#[cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")]
10#[doc(inline)]
11pub use self::private::{PartialRow, RowSealed};
1213#[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};
1617/// 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
27fn idx(&self, idx: I) -> Option<usize>;
28}
2930#[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>;
3435/// 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>:
41RowIndex<usize> + for<'b> RowIndex<&'b str> + self::private::RowSealed + Sized42{
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
50type Field<'f>: Field<'f, DB>
51where
52'a: 'f,
53Self: 'f;
5455/// 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 )]
63type InnerPartialRow: Row<'a, DB>;
6465/// Get the number of fields in the current row
66fn field_count(&self) -> usize;
6768/// Get the field with the provided index from the row.
69 ///
70 /// Returns `None` if there is no matching field for the given index
71fn get<'b, I>(&'b self, idx: I) -> Option<Self::Field<'b>>
72where
73'a: 'b,
74Self: RowIndex<I>;
7576/// Get a deserialized value with the provided index from the row.
77fn get_value<ST, T, I>(&self, idx: I) -> crate::deserialize::Result<T>
78where
79Self: RowIndex<I>,
80 T: FromSql<ST, DB>,
81 {
82let field = self.get(idx).ok_or(crate::result::UnexpectedEndOfRow)?;
83 <T as FromSql<ST, DB>>::from_nullable_sql(field.value())
84 }
8586/// 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 )]
92fn partial_row(&self, range: Range<usize>) -> PartialRow<'_, Self::InnerPartialRow>;
93}
9495/// 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
103fn field_name(&self) -> Option<&str>;
104105/// Get the value representing the current field in the raw representation
106 /// as it is transmitted by the database
107fn value(&self) -> Option<DB::RawValue<'_>>;
108109/// Checks whether this field is null or not.
110fn is_null(&self) -> bool {
111self.value().is_none()
112 }
113}
114115/// 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.
130fn get<ST, T>(&self, column_name: &str) -> deserialize::Result<T>
131where
132T: FromSql<ST, DB>;
133}
134135impl<'a, R, DB> NamedRow<'a, DB> for R
136where
137R: Row<'a, DB>,
138 DB: Backend,
139{
140fn get<ST, T>(&self, column_name: &str) -> deserialize::Result<T>
141where
142T: FromSql<ST, DB>,
143 {
144let field = Row::get(self, column_name)
145 .ok_or_else(|| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Column `{0}` was not present in query",
column_name))
})format!("Column `{column_name}` was not present in query"))?;
146147 T::from_nullable_sql(field.value())
148 }
149}
150151/// A row that can be turned into an owned version
152#[doc = " A row that can be turned into an owned version"]
pub trait IntoOwnedRow<'a, DB: Backend>: Row<'a, DB> {
/// The owned version of the row
type OwnedRow: Row<'a, DB> + Send + 'static;
/// A store for cached information between rows for faster access
type Cache: Default + 'static;
/// Turn the row into its owned version
fn into_owned(self, cache: &mut Self::Cache)
-> Self::OwnedRow;
}#[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
157type OwnedRow: Row<'a, DB> + Send + 'static;
158159/// A store for cached information between rows for faster access
160type Cache: Default + 'static;
161162/// Turn the row into its owned version
163fn into_owned(self, cache: &mut Self::Cache) -> Self::OwnedRow;
164}
165166// 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 {
172use super::*;
173174/// This trait restricts who can implement `Row`
175#[cfg_attr(
176 diesel_docsrs,
177 doc(cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"))
178 )]
179pub trait RowSealed {}
180181/// 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(#[automatically_derived]
impl<'a, R: ::core::fmt::Debug> ::core::fmt::Debug for PartialRow<'a, R> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "PartialRow",
"inner", &self.inner, "range", &&self.range)
}
}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 )]
194pub struct PartialRow<'a, R> {
195 inner: &'a R,
196 range: Range<usize>,
197 }
198199impl<'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.
205pub fn new<'b, DB>(inner: &'a R, range: Range<usize>) -> Self
206where
207R: Row<'b, DB>,
208 DB: Backend,
209 {
210let range_lower = std::cmp::min(range.start, inner.field_count());
211let range_upper = std::cmp::min(range.end, inner.field_count());
212Self {
213inner,
214 range: range_lower..range_upper,
215 }
216 }
217 }
218219impl<R> RowSealedfor PartialRow<'_, R> {}
220221impl<'a, DB, R> Row<'a, DB> for PartialRow<'_, R>
222where
223DB: Backend,
224 R: Row<'a, DB>,
225 {
226type Field<'f>
227 = R::Field<'f>
228where
229'a: 'f,
230 R: 'f,
231Self: 'f;
232type InnerPartialRow = R;
233234fn field_count(&self) -> usize {
235self.range.len()
236 }
237238fn get<'c, I>(&'c self, idx: I) -> Option<Self::Field<'c>>
239where
240'a: 'c,
241Self: RowIndex<I>,
242 {
243let idx = self.idx(idx)?;
244self.inner.get(idx)
245 }
246247fn partial_row(&self, range: Range<usize>) -> PartialRow<'_, R> {
248let range_upper_bound = std::cmp::min(self.range.end, self.range.start + range.end);
249let range = (self.range.start + range.start)..range_upper_bound;
250PartialRow {
251 inner: self.inner,
252range,
253 }
254 }
255 }
256257impl<'a, R> RowIndex<&'a str> for PartialRow<'_, R>
258where
259R: RowIndex<&'a str>,
260 {
261fn idx(&self, idx: &'a str) -> Option<usize> {
262let idx = self.inner.idx(idx)?;
263if self.range.contains(&idx) {
264Some(idx)
265 } else {
266None267 }
268 }
269 }
270271impl<R> RowIndex<usize> for PartialRow<'_, R>
272where
273R: RowIndex<usize>,
274 {
275fn idx(&self, idx: usize) -> Option<usize> {
276let idx = self.inner.idx(idx + self.range.start)?;
277if self.range.contains(&idx) {
278Some(idx)
279 } else {
280None281 }
282 }
283 }
284285// 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)]
289pub trait RowLifetimeHelper<DB>: for<'a> super::Row<'a, DB>
290where
291DB: Backend,
292 {
293type Field<'f>
294where
295Self: 'f;
296 }
297298#[cfg(all(feature = "with-deprecated", not(feature = "without-deprecated")))]
299impl<R, DB> RowLifetimeHelper<DB> for R
300where
301DB: Backend,
302for<'a> R: super::Row<'a, DB>,
303 {
304type Field<'f>
305 = <R as super::Row<'f, DB>>::Field<'f>
306where
307R: 'f;
308 }
309}