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 )+
216 $crate::allow_tables_to_appear_in_same_query!($($right_mod,)+);
217 };
218
219 ($last_table:ident,) => {};
220
221 () => {};
222}
223
224#[doc(hidden)]
225#[macro_export]
226macro_rules! __diesel_impl_allow_in_same_group_by_clause {
227 (
228 left = [$($left_path:tt)::+],
229 ) => {};
230 (
231 left = [$($left_path:tt)::+],
232 $($right_path:tt)::+
233 ) => {
234 $crate::__diesel_impl_allow_in_same_group_by_clause! {
235 left = [$($left_path)+],
236 right = [$($right_path)+],
237 left_tbl = [],
238 left_path = [],
239 }
240 };
241 (
242 left = [$($left_path:tt)::+],
243 $($right_path:tt)::+,
244 $($other:tt)*
245 ) => {
246 $crate::__diesel_impl_allow_in_same_group_by_clause! {
247 left = [$($left_path)+],
248 right = [$($right_path)+],
249 left_tbl = [],
250 left_path = [],
251 }
252 $crate::__diesel_impl_allow_in_same_group_by_clause! {
253 left = [$($left_path)::+],
254 $($other)*
255 }
256 };
257 (
258 left = [$left_path_p1: tt $($left_path: tt)+],
259 right = [$($right_path: tt)*],
260 left_tbl = [$($left_tbl:tt)?],
261 left_path = [$($left_out_path:tt)*],
262 ) => {
263 $crate::__diesel_impl_allow_in_same_group_by_clause! {
264 left = [$($left_path)+],
265 right = [$($right_path)*],
266 left_tbl = [$left_path_p1],
267 left_path = [$($left_out_path)* $($left_tbl)?],
268 }
269 };
270 (
271 left = [$left_col: tt],
272 right = [$($right_path: tt)*],
273 left_tbl = [$($left_tbl:tt)?],
274 left_path = [$($left_out_path:tt)*],
275 ) => {
276 $crate::__diesel_impl_allow_in_same_group_by_clause! {
277 left = [$left_col],
278 right = [$($right_path)*],
279 left_tbl = [$($left_tbl)?],
280 left_path = [$($left_out_path)*],
281 right_tbl = [],
282 right_path = [],
283 }
284 };
285 (
286 left = [$left_col: tt ],
287 right = [$right_path_p1: tt $($right_path: tt)+],
288 left_tbl = [$($left_tbl:tt)?],
289 left_path = [$($left_out_path:tt)*],
290 right_tbl = [$($right_tbl:tt)?],
291 right_path = [$($right_out_path:tt)*],
292 ) => {
293 $crate::__diesel_impl_allow_in_same_group_by_clause! {
294 left = [$left_col],
295 right = [$($right_path)+],
296 left_tbl = [$($left_tbl)?],
297 left_path = [$($left_out_path)*],
298 right_tbl = [$right_path_p1],
299 right_path = [$($right_out_path)* $($right_tbl)?],
300 }
301 };
302 (
303 left = [$left_col: tt],
304 right = [$right_col: tt],
305 left_tbl = [$left_tbl:tt],
306 left_path = [$($left_begin:tt)*],
307 right_tbl = [$right_tbl:tt],
308 right_path = [$($right_begin:tt)*],
309 ) => {
310 $crate::static_cond! {
311 if $left_tbl != $right_tbl {
312 impl $crate::expression::IsContainedInGroupBy<$($left_begin ::)* $left_tbl :: $left_col> for $($right_begin ::)* $right_tbl :: $right_col {
313 type Output = $crate::expression::is_contained_in_group_by::No;
314 }
315
316 impl $crate::expression::IsContainedInGroupBy<$($right_begin ::)* $right_tbl :: $right_col> for $($left_begin ::)* $left_tbl :: $left_col {
317 type Output = $crate::expression::is_contained_in_group_by::No;
318 }
319 }
320 }
321 };
322 (
323 left = [$left_col: tt],
324 right = [$right_col: tt],
325 left_tbl = [$($left_tbl:tt)?],
326 left_path = [$($left_begin:tt)*],
327 right_tbl = [$($right_tbl:tt)?],
328 right_path = [$($right_begin:tt)*],
329 ) => {
330 impl $crate::expression::IsContainedInGroupBy<$($left_begin ::)* $($left_tbl ::)? $left_col> for $($right_begin ::)* $($right_tbl ::)? $right_col {
331 type Output = $crate::expression::is_contained_in_group_by::No;
332 }
333
334 impl $crate::expression::IsContainedInGroupBy<$($right_begin ::)* $($right_tbl ::)? $right_col> for $($left_begin ::)* $($left_tbl ::)? $left_col {
335 type Output = $crate::expression::is_contained_in_group_by::No;
336 }
337 };
338
339}
340
341#[macro_export]
379macro_rules! allow_columns_to_appear_in_same_group_by_clause {
380 ($($left_path:tt)::+, $($right_path:tt)::+ $(,)?) => {
381 $crate::__diesel_impl_allow_in_same_group_by_clause! {
382 left = [$($left_path)::+],
383 $($right_path)::+,
384 }
385 };
386 ($($left_path:tt)::+, $($right_path:tt)::+, $($other: tt)*) => {
387 $crate::__diesel_impl_allow_in_same_group_by_clause! {
388 left = [$($left_path)::+],
389 $($right_path)::+,
390 $($other)*
391 }
392 $crate::allow_columns_to_appear_in_same_group_by_clause! {
393 $($right_path)::+,
394 $($other)*
395 }
396 };
397 ($last_col:ty,) => {};
398 () => {};
399}
400
401#[macro_export]
402#[doc(hidden)]
403macro_rules! __diesel_with_dollar_sign {
404 ($($body:tt)*) => {
405 macro_rules! __with_dollar_sign { $($body)* }
406 __with_dollar_sign!($);
407 }
408}
409
410#[macro_use]
413mod internal;
414#[macro_use]
415mod static_cond;
416#[macro_use]
417mod ops;
418
419#[cfg(test)]
420mod tests {
421 use crate::prelude::*;
422
423 table! {
424 foo.bars {
425 id -> Integer,
426 baz -> Text,
427 }
428 }
429
430 mod my_types {
431 #[derive(Debug, Clone, Copy, crate::sql_types::SqlType)]
432 pub struct MyCustomType;
433 }
434
435 table! {
436 use crate::sql_types::*;
437 use crate::macros::tests::my_types::*;
438
439 table_with_custom_types {
440 id -> Integer,
441 my_type -> MyCustomType,
442 }
443 }
444
445 table! {
446 use crate::sql_types::*;
447 use crate::macros::tests::my_types::*;
448
449 table_with_custom_type_and_id (a) {
453 a -> Integer,
457 my_type -> MyCustomType,
458 }
459 }
460
461 #[diesel_test_helper::test]
462 #[cfg(feature = "postgres")]
463 fn table_with_custom_schema() {
464 use crate::pg::Pg;
465 let expected_sql = r#"SELECT "foo"."bars"."baz" FROM "foo"."bars" -- binds: []"#;
466 assert_eq!(
467 expected_sql,
468 &crate::debug_query::<Pg, _>(&bars::table.select(bars::baz)).to_string()
469 );
470 }
471
472 table! {
473 use crate::sql_types;
474 use crate::sql_types::*;
475
476 table_with_arbitrarily_complex_types {
477 id -> sql_types::Integer,
478 qualified_nullable -> sql_types::Nullable<sql_types::Integer>,
479 deeply_nested_type -> Nullable<Nullable<Integer>>,
480 }
485 }
486
487 table!(
488 foo {
489 id -> Integer,
491
492 #[sql_name = "type"]
493 mytype -> Integer,
495
496 #[sql_name = "bleh"]
498 hey -> Integer,
499 }
500 );
501
502 #[diesel_test_helper::test]
503 #[cfg(feature = "postgres")]
504 fn table_with_column_renaming_postgres() {
505 use crate::pg::Pg;
506 let expected_sql = r#"SELECT "foo"."id", "foo"."type", "foo"."bleh" FROM "foo" WHERE ("foo"."type" = $1) -- binds: [1]"#;
507 assert_eq!(
508 expected_sql,
509 crate::debug_query::<Pg, _>(&foo::table.filter(foo::mytype.eq(1))).to_string()
510 );
511 }
512
513 #[diesel_test_helper::test]
514 #[cfg(feature = "mysql")]
515 fn table_with_column_renaming_mysql() {
516 use crate::mysql::Mysql;
517 let expected_sql = r#"SELECT `foo`.`id`, `foo`.`type`, `foo`.`bleh` FROM `foo` WHERE (`foo`.`type` = ?) -- binds: [1]"#;
518 assert_eq!(
519 expected_sql,
520 crate::debug_query::<Mysql, _>(&foo::table.filter(foo::mytype.eq(1))).to_string()
521 );
522 }
523
524 #[diesel_test_helper::test]
525 #[cfg(feature = "sqlite")]
526 fn table_with_column_renaming_sqlite() {
527 use crate::sqlite::Sqlite;
528 let expected_sql = r#"SELECT `foo`.`id`, `foo`.`type`, `foo`.`bleh` FROM `foo` WHERE (`foo`.`type` = ?) -- binds: [1]"#;
529 assert_eq!(
530 expected_sql,
531 crate::debug_query::<Sqlite, _>(&foo::table.filter(foo::mytype.eq(1))).to_string()
532 );
533 }
534
535 table!(
536 use crate::sql_types::*;
537
538 #[sql_name="mod"]
540 bar {
542 id -> Integer,
543 }
544 );
545
546 #[diesel_test_helper::test]
547 #[cfg(feature = "postgres")]
548 fn table_renaming_postgres() {
549 use crate::pg::Pg;
550 let expected_sql = r#"SELECT "mod"."id" FROM "mod" -- binds: []"#;
551 assert_eq!(
552 expected_sql,
553 crate::debug_query::<Pg, _>(&bar::table.select(bar::id)).to_string()
554 );
555 }
556
557 #[diesel_test_helper::test]
558 #[cfg(feature = "mysql")]
559 fn table_renaming_mysql() {
560 use crate::mysql::Mysql;
561 let expected_sql = r#"SELECT `mod`.`id` FROM `mod` -- binds: []"#;
562 assert_eq!(
563 expected_sql,
564 crate::debug_query::<Mysql, _>(&bar::table.select(bar::id)).to_string()
565 );
566 }
567
568 #[diesel_test_helper::test]
569 #[cfg(feature = "sqlite")]
570 fn table_renaming_sqlite() {
571 use crate::sqlite::Sqlite;
572 let expected_sql = r#"SELECT `mod`.`id` FROM `mod` -- binds: []"#;
573 assert_eq!(
574 expected_sql,
575 crate::debug_query::<Sqlite, _>(&bar::table.select(bar::id)).to_string()
576 );
577 }
578
579 mod tests_for_allow_combined_group_by_syntax {
580 use crate::table;
581
582 table! {
583 a(b) {
584 b -> Text,
585 c -> Text,
586 d -> Text,
587 e -> Text,
588 }
589 }
590
591 table! {
592 b(a) {
593 a -> Text,
594 c -> Text,
595 d -> Text,
596 }
597 }
598
599 table! {
600 c(a) {
601 a -> Text,
602 b -> Text,
603 d -> Text,
604 }
605 }
606
607 allow_columns_to_appear_in_same_group_by_clause!(a::b, b::a, a::d,);
609
610 allow_columns_to_appear_in_same_group_by_clause!(self::a::c, self::b::c, self::b::d,);
612
613 use self::a::d as a_d;
614 use self::b::d as b_d;
615 use self::c::d as c_d;
616
617 allow_columns_to_appear_in_same_group_by_clause!(a_d, b_d, c_d);
619
620 allow_columns_to_appear_in_same_group_by_clause!(c_d, self::b::a, a::e,);
622 }
623}