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