Skip to content

Commit 38c8a17

Browse files
committed
Add support for DENY statements
1 parent 178a351 commit 38c8a17

File tree

5 files changed

+100
-4
lines changed

5 files changed

+100
-4
lines changed

src/ast/mod.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3906,6 +3906,10 @@ pub enum Statement {
39063906
granted_by: Option<Ident>,
39073907
},
39083908
/// ```sql
3909+
/// DENY privileges ON object TO grantees
3910+
/// ```
3911+
Deny(DenyStatement),
3912+
/// ```sql
39093913
/// REVOKE privileges ON objects FROM grantees
39103914
/// ```
39113915
Revoke {
@@ -5595,6 +5599,7 @@ impl fmt::Display for Statement {
55955599
}
55965600
Ok(())
55975601
}
5602+
Statement::Deny(s) => write!(f, "{s}"),
55985603
Statement::Revoke {
55995604
privileges,
56005605
objects,
@@ -6867,6 +6872,37 @@ impl fmt::Display for GrantObjects {
68676872
}
68686873
}
68696874

6875+
/// A `DENY` statement
6876+
///
6877+
/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
6878+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6879+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6880+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6881+
pub struct DenyStatement {
6882+
pub privileges: Privileges,
6883+
pub objects: GrantObjects,
6884+
pub grantees: Vec<Grantee>,
6885+
pub granted_by: Option<Ident>,
6886+
pub cascade: Option<CascadeOption>,
6887+
}
6888+
6889+
impl fmt::Display for DenyStatement {
6890+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6891+
write!(f, "DENY {}", self.privileges)?;
6892+
write!(f, " ON {}", self.objects)?;
6893+
if !self.grantees.is_empty() {
6894+
write!(f, " TO {}", display_comma_separated(&self.grantees))?;
6895+
}
6896+
if let Some(cascade) = &self.cascade {
6897+
write!(f, " {cascade}")?;
6898+
}
6899+
if let Some(granted_by) = &self.granted_by {
6900+
write!(f, " AS {granted_by}")?;
6901+
}
6902+
Ok(())
6903+
}
6904+
}
6905+
68706906
/// SQL assignment `foo = expr` as used in SQLUpdate
68716907
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
68726908
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]

src/ast/spans.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,7 @@ impl Spanned for Statement {
491491
Statement::CreateStage { .. } => Span::empty(),
492492
Statement::Assert { .. } => Span::empty(),
493493
Statement::Grant { .. } => Span::empty(),
494+
Statement::Deny { .. } => Span::empty(),
494495
Statement::Revoke { .. } => Span::empty(),
495496
Statement::Deallocate { .. } => Span::empty(),
496497
Statement::Execute { .. } => Span::empty(),

src/keywords.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ define_keywords!(
278278
DELIMITER,
279279
DELTA,
280280
DENSE_RANK,
281+
DENY,
281282
DEREF,
282283
DESC,
283284
DESCRIBE,

src/parser/mod.rs

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,10 @@ impl<'a> Parser<'a> {
583583
Keyword::SHOW => self.parse_show(),
584584
Keyword::USE => self.parse_use(),
585585
Keyword::GRANT => self.parse_grant(),
586+
Keyword::DENY => {
587+
self.prev_token();
588+
self.parse_deny()
589+
}
586590
Keyword::REVOKE => self.parse_revoke(),
587591
Keyword::START => self.parse_start_transaction(),
588592
Keyword::BEGIN => self.parse_begin(),
@@ -13381,7 +13385,7 @@ impl<'a> Parser<'a> {
1338113385

1338213386
/// Parse a GRANT statement.
1338313387
pub fn parse_grant(&mut self) -> Result<Statement, ParserError> {
13384-
let (privileges, objects) = self.parse_grant_revoke_privileges_objects()?;
13388+
let (privileges, objects) = self.parse_grant_deny_revoke_privileges_objects()?;
1338513389

1338613390
self.expect_keyword_is(Keyword::TO)?;
1338713391
let grantees = self.parse_grantees()?;
@@ -13460,7 +13464,7 @@ impl<'a> Parser<'a> {
1346013464
Ok(values)
1346113465
}
1346213466

13463-
pub fn parse_grant_revoke_privileges_objects(
13467+
pub fn parse_grant_deny_revoke_privileges_objects(
1346413468
&mut self,
1346513469
) -> Result<(Privileges, Option<GrantObjects>), ParserError> {
1346613470
let privileges = if self.parse_keyword(Keyword::ALL) {
@@ -13510,7 +13514,6 @@ impl<'a> Parser<'a> {
1351013514
let object_type = self.parse_one_of_keywords(&[
1351113515
Keyword::SEQUENCE,
1351213516
Keyword::DATABASE,
13513-
Keyword::DATABASE,
1351413517
Keyword::SCHEMA,
1351513518
Keyword::TABLE,
1351613519
Keyword::VIEW,
@@ -13803,9 +13806,40 @@ impl<'a> Parser<'a> {
1380313806
}
1380413807
}
1380513808

13809+
/// Parse [`Statement::Deny`]
13810+
pub fn parse_deny(&mut self) -> Result<Statement, ParserError> {
13811+
self.expect_keyword(Keyword::DENY)?;
13812+
13813+
let (privileges, objects) = self.parse_grant_deny_revoke_privileges_objects()?;
13814+
let objects = match objects {
13815+
Some(o) => o,
13816+
None => {
13817+
return parser_err!(
13818+
"DENY statements must specify an object",
13819+
self.peek_token().span.start
13820+
)
13821+
}
13822+
};
13823+
13824+
self.expect_keyword_is(Keyword::TO)?;
13825+
let grantees = self.parse_grantees()?;
13826+
let cascade = self.parse_cascade_option();
13827+
let granted_by = self
13828+
.parse_keywords(&[Keyword::AS])
13829+
.then(|| self.parse_identifier().unwrap());
13830+
13831+
Ok(Statement::Deny(DenyStatement {
13832+
privileges,
13833+
objects,
13834+
grantees,
13835+
cascade,
13836+
granted_by,
13837+
}))
13838+
}
13839+
1380613840
/// Parse a REVOKE statement
1380713841
pub fn parse_revoke(&mut self) -> Result<Statement, ParserError> {
13808-
let (privileges, objects) = self.parse_grant_revoke_privileges_objects()?;
13842+
let (privileges, objects) = self.parse_grant_deny_revoke_privileges_objects()?;
1380913843

1381013844
self.expect_keyword_is(Keyword::FROM)?;
1381113845
let grantees = self.parse_grantees()?;

tests/sqlparser_common.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9333,6 +9333,30 @@ fn parse_grant() {
93339333
verified_stmt("GRANT SELECT ON VIEW view1 TO ROLE role1");
93349334
}
93359335

9336+
#[test]
9337+
fn parse_deny() {
9338+
let sql = "DENY INSERT, DELETE ON users TO analyst CASCADE AS admin";
9339+
match verified_stmt(sql) {
9340+
Statement::Deny(deny) => {
9341+
assert_eq!(
9342+
Privileges::Actions(vec![Action::Insert { columns: None }, Action::Delete]),
9343+
deny.privileges
9344+
);
9345+
assert_eq!(
9346+
&GrantObjects::Tables(vec![ObjectName::from(vec![Ident::new("users")])]),
9347+
&deny.objects
9348+
);
9349+
assert_eq_vec(&["analyst"], &deny.grantees);
9350+
assert_eq!(Some(CascadeOption::Cascade), deny.cascade);
9351+
assert_eq!(Some(Ident::from("admin")), deny.granted_by);
9352+
}
9353+
_ => unreachable!(),
9354+
}
9355+
9356+
verified_stmt("DENY SELECT, INSERT, UPDATE, DELETE ON db1.sc1 TO role1, role2");
9357+
verified_stmt("DENY ALL ON db1.sc1 TO role1");
9358+
}
9359+
93369360
#[test]
93379361
fn test_revoke() {
93389362
let sql = "REVOKE ALL PRIVILEGES ON users, auth FROM analyst";

0 commit comments

Comments
 (0)