1use std::fmt::{self, Display, Formatter};
2
3use crate::postgres::general::{Column, Condition, Expression, TableName};
4use crate::tools::joined;
5
6use super::column_constraints::*;
7
8#[derive(Debug, Clone)]
9pub struct ColumnDefinition {
10 name: String,
11 type_: String,
12 constraints: Vec<ColumnConstraint>,
13}
14
15impl Display for ColumnDefinition {
16 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
17 write!(f, "{} {}", self.name, self.type_)?;
18
19 if !self.constraints.is_empty() {
20 write!(f, " {}", joined(&self.constraints, " "))?
21 }
22
23 Ok(())
24 }
25}
26
27impl<N, P, U, D, R, C> From<ColumnDefinitionBuilder<N, P, U, D, R, C>> for ColumnDefinition
28where
29 N: NullabilityConstraint,
30 P: PrimaryKeyConstraint,
31 U: UniqueConstraint,
32 D: DefaultConstraint,
33 R: ReferencesConstraint,
34 C: CheckConstraint,
35{
36 fn from(builder: ColumnDefinitionBuilder<N, P, U, D, R, C>) -> Self {
37 let mut constraints = Vec::new();
38
39 if let Some(constraint) = builder.nullability.into_column_constraint() {
40 constraints.push(constraint);
41 }
42
43 if let Some(constraint) = builder.primary_key.into_column_constraint() {
44 constraints.push(constraint);
45 }
46
47 if let Some(constraint) = builder.unique.into_column_constraint() {
48 constraints.push(constraint);
49 }
50
51 if let Some(constraint) = builder.default.into_column_constraint() {
52 constraints.push(constraint);
53 }
54
55 if let Some(constraint) = builder.references.into_column_constraint() {
56 constraints.push(constraint);
57 }
58
59 if let Some(constraint) = builder.check.into_column_constraint() {
60 constraints.push(constraint);
61 }
62
63 ColumnDefinition {
64 name: builder.name,
65 type_: builder.type_,
66 constraints,
67 }
68 }
69}
70
71impl<T, U> From<(T, U)> for ColumnDefinition
72where
73 T: Into<String>,
74 U: Into<String>,
75{
76 fn from((name, type_): (T, U)) -> Self {
77 ColumnDefinition {
78 name: name.into(),
79 type_: type_.into(),
80 constraints: Vec::new(),
81 }
82 }
83}
84
85#[derive(Debug)]
88pub struct ColumnDefinitionBuilder<
89 N = NoConstraint,
90 P = NoConstraint,
91 U = NoConstraint,
92 D = NoConstraint,
93 R = NoConstraint,
94 C = NoConstraint,
95> where
96 N: NullabilityConstraint,
97 P: PrimaryKeyConstraint,
98 U: UniqueConstraint,
99 D: DefaultConstraint,
100 R: ReferencesConstraint,
101 C: CheckConstraint,
102{
103 name: String,
104 type_: String,
105 nullability: N,
106 primary_key: P,
107 unique: U,
108 default: D,
109 references: R,
110 check: C,
111}
112
113impl ColumnDefinitionBuilder {
114 fn new(name: String, type_: String) -> ColumnDefinitionBuilder {
115 ColumnDefinitionBuilder {
116 name,
117 type_,
118 nullability: NoConstraint,
119 primary_key: NoConstraint,
120 unique: NoConstraint,
121 default: NoConstraint,
122 references: NoConstraint,
123 check: NoConstraint,
124 }
125 }
126}
127
128impl<P, U, D, R, C> ColumnDefinitionBuilder<NoConstraint, P, U, D, R, C>
129where
130 P: PrimaryKeyConstraint,
131 U: UniqueConstraint,
132 D: DefaultConstraint,
133 R: ReferencesConstraint,
134 C: CheckConstraint,
135{
136 pub fn null(self) -> ColumnDefinitionBuilder<IsNull, P, U, D, R, C> {
137 ColumnDefinitionBuilder {
138 name: self.name,
139 type_: self.type_,
140 nullability: IsNull,
141 primary_key: self.primary_key,
142 unique: self.unique,
143 default: self.default,
144 references: self.references,
145 check: self.check,
146 }
147 }
148
149 pub fn not_null(self) -> ColumnDefinitionBuilder<IsNotNull, P, U, D, R, C> {
150 ColumnDefinitionBuilder {
151 name: self.name,
152 type_: self.type_,
153 nullability: IsNotNull,
154 primary_key: self.primary_key,
155 unique: self.unique,
156 default: self.default,
157 references: self.references,
158 check: self.check,
159 }
160 }
161}
162
163impl<N, U, D, R, C> ColumnDefinitionBuilder<N, NoConstraint, U, D, R, C>
164where
165 N: NullabilityConstraint,
166 U: UniqueConstraint,
167 D: DefaultConstraint,
168 R: ReferencesConstraint,
169 C: CheckConstraint,
170{
171 pub fn primary_key(self) -> ColumnDefinitionBuilder<N, IsPrimaryKey, U, D, R, C> {
172 ColumnDefinitionBuilder {
173 name: self.name,
174 type_: self.type_,
175 nullability: self.nullability,
176 primary_key: IsPrimaryKey,
177 unique: self.unique,
178 default: self.default,
179 references: self.references,
180 check: self.check,
181 }
182 }
183}
184
185impl<N, P, D, R, C> ColumnDefinitionBuilder<N, P, NoConstraint, D, R, C>
186where
187 N: NullabilityConstraint,
188 P: PrimaryKeyConstraint,
189 D: DefaultConstraint,
190 R: ReferencesConstraint,
191 C: CheckConstraint,
192{
193 pub fn unique(self) -> ColumnDefinitionBuilder<N, P, IsUnique, D, R, C> {
194 ColumnDefinitionBuilder {
195 name: self.name,
196 type_: self.type_,
197 nullability: self.nullability,
198 primary_key: self.primary_key,
199 unique: IsUnique,
200 default: self.default,
201 references: self.references,
202 check: self.check,
203 }
204 }
205}
206
207impl<N, P, U, R, C> ColumnDefinitionBuilder<N, P, U, NoConstraint, R, C>
208where
209 N: NullabilityConstraint,
210 P: PrimaryKeyConstraint,
211 U: UniqueConstraint,
212 R: ReferencesConstraint,
213 C: CheckConstraint,
214{
215 pub fn default(
216 self,
217 expr: impl Into<Expression>,
218 ) -> ColumnDefinitionBuilder<N, P, U, HasDefault, R, C> {
219 ColumnDefinitionBuilder {
220 name: self.name,
221 type_: self.type_,
222 nullability: self.nullability,
223 primary_key: self.primary_key,
224 unique: self.unique,
225 default: HasDefault(expr.into()),
226 references: self.references,
227 check: self.check,
228 }
229 }
230}
231
232impl<N, P, U, D, C> ColumnDefinitionBuilder<N, P, U, D, NoConstraint, C>
233where
234 N: NullabilityConstraint,
235 P: PrimaryKeyConstraint,
236 U: UniqueConstraint,
237 D: DefaultConstraint,
238 C: CheckConstraint,
239{
240 pub fn references(
241 self,
242 table_name: impl Into<TableName>,
243 column: impl Into<Column>,
244 ) -> ColumnDefinitionBuilder<N, P, U, D, References, C> {
245 ColumnDefinitionBuilder {
246 name: self.name,
247 type_: self.type_,
248 nullability: self.nullability,
249 primary_key: self.primary_key,
250 unique: self.unique,
251 default: self.default,
252 references: References(table_name.into(), column.into()),
253 check: self.check,
254 }
255 }
256}
257
258impl<N, P, U, D, R> ColumnDefinitionBuilder<N, P, U, D, R, NoConstraint>
259where
260 N: NullabilityConstraint,
261 P: PrimaryKeyConstraint,
262 U: UniqueConstraint,
263 D: DefaultConstraint,
264 R: ReferencesConstraint,
265{
266 pub fn check(
267 self,
268 cond: impl Into<Condition>,
269 ) -> ColumnDefinitionBuilder<N, P, U, D, R, Check> {
270 ColumnDefinitionBuilder {
271 name: self.name,
272 type_: self.type_,
273 nullability: self.nullability,
274 primary_key: self.primary_key,
275 unique: self.unique,
276 default: self.default,
277 references: self.references,
278 check: Check(cond.into()),
279 }
280 }
281}
282
283impl<T, U> From<(T, U)> for ColumnDefinitionBuilder
284where
285 T: Into<String>,
286 U: Into<String>,
287{
288 fn from((name, type_): (T, U)) -> Self {
289 ColumnDefinitionBuilder::new(name.into(), type_.into())
290 }
291}
292
293pub trait ColumnDefinitionable: Into<ColumnDefinitionBuilder> {
294 fn null(self) -> ColumnDefinitionBuilder<IsNull>;
295 fn not_null(self) -> ColumnDefinitionBuilder<IsNotNull>;
296 fn primary_key(self) -> ColumnDefinitionBuilder<NoConstraint, IsPrimaryKey>;
297 fn unique(self) -> ColumnDefinitionBuilder<NoConstraint, NoConstraint, IsUnique>;
298 fn default(
299 self,
300 expr: impl Into<Expression>,
301 ) -> ColumnDefinitionBuilder<NoConstraint, NoConstraint, NoConstraint, HasDefault>;
302 fn references(
303 self,
304 table_name: impl Into<TableName>,
305 column: impl Into<Column>,
306 ) -> ColumnDefinitionBuilder<NoConstraint, NoConstraint, NoConstraint, NoConstraint, References>;
307 fn check(
308 self,
309 cond: impl Into<Condition>,
310 ) -> ColumnDefinitionBuilder<
311 NoConstraint,
312 NoConstraint,
313 NoConstraint,
314 NoConstraint,
315 NoConstraint,
316 Check,
317 >;
318}
319
320impl<T, U> ColumnDefinitionable for (T, U)
321where
322 T: Into<String>,
323 U: Into<String>,
324{
325 fn null(self) -> ColumnDefinitionBuilder<IsNull> {
326 ColumnDefinitionBuilder::from(self).null()
327 }
328
329 fn not_null(self) -> ColumnDefinitionBuilder<IsNotNull> {
330 ColumnDefinitionBuilder::from(self).not_null()
331 }
332
333 fn primary_key(self) -> ColumnDefinitionBuilder<NoConstraint, IsPrimaryKey> {
334 ColumnDefinitionBuilder::from(self).primary_key()
335 }
336
337 fn unique(self) -> ColumnDefinitionBuilder<NoConstraint, NoConstraint, IsUnique> {
338 ColumnDefinitionBuilder::from(self).unique()
339 }
340
341 fn default(
342 self,
343 expr: impl Into<Expression>,
344 ) -> ColumnDefinitionBuilder<NoConstraint, NoConstraint, NoConstraint, HasDefault> {
345 ColumnDefinitionBuilder::from(self).default(expr)
346 }
347
348 fn references(
349 self,
350 table_name: impl Into<TableName>,
351 column: impl Into<Column>,
352 ) -> ColumnDefinitionBuilder<NoConstraint, NoConstraint, NoConstraint, NoConstraint, References>
353 {
354 ColumnDefinitionBuilder::from(self).references(table_name, column)
355 }
356
357 fn check(
358 self,
359 expr: impl Into<Condition>,
360 ) -> ColumnDefinitionBuilder<
361 NoConstraint,
362 NoConstraint,
363 NoConstraint,
364 NoConstraint,
365 NoConstraint,
366 Check,
367 > {
368 ColumnDefinitionBuilder::from(self).check(expr)
369 }
370}