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