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