mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-23 07:24:10 +00:00
Support DROP FUNCTION
syntax (#752)
* drop function * update and to Option * fix review * update * fmt
This commit is contained in:
parent
3d5cc54dcf
commit
2d801c9fb6
3 changed files with 207 additions and 15 deletions
|
@ -1268,6 +1268,14 @@ pub enum Statement {
|
||||||
/// deleted along with the dropped table
|
/// deleted along with the dropped table
|
||||||
purge: bool,
|
purge: bool,
|
||||||
},
|
},
|
||||||
|
/// DROP Function
|
||||||
|
DropFunction {
|
||||||
|
if_exists: bool,
|
||||||
|
/// One or more function to drop
|
||||||
|
func_desc: Vec<DropFunctionDesc>,
|
||||||
|
/// `CASCADE` or `RESTRICT`
|
||||||
|
option: Option<ReferentialAction>,
|
||||||
|
},
|
||||||
/// DECLARE - Declaring Cursor Variables
|
/// DECLARE - Declaring Cursor Variables
|
||||||
///
|
///
|
||||||
/// Note: this is a PostgreSQL-specific statement,
|
/// Note: this is a PostgreSQL-specific statement,
|
||||||
|
@ -1432,7 +1440,7 @@ pub enum Statement {
|
||||||
or_replace: bool,
|
or_replace: bool,
|
||||||
temporary: bool,
|
temporary: bool,
|
||||||
name: ObjectName,
|
name: ObjectName,
|
||||||
args: Option<Vec<CreateFunctionArg>>,
|
args: Option<Vec<OperateFunctionArg>>,
|
||||||
return_type: Option<DataType>,
|
return_type: Option<DataType>,
|
||||||
/// Optional parameters.
|
/// Optional parameters.
|
||||||
params: CreateFunctionBody,
|
params: CreateFunctionBody,
|
||||||
|
@ -2284,6 +2292,22 @@ impl fmt::Display for Statement {
|
||||||
if *restrict { " RESTRICT" } else { "" },
|
if *restrict { " RESTRICT" } else { "" },
|
||||||
if *purge { " PURGE" } else { "" }
|
if *purge { " PURGE" } else { "" }
|
||||||
),
|
),
|
||||||
|
Statement::DropFunction {
|
||||||
|
if_exists,
|
||||||
|
func_desc,
|
||||||
|
option,
|
||||||
|
} => {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"DROP FUNCTION{} {}",
|
||||||
|
if *if_exists { " IF EXISTS" } else { "" },
|
||||||
|
display_comma_separated(func_desc),
|
||||||
|
)?;
|
||||||
|
if let Some(op) = option {
|
||||||
|
write!(f, " {}", op)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Statement::Discard { object_type } => {
|
Statement::Discard { object_type } => {
|
||||||
write!(f, "DISCARD {object_type}", object_type = object_type)?;
|
write!(f, "DISCARD {object_type}", object_type = object_type)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -3726,17 +3750,52 @@ impl fmt::Display for ContextModifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Function argument in CREATE FUNCTION.
|
/// Function describe in DROP FUNCTION.
|
||||||
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct CreateFunctionArg {
|
pub enum DropFunctionOption {
|
||||||
|
Restrict,
|
||||||
|
Cascade,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for DropFunctionOption {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
DropFunctionOption::Restrict => write!(f, "RESTRICT "),
|
||||||
|
DropFunctionOption::Cascade => write!(f, "CASCADE "),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Function describe in DROP FUNCTION.
|
||||||
|
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
pub struct DropFunctionDesc {
|
||||||
|
pub name: ObjectName,
|
||||||
|
pub args: Option<Vec<OperateFunctionArg>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for DropFunctionDesc {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.name)?;
|
||||||
|
if let Some(args) = &self.args {
|
||||||
|
write!(f, "({})", display_comma_separated(args))?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Function argument in CREATE OR DROP FUNCTION.
|
||||||
|
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
pub struct OperateFunctionArg {
|
||||||
pub mode: Option<ArgMode>,
|
pub mode: Option<ArgMode>,
|
||||||
pub name: Option<Ident>,
|
pub name: Option<Ident>,
|
||||||
pub data_type: DataType,
|
pub data_type: DataType,
|
||||||
pub default_expr: Option<Expr>,
|
pub default_expr: Option<Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreateFunctionArg {
|
impl OperateFunctionArg {
|
||||||
/// Returns an unnamed argument.
|
/// Returns an unnamed argument.
|
||||||
pub fn unnamed(data_type: DataType) -> Self {
|
pub fn unnamed(data_type: DataType) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -3758,7 +3817,7 @@ impl CreateFunctionArg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for CreateFunctionArg {
|
impl fmt::Display for OperateFunctionArg {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
if let Some(mode) = &self.mode {
|
if let Some(mode) = &self.mode {
|
||||||
write!(f, "{} ", mode)?;
|
write!(f, "{} ", mode)?;
|
||||||
|
|
|
@ -2343,7 +2343,13 @@ impl<'a> Parser<'a> {
|
||||||
} else if dialect_of!(self is PostgreSqlDialect) {
|
} else if dialect_of!(self is PostgreSqlDialect) {
|
||||||
let name = self.parse_object_name()?;
|
let name = self.parse_object_name()?;
|
||||||
self.expect_token(&Token::LParen)?;
|
self.expect_token(&Token::LParen)?;
|
||||||
let args = self.parse_comma_separated(Parser::parse_create_function_arg)?;
|
let args = if self.consume_token(&Token::RParen) {
|
||||||
|
self.prev_token();
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(self.parse_comma_separated(Parser::parse_function_arg)?)
|
||||||
|
};
|
||||||
|
|
||||||
self.expect_token(&Token::RParen)?;
|
self.expect_token(&Token::RParen)?;
|
||||||
|
|
||||||
let return_type = if self.parse_keyword(Keyword::RETURNS) {
|
let return_type = if self.parse_keyword(Keyword::RETURNS) {
|
||||||
|
@ -2358,7 +2364,7 @@ impl<'a> Parser<'a> {
|
||||||
or_replace,
|
or_replace,
|
||||||
temporary,
|
temporary,
|
||||||
name,
|
name,
|
||||||
args: Some(args),
|
args,
|
||||||
return_type,
|
return_type,
|
||||||
params,
|
params,
|
||||||
})
|
})
|
||||||
|
@ -2368,7 +2374,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_create_function_arg(&mut self) -> Result<CreateFunctionArg, ParserError> {
|
fn parse_function_arg(&mut self) -> Result<OperateFunctionArg, ParserError> {
|
||||||
let mode = if self.parse_keyword(Keyword::IN) {
|
let mode = if self.parse_keyword(Keyword::IN) {
|
||||||
Some(ArgMode::In)
|
Some(ArgMode::In)
|
||||||
} else if self.parse_keyword(Keyword::OUT) {
|
} else if self.parse_keyword(Keyword::OUT) {
|
||||||
|
@ -2394,7 +2400,7 @@ impl<'a> Parser<'a> {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
Ok(CreateFunctionArg {
|
Ok(OperateFunctionArg {
|
||||||
mode,
|
mode,
|
||||||
name,
|
name,
|
||||||
data_type,
|
data_type,
|
||||||
|
@ -2767,9 +2773,11 @@ impl<'a> Parser<'a> {
|
||||||
ObjectType::Schema
|
ObjectType::Schema
|
||||||
} else if self.parse_keyword(Keyword::SEQUENCE) {
|
} else if self.parse_keyword(Keyword::SEQUENCE) {
|
||||||
ObjectType::Sequence
|
ObjectType::Sequence
|
||||||
|
} else if self.parse_keyword(Keyword::FUNCTION) {
|
||||||
|
return self.parse_drop_function();
|
||||||
} else {
|
} else {
|
||||||
return self.expected(
|
return self.expected(
|
||||||
"TABLE, VIEW, INDEX, ROLE, SCHEMA, or SEQUENCE after DROP",
|
"TABLE, VIEW, INDEX, ROLE, SCHEMA, FUNCTION or SEQUENCE after DROP",
|
||||||
self.peek_token(),
|
self.peek_token(),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -2796,6 +2804,41 @@ impl<'a> Parser<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// DROP FUNCTION [ IF EXISTS ] name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] [, ...]
|
||||||
|
/// [ CASCADE | RESTRICT ]
|
||||||
|
fn parse_drop_function(&mut self) -> Result<Statement, ParserError> {
|
||||||
|
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
||||||
|
let func_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),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
Ok(Statement::DropFunction {
|
||||||
|
if_exists,
|
||||||
|
func_desc,
|
||||||
|
option,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_drop_function_desc(&mut self) -> Result<DropFunctionDesc, ParserError> {
|
||||||
|
let name = self.parse_object_name()?;
|
||||||
|
|
||||||
|
let args = if self.consume_token(&Token::LParen) {
|
||||||
|
if self.consume_token(&Token::RParen) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let args = self.parse_comma_separated(Parser::parse_function_arg)?;
|
||||||
|
self.expect_token(&Token::RParen)?;
|
||||||
|
Some(args)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(DropFunctionDesc { name, args })
|
||||||
|
}
|
||||||
|
|
||||||
/// DECLARE name [ BINARY ] [ ASENSITIVE | INSENSITIVE ] [ [ NO ] SCROLL ]
|
/// DECLARE name [ BINARY ] [ ASENSITIVE | INSENSITIVE ] [ [ NO ] SCROLL ]
|
||||||
// CURSOR [ { WITH | WITHOUT } HOLD ] FOR query
|
// CURSOR [ { WITH | WITHOUT } HOLD ] FOR query
|
||||||
pub fn parse_declare(&mut self) -> Result<Statement, ParserError> {
|
pub fn parse_declare(&mut self) -> Result<Statement, ParserError> {
|
||||||
|
|
|
@ -2348,8 +2348,8 @@ fn parse_create_function() {
|
||||||
temporary: false,
|
temporary: false,
|
||||||
name: ObjectName(vec![Ident::new("add")]),
|
name: ObjectName(vec![Ident::new("add")]),
|
||||||
args: Some(vec![
|
args: Some(vec![
|
||||||
CreateFunctionArg::unnamed(DataType::Integer(None)),
|
OperateFunctionArg::unnamed(DataType::Integer(None)),
|
||||||
CreateFunctionArg::unnamed(DataType::Integer(None)),
|
OperateFunctionArg::unnamed(DataType::Integer(None)),
|
||||||
]),
|
]),
|
||||||
return_type: Some(DataType::Integer(None)),
|
return_type: Some(DataType::Integer(None)),
|
||||||
params: CreateFunctionBody {
|
params: CreateFunctionBody {
|
||||||
|
@ -2371,8 +2371,8 @@ fn parse_create_function() {
|
||||||
temporary: false,
|
temporary: false,
|
||||||
name: ObjectName(vec![Ident::new("add")]),
|
name: ObjectName(vec![Ident::new("add")]),
|
||||||
args: Some(vec![
|
args: Some(vec![
|
||||||
CreateFunctionArg::with_name("a", DataType::Integer(None)),
|
OperateFunctionArg::with_name("a", DataType::Integer(None)),
|
||||||
CreateFunctionArg {
|
OperateFunctionArg {
|
||||||
mode: Some(ArgMode::In),
|
mode: Some(ArgMode::In),
|
||||||
name: Some("b".into()),
|
name: Some("b".into()),
|
||||||
data_type: DataType::Integer(None),
|
data_type: DataType::Integer(None),
|
||||||
|
@ -2400,7 +2400,7 @@ fn parse_create_function() {
|
||||||
or_replace: true,
|
or_replace: true,
|
||||||
temporary: false,
|
temporary: false,
|
||||||
name: ObjectName(vec![Ident::new("increment")]),
|
name: ObjectName(vec![Ident::new("increment")]),
|
||||||
args: Some(vec![CreateFunctionArg::with_name(
|
args: Some(vec![OperateFunctionArg::with_name(
|
||||||
"i",
|
"i",
|
||||||
DataType::Integer(None)
|
DataType::Integer(None)
|
||||||
)]),
|
)]),
|
||||||
|
@ -2417,3 +2417,93 @@ fn parse_create_function() {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_drop_function() {
|
||||||
|
let sql = "DROP FUNCTION IF EXISTS test_func";
|
||||||
|
assert_eq!(
|
||||||
|
pg().verified_stmt(sql),
|
||||||
|
Statement::DropFunction {
|
||||||
|
if_exists: true,
|
||||||
|
func_desc: vec![DropFunctionDesc {
|
||||||
|
name: ObjectName(vec![Ident {
|
||||||
|
value: "test_func".to_string(),
|
||||||
|
quote_style: None
|
||||||
|
}]),
|
||||||
|
args: None
|
||||||
|
}],
|
||||||
|
option: None
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let sql = "DROP FUNCTION IF EXISTS test_func(a INTEGER, IN b INTEGER = 1)";
|
||||||
|
assert_eq!(
|
||||||
|
pg().verified_stmt(sql),
|
||||||
|
Statement::DropFunction {
|
||||||
|
if_exists: true,
|
||||||
|
func_desc: vec![DropFunctionDesc {
|
||||||
|
name: ObjectName(vec![Ident {
|
||||||
|
value: "test_func".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 FUNCTION IF EXISTS test_func1(a INTEGER, IN b INTEGER = 1), test_func2(a VARCHAR, IN b INTEGER = 1)";
|
||||||
|
assert_eq!(
|
||||||
|
pg().verified_stmt(sql),
|
||||||
|
Statement::DropFunction {
|
||||||
|
if_exists: true,
|
||||||
|
func_desc: vec![
|
||||||
|
DropFunctionDesc {
|
||||||
|
name: ObjectName(vec![Ident {
|
||||||
|
value: "test_func1".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_func2".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
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue