sea_query/backend/postgres/
table.rs1use 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 }
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}