Skip to content

Commit 2d801c9

Browse files
authored
Support DROP FUNCTION syntax (#752)
* drop function * update and to Option * fix review * update * fmt
1 parent 3d5cc54 commit 2d801c9

File tree

3 files changed

+207
-15
lines changed

3 files changed

+207
-15
lines changed

src/ast/mod.rs

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,6 +1268,14 @@ pub enum Statement {
12681268
/// deleted along with the dropped table
12691269
purge: bool,
12701270
},
1271+
/// DROP Function
1272+
DropFunction {
1273+
if_exists: bool,
1274+
/// One or more function to drop
1275+
func_desc: Vec<DropFunctionDesc>,
1276+
/// `CASCADE` or `RESTRICT`
1277+
option: Option<ReferentialAction>,
1278+
},
12711279
/// DECLARE - Declaring Cursor Variables
12721280
///
12731281
/// Note: this is a PostgreSQL-specific statement,
@@ -1432,7 +1440,7 @@ pub enum Statement {
14321440
or_replace: bool,
14331441
temporary: bool,
14341442
name: ObjectName,
1435-
args: Option<Vec<CreateFunctionArg>>,
1443+
args: Option<Vec<OperateFunctionArg>>,
14361444
return_type: Option<DataType>,
14371445
/// Optional parameters.
14381446
params: CreateFunctionBody,
@@ -2284,6 +2292,22 @@ impl fmt::Display for Statement {
22842292
if *restrict { " RESTRICT" } else { "" },
22852293
if *purge { " PURGE" } else { "" }
22862294
),
2295+
Statement::DropFunction {
2296+
if_exists,
2297+
func_desc,
2298+
option,
2299+
} => {
2300+
write!(
2301+
f,
2302+
"DROP FUNCTION{} {}",
2303+
if *if_exists { " IF EXISTS" } else { "" },
2304+
display_comma_separated(func_desc),
2305+
)?;
2306+
if let Some(op) = option {
2307+
write!(f, " {}", op)?;
2308+
}
2309+
Ok(())
2310+
}
22872311
Statement::Discard { object_type } => {
22882312
write!(f, "DISCARD {object_type}", object_type = object_type)?;
22892313
Ok(())
@@ -3726,17 +3750,52 @@ impl fmt::Display for ContextModifier {
37263750
}
37273751
}
37283752

3729-
/// Function argument in CREATE FUNCTION.
3753+
/// Function describe in DROP FUNCTION.
3754+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3755+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3756+
pub enum DropFunctionOption {
3757+
Restrict,
3758+
Cascade,
3759+
}
3760+
3761+
impl fmt::Display for DropFunctionOption {
3762+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3763+
match self {
3764+
DropFunctionOption::Restrict => write!(f, "RESTRICT "),
3765+
DropFunctionOption::Cascade => write!(f, "CASCADE "),
3766+
}
3767+
}
3768+
}
3769+
3770+
/// Function describe in DROP FUNCTION.
3771+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3772+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3773+
pub struct DropFunctionDesc {
3774+
pub name: ObjectName,
3775+
pub args: Option<Vec<OperateFunctionArg>>,
3776+
}
3777+
3778+
impl fmt::Display for DropFunctionDesc {
3779+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3780+
write!(f, "{}", self.name)?;
3781+
if let Some(args) = &self.args {
3782+
write!(f, "({})", display_comma_separated(args))?;
3783+
}
3784+
Ok(())
3785+
}
3786+
}
3787+
3788+
/// Function argument in CREATE OR DROP FUNCTION.
37303789
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
37313790
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
3732-
pub struct CreateFunctionArg {
3791+
pub struct OperateFunctionArg {
37333792
pub mode: Option<ArgMode>,
37343793
pub name: Option<Ident>,
37353794
pub data_type: DataType,
37363795
pub default_expr: Option<Expr>,
37373796
}
37383797

3739-
impl CreateFunctionArg {
3798+
impl OperateFunctionArg {
37403799
/// Returns an unnamed argument.
37413800
pub fn unnamed(data_type: DataType) -> Self {
37423801
Self {
@@ -3758,7 +3817,7 @@ impl CreateFunctionArg {
37583817
}
37593818
}
37603819

3761-
impl fmt::Display for CreateFunctionArg {
3820+
impl fmt::Display for OperateFunctionArg {
37623821
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
37633822
if let Some(mode) = &self.mode {
37643823
write!(f, "{} ", mode)?;

src/parser.rs

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2343,7 +2343,13 @@ impl<'a> Parser<'a> {
23432343
} else if dialect_of!(self is PostgreSqlDialect) {
23442344
let name = self.parse_object_name()?;
23452345
self.expect_token(&Token::LParen)?;
2346-
let args = self.parse_comma_separated(Parser::parse_create_function_arg)?;
2346+
let args = if self.consume_token(&Token::RParen) {
2347+
self.prev_token();
2348+
None
2349+
} else {
2350+
Some(self.parse_comma_separated(Parser::parse_function_arg)?)
2351+
};
2352+
23472353
self.expect_token(&Token::RParen)?;
23482354

23492355
let return_type = if self.parse_keyword(Keyword::RETURNS) {
@@ -2358,7 +2364,7 @@ impl<'a> Parser<'a> {
23582364
or_replace,
23592365
temporary,
23602366
name,
2361-
args: Some(args),
2367+
args,
23622368
return_type,
23632369
params,
23642370
})
@@ -2368,7 +2374,7 @@ impl<'a> Parser<'a> {
23682374
}
23692375
}
23702376

2371-
fn parse_create_function_arg(&mut self) -> Result<CreateFunctionArg, ParserError> {
2377+
fn parse_function_arg(&mut self) -> Result<OperateFunctionArg, ParserError> {
23722378
let mode = if self.parse_keyword(Keyword::IN) {
23732379
Some(ArgMode::In)
23742380
} else if self.parse_keyword(Keyword::OUT) {
@@ -2394,7 +2400,7 @@ impl<'a> Parser<'a> {
23942400
} else {
23952401
None
23962402
};
2397-
Ok(CreateFunctionArg {
2403+
Ok(OperateFunctionArg {
23982404
mode,
23992405
name,
24002406
data_type,
@@ -2767,9 +2773,11 @@ impl<'a> Parser<'a> {
27672773
ObjectType::Schema
27682774
} else if self.parse_keyword(Keyword::SEQUENCE) {
27692775
ObjectType::Sequence
2776+
} else if self.parse_keyword(Keyword::FUNCTION) {
2777+
return self.parse_drop_function();
27702778
} else {
27712779
return self.expected(
2772-
"TABLE, VIEW, INDEX, ROLE, SCHEMA, or SEQUENCE after DROP",
2780+
"TABLE, VIEW, INDEX, ROLE, SCHEMA, FUNCTION or SEQUENCE after DROP",
27732781
self.peek_token(),
27742782
);
27752783
};
@@ -2796,6 +2804,41 @@ impl<'a> Parser<'a> {
27962804
})
27972805
}
27982806

2807+
/// DROP FUNCTION [ IF EXISTS ] name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] [, ...]
2808+
/// [ CASCADE | RESTRICT ]
2809+
fn parse_drop_function(&mut self) -> Result<Statement, ParserError> {
2810+
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
2811+
let func_desc = self.parse_comma_separated(Parser::parse_drop_function_desc)?;
2812+
let option = match self.parse_one_of_keywords(&[Keyword::CASCADE, Keyword::RESTRICT]) {
2813+
Some(Keyword::CASCADE) => Some(ReferentialAction::Cascade),
2814+
Some(Keyword::RESTRICT) => Some(ReferentialAction::Restrict),
2815+
_ => None,
2816+
};
2817+
Ok(Statement::DropFunction {
2818+
if_exists,
2819+
func_desc,
2820+
option,
2821+
})
2822+
}
2823+
2824+
fn parse_drop_function_desc(&mut self) -> Result<DropFunctionDesc, ParserError> {
2825+
let name = self.parse_object_name()?;
2826+
2827+
let args = if self.consume_token(&Token::LParen) {
2828+
if self.consume_token(&Token::RParen) {
2829+
None
2830+
} else {
2831+
let args = self.parse_comma_separated(Parser::parse_function_arg)?;
2832+
self.expect_token(&Token::RParen)?;
2833+
Some(args)
2834+
}
2835+
} else {
2836+
None
2837+
};
2838+
2839+
Ok(DropFunctionDesc { name, args })
2840+
}
2841+
27992842
/// DECLARE name [ BINARY ] [ ASENSITIVE | INSENSITIVE ] [ [ NO ] SCROLL ]
28002843
// CURSOR [ { WITH | WITHOUT } HOLD ] FOR query
28012844
pub fn parse_declare(&mut self) -> Result<Statement, ParserError> {

tests/sqlparser_postgres.rs

Lines changed: 95 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2348,8 +2348,8 @@ fn parse_create_function() {
23482348
temporary: false,
23492349
name: ObjectName(vec![Ident::new("add")]),
23502350
args: Some(vec![
2351-
CreateFunctionArg::unnamed(DataType::Integer(None)),
2352-
CreateFunctionArg::unnamed(DataType::Integer(None)),
2351+
OperateFunctionArg::unnamed(DataType::Integer(None)),
2352+
OperateFunctionArg::unnamed(DataType::Integer(None)),
23532353
]),
23542354
return_type: Some(DataType::Integer(None)),
23552355
params: CreateFunctionBody {
@@ -2371,8 +2371,8 @@ fn parse_create_function() {
23712371
temporary: false,
23722372
name: ObjectName(vec![Ident::new("add")]),
23732373
args: Some(vec![
2374-
CreateFunctionArg::with_name("a", DataType::Integer(None)),
2375-
CreateFunctionArg {
2374+
OperateFunctionArg::with_name("a", DataType::Integer(None)),
2375+
OperateFunctionArg {
23762376
mode: Some(ArgMode::In),
23772377
name: Some("b".into()),
23782378
data_type: DataType::Integer(None),
@@ -2400,7 +2400,7 @@ fn parse_create_function() {
24002400
or_replace: true,
24012401
temporary: false,
24022402
name: ObjectName(vec![Ident::new("increment")]),
2403-
args: Some(vec![CreateFunctionArg::with_name(
2403+
args: Some(vec![OperateFunctionArg::with_name(
24042404
"i",
24052405
DataType::Integer(None)
24062406
)]),
@@ -2417,3 +2417,93 @@ fn parse_create_function() {
24172417
}
24182418
);
24192419
}
2420+
2421+
#[test]
2422+
fn parse_drop_function() {
2423+
let sql = "DROP FUNCTION IF EXISTS test_func";
2424+
assert_eq!(
2425+
pg().verified_stmt(sql),
2426+
Statement::DropFunction {
2427+
if_exists: true,
2428+
func_desc: vec![DropFunctionDesc {
2429+
name: ObjectName(vec![Ident {
2430+
value: "test_func".to_string(),
2431+
quote_style: None
2432+
}]),
2433+
args: None
2434+
}],
2435+
option: None
2436+
}
2437+
);
2438+
2439+
let sql = "DROP FUNCTION IF EXISTS test_func(a INTEGER, IN b INTEGER = 1)";
2440+
assert_eq!(
2441+
pg().verified_stmt(sql),
2442+
Statement::DropFunction {
2443+
if_exists: true,
2444+
func_desc: vec![DropFunctionDesc {
2445+
name: ObjectName(vec![Ident {
2446+
value: "test_func".to_string(),
2447+
quote_style: None
2448+
}]),
2449+
args: Some(vec![
2450+
OperateFunctionArg::with_name("a", DataType::Integer(None)),
2451+
OperateFunctionArg {
2452+
mode: Some(ArgMode::In),
2453+
name: Some("b".into()),
2454+
data_type: DataType::Integer(None),
2455+
default_expr: Some(Expr::Value(Value::Number("1".parse().unwrap(), false))),
2456+
}
2457+
]),
2458+
}],
2459+
option: None
2460+
}
2461+
);
2462+
2463+
let sql = "DROP FUNCTION IF EXISTS test_func1(a INTEGER, IN b INTEGER = 1), test_func2(a VARCHAR, IN b INTEGER = 1)";
2464+
assert_eq!(
2465+
pg().verified_stmt(sql),
2466+
Statement::DropFunction {
2467+
if_exists: true,
2468+
func_desc: vec![
2469+
DropFunctionDesc {
2470+
name: ObjectName(vec![Ident {
2471+
value: "test_func1".to_string(),
2472+
quote_style: None
2473+
}]),
2474+
args: Some(vec![
2475+
OperateFunctionArg::with_name("a", DataType::Integer(None)),
2476+
OperateFunctionArg {
2477+
mode: Some(ArgMode::In),
2478+
name: Some("b".into()),
2479+
data_type: DataType::Integer(None),
2480+
default_expr: Some(Expr::Value(Value::Number(
2481+
"1".parse().unwrap(),
2482+
false
2483+
))),
2484+
}
2485+
]),
2486+
},
2487+
DropFunctionDesc {
2488+
name: ObjectName(vec![Ident {
2489+
value: "test_func2".to_string(),
2490+
quote_style: None
2491+
}]),
2492+
args: Some(vec![
2493+
OperateFunctionArg::with_name("a", DataType::Varchar(None)),
2494+
OperateFunctionArg {
2495+
mode: Some(ArgMode::In),
2496+
name: Some("b".into()),
2497+
data_type: DataType::Integer(None),
2498+
default_expr: Some(Expr::Value(Value::Number(
2499+
"1".parse().unwrap(),
2500+
false
2501+
))),
2502+
}
2503+
]),
2504+
}
2505+
],
2506+
option: None
2507+
}
2508+
);
2509+
}

0 commit comments

Comments
 (0)