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}