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