mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-09-01 03:37:21 +00:00
Merge pull request #167 from mashuai/add_index_support
Adds support for the most common forms of CREATE INDEX, and for DROP INDEX: CREATE [ UNIQUE ] INDEX [ IF NOT EXISTS ] <index_name> ON <table_name> ( col_name [, ...] ) DROP INDEX <index_name>
This commit is contained in:
commit
789fcc8521
5 changed files with 96 additions and 2 deletions
|
@ -13,6 +13,7 @@ Check https://github.com/andygrove/sqlparser-rs/commits/master for undocumented
|
|||
- Support Snowflake's `FROM (table_name)` (#155) - thanks @eyalleshem!
|
||||
|
||||
### Added
|
||||
- Support basic forms of `CREATE INDEX` and `DROP INDEX` (#167) - thanks @mashuai!
|
||||
- Support MSSQL `TOP (<N>) [ PERCENT ] [ WITH TIES ]` (#150) - thanks @alexkyllo!
|
||||
- Support MySQL `LIMIT row_count OFFSET offset` (not followed by `ROW` or `ROWS`) and remember which variant was parsed (#158) - thanks @mjibson!
|
||||
- Support PostgreSQL `CREATE TABLE IF NOT EXISTS table_name` (#163) - thanks @alex-dukhno!
|
||||
|
|
|
@ -476,6 +476,15 @@ pub enum Statement {
|
|||
file_format: Option<FileFormat>,
|
||||
location: Option<String>,
|
||||
},
|
||||
/// CREATE INDEX
|
||||
CreateIndex {
|
||||
/// index name
|
||||
name: ObjectName,
|
||||
table_name: ObjectName,
|
||||
columns: Vec<Ident>,
|
||||
unique: bool,
|
||||
if_not_exists: bool,
|
||||
},
|
||||
/// ALTER TABLE
|
||||
AlterTable {
|
||||
/// Table name
|
||||
|
@ -655,6 +664,28 @@ impl fmt::Display for Statement {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
Statement::CreateIndex {
|
||||
name,
|
||||
table_name,
|
||||
columns,
|
||||
unique,
|
||||
if_not_exists,
|
||||
} => {
|
||||
write!(
|
||||
f,
|
||||
"CREATE{}INDEX{}{} ON {}({}",
|
||||
if *unique { " UNIQUE " } else { " " },
|
||||
if *if_not_exists {
|
||||
" IF NOT EXISTS "
|
||||
} else {
|
||||
" "
|
||||
},
|
||||
name,
|
||||
table_name,
|
||||
display_separated(columns, ",")
|
||||
)?;
|
||||
write!(f, ");")
|
||||
}
|
||||
Statement::AlterTable { name, operation } => {
|
||||
write!(f, "ALTER TABLE {} {}", name, operation)
|
||||
}
|
||||
|
@ -819,6 +850,7 @@ impl FromStr for FileFormat {
|
|||
pub enum ObjectType {
|
||||
Table,
|
||||
View,
|
||||
Index,
|
||||
}
|
||||
|
||||
impl fmt::Display for ObjectType {
|
||||
|
@ -826,6 +858,7 @@ impl fmt::Display for ObjectType {
|
|||
f.write_str(match self {
|
||||
ObjectType::Table => "TABLE",
|
||||
ObjectType::View => "VIEW",
|
||||
ObjectType::Index => "INDEX",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -200,6 +200,7 @@ define_keywords!(
|
|||
IDENTITY,
|
||||
IF,
|
||||
IN,
|
||||
INDEX,
|
||||
INDICATOR,
|
||||
INNER,
|
||||
INOUT,
|
||||
|
|
|
@ -855,13 +855,17 @@ impl Parser {
|
|||
pub fn parse_create(&mut self) -> Result<Statement, ParserError> {
|
||||
if self.parse_keyword("TABLE") {
|
||||
self.parse_create_table()
|
||||
} else if self.parse_keyword("INDEX") {
|
||||
self.parse_create_index(false)
|
||||
} else if self.parse_keywords(vec!["UNIQUE", "INDEX"]) {
|
||||
self.parse_create_index(true)
|
||||
} else if self.parse_keyword("MATERIALIZED") || self.parse_keyword("VIEW") {
|
||||
self.prev_token();
|
||||
self.parse_create_view()
|
||||
} else if self.parse_keyword("EXTERNAL") {
|
||||
self.parse_create_external_table()
|
||||
} else {
|
||||
self.expected("TABLE or VIEW after CREATE", self.peek_token())
|
||||
self.expected("TABLE, VIEW or INDEX after CREATE", self.peek_token())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -912,8 +916,10 @@ impl Parser {
|
|||
ObjectType::Table
|
||||
} else if self.parse_keyword("VIEW") {
|
||||
ObjectType::View
|
||||
} else if self.parse_keyword("INDEX") {
|
||||
ObjectType::Index
|
||||
} else {
|
||||
return self.expected("TABLE or VIEW after DROP", self.peek_token());
|
||||
return self.expected("TABLE, VIEW or INDEX after DROP", self.peek_token());
|
||||
};
|
||||
// Many dialects support the non standard `IF EXISTS` clause and allow
|
||||
// specifying multiple objects to delete in a single statement
|
||||
|
@ -932,6 +938,21 @@ impl Parser {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn parse_create_index(&mut self, unique: bool) -> Result<Statement, ParserError> {
|
||||
let if_not_exists = self.parse_keywords(vec!["IF", "NOT", "EXISTS"]);
|
||||
let index_name = self.parse_object_name()?;
|
||||
self.expect_keyword("ON")?;
|
||||
let table_name = self.parse_object_name()?;
|
||||
let columns = self.parse_parenthesized_column_list(Mandatory)?;
|
||||
Ok(Statement::CreateIndex {
|
||||
name: index_name,
|
||||
table_name,
|
||||
columns,
|
||||
unique,
|
||||
if_not_exists,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parse_create_table(&mut self) -> Result<Statement, ParserError> {
|
||||
let if_not_exists = self.parse_keywords(vec!["IF", "NOT", "EXISTS"]);
|
||||
let table_name = self.parse_object_name()?;
|
||||
|
|
|
@ -2631,6 +2631,44 @@ fn ensure_multiple_dialects_are_tested() {
|
|||
let _ = parse_sql_statements("SELECT @foo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_create_index() {
|
||||
let sql = "CREATE UNIQUE INDEX IF NOT EXISTS idx_name ON test(name,age);";
|
||||
let ident_vec = vec![Ident::new("name"), Ident::new("age")];
|
||||
match verified_stmt(sql) {
|
||||
Statement::CreateIndex {
|
||||
name,
|
||||
table_name,
|
||||
columns,
|
||||
unique,
|
||||
if_not_exists,
|
||||
} => {
|
||||
assert_eq!("idx_name", name.to_string());
|
||||
assert_eq!("test", table_name.to_string());
|
||||
assert_eq!(ident_vec, columns);
|
||||
assert_eq!(true, unique);
|
||||
assert_eq!(true, if_not_exists)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn parse_drop_index() {
|
||||
let sql = "DROP INDEX idx_a";
|
||||
match verified_stmt(sql) {
|
||||
Statement::Drop {
|
||||
names, object_type, ..
|
||||
} => {
|
||||
assert_eq!(
|
||||
vec!["idx_a"],
|
||||
names.iter().map(ToString::to_string).collect::<Vec<_>>()
|
||||
);
|
||||
assert_eq!(ObjectType::Index, object_type);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_sql_statements(sql: &str) -> Result<Vec<Statement>, ParserError> {
|
||||
all_dialects().parse_sql_statements(sql)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue