1use crate::{
2 ColumnTrait, EntityTrait, IdenStatic, Iterable, Linked, QueryFilter, QuerySelect, QueryTrait,
3 Related, Select, SelectA, SelectB, SelectThree, SelectTwo, SelectTwoMany, TopologyChain,
4 TopologyStar, find_linked_recursive, join_tbl_on_condition,
5};
6pub use sea_query::JoinType;
7use sea_query::{Condition, Expr, IntoCondition, IntoIden, SelectExpr};
8
9impl<E> Select<E>
10where
11 E: EntityTrait,
12{
13 pub fn left_join<R>(self, _: R) -> Self
15 where
16 R: EntityTrait,
17 E: Related<R>,
18 {
19 self.join_join(JoinType::LeftJoin, E::to(), E::via())
20 }
21
22 pub fn right_join<R>(self, _: R) -> Self
24 where
25 R: EntityTrait,
26 E: Related<R>,
27 {
28 self.join_join(JoinType::RightJoin, E::to(), E::via())
29 }
30
31 pub fn inner_join<R>(self, _: R) -> Self
33 where
34 R: EntityTrait,
35 E: Related<R>,
36 {
37 self.join_join(JoinType::InnerJoin, E::to(), E::via())
38 }
39
40 pub fn reverse_join<R>(self, _: R) -> Self
42 where
43 R: EntityTrait + Related<E>,
44 {
45 self.join_rev(JoinType::InnerJoin, R::to())
46 }
47
48 pub fn find_also<R>(self, _: E, r: R) -> SelectTwo<E, R>
50 where
51 R: EntityTrait,
52 E: Related<R>,
53 {
54 self.left_join(r).select_also(r)
55 }
56
57 pub fn find_also_related<R>(self, r: R) -> SelectTwo<E, R>
59 where
60 R: EntityTrait,
61 E: Related<R>,
62 {
63 self.left_join(r).select_also(r)
64 }
65
66 pub fn find_with_related<R>(self, r: R) -> SelectTwoMany<E, R>
68 where
69 R: EntityTrait,
70 E: Related<R>,
71 {
72 self.left_join(r).select_with(r)
73 }
74
75 pub fn find_also_linked<L, T>(self, l: L) -> SelectTwo<E, T>
77 where
78 L: Linked<FromEntity = E, ToEntity = T>,
79 T: EntityTrait,
80 {
81 SelectTwo::new_without_prepare(self.left_join_linked(l).into_query())
82 }
83
84 pub fn find_with_linked<L, T>(self, l: L) -> SelectTwoMany<E, T>
86 where
87 L: Linked<FromEntity = E, ToEntity = T>,
88 T: EntityTrait,
89 {
90 SelectTwoMany::new_without_prepare(self.left_join_linked(l).into_query())
91 }
92
93 pub fn left_join_linked<L, T>(mut self, l: L) -> Self
95 where
96 L: Linked<FromEntity = E, ToEntity = T>,
97 T: EntityTrait,
98 {
99 for (i, mut rel) in l.link().into_iter().enumerate() {
100 let r = self.linked_index;
101 self.linked_index += 1;
102 let to_tbl = format!("r{r}").into_iden();
103 let from_tbl = if i > 0 {
104 format!("r{}", i - 1).into_iden()
105 } else {
106 rel.from_tbl.sea_orm_table().clone()
107 };
108 let table_ref = rel.to_tbl;
109
110 let mut condition = Condition::all().add(join_tbl_on_condition(
111 from_tbl.clone(),
112 to_tbl.clone(),
113 rel.from_col,
114 rel.to_col,
115 ));
116 if let Some(f) = rel.on_condition.take() {
117 condition = condition.add(f(from_tbl.clone(), to_tbl.clone()));
118 }
119
120 self.query
121 .join_as(JoinType::LeftJoin, table_ref, to_tbl, condition);
122 }
123 self = self.apply_alias(SelectA.as_str());
124 for col in <T::Column as Iterable>::iter() {
125 let alias = format!("{}{}", SelectB.as_str(), col.as_str());
126 let expr = Expr::col((
127 format!("r{}", self.linked_index - 1).into_iden(),
128 col.into_iden(),
129 ));
130 self.query.expr(SelectExpr {
131 expr: col.select_as(expr),
132 alias: Some(alias.into_iden()),
133 window: None,
134 });
135 }
136 self
137 }
138
139 pub fn has_related<R, C>(mut self, _: R, condition: C) -> Self
172 where
173 R: EntityTrait,
174 E: Related<R>,
175 C: IntoCondition,
176 {
177 let mut to = None;
178 let mut condition = condition.into_condition();
179 condition = condition.add(if let Some(via) = E::via() {
180 to = Some(E::to());
181 via
182 } else {
183 E::to()
184 });
185 let mut subquery = R::find()
186 .select_only()
187 .expr(Expr::cust("1"))
188 .filter(condition)
189 .into_query();
190 if let Some(to) = to {
191 subquery.inner_join(to.from_tbl.clone(), to);
193 }
194 self.query.cond_where(Expr::exists(subquery));
195 self
196 }
197
198 #[doc(hidden)]
199 pub fn find_with_linked_recursive<L>(self, l: L) -> Select<E>
201 where
202 L: Linked<FromEntity = E, ToEntity = E>,
203 {
204 find_linked_recursive(self, l.link())
205 }
206}
207
208impl<E, F> SelectTwo<E, F>
209where
210 E: EntityTrait,
211 F: EntityTrait,
212{
213 #[doc(hidden)]
215 pub fn select_also_fake<R>(self, _: R) -> SelectThree<E, F, R, TopologyStar>
216 where
217 R: EntityTrait,
218 {
219 SelectThree::new_without_prepare(self.into_query())
221 }
222
223 pub fn find_also<G, R>(self, _: G, _: R) -> SelectThree<E, F, R, TopologyStar>
225 where
226 R: EntityTrait,
227 G: EntityTrait + Related<R>,
228 {
229 SelectThree::new(
230 self.join_join(JoinType::LeftJoin, G::to(), G::via())
231 .into_query(),
232 )
233 }
234
235 pub fn find_also_related<R>(self, _: R) -> SelectThree<E, F, R, TopologyStar>
237 where
238 R: EntityTrait,
239 E: Related<R>,
240 {
241 SelectThree::new(
242 self.join_join(JoinType::LeftJoin, E::to(), E::via())
243 .into_query(),
244 )
245 }
246
247 pub fn and_also_related<R>(self, _: R) -> SelectThree<E, F, R, TopologyChain>
249 where
250 R: EntityTrait,
251 F: Related<R>,
252 {
253 SelectThree::new(
254 self.join_join(JoinType::LeftJoin, F::to(), F::via())
255 .into_query(),
256 )
257 }
258}
259
260#[cfg(test)]
261mod tests {
262 use crate::tests_cfg::{
263 cake, cake_compact, cake_filling, cake_filling_price, entity_linked, filling, fruit,
264 };
265 use crate::{
266 ColumnTrait, DbBackend, EntityTrait, ModelTrait, QueryFilter, QuerySelect, QueryTrait,
267 RelationTrait,
268 };
269 use pretty_assertions::assert_eq;
270 use sea_query::{ConditionType, Expr, ExprTrait, IntoCondition, JoinType};
271
272 #[test]
273 fn join_1() {
274 assert_eq!(
275 cake::Entity::find()
276 .left_join(fruit::Entity)
277 .build(DbBackend::MySql)
278 .to_string(),
279 [
280 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
281 "LEFT JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id`",
282 ]
283 .join(" ")
284 );
285 }
286
287 #[test]
288 fn join_2() {
289 assert_eq!(
290 cake::Entity::find()
291 .inner_join(fruit::Entity)
292 .filter(fruit::Column::Name.contains("cherry"))
293 .build(DbBackend::MySql)
294 .to_string(),
295 [
296 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
297 "INNER JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id`",
298 "WHERE `fruit`.`name` LIKE \'%cherry%\'"
299 ]
300 .join(" ")
301 );
302 }
303
304 #[test]
305 fn join_3() {
306 assert_eq!(
307 fruit::Entity::find()
308 .reverse_join(cake::Entity)
309 .build(DbBackend::MySql)
310 .to_string(),
311 [
312 "SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit`",
313 "INNER JOIN `cake` ON `cake`.`id` = `fruit`.`cake_id`",
314 ]
315 .join(" ")
316 );
317 }
318
319 #[test]
320 fn join_4() {
321 use crate::{Related, Select};
322
323 let find_fruit: Select<fruit::Entity> = cake::Entity::find_related();
324 assert_eq!(
325 find_fruit
326 .filter(cake::Column::Id.eq(11))
327 .build(DbBackend::MySql)
328 .to_string(),
329 [
330 "SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit`",
331 "INNER JOIN `cake` ON `cake`.`id` = `fruit`.`cake_id`",
332 "WHERE `cake`.`id` = 11",
333 ]
334 .join(" ")
335 );
336
337 let find_fruit: Select<fruit::Entity> = cake::Entity::find_related_rev();
338 assert_eq!(
339 find_fruit
340 .filter(cake::Column::Id.eq(11))
341 .build(DbBackend::MySql)
342 .to_string(),
343 [
344 "SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit`",
345 "INNER JOIN `cake` ON `fruit`.`cake_id` = `cake`.`id`",
346 "WHERE `cake`.`id` = 11",
347 ]
348 .join(" ")
349 );
350 }
351
352 #[test]
353 fn join_5() {
354 let cake_model = cake::Model {
355 id: 12,
356 name: "".to_owned(),
357 };
358
359 assert_eq!(
360 cake_model
361 .find_related(fruit::Entity)
362 .build(DbBackend::MySql)
363 .to_string(),
364 [
365 "SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit`",
366 "INNER JOIN `cake` ON `cake`.`id` = `fruit`.`cake_id`",
367 "WHERE `cake`.`id` = 12",
368 ]
369 .join(" ")
370 );
371 }
372
373 #[test]
374 fn join_6() {
375 assert_eq!(
376 cake::Entity::find()
377 .left_join(filling::Entity)
378 .build(DbBackend::MySql)
379 .to_string(),
380 [
381 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
382 "LEFT JOIN `cake_filling` ON `cake`.`id` = `cake_filling`.`cake_id`",
383 "LEFT JOIN `filling` ON `cake_filling`.`filling_id` = `filling`.`id`",
384 ]
385 .join(" ")
386 );
387 }
388
389 #[test]
390 fn join_7() {
391 use crate::{Related, Select};
392
393 let find_filling: Select<filling::Entity> = cake::Entity::find_related();
394 assert_eq!(
395 find_filling.build(DbBackend::MySql).to_string(),
396 [
397 "SELECT `filling`.`id`, `filling`.`name`, `filling`.`vendor_id` FROM `filling`",
398 "INNER JOIN `cake_filling` ON `cake_filling`.`filling_id` = `filling`.`id`",
399 "INNER JOIN `cake` ON `cake`.`id` = `cake_filling`.`cake_id`",
400 ]
401 .join(" ")
402 );
403
404 let find_filling: Select<filling::Entity> = cake::Entity::find_related_rev();
405 assert_eq!(
406 find_filling.build(DbBackend::MySql).to_string(),
407 [
408 "SELECT `filling`.`id`, `filling`.`name`, `filling`.`vendor_id` FROM `filling`",
409 "INNER JOIN `cake_filling` ON `filling`.`id` = `cake_filling`.`filling_id`",
410 "INNER JOIN `cake` ON `cake_filling`.`cake_id` = `cake`.`id`",
411 ]
412 .join(" ")
413 );
414 }
415
416 #[test]
417 fn join_8() {
418 use crate::{Related, Select};
419
420 let find_cake_filling_price: Select<cake_filling_price::Entity> =
421 cake_filling::Entity::find_related();
422 assert_eq!(
423 find_cake_filling_price.build(DbBackend::Postgres).to_string(),
424 [
425 r#"SELECT "cake_filling_price"."cake_id", "cake_filling_price"."filling_id", "cake_filling_price"."price""#,
426 r#"FROM "public"."cake_filling_price""#,
427 r#"INNER JOIN "cake_filling" ON"#,
428 r#""cake_filling"."cake_id" = "cake_filling_price"."cake_id" AND"#,
429 r#""cake_filling"."filling_id" = "cake_filling_price"."filling_id""#,
430 ]
431 .join(" ")
432 );
433 }
434
435 #[test]
436 fn join_9() {
437 use crate::{Related, Select};
438
439 let find_cake_filling: Select<cake_filling::Entity> =
440 cake_filling_price::Entity::find_related();
441 assert_eq!(
442 find_cake_filling.build(DbBackend::Postgres).to_string(),
443 [
444 r#"SELECT "cake_filling"."cake_id", "cake_filling"."filling_id""#,
445 r#"FROM "cake_filling""#,
446 r#"INNER JOIN "public"."cake_filling_price" ON"#,
447 r#""cake_filling_price"."cake_id" = "cake_filling"."cake_id" AND"#,
448 r#""cake_filling_price"."filling_id" = "cake_filling"."filling_id""#,
449 ]
450 .join(" ")
451 );
452 }
453
454 #[test]
455 fn join_10() {
456 let cake_model = cake::Model {
457 id: 12,
458 name: "".to_owned(),
459 };
460
461 assert_eq!(
462 cake_model
463 .find_linked(entity_linked::CakeToFilling)
464 .build(DbBackend::MySql)
465 .to_string(),
466 [
467 r#"SELECT `filling`.`id`, `filling`.`name`, `filling`.`vendor_id`"#,
468 r#"FROM `filling`"#,
469 r#"INNER JOIN `cake_filling` AS `r0` ON `r0`.`filling_id` = `filling`.`id`"#,
470 r#"INNER JOIN `cake` AS `r1` ON `r1`.`id` = `r0`.`cake_id`"#,
471 r#"WHERE `r1`.`id` = 12"#,
472 ]
473 .join(" ")
474 );
475 }
476
477 #[test]
478 fn join_11() {
479 let cake_model = cake::Model {
480 id: 18,
481 name: "".to_owned(),
482 };
483
484 assert_eq!(
485 cake_model
486 .find_linked(entity_linked::CakeToFillingVendor)
487 .build(DbBackend::MySql)
488 .to_string(),
489 [
490 r#"SELECT `vendor`.`id`, `vendor`.`name`"#,
491 r#"FROM `vendor`"#,
492 r#"INNER JOIN `filling` AS `r0` ON `r0`.`vendor_id` = `vendor`.`id`"#,
493 r#"INNER JOIN `cake_filling` AS `r1` ON `r1`.`filling_id` = `r0`.`id`"#,
494 r#"INNER JOIN `cake` AS `r2` ON `r2`.`id` = `r1`.`cake_id`"#,
495 r#"WHERE `r2`.`id` = 18"#,
496 ]
497 .join(" ")
498 );
499 }
500
501 #[test]
502 fn join_12() {
503 assert_eq!(
504 cake::Entity::find()
505 .find_also_linked(entity_linked::CakeToFilling)
506 .build(DbBackend::MySql)
507 .to_string(),
508 [
509 r#"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,"#,
510 r#"`r1`.`id` AS `B_id`, `r1`.`name` AS `B_name`, `r1`.`vendor_id` AS `B_vendor_id`"#,
511 r#"FROM `cake`"#,
512 r#"LEFT JOIN `cake_filling` AS `r0` ON `cake`.`id` = `r0`.`cake_id`"#,
513 r#"LEFT JOIN `filling` AS `r1` ON `r0`.`filling_id` = `r1`.`id`"#,
514 ]
515 .join(" ")
516 );
517 }
518
519 #[test]
520 fn join_13() {
521 assert_eq!(
522 cake::Entity::find()
523 .find_also_linked(entity_linked::CakeToFillingVendor)
524 .build(DbBackend::MySql)
525 .to_string(),
526 [
527 r#"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,"#,
528 r#"`r2`.`id` AS `B_id`, `r2`.`name` AS `B_name`"#,
529 r#"FROM `cake`"#,
530 r#"LEFT JOIN `cake_filling` AS `r0` ON `cake`.`id` = `r0`.`cake_id`"#,
531 r#"LEFT JOIN `filling` AS `r1` ON `r0`.`filling_id` = `r1`.`id`"#,
532 r#"LEFT JOIN `vendor` AS `r2` ON `r1`.`vendor_id` = `r2`.`id`"#,
533 ]
534 .join(" ")
535 );
536 }
537
538 #[test]
539 fn join_14() {
540 assert_eq!(
541 cake_compact::Entity::find()
542 .join(JoinType::LeftJoin, cake_compact::Relation::TropicalFruit.def())
543 .build(DbBackend::MySql)
544 .to_string(),
545 [
546 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
547 "LEFT JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id` AND `fruit`.`name` LIKE '%tropical%'",
548 ]
549 .join(" ")
550 );
551 }
552
553 #[test]
554 fn join_15() {
555 let cake_model = cake::Model {
556 id: 18,
557 name: "".to_owned(),
558 };
559
560 assert_eq!(
561 cake_model
562 .find_linked(entity_linked::CheeseCakeToFillingVendor)
563 .build(DbBackend::MySql)
564 .to_string(),
565 [
566 r#"SELECT `vendor`.`id`, `vendor`.`name`"#,
567 r#"FROM `vendor`"#,
568 r#"INNER JOIN `filling` AS `r0` ON `r0`.`vendor_id` = `vendor`.`id`"#,
569 r#"INNER JOIN `cake_filling` AS `r1` ON `r1`.`filling_id` = `r0`.`id`"#,
570 r#"INNER JOIN `cake` AS `r2` ON `r2`.`id` = `r1`.`cake_id` AND `r2`.`name` LIKE '%cheese%'"#,
571 r#"WHERE `r2`.`id` = 18"#,
572 ]
573 .join(" ")
574 );
575 }
576
577 #[test]
578 fn join_16() {
579 }
581
582 #[test]
583 fn join_17() {
584 assert_eq!(
585 cake::Entity::find()
586 .find_also_linked(entity_linked::CheeseCakeToFillingVendor)
587 .build(DbBackend::MySql)
588 .to_string(),
589 [
590 r#"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,"#,
591 r#"`r2`.`id` AS `B_id`, `r2`.`name` AS `B_name`"#,
592 r#"FROM `cake`"#,
593 r#"LEFT JOIN `cake_filling` AS `r0` ON `cake`.`id` = `r0`.`cake_id` AND `cake`.`name` LIKE '%cheese%'"#,
594 r#"LEFT JOIN `filling` AS `r1` ON `r0`.`filling_id` = `r1`.`id`"#,
595 r#"LEFT JOIN `vendor` AS `r2` ON `r1`.`vendor_id` = `r2`.`id`"#,
596 ]
597 .join(" ")
598 );
599 }
600
601 #[test]
602 fn join_18() {
603 }
605
606 #[test]
607 fn join_19() {
608 assert_eq!(
609 cake_compact::Entity::find()
610 .join(JoinType::LeftJoin, cake_compact::Relation::TropicalFruit.def())
611 .join(
612 JoinType::LeftJoin,
613 cake_filling::Relation::Cake
614 .def()
615 .rev()
616 .on_condition(|_left, right| {
617 Expr::col((right, cake_filling::Column::CakeId))
618 .gt(10)
619 .into_condition()
620 })
621 )
622 .join(
623 JoinType::LeftJoin,
624 cake_filling::Relation::Filling
625 .def()
626 .on_condition(|_left, right| {
627 Expr::col((right, filling::Column::Name))
628 .like("%lemon%")
629 .into_condition()
630 })
631 )
632 .join(JoinType::LeftJoin, filling::Relation::Vendor.def())
633 .build(DbBackend::MySql)
634 .to_string(),
635 [
636 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
637 "LEFT JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id` AND `fruit`.`name` LIKE '%tropical%'",
638 "LEFT JOIN `cake_filling` ON `cake`.`id` = `cake_filling`.`cake_id` AND `cake_filling`.`cake_id` > 10",
639 "LEFT JOIN `filling` ON `cake_filling`.`filling_id` = `filling`.`id` AND `filling`.`name` LIKE '%lemon%'",
640 "LEFT JOIN `vendor` ON `filling`.`vendor_id` = `vendor`.`id`",
641 ]
642 .join(" ")
643 );
644 }
645
646 #[test]
647 fn join_20() {
648 assert_eq!(
649 cake::Entity::find()
650 .column_as(
651 Expr::col(("fruit_alias", fruit::Column::Name)),
652 "fruit_name"
653 )
654 .join_as(
655 JoinType::LeftJoin,
656 cake::Relation::Fruit
657 .def()
658 .on_condition(|_left, right| {
659 Expr::col((right, fruit::Column::Name))
660 .like("%tropical%")
661 .into_condition()
662 }),
663 "fruit_alias"
664 )
665 .build(DbBackend::MySql)
666 .to_string(),
667 [
668 "SELECT `cake`.`id`, `cake`.`name`, `fruit_alias`.`name` AS `fruit_name` FROM `cake`",
669 "LEFT JOIN `fruit` AS `fruit_alias` ON `cake`.`id` = `fruit_alias`.`cake_id` AND `fruit_alias`.`name` LIKE '%tropical%'",
670 ]
671 .join(" ")
672 );
673 }
674
675 #[test]
676 fn join_21() {
677 assert_eq!(
678 cake_compact::Entity::find()
679 .column_as(
680 Expr::col(("cake_filling_alias", cake_filling::Column::CakeId)),
681 "cake_filling_cake_id"
682 )
683 .join(JoinType::LeftJoin, cake_compact::Relation::TropicalFruit.def())
684 .join_as_rev(
685 JoinType::LeftJoin,
686 cake_filling::Relation::Cake
687 .def()
688 .on_condition(|left, _right| {
689 Expr::col((left, cake_filling::Column::CakeId))
690 .gt(10)
691 .into_condition()
692 }),
693 "cake_filling_alias"
694 )
695 .build(DbBackend::MySql)
696 .to_string(),
697 [
698 "SELECT `cake`.`id`, `cake`.`name`, `cake_filling_alias`.`cake_id` AS `cake_filling_cake_id` FROM `cake`",
699 "LEFT JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id` AND `fruit`.`name` LIKE '%tropical%'",
700 "LEFT JOIN `cake_filling` AS `cake_filling_alias` ON `cake_filling_alias`.`cake_id` = `cake`.`id` AND `cake_filling_alias`.`cake_id` > 10",
701 ]
702 .join(" ")
703 );
704 }
705
706 #[test]
707 fn join_22() {
708 assert_eq!(
709 cake_compact::Entity::find()
710 .column_as(
711 Expr::col(("cake_filling_alias", cake_filling::Column::CakeId)),
712 "cake_filling_cake_id"
713 )
714 .join(JoinType::LeftJoin, cake_compact::Relation::OrTropicalFruit.def())
715 .join_as_rev(
716 JoinType::LeftJoin,
717 cake_filling::Relation::Cake
718 .def()
719 .condition_type(ConditionType::Any)
720 .on_condition(|left, _right| {
721 Expr::col((left, cake_filling::Column::CakeId))
722 .gt(10)
723 .into_condition()
724 }),
725 "cake_filling_alias"
726 )
727 .build(DbBackend::MySql)
728 .to_string(),
729 [
730 "SELECT `cake`.`id`, `cake`.`name`, `cake_filling_alias`.`cake_id` AS `cake_filling_cake_id` FROM `cake`",
731 "LEFT JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id` OR `fruit`.`name` LIKE '%tropical%'",
732 "LEFT JOIN `cake_filling` AS `cake_filling_alias` ON `cake_filling_alias`.`cake_id` = `cake`.`id` OR `cake_filling_alias`.`cake_id` > 10",
733 ]
734 .join(" ")
735 );
736 }
737
738 #[test]
739 fn join_23() {
740 let cake_model = cake::Model {
741 id: 18,
742 name: "".to_owned(),
743 };
744
745 assert_eq!(
746 cake_model
747 .find_linked(entity_linked::CakeToCakeViaFilling)
748 .build(DbBackend::MySql)
749 .to_string(),
750 [
751 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
752 "INNER JOIN `cake_filling` AS `r0` ON `r0`.`cake_id` = `cake`.`id`",
753 "INNER JOIN `filling` AS `r1` ON `r1`.`id` = `r0`.`filling_id`",
754 "INNER JOIN `cake_filling` AS `r2` ON `r2`.`filling_id` = `r1`.`id`",
755 "INNER JOIN `cake` AS `r3` ON `r3`.`id` = `r2`.`cake_id`",
756 "WHERE `r3`.`id` = 18",
757 ]
758 .join(" ")
759 );
760 }
761
762 #[test]
763 fn join_24() {
764 let cake_model = cake::Model {
765 id: 12,
766 name: "".to_owned(),
767 };
768
769 assert_eq!(
770 cake_model
771 .find_linked_recursive(entity_linked::CakeToCakeViaFilling)
772 .build(DbBackend::MySql)
773 .to_string(),
774 [
775 "WITH `cte` AS (SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
776 "INNER JOIN `cake_filling` AS `r0` ON `r0`.`cake_id` = `cake`.`id`",
777 "INNER JOIN `filling` AS `r1` ON `r1`.`id` = `r0`.`filling_id`",
778 "INNER JOIN `cake_filling` AS `r2` ON `r2`.`filling_id` = `r1`.`id`",
779 "INNER JOIN `cake` AS `r3` ON `r3`.`id` = `r2`.`cake_id`",
780 "WHERE `r3`.`id` = 12",
781 "UNION ALL (SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
782 "INNER JOIN `cake_filling` AS `r0` ON `r0`.`cake_id` = `cake`.`id`",
783 "INNER JOIN `filling` AS `r1` ON `r1`.`id` = `r0`.`filling_id`",
784 "INNER JOIN `cake_filling` AS `r2` ON `r2`.`filling_id` = `r1`.`id`",
785 "INNER JOIN `cte` AS `r3` ON `r3`.`id` = `r2`.`cake_id`))",
786 "SELECT `cake`.`id`, `cake`.`name` FROM `cte` AS `cake`",
787 ]
788 .join(" ")
789 );
790 }
791
792 #[test]
793 fn join_25() {
794 assert_eq!(
795 cake::Entity::find()
796 .find_with_linked_recursive(entity_linked::CakeToCakeViaFilling)
797 .build(DbBackend::MySql)
798 .to_string(),
799 [
800 "WITH `cte` AS (SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
801 "UNION ALL (SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
802 "INNER JOIN `cake_filling` AS `r0` ON `r0`.`cake_id` = `cake`.`id`",
803 "INNER JOIN `filling` AS `r1` ON `r1`.`id` = `r0`.`filling_id`",
804 "INNER JOIN `cake_filling` AS `r2` ON `r2`.`filling_id` = `r1`.`id`",
805 "INNER JOIN `cte` AS `r3` ON `r3`.`id` = `r2`.`cake_id`))",
806 "SELECT `cake`.`id`, `cake`.`name` FROM `cte` AS `cake`",
807 ]
808 .join(" ")
809 );
810 }
811}