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