Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,9 @@ pub enum Statement {
/// DELETE
Delete {
/// FROM
table_name: ObjectName,
table_name: TableFactor,
/// USING (Snowflake, Postgres)
using: Option<TableFactor>,
/// WHERE
selection: Option<Expr>,
},
Expand Down Expand Up @@ -1395,9 +1397,13 @@ impl fmt::Display for Statement {
}
Statement::Delete {
table_name,
using,
selection,
} => {
write!(f, "DELETE FROM {}", table_name)?;
if let Some(using) = using {
write!(f, " USING {}", using)?;
}
if let Some(selection) = selection {
write!(f, " WHERE {}", selection)?;
}
Expand Down
8 changes: 7 additions & 1 deletion src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3132,7 +3132,12 @@ impl<'a> Parser<'a> {

pub fn parse_delete(&mut self) -> Result<Statement, ParserError> {
self.expect_keyword(Keyword::FROM)?;
let table_name = self.parse_object_name()?;
let table_name = self.parse_table_factor()?;
let using = if self.parse_keyword(Keyword::USING) {
Some(self.parse_table_factor()?)
} else {
None
};
let selection = if self.parse_keyword(Keyword::WHERE) {
Some(self.parse_expr()?)
} else {
Expand All @@ -3141,6 +3146,7 @@ impl<'a> Parser<'a> {

Ok(Statement::Delete {
table_name,
using,
selection,
})
}
Expand Down
75 changes: 72 additions & 3 deletions tests/sqlparser_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,12 @@ fn parse_delete_statement() {
match verified_stmt(sql) {
Statement::Delete { table_name, .. } => {
assert_eq!(
ObjectName(vec![Ident::with_quote('"', "table")]),
TableFactor::Table {
name: ObjectName(vec![Ident::with_quote('"', "table")]),
alias: None,
args: None,
with_hints: vec![]
},
table_name
);
}
Expand All @@ -269,11 +274,20 @@ fn parse_where_delete_statement() {
match verified_stmt(sql) {
Statement::Delete {
table_name,
using,
selection,
..
} => {
assert_eq!(ObjectName(vec![Ident::new("foo")]), table_name);
assert_eq!(
TableFactor::Table {
name: ObjectName(vec![Ident::new("foo")]),
alias: None,
args: None,
with_hints: vec![]
},
table_name,
);

assert_eq!(None, using);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please add a positive test for using as well (aka a query that has a USING clause)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alamb I added it few lines below already: https://github.com/sqlparser-rs/sqlparser-rs/pull/541/files#diff-ae2dab2c924f4018c1daf0743b8fd912c44c5b63ae7144dd8b951bb3bd254349R305

Unless you mean something else? Like, more complex TableFactor?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No this is fine -- I just wanted to add some coverage so that we didn't accidentally break the functionality in the future but have all the tests pass

assert_eq!(
Expr::BinaryOp {
left: Box::new(Expr::Identifier(Ident::new("name"))),
Expand All @@ -287,6 +301,61 @@ fn parse_where_delete_statement() {
}
}

#[test]
fn parse_where_delete_with_alias_statement() {
use self::BinaryOperator::*;

let sql = "DELETE FROM basket AS a USING basket AS b WHERE a.id < b.id";
match verified_stmt(sql) {
Statement::Delete {
table_name,
using,
selection,
} => {
assert_eq!(
TableFactor::Table {
name: ObjectName(vec![Ident::new("basket")]),
alias: Some(TableAlias {
name: Ident::new("a"),
columns: vec![]
}),
args: None,
with_hints: vec![]
},
table_name,
);

assert_eq!(
Some(TableFactor::Table {
name: ObjectName(vec![Ident::new("basket")]),
alias: Some(TableAlias {
name: Ident::new("b"),
columns: vec![]
}),
args: None,
with_hints: vec![]
}),
using
);
assert_eq!(
Expr::BinaryOp {
left: Box::new(Expr::CompoundIdentifier(vec![
Ident::new("a"),
Ident::new("id")
])),
op: Lt,
right: Box::new(Expr::CompoundIdentifier(vec![
Ident::new("b"),
Ident::new("id")
])),
},
selection.unwrap(),
);
}
_ => unreachable!(),
}
}

#[test]
fn parse_top_level() {
verified_stmt("SELECT 1");
Expand Down