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 = if cfg!(feature = "option-postgres-use-serial") {
230 match column_type {
231 ColumnType::SmallInteger => "smallserial",
232 ColumnType::Integer => "serial",
233 ColumnType::BigInteger => "bigserial",
234 _ => unimplemented!("{:?} doesn't support auto increment", column_type),
235 }
236 } else {
237 match column_type {
238 ColumnType::SmallInteger => "smallint GENERATED BY DEFAULT AS IDENTITY",
239 ColumnType::Integer => "integer GENERATED BY DEFAULT AS IDENTITY",
240 ColumnType::BigInteger => "bigint GENERATED BY DEFAULT AS IDENTITY",
241 _ => unimplemented!("{:?} doesn't support auto increment", column_type),
242 }
243 };
244
245 sql.write_str(num_ty).unwrap();
246 }
247
248 fn prepare_column_type_check_auto_increment(
249 &self,
250 column_def: &ColumnDef,
251 sql: &mut impl SqlWriter,
252 ) {
253 if let Some(column_type) = &column_def.types {
254 let is_auto_increment = column_def.spec.auto_increment;
255
256 sql.write_str(" ").unwrap();
257
258 if is_auto_increment {
259 self.prepare_column_auto_increment(column_type, sql);
260 } else {
261 self.prepare_column_type(column_type, sql);
262 }
263 }
264 }
265
266 fn prepare_column_def_common<F, W>(&self, column_def: &ColumnDef, sql: &mut W, f: F)
267 where
268 F: Fn(&ColumnDef, &mut W),
269 W: SqlWriter,
270 {
271 self.prepare_iden(&column_def.name, sql);
272
273 f(column_def, sql);
274
275 self.prepare_column_spec(&column_def.spec, sql);
276 }
277
278 fn prepare_modify_column(&self, sql: &mut impl SqlWriter, column_def: &ColumnDef) {
279 let mut is_first = true;
280
281 macro_rules! write_comma_if_not_first {
282 () => {
283 if !is_first {
284 write!(sql, ", ").unwrap();
285 } else {
286 is_first = false
287 }
288 };
289 }
290
291 if let Some(column_type) = &column_def.types {
292 write!(sql, "ALTER COLUMN ").unwrap();
293 self.prepare_iden(&column_def.name, sql);
294 write!(sql, " TYPE ").unwrap();
295 self.prepare_column_type(column_type, sql);
296 is_first = false;
297 }
298
299 if column_def.spec.auto_increment {
300 }
302
303 if let Some(nullable) = column_def.spec.nullable {
304 write_comma_if_not_first!();
305 write!(sql, "ALTER COLUMN ").unwrap();
306 self.prepare_iden(&column_def.name, sql);
307 if nullable {
308 write!(sql, " DROP NOT NULL").unwrap();
309 } else {
310 write!(sql, " SET NOT NULL").unwrap();
311 }
312 }
313
314 if let Some(default) = &column_def.spec.default {
315 write_comma_if_not_first!();
316 write!(sql, "ALTER COLUMN ").unwrap();
317 self.prepare_iden(&column_def.name, sql);
318 write!(sql, " SET DEFAULT ").unwrap();
319 QueryBuilder::prepare_expr(self, default, sql);
320 }
321 if column_def.spec.unique {
322 write_comma_if_not_first!();
323 write!(sql, "ADD UNIQUE (").unwrap();
324 self.prepare_iden(&column_def.name, sql);
325 write!(sql, ")").unwrap();
326 }
327 if column_def.spec.primary_key {
328 write_comma_if_not_first!();
329 write!(sql, "ADD PRIMARY KEY (").unwrap();
330 self.prepare_iden(&column_def.name, sql);
331 write!(sql, ")").unwrap();
332 }
333 if let Some(check) = &column_def.spec.check {
334 write_comma_if_not_first!();
335 self.prepare_check_constraint(check, sql);
336 }
337
338 if let Some(x) = &column_def.spec.generated {
339 let _ = x;
340 }
341
342 if let Some(x) = &column_def.spec.comment {
343 let _ = x;
344 }
345
346 if let Some(expr) = &column_def.spec.using {
347 write!(sql, " USING ").unwrap();
348 QueryBuilder::prepare_expr(self, expr, sql);
349 }
350
351 if let Some(extra) = &column_def.spec.extra {
352 write!(sql, "{extra}").unwrap()
353 }
354
355 let _ = is_first;
356 }
357}