Skip to content

Commit 371cf09

Browse files
beneschjamii
andcommitted
Support DROP [TABLE|VIEW]
Co-authored-by: Jamie Brandon <[email protected]>
1 parent 4f944dd commit 371cf09

File tree

4 files changed

+141
-0
lines changed

4 files changed

+141
-0
lines changed

src/dialect/keywords.rs

+3
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ define_keywords!(
7171
CALL,
7272
CALLED,
7373
CARDINALITY,
74+
CASCADE,
7475
CASCADED,
7576
CASE,
7677
CAST,
@@ -178,6 +179,7 @@ define_keywords!(
178179
HOLD,
179180
HOUR,
180181
IDENTITY,
182+
IF,
181183
IN,
182184
INDICATOR,
183185
INNER,
@@ -290,6 +292,7 @@ define_keywords!(
290292
REGR_SXY,
291293
REGR_SYY,
292294
RELEASE,
295+
RESTRICT,
293296
RESULT,
294297
RETURN,
295298
RETURNS,

src/sqlast/mod.rs

+31
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,10 @@ pub enum SQLStatement {
394394
name: SQLObjectName,
395395
operation: AlterOperation,
396396
},
397+
/// DROP TABLE
398+
SQLDropTable(SQLDrop),
399+
/// DROP VIEW
400+
SQLDropView(SQLDrop),
397401
}
398402

399403
impl ToString for SQLStatement {
@@ -499,6 +503,8 @@ impl ToString for SQLStatement {
499503
name.to_string(),
500504
comma_separated_string(columns)
501505
),
506+
SQLStatement::SQLDropTable(drop) => drop.to_string_internal("TABLE"),
507+
SQLStatement::SQLDropView(drop) => drop.to_string_internal("VIEW"),
502508
SQLStatement::SQLAlterTable { name, operation } => {
503509
format!("ALTER TABLE {} {}", name.to_string(), operation.to_string())
504510
}
@@ -608,3 +614,28 @@ impl FromStr for FileFormat {
608614
}
609615
}
610616
}
617+
618+
#[derive(Debug, Clone, PartialEq)]
619+
pub struct SQLDrop {
620+
pub if_exists: bool,
621+
pub names: Vec<SQLObjectName>,
622+
pub cascade: bool,
623+
pub restrict: bool,
624+
}
625+
626+
impl SQLDrop {
627+
fn to_string_internal(&self, object_type: &str) -> String {
628+
format!(
629+
"DROP {}{} {}{}{}",
630+
object_type,
631+
if self.if_exists { " IF EXISTS" } else { "" },
632+
self.names
633+
.iter()
634+
.map(|name| name.to_string())
635+
.collect::<Vec<String>>()
636+
.join(", "),
637+
if self.cascade { " CASCADE" } else { "" },
638+
if self.restrict { " RESTRICT" } else { "" },
639+
)
640+
}
641+
}

src/sqlparser.rs

+46
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ impl Parser {
9797
Ok(SQLStatement::SQLQuery(Box::new(self.parse_query()?)))
9898
}
9999
"CREATE" => Ok(self.parse_create()?),
100+
"DROP" => Ok(self.parse_drop()?),
100101
"DELETE" => Ok(self.parse_delete()?),
101102
"INSERT" => Ok(self.parse_insert()?),
102103
"ALTER" => Ok(self.parse_alter()?),
@@ -738,6 +739,51 @@ impl Parser {
738739
})
739740
}
740741

742+
pub fn parse_drop(&mut self) -> Result<SQLStatement, ParserError> {
743+
if self.parse_keyword("TABLE") {
744+
self.parse_drop_table()
745+
} else if self.parse_keyword("VIEW") {
746+
self.parse_drop_view()
747+
} else {
748+
parser_err!(format!(
749+
"Unexpected token after DROP: {:?}",
750+
self.peek_token()
751+
))
752+
}
753+
}
754+
755+
pub fn parse_drop_table(&mut self) -> Result<SQLStatement, ParserError> {
756+
Ok(SQLStatement::SQLDropTable(self.parse_drop_inner()?))
757+
}
758+
759+
pub fn parse_drop_view(&mut self) -> Result<SQLStatement, ParserError> {
760+
Ok(SQLStatement::SQLDropView(self.parse_drop_inner()?))
761+
}
762+
763+
pub fn parse_drop_inner(&mut self) -> Result<SQLDrop, ParserError> {
764+
let if_exists = self.parse_keywords(vec!["IF", "EXISTS"]);
765+
let mut names = vec![self.parse_object_name()?];
766+
loop {
767+
let token = &self.next_token();
768+
if let Some(Token::Comma) = token {
769+
names.push(self.parse_object_name()?)
770+
} else {
771+
if token.is_some() {
772+
self.prev_token();
773+
}
774+
break;
775+
}
776+
}
777+
let cascade = self.parse_keyword("CASCADE");
778+
let restrict = !cascade && self.parse_keyword("RESTRICT");
779+
Ok(SQLDrop {
780+
if_exists,
781+
names,
782+
cascade,
783+
restrict,
784+
})
785+
}
786+
741787
pub fn parse_create_table(&mut self) -> Result<SQLStatement, ParserError> {
742788
let table_name = self.parse_object_name()?;
743789
// parse optional column list (schema)

tests/sqlparser_common.rs

+61
Original file line numberDiff line numberDiff line change
@@ -1200,6 +1200,67 @@ fn parse_create_materialized_view() {
12001200
}
12011201
}
12021202

1203+
#[test]
1204+
fn parse_drop_table() {
1205+
let sql = "DROP TABLE foo";
1206+
match verified_stmt(sql) {
1207+
SQLStatement::SQLDropTable(SQLDrop {
1208+
if_exists,
1209+
names,
1210+
cascade,
1211+
restrict,
1212+
}) => {
1213+
assert_eq!(false, if_exists);
1214+
assert_eq!(
1215+
vec!["foo"],
1216+
names.iter().map(|n| n.to_string()).collect::<Vec<_>>()
1217+
);
1218+
assert_eq!(false, cascade);
1219+
assert_eq!(false, restrict);
1220+
}
1221+
_ => assert!(false),
1222+
}
1223+
1224+
let sql = "DROP TABLE IF EXISTS foo, bar CASCADE";
1225+
match verified_stmt(sql) {
1226+
SQLStatement::SQLDropTable(SQLDrop {
1227+
if_exists,
1228+
names,
1229+
cascade,
1230+
restrict,
1231+
}) => {
1232+
assert_eq!(true, if_exists);
1233+
assert_eq!(
1234+
vec!["foo", "bar"],
1235+
names.iter().map(|n| n.to_string()).collect::<Vec<_>>()
1236+
);
1237+
assert_eq!(true, cascade);
1238+
assert_eq!(false, restrict);
1239+
}
1240+
_ => assert!(false),
1241+
}
1242+
1243+
let sql = "DROP TABLE";
1244+
assert!(parse_sql_statements(sql).is_err());
1245+
1246+
let sql = "DROP TABLE IF EXISTS foo, bar CASCADE RESTRICT";
1247+
assert!(parse_sql_statements(sql).is_err());
1248+
}
1249+
1250+
#[test]
1251+
fn parse_drop_view() {
1252+
let sql = "DROP VIEW myschema.myview";
1253+
match verified_stmt(sql) {
1254+
SQLStatement::SQLDropView(SQLDrop { names, .. }) => {
1255+
assert_eq!(
1256+
vec!["myschema.myview"],
1257+
names.iter().map(|n| n.to_string()).collect::<Vec<_>>()
1258+
);
1259+
}
1260+
_ => assert!(false),
1261+
}
1262+
}
1263+
12031264
#[test]
12041265
fn parse_invalid_subquery_without_parens() {
12051266
let res = parse_sql_statements("SELECT SELECT 1 FROM bar WHERE 1=1 FROM baz");

0 commit comments

Comments
 (0)