1use crate::{
2 ColumnTrait, EntityTrait, IdenStatic, Iterable, Linked, QueryFilter, QuerySelect, QueryTrait,
3 Related, Select, SelectA, SelectB, SelectThree, SelectTwo, SelectTwoMany, TopologyChain,
4 TopologyStar, 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
199impl<E, F> SelectTwo<E, F>
200where
201 E: EntityTrait,
202 F: EntityTrait,
203{
204 #[doc(hidden)]
206 pub fn select_also_fake<R>(self, _: R) -> SelectThree<E, F, R, TopologyStar>
207 where
208 R: EntityTrait,
209 {
210 SelectThree::new_without_prepare(self.into_query())
212 }
213
214 pub fn find_also<G, R>(self, _: G, _: R) -> SelectThree<E, F, R, TopologyStar>
216 where
217 R: EntityTrait,
218 G: EntityTrait + Related<R>,
219 {
220 SelectThree::new(
221 self.join_join(JoinType::LeftJoin, G::to(), G::via())
222 .into_query(),
223 )
224 }
225
226 pub fn find_also_related<R>(self, _: R) -> SelectThree<E, F, R, TopologyStar>
228 where
229 R: EntityTrait,
230 E: Related<R>,
231 {
232 SelectThree::new(
233 self.join_join(JoinType::LeftJoin, E::to(), E::via())
234 .into_query(),
235 )
236 }
237
238 pub fn and_also_related<R>(self, _: R) -> SelectThree<E, F, R, TopologyChain>
240 where
241 R: EntityTrait,
242 F: Related<R>,
243 {
244 SelectThree::new(
245 self.join_join(JoinType::LeftJoin, F::to(), F::via())
246 .into_query(),
247 )
248 }
249}
250
251#[cfg(test)]
252mod tests {
253 use crate::tests_cfg::{
254 cake, cake_compact, cake_filling, cake_filling_price, entity_linked, filling, fruit,
255 };
256 use crate::{
257 ColumnTrait, DbBackend, EntityTrait, ModelTrait, QueryFilter, QuerySelect, QueryTrait,
258 RelationTrait,
259 };
260 use pretty_assertions::assert_eq;
261 use sea_query::{ConditionType, Expr, ExprTrait, IntoCondition, JoinType};
262
263 #[test]
264 fn join_1() {
265 assert_eq!(
266 cake::Entity::find()
267 .left_join(fruit::Entity)
268 .build(DbBackend::MySql)
269 .to_string(),
270 [
271 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
272 "LEFT JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id`",
273 ]
274 .join(" ")
275 );
276 }
277
278 #[test]
279 fn join_2() {
280 assert_eq!(
281 cake::Entity::find()
282 .inner_join(fruit::Entity)
283 .filter(fruit::Column::Name.contains("cherry"))
284 .build(DbBackend::MySql)
285 .to_string(),
286 [
287 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
288 "INNER JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id`",
289 "WHERE `fruit`.`name` LIKE \'%cherry%\'"
290 ]
291 .join(" ")
292 );
293 }
294
295 #[test]
296 fn join_3() {
297 assert_eq!(
298 fruit::Entity::find()
299 .reverse_join(cake::Entity)
300 .build(DbBackend::MySql)
301 .to_string(),
302 [
303 "SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit`",
304 "INNER JOIN `cake` ON `cake`.`id` = `fruit`.`cake_id`",
305 ]
306 .join(" ")
307 );
308 }
309
310 #[test]
311 fn join_4() {
312 use crate::{Related, Select};
313
314 let find_fruit: Select<fruit::Entity> = cake::Entity::find_related();
315 assert_eq!(
316 find_fruit
317 .filter(cake::Column::Id.eq(11))
318 .build(DbBackend::MySql)
319 .to_string(),
320 [
321 "SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit`",
322 "INNER JOIN `cake` ON `cake`.`id` = `fruit`.`cake_id`",
323 "WHERE `cake`.`id` = 11",
324 ]
325 .join(" ")
326 );
327 }
328
329 #[test]
330 fn join_5() {
331 let cake_model = cake::Model {
332 id: 12,
333 name: "".to_owned(),
334 };
335
336 assert_eq!(
337 cake_model
338 .find_related(fruit::Entity)
339 .build(DbBackend::MySql)
340 .to_string(),
341 [
342 "SELECT `fruit`.`id`, `fruit`.`name`, `fruit`.`cake_id` FROM `fruit`",
343 "INNER JOIN `cake` ON `cake`.`id` = `fruit`.`cake_id`",
344 "WHERE `cake`.`id` = 12",
345 ]
346 .join(" ")
347 );
348 }
349
350 #[test]
351 fn join_6() {
352 assert_eq!(
353 cake::Entity::find()
354 .left_join(filling::Entity)
355 .build(DbBackend::MySql)
356 .to_string(),
357 [
358 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
359 "LEFT JOIN `cake_filling` ON `cake`.`id` = `cake_filling`.`cake_id`",
360 "LEFT JOIN `filling` ON `cake_filling`.`filling_id` = `filling`.`id`",
361 ]
362 .join(" ")
363 );
364 }
365
366 #[test]
367 fn join_7() {
368 use crate::{Related, Select};
369
370 let find_filling: Select<filling::Entity> = cake::Entity::find_related();
371 assert_eq!(
372 find_filling.build(DbBackend::MySql).to_string(),
373 [
374 "SELECT `filling`.`id`, `filling`.`name`, `filling`.`vendor_id` FROM `filling`",
375 "INNER JOIN `cake_filling` ON `cake_filling`.`filling_id` = `filling`.`id`",
376 "INNER JOIN `cake` ON `cake`.`id` = `cake_filling`.`cake_id`",
377 ]
378 .join(" ")
379 );
380 }
381
382 #[test]
383 fn join_8() {
384 use crate::{Related, Select};
385
386 let find_cake_filling_price: Select<cake_filling_price::Entity> =
387 cake_filling::Entity::find_related();
388 assert_eq!(
389 find_cake_filling_price.build(DbBackend::Postgres).to_string(),
390 [
391 r#"SELECT "cake_filling_price"."cake_id", "cake_filling_price"."filling_id", "cake_filling_price"."price""#,
392 r#"FROM "public"."cake_filling_price""#,
393 r#"INNER JOIN "cake_filling" ON"#,
394 r#""cake_filling"."cake_id" = "cake_filling_price"."cake_id" AND"#,
395 r#""cake_filling"."filling_id" = "cake_filling_price"."filling_id""#,
396 ]
397 .join(" ")
398 );
399 }
400
401 #[test]
402 fn join_9() {
403 use crate::{Related, Select};
404
405 let find_cake_filling: Select<cake_filling::Entity> =
406 cake_filling_price::Entity::find_related();
407 assert_eq!(
408 find_cake_filling.build(DbBackend::Postgres).to_string(),
409 [
410 r#"SELECT "cake_filling"."cake_id", "cake_filling"."filling_id""#,
411 r#"FROM "cake_filling""#,
412 r#"INNER JOIN "public"."cake_filling_price" ON"#,
413 r#""cake_filling_price"."cake_id" = "cake_filling"."cake_id" AND"#,
414 r#""cake_filling_price"."filling_id" = "cake_filling"."filling_id""#,
415 ]
416 .join(" ")
417 );
418 }
419
420 #[test]
421 fn join_10() {
422 let cake_model = cake::Model {
423 id: 12,
424 name: "".to_owned(),
425 };
426
427 assert_eq!(
428 cake_model
429 .find_linked(entity_linked::CakeToFilling)
430 .build(DbBackend::MySql)
431 .to_string(),
432 [
433 r#"SELECT `filling`.`id`, `filling`.`name`, `filling`.`vendor_id`"#,
434 r#"FROM `filling`"#,
435 r#"INNER JOIN `cake_filling` AS `r0` ON `r0`.`filling_id` = `filling`.`id`"#,
436 r#"INNER JOIN `cake` AS `r1` ON `r1`.`id` = `r0`.`cake_id`"#,
437 r#"WHERE `r1`.`id` = 12"#,
438 ]
439 .join(" ")
440 );
441 }
442
443 #[test]
444 fn join_11() {
445 let cake_model = cake::Model {
446 id: 18,
447 name: "".to_owned(),
448 };
449
450 assert_eq!(
451 cake_model
452 .find_linked(entity_linked::CakeToFillingVendor)
453 .build(DbBackend::MySql)
454 .to_string(),
455 [
456 r#"SELECT `vendor`.`id`, `vendor`.`name`"#,
457 r#"FROM `vendor`"#,
458 r#"INNER JOIN `filling` AS `r0` ON `r0`.`vendor_id` = `vendor`.`id`"#,
459 r#"INNER JOIN `cake_filling` AS `r1` ON `r1`.`filling_id` = `r0`.`id`"#,
460 r#"INNER JOIN `cake` AS `r2` ON `r2`.`id` = `r1`.`cake_id`"#,
461 r#"WHERE `r2`.`id` = 18"#,
462 ]
463 .join(" ")
464 );
465 }
466
467 #[test]
468 fn join_12() {
469 assert_eq!(
470 cake::Entity::find()
471 .find_also_linked(entity_linked::CakeToFilling)
472 .build(DbBackend::MySql)
473 .to_string(),
474 [
475 r#"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,"#,
476 r#"`r1`.`id` AS `B_id`, `r1`.`name` AS `B_name`, `r1`.`vendor_id` AS `B_vendor_id`"#,
477 r#"FROM `cake`"#,
478 r#"LEFT JOIN `cake_filling` AS `r0` ON `cake`.`id` = `r0`.`cake_id`"#,
479 r#"LEFT JOIN `filling` AS `r1` ON `r0`.`filling_id` = `r1`.`id`"#,
480 ]
481 .join(" ")
482 );
483 }
484
485 #[test]
486 fn join_13() {
487 assert_eq!(
488 cake::Entity::find()
489 .find_also_linked(entity_linked::CakeToFillingVendor)
490 .build(DbBackend::MySql)
491 .to_string(),
492 [
493 r#"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,"#,
494 r#"`r2`.`id` AS `B_id`, `r2`.`name` AS `B_name`"#,
495 r#"FROM `cake`"#,
496 r#"LEFT JOIN `cake_filling` AS `r0` ON `cake`.`id` = `r0`.`cake_id`"#,
497 r#"LEFT JOIN `filling` AS `r1` ON `r0`.`filling_id` = `r1`.`id`"#,
498 r#"LEFT JOIN `vendor` AS `r2` ON `r1`.`vendor_id` = `r2`.`id`"#,
499 ]
500 .join(" ")
501 );
502 }
503
504 #[test]
505 fn join_14() {
506 assert_eq!(
507 cake_compact::Entity::find()
508 .join(JoinType::LeftJoin, cake_compact::Relation::TropicalFruit.def())
509 .build(DbBackend::MySql)
510 .to_string(),
511 [
512 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
513 "LEFT JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id` AND `fruit`.`name` LIKE '%tropical%'",
514 ]
515 .join(" ")
516 );
517 }
518
519 #[test]
520 fn join_15() {
521 let cake_model = cake::Model {
522 id: 18,
523 name: "".to_owned(),
524 };
525
526 assert_eq!(
527 cake_model
528 .find_linked(entity_linked::CheeseCakeToFillingVendor)
529 .build(DbBackend::MySql)
530 .to_string(),
531 [
532 r#"SELECT `vendor`.`id`, `vendor`.`name`"#,
533 r#"FROM `vendor`"#,
534 r#"INNER JOIN `filling` AS `r0` ON `r0`.`vendor_id` = `vendor`.`id`"#,
535 r#"INNER JOIN `cake_filling` AS `r1` ON `r1`.`filling_id` = `r0`.`id`"#,
536 r#"INNER JOIN `cake` AS `r2` ON `r2`.`id` = `r1`.`cake_id` AND `r2`.`name` LIKE '%cheese%'"#,
537 r#"WHERE `r2`.`id` = 18"#,
538 ]
539 .join(" ")
540 );
541 }
542
543 #[test]
544 fn join_16() {
545 let cake_model = cake::Model {
546 id: 18,
547 name: "".to_owned(),
548 };
549 assert_eq!(
550 cake_model
551 .find_linked(entity_linked::JoinWithoutReverse)
552 .build(DbBackend::MySql)
553 .to_string(),
554 [
555 r#"SELECT `vendor`.`id`, `vendor`.`name`"#,
556 r#"FROM `vendor`"#,
557 r#"INNER JOIN `filling` AS `r0` ON `r0`.`vendor_id` = `vendor`.`id`"#,
558 r#"INNER JOIN `cake_filling` AS `r1` ON `r1`.`filling_id` = `r0`.`id`"#,
559 r#"INNER JOIN `cake_filling` AS `r2` ON `r2`.`cake_id` = `r1`.`id` AND `r2`.`name` LIKE '%cheese%'"#,
560 r#"WHERE `r2`.`id` = 18"#,
561 ]
562 .join(" ")
563 );
564 }
565
566 #[test]
567 fn join_17() {
568 assert_eq!(
569 cake::Entity::find()
570 .find_also_linked(entity_linked::CheeseCakeToFillingVendor)
571 .build(DbBackend::MySql)
572 .to_string(),
573 [
574 r#"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,"#,
575 r#"`r2`.`id` AS `B_id`, `r2`.`name` AS `B_name`"#,
576 r#"FROM `cake`"#,
577 r#"LEFT JOIN `cake_filling` AS `r0` ON `cake`.`id` = `r0`.`cake_id` AND `cake`.`name` LIKE '%cheese%'"#,
578 r#"LEFT JOIN `filling` AS `r1` ON `r0`.`filling_id` = `r1`.`id`"#,
579 r#"LEFT JOIN `vendor` AS `r2` ON `r1`.`vendor_id` = `r2`.`id`"#,
580 ]
581 .join(" ")
582 );
583 }
584
585 #[test]
586 fn join_18() {
587 assert_eq!(
588 cake::Entity::find()
589 .find_also_linked(entity_linked::JoinWithoutReverse)
590 .build(DbBackend::MySql)
591 .to_string(),
592 [
593 r#"SELECT `cake`.`id` AS `A_id`, `cake`.`name` AS `A_name`,"#,
594 r#"`r2`.`id` AS `B_id`, `r2`.`name` AS `B_name`"#,
595 r#"FROM `cake`"#,
596 r#"LEFT JOIN `cake` AS `r0` ON `cake_filling`.`cake_id` = `r0`.`id` AND `cake_filling`.`name` LIKE '%cheese%'"#,
597 r#"LEFT JOIN `filling` AS `r1` ON `r0`.`filling_id` = `r1`.`id`"#,
598 r#"LEFT JOIN `vendor` AS `r2` ON `r1`.`vendor_id` = `r2`.`id`"#,
599 ]
600 .join(" ")
601 );
602 }
603
604 #[test]
605 fn join_19() {
606 assert_eq!(
607 cake_compact::Entity::find()
608 .join(JoinType::LeftJoin, cake_compact::Relation::TropicalFruit.def())
609 .join(
610 JoinType::LeftJoin,
611 cake_filling::Relation::Cake
612 .def()
613 .rev()
614 .on_condition(|_left, right| {
615 Expr::col((right, cake_filling::Column::CakeId))
616 .gt(10)
617 .into_condition()
618 })
619 )
620 .join(
621 JoinType::LeftJoin,
622 cake_filling::Relation::Filling
623 .def()
624 .on_condition(|_left, right| {
625 Expr::col((right, filling::Column::Name))
626 .like("%lemon%")
627 .into_condition()
628 })
629 )
630 .join(JoinType::LeftJoin, filling::Relation::Vendor.def())
631 .build(DbBackend::MySql)
632 .to_string(),
633 [
634 "SELECT `cake`.`id`, `cake`.`name` FROM `cake`",
635 "LEFT JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id` AND `fruit`.`name` LIKE '%tropical%'",
636 "LEFT JOIN `cake_filling` ON `cake`.`id` = `cake_filling`.`cake_id` AND `cake_filling`.`cake_id` > 10",
637 "LEFT JOIN `filling` ON `cake_filling`.`filling_id` = `filling`.`id` AND `filling`.`name` LIKE '%lemon%'",
638 "LEFT JOIN `vendor` ON `filling`.`vendor_id` = `vendor`.`id`",
639 ]
640 .join(" ")
641 );
642 }
643
644 #[test]
645 fn join_20() {
646 assert_eq!(
647 cake::Entity::find()
648 .column_as(
649 Expr::col(("fruit_alias", fruit::Column::Name)),
650 "fruit_name"
651 )
652 .join_as(
653 JoinType::LeftJoin,
654 cake::Relation::Fruit
655 .def()
656 .on_condition(|_left, right| {
657 Expr::col((right, fruit::Column::Name))
658 .like("%tropical%")
659 .into_condition()
660 }),
661 "fruit_alias"
662 )
663 .build(DbBackend::MySql)
664 .to_string(),
665 [
666 "SELECT `cake`.`id`, `cake`.`name`, `fruit_alias`.`name` AS `fruit_name` FROM `cake`",
667 "LEFT JOIN `fruit` AS `fruit_alias` ON `cake`.`id` = `fruit_alias`.`cake_id` AND `fruit_alias`.`name` LIKE '%tropical%'",
668 ]
669 .join(" ")
670 );
671 }
672
673 #[test]
674 fn join_21() {
675 assert_eq!(
676 cake_compact::Entity::find()
677 .column_as(
678 Expr::col(("cake_filling_alias", cake_filling::Column::CakeId)),
679 "cake_filling_cake_id"
680 )
681 .join(JoinType::LeftJoin, cake_compact::Relation::TropicalFruit.def())
682 .join_as_rev(
683 JoinType::LeftJoin,
684 cake_filling::Relation::Cake
685 .def()
686 .on_condition(|left, _right| {
687 Expr::col((left, cake_filling::Column::CakeId))
688 .gt(10)
689 .into_condition()
690 }),
691 "cake_filling_alias"
692 )
693 .build(DbBackend::MySql)
694 .to_string(),
695 [
696 "SELECT `cake`.`id`, `cake`.`name`, `cake_filling_alias`.`cake_id` AS `cake_filling_cake_id` FROM `cake`",
697 "LEFT JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id` AND `fruit`.`name` LIKE '%tropical%'",
698 "LEFT JOIN `cake_filling` AS `cake_filling_alias` ON `cake_filling_alias`.`cake_id` = `cake`.`id` AND `cake_filling_alias`.`cake_id` > 10",
699 ]
700 .join(" ")
701 );
702 }
703
704 #[test]
705 fn join_22() {
706 assert_eq!(
707 cake_compact::Entity::find()
708 .column_as(
709 Expr::col(("cake_filling_alias", cake_filling::Column::CakeId)),
710 "cake_filling_cake_id"
711 )
712 .join(JoinType::LeftJoin, cake_compact::Relation::OrTropicalFruit.def())
713 .join_as_rev(
714 JoinType::LeftJoin,
715 cake_filling::Relation::Cake
716 .def()
717 .condition_type(ConditionType::Any)
718 .on_condition(|left, _right| {
719 Expr::col((left, cake_filling::Column::CakeId))
720 .gt(10)
721 .into_condition()
722 }),
723 "cake_filling_alias"
724 )
725 .build(DbBackend::MySql)
726 .to_string(),
727 [
728 "SELECT `cake`.`id`, `cake`.`name`, `cake_filling_alias`.`cake_id` AS `cake_filling_cake_id` FROM `cake`",
729 "LEFT JOIN `fruit` ON `cake`.`id` = `fruit`.`cake_id` OR `fruit`.`name` LIKE '%tropical%'",
730 "LEFT JOIN `cake_filling` AS `cake_filling_alias` ON `cake_filling_alias`.`cake_id` = `cake`.`id` OR `cake_filling_alias`.`cake_id` > 10",
731 ]
732 .join(" ")
733 );
734 }
735}