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