1use 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
17pub trait RowIndex<I> {
27 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
36pub trait Row<'a, DB: Backend>:
42 RowIndex<usize> + for<'b> RowIndex<&'b str> + self::private::RowSealed + Sized
43{
44 type Field<'f>: Field<'f, DB>
52 where
53 'a: 'f,
54 Self: 'f;
55
56 #[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 fn field_count(&self) -> usize;
68
69 fn get<'b, I>(&'b self, idx: I) -> Option<Self::Field<'b>>
73 where
74 'a: 'b,
75 Self: RowIndex<I>;
76
77 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 #[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
96pub trait Field<'a, DB: Backend> {
101 fn field_name(&self) -> Option<&str>;
105
106 fn value(&self) -> Option<DB::RawValue<'_>>;
109
110 fn is_null(&self) -> bool {
112 self.value().is_none()
113 }
114}
115
116pub trait NamedRow<'a, DB: Backend>: Row<'a, DB> {
122 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#[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 type OwnedRow: Row<'a, DB> + Send + 'static;
159
160 type Cache: Default + 'static;
162
163 fn into_owned(self, cache: &mut Self::Cache) -> Self::OwnedRow;
165}
166
167pub(crate) mod private {
173 use super::*;
174
175 #[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 #[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 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 #[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}