Skip to content

Commit 5aacc5e

Browse files
author
mashuai
committed
add create index and drop index support
1 parent 2644bc4 commit 5aacc5e

File tree

4 files changed

+98
-3
lines changed

4 files changed

+98
-3
lines changed

src/ast/mod.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,15 @@ pub enum Statement {
476476
file_format: Option<FileFormat>,
477477
location: Option<String>,
478478
},
479+
/// CREATE INDEX
480+
CreateIndex {
481+
/// index name
482+
name: ObjectName,
483+
table_name: ObjectName,
484+
columns: Vec<Ident>,
485+
unique: bool,
486+
if_not_exists: bool,
487+
},
479488
/// ALTER TABLE
480489
AlterTable {
481490
/// Table name
@@ -655,6 +664,28 @@ impl fmt::Display for Statement {
655664
}
656665
Ok(())
657666
}
667+
Statement::CreateIndex {
668+
name,
669+
table_name,
670+
columns,
671+
unique,
672+
if_not_exists,
673+
} => {
674+
write!(
675+
f,
676+
"CREATE{}INDEX{}{} ON {}({}",
677+
if *unique { " UNIQUE " } else { " " },
678+
if *if_not_exists {
679+
" IF NOT EXISTS "
680+
} else {
681+
" "
682+
},
683+
name,
684+
table_name,
685+
display_separated(columns, ",")
686+
)?;
687+
write!(f, ");")
688+
}
658689
Statement::AlterTable { name, operation } => {
659690
write!(f, "ALTER TABLE {} {}", name, operation)
660691
}
@@ -819,13 +850,15 @@ impl FromStr for FileFormat {
819850
pub enum ObjectType {
820851
Table,
821852
View,
853+
Index,
822854
}
823855

824856
impl fmt::Display for ObjectType {
825857
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
826858
f.write_str(match self {
827859
ObjectType::Table => "TABLE",
828860
ObjectType::View => "VIEW",
861+
ObjectType::Index => "INDEX",
829862
})
830863
}
831864
}

src/dialect/keywords.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,8 @@ define_keywords!(
420420
WORK,
421421
YEAR,
422422
ZONE,
423-
END_EXEC = "END-EXEC"
423+
END_EXEC = "END-EXEC",
424+
INDEX
424425
);
425426

426427
/// These keywords can't be used as a table alias, so that `FROM table_name alias`

src/parser.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -855,13 +855,17 @@ impl Parser {
855855
pub fn parse_create(&mut self) -> Result<Statement, ParserError> {
856856
if self.parse_keyword("TABLE") {
857857
self.parse_create_table()
858+
} else if self.parse_keyword("INDEX") {
859+
self.parse_create_index(false)
860+
} else if self.parse_keywords(vec!["UNIQUE", "INDEX"]) {
861+
self.parse_create_index(true)
858862
} else if self.parse_keyword("MATERIALIZED") || self.parse_keyword("VIEW") {
859863
self.prev_token();
860864
self.parse_create_view()
861865
} else if self.parse_keyword("EXTERNAL") {
862866
self.parse_create_external_table()
863867
} else {
864-
self.expected("TABLE or VIEW after CREATE", self.peek_token())
868+
self.expected("TABLE, VIEW or INDEX after CREATE", self.peek_token())
865869
}
866870
}
867871

@@ -912,8 +916,10 @@ impl Parser {
912916
ObjectType::Table
913917
} else if self.parse_keyword("VIEW") {
914918
ObjectType::View
919+
} else if self.parse_keyword("INDEX") {
920+
ObjectType::Index
915921
} else {
916-
return self.expected("TABLE or VIEW after DROP", self.peek_token());
922+
return self.expected("TABLE, VIEW or INDEX after DROP", self.peek_token());
917923
};
918924
// Many dialects support the non standard `IF EXISTS` clause and allow
919925
// specifying multiple objects to delete in a single statement
@@ -932,6 +938,23 @@ impl Parser {
932938
})
933939
}
934940

941+
pub fn parse_create_index(&mut self, unique: bool) -> Result<Statement, ParserError> {
942+
let if_not_exists = self.parse_keywords(vec!["IF", "NOT", "EXISTS"]);
943+
let index_name = self.parse_object_name()?;
944+
self.expect_keyword("ON")?;
945+
let table_name = self.parse_object_name()?;
946+
self.expect_token(&Token::LParen)?;
947+
let columns = self.parse_comma_separated(Parser::parse_identifier)?;
948+
self.expect_token(&Token::RParen)?;
949+
Ok(Statement::CreateIndex {
950+
name: index_name,
951+
table_name,
952+
columns,
953+
unique,
954+
if_not_exists,
955+
})
956+
}
957+
935958
pub fn parse_create_table(&mut self) -> Result<Statement, ParserError> {
936959
let if_not_exists = self.parse_keywords(vec!["IF", "NOT", "EXISTS"]);
937960
let table_name = self.parse_object_name()?;

tests/sqlparser_common.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2631,6 +2631,44 @@ fn ensure_multiple_dialects_are_tested() {
26312631
let _ = parse_sql_statements("SELECT @foo");
26322632
}
26332633

2634+
#[test]
2635+
fn parse_create_index() {
2636+
let sql = "CREATE UNIQUE INDEX IF NOT EXISTS idx_name ON test(name,age);";
2637+
let ident_vec = vec![Ident::new("name"), Ident::new("age")];
2638+
match verified_stmt(sql) {
2639+
Statement::CreateIndex {
2640+
name,
2641+
table_name,
2642+
columns,
2643+
unique,
2644+
if_not_exists,
2645+
} => {
2646+
assert_eq!("idx_name", name.to_string());
2647+
assert_eq!("test", table_name.to_string());
2648+
assert_eq!(ident_vec, columns);
2649+
assert_eq!(true, unique);
2650+
assert_eq!(true, if_not_exists)
2651+
}
2652+
_ => unreachable!(),
2653+
}
2654+
}
2655+
#[test]
2656+
fn parse_drop_index() {
2657+
let sql = "DROP INDEX idx_a";
2658+
match verified_stmt(sql) {
2659+
Statement::Drop {
2660+
names, object_type, ..
2661+
} => {
2662+
assert_eq!(
2663+
vec!["idx_a"],
2664+
names.iter().map(ToString::to_string).collect::<Vec<_>>()
2665+
);
2666+
assert_eq!(ObjectType::Index, object_type);
2667+
}
2668+
_ => unreachable!(),
2669+
}
2670+
}
2671+
26342672
fn parse_sql_statements(sql: &str) -> Result<Vec<Statement>, ParserError> {
26352673
all_dialects().parse_sql_statements(sql)
26362674
}

0 commit comments

Comments
 (0)