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