sqlparser_mysql/dds/
drop_index.rs

1use nom::bytes::complete::tag_no_case;
2use nom::character::complete::{multispace0, multispace1};
3use nom::combinator::{map, opt};
4use nom::sequence::tuple;
5use nom::IResult;
6use std::fmt::{Display, Formatter};
7
8use base::algorithm_type::AlgorithmType;
9use base::error::ParseSQLError;
10use base::lock_type::LockType;
11use base::table::Table;
12use base::CommonParser;
13
14/// parse `DROP INDEX index_name ON tbl_name
15///     [algorithm_option | lock_option] ...`
16///
17/// algorithm_option: `ALGORITHM [=] {DEFAULT | INSTANT | INPLACE | COPY}`
18/// lock_option: `LOCK [=] {DEFAULT | NONE | SHARED | EXCLUSIVE}`
19#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
20pub struct DropIndexStatement {
21    pub index_name: String,
22    pub table: Table,
23    pub algorithm_option: Option<AlgorithmType>,
24    pub lock_option: Option<LockType>,
25}
26
27impl Display for DropIndexStatement {
28    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
29        write!(f, "DROP INDEX {} ON {}", &self.index_name, &self.table);
30        if let Some(algorithm_option) = &self.algorithm_option {
31            write!(f, " {}", algorithm_option);
32        }
33        if let Some(lock_option) = &self.lock_option {
34            write!(f, " {}", lock_option);
35        }
36        Ok(())
37    }
38}
39
40impl DropIndexStatement {
41    pub fn parse(i: &str) -> IResult<&str, DropIndexStatement, ParseSQLError<&str>> {
42        map(
43            tuple((
44                tuple((tag_no_case("DROP"), multispace1)),
45                tuple((tag_no_case("INDEX"), multispace1)),
46                map(
47                    tuple((
48                        CommonParser::sql_identifier,
49                        multispace1,
50                        tag_no_case("ON"),
51                        multispace1,
52                    )),
53                    |x| String::from(x.0),
54                ),
55                Table::without_alias, // tbl_name
56                multispace0,
57                opt(AlgorithmType::parse), // algorithm_option
58                multispace0,
59                opt(LockType::parse), // lock_option
60                multispace0,
61                CommonParser::statement_terminator,
62            )),
63            |(_, _, index_name, table, _, algorithm_option, _, lock_option, _, _)| {
64                DropIndexStatement {
65                    index_name,
66                    table,
67                    algorithm_option,
68                    lock_option,
69                }
70            },
71        )(i)
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use base::algorithm_type::AlgorithmType;
78    use base::lock_type::LockType;
79    use base::Table;
80    use dds::drop_index::DropIndexStatement;
81
82    #[test]
83    fn parse_drop_index() {
84        let sqls = [
85            "drop index agent_id_index on tbl_name;",
86            "drop index agent_id_index on db_name.tbl_name ALGORITHM = COPY;",
87            "DROP INDEX IX_brand_id ON tbl_name LOCK = default;",
88            "DROP INDEX IX_brand_id ON db_name.tbl_name ALGORITHM = COPY LOCK = default;",
89        ];
90        let exp_statements = [
91            DropIndexStatement {
92                index_name: "agent_id_index".to_string(),
93                table: "tbl_name".into(),
94                algorithm_option: None,
95                lock_option: None,
96            },
97            DropIndexStatement {
98                index_name: "agent_id_index".to_string(),
99                table: ("db_name", "tbl_name").into(),
100                algorithm_option: Some(AlgorithmType::Copy),
101                lock_option: None,
102            },
103            DropIndexStatement {
104                index_name: "IX_brand_id".to_string(),
105                table: "tbl_name".into(),
106                algorithm_option: None,
107                lock_option: Some(LockType::Default),
108            },
109            DropIndexStatement {
110                index_name: "IX_brand_id".to_string(),
111                table: ("db_name", "tbl_name").into(),
112                algorithm_option: Some(AlgorithmType::Copy),
113                lock_option: Some(LockType::Default),
114            },
115        ];
116
117        for i in 0..sqls.len() {
118            let res = DropIndexStatement::parse(sqls[i]);
119            assert!(res.is_ok());
120            assert_eq!(res.unwrap().1, exp_statements[i]);
121        }
122    }
123}