sea_orm/executor/select.rs
1use super::{
2 consolidate_query_result, consolidate_query_result_chain, consolidate_query_result_tee,
3};
4use crate::{
5 ConnectionTrait, DbBackend, EntityTrait, FromQueryResult, IdenStatic, PartialModelTrait,
6 QueryResult, QuerySelect, Select, SelectA, SelectB, SelectTwo, SelectTwoMany,
7 SelectTwoRequired, Statement, StreamTrait, TryGetableMany, error::*,
8};
9use futures_util::{Stream, TryStreamExt};
10use itertools::Itertools;
11use sea_query::SelectStatement;
12use std::{marker::PhantomData, pin::Pin};
13
14mod five;
15mod four;
16mod six;
17mod three;
18
19#[cfg(feature = "with-json")]
20use crate::JsonValue;
21
22#[cfg(not(feature = "sync"))]
23type PinBoxStream<'b, S> = Pin<Box<dyn Stream<Item = Result<S, DbErr>> + 'b + Send>>;
24#[cfg(feature = "sync")]
25type PinBoxStream<'b, S> = Box<dyn Iterator<Item = Result<S, DbErr>> + 'b + Send>;
26
27/// Defines a type to do `SELECT` operations through a [SelectStatement] on a Model
28#[derive(Clone, Debug)]
29pub struct Selector<S>
30where
31 S: SelectorTrait,
32{
33 pub(crate) query: SelectStatement,
34 selector: PhantomData<S>,
35}
36
37/// Performs a raw `SELECT` operation on a model
38#[derive(Clone, Debug)]
39pub struct SelectorRaw<S>
40where
41 S: SelectorTrait,
42{
43 pub(crate) stmt: Statement,
44 pub(super) selector: PhantomData<S>,
45}
46
47/// A Trait for any type that can perform SELECT queries
48pub trait SelectorTrait {
49 #[allow(missing_docs)]
50 type Item: Sized;
51
52 /// The method to perform a query on a Model
53 fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr>;
54}
55
56/// Get tuple from query result based on a list of column identifiers
57#[derive(Debug)]
58pub struct SelectGetableValue<T, C>
59where
60 T: TryGetableMany,
61 C: strum::IntoEnumIterator + sea_query::Iden,
62{
63 columns: PhantomData<C>,
64 model: PhantomData<T>,
65}
66
67/// Get tuple from query result based on column index
68#[derive(Debug)]
69pub struct SelectGetableTuple<T>
70where
71 T: TryGetableMany,
72{
73 model: PhantomData<T>,
74}
75
76/// Helper class to handle query result for 1 Model
77#[derive(Debug)]
78pub struct SelectModel<M>
79where
80 M: FromQueryResult,
81{
82 model: PhantomData<M>,
83}
84
85/// Defines a type to get two Models, with the second being optional
86#[derive(Clone, Debug)]
87pub struct SelectTwoModel<M, N>
88where
89 M: FromQueryResult,
90 N: FromQueryResult,
91{
92 model: PhantomData<(M, N)>,
93}
94
95/// Defines a type to get two Models
96#[derive(Clone, Debug)]
97pub struct SelectTwoRequiredModel<M, N>
98where
99 M: FromQueryResult,
100 N: FromQueryResult,
101{
102 model: PhantomData<(M, N)>,
103}
104
105/// Helper class to handle query result for 3 Models
106#[derive(Clone, Debug)]
107pub struct SelectThreeModel<M, N, O>
108where
109 M: FromQueryResult,
110 N: FromQueryResult,
111 O: FromQueryResult,
112{
113 model: PhantomData<(M, N, O)>,
114}
115
116/// Helper class to handle query result for 4 Models
117#[derive(Clone, Debug)]
118pub struct SelectFourModel<M, N, O, P>
119where
120 M: FromQueryResult,
121 N: FromQueryResult,
122 O: FromQueryResult,
123 P: FromQueryResult,
124{
125 model: PhantomData<(M, N, O, P)>,
126}
127
128/// Helper class to handle query result for 5 Models
129#[derive(Clone, Debug)]
130pub struct SelectFiveModel<M, N, O, P, Q>
131where
132 M: FromQueryResult,
133 N: FromQueryResult,
134 O: FromQueryResult,
135 P: FromQueryResult,
136 Q: FromQueryResult,
137{
138 model: PhantomData<(M, N, O, P, Q)>,
139}
140
141/// Helper class to handle query result for 6 Models
142#[derive(Clone, Debug)]
143pub struct SelectSixModel<M, N, O, P, Q, R>
144where
145 M: FromQueryResult,
146 N: FromQueryResult,
147 O: FromQueryResult,
148 P: FromQueryResult,
149 Q: FromQueryResult,
150 R: FromQueryResult,
151{
152 model: PhantomData<(M, N, O, P, Q, R)>,
153}
154
155impl<T, C> Default for SelectGetableValue<T, C>
156where
157 T: TryGetableMany,
158 C: strum::IntoEnumIterator + sea_query::Iden,
159{
160 fn default() -> Self {
161 Self {
162 columns: PhantomData,
163 model: PhantomData,
164 }
165 }
166}
167
168impl<T, C> SelectorTrait for SelectGetableValue<T, C>
169where
170 T: TryGetableMany,
171 C: strum::IntoEnumIterator + sea_query::Iden,
172{
173 type Item = T;
174
175 fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr> {
176 let cols: Vec<String> = C::iter().map(|col| col.to_string()).collect();
177 T::try_get_many(&res, "", &cols).map_err(Into::into)
178 }
179}
180
181impl<T> SelectorTrait for SelectGetableTuple<T>
182where
183 T: TryGetableMany,
184{
185 type Item = T;
186
187 fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr> {
188 T::try_get_many_by_index(&res).map_err(Into::into)
189 }
190}
191
192impl<M> SelectorTrait for SelectModel<M>
193where
194 M: FromQueryResult + Sized,
195{
196 type Item = M;
197
198 fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr> {
199 M::from_query_result(&res, "")
200 }
201}
202
203impl<M, N> SelectorTrait for SelectTwoModel<M, N>
204where
205 M: FromQueryResult + Sized,
206 N: FromQueryResult + Sized,
207{
208 type Item = (M, Option<N>);
209
210 fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr> {
211 Ok((
212 M::from_query_result(&res, SelectA.as_str())?,
213 N::from_query_result_optional(&res, SelectB.as_str())?,
214 ))
215 }
216}
217
218impl<M, N> SelectorTrait for SelectTwoRequiredModel<M, N>
219where
220 M: FromQueryResult + Sized,
221 N: FromQueryResult + Sized,
222{
223 type Item = (M, N);
224
225 fn from_raw_query_result(res: QueryResult) -> Result<Self::Item, DbErr> {
226 Ok((
227 M::from_query_result(&res, SelectA.as_str())?,
228 N::from_query_result(&res, SelectB.as_str())?,
229 ))
230 }
231}
232
233impl<E> Select<E>
234where
235 E: EntityTrait,
236{
237 /// Perform a Select operation on a Model using a [Statement]
238 #[allow(clippy::wrong_self_convention)]
239 pub fn from_raw_sql(self, stmt: Statement) -> SelectorRaw<SelectModel<E::Model>> {
240 SelectorRaw {
241 stmt,
242 selector: PhantomData,
243 }
244 }
245
246 /// Return a [Selector] from `Self` that wraps a [SelectModel]
247 pub fn into_model<M>(self) -> Selector<SelectModel<M>>
248 where
249 M: FromQueryResult,
250 {
251 Selector {
252 query: self.query,
253 selector: PhantomData,
254 }
255 }
256
257 /// Return a [Selector] from `Self` that wraps a [SelectModel] with a [PartialModel](PartialModelTrait)
258 ///
259 /// ```
260 /// # #[cfg(feature = "macros")]
261 /// # {
262 /// use sea_orm::{
263 /// entity::*,
264 /// query::*,
265 /// tests_cfg::cake::{self, Entity as Cake},
266 /// DbBackend, DerivePartialModel,
267 /// };
268 /// use sea_query::{Expr, Func, SimpleExpr};
269 ///
270 /// #[derive(DerivePartialModel)]
271 /// #[sea_orm(entity = "Cake")]
272 /// struct PartialCake {
273 /// name: String,
274 /// #[sea_orm(
275 /// from_expr = r#"SimpleExpr::FunctionCall(Func::upper(Expr::col((Cake, cake::Column::Name))))"#
276 /// )]
277 /// name_upper: String,
278 /// }
279 ///
280 /// assert_eq!(
281 /// cake::Entity::find()
282 /// .into_partial_model::<PartialCake>()
283 /// .into_statement(DbBackend::Sqlite)
284 /// .to_string(),
285 /// r#"SELECT "cake"."name" AS "name", UPPER("cake"."name") AS "name_upper" FROM "cake""#
286 /// );
287 /// # }
288 /// ```
289 pub fn into_partial_model<M>(self) -> Selector<SelectModel<M>>
290 where
291 M: PartialModelTrait,
292 {
293 M::select_cols(QuerySelect::select_only(self)).into_model::<M>()
294 }
295
296 /// Get a selectable Model as a [JsonValue] for SQL JSON operations
297 #[cfg(feature = "with-json")]
298 pub fn into_json(self) -> Selector<SelectModel<JsonValue>> {
299 Selector {
300 query: self.query,
301 selector: PhantomData,
302 }
303 }
304
305 /// ```
306 /// # use sea_orm::{error::*, tests_cfg::*, *};
307 /// #
308 /// # #[smol_potat::main]
309 /// # #[cfg(all(feature = "mock", feature = "macros"))]
310 /// # pub async fn main() -> Result<(), DbErr> {
311 /// #
312 /// # let db = MockDatabase::new(DbBackend::Postgres)
313 /// # .append_query_results([[
314 /// # maplit::btreemap! {
315 /// # "cake_name" => Into::<Value>::into("Chocolate Forest"),
316 /// # },
317 /// # maplit::btreemap! {
318 /// # "cake_name" => Into::<Value>::into("New York Cheese"),
319 /// # },
320 /// # ]])
321 /// # .into_connection();
322 /// #
323 /// use sea_orm::{DeriveColumn, EnumIter, entity::*, query::*, tests_cfg::cake};
324 ///
325 /// #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
326 /// enum QueryAs {
327 /// CakeName,
328 /// }
329 ///
330 /// let res: Vec<String> = cake::Entity::find()
331 /// .select_only()
332 /// .column_as(cake::Column::Name, QueryAs::CakeName)
333 /// .into_values::<_, QueryAs>()
334 /// .all(&db)
335 /// .await?;
336 ///
337 /// assert_eq!(
338 /// res,
339 /// ["Chocolate Forest".to_owned(), "New York Cheese".to_owned()]
340 /// );
341 ///
342 /// assert_eq!(
343 /// db.into_transaction_log(),
344 /// [Transaction::from_sql_and_values(
345 /// DbBackend::Postgres,
346 /// r#"SELECT "cake"."name" AS "cake_name" FROM "cake""#,
347 /// []
348 /// )]
349 /// );
350 /// #
351 /// # Ok(())
352 /// # }
353 /// ```
354 ///
355 /// ```
356 /// # use sea_orm::{error::*, tests_cfg::*, *};
357 /// #
358 /// # #[smol_potat::main]
359 /// # #[cfg(all(feature = "mock", feature = "macros"))]
360 /// # pub async fn main() -> Result<(), DbErr> {
361 /// #
362 /// # let db = MockDatabase::new(DbBackend::Postgres)
363 /// # .append_query_results([[
364 /// # maplit::btreemap! {
365 /// # "cake_name" => Into::<Value>::into("Chocolate Forest"),
366 /// # "num_of_cakes" => Into::<Value>::into(2i64),
367 /// # },
368 /// # ]])
369 /// # .into_connection();
370 /// #
371 /// use sea_orm::{DeriveColumn, EnumIter, entity::*, query::*, tests_cfg::cake};
372 ///
373 /// #[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
374 /// enum QueryAs {
375 /// CakeName,
376 /// NumOfCakes,
377 /// }
378 ///
379 /// let res: Vec<(String, i64)> = cake::Entity::find()
380 /// .select_only()
381 /// .column_as(cake::Column::Name, QueryAs::CakeName)
382 /// .column_as(cake::Column::Id.count(), QueryAs::NumOfCakes)
383 /// .group_by(cake::Column::Name)
384 /// .into_values::<_, QueryAs>()
385 /// .all(&db)
386 /// .await?;
387 ///
388 /// assert_eq!(res, [("Chocolate Forest".to_owned(), 2i64)]);
389 ///
390 /// assert_eq!(
391 /// db.into_transaction_log(),
392 /// [Transaction::from_sql_and_values(
393 /// DbBackend::Postgres,
394 /// [
395 /// r#"SELECT "cake"."name" AS "cake_name", COUNT("cake"."id") AS "num_of_cakes""#,
396 /// r#"FROM "cake" GROUP BY "cake"."name""#,
397 /// ]
398 /// .join(" ")
399 /// .as_str(),
400 /// []
401 /// )]
402 /// );
403 /// #
404 /// # Ok(())
405 /// # }
406 /// ```
407 pub fn into_values<T, C>(self) -> Selector<SelectGetableValue<T, C>>
408 where
409 T: TryGetableMany,
410 C: strum::IntoEnumIterator + sea_query::Iden,
411 {
412 Selector {
413 query: self.query,
414 selector: PhantomData,
415 }
416 }
417
418 /// ```
419 /// # use sea_orm::{error::*, tests_cfg::*, *};
420 /// #
421 /// # #[smol_potat::main]
422 /// # #[cfg(all(feature = "mock", feature = "macros"))]
423 /// # pub async fn main() -> Result<(), DbErr> {
424 /// #
425 /// # let db = MockDatabase::new(DbBackend::Postgres)
426 /// # .append_query_results(vec![vec![
427 /// # maplit::btreemap! {
428 /// # "cake_name" => Into::<Value>::into("Chocolate Forest"),
429 /// # },
430 /// # maplit::btreemap! {
431 /// # "cake_name" => Into::<Value>::into("New York Cheese"),
432 /// # },
433 /// # ]])
434 /// # .into_connection();
435 /// #
436 /// use sea_orm::{entity::*, query::*, tests_cfg::cake};
437 ///
438 /// let res: Vec<String> = cake::Entity::find()
439 /// .select_only()
440 /// .column(cake::Column::Name)
441 /// .into_tuple()
442 /// .all(&db)
443 /// .await?;
444 ///
445 /// assert_eq!(
446 /// res,
447 /// vec!["Chocolate Forest".to_owned(), "New York Cheese".to_owned()]
448 /// );
449 ///
450 /// assert_eq!(
451 /// db.into_transaction_log(),
452 /// vec![Transaction::from_sql_and_values(
453 /// DbBackend::Postgres,
454 /// r#"SELECT "cake"."name" FROM "cake""#,
455 /// vec![]
456 /// )]
457 /// );
458 /// #
459 /// # Ok(())
460 /// # }
461 /// ```
462 ///
463 /// ```
464 /// # use sea_orm::{error::*, tests_cfg::*, *};
465 /// #
466 /// # #[smol_potat::main]
467 /// # #[cfg(all(feature = "mock", feature = "macros"))]
468 /// # pub async fn main() -> Result<(), DbErr> {
469 /// #
470 /// # let db = MockDatabase::new(DbBackend::Postgres)
471 /// # .append_query_results(vec![vec![
472 /// # maplit::btreemap! {
473 /// # "cake_name" => Into::<Value>::into("Chocolate Forest"),
474 /// # "num_of_cakes" => Into::<Value>::into(2i64),
475 /// # },
476 /// # ]])
477 /// # .into_connection();
478 /// #
479 /// use sea_orm::{entity::*, query::*, tests_cfg::cake};
480 ///
481 /// let res: Vec<(String, i64)> = cake::Entity::find()
482 /// .select_only()
483 /// .column(cake::Column::Name)
484 /// .column(cake::Column::Id)
485 /// .group_by(cake::Column::Name)
486 /// .into_tuple()
487 /// .all(&db)
488 /// .await?;
489 ///
490 /// assert_eq!(res, vec![("Chocolate Forest".to_owned(), 2i64)]);
491 ///
492 /// assert_eq!(
493 /// db.into_transaction_log(),
494 /// vec![Transaction::from_sql_and_values(
495 /// DbBackend::Postgres,
496 /// vec![
497 /// r#"SELECT "cake"."name", "cake"."id""#,
498 /// r#"FROM "cake" GROUP BY "cake"."name""#,
499 /// ]
500 /// .join(" ")
501 /// .as_str(),
502 /// vec![]
503 /// )]
504 /// );
505 /// #
506 /// # Ok(())
507 /// # }
508 /// ```
509 pub fn into_tuple<T>(self) -> Selector<SelectGetableTuple<T>>
510 where
511 T: TryGetableMany,
512 {
513 Selector {
514 query: self.query,
515 selector: PhantomData,
516 }
517 }
518
519 /// Get one Model from the SELECT query
520 pub async fn one<C>(self, db: &C) -> Result<Option<E::Model>, DbErr>
521 where
522 C: ConnectionTrait,
523 {
524 self.into_model().one(db).await
525 }
526
527 /// Get all Models from the SELECT query
528 pub async fn all<C>(self, db: &C) -> Result<Vec<E::Model>, DbErr>
529 where
530 C: ConnectionTrait,
531 {
532 self.into_model().all(db).await
533 }
534
535 /// Stream the results of a SELECT operation on a Model
536 pub async fn stream<'a: 'b, 'b, C>(
537 self,
538 db: &'a C,
539 ) -> Result<impl Stream<Item = Result<E::Model, DbErr>> + 'b + Send, DbErr>
540 where
541 C: ConnectionTrait + StreamTrait + Send,
542 {
543 self.into_model().stream(db).await
544 }
545
546 /// Stream the result of the operation with PartialModel
547 pub async fn stream_partial_model<'a: 'b, 'b, C, M>(
548 self,
549 db: &'a C,
550 ) -> Result<impl Stream<Item = Result<M, DbErr>> + 'b + Send, DbErr>
551 where
552 C: ConnectionTrait + StreamTrait + Send,
553 M: PartialModelTrait + Send + 'b,
554 {
555 self.into_partial_model().stream(db).await
556 }
557}
558
559impl<E, F> SelectTwo<E, F>
560where
561 E: EntityTrait,
562 F: EntityTrait,
563{
564 /// Perform a conversion into a [SelectTwoModel]
565 pub fn into_model<M, N>(self) -> Selector<SelectTwoModel<M, N>>
566 where
567 M: FromQueryResult,
568 N: FromQueryResult,
569 {
570 Selector {
571 query: self.query,
572 selector: PhantomData,
573 }
574 }
575
576 /// Perform a conversion into a [SelectTwoModel] with [PartialModel](PartialModelTrait)
577 pub fn into_partial_model<M, N>(self) -> Selector<SelectTwoModel<M, N>>
578 where
579 M: PartialModelTrait,
580 N: PartialModelTrait,
581 {
582 let select = QuerySelect::select_only(self);
583 let select = M::select_cols(select);
584 let select = N::select_cols(select);
585 select.into_model::<M, N>()
586 }
587
588 /// Convert the Models into JsonValue
589 #[cfg(feature = "with-json")]
590 pub fn into_json(self) -> Selector<SelectTwoModel<JsonValue, JsonValue>> {
591 Selector {
592 query: self.query,
593 selector: PhantomData,
594 }
595 }
596
597 /// Get one Model from the Select query
598 pub async fn one<C>(self, db: &C) -> Result<Option<(E::Model, Option<F::Model>)>, DbErr>
599 where
600 C: ConnectionTrait,
601 {
602 self.into_model().one(db).await
603 }
604
605 /// Get all Models from the Select query
606 pub async fn all<C>(self, db: &C) -> Result<Vec<(E::Model, Option<F::Model>)>, DbErr>
607 where
608 C: ConnectionTrait,
609 {
610 self.into_model().all(db).await
611 }
612
613 /// Stream the results of a Select operation on a Model
614 pub async fn stream<'a: 'b, 'b, C>(
615 self,
616 db: &'a C,
617 ) -> Result<impl Stream<Item = Result<(E::Model, Option<F::Model>), DbErr>> + 'b, DbErr>
618 where
619 C: ConnectionTrait + StreamTrait + Send,
620 {
621 self.into_model().stream(db).await
622 }
623
624 /// Stream the result of the operation with PartialModel
625 pub async fn stream_partial_model<'a: 'b, 'b, C, M, N>(
626 self,
627 db: &'a C,
628 ) -> Result<impl Stream<Item = Result<(M, Option<N>), DbErr>> + 'b + Send, DbErr>
629 where
630 C: ConnectionTrait + StreamTrait + Send,
631 M: PartialModelTrait + Send + 'b,
632 N: PartialModelTrait + Send + 'b,
633 {
634 self.into_partial_model().stream(db).await
635 }
636}
637
638impl<E, F> SelectTwoMany<E, F>
639where
640 E: EntityTrait,
641 F: EntityTrait,
642{
643 /// Performs a conversion to [Selector]
644 fn into_model<M, N>(self) -> Selector<SelectTwoModel<M, N>>
645 where
646 M: FromQueryResult,
647 N: FromQueryResult,
648 {
649 Selector {
650 query: self.query,
651 selector: PhantomData,
652 }
653 }
654
655 /// Get all Models from the select operation and consolidate result based on left Model.
656 ///
657 /// > `SelectTwoMany::one()` method has been dropped (#486)
658 /// >
659 /// > You can get `(Entity, Vec<relatedEntity>)` by first querying a single model from Entity,
660 /// > then use [`ModelTrait::find_related`] on the model.
661 /// >
662 /// > See https://www.sea-ql.org/SeaORM/docs/basic-crud/select#lazy-loading for details.
663 pub async fn all<C>(self, db: &C) -> Result<Vec<(E::Model, Vec<F::Model>)>, DbErr>
664 where
665 C: ConnectionTrait,
666 {
667 let rows = self.into_model().all(db).await?;
668 Ok(consolidate_query_result::<E, F>(rows))
669 }
670
671 // pub fn paginate()
672 // we could not implement paginate easily, if the number of children for a
673 // parent is larger than one page, then we will end up splitting it in two pages
674 // so the correct way is actually perform query in two stages
675 // paginate the parent model and then populate the children
676
677 // pub fn count()
678 // we should only count the number of items of the parent model
679}
680
681impl<E, F> SelectTwoRequired<E, F>
682where
683 E: EntityTrait,
684 F: EntityTrait,
685{
686 /// Perform a conversion into a [SelectTwoRequiredModel]
687 pub fn into_model<M, N>(self) -> Selector<SelectTwoRequiredModel<M, N>>
688 where
689 M: FromQueryResult,
690 N: FromQueryResult,
691 {
692 Selector {
693 query: self.query,
694 selector: PhantomData,
695 }
696 }
697
698 /// Perform a conversion into a [SelectTwoRequiredModel] with [PartialModel](PartialModelTrait)
699 pub fn into_partial_model<M, N>(self) -> Selector<SelectTwoRequiredModel<M, N>>
700 where
701 M: PartialModelTrait,
702 N: PartialModelTrait,
703 {
704 let select = QuerySelect::select_only(self);
705 let select = M::select_cols(select);
706 let select = N::select_cols(select);
707 select.into_model::<M, N>()
708 }
709
710 /// Convert the Models into JsonValue
711 #[cfg(feature = "with-json")]
712 pub fn into_json(self) -> Selector<SelectTwoRequiredModel<JsonValue, JsonValue>> {
713 Selector {
714 query: self.query,
715 selector: PhantomData,
716 }
717 }
718
719 /// Get one Model from the Select query
720 pub async fn one<C>(self, db: &C) -> Result<Option<(E::Model, F::Model)>, DbErr>
721 where
722 C: ConnectionTrait,
723 {
724 self.into_model().one(db).await
725 }
726
727 /// Get all Models from the Select query
728 pub async fn all<C>(self, db: &C) -> Result<Vec<(E::Model, F::Model)>, DbErr>
729 where
730 C: ConnectionTrait,
731 {
732 self.into_model().all(db).await
733 }
734
735 /// Stream the results of a Select operation on a Model
736 pub async fn stream<'a: 'b, 'b, C>(
737 self,
738 db: &'a C,
739 ) -> Result<impl Stream<Item = Result<(E::Model, F::Model), DbErr>> + 'b, DbErr>
740 where
741 C: ConnectionTrait + StreamTrait + Send,
742 {
743 self.into_model().stream(db).await
744 }
745
746 /// Stream the result of the operation with PartialModel
747 pub async fn stream_partial_model<'a: 'b, 'b, C, M, N>(
748 self,
749 db: &'a C,
750 ) -> Result<impl Stream<Item = Result<(M, N), DbErr>> + 'b + Send, DbErr>
751 where
752 C: ConnectionTrait + StreamTrait + Send,
753 M: PartialModelTrait + Send + 'b,
754 N: PartialModelTrait + Send + 'b,
755 {
756 self.into_partial_model().stream(db).await
757 }
758}
759
760impl<S> Selector<S>
761where
762 S: SelectorTrait,
763{
764 /// Get the SQL statement
765 pub fn into_statement(self, builder: DbBackend) -> Statement {
766 builder.build(&self.query)
767 }
768
769 /// Get an item from the Select query
770 pub async fn one<C>(mut self, db: &C) -> Result<Option<S::Item>, DbErr>
771 where
772 C: ConnectionTrait,
773 {
774 self.query.limit(1);
775 let row = db.query_one(&self.query).await?;
776 match row {
777 Some(row) => Ok(Some(S::from_raw_query_result(row)?)),
778 None => Ok(None),
779 }
780 }
781
782 /// Get all items from the Select query
783 pub async fn all<C>(self, db: &C) -> Result<Vec<S::Item>, DbErr>
784 where
785 C: ConnectionTrait,
786 {
787 db.query_all(&self.query)
788 .await?
789 .into_iter()
790 .map(|row| S::from_raw_query_result(row))
791 .try_collect()
792 }
793
794 /// Stream the results of the Select operation
795 pub async fn stream<'a: 'b, 'b, C>(self, db: &'a C) -> Result<PinBoxStream<'b, S::Item>, DbErr>
796 where
797 C: ConnectionTrait + StreamTrait + Send,
798 S: 'b,
799 S::Item: Send,
800 {
801 let stream = db.stream(&self.query).await?;
802
803 #[cfg(not(feature = "sync"))]
804 {
805 Ok(Box::pin(stream.and_then(|row| {
806 futures_util::future::ready(S::from_raw_query_result(row))
807 })))
808 }
809 #[cfg(feature = "sync")]
810 {
811 Ok(Box::new(
812 stream.map(|item| item.and_then(S::from_raw_query_result)),
813 ))
814 }
815 }
816}
817
818impl<S> SelectorRaw<S>
819where
820 S: SelectorTrait,
821{
822 /// Select a custom Model from a raw SQL [Statement].
823 pub fn from_statement<M>(stmt: Statement) -> SelectorRaw<SelectModel<M>>
824 where
825 M: FromQueryResult,
826 {
827 SelectorRaw {
828 stmt,
829 selector: PhantomData,
830 }
831 }
832
833 /// ```
834 /// # use sea_orm::{error::*, tests_cfg::*, *};
835 /// #
836 /// # #[smol_potat::main]
837 /// # #[cfg(feature = "mock")]
838 /// # pub async fn main() -> Result<(), DbErr> {
839 /// #
840 /// # let db = MockDatabase::new(DbBackend::Postgres)
841 /// # .append_query_results([[
842 /// # maplit::btreemap! {
843 /// # "name" => Into::<Value>::into("Chocolate Forest"),
844 /// # "num_of_cakes" => Into::<Value>::into(1),
845 /// # },
846 /// # maplit::btreemap! {
847 /// # "name" => Into::<Value>::into("New York Cheese"),
848 /// # "num_of_cakes" => Into::<Value>::into(1),
849 /// # },
850 /// # ]])
851 /// # .into_connection();
852 /// #
853 /// use sea_orm::{FromQueryResult, entity::*, query::*, tests_cfg::cake};
854 ///
855 /// #[derive(Debug, PartialEq, FromQueryResult)]
856 /// struct SelectResult {
857 /// name: String,
858 /// num_of_cakes: i32,
859 /// }
860 ///
861 /// let res: Vec<SelectResult> = cake::Entity::find()
862 /// .from_raw_sql(Statement::from_sql_and_values(
863 /// DbBackend::Postgres,
864 /// r#"SELECT "cake"."name", count("cake"."id") AS "num_of_cakes" FROM "cake""#,
865 /// [],
866 /// ))
867 /// .into_model::<SelectResult>()
868 /// .all(&db)
869 /// .await?;
870 ///
871 /// assert_eq!(
872 /// res,
873 /// [
874 /// SelectResult {
875 /// name: "Chocolate Forest".to_owned(),
876 /// num_of_cakes: 1,
877 /// },
878 /// SelectResult {
879 /// name: "New York Cheese".to_owned(),
880 /// num_of_cakes: 1,
881 /// },
882 /// ]
883 /// );
884 ///
885 /// assert_eq!(
886 /// db.into_transaction_log(),
887 /// [Transaction::from_sql_and_values(
888 /// DbBackend::Postgres,
889 /// r#"SELECT "cake"."name", count("cake"."id") AS "num_of_cakes" FROM "cake""#,
890 /// []
891 /// ),]
892 /// );
893 /// #
894 /// # Ok(())
895 /// # }
896 /// ```
897 pub fn into_model<M>(self) -> SelectorRaw<SelectModel<M>>
898 where
899 M: FromQueryResult,
900 {
901 SelectorRaw {
902 stmt: self.stmt,
903 selector: PhantomData,
904 }
905 }
906
907 /// ```
908 /// # use sea_orm::{error::*, tests_cfg::*, *};
909 /// #
910 /// # #[smol_potat::main]
911 /// # #[cfg(feature = "mock")]
912 /// # pub async fn main() -> Result<(), DbErr> {
913 /// #
914 /// # let db = MockDatabase::new(DbBackend::Postgres)
915 /// # .append_query_results([[
916 /// # maplit::btreemap! {
917 /// # "name" => Into::<Value>::into("Chocolate Forest"),
918 /// # "num_of_cakes" => Into::<Value>::into(1),
919 /// # },
920 /// # maplit::btreemap! {
921 /// # "name" => Into::<Value>::into("New York Cheese"),
922 /// # "num_of_cakes" => Into::<Value>::into(1),
923 /// # },
924 /// # ]])
925 /// # .into_connection();
926 /// #
927 /// use sea_orm::{entity::*, query::*, tests_cfg::cake};
928 ///
929 /// let res: Vec<serde_json::Value> = cake::Entity::find().from_raw_sql(
930 /// Statement::from_sql_and_values(
931 /// DbBackend::Postgres, r#"SELECT "cake"."id", "cake"."name" FROM "cake""#, []
932 /// )
933 /// )
934 /// .into_json()
935 /// .all(&db)
936 /// .await?;
937 ///
938 /// assert_eq!(
939 /// res,
940 /// [
941 /// serde_json::json!({
942 /// "name": "Chocolate Forest",
943 /// "num_of_cakes": 1,
944 /// }),
945 /// serde_json::json!({
946 /// "name": "New York Cheese",
947 /// "num_of_cakes": 1,
948 /// }),
949 /// ]
950 /// );
951 ///
952 /// assert_eq!(
953 /// db.into_transaction_log(),
954 /// [
955 /// Transaction::from_sql_and_values(
956 /// DbBackend::Postgres, r#"SELECT "cake"."id", "cake"."name" FROM "cake""#, []
957 /// ),
958 /// ]);
959 /// #
960 /// # Ok(())
961 /// # }
962 /// ```
963 #[cfg(feature = "with-json")]
964 pub fn into_json(self) -> SelectorRaw<SelectModel<JsonValue>> {
965 SelectorRaw {
966 stmt: self.stmt,
967 selector: PhantomData,
968 }
969 }
970
971 /// Get the SQL statement
972 pub fn into_statement(self) -> Statement {
973 self.stmt
974 }
975
976 /// Get an item from the Select query
977 /// ```
978 /// # use sea_orm::{error::*, tests_cfg::*, *};
979 /// #
980 /// # #[smol_potat::main]
981 /// # #[cfg(feature = "mock")]
982 /// # pub async fn main() -> Result<(), DbErr> {
983 /// #
984 /// # let db = MockDatabase::new(DbBackend::Postgres)
985 /// # .append_query_results([
986 /// # [cake::Model {
987 /// # id: 1,
988 /// # name: "Cake".to_owned(),
989 /// # }],
990 /// # ])
991 /// # .into_connection();
992 /// #
993 /// use sea_orm::{entity::*, query::*, raw_sql, tests_cfg::cake};
994 ///
995 /// let id = 1;
996 ///
997 /// let _: Option<cake::Model> = cake::Entity::find()
998 /// .from_raw_sql(raw_sql!(
999 /// Postgres,
1000 /// r#"SELECT "cake"."id", "cake"."name" FROM "cake" WHERE "id" = {id}"#
1001 /// ))
1002 /// .one(&db)
1003 /// .await?;
1004 ///
1005 /// assert_eq!(
1006 /// db.into_transaction_log(),
1007 /// [Transaction::from_sql_and_values(
1008 /// DbBackend::Postgres,
1009 /// r#"SELECT "cake"."id", "cake"."name" FROM "cake" WHERE "id" = $1"#,
1010 /// [1.into()]
1011 /// ),]
1012 /// );
1013 /// #
1014 /// # Ok(())
1015 /// # }
1016 /// ```
1017 pub async fn one<C>(self, db: &C) -> Result<Option<S::Item>, DbErr>
1018 where
1019 C: ConnectionTrait,
1020 {
1021 let row = db.query_one_raw(self.stmt).await?;
1022 match row {
1023 Some(row) => Ok(Some(S::from_raw_query_result(row)?)),
1024 None => Ok(None),
1025 }
1026 }
1027
1028 /// Get all items from the Select query
1029 /// ```
1030 /// # use sea_orm::{error::*, tests_cfg::*, *};
1031 /// #
1032 /// # #[smol_potat::main]
1033 /// # #[cfg(feature = "mock")]
1034 /// # pub async fn main() -> Result<(), DbErr> {
1035 /// #
1036 /// # let db = MockDatabase::new(DbBackend::Postgres)
1037 /// # .append_query_results([
1038 /// # [cake::Model {
1039 /// # id: 1,
1040 /// # name: "Cake".to_owned(),
1041 /// # }],
1042 /// # ])
1043 /// # .into_connection();
1044 /// #
1045 /// use sea_orm::{entity::*, query::*, raw_sql, tests_cfg::cake};
1046 ///
1047 /// let _: Vec<cake::Model> = cake::Entity::find()
1048 /// .from_raw_sql(raw_sql!(
1049 /// Postgres,
1050 /// r#"SELECT "cake"."id", "cake"."name" FROM "cake""#
1051 /// ))
1052 /// .all(&db)
1053 /// .await?;
1054 ///
1055 /// assert_eq!(
1056 /// db.into_transaction_log(),
1057 /// [Transaction::from_sql_and_values(
1058 /// DbBackend::Postgres,
1059 /// r#"SELECT "cake"."id", "cake"."name" FROM "cake""#,
1060 /// []
1061 /// ),]
1062 /// );
1063 /// #
1064 /// # Ok(())
1065 /// # }
1066 /// ```
1067 pub async fn all<C>(self, db: &C) -> Result<Vec<S::Item>, DbErr>
1068 where
1069 C: ConnectionTrait,
1070 {
1071 db.query_all_raw(self.stmt)
1072 .await?
1073 .into_iter()
1074 .map(|row| S::from_raw_query_result(row))
1075 .try_collect()
1076 }
1077
1078 /// Stream the results of the Select operation
1079 pub async fn stream<'a: 'b, 'b, C>(self, db: &'a C) -> Result<PinBoxStream<'b, S::Item>, DbErr>
1080 where
1081 C: ConnectionTrait + StreamTrait + Send,
1082 S: 'b,
1083 S::Item: Send,
1084 {
1085 let stream = db.stream_raw(self.stmt).await?;
1086
1087 #[cfg(not(feature = "sync"))]
1088 {
1089 Ok(Box::pin(stream.and_then(|row| {
1090 futures_util::future::ready(S::from_raw_query_result(row))
1091 })))
1092 }
1093 #[cfg(feature = "sync")]
1094 {
1095 Ok(Box::new(
1096 stream.map(|item| item.and_then(S::from_raw_query_result)),
1097 ))
1098 }
1099 }
1100}