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#[doc(hidden)]
132#[macro_export]
133macro_rules! __diesel_impl_allow_in_same_group_by_clause {
134 (
135 left = [$($left_path:tt)::+],
136 ) => {};
137 (
138 left = [$($left_path:tt)::+],
139 $($right_path:tt)::+
140 ) => {
141 $crate::__diesel_impl_allow_in_same_group_by_clause! {
142 left = [$($left_path)+],
143 right = [$($right_path)+],
144 left_tbl = [],
145 left_path = [],
146 }
147 };
148 (
149 left = [$($left_path:tt)::+],
150 $($right_path:tt)::+,
151 $($other:tt)*
152 ) => {
153 $crate::__diesel_impl_allow_in_same_group_by_clause! {
154 left = [$($left_path)+],
155 right = [$($right_path)+],
156 left_tbl = [],
157 left_path = [],
158 }
159 $crate::__diesel_impl_allow_in_same_group_by_clause! {
160 left = [$($left_path)::+],
161 $($other)*
162 }
163 };
164 (
165 left = [$left_path_p1: tt $($left_path: tt)+],
166 right = [$($right_path: tt)*],
167 left_tbl = [$($left_tbl:tt)?],
168 left_path = [$($left_out_path:tt)*],
169 ) => {
170 $crate::__diesel_impl_allow_in_same_group_by_clause! {
171 left = [$($left_path)+],
172 right = [$($right_path)*],
173 left_tbl = [$left_path_p1],
174 left_path = [$($left_out_path)* $($left_tbl)?],
175 }
176 };
177 (
178 left = [$left_col: tt],
179 right = [$($right_path: tt)*],
180 left_tbl = [$($left_tbl:tt)?],
181 left_path = [$($left_out_path:tt)*],
182 ) => {
183 $crate::__diesel_impl_allow_in_same_group_by_clause! {
184 left = [$left_col],
185 right = [$($right_path)*],
186 left_tbl = [$($left_tbl)?],
187 left_path = [$($left_out_path)*],
188 right_tbl = [],
189 right_path = [],
190 }
191 };
192 (
193 left = [$left_col: tt ],
194 right = [$right_path_p1: tt $($right_path: tt)+],
195 left_tbl = [$($left_tbl:tt)?],
196 left_path = [$($left_out_path:tt)*],
197 right_tbl = [$($right_tbl:tt)?],
198 right_path = [$($right_out_path:tt)*],
199 ) => {
200 $crate::__diesel_impl_allow_in_same_group_by_clause! {
201 left = [$left_col],
202 right = [$($right_path)+],
203 left_tbl = [$($left_tbl)?],
204 left_path = [$($left_out_path)*],
205 right_tbl = [$right_path_p1],
206 right_path = [$($right_out_path)* $($right_tbl)?],
207 }
208 };
209 (
210 left = [$left_col: tt],
211 right = [$right_col: tt],
212 left_tbl = [$left_tbl:tt],
213 left_path = [$($left_begin:tt)*],
214 right_tbl = [$right_tbl:tt],
215 right_path = [$($right_begin:tt)*],
216 ) => {
217 $crate::static_cond! {
218 if $left_tbl != $right_tbl {
219 impl $crate::expression::IsContainedInGroupBy<$($left_begin ::)* $left_tbl :: $left_col> for $($right_begin ::)* $right_tbl :: $right_col {
220 type Output = $crate::expression::is_contained_in_group_by::No;
221 }
222
223 impl $crate::expression::IsContainedInGroupBy<$($right_begin ::)* $right_tbl :: $right_col> for $($left_begin ::)* $left_tbl :: $left_col {
224 type Output = $crate::expression::is_contained_in_group_by::No;
225 }
226 }
227 }
228 };
229 (
230 left = [$left_col: tt],
231 right = [$right_col: tt],
232 left_tbl = [$($left_tbl:tt)?],
233 left_path = [$($left_begin:tt)*],
234 right_tbl = [$($right_tbl:tt)?],
235 right_path = [$($right_begin:tt)*],
236 ) => {
237 impl $crate::expression::IsContainedInGroupBy<$($left_begin ::)* $($left_tbl ::)? $left_col> for $($right_begin ::)* $($right_tbl ::)? $right_col {
238 type Output = $crate::expression::is_contained_in_group_by::No;
239 }
240
241 impl $crate::expression::IsContainedInGroupBy<$($right_begin ::)* $($right_tbl ::)? $right_col> for $($left_begin ::)* $($left_tbl ::)? $left_col {
242 type Output = $crate::expression::is_contained_in_group_by::No;
243 }
244 };
245
246}
247
248#[macro_export]
286macro_rules! allow_columns_to_appear_in_same_group_by_clause {
287 ($($left_path:tt)::+, $($right_path:tt)::+ $(,)?) => {
288 $crate::__diesel_impl_allow_in_same_group_by_clause! {
289 left = [$($left_path)::+],
290 $($right_path)::+,
291 }
292 };
293 ($($left_path:tt)::+, $($right_path:tt)::+, $($other: tt)*) => {
294 $crate::__diesel_impl_allow_in_same_group_by_clause! {
295 left = [$($left_path)::+],
296 $($right_path)::+,
297 $($other)*
298 }
299 $crate::allow_columns_to_appear_in_same_group_by_clause! {
300 $($right_path)::+,
301 $($other)*
302 }
303 };
304 ($last_col:ty,) => {};
305 () => {};
306}
307
308#[macro_export]
309#[doc(hidden)]
310macro_rules! __diesel_with_dollar_sign {
311 ($($body:tt)*) => {
312 macro_rules! __with_dollar_sign { $($body)* }
313 __with_dollar_sign!($);
314 }
315}
316
317#[macro_use]
320mod internal;
321#[macro_use]
322mod static_cond;
323#[macro_use]
324mod ops;
325
326#[cfg(test)]
327mod tests {
328 use crate::prelude::*;
329
330 table! {
331 foo.bars {
332 id -> Integer,
333 baz -> Text,
334 }
335 }
336
337 mod my_types {
338 #[derive(Debug, Clone, Copy, crate::sql_types::SqlType)]
339 pub struct MyCustomType;
340 }
341
342 table! {
343 use crate::sql_types::*;
344 use crate::macros::tests::my_types::*;
345
346 table_with_custom_types {
347 id -> Integer,
348 my_type -> MyCustomType,
349 }
350 }
351
352 table! {
353 use crate::sql_types::*;
354 use crate::macros::tests::my_types::*;
355
356 table_with_custom_type_and_id (a) {
360 a -> Integer,
364 my_type -> MyCustomType,
365 }
366 }
367
368 #[diesel_test_helper::test]
369 #[cfg(feature = "postgres")]
370 fn table_with_custom_schema() {
371 use crate::pg::Pg;
372 let expected_sql = r#"SELECT "foo"."bars"."baz" FROM "foo"."bars" -- binds: []"#;
373 assert_eq!(
374 expected_sql,
375 &crate::debug_query::<Pg, _>(&bars::table.select(bars::baz)).to_string()
376 );
377 }
378
379 table! {
380 use crate::sql_types;
381 use crate::sql_types::*;
382
383 table_with_arbitrarily_complex_types {
384 id -> sql_types::Integer,
385 qualified_nullable -> sql_types::Nullable<sql_types::Integer>,
386 deeply_nested_type -> Nullable<Nullable<Integer>>,
387 }
392 }
393
394 table!(
395 foo {
396 id -> Integer,
398
399 #[sql_name = "type"]
400 mytype -> Integer,
402
403 #[sql_name = "bleh"]
405 hey -> Integer,
406 }
407 );
408
409 #[diesel_test_helper::test]
410 #[cfg(feature = "postgres")]
411 fn table_with_column_renaming_postgres() {
412 use crate::pg::Pg;
413 let expected_sql = r#"SELECT "foo"."id", "foo"."type", "foo"."bleh" FROM "foo" WHERE ("foo"."type" = $1) -- binds: [1]"#;
414 assert_eq!(
415 expected_sql,
416 crate::debug_query::<Pg, _>(&foo::table.filter(foo::mytype.eq(1))).to_string()
417 );
418 }
419
420 #[diesel_test_helper::test]
421 #[cfg(feature = "mysql")]
422 fn table_with_column_renaming_mysql() {
423 use crate::mysql::Mysql;
424 let expected_sql = r#"SELECT `foo`.`id`, `foo`.`type`, `foo`.`bleh` FROM `foo` WHERE (`foo`.`type` = ?) -- binds: [1]"#;
425 assert_eq!(
426 expected_sql,
427 crate::debug_query::<Mysql, _>(&foo::table.filter(foo::mytype.eq(1))).to_string()
428 );
429 }
430
431 #[diesel_test_helper::test]
432 #[cfg(feature = "sqlite")]
433 fn table_with_column_renaming_sqlite() {
434 use crate::sqlite::Sqlite;
435 let expected_sql = r#"SELECT `foo`.`id`, `foo`.`type`, `foo`.`bleh` FROM `foo` WHERE (`foo`.`type` = ?) -- binds: [1]"#;
436 assert_eq!(
437 expected_sql,
438 crate::debug_query::<Sqlite, _>(&foo::table.filter(foo::mytype.eq(1))).to_string()
439 );
440 }
441
442 table!(
443 use crate::sql_types::*;
444
445 #[sql_name="mod"]
447 bar {
449 id -> Integer,
450 }
451 );
452
453 #[diesel_test_helper::test]
454 #[cfg(feature = "postgres")]
455 fn table_renaming_postgres() {
456 use crate::pg::Pg;
457 let expected_sql = r#"SELECT "mod"."id" FROM "mod" -- binds: []"#;
458 assert_eq!(
459 expected_sql,
460 crate::debug_query::<Pg, _>(&bar::table.select(bar::id)).to_string()
461 );
462 }
463
464 #[diesel_test_helper::test]
465 #[cfg(feature = "mysql")]
466 fn table_renaming_mysql() {
467 use crate::mysql::Mysql;
468 let expected_sql = r#"SELECT `mod`.`id` FROM `mod` -- binds: []"#;
469 assert_eq!(
470 expected_sql,
471 crate::debug_query::<Mysql, _>(&bar::table.select(bar::id)).to_string()
472 );
473 }
474
475 #[diesel_test_helper::test]
476 #[cfg(feature = "sqlite")]
477 fn table_renaming_sqlite() {
478 use crate::sqlite::Sqlite;
479 let expected_sql = r#"SELECT `mod`.`id` FROM `mod` -- binds: []"#;
480 assert_eq!(
481 expected_sql,
482 crate::debug_query::<Sqlite, _>(&bar::table.select(bar::id)).to_string()
483 );
484 }
485
486 mod tests_for_allow_combined_group_by_syntax {
487 use crate::table;
488
489 table! {
490 a(b) {
491 b -> Text,
492 c -> Text,
493 d -> Text,
494 e -> Text,
495 }
496 }
497
498 table! {
499 b(a) {
500 a -> Text,
501 c -> Text,
502 d -> Text,
503 }
504 }
505
506 table! {
507 c(a) {
508 a -> Text,
509 b -> Text,
510 d -> Text,
511 }
512 }
513
514 allow_columns_to_appear_in_same_group_by_clause!(a::b, b::a, a::d,);
516
517 allow_columns_to_appear_in_same_group_by_clause!(self::a::c, self::b::c, self::b::d,);
519
520 use self::a::d as a_d;
521 use self::b::d as b_d;
522 use self::c::d as c_d;
523
524 allow_columns_to_appear_in_same_group_by_clause!(a_d, b_d, c_d);
526
527 allow_columns_to_appear_in_same_group_by_clause!(c_d, self::b::a, a::e,);
529 }
530}