sql_table/
table.rs

1pub trait Iden: core::fmt::Display + Clone + Copy {}
2impl<T> Iden for T where T: core::fmt::Display + Clone + Copy {}
3
4pub trait Table: Iden + Unquote {
5    type Unquoted: Table;
6    const UNQUOTED: Self::Unquoted;
7    const QUOTE: &'static str;
8}
9
10pub trait TableColumn: Iden + Unquote {
11    type Table: Table;
12    type Unquoted: TableColumn;
13    const TABLE: Self::Table;
14    const QUOTE: &'static str;
15}
16
17pub trait Unquote: Iden {
18    type Target: Iden;
19    fn unquoted(self) -> Self::Target;
20}
21
22#[macro_export]
23macro_rules! table {
24    (
25        $name:ident: $table_name:literal {
26            $($col:ident: $col_name:literal),+ $(,)?
27        } $(,)?
28    ) => {
29        table!($name: $table_name {
30            $($col: $col_name),+
31        }, quote: "");
32    };
33    (
34        $name:ident: $table_name:literal {
35            $($col:ident: $col_name:literal),+ $(,)?
36        }, quote: $q:literal $(,)?
37    ) => {
38
39        sql_table::paste::paste! {
40            #[derive(Debug, Clone, Copy)]
41            pub struct $name;
42
43            #[allow(non_upper_case_globals)]
44            impl $name {
45                $(
46                    const [<$col>]: [<$name Column>] = [<$name Column>]::$col;
47                )+
48            }
49
50            impl ::core::fmt::Display for $name {
51                fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
52                    f.write_str(&format!("{}{}{}", $q, $table_name, $q))
53                }
54            }
55
56            #[derive(Debug, Clone, Copy)]
57            pub enum [<$name Column>] {
58                $($col),+
59            }
60
61            impl ::core::fmt::Display for [<$name Column>] {
62                fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
63                    match self {
64                        $(
65                            Self::$col => f.write_str(&format!("{}{}{}", $q, $col_name, $q)),
66                        )+
67                    }
68                }
69            }
70
71            impl sql_table::table::TableColumn for [<$name Column>] {
72                type Table = $name;
73                type Unquoted = [<$name UnquotedColumn>];
74                const TABLE: $name = $name;
75                const QUOTE: &'static str = $q;
76            }
77
78            #[derive(Debug, Clone, Copy)]
79            pub struct [<Unquoted $name>];
80
81            #[allow(non_upper_case_globals)]
82            impl [<Unquoted $name>] {
83                $(
84                    const [<$col>]: [<Unquoted $name Column>] 
85                        = [<Unquoted $name Column>]::$col;
86                )+
87            }
88
89            impl ::core::fmt::Display for [<Unquoted $name>] {
90                fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
91                    f.write_str($table_name)
92                }
93            }
94
95            impl sql_table::table::Unquote for $name {
96                type Target = <Self as sql_table::table::Table>::Unquoted;
97                fn unquoted(self) -> Self::Target {
98                    [<Unquoted $name>]
99                }
100            }
101
102            impl sql_table::table::Table for $name {
103                type Unquoted = [<Unquoted $name>];
104                const UNQUOTED: Self::Unquoted = [<Unquoted $name>];
105                const QUOTE: &'static str = $q;
106            }
107
108            impl sql_table::table::Unquote for [<Unquoted $name>] {
109                type Target = <Self as sql_table::table::Table>::Unquoted;
110                fn unquoted(self) -> Self::Target {
111                    self
112                }
113            }
114
115            impl sql_table::table::Table for [<Unquoted $name>] {
116                type Unquoted = Self;
117                const UNQUOTED: Self::Unquoted = [<Unquoted $name>];
118                const QUOTE: &'static str = "";
119            }
120
121            #[derive(Debug, Clone, Copy)]
122            pub enum [<$name UnquotedColumn>] {
123                $($col),+
124            }
125
126            impl ::core::fmt::Display for [<$name UnquotedColumn>] {
127                fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
128                    match self {
129                        $(
130                            Self::$col => f.write_str($col_name),
131                        )+
132                    }
133                }
134            }
135
136            impl sql_table::table::TableColumn for [<$name UnquotedColumn>] {
137                type Table = [<$name>];
138                type Unquoted = Self;
139                const TABLE: [<$name>] = [<$name>];
140                const QUOTE: &'static str = "";
141            }
142
143            #[derive(Debug, Clone, Copy)]
144            pub enum [<Unquoted $name Column>] {
145                $($col),+
146            }
147
148            impl ::core::fmt::Display for [<Unquoted $name Column>] {
149                fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
150                    match self {
151                        $(
152                            Self::$col => f.write_str($col_name),
153                        )+
154                    }
155                }
156            }
157
158            impl sql_table::table::TableColumn for [<Unquoted $name Column>] {
159                type Table = [<Unquoted $name>];
160                type Unquoted = Self;
161                const TABLE: [<Unquoted $name>] = [<Unquoted $name>];
162                const QUOTE: &'static str = $q;
163            }
164
165            #[derive(Debug, Clone, Copy)]
166            pub enum [<Unquoted $name UnquotedColumn>] {
167                $($col),+
168            }
169
170            impl ::core::fmt::Display for [<Unquoted $name UnquotedColumn>] {
171                fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
172                    match self {
173                        $(
174                            Self::$col => f.write_str($col_name),
175                        )+
176                    }
177                }
178            }
179
180            impl sql_table::table::TableColumn for [<Unquoted $name UnquotedColumn>] {
181                type Table = [<Unquoted $name>];
182                type Unquoted = Self;
183                const TABLE: [<Unquoted $name>] = [<Unquoted $name>];
184                const QUOTE: &'static str = "";
185            }
186
187            impl sql_table::table::Unquote for [<$name Column>] {
188                type Target = [<$name UnquotedColumn>];
189                fn unquoted(self) -> [<$name UnquotedColumn>] {
190                    match self {
191                        $(
192                            Self::$col => Self::Target::$col,
193                        )+
194                    }
195                }
196            }
197
198            impl sql_table::table::Unquote for [<$name UnquotedColumn>] {
199                type Target = Self;
200                fn unquoted(self) -> Self {
201                    match self {
202                        $(
203                            Self::$col => Self::Target::$col,
204                        )+
205                    }
206                }
207            }
208
209            impl sql_table::table::Unquote for [<Unquoted $name Column>] {
210                type Target = [<Unquoted $name UnquotedColumn>];
211                fn unquoted(self) -> Self::Target {
212                    match self {
213                        $(
214                            Self::$col => Self::Target::$col,
215                        )+
216                    }
217                }
218            }
219
220            impl sql_table::table::Unquote for [<Unquoted $name UnquotedColumn>] {
221                type Target = Self;
222                fn unquoted(self) -> Self {
223                    match self {
224                        $(
225                            Self::$col => Self::Target::$col,
226                        )+
227                    }
228                }
229            }
230        }
231    };
232}