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