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