sea_query/backend/postgres/
table.rs

1use super::*;
2use crate::write_int;
3
4impl TableBuilder for PostgresQueryBuilder {
5    fn prepare_column_def(&self, column_def: &ColumnDef, sql: &mut impl SqlWriter) {
6        fn f(this: &PostgresQueryBuilder, column_def: &ColumnDef, sql: &mut impl SqlWriter) {
7            this.prepare_column_type_check_auto_increment(column_def, sql);
8        }
9
10        self.prepare_column_def_common(column_def, sql, |column_def, sql| f(self, column_def, sql));
11    }
12
13    fn prepare_column_type(&self, column_type: &ColumnType, sql: &mut impl SqlWriter) {
14        match column_type {
15            ColumnType::Char(length) => match length {
16                Some(length) => {
17                    sql.write_str("char(").unwrap();
18                    write_int(sql, *length);
19                    sql.write_char(')')
20                }
21                None => sql.write_str("char"),
22            },
23            ColumnType::String(length) => match length {
24                StringLen::N(length) => {
25                    sql.write_str("varchar(").unwrap();
26                    write_int(sql, *length);
27                    sql.write_char(')')
28                }
29                _ => sql.write_str("varchar"),
30            },
31            ColumnType::Text => sql.write_str("text"),
32            ColumnType::TinyInteger | ColumnType::TinyUnsigned => sql.write_str("smallint"),
33            ColumnType::SmallInteger | ColumnType::SmallUnsigned => sql.write_str("smallint"),
34            ColumnType::Integer | ColumnType::Unsigned => sql.write_str("integer"),
35            ColumnType::BigInteger | ColumnType::BigUnsigned => sql.write_str("bigint"),
36            ColumnType::Float => sql.write_str("real"),
37            ColumnType::Double => sql.write_str("double precision"),
38            ColumnType::Decimal(precision) => match precision {
39                Some((precision, scale)) => {
40                    sql.write_str("decimal(").unwrap();
41                    write_int(sql, *precision);
42                    sql.write_str(", ").unwrap();
43                    write_int(sql, *scale);
44                    sql.write_char(')')
45                }
46                None => sql.write_str("decimal"),
47            },
48            ColumnType::DateTime => sql.write_str("timestamp without time zone"),
49            ColumnType::Timestamp => sql.write_str("timestamp"),
50            ColumnType::TimestampWithTimeZone => sql.write_str("timestamp with time zone"),
51            ColumnType::Time => sql.write_str("time"),
52            ColumnType::Date => sql.write_str("date"),
53            ColumnType::Interval(fields, precision) => {
54                sql.write_str("interval").unwrap();
55
56                if let Some(fields) = fields {
57                    write!(sql, " {fields}").unwrap();
58                }
59
60                if let Some(precision) = precision {
61                    sql.write_char('(').unwrap();
62                    write_int(sql, *precision);
63                    sql.write_char(')').unwrap();
64                }
65                Ok(())
66            }
67            ColumnType::Binary(_) | ColumnType::VarBinary(_) | ColumnType::Blob => {
68                sql.write_str("bytea")
69            }
70            ColumnType::Bit(length) => match length {
71                Some(length) => {
72                    sql.write_str("bit(").unwrap();
73                    write_int(sql, *length);
74                    sql.write_char(')')
75                }
76                None => sql.write_str("bit"),
77            },
78            ColumnType::VarBit(length) => {
79                sql.write_str("varbit(").unwrap();
80                write_int(sql, *length);
81                sql.write_char(')')
82            }
83            ColumnType::Boolean => sql.write_str("bool"),
84            ColumnType::Money(precision) => match precision {
85                Some((precision, scale)) => {
86                    sql.write_str("money(").unwrap();
87                    write_int(sql, *precision);
88                    sql.write_str(", ").unwrap();
89                    write_int(sql, *scale);
90                    sql.write_char(')')
91                }
92                None => sql.write_str("money"),
93            },
94            ColumnType::Json => sql.write_str("json"),
95            ColumnType::JsonBinary => sql.write_str("jsonb"),
96            ColumnType::Uuid => sql.write_str("uuid"),
97            ColumnType::Array(elem_type) => {
98                self.prepare_column_type(elem_type, sql);
99                sql.write_str("[]")
100            }
101            ColumnType::Vector(size) => match size {
102                Some(size) => {
103                    sql.write_str("vector(").unwrap();
104                    write_int(sql, *size);
105                    sql.write_str(")")
106                }
107                None => sql.write_str("vector"),
108            },
109            ColumnType::Custom(iden) => sql.write_str(&iden.0),
110            ColumnType::Enum { name, .. } => sql.write_str(&name.0),
111            ColumnType::Cidr => sql.write_str("cidr"),
112            ColumnType::Inet => sql.write_str("inet"),
113            ColumnType::MacAddr => sql.write_str("macaddr"),
114            ColumnType::Year => unimplemented!("Year is not available in Postgres."),
115            ColumnType::LTree => sql.write_str("ltree"),
116        }
117        .unwrap()
118    }
119
120    fn column_spec_auto_increment_keyword(&self) -> &str {
121        ""
122    }
123
124    fn prepare_table_alter_statement(&self, alter: &TableAlterStatement, sql: &mut impl SqlWriter) {
125        if alter.options.is_empty() {
126            panic!("No alter option found")
127        };
128        sql.write_str("ALTER TABLE ").unwrap();
129        if let Some(table) = &alter.table {
130            self.prepare_table_ref_table_stmt(table, sql);
131            sql.write_str(" ").unwrap();
132        }
133
134        let mut opts = alter.options.iter();
135
136        join_io!(
137            opts,
138            opt,
139            join {
140                sql.write_str(", ").unwrap();
141            },
142            do {
143                match opt {
144                    TableAlterOption::AddColumn(AddColumnOption {
145                        column,
146                        if_not_exists,
147                    }) => {
148                        sql.write_str("ADD COLUMN ").unwrap();
149                        if *if_not_exists {
150                            sql.write_str("IF NOT EXISTS ").unwrap();
151                        }
152
153                        self.prepare_column_def_common(column, sql, |column_def, sql| {
154                            if let Some(column_type) = &column_def.types {
155                                write!(sql, " ").unwrap();
156                                if column_def.spec.auto_increment {
157                                    self.prepare_column_auto_increment(column_type, sql);
158                                } else {
159                                    self.prepare_column_type(column_type, sql);
160                                }
161                            }
162                        });
163                    }
164                    TableAlterOption::ModifyColumn(column_def) => {
165                        self.prepare_modify_column(sql, column_def);
166                    }
167                    TableAlterOption::RenameColumn(from_name, to_name) => {
168                        sql.write_str("RENAME COLUMN ").unwrap();
169                        self.prepare_iden(from_name, sql);
170                        sql.write_str(" TO ").unwrap();
171                        self.prepare_iden(to_name, sql);
172                    }
173                    TableAlterOption::DropColumn(DropColumnOption{
174                        column_name,
175                        if_exists
176                    }) => {
177                        sql.write_str("DROP COLUMN ").unwrap();
178                         if *if_exists {
179                            sql.write_str("IF EXISTS ").unwrap();
180                        }
181                        self.prepare_iden(column_name, sql);
182                    }
183                    TableAlterOption::DropForeignKey(name) => {
184                        let mut foreign_key = TableForeignKey::new();
185                        foreign_key.name(name.to_string());
186                        let drop = ForeignKeyDropStatement {
187                            foreign_key,
188                            table: None,
189                        };
190                        self.prepare_foreign_key_drop_statement_internal(
191                            &drop,
192                            sql,
193                            Mode::TableAlter,
194                        );
195                    }
196                    TableAlterOption::AddForeignKey(foreign_key) => {
197                        let create = ForeignKeyCreateStatement {
198                            foreign_key: foreign_key.to_owned(),
199                        };
200                        self.prepare_foreign_key_create_statement_internal(
201                            &create,
202                            sql,
203                            Mode::TableAlter,
204                        );
205                    }
206                }
207            }
208        );
209    }
210
211    fn prepare_table_rename_statement(
212        &self,
213        rename: &TableRenameStatement,
214        sql: &mut impl SqlWriter,
215    ) {
216        sql.write_str("ALTER TABLE ").unwrap();
217        if let Some(from_name) = &rename.from_name {
218            self.prepare_table_ref_table_stmt(from_name, sql);
219        }
220        sql.write_str(" RENAME TO ").unwrap();
221        if let Some(to_name) = &rename.to_name {
222            self.prepare_table_ref_table_stmt(to_name, sql);
223        }
224    }
225}
226
227impl PostgresQueryBuilder {
228    fn prepare_column_auto_increment(&self, column_type: &ColumnType, sql: &mut impl SqlWriter) {
229        let num_ty = match column_type {
230            ColumnType::SmallInteger => "smallint GENERATED BY DEFAULT AS IDENTITY",
231            ColumnType::Integer => "integer GENERATED BY DEFAULT AS IDENTITY",
232            ColumnType::BigInteger => "bigint GENERATED BY DEFAULT AS IDENTITY",
233            _ => unimplemented!("{:?} doesn't support auto increment", column_type),
234        };
235
236        sql.write_str(num_ty).unwrap();
237    }
238
239    fn prepare_column_type_check_auto_increment(
240        &self,
241        column_def: &ColumnDef,
242        sql: &mut impl SqlWriter,
243    ) {
244        if let Some(column_type) = &column_def.types {
245            let is_auto_increment = column_def.spec.auto_increment;
246
247            sql.write_str(" ").unwrap();
248
249            if is_auto_increment {
250                self.prepare_column_auto_increment(column_type, sql);
251            } else {
252                self.prepare_column_type(column_type, sql);
253            }
254        }
255    }
256
257    fn prepare_column_def_common<F, W>(&self, column_def: &ColumnDef, sql: &mut W, f: F)
258    where
259        F: Fn(&ColumnDef, &mut W),
260        W: SqlWriter,
261    {
262        self.prepare_iden(&column_def.name, sql);
263
264        f(column_def, sql);
265
266        self.prepare_column_spec(&column_def.spec, sql);
267    }
268
269    fn prepare_modify_column(&self, sql: &mut impl SqlWriter, column_def: &ColumnDef) {
270        let mut is_first = true;
271
272        macro_rules! write_comma_if_not_first {
273            () => {
274                if !is_first {
275                    write!(sql, ", ").unwrap();
276                } else {
277                    is_first = false
278                }
279            };
280        }
281
282        if let Some(column_type) = &column_def.types {
283            write!(sql, "ALTER COLUMN ").unwrap();
284            self.prepare_iden(&column_def.name, sql);
285            write!(sql, " TYPE ").unwrap();
286            self.prepare_column_type(column_type, sql);
287            is_first = false;
288        }
289
290        if column_def.spec.auto_increment {
291            //
292        }
293
294        if let Some(nullable) = column_def.spec.nullable {
295            write_comma_if_not_first!();
296            write!(sql, "ALTER COLUMN ").unwrap();
297            self.prepare_iden(&column_def.name, sql);
298            if nullable {
299                write!(sql, " DROP NOT NULL").unwrap();
300            } else {
301                write!(sql, " SET NOT NULL").unwrap();
302            }
303        }
304
305        if let Some(default) = &column_def.spec.default {
306            write_comma_if_not_first!();
307            write!(sql, "ALTER COLUMN ").unwrap();
308            self.prepare_iden(&column_def.name, sql);
309            write!(sql, " SET DEFAULT ").unwrap();
310            QueryBuilder::prepare_expr(self, default, sql);
311        }
312        if column_def.spec.unique {
313            write_comma_if_not_first!();
314            write!(sql, "ADD UNIQUE (").unwrap();
315            self.prepare_iden(&column_def.name, sql);
316            write!(sql, ")").unwrap();
317        }
318        if column_def.spec.primary_key {
319            write_comma_if_not_first!();
320            write!(sql, "ADD PRIMARY KEY (").unwrap();
321            self.prepare_iden(&column_def.name, sql);
322            write!(sql, ")").unwrap();
323        }
324        if let Some(check) = &column_def.spec.check {
325            write_comma_if_not_first!();
326            self.prepare_check_constraint(check, sql);
327        }
328
329        if let Some(x) = &column_def.spec.generated {
330            let _ = x;
331        }
332
333        if let Some(x) = &column_def.spec.comment {
334            let _ = x;
335        }
336
337        if let Some(expr) = &column_def.spec.using {
338            write!(sql, " USING ").unwrap();
339            QueryBuilder::prepare_expr(self, expr, sql);
340        }
341
342        if let Some(extra) = &column_def.spec.extra {
343            write!(sql, "{extra}").unwrap()
344        }
345
346        let _ = is_first;
347    }
348}