1pub(crate) mod prelude {
2 #[cfg_attr(
3 any(feature = "huge-tables", feature = "large-tables"),
4 allow(deprecated)
5 )]
6 #[allow(unreachable_pub, unused_imports)]
8 #[doc(inline)]
9 pub use crate::{
10 allow_columns_to_appear_in_same_group_by_clause, allow_tables_to_appear_in_same_query,
11 joinable, table,
12 };
13}
14
15#[doc(inline)]
16pub use diesel_derives::table_proc as table;
17
18#[macro_export]
83macro_rules! joinable {
84 ($($child:ident)::* -> $($parent:ident)::* ($source:ident)) => {
85 $crate::joinable_inner!($($child)::* ::table => $($parent)::* ::table : ($($child)::* ::$source = $($parent)::* ::table));
86 $crate::joinable_inner!($($parent)::* ::table => $($child)::* ::table : ($($child)::* ::$source = $($parent)::* ::table));
87 }
88}
89
90#[macro_export]
91#[doc(hidden)]
92macro_rules! joinable_inner {
93 ($left_table:path => $right_table:path : ($foreign_key:path = $parent_table:path)) => {
94 $crate::joinable_inner!(
95 left_table_ty = $left_table,
96 right_table_ty = $right_table,
97 right_table_expr = $right_table,
98 foreign_key = $foreign_key,
99 primary_key_ty = <$parent_table as $crate::query_source::Table>::PrimaryKey,
100 primary_key_expr =
101 <$parent_table as $crate::query_source::Table>::primary_key(&$parent_table),
102 );
103 };
104
105 (
106 left_table_ty = $left_table_ty:ty,
107 right_table_ty = $right_table_ty:ty,
108 right_table_expr = $right_table_expr:expr,
109 foreign_key = $foreign_key:path,
110 primary_key_ty = $primary_key_ty:ty,
111 primary_key_expr = $primary_key_expr:expr,
112 ) => {
113 impl $crate::JoinTo<$right_table_ty> for $left_table_ty {
114 type FromClause = $right_table_ty;
115 type OnClause = $crate::dsl::Eq<
116 $crate::internal::table_macro::NullableExpression<$foreign_key>,
117 $crate::internal::table_macro::NullableExpression<$primary_key_ty>,
118 >;
119
120 fn join_target(rhs: $right_table_ty) -> (Self::FromClause, Self::OnClause) {
121 use $crate::{ExpressionMethods, NullableExpressionMethods};
122
123 (
124 rhs,
125 $foreign_key.nullable().eq($primary_key_expr.nullable()),
126 )
127 }
128 }
129 };
130}
131
132#[macro_export]
211macro_rules! allow_tables_to_appear_in_same_query {
212 ($left_mod:ident, $($right_mod:ident),+ $(,)*) => {
213 $(
214 impl $crate::query_source::TableNotEqual<$left_mod::table> for $right_mod::table {}
215 impl $crate::query_source::TableNotEqual<$right_mod::table> for $left_mod::table {}
216 $crate::__diesel_internal_backend_specific_allow_tables_to_appear_in_same_query!($left_mod, $right_mod);
217 )+
218 $crate::allow_tables_to_appear_in_same_query!($($right_mod,)+);
219 };
220
221 ($last_table:ident,) => {};
222
223 () => {};
224}
225#[doc(hidden)]
226#[macro_export]
227#[cfg(feature = "postgres_backend")]
228macro_rules! __diesel_internal_backend_specific_allow_tables_to_appear_in_same_query {
229 ($left:ident, $right:ident) => {
230 impl $crate::query_source::TableNotEqual<$left::table>
231 for $crate::query_builder::Only<$right::table>
232 {
233 }
234 impl $crate::query_source::TableNotEqual<$right::table>
235 for $crate::query_builder::Only<$left::table>
236 {
237 }
238 impl $crate::query_source::TableNotEqual<$crate::query_builder::Only<$left::table>>
239 for $right::table
240 {
241 }
242 impl $crate::query_source::TableNotEqual<$crate::query_builder::Only<$right::table>>
243 for $left::table
244 {
245 }
246 impl<TSM> $crate::query_source::TableNotEqual<$left::table>
247 for $crate::query_builder::Tablesample<$right::table, TSM>
248 where
249 TSM: $crate::internal::table_macro::TablesampleMethod,
250 {
251 }
252 impl<TSM> $crate::query_source::TableNotEqual<$right::table>
253 for $crate::query_builder::Tablesample<$left::table, TSM>
254 where
255 TSM: $crate::internal::table_macro::TablesampleMethod,
256 {
257 }
258 impl<TSM>
259 $crate::query_source::TableNotEqual<
260 $crate::query_builder::Tablesample<$left::table, TSM>,
261 > for $right::table
262 where
263 TSM: $crate::internal::table_macro::TablesampleMethod,
264 {
265 }
266 impl<TSM>
267 $crate::query_source::TableNotEqual<
268 $crate::query_builder::Tablesample<$right::table, TSM>,
269 > for $left::table
270 where
271 TSM: $crate::internal::table_macro::TablesampleMethod,
272 {
273 }
274 };
275}
276#[doc(hidden)]
277#[macro_export]
278#[cfg(not(feature = "postgres_backend"))]
279macro_rules! __diesel_internal_backend_specific_allow_tables_to_appear_in_same_query {
280 ($left:ident, $right:ident) => {};
281}
282
283#[doc(hidden)]
284#[macro_export]
285macro_rules! __diesel_impl_allow_in_same_group_by_clause {
286 (
287 left = [$($left_path:tt)::+],
288 ) => {};
289 (
290 left = [$($left_path:tt)::+],
291 $($right_path:tt)::+
292 ) => {
293 $crate::__diesel_impl_allow_in_same_group_by_clause! {
294 left = [$($left_path)+],
295 right = [$($right_path)+],
296 left_tbl = [],
297 left_path = [],
298 }
299 };
300 (
301 left = [$($left_path:tt)::+],
302 $($right_path:tt)::+,
303 $($other:tt)*
304 ) => {
305 $crate::__diesel_impl_allow_in_same_group_by_clause! {
306 left = [$($left_path)+],
307 right = [$($right_path)+],
308 left_tbl = [],
309 left_path = [],
310 }
311 $crate::__diesel_impl_allow_in_same_group_by_clause! {
312 left = [$($left_path)::+],
313 $($other)*
314 }
315 };
316 (
317 left = [$left_path_p1: tt $($left_path: tt)+],
318 right = [$($right_path: tt)*],
319 left_tbl = [$($left_tbl:tt)?],
320 left_path = [$($left_out_path:tt)*],
321 ) => {
322 $crate::__diesel_impl_allow_in_same_group_by_clause! {
323 left = [$($left_path)+],
324 right = [$($right_path)*],
325 left_tbl = [$left_path_p1],
326 left_path = [$($left_out_path)* $($left_tbl)?],
327 }
328 };
329 (
330 left = [$left_col: tt],
331 right = [$($right_path: tt)*],
332 left_tbl = [$($left_tbl:tt)?],
333 left_path = [$($left_out_path:tt)*],
334 ) => {
335 $crate::__diesel_impl_allow_in_same_group_by_clause! {
336 left = [$left_col],
337 right = [$($right_path)*],
338 left_tbl = [$($left_tbl)?],
339 left_path = [$($left_out_path)*],
340 right_tbl = [],
341 right_path = [],
342 }
343 };
344 (
345 left = [$left_col: tt ],
346 right = [$right_path_p1: tt $($right_path: tt)+],
347 left_tbl = [$($left_tbl:tt)?],
348 left_path = [$($left_out_path:tt)*],
349 right_tbl = [$($right_tbl:tt)?],
350 right_path = [$($right_out_path:tt)*],
351 ) => {
352 $crate::__diesel_impl_allow_in_same_group_by_clause! {
353 left = [$left_col],
354 right = [$($right_path)+],
355 left_tbl = [$($left_tbl)?],
356 left_path = [$($left_out_path)*],
357 right_tbl = [$right_path_p1],
358 right_path = [$($right_out_path)* $($right_tbl)?],
359 }
360 };
361 (
362 left = [$left_col: tt],
363 right = [$right_col: tt],
364 left_tbl = [$left_tbl:tt],
365 left_path = [$($left_begin:tt)*],
366 right_tbl = [$right_tbl:tt],
367 right_path = [$($right_begin:tt)*],
368 ) => {
369 $crate::static_cond! {
370 if $left_tbl != $right_tbl {
371 impl $crate::expression::IsContainedInGroupBy<$($left_begin ::)* $left_tbl :: $left_col> for $($right_begin ::)* $right_tbl :: $right_col {
372 type Output = $crate::expression::is_contained_in_group_by::No;
373 }
374
375 impl $crate::expression::IsContainedInGroupBy<$($right_begin ::)* $right_tbl :: $right_col> for $($left_begin ::)* $left_tbl :: $left_col {
376 type Output = $crate::expression::is_contained_in_group_by::No;
377 }
378 }
379 }
380 };
381 (
382 left = [$left_col: tt],
383 right = [$right_col: tt],
384 left_tbl = [$($left_tbl:tt)?],
385 left_path = [$($left_begin:tt)*],
386 right_tbl = [$($right_tbl:tt)?],
387 right_path = [$($right_begin:tt)*],
388 ) => {
389 impl $crate::expression::IsContainedInGroupBy<$($left_begin ::)* $($left_tbl ::)? $left_col> for $($right_begin ::)* $($right_tbl ::)? $right_col {
390 type Output = $crate::expression::is_contained_in_group_by::No;
391 }
392
393 impl $crate::expression::IsContainedInGroupBy<$($right_begin ::)* $($right_tbl ::)? $right_col> for $($left_begin ::)* $($left_tbl ::)? $left_col {
394 type Output = $crate::expression::is_contained_in_group_by::No;
395 }
396 };
397
398}
399
400#[macro_export]
436macro_rules! allow_columns_to_appear_in_same_group_by_clause {
437 ($($left_path:tt)::+, $($right_path:tt)::+ $(,)?) => {
438 $crate::__diesel_impl_allow_in_same_group_by_clause! {
439 left = [$($left_path)::+],
440 $($right_path)::+,
441 }
442 };
443 ($($left_path:tt)::+, $($right_path:tt)::+, $($other: tt)*) => {
444 $crate::__diesel_impl_allow_in_same_group_by_clause! {
445 left = [$($left_path)::+],
446 $($right_path)::+,
447 $($other)*
448 }
449 $crate::allow_columns_to_appear_in_same_group_by_clause! {
450 $($right_path)::+,
451 $($other)*
452 }
453 };
454 ($last_col:ty,) => {};
455 () => {};
456}
457
458#[macro_export]
459#[doc(hidden)]
460macro_rules! __diesel_with_dollar_sign {
461 ($($body:tt)*) => {
462 macro_rules! __with_dollar_sign { $($body)* }
463 __with_dollar_sign!($);
464 }
465}
466
467#[macro_use]
470mod internal;
471#[macro_use]
472mod static_cond;
473#[macro_use]
474mod ops;
475
476#[cfg(test)]
477mod tests {
478 use crate::prelude::*;
479
480 table! {
481 foo.bars {
482 id -> Integer,
483 baz -> Text,
484 }
485 }
486
487 mod my_types {
488 #[derive(Debug, Clone, Copy, crate::sql_types::SqlType)]
489 pub struct MyCustomType;
490 }
491
492 table! {
493 use crate::sql_types::*;
494 use crate::macros::tests::my_types::*;
495
496 table_with_custom_types {
497 id -> Integer,
498 my_type -> MyCustomType,
499 }
500 }
501
502 table! {
503 use crate::sql_types::*;
504 use crate::macros::tests::my_types::*;
505
506 table_with_custom_type_and_id (a) {
510 a -> Integer,
514 my_type -> MyCustomType,
515 }
516 }
517
518 #[test]
519 #[cfg(feature = "postgres")]
520 fn table_with_custom_schema() {
521 use crate::pg::Pg;
522 let expected_sql = r#"SELECT "foo"."bars"."baz" FROM "foo"."bars" -- binds: []"#;
523 assert_eq!(
524 expected_sql,
525 &crate::debug_query::<Pg, _>(&bars::table.select(bars::baz)).to_string()
526 );
527 }
528
529 table! {
530 use crate::sql_types;
531 use crate::sql_types::*;
532
533 table_with_arbitrarily_complex_types {
534 id -> sql_types::Integer,
535 qualified_nullable -> sql_types::Nullable<sql_types::Integer>,
536 deeply_nested_type -> Nullable<Nullable<Integer>>,
537 }
542 }
543
544 table!(
545 foo {
546 id -> Integer,
548
549 #[sql_name = "type"]
550 mytype -> Integer,
552
553 #[sql_name = "bleh"]
555 hey -> Integer,
556 }
557 );
558
559 #[test]
560 #[cfg(feature = "postgres")]
561 fn table_with_column_renaming_postgres() {
562 use crate::pg::Pg;
563 let expected_sql = r#"SELECT "foo"."id", "foo"."type", "foo"."bleh" FROM "foo" WHERE ("foo"."type" = $1) -- binds: [1]"#;
564 assert_eq!(
565 expected_sql,
566 crate::debug_query::<Pg, _>(&foo::table.filter(foo::mytype.eq(1))).to_string()
567 );
568 }
569
570 #[test]
571 #[cfg(feature = "mysql")]
572 fn table_with_column_renaming_mysql() {
573 use crate::mysql::Mysql;
574 let expected_sql = r#"SELECT `foo`.`id`, `foo`.`type`, `foo`.`bleh` FROM `foo` WHERE (`foo`.`type` = ?) -- binds: [1]"#;
575 assert_eq!(
576 expected_sql,
577 crate::debug_query::<Mysql, _>(&foo::table.filter(foo::mytype.eq(1))).to_string()
578 );
579 }
580
581 #[test]
582 #[cfg(feature = "sqlite")]
583 fn table_with_column_renaming_sqlite() {
584 use crate::sqlite::Sqlite;
585 let expected_sql = r#"SELECT `foo`.`id`, `foo`.`type`, `foo`.`bleh` FROM `foo` WHERE (`foo`.`type` = ?) -- binds: [1]"#;
586 assert_eq!(
587 expected_sql,
588 crate::debug_query::<Sqlite, _>(&foo::table.filter(foo::mytype.eq(1))).to_string()
589 );
590 }
591
592 table!(
593 use crate::sql_types::*;
594
595 #[sql_name="mod"]
597 bar {
599 id -> Integer,
600 }
601 );
602
603 #[test]
604 #[cfg(feature = "postgres")]
605 fn table_renaming_postgres() {
606 use crate::pg::Pg;
607 let expected_sql = r#"SELECT "mod"."id" FROM "mod" -- binds: []"#;
608 assert_eq!(
609 expected_sql,
610 crate::debug_query::<Pg, _>(&bar::table.select(bar::id)).to_string()
611 );
612 }
613
614 #[test]
615 #[cfg(feature = "mysql")]
616 fn table_renaming_mysql() {
617 use crate::mysql::Mysql;
618 let expected_sql = r#"SELECT `mod`.`id` FROM `mod` -- binds: []"#;
619 assert_eq!(
620 expected_sql,
621 crate::debug_query::<Mysql, _>(&bar::table.select(bar::id)).to_string()
622 );
623 }
624
625 #[test]
626 #[cfg(feature = "sqlite")]
627 fn table_renaming_sqlite() {
628 use crate::sqlite::Sqlite;
629 let expected_sql = r#"SELECT `mod`.`id` FROM `mod` -- binds: []"#;
630 assert_eq!(
631 expected_sql,
632 crate::debug_query::<Sqlite, _>(&bar::table.select(bar::id)).to_string()
633 );
634 }
635
636 mod tests_for_allow_combined_group_by_syntax {
637 use crate::table;
638
639 table! {
640 a(b) {
641 b -> Text,
642 c -> Text,
643 d -> Text,
644 e -> Text,
645 }
646 }
647
648 table! {
649 b(a) {
650 a -> Text,
651 c -> Text,
652 d -> Text,
653 }
654 }
655
656 table! {
657 c(a) {
658 a -> Text,
659 b -> Text,
660 d -> Text,
661 }
662 }
663
664 allow_columns_to_appear_in_same_group_by_clause!(a::b, b::a, a::d,);
666
667 allow_columns_to_appear_in_same_group_by_clause!(self::a::c, self::b::c, self::b::d,);
669
670 use self::a::d as a_d;
671 use self::b::d as b_d;
672 use self::c::d as c_d;
673
674 allow_columns_to_appear_in_same_group_by_clause!(a_d, b_d, c_d);
676
677 allow_columns_to_appear_in_same_group_by_clause!(c_d, self::b::a, a::e,);
679 }
680}