sql/parsers/
alter_parser.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#[cfg(feature = "enterprise")]
16pub mod trigger;
17
18use std::collections::HashMap;
19
20use common_query::AddColumnLocation;
21use datatypes::schema::COLUMN_FULLTEXT_CHANGE_OPT_KEY_ENABLE;
22use snafu::{ResultExt, ensure};
23use sqlparser::ast::Ident;
24use sqlparser::keywords::Keyword;
25use sqlparser::parser::{Parser, ParserError};
26use sqlparser::tokenizer::{Token, TokenWithSpan};
27
28use crate::ast::ObjectNamePartExt;
29use crate::error::{self, InvalidColumnOptionSnafu, Result, SetFulltextOptionSnafu};
30use crate::parser::ParserContext;
31use crate::parsers::create_parser::INVERTED;
32use crate::parsers::utils::{
33    validate_column_fulltext_create_option, validate_column_skipping_index_create_option,
34};
35use crate::statements::alter::{
36    AddColumn, AlterDatabase, AlterDatabaseOperation, AlterTable, AlterTableOperation,
37    DropDefaultsOperation, KeyValueOption, SetDefaultsOperation, SetIndexOperation,
38    UnsetIndexOperation,
39};
40use crate::statements::statement::Statement;
41use crate::util::parse_option_string;
42
43impl ParserContext<'_> {
44    pub(crate) fn parse_alter(&mut self) -> Result<Statement> {
45        let _ = self.parser.expect_keyword(Keyword::ALTER);
46        match self.parser.peek_token().token {
47            Token::Word(w) => match w.keyword {
48                Keyword::DATABASE => self.parse_alter_database().map(Statement::AlterDatabase),
49                Keyword::TABLE => self.parse_alter_table().map(Statement::AlterTable),
50                #[cfg(feature = "enterprise")]
51                Keyword::TRIGGER => {
52                    self.parser.next_token();
53                    self.parse_alter_trigger()
54                }
55                _ => self.expected("DATABASE or TABLE after ALTER", self.parser.peek_token()),
56            },
57            unexpected => self.unsupported(unexpected.to_string()),
58        }
59    }
60
61    fn parse_alter_database(&mut self) -> Result<AlterDatabase> {
62        self.parser
63            .expect_keyword(Keyword::DATABASE)
64            .context(error::SyntaxSnafu)?;
65
66        let database_name = self
67            .parser
68            .parse_object_name(false)
69            .context(error::SyntaxSnafu)?;
70        let database_name = Self::canonicalize_object_name(database_name);
71
72        match self.parser.peek_token().token {
73            Token::Word(w) => {
74                if w.value.eq_ignore_ascii_case("UNSET") {
75                    let _ = self.parser.next_token();
76                    let keys = self
77                        .parser
78                        .parse_comma_separated(parse_string_option_names)
79                        .context(error::SyntaxSnafu)?
80                        .into_iter()
81                        .map(|name| name.to_string())
82                        .collect();
83                    Ok(AlterDatabase::new(
84                        database_name,
85                        AlterDatabaseOperation::UnsetDatabaseOption { keys },
86                    ))
87                } else if w.keyword == Keyword::SET {
88                    let _ = self.parser.next_token();
89                    let options = self
90                        .parser
91                        .parse_comma_separated(parse_string_options)
92                        .context(error::SyntaxSnafu)?
93                        .into_iter()
94                        .map(|(key, value)| KeyValueOption { key, value })
95                        .collect();
96                    Ok(AlterDatabase::new(
97                        database_name,
98                        AlterDatabaseOperation::SetDatabaseOption { options },
99                    ))
100                } else {
101                    self.expected(
102                        "SET or UNSET after ALTER DATABASE",
103                        self.parser.peek_token(),
104                    )
105                }
106            }
107            unexpected => self.unsupported(unexpected.to_string()),
108        }
109    }
110
111    fn parse_alter_table(&mut self) -> Result<AlterTable> {
112        self.parser
113            .expect_keyword(Keyword::TABLE)
114            .context(error::SyntaxSnafu)?;
115
116        let raw_table_name = self
117            .parser
118            .parse_object_name(false)
119            .context(error::SyntaxSnafu)?;
120        let table_name = Self::canonicalize_object_name(raw_table_name);
121
122        let alter_operation = match self.parser.peek_token().token {
123            Token::Word(w) => {
124                if w.value.eq_ignore_ascii_case("MODIFY") {
125                    self.parse_alter_table_modify()?
126                } else if w.value.eq_ignore_ascii_case("UNSET") {
127                    self.parse_alter_table_unset()?
128                } else {
129                    match w.keyword {
130                        Keyword::ADD => self.parse_alter_table_add()?,
131                        Keyword::DROP => {
132                            let _ = self.parser.next_token();
133                            self.parser
134                                .expect_keyword(Keyword::COLUMN)
135                                .context(error::SyntaxSnafu)?;
136                            let name = Self::canonicalize_identifier(
137                                self.parser.parse_identifier().context(error::SyntaxSnafu)?,
138                            );
139                            AlterTableOperation::DropColumn { name }
140                        }
141                        Keyword::RENAME => {
142                            let _ = self.parser.next_token();
143                            let new_table_name_obj_raw =
144                                self.parse_object_name().context(error::SyntaxSnafu)?;
145                            let new_table_name_obj =
146                                Self::canonicalize_object_name(new_table_name_obj_raw);
147                            let new_table_name = match &new_table_name_obj.0[..] {
148                                [table] => table.to_string_unquoted(),
149                                _ => {
150                                    return Err(ParserError::ParserError(format!(
151                                        "expect table name, actual: {new_table_name_obj}"
152                                    )))
153                                    .context(error::SyntaxSnafu);
154                                }
155                            };
156                            AlterTableOperation::RenameTable { new_table_name }
157                        }
158                        Keyword::SET => {
159                            let _ = self.parser.next_token();
160                            let options = self
161                                .parser
162                                .parse_comma_separated(parse_string_options)
163                                .context(error::SyntaxSnafu)?
164                                .into_iter()
165                                .map(|(key, value)| KeyValueOption { key, value })
166                                .collect();
167                            AlterTableOperation::SetTableOptions { options }
168                        }
169                        _ => self.expected(
170                            "ADD or DROP or MODIFY or RENAME or SET after ALTER TABLE",
171                            self.parser.peek_token(),
172                        )?,
173                    }
174                }
175            }
176            unexpected => self.unsupported(unexpected.to_string())?,
177        };
178        Ok(AlterTable::new(table_name, alter_operation))
179    }
180
181    fn parse_alter_table_unset(&mut self) -> Result<AlterTableOperation> {
182        let _ = self.parser.next_token();
183        let keys = self
184            .parser
185            .parse_comma_separated(parse_string_option_names)
186            .context(error::SyntaxSnafu)?
187            .into_iter()
188            .collect();
189
190        Ok(AlterTableOperation::UnsetTableOptions { keys })
191    }
192
193    fn parse_alter_table_add(&mut self) -> Result<AlterTableOperation> {
194        let _ = self.parser.next_token();
195        if let Some(constraint) = self
196            .parser
197            .parse_optional_table_constraint()
198            .context(error::SyntaxSnafu)?
199        {
200            Ok(AlterTableOperation::AddConstraint(constraint))
201        } else {
202            self.parser.prev_token();
203            let add_columns = self
204                .parser
205                .parse_comma_separated(parse_add_columns)
206                .context(error::SyntaxSnafu)?;
207            Ok(AlterTableOperation::AddColumns { add_columns })
208        }
209    }
210
211    fn parse_alter_table_drop_default(
212        &mut self,
213        column_name: Ident,
214    ) -> Result<AlterTableOperation> {
215        let drop_default = DropDefaultsOperation(column_name);
216        if self.parser.consume_token(&Token::Comma) {
217            let mut columns = self
218                .parser
219                .parse_comma_separated(parse_alter_column_drop_default)
220                .context(error::SyntaxSnafu)?;
221            columns.insert(0, drop_default);
222            Ok(AlterTableOperation::DropDefaults { columns })
223        } else {
224            Ok(AlterTableOperation::DropDefaults {
225                columns: vec![drop_default],
226            })
227        }
228    }
229
230    fn parse_alter_table_set_default(&mut self, column_name: Ident) -> Result<AlterTableOperation> {
231        let default_constraint = self.parser.parse_expr().context(error::SyntaxSnafu)?;
232        let set_default = SetDefaultsOperation {
233            column_name,
234            default_constraint,
235        };
236        if self.parser.consume_token(&Token::Comma) {
237            let mut defaults = self
238                .parser
239                .parse_comma_separated(parse_alter_column_set_default)
240                .context(error::SyntaxSnafu)?;
241            defaults.insert(0, set_default);
242            Ok(AlterTableOperation::SetDefaults { defaults })
243        } else {
244            Ok(AlterTableOperation::SetDefaults {
245                defaults: vec![set_default],
246            })
247        }
248    }
249
250    fn parse_alter_table_modify(&mut self) -> Result<AlterTableOperation> {
251        let _ = self.parser.next_token();
252        self.parser
253            .expect_keyword(Keyword::COLUMN)
254            .context(error::SyntaxSnafu)?;
255        let column_name = Self::canonicalize_identifier(
256            self.parser.parse_identifier().context(error::SyntaxSnafu)?,
257        );
258
259        match self.parser.peek_token().token {
260            Token::Word(w) => {
261                if w.value.eq_ignore_ascii_case("UNSET") {
262                    // consume the current token.
263                    self.parser.next_token();
264                    self.parse_alter_column_unset_index(column_name)
265                } else if w.keyword == Keyword::SET {
266                    // consume the current token.
267                    self.parser.next_token();
268                    if let Token::Word(w) = self.parser.peek_token().token
269                        && matches!(w.keyword, Keyword::DEFAULT)
270                    {
271                        self.parser
272                            .expect_keyword(Keyword::DEFAULT)
273                            .context(error::SyntaxSnafu)?;
274                        self.parse_alter_table_set_default(column_name)
275                    } else {
276                        self.parse_alter_column_set_index(column_name)
277                    }
278                } else if w.keyword == Keyword::DROP {
279                    // consume the current token.
280                    self.parser.next_token();
281                    self.parser
282                        .expect_keyword(Keyword::DEFAULT)
283                        .context(error::SyntaxSnafu)?;
284                    self.parse_alter_table_drop_default(column_name)
285                } else {
286                    let data_type = self.parser.parse_data_type().context(error::SyntaxSnafu)?;
287                    Ok(AlterTableOperation::ModifyColumnType {
288                        column_name,
289                        target_type: data_type,
290                    })
291                }
292            }
293            _ => self.expected(
294                "SET or UNSET or data type after MODIFY COLUMN",
295                self.parser.peek_token(),
296            )?,
297        }
298    }
299
300    fn parse_alter_column_unset_index(
301        &mut self,
302        column_name: Ident,
303    ) -> Result<AlterTableOperation> {
304        match self.parser.next_token() {
305            TokenWithSpan {
306                token: Token::Word(w),
307                ..
308            } if w.keyword == Keyword::FULLTEXT => {
309                self.parser
310                    .expect_keyword(Keyword::INDEX)
311                    .context(error::SyntaxSnafu)?;
312                Ok(AlterTableOperation::UnsetIndex {
313                    options: UnsetIndexOperation::Fulltext { column_name },
314                })
315            }
316
317            TokenWithSpan {
318                token: Token::Word(w),
319                ..
320            } if w.value.eq_ignore_ascii_case(INVERTED) => {
321                self.parser
322                    .expect_keyword(Keyword::INDEX)
323                    .context(error::SyntaxSnafu)?;
324                Ok(AlterTableOperation::UnsetIndex {
325                    options: UnsetIndexOperation::Inverted { column_name },
326                })
327            }
328
329            TokenWithSpan {
330                token: Token::Word(w),
331                ..
332            } if w.value.eq_ignore_ascii_case("SKIPPING") => {
333                self.parser
334                    .expect_keyword(Keyword::INDEX)
335                    .context(error::SyntaxSnafu)?;
336                Ok(AlterTableOperation::UnsetIndex {
337                    options: UnsetIndexOperation::Skipping { column_name },
338                })
339            }
340            _ => self.expected(
341                format!(
342                    "{:?} OR INVERTED INDEX OR SKIPPING INDEX",
343                    Keyword::FULLTEXT
344                )
345                .as_str(),
346                self.parser.peek_token(),
347            ),
348        }
349    }
350
351    fn parse_alter_column_set_index(&mut self, column_name: Ident) -> Result<AlterTableOperation> {
352        match self.parser.next_token() {
353            TokenWithSpan {
354                token: Token::Word(w),
355                ..
356            } if w.keyword == Keyword::FULLTEXT => {
357                self.parser
358                    .expect_keyword(Keyword::INDEX)
359                    .context(error::SyntaxSnafu)?;
360                self.parse_alter_column_fulltext(column_name)
361            }
362
363            TokenWithSpan {
364                token: Token::Word(w),
365                ..
366            } if w.value.eq_ignore_ascii_case(INVERTED) => {
367                self.parser
368                    .expect_keyword(Keyword::INDEX)
369                    .context(error::SyntaxSnafu)?;
370                Ok(AlterTableOperation::SetIndex {
371                    options: SetIndexOperation::Inverted { column_name },
372                })
373            }
374
375            TokenWithSpan {
376                token: Token::Word(w),
377                ..
378            } if w.value.eq_ignore_ascii_case("SKIPPING") => {
379                self.parser
380                    .expect_keyword(Keyword::INDEX)
381                    .context(error::SyntaxSnafu)?;
382                self.parse_alter_column_skipping(column_name)
383            }
384            t => self.expected(
385                format!("{:?} OR INVERTED OR SKIPPING INDEX", Keyword::FULLTEXT).as_str(),
386                t,
387            ),
388        }
389    }
390
391    fn parse_alter_column_fulltext(&mut self, column_name: Ident) -> Result<AlterTableOperation> {
392        let mut options = self
393            .parser
394            .parse_options(Keyword::WITH)
395            .context(error::SyntaxSnafu)?
396            .into_iter()
397            .map(parse_option_string)
398            .collect::<Result<HashMap<String, String>>>()?;
399
400        for key in options.keys() {
401            ensure!(
402                validate_column_fulltext_create_option(key),
403                InvalidColumnOptionSnafu {
404                    name: column_name.to_string(),
405                    msg: format!("invalid FULLTEXT option: {key}"),
406                }
407            );
408        }
409
410        options.insert(
411            COLUMN_FULLTEXT_CHANGE_OPT_KEY_ENABLE.to_string(),
412            "true".to_string(),
413        );
414
415        Ok(AlterTableOperation::SetIndex {
416            options: SetIndexOperation::Fulltext {
417                column_name,
418                options: options.try_into().context(SetFulltextOptionSnafu)?,
419            },
420        })
421    }
422
423    fn parse_alter_column_skipping(&mut self, column_name: Ident) -> Result<AlterTableOperation> {
424        let options = self
425            .parser
426            .parse_options(Keyword::WITH)
427            .context(error::SyntaxSnafu)?
428            .into_iter()
429            .map(parse_option_string)
430            .collect::<Result<HashMap<String, String>>>()?;
431
432        for key in options.keys() {
433            ensure!(
434                validate_column_skipping_index_create_option(key),
435                InvalidColumnOptionSnafu {
436                    name: column_name.to_string(),
437                    msg: format!("invalid SKIPPING INDEX option: {key}"),
438                }
439            );
440        }
441
442        Ok(AlterTableOperation::SetIndex {
443            options: SetIndexOperation::Skipping {
444                column_name,
445                options: options
446                    .try_into()
447                    .context(error::SetSkippingIndexOptionSnafu)?,
448            },
449        })
450    }
451}
452
453fn parse_alter_column_drop_default(
454    parser: &mut Parser,
455) -> std::result::Result<DropDefaultsOperation, ParserError> {
456    parser.expect_keywords(&[Keyword::MODIFY, Keyword::COLUMN])?;
457    let column_name = ParserContext::canonicalize_identifier(parser.parse_identifier()?);
458    let t = parser.next_token();
459    match t.token {
460        Token::Word(w) if w.keyword == Keyword::DROP => {
461            parser.expect_keyword(Keyword::DEFAULT)?;
462            Ok(DropDefaultsOperation(column_name))
463        }
464        _ => Err(ParserError::ParserError(format!(
465            "Unexpected keyword, expect DROP, got: `{t}`"
466        ))),
467    }
468}
469
470fn parse_alter_column_set_default(
471    parser: &mut Parser,
472) -> std::result::Result<SetDefaultsOperation, ParserError> {
473    parser.expect_keywords(&[Keyword::MODIFY, Keyword::COLUMN])?;
474    let column_name = ParserContext::canonicalize_identifier(parser.parse_identifier()?);
475    let t = parser.next_token();
476    match t.token {
477        Token::Word(w) if w.keyword == Keyword::SET => {
478            parser.expect_keyword(Keyword::DEFAULT)?;
479            if let Ok(default_constraint) = parser.parse_expr() {
480                Ok(SetDefaultsOperation {
481                    column_name,
482                    default_constraint,
483                })
484            } else {
485                Err(ParserError::ParserError(format!(
486                    "Invalid default value after SET DEFAULT, got: `{}`",
487                    parser.peek_token()
488                )))
489            }
490        }
491        _ => Err(ParserError::ParserError(format!(
492            "Unexpected keyword, expect SET, got: `{t}`"
493        ))),
494    }
495}
496
497/// Parses a string literal and an optional string literal value.
498fn parse_string_options(parser: &mut Parser) -> std::result::Result<(String, String), ParserError> {
499    let name = parser.parse_literal_string()?;
500    parser.expect_token(&Token::Eq)?;
501    let value = if parser.parse_keyword(Keyword::NULL) {
502        "".to_string()
503    } else {
504        let next_token = parser.peek_token();
505        if let Token::Number(number_as_string, _) = next_token.token {
506            parser.advance_token();
507            number_as_string
508        } else {
509            parser.parse_literal_string().map_err(|_|{
510                ParserError::ParserError(format!("Unexpected option value for alter table statements, expect string literal, numeric literal or NULL, got: `{}`", next_token))
511            })?
512        }
513    };
514    Ok((name, value))
515}
516
517fn parse_add_columns(parser: &mut Parser) -> std::result::Result<AddColumn, ParserError> {
518    parser.expect_keyword(Keyword::ADD)?;
519    let _ = parser.parse_keyword(Keyword::COLUMN);
520    let add_if_not_exists = parser.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
521    let mut column_def = parser.parse_column_def()?;
522    column_def.name = ParserContext::canonicalize_identifier(column_def.name);
523    let location = if parser.parse_keyword(Keyword::FIRST) {
524        Some(AddColumnLocation::First)
525    } else if let Token::Word(word) = parser.peek_token().token {
526        if word.value.eq_ignore_ascii_case("AFTER") {
527            let _ = parser.next_token();
528            let name = ParserContext::canonicalize_identifier(parser.parse_identifier()?);
529            Some(AddColumnLocation::After {
530                column_name: name.value,
531            })
532        } else {
533            None
534        }
535    } else {
536        None
537    };
538    Ok(AddColumn {
539        column_def,
540        location,
541        add_if_not_exists,
542    })
543}
544
545/// Parses a comma separated list of string literals.
546fn parse_string_option_names(parser: &mut Parser) -> std::result::Result<String, ParserError> {
547    parser.parse_literal_string()
548}
549
550#[cfg(test)]
551mod tests {
552    use std::assert_matches::assert_matches;
553
554    use common_error::ext::ErrorExt;
555    use datatypes::schema::{FulltextAnalyzer, FulltextBackend, FulltextOptions};
556    use sqlparser::ast::{ColumnDef, ColumnOption, ColumnOptionDef, DataType};
557
558    use super::*;
559    use crate::ast::ObjectNamePartExt;
560    use crate::dialect::GreptimeDbDialect;
561    use crate::parser::ParseOptions;
562    use crate::statements::alter::AlterDatabaseOperation;
563
564    #[test]
565    fn test_parse_alter_database() {
566        let sql = "ALTER DATABASE test_db SET 'a'='A', 'b' = 'B'";
567        let mut result =
568            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
569                .unwrap();
570        assert_eq!(1, result.len());
571
572        let statement = result.remove(0);
573        assert_matches!(statement, Statement::AlterDatabase { .. });
574        match statement {
575            Statement::AlterDatabase(alter_database) => {
576                assert_eq!("test_db", alter_database.database_name().0[0].to_string());
577
578                let alter_operation = alter_database.alter_operation();
579                assert_matches!(
580                    alter_operation,
581                    AlterDatabaseOperation::SetDatabaseOption { .. }
582                );
583                match alter_operation {
584                    AlterDatabaseOperation::SetDatabaseOption { options } => {
585                        assert_eq!(2, options.len());
586                        assert_eq!("a", options[0].key);
587                        assert_eq!("A", options[0].value);
588                        assert_eq!("b", options[1].key);
589                        assert_eq!("B", options[1].value);
590                    }
591                    _ => unreachable!(),
592                }
593            }
594            _ => unreachable!(),
595        }
596        let sql = "ALTER DATABASE test_db UNSET 'a', 'b'";
597        let mut result =
598            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
599                .unwrap();
600        assert_eq!(1, result.len());
601        let statement = result.remove(0);
602        assert_matches!(statement, Statement::AlterDatabase { .. });
603        match statement {
604            Statement::AlterDatabase(alter_database) => {
605                assert_eq!("test_db", alter_database.database_name().0[0].to_string());
606                let alter_operation = alter_database.alter_operation();
607                assert_matches!(
608                    alter_operation,
609                    AlterDatabaseOperation::UnsetDatabaseOption { .. }
610                );
611                match alter_operation {
612                    AlterDatabaseOperation::UnsetDatabaseOption { keys } => {
613                        assert_eq!(2, keys.len());
614                        assert_eq!("a", keys[0]);
615                        assert_eq!("b", keys[1]);
616                    }
617                    _ => unreachable!(),
618                }
619            }
620            _ => unreachable!(),
621        }
622    }
623
624    #[test]
625    fn test_parse_alter_add_column() {
626        let sql = "ALTER TABLE my_metric_1 ADD tagk_i STRING Null;";
627        let mut result =
628            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
629                .unwrap();
630        assert_eq!(1, result.len());
631
632        let statement = result.remove(0);
633        assert_matches!(statement, Statement::AlterTable { .. });
634        match statement {
635            Statement::AlterTable(alter_table) => {
636                assert_eq!("my_metric_1", alter_table.table_name().0[0].to_string());
637
638                let alter_operation = alter_table.alter_operation();
639                assert_matches!(alter_operation, AlterTableOperation::AddColumns { .. });
640                match alter_operation {
641                    AlterTableOperation::AddColumns { add_columns } => {
642                        assert_eq!(add_columns.len(), 1);
643                        assert_eq!("tagk_i", add_columns[0].column_def.name.value);
644                        assert_eq!(DataType::String(None), add_columns[0].column_def.data_type);
645                        assert!(
646                            add_columns[0]
647                                .column_def
648                                .options
649                                .iter()
650                                .any(|o| matches!(o.option, ColumnOption::Null))
651                        );
652                        assert_eq!(&None, &add_columns[0].location);
653                    }
654                    _ => unreachable!(),
655                }
656            }
657            _ => unreachable!(),
658        }
659    }
660
661    #[test]
662    fn test_parse_alter_add_column_with_first() {
663        let sql = "ALTER TABLE my_metric_1 ADD tagk_i STRING Null FIRST;";
664        let mut result =
665            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
666                .unwrap();
667        assert_eq!(1, result.len());
668
669        let statement = result.remove(0);
670        assert_matches!(statement, Statement::AlterTable { .. });
671        match statement {
672            Statement::AlterTable(alter_table) => {
673                assert_eq!("my_metric_1", alter_table.table_name().0[0].to_string());
674
675                let alter_operation = alter_table.alter_operation();
676                assert_matches!(alter_operation, AlterTableOperation::AddColumns { .. });
677                match alter_operation {
678                    AlterTableOperation::AddColumns { add_columns } => {
679                        assert_eq!("tagk_i", add_columns[0].column_def.name.value);
680                        assert_eq!(DataType::String(None), add_columns[0].column_def.data_type);
681                        assert!(
682                            add_columns[0]
683                                .column_def
684                                .options
685                                .iter()
686                                .any(|o| matches!(o.option, ColumnOption::Null))
687                        );
688                        assert_eq!(&Some(AddColumnLocation::First), &add_columns[0].location);
689                    }
690                    _ => unreachable!(),
691                }
692            }
693            _ => unreachable!(),
694        }
695    }
696
697    #[test]
698    fn test_parse_alter_add_column_with_after() {
699        let sql =
700            "ALTER TABLE my_metric_1 ADD tagk_i STRING Null AFTER ts, add column tagl_i String;";
701        let mut result =
702            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
703                .unwrap();
704        assert_eq!(1, result.len());
705
706        let statement = result.remove(0);
707        assert_matches!(statement, Statement::AlterTable { .. });
708        match statement {
709            Statement::AlterTable(alter_table) => {
710                assert_eq!("my_metric_1", alter_table.table_name().0[0].to_string());
711
712                let alter_operation = alter_table.alter_operation();
713                assert_matches!(alter_operation, AlterTableOperation::AddColumns { .. });
714                match alter_operation {
715                    AlterTableOperation::AddColumns { add_columns } => {
716                        let expecteds: Vec<(Option<AddColumnLocation>, ColumnDef)> = vec![
717                            (
718                                Some(AddColumnLocation::After {
719                                    column_name: "ts".to_string(),
720                                }),
721                                ColumnDef {
722                                    name: Ident::new("tagk_i"),
723                                    data_type: DataType::String(None),
724                                    options: vec![ColumnOptionDef {
725                                        name: None,
726                                        option: ColumnOption::Null,
727                                    }],
728                                },
729                            ),
730                            (
731                                None,
732                                ColumnDef {
733                                    name: Ident::new("tagl_i"),
734                                    data_type: DataType::String(None),
735                                    options: vec![],
736                                },
737                            ),
738                        ];
739                        for (add_column, expected) in add_columns
740                            .iter()
741                            .zip(expecteds)
742                            .collect::<Vec<(&AddColumn, (Option<AddColumnLocation>, ColumnDef))>>()
743                        {
744                            assert_eq!(add_column.column_def, expected.1);
745                            assert_eq!(&expected.0, &add_column.location);
746                        }
747                    }
748                    _ => unreachable!(),
749                }
750            }
751            _ => unreachable!(),
752        }
753    }
754
755    #[test]
756    fn test_parse_add_column_if_not_exists() {
757        let sql = "ALTER TABLE test ADD COLUMN IF NOT EXISTS a INTEGER, ADD COLUMN b STRING, ADD COLUMN IF NOT EXISTS c INT;";
758        let mut result =
759            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
760                .unwrap();
761        assert_eq!(result.len(), 1);
762        let statement = result.remove(0);
763        assert_matches!(statement, Statement::AlterTable { .. });
764        match statement {
765            Statement::AlterTable(alter) => {
766                assert_eq!(alter.table_name.0[0].to_string(), "test");
767                assert_matches!(
768                    alter.alter_operation,
769                    AlterTableOperation::AddColumns { .. }
770                );
771                match alter.alter_operation {
772                    AlterTableOperation::AddColumns { add_columns } => {
773                        let expected = vec![
774                            AddColumn {
775                                column_def: ColumnDef {
776                                    name: Ident::new("a"),
777                                    data_type: DataType::Integer(None),
778                                    options: vec![],
779                                },
780                                location: None,
781                                add_if_not_exists: true,
782                            },
783                            AddColumn {
784                                column_def: ColumnDef {
785                                    name: Ident::new("b"),
786                                    data_type: DataType::String(None),
787                                    options: vec![],
788                                },
789                                location: None,
790                                add_if_not_exists: false,
791                            },
792                            AddColumn {
793                                column_def: ColumnDef {
794                                    name: Ident::new("c"),
795                                    data_type: DataType::Int(None),
796                                    options: vec![],
797                                },
798                                location: None,
799                                add_if_not_exists: true,
800                            },
801                        ];
802                        for (idx, add_column) in add_columns.into_iter().enumerate() {
803                            assert_eq!(add_column, expected[idx]);
804                        }
805                    }
806                    _ => unreachable!(),
807                }
808            }
809            _ => unreachable!(),
810        }
811    }
812
813    #[test]
814    fn test_parse_alter_drop_column() {
815        let sql = "ALTER TABLE my_metric_1 DROP a";
816        let result =
817            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
818                .unwrap_err();
819        let err = result.output_msg();
820        assert_eq!(
821            err,
822            "Invalid SQL syntax: sql parser error: Expected: COLUMN, found: a at Line: 1, Column: 30"
823        );
824
825        let sql = "ALTER TABLE my_metric_1 DROP COLUMN a";
826        let mut result =
827            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
828                .unwrap();
829        assert_eq!(1, result.len());
830
831        let statement = result.remove(0);
832        assert_matches!(statement, Statement::AlterTable { .. });
833        match statement {
834            Statement::AlterTable(alter_table) => {
835                assert_eq!("my_metric_1", alter_table.table_name().0[0].to_string());
836
837                let alter_operation = alter_table.alter_operation();
838                assert_matches!(alter_operation, AlterTableOperation::DropColumn { .. });
839                match alter_operation {
840                    AlterTableOperation::DropColumn { name } => {
841                        assert_eq!("a", name.value);
842                    }
843                    _ => unreachable!(),
844                }
845            }
846            _ => unreachable!(),
847        }
848    }
849
850    #[test]
851    fn test_parse_alter_modify_column_type() {
852        let sql_1 = "ALTER TABLE my_metric_1 MODIFY COLUMN a STRING";
853        let result_1 = ParserContext::create_with_dialect(
854            sql_1,
855            &GreptimeDbDialect {},
856            ParseOptions::default(),
857        )
858        .unwrap();
859
860        let sql_2 = "ALTER TABLE my_metric_1 MODIFY COLUMN a STRING";
861        let mut result_2 = ParserContext::create_with_dialect(
862            sql_2,
863            &GreptimeDbDialect {},
864            ParseOptions::default(),
865        )
866        .unwrap();
867        assert_eq!(result_1, result_2);
868        assert_eq!(1, result_2.len());
869
870        let statement = result_2.remove(0);
871        assert_matches!(statement, Statement::AlterTable { .. });
872        match statement {
873            Statement::AlterTable(alter_table) => {
874                assert_eq!("my_metric_1", alter_table.table_name().0[0].to_string());
875
876                let alter_operation = alter_table.alter_operation();
877                assert_matches!(
878                    alter_operation,
879                    AlterTableOperation::ModifyColumnType { .. }
880                );
881                match alter_operation {
882                    AlterTableOperation::ModifyColumnType {
883                        column_name,
884                        target_type,
885                    } => {
886                        assert_eq!("a", column_name.value);
887                        assert_eq!(DataType::String(None), *target_type);
888                    }
889                    _ => unreachable!(),
890                }
891            }
892            _ => unreachable!(),
893        }
894    }
895
896    #[test]
897    fn test_parse_alter_change_column_alias_type() {
898        let sql_1 = "ALTER TABLE my_metric_1 MODIFY COLUMN a MediumText";
899        let mut result_1 = ParserContext::create_with_dialect(
900            sql_1,
901            &GreptimeDbDialect {},
902            ParseOptions::default(),
903        )
904        .unwrap();
905
906        match result_1.remove(0) {
907            Statement::AlterTable(alter_table) => {
908                assert_eq!("my_metric_1", alter_table.table_name().0[0].to_string());
909
910                let alter_operation = alter_table.alter_operation();
911                assert_matches!(
912                    alter_operation,
913                    AlterTableOperation::ModifyColumnType { .. }
914                );
915                match alter_operation {
916                    AlterTableOperation::ModifyColumnType {
917                        column_name,
918                        target_type,
919                    } => {
920                        assert_eq!("a", column_name.value);
921                        assert_eq!(DataType::MediumText, *target_type);
922                    }
923                    _ => unreachable!(),
924                }
925            }
926            _ => unreachable!(),
927        }
928
929        let sql_2 = "ALTER TABLE my_metric_1 MODIFY COLUMN a TIMESTAMP_US";
930        let mut result_2 = ParserContext::create_with_dialect(
931            sql_2,
932            &GreptimeDbDialect {},
933            ParseOptions::default(),
934        )
935        .unwrap();
936
937        match result_2.remove(0) {
938            Statement::AlterTable(alter_table) => {
939                assert_eq!("my_metric_1", alter_table.table_name().0[0].to_string());
940
941                let alter_operation = alter_table.alter_operation();
942                assert_matches!(
943                    alter_operation,
944                    AlterTableOperation::ModifyColumnType { .. }
945                );
946                match alter_operation {
947                    AlterTableOperation::ModifyColumnType {
948                        column_name,
949                        target_type,
950                    } => {
951                        assert_eq!("a", column_name.value);
952                        assert!(matches!(target_type, DataType::Timestamp(Some(6), _)));
953                    }
954                    _ => unreachable!(),
955                }
956            }
957            _ => unreachable!(),
958        }
959    }
960
961    #[test]
962    fn test_parse_alter_rename_table() {
963        let sql = "ALTER TABLE test_table table_t";
964        let result =
965            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
966                .unwrap_err();
967        let err = result.output_msg();
968        assert_eq!(
969            err,
970            "Invalid SQL syntax: sql parser error: Expected ADD or DROP or MODIFY or RENAME or SET after ALTER TABLE, found: table_t"
971        );
972
973        let sql = "ALTER TABLE test_table RENAME table_t";
974        let mut result =
975            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
976                .unwrap();
977        assert_eq!(1, result.len());
978
979        let statement = result.remove(0);
980        assert_matches!(statement, Statement::AlterTable { .. });
981        match statement {
982            Statement::AlterTable(alter_table) => {
983                assert_eq!("test_table", alter_table.table_name().0[0].to_string());
984
985                let alter_operation = alter_table.alter_operation();
986                assert_matches!(alter_operation, AlterTableOperation::RenameTable { .. });
987                match alter_operation {
988                    AlterTableOperation::RenameTable { new_table_name } => {
989                        assert_eq!("table_t", new_table_name);
990                    }
991                    _ => unreachable!(),
992                }
993            }
994            _ => unreachable!(),
995        }
996    }
997
998    fn check_parse_alter_table_set_options(sql: &str, expected: &[(&str, &str)]) {
999        let result =
1000            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
1001                .unwrap();
1002        assert_eq!(1, result.len());
1003        let Statement::AlterTable(alter) = &result[0] else {
1004            unreachable!()
1005        };
1006        assert_eq!("test_table", alter.table_name.0[0].to_string());
1007        let AlterTableOperation::SetTableOptions { options } = &alter.alter_operation else {
1008            unreachable!()
1009        };
1010
1011        assert_eq!(sql, alter.to_string());
1012        let res = options
1013            .iter()
1014            .map(|o| (o.key.as_str(), o.value.as_str()))
1015            .collect::<Vec<_>>();
1016        assert_eq!(expected, &res);
1017    }
1018
1019    fn check_parse_alter_table_unset_options(sql: &str, expected: &[&str]) {
1020        let result =
1021            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
1022                .unwrap();
1023        assert_eq!(1, result.len());
1024        let Statement::AlterTable(alter) = &result[0] else {
1025            unreachable!()
1026        };
1027        assert_eq!("test_table", alter.table_name.0[0].to_string());
1028        let AlterTableOperation::UnsetTableOptions { keys } = &alter.alter_operation else {
1029            unreachable!()
1030        };
1031
1032        assert_eq!(sql, alter.to_string());
1033        let res = keys.iter().map(|o| o.to_string()).collect::<Vec<_>>();
1034        assert_eq!(expected, &res);
1035    }
1036
1037    #[test]
1038    fn test_parse_alter_table_set_options() {
1039        check_parse_alter_table_set_options("ALTER TABLE test_table SET 'a'='A'", &[("a", "A")]);
1040        check_parse_alter_table_set_options(
1041            "ALTER TABLE test_table SET 'a'='A','b'='B'",
1042            &[("a", "A"), ("b", "B")],
1043        );
1044        check_parse_alter_table_set_options(
1045            "ALTER TABLE test_table SET 'a'='A','b'='B','c'='C'",
1046            &[("a", "A"), ("b", "B"), ("c", "C")],
1047        );
1048        check_parse_alter_table_set_options("ALTER TABLE test_table SET 'a'=NULL", &[("a", "")]);
1049
1050        ParserContext::create_with_dialect(
1051            "ALTER TABLE test_table SET a INTEGER",
1052            &GreptimeDbDialect {},
1053            ParseOptions::default(),
1054        )
1055        .unwrap_err();
1056    }
1057
1058    #[test]
1059    fn test_parse_alter_table_unset_options() {
1060        check_parse_alter_table_unset_options("ALTER TABLE test_table UNSET 'a'", &["a"]);
1061        check_parse_alter_table_unset_options("ALTER TABLE test_table UNSET 'a','b'", &["a", "b"]);
1062        ParserContext::create_with_dialect(
1063            "ALTER TABLE test_table UNSET a INTEGER",
1064            &GreptimeDbDialect {},
1065            ParseOptions::default(),
1066        )
1067        .unwrap_err();
1068    }
1069
1070    #[test]
1071    fn test_parse_alter_column_fulltext() {
1072        let sql = "ALTER TABLE test_table MODIFY COLUMN a SET FULLTEXT INDEX WITH(analyzer='English',case_sensitive='false',backend='bloom',granularity=1000,false_positive_rate=0.01)";
1073        let mut result =
1074            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
1075                .unwrap();
1076
1077        assert_eq!(1, result.len());
1078        let statement = result.remove(0);
1079        assert_matches!(statement, Statement::AlterTable { .. });
1080        match statement {
1081            Statement::AlterTable(alter_table) => {
1082                assert_eq!("test_table", alter_table.table_name().0[0].to_string());
1083
1084                let alter_operation = alter_table.alter_operation();
1085                match alter_operation {
1086                    AlterTableOperation::SetIndex {
1087                        options:
1088                            SetIndexOperation::Fulltext {
1089                                column_name,
1090                                options,
1091                            },
1092                    } => {
1093                        assert_eq!("a", column_name.value);
1094                        assert_eq!(
1095                            FulltextOptions::new_unchecked(
1096                                true,
1097                                FulltextAnalyzer::English,
1098                                false,
1099                                FulltextBackend::Bloom,
1100                                1000,
1101                                0.01,
1102                            ),
1103                            *options
1104                        );
1105                    }
1106                    _ => unreachable!(),
1107                };
1108            }
1109            _ => unreachable!(),
1110        }
1111
1112        let sql = "ALTER TABLE test_table MODIFY COLUMN a UNSET FULLTEXT INDEX";
1113        let mut result =
1114            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
1115                .unwrap();
1116        assert_eq!(1, result.len());
1117        let statement = result.remove(0);
1118        assert_matches!(statement, Statement::AlterTable { .. });
1119        match statement {
1120            Statement::AlterTable(alter_table) => {
1121                assert_eq!("test_table", alter_table.table_name().0[0].to_string());
1122
1123                let alter_operation = alter_table.alter_operation();
1124                assert_eq!(
1125                    alter_operation,
1126                    &AlterTableOperation::UnsetIndex {
1127                        options: UnsetIndexOperation::Fulltext {
1128                            column_name: Ident::new("a"),
1129                        }
1130                    }
1131                );
1132            }
1133            _ => unreachable!(),
1134        }
1135
1136        let invalid_sql =
1137            "ALTER TABLE test_table MODIFY COLUMN a SET FULLTEXT INDEX WITH('abcd'='true')";
1138        let result = ParserContext::create_with_dialect(
1139            invalid_sql,
1140            &GreptimeDbDialect {},
1141            ParseOptions::default(),
1142        )
1143        .unwrap_err();
1144        let err = result.to_string();
1145        assert_eq!(
1146            err,
1147            "Invalid column option, column name: a, error: invalid FULLTEXT option: abcd"
1148        );
1149    }
1150
1151    #[test]
1152    fn test_parse_alter_column_inverted() {
1153        let sql = "ALTER TABLE test_table MODIFY COLUMN a SET INVERTED INDEX";
1154        let mut result =
1155            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
1156                .unwrap();
1157
1158        assert_eq!(1, result.len());
1159        let statement = result.remove(0);
1160        assert_matches!(statement, Statement::AlterTable { .. });
1161        match statement {
1162            Statement::AlterTable(alter_table) => {
1163                assert_eq!("test_table", alter_table.table_name().0[0].to_string());
1164
1165                let alter_operation = alter_table.alter_operation();
1166                match alter_operation {
1167                    AlterTableOperation::SetIndex {
1168                        options: SetIndexOperation::Inverted { column_name },
1169                    } => assert_eq!("a", column_name.value),
1170                    _ => unreachable!(),
1171                };
1172            }
1173            _ => unreachable!(),
1174        }
1175
1176        let sql = "ALTER TABLE test_table MODIFY COLUMN a UNSET INVERTED INDEX";
1177        let mut result =
1178            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
1179                .unwrap();
1180        assert_eq!(1, result.len());
1181        let statement = result.remove(0);
1182        assert_matches!(statement, Statement::AlterTable { .. });
1183        match statement {
1184            Statement::AlterTable(alter_table) => {
1185                assert_eq!("test_table", alter_table.table_name().0[0].to_string());
1186
1187                let alter_operation = alter_table.alter_operation();
1188                assert_eq!(
1189                    alter_operation,
1190                    &AlterTableOperation::UnsetIndex {
1191                        options: UnsetIndexOperation::Inverted {
1192                            column_name: Ident::new("a"),
1193                        }
1194                    }
1195                );
1196            }
1197            _ => unreachable!(),
1198        }
1199
1200        let invalid_sql = "ALTER TABLE test_table MODIFY COLUMN a SET INVERTED";
1201        ParserContext::create_with_dialect(
1202            invalid_sql,
1203            &GreptimeDbDialect {},
1204            ParseOptions::default(),
1205        )
1206        .unwrap_err();
1207    }
1208
1209    #[test]
1210    fn test_parse_alter_with_numeric_value() {
1211        for sql in [
1212            "ALTER TABLE test SET 'compaction.twcs.trigger_file_num'=8;",
1213            "ALTER TABLE test SET 'compaction.twcs.trigger_file_num'='8';",
1214        ] {
1215            let mut result = ParserContext::create_with_dialect(
1216                sql,
1217                &GreptimeDbDialect {},
1218                ParseOptions::default(),
1219            )
1220            .unwrap();
1221            assert_eq!(1, result.len());
1222
1223            let statement = result.remove(0);
1224            assert_matches!(statement, Statement::AlterTable { .. });
1225            match statement {
1226                Statement::AlterTable(alter_table) => {
1227                    let alter_operation = alter_table.alter_operation();
1228                    assert_matches!(alter_operation, AlterTableOperation::SetTableOptions { .. });
1229                    match alter_operation {
1230                        AlterTableOperation::SetTableOptions { options } => {
1231                            assert_eq!(options.len(), 1);
1232                            assert_eq!(options[0].key, "compaction.twcs.trigger_file_num");
1233                            assert_eq!(options[0].value, "8");
1234                        }
1235                        _ => unreachable!(),
1236                    }
1237                }
1238                _ => unreachable!(),
1239            }
1240        }
1241    }
1242
1243    #[test]
1244    fn test_parse_alter_drop_default() {
1245        let columns = vec![vec!["a"], vec!["a", "b", "c"]];
1246        for col in columns {
1247            let sql = col
1248                .iter()
1249                .map(|x| format!("MODIFY COLUMN {x} DROP DEFAULT"))
1250                .collect::<Vec<String>>()
1251                .join(",");
1252            let sql = format!("ALTER TABLE test_table {sql}");
1253            let mut result = ParserContext::create_with_dialect(
1254                &sql,
1255                &GreptimeDbDialect {},
1256                ParseOptions::default(),
1257            )
1258            .unwrap();
1259            assert_eq!(1, result.len());
1260            let statement = result.remove(0);
1261            assert_matches!(statement, Statement::AlterTable { .. });
1262            match statement {
1263                Statement::AlterTable(alter_table) => {
1264                    assert_eq!(
1265                        "test_table",
1266                        alter_table.table_name().0[0].to_string_unquoted()
1267                    );
1268                    let alter_operation = alter_table.alter_operation();
1269                    match alter_operation {
1270                        AlterTableOperation::DropDefaults { columns } => {
1271                            assert_eq!(col.len(), columns.len());
1272                            for i in 0..columns.len() {
1273                                assert_eq!(col[i], columns[i].0.value);
1274                            }
1275                        }
1276                        _ => unreachable!(),
1277                    }
1278                }
1279                _ => unreachable!(),
1280            }
1281        }
1282    }
1283
1284    #[test]
1285    fn test_parse_alter_set_default() {
1286        let columns = vec![vec!["a"], vec!["a", "b"], vec!["a", "b", "c"]];
1287        for col in columns {
1288            let sql = col
1289                .iter()
1290                .map(|x| format!("MODIFY COLUMN {x} SET DEFAULT 100"))
1291                .collect::<Vec<String>>()
1292                .join(",");
1293            let sql = format!("ALTER TABLE test_table {sql}");
1294            let mut result = ParserContext::create_with_dialect(
1295                &sql,
1296                &GreptimeDbDialect {},
1297                ParseOptions::default(),
1298            )
1299            .unwrap();
1300            assert_eq!(1, result.len());
1301            let statement = result.remove(0);
1302            assert_matches!(statement, Statement::AlterTable { .. });
1303            match statement {
1304                Statement::AlterTable(alter_table) => {
1305                    assert_eq!("test_table", alter_table.table_name().to_string());
1306                    let alter_operation = alter_table.alter_operation();
1307                    match alter_operation {
1308                        AlterTableOperation::SetDefaults { defaults } => {
1309                            assert_eq!(col.len(), defaults.len());
1310                            for i in 0..defaults.len() {
1311                                assert_eq!(col[i], defaults[i].column_name.to_string());
1312                                assert_eq!(
1313                                    "100".to_string(),
1314                                    defaults[i].default_constraint.to_string()
1315                                );
1316                            }
1317                        }
1318                        _ => unreachable!(),
1319                    }
1320                }
1321                _ => unreachable!(),
1322            }
1323        }
1324    }
1325
1326    #[test]
1327    fn test_parse_alter_set_default_invalid() {
1328        let sql = "ALTER TABLE test_table MODIFY COLUMN a SET 100;";
1329        let result =
1330            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
1331                .unwrap_err();
1332        let err = result.output_msg();
1333        assert_eq!(
1334            err,
1335            "Invalid SQL syntax: sql parser error: Expected FULLTEXT OR INVERTED OR SKIPPING INDEX, found: 100"
1336        );
1337
1338        let sql = "ALTER TABLE test_table MODIFY COLUMN a SET DEFAULT 100, b SET DEFAULT 200";
1339        let result =
1340            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
1341                .unwrap_err();
1342        let err = result.output_msg();
1343        assert_eq!(
1344            err,
1345            "Invalid SQL syntax: sql parser error: Expected: MODIFY, found: b at Line: 1, Column: 57"
1346        );
1347
1348        let sql = "ALTER TABLE test_table MODIFY COLUMN a SET DEFAULT 100, MODIFY COLUMN b DROP DEFAULT 200";
1349        let result =
1350            ParserContext::create_with_dialect(sql, &GreptimeDbDialect {}, ParseOptions::default())
1351                .unwrap_err();
1352        let err = result.output_msg();
1353        assert_eq!(
1354            err,
1355            "Invalid SQL syntax: sql parser error: Unexpected keyword, expect SET, got: `DROP`"
1356        );
1357    }
1358}