diesel/macros/
mod.rs

1#![cfg_attr(rustfmt, rustfmt_skip)] // https://github.com/rust-lang-nursery/rustfmt/issues/2755
2
3#[macro_export]
4#[doc(hidden)]
5macro_rules! __diesel_column {
6    (
7        table = $table:ident,
8        name = $column_name:ident,
9        sql_name = $sql_name:expr,
10        ty = ($($Type:tt)*),
11        meta = [$($meta:tt)*],
12    ) => {
13        $($meta)*
14        #[allow(non_camel_case_types, dead_code)]
15        #[derive(Debug, Clone, Copy, QueryId, Default)]
16        pub struct $column_name;
17
18        impl $crate::expression::Expression for $column_name {
19            type SqlType = $($Type)*;
20        }
21
22        impl<DB> $crate::query_builder::QueryFragment<DB> for $column_name where
23            DB: $crate::backend::Backend,
24            <$table as QuerySource>::FromClause: QueryFragment<DB>,
25        {
26            fn walk_ast(&self, mut out: $crate::query_builder::AstPass<DB>) -> $crate::result::QueryResult<()> {
27                $table.from_clause().walk_ast(out.reborrow())?;
28                out.push_sql(".");
29                out.push_identifier($sql_name)
30            }
31        }
32
33        impl SelectableExpression<$table> for $column_name {
34        }
35
36        impl<QS> AppearsOnTable<QS> for $column_name where
37            QS: AppearsInFromClause<$table, Count=Once>,
38        {
39        }
40
41        impl<Left, Right> SelectableExpression<
42            Join<Left, Right, LeftOuter>,
43        > for $column_name where
44            $column_name: AppearsOnTable<Join<Left, Right, LeftOuter>>,
45            Left: AppearsInFromClause<$table, Count=Once>,
46            Right: AppearsInFromClause<$table, Count=Never>,
47        {
48        }
49
50        impl<Left, Right> SelectableExpression<
51            Join<Left, Right, Inner>,
52        > for $column_name where
53            $column_name: AppearsOnTable<Join<Left, Right, Inner>>,
54            Join<Left, Right, Inner>: AppearsInFromClause<$table, Count=Once>,
55        {
56        }
57
58        // FIXME: Remove this when overlapping marker traits are stable
59        impl<Join, On> SelectableExpression<JoinOn<Join, On>> for $column_name where
60            $column_name: SelectableExpression<Join> + AppearsOnTable<JoinOn<Join, On>>,
61        {
62        }
63
64        // FIXME: Remove this when overlapping marker traits are stable
65        impl<From> SelectableExpression<SelectStatement<From>> for $column_name where
66            $column_name: SelectableExpression<From> + AppearsOnTable<SelectStatement<From>>,
67        {
68        }
69
70        impl $crate::expression::NonAggregate for $column_name {}
71
72        impl $crate::query_source::Column for $column_name {
73            type Table = $table;
74
75            const NAME: &'static str = $sql_name;
76        }
77
78        impl<T> $crate::EqAll<T> for $column_name where
79            T: $crate::expression::AsExpression<$($Type)*>,
80            $crate::dsl::Eq<$column_name, T>: $crate::Expression<SqlType=$crate::sql_types::Bool>,
81        {
82            type Output = $crate::dsl::Eq<Self, T>;
83
84            fn eq_all(self, rhs: T) -> Self::Output {
85                $crate::expression::operators::Eq::new(self, rhs.as_expression())
86            }
87        }
88
89        __diesel_generate_ops_impls_if_numeric!($column_name, $($Type)*);
90        __diesel_generate_ops_impls_if_date_time!($column_name, $($Type)*);
91    }
92}
93
94/// Specifies that a table exists, and what columns it has. This will create a
95/// new public module, with the same name, as the name of the table. In this
96/// module, you'll find a unit struct named `table`, and a unit struct with the
97/// names of each of the columns.
98///
99/// By default this allows a maximum of 32 columns per table.
100/// You can increase this limit to 64 by enabling the `64-column-tables` feature.
101/// You can increase it to 128 by enabling the `128-column-tables` feature.
102/// You can decrease it to 16 columns,
103/// which improves compilation time,
104/// by disabling the default features of Diesel.
105/// Note that enabling 64 column tables or larger will substantially increase
106/// the compile time of Diesel.
107///
108/// Example usage
109/// -------------
110///
111/// ```rust
112/// # #[macro_use] extern crate diesel;
113/// table! {
114///     users {
115///         id -> Integer,
116///         name -> VarChar,
117///         favorite_color -> Nullable<VarChar>,
118///     }
119/// }
120/// # fn main() {}
121/// ```
122///
123/// You may also specify a primary key if it's called something other than `id`.
124/// Tables with no primary key are not supported.
125///
126/// ```rust
127/// # #[macro_use] extern crate diesel;
128/// table! {
129///     users (non_standard_primary_key) {
130///         non_standard_primary_key -> Integer,
131///         name -> VarChar,
132///         favorite_color -> Nullable<VarChar>,
133///     }
134/// }
135/// # fn main() {}
136/// ```
137///
138/// For tables with composite primary keys, list all of the columns in the
139/// primary key.
140///
141/// ```rust
142/// # #[macro_use] extern crate diesel;
143/// table! {
144///     followings (user_id, post_id) {
145///         user_id -> Integer,
146///         post_id -> Integer,
147///         favorited -> Bool,
148///     }
149/// }
150/// # fn main() {
151/// #     use diesel::prelude::*;
152/// #     use self::followings::dsl::*;
153/// #     // Poor man's assert_eq! -- since this is type level this would fail
154/// #     // to compile if the wrong primary key were generated
155/// #     let (user_id {}, post_id {}) = followings.primary_key();
156/// # }
157/// ```
158///
159/// If you are using types that aren't from Diesel's core types, you can specify
160/// which types to import.
161///
162/// ```
163/// #[macro_use] extern crate diesel;
164/// # /*
165/// extern crate diesel_full_text_search;
166/// # */
167/// # mod diesel_full_text_search {
168/// #     pub struct TsVector;
169/// # }
170///
171/// table! {
172///     use diesel::sql_types::*;
173///     use diesel_full_text_search::*;
174///
175///     posts {
176///         id -> Integer,
177///         title -> Text,
178///         keywords -> TsVector,
179///     }
180/// }
181/// # fn main() {}
182/// ```
183///
184/// If you want to add documentation to the generated code you can use the
185/// following syntax:
186///
187/// ```
188/// #[macro_use] extern crate diesel;
189///
190/// table! {
191///
192///     /// The table containing all blog posts
193///     posts {
194///         /// The post's unique id
195///         id -> Integer,
196///         /// The post's title
197///         title -> Text,
198///     }
199/// }
200/// # fn main() {}
201/// ```
202///
203/// If you have a column with the same name as a Rust reserved keyword, you can use
204/// the `sql_name` attribute like this:
205///
206/// ```
207/// #[macro_use] extern crate diesel;
208///
209/// table! {
210///     posts {
211///         id -> Integer,
212///         /// This column is named `mytype` but references the table `type` column.
213///         #[sql_name = "type"]
214///         mytype -> Text,
215///     }
216/// }
217/// # fn main() {}
218/// ```
219///
220/// This module will also contain several helper types:
221///
222/// dsl
223/// ---
224///
225/// This simply re-exports the table, renamed to the same name as the module,
226/// and each of the columns. This is useful to glob import when you're dealing
227/// primarily with one table, to allow writing `users.filter(name.eq("Sean"))`
228/// instead of `users::table.filter(users::name.eq("Sean"))`.
229///
230/// `all_columns`
231/// -----------
232///
233/// A constant will be assigned called `all_columns`. This is what will be
234/// selected if you don't otherwise specify a select clause. It's type will be
235/// `table::AllColumns`. You can also get this value from the
236/// `Table::all_columns` function.
237///
238/// star
239/// ----
240///
241/// This will be the qualified "star" expression for this table (e.g.
242/// `users.*`). Internally, we read columns by index, not by name, so this
243/// column is not safe to read data out of, and it has had it's SQL type set to
244/// `()` to prevent accidentally using it as such. It is sometimes useful for
245/// count statements however. It can also be accessed through the `Table.star()`
246/// method.
247///
248/// `SqlType`
249/// -------
250///
251/// A type alias called `SqlType` will be created. It will be the SQL type of
252/// `all_columns`. The SQL type is needed for things like [returning boxed
253/// queries][boxed_queries].
254///
255/// [boxed_queries]: query_dsl/trait.QueryDsl.html#method.into_boxed
256///
257/// `BoxedQuery`
258/// ----------
259///
260/// ```ignore
261/// pub type BoxedQuery<'a, DB, ST = SqlType> = BoxedSelectStatement<'a, ST, table, DB>;
262/// ```
263#[macro_export]
264macro_rules! table {
265    ($($tokens:tt)*) => {
266        __diesel_parse_table! {
267            tokens = [$($tokens)*],
268            imports = [],
269            meta = [],
270            sql_name = unknown,
271            name = unknown,
272            schema = public,
273            primary_key = (id),
274        }
275    }
276}
277
278#[macro_export]
279#[doc(hidden)]
280macro_rules! __diesel_invalid_table_syntax {
281    () => {
282        compile_error!(
283            "Invalid `table!` syntax. Please see the `table!` macro docs for more info."
284        );
285    };
286}
287
288#[macro_export]
289#[doc(hidden)]
290macro_rules! __diesel_parse_table {
291    // Found an import
292    (
293        tokens = [use $($import:tt)::+; $($rest:tt)*],
294        imports = [$($imports:tt)*],
295        $($args:tt)*
296    ) => {
297        __diesel_parse_table! {
298            tokens = [$($rest)*],
299            imports = [$($imports)* use $($import)::+;],
300            $($args)*
301        }
302    };
303
304    // Found sql_name attribute, override whatever we had before
305    (
306        tokens = [#[sql_name = $sql_name:expr] $($rest:tt)*],
307        imports = $imports:tt,
308        meta = $meta:tt,
309        sql_name = $ignore:tt,
310        $($args:tt)*
311    ) => {
312        __diesel_parse_table! {
313            tokens = [$($rest)*],
314            imports = $imports,
315            meta = $meta,
316            sql_name = $sql_name,
317            $($args)*
318        }
319    };
320
321    // Meta item other than sql_name, attach it to the table struct
322    (
323        tokens = [#$new_meta:tt $($rest:tt)*],
324        imports = $imports:tt,
325        meta = [$($meta:tt)*],
326        $($args:tt)*
327    ) => {
328        __diesel_parse_table! {
329            tokens = [$($rest)*],
330            imports = $imports,
331            meta = [$($meta)* #$new_meta],
332            $($args)*
333        }
334    };
335
336    // Found a schema name, override whatever we had before
337    (
338        tokens = [$schema:ident . $($rest:tt)*],
339        imports = $imports:tt,
340        meta = $meta:tt,
341        sql_name = $sql_name:tt,
342        name = $name:tt,
343        schema = $ignore:tt,
344        $($args:tt)*
345    ) => {
346        __diesel_parse_table! {
347            tokens = [$($rest)*],
348            imports = $imports,
349            meta = $meta,
350            sql_name = $sql_name,
351            name = $name,
352            schema = $schema,
353            $($args)*
354        }
355    };
356
357    // Found a table name, override whatever we had before
358    (
359        tokens = [$name:ident $($rest:tt)*],
360        imports = $imports:tt,
361        meta = $meta:tt,
362        sql_name = $sql_name:tt,
363        name = $ignore:tt,
364        $($args:tt)*
365    ) => {
366        __diesel_parse_table! {
367            tokens = [$($rest)*],
368            imports = $imports,
369            meta = $meta,
370            sql_name = $sql_name,
371            name = $name,
372            $($args)*
373        }
374    };
375
376    // Found a primary key, override whatever we had before
377    (
378        tokens = [($($pk:ident),+ $(,)*) $($rest:tt)*],
379        imports = $imports:tt,
380        meta = $meta:tt,
381        sql_name = $sql_name:tt,
382        name = $name:tt,
383        schema = $schema:tt,
384        primary_key = $ignore:tt,
385        $($args:tt)*
386    ) => {
387        __diesel_parse_table! {
388            tokens = [$($rest)*],
389            imports = $imports,
390            meta = $meta,
391            sql_name = $sql_name,
392            name = $name,
393            schema = $schema,
394            primary_key = ($($pk),+),
395            $($args)*
396        }
397    };
398
399    // Reached columns with no imports, set a default
400    (
401        tokens = [{$($columns:tt)*}],
402        imports = [],
403        $($args:tt)*
404    ) => {
405        __diesel_parse_table! {
406            tokens = [{$($columns)*}],
407            imports = [use $crate::sql_types::*;],
408            $($args)*
409        }
410    };
411
412    // Reached columns with no sql_name, set a default
413    (
414        tokens = [{$($columns:tt)*}],
415        imports = $imports:tt,
416        meta = $meta:tt,
417        sql_name = unknown,
418        name = $name:tt,
419        $($args:tt)*
420    ) => {
421        __diesel_parse_table! {
422            tokens = [{$($columns)*}],
423            imports = $imports,
424            meta = $meta,
425            sql_name = stringify!($name),
426            name = $name,
427            $($args)*
428        }
429    };
430
431    // Parse the columns
432    (
433        tokens = [{$($columns:tt)*}],
434        $($args:tt)*
435    ) => {
436        __diesel_parse_columns! {
437            tokens = [$($columns)*],
438            table = { $($args)* },
439            columns = [],
440        }
441    };
442
443    // Invalid syntax
444    ($($tokens:tt)*) => {
445        __diesel_invalid_table_syntax!();
446    }
447}
448
449#[macro_export]
450#[doc(hidden)]
451macro_rules! __diesel_parse_columns {
452    // No column being parsed, start a new one.
453    // Attempt to capture the type as separate tokens if at all possible.
454    (
455        tokens = [
456            $(#$meta:tt)*
457            $name:ident -> $($ty:tt)::* $(<$($ty_params:tt)::*>)*,
458            $($rest:tt)*
459        ],
460        $($args:tt)*
461    ) => {
462        __diesel_parse_columns! {
463            current_column = {
464                unchecked_meta = [$(#$meta)*],
465                name = $name,
466                sql_name = stringify!($name),
467                ty = ($($ty)::* $(<$($ty_params)::*>)*),
468                meta = [],
469            },
470            tokens = [$($rest)*],
471            $($args)*
472        }
473    };
474
475    // No column being parsed, start a new one. Couldn't keep the `ty` separate.
476    (
477        tokens = [
478            $(#$meta:tt)*
479            $name:ident -> $ty:ty,
480            $($rest:tt)*
481        ],
482        $($args:tt)*
483    ) => {
484        __diesel_parse_columns! {
485            current_column = {
486                unchecked_meta = [$(#$meta)*],
487                name = $name,
488                sql_name = stringify!($name),
489                ty = ($ty),
490                meta = [],
491            },
492            tokens = [$($rest)*],
493            $($args)*
494        }
495    };
496
497
498    // Found #[sql_name]
499    (
500        current_column = {
501            unchecked_meta = [#[sql_name = $sql_name:expr] $($meta:tt)*],
502            name = $name:tt,
503            sql_name = $ignore:expr,
504            $($current_column:tt)*
505        },
506        $($args:tt)*
507    ) => {
508        __diesel_parse_columns! {
509            current_column = {
510                unchecked_meta = [$($meta)*],
511                name = $name,
512                sql_name = $sql_name,
513                $($current_column)*
514            },
515            $($args)*
516        }
517    };
518
519    // Meta item other than #[sql_name]
520    (
521        current_column = {
522            unchecked_meta = [#$new_meta:tt $($unchecked_meta:tt)*],
523            name = $name:tt,
524            sql_name = $sql_name:expr,
525            ty = $ty:tt,
526            meta = [$($meta:tt)*],
527            $($current_column:tt)*
528        },
529        $($args:tt)*
530    ) => {
531        __diesel_parse_columns! {
532            current_column = {
533                unchecked_meta = [$($unchecked_meta)*],
534                name = $name,
535                sql_name = $sql_name,
536                ty = $ty,
537                meta = [$($meta)* #$new_meta],
538                $($current_column)*
539            },
540            $($args)*
541        }
542    };
543
544    // Done parsing this column
545    (
546        current_column = {
547            unchecked_meta = [],
548            $($current_column:tt)*
549        },
550        tokens = $tokens:tt,
551        table = $table:tt,
552        columns = [$($columns:tt,)*],
553        $($args:tt)*
554    ) => {
555        __diesel_parse_columns! {
556            tokens = $tokens,
557            table = $table,
558            columns = [$($columns,)* { $($current_column)* },],
559            $($args)*
560        }
561    };
562
563    // Done parsing all columns
564    (
565        tokens = [],
566        $($args:tt)*
567    ) => {
568        __diesel_table_impl!($($args)*);
569    };
570
571    // Invalid syntax
572    ($($tokens:tt)*) => {
573        __diesel_invalid_table_syntax!();
574    }
575}
576
577#[macro_export]
578#[doc(hidden)]
579macro_rules! __diesel_table_impl {
580    (
581        table = {
582            imports = [$($imports:tt)*],
583            meta = [$($meta:tt)*],
584            sql_name = $sql_name:expr,
585            name = $table_name:ident,
586            schema = $schema:ident,
587            primary_key = $primary_key:tt,
588        },
589        columns = [$({
590            name = $column_name:ident,
591            sql_name = $column_sql_name:expr,
592            ty = ($($column_ty:tt)*),
593            $($column:tt)*
594        },)+],
595    ) => {
596        $($meta)*
597        pub mod $table_name {
598            #![allow(dead_code)]
599            use $crate::{
600                QuerySource,
601                Table,
602                JoinTo,
603            };
604            use $crate::associations::HasTable;
605            use $crate::insertable::Insertable;
606            use $crate::query_builder::*;
607            use $crate::query_builder::nodes::Identifier;
608            use $crate::query_source::{AppearsInFromClause, Once, Never};
609            use $crate::query_source::joins::{Join, JoinOn};
610            $($imports)*
611            pub use self::columns::*;
612
613            /// Re-exports all of the columns of this table, as well as the
614            /// table struct renamed to the module name. This is meant to be
615            /// glob imported for functions which only deal with one table.
616            pub mod dsl {
617                $(static_cond! {
618                    if $table_name == $column_name {
619                        compile_error!(concat!(
620                            "Column `",
621                            stringify!($column_name),
622                            "` cannot be named the same as its table.\n \
623                            You may use `#[sql_name = \"",
624                            stringify!($column_name),
625                            "\"]` to reference the table's `",
626                            stringify!($column_name),
627                            "` column. \n \
628                            See the documentation of the `table!` macro for details`\n"
629                        ));
630                    } else {
631                        pub use super::columns::{$column_name};
632                    }
633                })+
634                pub use super::table as $table_name;
635            }
636
637            #[allow(non_upper_case_globals, dead_code)]
638            /// A tuple of all of the columns on this table
639            pub const all_columns: ($($column_name,)+) = ($($column_name,)+);
640
641            #[allow(non_camel_case_types)]
642            #[derive(Debug, Clone, Copy, QueryId)]
643            /// The actual table struct
644            ///
645            /// This is the type which provides the base methods of the query
646            /// builder, such as `.select` and `.filter`.
647            pub struct table;
648
649            impl table {
650                #[allow(dead_code)]
651                /// Represents `table_name.*`, which is sometimes necessary
652                /// for efficient count queries. It cannot be used in place of
653                /// `all_columns`
654                pub fn star(&self) -> star {
655                    star
656                }
657            }
658
659            /// The SQL type of all of the columns on this table
660            pub type SqlType = ($($($column_ty)*,)+);
661
662            /// Helper type for representing a boxed query from this table
663            pub type BoxedQuery<'a, DB, ST = SqlType> = BoxedSelectStatement<'a, ST, table, DB>;
664
665            __diesel_table_query_source_impl!(table, $schema, $sql_name);
666
667            impl AsQuery for table {
668                type SqlType = SqlType;
669                type Query = SelectStatement<Self>;
670
671                fn as_query(self) -> Self::Query {
672                    SelectStatement::simple(self)
673                }
674            }
675
676            impl Table for table {
677                type PrimaryKey = $primary_key;
678                type AllColumns = ($($column_name,)+);
679
680                fn primary_key(&self) -> Self::PrimaryKey {
681                    $primary_key
682                }
683
684                fn all_columns() -> Self::AllColumns {
685                    ($($column_name,)+)
686                }
687            }
688
689            impl HasTable for table {
690                type Table = Self;
691
692                fn table() -> Self::Table {
693                    table
694                }
695            }
696
697            impl IntoUpdateTarget for table {
698                type WhereClause = <<Self as AsQuery>::Query as IntoUpdateTarget>::WhereClause;
699
700                fn into_update_target(self) -> UpdateTarget<Self::Table, Self::WhereClause> {
701                    self.as_query().into_update_target()
702                }
703            }
704
705            impl AppearsInFromClause<table> for table {
706                type Count = Once;
707            }
708
709            impl AppearsInFromClause<table> for () {
710                type Count = Never;
711            }
712
713            impl<Left, Right, Kind> JoinTo<Join<Left, Right, Kind>> for table where
714                Join<Left, Right, Kind>: JoinTo<table>,
715            {
716                type FromClause = Join<Left, Right, Kind>;
717                type OnClause = <Join<Left, Right, Kind> as JoinTo<table>>::OnClause;
718
719                fn join_target(rhs: Join<Left, Right, Kind>) -> (Self::FromClause, Self::OnClause) {
720                    let (_, on_clause) = Join::join_target(table);
721                    (rhs, on_clause)
722                }
723            }
724
725            impl<Join, On> JoinTo<JoinOn<Join, On>> for table where
726                JoinOn<Join, On>: JoinTo<table>,
727            {
728                type FromClause = JoinOn<Join, On>;
729                type OnClause = <JoinOn<Join, On> as JoinTo<table>>::OnClause;
730
731                fn join_target(rhs: JoinOn<Join, On>) -> (Self::FromClause, Self::OnClause) {
732                    let (_, on_clause) = JoinOn::join_target(table);
733                    (rhs, on_clause)
734                }
735            }
736
737            impl<F, S, D, W, O, L, Of, G> JoinTo<SelectStatement<F, S, D, W, O, L, Of, G>> for table where
738                SelectStatement<F, S, D, W, O, L, Of, G>: JoinTo<table>,
739            {
740                type FromClause = SelectStatement<F, S, D, W, O, L, Of, G>;
741                type OnClause = <SelectStatement<F, S, D, W, O, L, Of, G> as JoinTo<table>>::OnClause;
742
743                fn join_target(rhs: SelectStatement<F, S, D, W, O, L, Of, G>) -> (Self::FromClause, Self::OnClause) {
744                    let (_, on_clause) = SelectStatement::join_target(table);
745                    (rhs, on_clause)
746                }
747            }
748
749            impl<'a, QS, ST, DB> JoinTo<BoxedSelectStatement<'a, QS, ST, DB>> for table where
750                BoxedSelectStatement<'a, QS, ST, DB>: JoinTo<table>,
751            {
752                type FromClause = BoxedSelectStatement<'a, QS, ST, DB>;
753                type OnClause = <BoxedSelectStatement<'a, QS, ST, DB> as JoinTo<table>>::OnClause;
754                fn join_target(rhs: BoxedSelectStatement<'a, QS, ST, DB>) -> (Self::FromClause, Self::OnClause) {
755                    let (_, on_clause) = BoxedSelectStatement::join_target(table);
756                    (rhs, on_clause)
757                }
758            }
759
760            // This impl should be able to live in Diesel,
761            // but Rust tries to recurse for no reason
762            impl<T> Insertable<T> for table
763            where
764                <table as AsQuery>::Query: Insertable<T>,
765            {
766                type Values = <<table as AsQuery>::Query as Insertable<T>>::Values;
767
768                fn values(self) -> Self::Values {
769                    self.as_query().values()
770                }
771            }
772
773            impl<'a, T> Insertable<T> for &'a table
774            where
775                table: Insertable<T>,
776            {
777                type Values = <table as Insertable<T>>::Values;
778
779                fn values(self) -> Self::Values {
780                    (*self).values()
781                }
782            }
783
784            /// Contains all of the columns of this table
785            pub mod columns {
786                use super::table;
787                use $crate::{Expression, SelectableExpression, AppearsOnTable, QuerySource};
788                use $crate::backend::Backend;
789                use $crate::query_builder::{QueryFragment, AstPass, SelectStatement};
790                use $crate::query_source::joins::{Join, JoinOn, Inner, LeftOuter};
791                use $crate::query_source::{AppearsInFromClause, Once, Never};
792                use $crate::result::QueryResult;
793                $($imports)*
794
795                #[allow(non_camel_case_types, dead_code)]
796                #[derive(Debug, Clone, Copy)]
797                /// Represents `table_name.*`, which is sometimes needed for
798                /// efficient count queries. It cannot be used in place of
799                /// `all_columns`, and has a `SqlType` of `()` to prevent it
800                /// being used that way
801                pub struct star;
802
803                impl Expression for star {
804                    type SqlType = ();
805                }
806
807                impl<DB: Backend> QueryFragment<DB> for star where
808                    <table as QuerySource>::FromClause: QueryFragment<DB>,
809                {
810                    fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
811                        table.from_clause().walk_ast(out.reborrow())?;
812                        out.push_sql(".*");
813                        Ok(())
814                    }
815                }
816
817                impl SelectableExpression<table> for star {
818                }
819
820                impl AppearsOnTable<table> for star {
821                }
822
823                $(__diesel_column! {
824                    table = table,
825                    name = $column_name,
826                    sql_name = $column_sql_name,
827                    ty = ($($column_ty)*),
828                    $($column)*
829                })+
830            }
831        }
832    }
833}
834
835#[macro_export]
836#[doc(hidden)]
837macro_rules! __diesel_table_query_source_impl {
838    ($table_struct:ident, public, $table_name:expr) => {
839        impl QuerySource for $table_struct {
840            type FromClause = Identifier<'static>;
841            type DefaultSelection = <Self as Table>::AllColumns;
842
843            fn from_clause(&self) -> Self::FromClause {
844                Identifier($table_name)
845            }
846
847            fn default_selection(&self) -> Self::DefaultSelection {
848                Self::all_columns()
849            }
850        }
851    };
852
853    ($table_struct:ident, $schema_name:ident, $table_name:expr) => {
854        impl QuerySource for $table_struct {
855            type FromClause = $crate::query_builder::nodes::InfixNode<
856                'static,
857                Identifier<'static>,
858                Identifier<'static>,
859            >;
860            type DefaultSelection = <Self as Table>::AllColumns;
861
862            fn from_clause(&self) -> Self::FromClause {
863                $crate::query_builder::nodes::InfixNode::new(
864                    Identifier(stringify!($schema_name)),
865                    Identifier($table_name),
866                    ".",
867                )
868            }
869
870            fn default_selection(&self) -> Self::DefaultSelection {
871                Self::all_columns()
872            }
873        }
874    };
875}
876
877/// Allow two tables to be referenced in a join query without providing an
878/// explicit `ON` clause.
879///
880/// The generated `ON` clause will always join to the primary key of the parent
881/// table. This macro removes the need to call [`.on`] explicitly, you will
882/// still need to invoke [`allow_tables_to_appear_in_same_query!`] for these two tables to
883/// be able to use the resulting query, unless you are using `infer_schema!` or
884/// `diesel print-schema` which will generate it for you.
885///
886/// If you are using `infer_schema!` or `diesel print-schema`, an invocation of
887/// this macro will be generated for every foreign key in your database unless
888/// one of the following is true:
889///
890/// - The foreign key references something other than the primary key
891/// - The foreign key is composite
892/// - There is more than one foreign key connecting two tables
893/// - The foreign key is self-referential
894///
895/// # Example
896///
897/// ```rust
898/// # #[macro_use] extern crate diesel;
899/// # include!("../doctest_setup.rs");
900/// use schema::*;
901///
902/// # /*
903/// joinable!(posts -> users (user_id));
904/// allow_tables_to_appear_in_same_query!(posts, users);
905/// # */
906///
907/// # fn main() {
908/// let implicit_on_clause = users::table.inner_join(posts::table);
909/// let implicit_on_clause_sql = diesel::debug_query::<DB, _>(&implicit_on_clause).to_string();
910///
911/// let explicit_on_clause = users::table
912///     .inner_join(posts::table.on(posts::user_id.eq(users::id)));
913/// let explicit_on_clause_sql = diesel::debug_query::<DB, _>(&explicit_on_clause).to_string();
914///
915/// assert_eq!(implicit_on_clause_sql, explicit_on_clause_sql);
916/// # }
917///
918/// ```
919///
920/// In the example above, the line `joinable!(posts -> users (user_id));`
921///
922/// specifies the relation of the tables and the ON clause in the following way:
923///
924/// `child_table -> parent_table (foreign_key)`
925///
926/// * `parent_table` is the Table with the Primary key.
927///
928/// * `child_table` is the Table with the Foreign key.
929///
930/// So given the Table decaration from [Associations docs](/associations/index.html)
931///
932/// * The parent table would be `User`
933/// * The child table would be `Post`
934/// * and the Foreign key would be `Post.user_id`
935///
936/// For joins that do not explicitly use on clauses via [`JoinOnDsl`](/prelude/trait.JoinOnDsl.html)
937/// the following on clause is generated implicitly:
938/// ```sql
939/// post JOIN users ON posts.user_id = users.id
940/// ```
941#[macro_export]
942macro_rules! joinable {
943    ($($child:ident)::* -> $($parent:ident)::* ($source:ident)) => {
944        joinable_inner!($($child)::* ::table => $($parent)::* ::table : ($($child)::* ::$source = $($parent)::* ::table));
945        joinable_inner!($($parent)::* ::table => $($child)::* ::table : ($($child)::* ::$source = $($parent)::* ::table));
946    }
947}
948
949#[macro_export]
950#[doc(hidden)]
951macro_rules! joinable_inner {
952    ($left_table:path => $right_table:path : ($foreign_key:path = $parent_table:path)) => {
953        joinable_inner!(
954            left_table_ty = $left_table,
955            right_table_ty = $right_table,
956            right_table_expr = $right_table,
957            foreign_key = $foreign_key,
958            primary_key_ty = <$parent_table as $crate::query_source::Table>::PrimaryKey,
959            primary_key_expr =
960                <$parent_table as $crate::query_source::Table>::primary_key(&$parent_table),
961        );
962    };
963
964    (
965        left_table_ty = $left_table_ty:ty,
966        right_table_ty = $right_table_ty:ty,
967        right_table_expr = $right_table_expr:expr,
968        foreign_key = $foreign_key:path,
969        primary_key_ty = $primary_key_ty:ty,
970        primary_key_expr = $primary_key_expr:expr,
971    ) => {
972        impl $crate::JoinTo<$right_table_ty> for $left_table_ty {
973            type FromClause = $right_table_ty;
974            type OnClause = $crate::dsl::Eq<
975                $crate::expression::nullable::Nullable<$foreign_key>,
976                $crate::expression::nullable::Nullable<$primary_key_ty>,
977            >;
978
979            fn join_target(rhs: $right_table_ty) -> (Self::FromClause, Self::OnClause) {
980                use $crate::{ExpressionMethods, NullableExpressionMethods};
981
982                (
983                    rhs,
984                    $foreign_key.nullable().eq($primary_key_expr.nullable()),
985                )
986            }
987        }
988    };
989}
990
991/// Allow two or more tables which are otherwise unrelated to be used together
992/// in a query.
993///
994/// This macro must be invoked any time two tables need to appear in the same
995/// query either because they are being joined together, or because one appears
996/// in a subselect. When this macro is invoked with more than 2 tables, every
997/// combination of those tables will be allowed to appear together.
998///
999/// If you are using `infer_schema!` or `diesel print-schema`, an invocation of
1000/// this macro will be generated for you for all tables in your schema.
1001///
1002/// # Example
1003///
1004/// ```ignore
1005/// // This would be required to do `users.inner_join(posts.inner_join(comments))`
1006/// allow_tables_to_appear_in_same_query!(comments, posts, users);
1007/// ```
1008///
1009/// When more than two tables are passed, the relevant code is generated for
1010/// every combination of those tables. This code would be equivalent to the
1011/// previous example.
1012///
1013/// ```ignore
1014/// allow_tables_to_appear_in_same_query!(comments, posts);
1015/// allow_tables_to_appear_in_same_query!(comments, users);
1016/// allow_tables_to_appear_in_same_query!(posts, users);
1017/// ```
1018#[macro_export]
1019macro_rules! allow_tables_to_appear_in_same_query {
1020    ($left_mod:ident, $($right_mod:ident),+ $(,)*) => {
1021        $(
1022            impl $crate::query_source::AppearsInFromClause<$left_mod::table>
1023                for $right_mod::table
1024            {
1025                type Count = $crate::query_source::Never;
1026            }
1027
1028            impl $crate::query_source::AppearsInFromClause<$right_mod::table>
1029                for $left_mod::table
1030            {
1031                type Count = $crate::query_source::Never;
1032            }
1033        )+
1034        allow_tables_to_appear_in_same_query!($($right_mod,)+);
1035    };
1036
1037    ($last_table:ident,) => {};
1038
1039    () => {};
1040}
1041
1042/// Gets the value out of an option, or returns an error.
1043///
1044/// This is used by `FromSql` implementations.
1045#[macro_export]
1046macro_rules! not_none {
1047    ($bytes:expr) => {
1048        match $bytes {
1049            Some(bytes) => bytes,
1050            None => return Err(Box::new($crate::result::UnexpectedNullError)),
1051        }
1052    };
1053}
1054
1055// The order of these modules is important (at least for those which have tests).
1056// Utility macros which don't call any others need to come first.
1057#[macro_use]
1058mod internal;
1059#[macro_use]
1060mod query_id;
1061#[macro_use]
1062mod static_cond;
1063#[macro_use]
1064mod ops;
1065#[macro_use]
1066mod tuples;
1067
1068#[cfg(test)]
1069mod tests {
1070    use prelude::*;
1071
1072    table! {
1073        foo.bars {
1074            id -> Integer,
1075            baz -> Text,
1076        }
1077    }
1078
1079    mod my_types {
1080        #[derive(Debug, Clone, Copy)]
1081        pub struct MyCustomType;
1082    }
1083
1084    table! {
1085        use sql_types::*;
1086        use macros::tests::my_types::*;
1087
1088        table_with_custom_types {
1089            id -> Integer,
1090            my_type -> MyCustomType,
1091        }
1092    }
1093
1094    table! {
1095        use sql_types::*;
1096        use macros::tests::my_types::*;
1097
1098        /// Table documentation
1099        ///
1100        /// some in detail documentation
1101        table_with_custom_type_and_id (a) {
1102            /// Column documentation
1103            ///
1104            /// some more details
1105            a -> Integer,
1106            my_type -> MyCustomType,
1107        }
1108    }
1109
1110    #[test]
1111    #[cfg(feature = "postgres")]
1112    fn table_with_custom_schema() {
1113        use pg::Pg;
1114        let expected_sql = r#"SELECT "foo"."bars"."baz" FROM "foo"."bars" -- binds: []"#;
1115        assert_eq!(
1116            expected_sql,
1117            &::debug_query::<Pg, _>(&bars::table.select(bars::baz)).to_string()
1118        );
1119    }
1120
1121    table! {
1122        use sql_types;
1123        use sql_types::*;
1124
1125        table_with_arbitrarily_complex_types {
1126            id -> sql_types::Integer,
1127            qualified_nullable -> sql_types::Nullable<sql_types::Integer>,
1128            deeply_nested_type -> Option<Nullable<Integer>>,
1129            // This actually should work, but there appears to be a rustc bug
1130            // on the `AsExpression` bound for `EqAll` when the ty param is a projection
1131            // projected_type -> <Nullable<Integer> as sql_types::IntoNullable>::Nullable,
1132            random_tuple -> (Integer, Integer),
1133        }
1134    }
1135
1136    table!(
1137        foo {
1138            /// Column doc
1139            id -> Integer,
1140
1141            #[sql_name = "type"]
1142            /// Also important to document this column
1143            mytype -> Integer,
1144
1145            /// And this one
1146            #[sql_name = "bleh"]
1147            hey -> Integer,
1148        }
1149    );
1150
1151    #[test]
1152    #[cfg(feature = "postgres")]
1153    fn table_with_column_renaming_postgres() {
1154        use pg::Pg;
1155        let expected_sql =
1156            r#"SELECT "foo"."id", "foo"."type", "foo"."bleh" FROM "foo" WHERE "foo"."type" = $1 -- binds: [1]"#;
1157        assert_eq!(
1158            expected_sql,
1159            ::debug_query::<Pg, _>(&foo::table.filter(foo::mytype.eq(1))).to_string()
1160        );
1161    }
1162
1163    #[test]
1164    #[cfg(feature = "mysql")]
1165    fn table_with_column_renaming_mysql() {
1166        use mysql::Mysql;
1167        let expected_sql =
1168            r#"SELECT `foo`.`id`, `foo`.`type`, `foo`.`bleh` FROM `foo` WHERE `foo`.`type` = ? -- binds: [1]"#;
1169        assert_eq!(
1170            expected_sql,
1171            ::debug_query::<Mysql, _>(&foo::table.filter(foo::mytype.eq(1))).to_string()
1172        );
1173    }
1174
1175    #[test]
1176    #[cfg(feature = "sqlite")]
1177    fn table_with_column_renaming_sqlite() {
1178        use sqlite::Sqlite;
1179        let expected_sql =
1180            r#"SELECT `foo`.`id`, `foo`.`type`, `foo`.`bleh` FROM `foo` WHERE `foo`.`type` = ? -- binds: [1]"#;
1181        assert_eq!(
1182            expected_sql,
1183            ::debug_query::<Sqlite, _>(&foo::table.filter(foo::mytype.eq(1))).to_string()
1184        );
1185    }
1186
1187    table!(
1188        use sql_types::*;
1189
1190        /// Some documentation
1191        #[sql_name="mod"]
1192        /// Some more documentation
1193        bar {
1194            id -> Integer,
1195        }
1196    );
1197
1198    #[test]
1199    #[cfg(feature = "postgres")]
1200    fn table_renaming_postgres() {
1201        use pg::Pg;
1202        let expected_sql = r#"SELECT "mod"."id" FROM "mod" -- binds: []"#;
1203        assert_eq!(
1204            expected_sql,
1205            ::debug_query::<Pg, _>(&bar::table.select(bar::id)).to_string()
1206        );
1207    }
1208
1209    #[test]
1210    #[cfg(feature = "mysql")]
1211    fn table_renaming_mysql() {
1212        use mysql::Mysql;
1213        let expected_sql = r#"SELECT `mod`.`id` FROM `mod` -- binds: []"#;
1214        assert_eq!(
1215            expected_sql,
1216            ::debug_query::<Mysql, _>(&bar::table.select(bar::id)).to_string()
1217        );
1218    }
1219
1220    #[test]
1221    #[cfg(feature = "sqlite")]
1222    fn table_renaming_sqlite() {
1223        use sqlite::Sqlite;
1224        let expected_sql = r#"SELECT `mod`.`id` FROM `mod` -- binds: []"#;
1225        assert_eq!(
1226            expected_sql,
1227            ::debug_query::<Sqlite, _>(&bar::table.select(bar::id)).to_string()
1228        );
1229    }
1230}