1use self::private::LoadIter;
2use super::RunQueryDsl;
3use crate::backend::Backend;
4use crate::connection::{Connection, DefaultLoadingMode, LoadConnection};
5use crate::deserialize::FromSqlRow;
6use crate::expression::QueryMetadata;
7use crate::query_builder::{AsQuery, QueryFragment, QueryId};
8use crate::result::QueryResult;
9
10#[cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")]
11pub use self::private::CompatibleType;
12
13#[cfg(not(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"))]
14pub(crate) use self::private::CompatibleType;
15
16pub trait LoadQuery<'query, Conn, U, B = DefaultLoadingMode>: RunQueryDsl<Conn> {
24 type RowIter<'conn>: Iterator<Item = QueryResult<U>>
26 where
27 Conn: 'conn;
28
29 #[diesel_derives::__diesel_public_if(
31 feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
32 )]
33 fn internal_load(self, conn: &mut Conn) -> QueryResult<Self::RowIter<'_>>;
34}
35
36#[doc(hidden)]
37#[cfg(all(feature = "with-deprecated", not(feature = "without-deprecated")))]
38#[deprecated(note = "Use `LoadQuery::Iter` directly")]
39pub type LoadRet<'conn, 'query, Q, C, U, B = DefaultLoadingMode> =
40 <Q as LoadQuery<'query, C, U, B>>::RowIter<'conn>;
41
42impl<'query, Conn, T, U, DB, B> LoadQuery<'query, Conn, U, B> for T
43where
44 Conn: Connection<Backend = DB> + LoadConnection<B>,
45 T: AsQuery + RunQueryDsl<Conn>,
46 T::Query: QueryFragment<DB> + QueryId + 'query,
47 T::SqlType: CompatibleType<U, DB>,
48 DB: Backend + QueryMetadata<T::SqlType> + 'static,
49 U: FromSqlRow<<T::SqlType as CompatibleType<U, DB>>::SqlType, DB> + 'static,
50 <T::SqlType as CompatibleType<U, DB>>::SqlType: 'static,
51{
52 type RowIter<'conn>
53 = LoadIter<
54 U,
55 <Conn as LoadConnection<B>>::Cursor<'conn, 'query>,
56 <T::SqlType as CompatibleType<U, DB>>::SqlType,
57 DB,
58 >
59 where
60 Conn: 'conn;
61
62 fn internal_load(self, conn: &mut Conn) -> QueryResult<Self::RowIter<'_>> {
63 const {
64 let _ = T::Query::IS_WINDOW_FUNCTION;
67 }
68 Ok(LoadIter {
69 cursor: conn.load(self.as_query())?,
70 _marker: Default::default(),
71 })
72 }
73}
74
75pub trait ExecuteDsl<Conn: Connection<Backend = DB>, DB: Backend = <Conn as Connection>::Backend>:
83 Sized
84{
85 fn execute(query: Self, conn: &mut Conn) -> QueryResult<usize>;
87}
88
89use crate::result::Error;
90
91impl<Conn, DB, T> ExecuteDsl<Conn, DB> for T
92where
93 Conn: Connection<Backend = DB>,
94 DB: Backend,
95 T: QueryFragment<DB> + QueryId,
96{
97 fn execute(query: T, conn: &mut Conn) -> Result<usize, Error> {
98 conn.execute_returning_count(&query)
99 }
100}
101
102mod private {
108 use crate::backend::Backend;
109 use crate::deserialize::FromSqlRow;
110 use crate::expression::select_by::SelectBy;
111 use crate::expression::{Expression, TypedExpressionType};
112 use crate::sql_types::{SqlType, Untyped};
113 use crate::{QueryResult, Selectable};
114
115 #[allow(missing_debug_implementations)]
116 pub struct LoadIter<U, C, ST, DB> {
117 pub(super) cursor: C,
118 pub(super) _marker: std::marker::PhantomData<(ST, U, DB)>,
119 }
120
121 impl<'a, C, U, ST, DB, R> LoadIter<U, C, ST, DB>
122 where
123 DB: Backend,
124 C: Iterator<Item = QueryResult<R>>,
125 R: crate::row::Row<'a, DB>,
126 U: FromSqlRow<ST, DB>,
127 {
128 pub(super) fn map_row(row: Option<QueryResult<R>>) -> Option<QueryResult<U>> {
129 match row? {
130 Ok(row) => Some(
131 U::build_from_row(&row).map_err(crate::result::Error::DeserializationError),
132 ),
133 Err(e) => Some(Err(e)),
134 }
135 }
136 }
137
138 impl<'a, C, U, ST, DB, R> Iterator for LoadIter<U, C, ST, DB>
139 where
140 DB: Backend,
141 C: Iterator<Item = QueryResult<R>>,
142 R: crate::row::Row<'a, DB>,
143 U: FromSqlRow<ST, DB>,
144 {
145 type Item = QueryResult<U>;
146
147 fn next(&mut self) -> Option<Self::Item> {
148 Self::map_row(self.cursor.next())
149 }
150
151 fn size_hint(&self) -> (usize, Option<usize>) {
152 self.cursor.size_hint()
153 }
154
155 fn count(self) -> usize
156 where
157 Self: Sized,
158 {
159 self.cursor.count()
160 }
161
162 fn last(self) -> Option<Self::Item>
163 where
164 Self: Sized,
165 {
166 Self::map_row(self.cursor.last())
167 }
168
169 fn nth(&mut self, n: usize) -> Option<Self::Item> {
170 Self::map_row(self.cursor.nth(n))
171 }
172 }
173
174 impl<'a, C, U, ST, DB, R> ExactSizeIterator for LoadIter<U, C, ST, DB>
175 where
176 DB: Backend,
177 C: ExactSizeIterator + Iterator<Item = QueryResult<R>>,
178 R: crate::row::Row<'a, DB>,
179 U: FromSqlRow<ST, DB>,
180 {
181 fn len(&self) -> usize {
182 self.cursor.len()
183 }
184 }
185
186 #[cfg_attr(
187 docsrs,
188 doc(cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"))
189 )]
190 #[diagnostic::on_unimplemented(
191 note = "this is a mismatch between what your query returns and what your type expects the query to return",
192 note = "the fields in your struct need to match the fields returned by your query in count, order and type",
193 note = "consider using `#[diesel(check_for_backend({DB}))]` on either `#[derive(Selectable)]` or `#[derive(QueryableByName)]` \n\
194 on your struct `{U}` and in your query `.select({U}::as_select())` to get a better error message"
195 )]
196 pub trait CompatibleType<U, DB> {
197 type SqlType;
198 }
199
200 impl<ST, U, DB> CompatibleType<U, DB> for ST
201 where
202 DB: Backend,
203 ST: SqlType + crate::sql_types::SingleValue,
204 U: FromSqlRow<ST, DB>,
205 {
206 type SqlType = ST;
207 }
208
209 impl<U, DB> CompatibleType<U, DB> for Untyped
210 where
211 U: FromSqlRow<Untyped, DB>,
212 DB: Backend,
213 {
214 type SqlType = Untyped;
215 }
216
217 impl<U, DB, E, ST> CompatibleType<U, DB> for SelectBy<U, DB>
218 where
219 DB: Backend,
220 ST: SqlType + TypedExpressionType,
221 U: Selectable<DB, SelectExpression = E>,
222 E: Expression<SqlType = ST>,
223 U: FromSqlRow<ST, DB>,
224 {
225 type SqlType = ST;
226 }
227}