mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-31 03:07:20 +00:00
Support DROP PROCEDURE
statement (#1324)
Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
This commit is contained in:
parent
bbee052890
commit
9f60eb1571
3 changed files with 151 additions and 1 deletions
|
@ -2215,6 +2215,16 @@ pub enum Statement {
|
||||||
option: Option<ReferentialAction>,
|
option: Option<ReferentialAction>,
|
||||||
},
|
},
|
||||||
/// ```sql
|
/// ```sql
|
||||||
|
/// DROP PROCEDURE
|
||||||
|
/// ```
|
||||||
|
DropProcedure {
|
||||||
|
if_exists: bool,
|
||||||
|
/// One or more function to drop
|
||||||
|
proc_desc: Vec<DropFunctionDesc>,
|
||||||
|
/// `CASCADE` or `RESTRICT`
|
||||||
|
option: Option<ReferentialAction>,
|
||||||
|
},
|
||||||
|
/// ```sql
|
||||||
/// DROP SECRET
|
/// DROP SECRET
|
||||||
/// ```
|
/// ```
|
||||||
DropSecret {
|
DropSecret {
|
||||||
|
@ -3644,6 +3654,22 @@ impl fmt::Display for Statement {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Statement::DropProcedure {
|
||||||
|
if_exists,
|
||||||
|
proc_desc,
|
||||||
|
option,
|
||||||
|
} => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"DROP PROCEDURE{} {}",
|
||||||
|
if *if_exists { " IF EXISTS" } else { "" },
|
||||||
|
display_comma_separated(proc_desc),
|
||||||
|
)?;
|
||||||
|
if let Some(op) = option {
|
||||||
|
write!(f, " {op}")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Statement::DropSecret {
|
Statement::DropSecret {
|
||||||
if_exists,
|
if_exists,
|
||||||
temporary,
|
temporary,
|
||||||
|
|
|
@ -4524,11 +4524,13 @@ impl<'a> Parser<'a> {
|
||||||
ObjectType::Stage
|
ObjectType::Stage
|
||||||
} else if self.parse_keyword(Keyword::FUNCTION) {
|
} else if self.parse_keyword(Keyword::FUNCTION) {
|
||||||
return self.parse_drop_function();
|
return self.parse_drop_function();
|
||||||
|
} else if self.parse_keyword(Keyword::PROCEDURE) {
|
||||||
|
return self.parse_drop_procedure();
|
||||||
} else if self.parse_keyword(Keyword::SECRET) {
|
} else if self.parse_keyword(Keyword::SECRET) {
|
||||||
return self.parse_drop_secret(temporary, persistent);
|
return self.parse_drop_secret(temporary, persistent);
|
||||||
} else {
|
} else {
|
||||||
return self.expected(
|
return self.expected(
|
||||||
"TABLE, VIEW, INDEX, ROLE, SCHEMA, FUNCTION, STAGE or SEQUENCE after DROP",
|
"TABLE, VIEW, INDEX, ROLE, SCHEMA, FUNCTION, PROCEDURE, STAGE or SEQUENCE after DROP",
|
||||||
self.peek_token(),
|
self.peek_token(),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -4580,6 +4582,26 @@ impl<'a> Parser<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ```sql
|
||||||
|
/// DROP PROCEDURE [ IF EXISTS ] name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] [, ...]
|
||||||
|
/// [ CASCADE | RESTRICT ]
|
||||||
|
/// ```
|
||||||
|
fn parse_drop_procedure(&mut self) -> Result<Statement, ParserError> {
|
||||||
|
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
||||||
|
let proc_desc = self.parse_comma_separated(Parser::parse_drop_function_desc)?;
|
||||||
|
let option = match self.parse_one_of_keywords(&[Keyword::CASCADE, Keyword::RESTRICT]) {
|
||||||
|
Some(Keyword::CASCADE) => Some(ReferentialAction::Cascade),
|
||||||
|
Some(Keyword::RESTRICT) => Some(ReferentialAction::Restrict),
|
||||||
|
Some(_) => unreachable!(), // parse_one_of_keywords does not return other keywords
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
Ok(Statement::DropProcedure {
|
||||||
|
if_exists,
|
||||||
|
proc_desc,
|
||||||
|
option,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_drop_function_desc(&mut self) -> Result<DropFunctionDesc, ParserError> {
|
fn parse_drop_function_desc(&mut self) -> Result<DropFunctionDesc, ParserError> {
|
||||||
let name = self.parse_object_name(false)?;
|
let name = self.parse_object_name(false)?;
|
||||||
|
|
||||||
|
|
|
@ -3629,6 +3629,108 @@ fn parse_drop_function() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_drop_procedure() {
|
||||||
|
let sql = "DROP PROCEDURE IF EXISTS test_proc";
|
||||||
|
assert_eq!(
|
||||||
|
pg().verified_stmt(sql),
|
||||||
|
Statement::DropProcedure {
|
||||||
|
if_exists: true,
|
||||||
|
proc_desc: vec![DropFunctionDesc {
|
||||||
|
name: ObjectName(vec![Ident {
|
||||||
|
value: "test_proc".to_string(),
|
||||||
|
quote_style: None
|
||||||
|
}]),
|
||||||
|
args: None
|
||||||
|
}],
|
||||||
|
option: None
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let sql = "DROP PROCEDURE IF EXISTS test_proc(a INTEGER, IN b INTEGER = 1)";
|
||||||
|
assert_eq!(
|
||||||
|
pg().verified_stmt(sql),
|
||||||
|
Statement::DropProcedure {
|
||||||
|
if_exists: true,
|
||||||
|
proc_desc: vec![DropFunctionDesc {
|
||||||
|
name: ObjectName(vec![Ident {
|
||||||
|
value: "test_proc".to_string(),
|
||||||
|
quote_style: None
|
||||||
|
}]),
|
||||||
|
args: Some(vec![
|
||||||
|
OperateFunctionArg::with_name("a", DataType::Integer(None)),
|
||||||
|
OperateFunctionArg {
|
||||||
|
mode: Some(ArgMode::In),
|
||||||
|
name: Some("b".into()),
|
||||||
|
data_type: DataType::Integer(None),
|
||||||
|
default_expr: Some(Expr::Value(Value::Number("1".parse().unwrap(), false))),
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
}],
|
||||||
|
option: None
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let sql = "DROP PROCEDURE IF EXISTS test_proc1(a INTEGER, IN b INTEGER = 1), test_proc2(a VARCHAR, IN b INTEGER = 1)";
|
||||||
|
assert_eq!(
|
||||||
|
pg().verified_stmt(sql),
|
||||||
|
Statement::DropProcedure {
|
||||||
|
if_exists: true,
|
||||||
|
proc_desc: vec![
|
||||||
|
DropFunctionDesc {
|
||||||
|
name: ObjectName(vec![Ident {
|
||||||
|
value: "test_proc1".to_string(),
|
||||||
|
quote_style: None
|
||||||
|
}]),
|
||||||
|
args: Some(vec![
|
||||||
|
OperateFunctionArg::with_name("a", DataType::Integer(None)),
|
||||||
|
OperateFunctionArg {
|
||||||
|
mode: Some(ArgMode::In),
|
||||||
|
name: Some("b".into()),
|
||||||
|
data_type: DataType::Integer(None),
|
||||||
|
default_expr: Some(Expr::Value(Value::Number(
|
||||||
|
"1".parse().unwrap(),
|
||||||
|
false
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
DropFunctionDesc {
|
||||||
|
name: ObjectName(vec![Ident {
|
||||||
|
value: "test_proc2".to_string(),
|
||||||
|
quote_style: None
|
||||||
|
}]),
|
||||||
|
args: Some(vec![
|
||||||
|
OperateFunctionArg::with_name("a", DataType::Varchar(None)),
|
||||||
|
OperateFunctionArg {
|
||||||
|
mode: Some(ArgMode::In),
|
||||||
|
name: Some("b".into()),
|
||||||
|
data_type: DataType::Integer(None),
|
||||||
|
default_expr: Some(Expr::Value(Value::Number(
|
||||||
|
"1".parse().unwrap(),
|
||||||
|
false
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
}
|
||||||
|
],
|
||||||
|
option: None
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let res = pg().parse_sql_statements("DROP PROCEDURE testproc DROP");
|
||||||
|
assert_eq!(
|
||||||
|
ParserError::ParserError("Expected: end of statement, found: DROP".to_string()),
|
||||||
|
res.unwrap_err()
|
||||||
|
);
|
||||||
|
|
||||||
|
let res = pg().parse_sql_statements("DROP PROCEDURE testproc SET NULL");
|
||||||
|
assert_eq!(
|
||||||
|
ParserError::ParserError("Expected: end of statement, found: SET".to_string()),
|
||||||
|
res.unwrap_err()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_dollar_quoted_string() {
|
fn parse_dollar_quoted_string() {
|
||||||
let sql = "SELECT $$hello$$, $tag_name$world$tag_name$, $$Foo$Bar$$, $$Foo$Bar$$col_name, $$$$, $tag_name$$tag_name$";
|
let sql = "SELECT $$hello$$, $tag_name$world$tag_name$, $$Foo$Bar$$, $$Foo$Bar$$col_name, $$$$, $tag_name$$tag_name$";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue