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 Repartition {
107 operation: RepartitionOperation,
108 },
109}
110
111#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
112pub struct DropDefaultsOperation(pub Ident);
114
115#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
116pub struct SetDefaultsOperation {
117 pub column_name: Ident,
118 pub default_constraint: Expr,
119}
120
121#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
122pub struct RepartitionOperation {
123 pub from_exprs: Vec<Expr>,
124 pub into_exprs: Vec<Expr>,
125}
126
127impl RepartitionOperation {
128 pub fn new(from_exprs: Vec<Expr>, into_exprs: Vec<Expr>) -> Self {
129 Self {
130 from_exprs,
131 into_exprs,
132 }
133 }
134}
135
136impl Display for RepartitionOperation {
137 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
138 let from = self
139 .from_exprs
140 .iter()
141 .map(|expr| expr.to_string())
142 .join(", ");
143 let into = self
144 .into_exprs
145 .iter()
146 .map(|expr| expr.to_string())
147 .join(", ");
148
149 write!(f, "({from}) INTO ({into})")
150 }
151}
152
153#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
154pub enum SetIndexOperation {
155 Fulltext {
157 column_name: Ident,
158 options: FulltextOptions,
159 },
160 Inverted { column_name: Ident },
162 Skipping {
164 column_name: Ident,
165 options: SkippingIndexOptions,
166 },
167}
168
169#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
170pub enum UnsetIndexOperation {
171 Fulltext { column_name: Ident },
173 Inverted { column_name: Ident },
175 Skipping { column_name: Ident },
177}
178
179#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
180pub struct AddColumn {
181 pub column_def: ColumnDef,
182 pub location: Option<AddColumnLocation>,
183 pub add_if_not_exists: bool,
184}
185
186impl Display for AddColumn {
187 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
188 if let Some(location) = &self.location {
189 write!(f, "{} {location}", self.column_def)
190 } else {
191 write!(f, "{}", self.column_def)
192 }
193 }
194}
195
196impl Display for AlterTableOperation {
197 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
198 match self {
199 AlterTableOperation::AddConstraint(constraint) => write!(f, r#"ADD {constraint}"#),
200 AlterTableOperation::AddColumns { add_columns } => {
201 let columns = add_columns
202 .iter()
203 .map(|add_column| format!("ADD COLUMN {add_column}"))
204 .join(", ");
205 write!(f, "{columns}")
206 }
207 AlterTableOperation::DropColumn { name } => write!(f, r#"DROP COLUMN {name}"#),
208 AlterTableOperation::RenameTable { new_table_name } => {
209 write!(f, r#"RENAME {new_table_name}"#)
210 }
211 AlterTableOperation::ModifyColumnType {
212 column_name,
213 target_type,
214 } => {
215 write!(f, r#"MODIFY COLUMN {column_name} {target_type}"#)
216 }
217 AlterTableOperation::SetTableOptions { options } => {
218 let kvs = options
219 .iter()
220 .map(|KeyValueOption { key, value }| {
221 if !value.is_empty() {
222 format!("'{key}'='{value}'")
223 } else {
224 format!("'{key}'=NULL")
225 }
226 })
227 .join(",");
228
229 write!(f, "SET {kvs}")
230 }
231 AlterTableOperation::UnsetTableOptions { keys } => {
232 let keys = keys.iter().map(|k| format!("'{k}'")).join(",");
233 write!(f, "UNSET {keys}")
234 }
235 AlterTableOperation::Repartition { operation } => {
236 write!(f, "REPARTITION {operation}")
237 }
238 AlterTableOperation::SetIndex { options } => match options {
239 SetIndexOperation::Fulltext {
240 column_name,
241 options,
242 } => {
243 write!(
244 f,
245 "MODIFY COLUMN {column_name} SET FULLTEXT INDEX WITH(analyzer={0}, case_sensitive={1}, backend={2})",
246 options.analyzer, options.case_sensitive, options.backend
247 )
248 }
249 SetIndexOperation::Inverted { column_name } => {
250 write!(f, "MODIFY COLUMN {column_name} SET INVERTED INDEX")
251 }
252 SetIndexOperation::Skipping {
253 column_name,
254 options,
255 } => {
256 write!(
257 f,
258 "MODIFY COLUMN {column_name} SET SKIPPING INDEX WITH(granularity={0}, index_type={1})",
259 options.granularity, options.index_type
260 )
261 }
262 },
263 AlterTableOperation::UnsetIndex { options } => match options {
264 UnsetIndexOperation::Fulltext { column_name } => {
265 write!(f, "MODIFY COLUMN {column_name} UNSET FULLTEXT INDEX")
266 }
267 UnsetIndexOperation::Inverted { column_name } => {
268 write!(f, "MODIFY COLUMN {column_name} UNSET INVERTED INDEX")
269 }
270 UnsetIndexOperation::Skipping { column_name } => {
271 write!(f, "MODIFY COLUMN {column_name} UNSET SKIPPING INDEX")
272 }
273 },
274 AlterTableOperation::DropDefaults { columns } => {
275 let columns = columns
276 .iter()
277 .map(|column| format!("MODIFY COLUMN {} DROP DEFAULT", column.0))
278 .join(", ");
279 write!(f, "{columns}")
280 }
281 AlterTableOperation::SetDefaults { defaults } => {
282 let defaults = defaults
283 .iter()
284 .map(|column| {
285 format!(
286 "MODIFY COLUMN {} SET DEFAULT {}",
287 column.column_name, column.default_constraint
288 )
289 })
290 .join(", ");
291 write!(f, "{defaults}")
292 }
293 }
294 }
295}
296
297#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
298pub struct KeyValueOption {
299 pub key: String,
300 pub value: String,
301}
302
303impl From<KeyValueOption> for v1::Option {
304 fn from(c: KeyValueOption) -> Self {
305 v1::Option {
306 key: c.key,
307 value: c.value,
308 }
309 }
310}
311
312#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
313pub struct AlterDatabase {
314 pub database_name: ObjectName,
315 pub alter_operation: AlterDatabaseOperation,
316}
317
318impl AlterDatabase {
319 pub(crate) fn new(database_name: ObjectName, alter_operation: AlterDatabaseOperation) -> Self {
320 Self {
321 database_name,
322 alter_operation,
323 }
324 }
325
326 pub fn database_name(&self) -> &ObjectName {
327 &self.database_name
328 }
329
330 pub fn alter_operation(&self) -> &AlterDatabaseOperation {
331 &self.alter_operation
332 }
333}
334
335impl Display for AlterDatabase {
336 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
337 let database_name = self.database_name();
338 let alter_operation = self.alter_operation();
339 write!(f, r#"ALTER DATABASE {database_name} {alter_operation}"#)
340 }
341}
342
343#[derive(Debug, Clone, PartialEq, Eq, Visit, VisitMut, Serialize)]
344pub enum AlterDatabaseOperation {
345 SetDatabaseOption { options: Vec<KeyValueOption> },
346 UnsetDatabaseOption { keys: Vec<String> },
347}
348
349impl Display for AlterDatabaseOperation {
350 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
351 match self {
352 AlterDatabaseOperation::SetDatabaseOption { options } => {
353 let kvs = options
354 .iter()
355 .map(|KeyValueOption { key, value }| {
356 if !value.is_empty() {
357 format!("'{key}'='{value}'")
358 } else {
359 format!("'{key}'=NULL")
360 }
361 })
362 .join(",");
363
364 write!(f, "SET {kvs}")?;
365
366 Ok(())
367 }
368 AlterDatabaseOperation::UnsetDatabaseOption { keys } => {
369 let keys = keys.iter().map(|key| format!("'{key}'")).join(",");
370 write!(f, "UNSET {keys}")?;
371
372 Ok(())
373 }
374 }
375 }
376}
377
378#[cfg(test)]
379mod tests {
380 use std::assert_matches::assert_matches;
381
382 use crate::dialect::GreptimeDbDialect;
383 use crate::parser::{ParseOptions, ParserContext};
384 use crate::statements::statement::Statement;
385
386 #[test]
387 fn test_display_alter() {
388 let sql = r"ALTER DATABASE db SET 'a' = 'b', 'c' = 'd'";
389 let stmts =
390 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
391 .unwrap();
392 assert_eq!(1, stmts.len());
393 assert_matches!(&stmts[0], Statement::AlterDatabase { .. });
394
395 match &stmts[0] {
396 Statement::AlterDatabase(set) => {
397 let new_sql = format!("\n{}", set);
398 assert_eq!(
399 r#"
400ALTER DATABASE db SET 'a'='b','c'='d'"#,
401 &new_sql
402 );
403 }
404 _ => {
405 unreachable!();
406 }
407 }
408
409 let sql = r"ALTER DATABASE db UNSET 'a', 'c'";
410 let stmts =
411 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
412 .unwrap();
413 assert_eq!(1, stmts.len());
414
415 match &stmts[0] {
416 Statement::AlterDatabase(set) => {
417 let new_sql = format!("\n{}", set);
418 assert_eq!(
419 r#"
420ALTER DATABASE db UNSET 'a','c'"#,
421 &new_sql
422 );
423 }
424 _ => {
425 unreachable!();
426 }
427 }
428
429 let sql =
430 r"alter table monitor add column app string default 'shop' primary key, add foo INT;";
431 let stmts =
432 ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
433 .unwrap();
434 assert_eq!(1, stmts.len());
435 assert_matches!(&stmts[0], Statement::AlterTable { .. });
436
437 match &stmts[0] {
438 Statement::AlterTable(set) => {
439 let new_sql = format!("\n{}", set);
440 assert_eq!(
441 r#"
442ALTER TABLE monitor ADD COLUMN app STRING DEFAULT 'shop' PRIMARY KEY, ADD COLUMN foo INT"#,
443 &new_sql
444 );
445 }
446 _ => {
447 unreachable!();
448 }
449 }
450
451 let sql = r"alter table monitor modify column load_15 string;";
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 MODIFY COLUMN load_15 STRING"#,
464 &new_sql
465 );
466 }
467 _ => {
468 unreachable!();
469 }
470 }
471
472 let sql = r"alter table monitor drop column load_15;";
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 DROP COLUMN load_15"#,
485 &new_sql
486 );
487 }
488 _ => {
489 unreachable!();
490 }
491 }
492
493 let sql = r"alter table monitor rename monitor_new;";
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 RENAME monitor_new"#,
506 &new_sql
507 );
508 }
509 _ => {
510 unreachable!();
511 }
512 }
513
514 let sql = "ALTER TABLE monitor MODIFY COLUMN a SET FULLTEXT INDEX WITH(analyzer='English',case_sensitive='false',backend='bloom')";
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 MODIFY COLUMN a SET FULLTEXT INDEX WITH(analyzer=English, case_sensitive=false, backend=bloom)"#,
527 &new_sql
528 );
529 }
530 _ => {
531 unreachable!();
532 }
533 }
534
535 let sql = "ALTER TABLE monitor MODIFY COLUMN a UNSET FULLTEXT INDEX";
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 UNSET FULLTEXT INDEX"#,
548 &new_sql
549 );
550 }
551 _ => {
552 unreachable!();
553 }
554 }
555
556 let sql = "ALTER TABLE monitor MODIFY COLUMN a SET INVERTED 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 SET INVERTED INDEX"#,
569 &new_sql
570 );
571 }
572 _ => {
573 unreachable!();
574 }
575 }
576
577 let sql = "ALTER TABLE monitor MODIFY COLUMN a DROP DEFAULT";
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 DROP DEFAULT"#,
590 &new_sql
591 );
592 }
593 _ => {
594 unreachable!();
595 }
596 }
597
598 let sql = "ALTER TABLE monitor MODIFY COLUMN a SET DEFAULT 'default_for_a'";
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 SET DEFAULT 'default_for_a'"#,
611 &new_sql
612 );
613 }
614 _ => {
615 unreachable!();
616 }
617 }
618 }
619}