1#[cfg(feature = "enterprise")]
16pub mod trigger;
17
18use std::fmt::{Debug, Display};
19
20use api::v1;
21use common_query::AddColumnLocation;
22use datatypes::schema::{FulltextOptions, SkippingIndexOptions};
23use itertools::Itertools;
24use serde::Serialize;
25use sqlparser::ast::{ColumnDef, DataType, Expr, Ident, ObjectName, TableConstraint};
26use sqlparser_derive::{Visit, VisitMut};
27
28#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
29pub struct AlterTable {
30 pub table_name: ObjectName,
31 pub alter_operation: AlterTableOperation,
32}
33
34impl AlterTable {
35 pub(crate) fn new(table_name: ObjectName, alter_operation: AlterTableOperation) -> Self {
36 Self {
37 table_name,
38 alter_operation,
39 }
40 }
41
42 pub fn table_name(&self) -> &ObjectName {
43 &self.table_name
44 }
45
46 pub fn alter_operation(&self) -> &AlterTableOperation {
47 &self.alter_operation
48 }
49
50 pub fn alter_operation_mut(&mut self) -> &mut AlterTableOperation {
51 &mut self.alter_operation
52 }
53}
54
55impl Display for AlterTable {
56 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57 let table_name = self.table_name();
58 let alter_operation = self.alter_operation();
59 write!(f, r#"ALTER TABLE {table_name} {alter_operation}"#)
60 }
61}
62
63#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
64pub enum AlterTableOperation {
65 AddConstraint(TableConstraint),
67 AddColumns {
69 add_columns: Vec<AddColumn>,
70 },
71 ModifyColumnType {
73 column_name: Ident,
74 target_type: DataType,
75 },
76 SetTableOptions {
78 options: Vec<KeyValueOption>,
79 },
80 UnsetTableOptions {
82 keys: Vec<String>,
83 },
84 DropColumn {
86 name: Ident,
87 },
88 RenameTable {
90 new_table_name: String,
91 },
92 SetIndex {
93 options: SetIndexOperation,
94 },
95 UnsetIndex {
96 options: UnsetIndexOperation,
97 },
98 DropDefaults {
99 columns: Vec<DropDefaultsOperation>,
100 },
101 SetDefaults {
103 defaults: Vec<SetDefaultsOperation>,
104 },
105}
106
107#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
108pub struct DropDefaultsOperation(pub Ident);
110
111#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
112pub struct SetDefaultsOperation {
113 pub column_name: Ident,
114 pub default_constraint: Expr,
115}
116
117#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
118pub enum SetIndexOperation {
119 Fulltext {
121 column_name: Ident,
122 options: FulltextOptions,
123 },
124 Inverted { column_name: Ident },
126 Skipping {
128 column_name: Ident,
129 options: SkippingIndexOptions,
130 },
131}
132
133#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
134pub enum UnsetIndexOperation {
135 Fulltext { column_name: Ident },
137 Inverted { column_name: Ident },
139 Skipping { column_name: Ident },
141}
142
143#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
144pub struct AddColumn {
145 pub column_def: ColumnDef,
146 pub location: Option<AddColumnLocation>,
147 pub add_if_not_exists: bool,
148}
149
150impl Display for AddColumn {
151 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
152 if let Some(location) = &self.location {
153 write!(f, "{} {location}", self.column_def)
154 } else {
155 write!(f, "{}", self.column_def)
156 }
157 }
158}
159
160impl Display for AlterTableOperation {
161 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
162 match self {
163 AlterTableOperation::AddConstraint(constraint) => write!(f, r#"ADD {constraint}"#),
164 AlterTableOperation::AddColumns { add_columns } => {
165 let columns = add_columns
166 .iter()
167 .map(|add_column| format!("ADD COLUMN {add_column}"))
168 .join(", ");
169 write!(f, "{columns}")
170 }
171 AlterTableOperation::DropColumn { name } => write!(f, r#"DROP COLUMN {name}"#),
172 AlterTableOperation::RenameTable { new_table_name } => {
173 write!(f, r#"RENAME {new_table_name}"#)
174 }
175 AlterTableOperation::ModifyColumnType {
176 column_name,
177 target_type,
178 } => {
179 write!(f, r#"MODIFY COLUMN {column_name} {target_type}"#)
180 }
181 AlterTableOperation::SetTableOptions { options } => {
182 let kvs = options
183 .iter()
184 .map(|KeyValueOption { key, value }| {
185 if !value.is_empty() {
186 format!("'{key}'='{value}'")
187 } else {
188 format!("'{key}'=NULL")
189 }
190 })
191 .join(",");
192
193 write!(f, "SET {kvs}")
194 }
195 AlterTableOperation::UnsetTableOptions { keys } => {
196 let keys = keys.iter().map(|k| format!("'{k}'")).join(",");
197 write!(f, "UNSET {keys}")
198 }
199 AlterTableOperation::SetIndex { options } => match options {
200 SetIndexOperation::Fulltext {
201 column_name,
202 options,
203 } => {
204 write!(
205 f,
206 "MODIFY COLUMN {column_name} SET FULLTEXT INDEX WITH(analyzer={0}, case_sensitive={1}, backend={2})",
207 options.analyzer, options.case_sensitive, options.backend
208 )
209 }
210 SetIndexOperation::Inverted { column_name } => {
211 write!(f, "MODIFY COLUMN {column_name} SET INVERTED INDEX")
212 }
213 SetIndexOperation::Skipping {
214 column_name,
215 options,
216 } => {
217 write!(
218 f,
219 "MODIFY COLUMN {column_name} SET SKIPPING INDEX WITH(granularity={0}, index_type={1})",
220 options.granularity, options.index_type
221 )
222 }
223 },
224 AlterTableOperation::UnsetIndex { options } => match options {
225 UnsetIndexOperation::Fulltext { column_name } => {
226 write!(f, "MODIFY COLUMN {column_name} UNSET FULLTEXT INDEX")
227 }
228 UnsetIndexOperation::Inverted { column_name } => {
229 write!(f, "MODIFY COLUMN {column_name} UNSET INVERTED INDEX")
230 }
231 UnsetIndexOperation::Skipping { column_name } => {
232 write!(f, "MODIFY COLUMN {column_name} UNSET SKIPPING INDEX")
233 }
234 },
235 AlterTableOperation::DropDefaults { columns } => {
236 let columns = columns
237 .iter()
238 .map(|column| format!("MODIFY COLUMN {} DROP DEFAULT", column.0))
239 .join(", ");
240 write!(f, "{columns}")
241 }
242 AlterTableOperation::SetDefaults { defaults } => {
243 let defaults = defaults
244 .iter()
245 .map(|column| {
246 format!(
247 "MODIFY COLUMN {} SET DEFAULT {}",
248 column.column_name, column.default_constraint
249 )
250 })
251 .join(", ");
252 write!(f, "{defaults}")
253 }
254 }
255 }
256}
257
258#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
259pub struct KeyValueOption {
260 pub key: String,
261 pub value: String,
262}
263
264impl From<KeyValueOption> for v1::Option {
265 fn from(c: KeyValueOption) -> Self {
266 v1::Option {
267 key: c.key,
268 value: c.value,
269 }
270 }
271}
272
273#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
274pub struct AlterDatabase {
275 pub database_name: ObjectName,
276 pub alter_operation: AlterDatabaseOperation,
277}
278
279impl AlterDatabase {
280 pub(crate) fn new(database_name: ObjectName, alter_operation: AlterDatabaseOperation) -> Self {
281 Self {
282 database_name,
283 alter_operation,
284 }
285 }
286
287 pub fn database_name(&self) -> &ObjectName {
288 &self.database_name
289 }
290
291 pub fn alter_operation(&self) -> &AlterDatabaseOperation {
292 &self.alter_operation
293 }
294}
295
296impl Display for AlterDatabase {
297 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
298 let database_name = self.database_name();
299 let alter_operation = self.alter_operation();
300 write!(f, r#"ALTER DATABASE {database_name} {alter_operation}"#)
301 }
302}
303
304#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
305pub enum AlterDatabaseOperation {
306 SetDatabaseOption { options: Vec<KeyValueOption> },
307 UnsetDatabaseOption { keys: Vec<String> },
308}
309
310impl Display for AlterDatabaseOperation {
311 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
312 match self {
313 AlterDatabaseOperation::SetDatabaseOption { options } => {
314 let kvs = options
315 .iter()
316 .map(|KeyValueOption { key, value }| {
317 if !value.is_empty() {
318 format!("'{key}'='{value}'")
319 } else {
320 format!("'{key}'=NULL")
321 }
322 })
323 .join(",");
324
325 write!(f, "SET {kvs}")?;
326
327 Ok(())
328 }
329 AlterDatabaseOperation::UnsetDatabaseOption { keys } => {
330 let keys = keys.iter().map(|key| format!("'{key}'")).join(",");
331 write!(f, "UNSET {keys}")?;
332
333 Ok(())
334 }
335 }
336 }
337}
338
339#[cfg(test)]
340mod tests {
341 use std::assert_matches::assert_matches;
342
343 use crate::dialect::GreptimeDbDialect;
344 use crate::parser::{ParseOptions, ParserContext};
345 use crate::statements::statement::Statement;
346
347 #[test]
348 fn test_display_alter() {
349 let sql = r"ALTER DATABASE db SET 'a' = 'b', 'c' = 'd'";
350 let stmts =
351 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
352 .unwrap();
353 assert_eq!(1, stmts.len());
354 assert_matches!(&stmts[0], Statement::AlterDatabase { .. });
355
356 match &stmts[0] {
357 Statement::AlterDatabase(set) => {
358 let new_sql = format!("\n{}", set);
359 assert_eq!(
360 r#"
361ALTER DATABASE db SET 'a'='b','c'='d'"#,
362 &new_sql
363 );
364 }
365 _ => {
366 unreachable!();
367 }
368 }
369
370 let sql = r"ALTER DATABASE db UNSET 'a', 'c'";
371 let stmts =
372 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
373 .unwrap();
374 assert_eq!(1, stmts.len());
375
376 match &stmts[0] {
377 Statement::AlterDatabase(set) => {
378 let new_sql = format!("\n{}", set);
379 assert_eq!(
380 r#"
381ALTER DATABASE db UNSET 'a','c'"#,
382 &new_sql
383 );
384 }
385 _ => {
386 unreachable!();
387 }
388 }
389
390 let sql =
391 r"alter table monitor add column app string default 'shop' primary key, add foo INT;";
392 let stmts =
393 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
394 .unwrap();
395 assert_eq!(1, stmts.len());
396 assert_matches!(&stmts[0], Statement::AlterTable { .. });
397
398 match &stmts[0] {
399 Statement::AlterTable(set) => {
400 let new_sql = format!("\n{}", set);
401 assert_eq!(
402 r#"
403ALTER TABLE monitor ADD COLUMN app STRING DEFAULT 'shop' PRIMARY KEY, ADD COLUMN foo INT"#,
404 &new_sql
405 );
406 }
407 _ => {
408 unreachable!();
409 }
410 }
411
412 let sql = r"alter table monitor modify column load_15 string;";
413 let stmts =
414 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
415 .unwrap();
416 assert_eq!(1, stmts.len());
417 assert_matches!(&stmts[0], Statement::AlterTable { .. });
418
419 match &stmts[0] {
420 Statement::AlterTable(set) => {
421 let new_sql = format!("\n{}", set);
422 assert_eq!(
423 r#"
424ALTER TABLE monitor MODIFY COLUMN load_15 STRING"#,
425 &new_sql
426 );
427 }
428 _ => {
429 unreachable!();
430 }
431 }
432
433 let sql = r"alter table monitor drop column load_15;";
434 let stmts =
435 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
436 .unwrap();
437 assert_eq!(1, stmts.len());
438 assert_matches!(&stmts[0], Statement::AlterTable { .. });
439
440 match &stmts[0] {
441 Statement::AlterTable(set) => {
442 let new_sql = format!("\n{}", set);
443 assert_eq!(
444 r#"
445ALTER TABLE monitor DROP COLUMN load_15"#,
446 &new_sql
447 );
448 }
449 _ => {
450 unreachable!();
451 }
452 }
453
454 let sql = r"alter table monitor rename monitor_new;";
455 let stmts =
456 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
457 .unwrap();
458 assert_eq!(1, stmts.len());
459 assert_matches!(&stmts[0], Statement::AlterTable { .. });
460
461 match &stmts[0] {
462 Statement::AlterTable(set) => {
463 let new_sql = format!("\n{}", set);
464 assert_eq!(
465 r#"
466ALTER TABLE monitor RENAME monitor_new"#,
467 &new_sql
468 );
469 }
470 _ => {
471 unreachable!();
472 }
473 }
474
475 let sql = "ALTER TABLE monitor MODIFY COLUMN a SET FULLTEXT INDEX WITH(analyzer='English',case_sensitive='false',backend='bloom')";
476 let stmts =
477 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
478 .unwrap();
479 assert_eq!(1, stmts.len());
480 assert_matches!(&stmts[0], Statement::AlterTable { .. });
481
482 match &stmts[0] {
483 Statement::AlterTable(set) => {
484 let new_sql = format!("\n{}", set);
485 assert_eq!(
486 r#"
487ALTER TABLE monitor MODIFY COLUMN a SET FULLTEXT INDEX WITH(analyzer=English, case_sensitive=false, backend=bloom)"#,
488 &new_sql
489 );
490 }
491 _ => {
492 unreachable!();
493 }
494 }
495
496 let sql = "ALTER TABLE monitor MODIFY COLUMN a UNSET FULLTEXT INDEX";
497 let stmts =
498 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
499 .unwrap();
500 assert_eq!(1, stmts.len());
501 assert_matches!(&stmts[0], Statement::AlterTable { .. });
502
503 match &stmts[0] {
504 Statement::AlterTable(set) => {
505 let new_sql = format!("\n{}", set);
506 assert_eq!(
507 r#"
508ALTER TABLE monitor MODIFY COLUMN a UNSET FULLTEXT INDEX"#,
509 &new_sql
510 );
511 }
512 _ => {
513 unreachable!();
514 }
515 }
516
517 let sql = "ALTER TABLE monitor MODIFY COLUMN a SET INVERTED INDEX";
518 let stmts =
519 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
520 .unwrap();
521 assert_eq!(1, stmts.len());
522 assert_matches!(&stmts[0], Statement::AlterTable { .. });
523
524 match &stmts[0] {
525 Statement::AlterTable(set) => {
526 let new_sql = format!("\n{}", set);
527 assert_eq!(
528 r#"
529ALTER TABLE monitor MODIFY COLUMN a SET INVERTED INDEX"#,
530 &new_sql
531 );
532 }
533 _ => {
534 unreachable!();
535 }
536 }
537
538 let sql = "ALTER TABLE monitor MODIFY COLUMN a DROP DEFAULT";
539 let stmts =
540 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
541 .unwrap();
542 assert_eq!(1, stmts.len());
543 assert_matches!(&stmts[0], Statement::AlterTable { .. });
544
545 match &stmts[0] {
546 Statement::AlterTable(set) => {
547 let new_sql = format!("\n{}", set);
548 assert_eq!(
549 r#"
550ALTER TABLE monitor MODIFY COLUMN a DROP DEFAULT"#,
551 &new_sql
552 );
553 }
554 _ => {
555 unreachable!();
556 }
557 }
558
559 let sql = "ALTER TABLE monitor MODIFY COLUMN a SET DEFAULT 'default_for_a'";
560 let stmts =
561 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
562 .unwrap();
563 assert_eq!(1, stmts.len());
564 assert_matches!(&stmts[0], Statement::AlterTable { .. });
565
566 match &stmts[0] {
567 Statement::AlterTable(set) => {
568 let new_sql = format!("\n{}", set);
569 assert_eq!(
570 r#"
571ALTER TABLE monitor MODIFY COLUMN a SET DEFAULT 'default_for_a'"#,
572 &new_sql
573 );
574 }
575 _ => {
576 unreachable!();
577 }
578 }
579 }
580}