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> {
26 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
35pub trait Row<'a, DB: Backend>:
41 RowIndex<usize> + for<'b> RowIndex<&'b str> + self::private::RowSealed + Sized
42{
43 type Field<'f>: Field<'f, DB>
51 where
52 'a: 'f,
53 Self: 'f;
54
55 #[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 fn field_count(&self) -> usize;
67
68 fn get<'b, I>(&'b self, idx: I) -> Option<Self::Field<'b>>
72 where
73 'a: 'b,
74 Self: RowIndex<I>;
75
76 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 #[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
95pub trait Field<'a, DB: Backend> {
100 fn field_name(&self) -> Option<&str>;
104
105 fn value(&self) -> Option<DB::RawValue<'_>>;
108
109 fn is_null(&self) -> bool {
111 self.value().is_none()
112 }
113}
114
115pub trait NamedRow<'a, DB: Backend>: Row<'a, DB> {
121 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#[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 type OwnedRow: Row<'a, DB> + Send + 'static;
158
159 type Cache: Default + 'static;
161
162 fn into_owned(self, cache: &mut Self::Cache) -> Self::OwnedRow;
164}
165
166pub(crate) mod private {
172 use super::*;
173
174 #[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 #[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 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 #[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}