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