Skip to content

Commit 6521aff

Browse files
committed
Implements DROP POLICY syntax for PostgreSQL
```SQL DROP POLICY [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ] ``` For the documentation, please refer: https://www.postgresql.org/docs/current/sql-createpolicy.html This closes apache#1404.
1 parent 8a534c0 commit 6521aff

File tree

3 files changed

+98
-11
lines changed

3 files changed

+98
-11
lines changed

src/ast/mod.rs

+26
Original file line numberDiff line numberDiff line change
@@ -2546,6 +2546,16 @@ pub enum Statement {
25462546
name: Ident,
25472547
storage_specifier: Option<Ident>,
25482548
},
2549+
///```sql
2550+
/// DROP POLICY
2551+
/// ```
2552+
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html)
2553+
DropPolicy {
2554+
if_exists: bool,
2555+
name: Ident,
2556+
table_name: ObjectName,
2557+
option: Option<ReferentialAction>,
2558+
},
25492559
/// ```sql
25502560
/// DECLARE
25512561
/// ```
@@ -4258,6 +4268,22 @@ impl fmt::Display for Statement {
42584268
}
42594269
Ok(())
42604270
}
4271+
Statement::DropPolicy {
4272+
if_exists,
4273+
name,
4274+
table_name,
4275+
option,
4276+
} => {
4277+
write!(f, "DROP POLICY")?;
4278+
if *if_exists {
4279+
write!(f, " IF EXISTS")?;
4280+
}
4281+
write!(f, " {name} ON {table_name}")?;
4282+
if let Some(option) = option {
4283+
write!(f, " {option}")?;
4284+
}
4285+
Ok(())
4286+
}
42614287
Statement::Discard { object_type } => {
42624288
write!(f, "DISCARD {object_type}")?;
42634289
Ok(())

src/parser/mod.rs

+31-11
Original file line numberDiff line numberDiff line change
@@ -4887,6 +4887,8 @@ impl<'a> Parser<'a> {
48874887
ObjectType::Stage
48884888
} else if self.parse_keyword(Keyword::FUNCTION) {
48894889
return self.parse_drop_function();
4890+
} else if self.parse_keyword(Keyword::POLICY) {
4891+
return self.parse_drop_policy();
48904892
} else if self.parse_keyword(Keyword::PROCEDURE) {
48914893
return self.parse_drop_procedure();
48924894
} else if self.parse_keyword(Keyword::SECRET) {
@@ -4928,38 +4930,56 @@ impl<'a> Parser<'a> {
49284930
})
49294931
}
49304932

4933+
fn parse_optional_referential_action(&mut self) -> Option<ReferentialAction> {
4934+
match self.parse_one_of_keywords(&[Keyword::CASCADE, Keyword::RESTRICT]) {
4935+
Some(Keyword::CASCADE) => Some(ReferentialAction::Cascade),
4936+
Some(Keyword::RESTRICT) => Some(ReferentialAction::Restrict),
4937+
_ => None,
4938+
}
4939+
}
4940+
49314941
/// ```sql
49324942
/// DROP FUNCTION [ IF EXISTS ] name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] [, ...]
49334943
/// [ CASCADE | RESTRICT ]
49344944
/// ```
49354945
fn parse_drop_function(&mut self) -> Result<Statement, ParserError> {
49364946
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
49374947
let func_desc = self.parse_comma_separated(Parser::parse_function_desc)?;
4938-
let option = match self.parse_one_of_keywords(&[Keyword::CASCADE, Keyword::RESTRICT]) {
4939-
Some(Keyword::CASCADE) => Some(ReferentialAction::Cascade),
4940-
Some(Keyword::RESTRICT) => Some(ReferentialAction::Restrict),
4941-
_ => None,
4942-
};
4948+
let option = self.parse_optional_referential_action();
49434949
Ok(Statement::DropFunction {
49444950
if_exists,
49454951
func_desc,
49464952
option,
49474953
})
49484954
}
49494955

4956+
/// ```sql
4957+
/// DROP POLICY [ IF EXISTS ] name ON table_name [ CASCADE | RESTRICT ]
4958+
/// ```
4959+
///
4960+
/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-droppolicy.html)
4961+
fn parse_drop_policy(&mut self) -> Result<Statement, ParserError> {
4962+
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
4963+
let name = self.parse_identifier(false)?;
4964+
self.expect_keyword(Keyword::ON)?;
4965+
let table_name = self.parse_object_name(false)?;
4966+
let option = self.parse_optional_referential_action();
4967+
Ok(Statement::DropPolicy {
4968+
if_exists,
4969+
name,
4970+
table_name,
4971+
option,
4972+
})
4973+
}
4974+
49504975
/// ```sql
49514976
/// DROP PROCEDURE [ IF EXISTS ] name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] [, ...]
49524977
/// [ CASCADE | RESTRICT ]
49534978
/// ```
49544979
fn parse_drop_procedure(&mut self) -> Result<Statement, ParserError> {
49554980
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
49564981
let proc_desc = self.parse_comma_separated(Parser::parse_function_desc)?;
4957-
let option = match self.parse_one_of_keywords(&[Keyword::CASCADE, Keyword::RESTRICT]) {
4958-
Some(Keyword::CASCADE) => Some(ReferentialAction::Cascade),
4959-
Some(Keyword::RESTRICT) => Some(ReferentialAction::Restrict),
4960-
Some(_) => unreachable!(), // parse_one_of_keywords does not return other keywords
4961-
None => None,
4962-
};
4982+
let option = self.parse_optional_referential_action();
49634983
Ok(Statement::DropProcedure {
49644984
if_exists,
49654985
proc_desc,

tests/sqlparser_common.rs

+41
Original file line numberDiff line numberDiff line change
@@ -11089,3 +11089,44 @@ fn test_create_policy() {
1108911089
"sql parser error: Expected: (, found: EOF"
1109011090
);
1109111091
}
11092+
11093+
#[test]
11094+
fn test_drop_policy() {
11095+
let sql = "DROP POLICY IF EXISTS my_policy ON my_table RESTRICT";
11096+
match all_dialects().verified_stmt(sql) {
11097+
Statement::DropPolicy {
11098+
if_exists,
11099+
name,
11100+
table_name,
11101+
option,
11102+
} => {
11103+
assert_eq!(if_exists, true);
11104+
assert_eq!(name.to_string(), "my_policy");
11105+
assert_eq!(table_name.to_string(), "my_table");
11106+
assert_eq!(option, Some(ReferentialAction::Restrict));
11107+
}
11108+
_ => unreachable!(),
11109+
}
11110+
11111+
// omit IF EXISTS is allowed
11112+
all_dialects().verified_stmt("DROP POLICY my_policy ON my_table CASCADE");
11113+
// omit option is allowed
11114+
all_dialects().verified_stmt("DROP POLICY my_policy ON my_table");
11115+
11116+
// missing table name
11117+
assert_eq!(
11118+
all_dialects()
11119+
.parse_sql_statements("DROP POLICY my_policy")
11120+
.unwrap_err()
11121+
.to_string(),
11122+
"sql parser error: Expected: ON, found: EOF"
11123+
);
11124+
// Wrong option name
11125+
assert_eq!(
11126+
all_dialects()
11127+
.parse_sql_statements("DROP POLICY my_policy ON my_table WRONG")
11128+
.unwrap_err()
11129+
.to_string(),
11130+
"sql parser error: Expected: end of statement, found: WRONG"
11131+
);
11132+
}

0 commit comments

Comments
 (0)