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