Skip to content

Commit 38f6f84

Browse files
committed
Add support for DENY statements
1 parent a5b9821 commit 38f6f84

File tree

5 files changed

+100
-4
lines changed

5 files changed

+100
-4
lines changed

src/ast/mod.rs

+36
Original file line numberDiff line numberDiff line change
@@ -3794,6 +3794,10 @@ pub enum Statement {
37943794
granted_by: Option<Ident>,
37953795
},
37963796
/// ```sql
3797+
/// DENY privileges ON object TO grantees
3798+
/// ```
3799+
Deny(DenyStatement),
3800+
/// ```sql
37973801
/// REVOKE privileges ON objects FROM grantees
37983802
/// ```
37993803
Revoke {
@@ -5424,6 +5428,7 @@ impl fmt::Display for Statement {
54245428
}
54255429
Ok(())
54265430
}
5431+
Statement::Deny(s) => write!(f, "{s}"),
54275432
Statement::Revoke {
54285433
privileges,
54295434
objects,
@@ -6674,6 +6679,37 @@ impl fmt::Display for GrantObjects {
66746679
}
66756680
}
66766681

6682+
/// A `DENY` statement
6683+
///
6684+
/// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/deny-transact-sql)
6685+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6686+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6687+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6688+
pub struct DenyStatement {
6689+
pub privileges: Privileges,
6690+
pub objects: GrantObjects,
6691+
pub grantees: Vec<Grantee>,
6692+
pub granted_by: Option<Ident>,
6693+
pub cascade: Option<CascadeOption>,
6694+
}
6695+
6696+
impl fmt::Display for DenyStatement {
6697+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6698+
write!(f, "DENY {}", self.privileges)?;
6699+
write!(f, " ON {}", self.objects)?;
6700+
if !self.grantees.is_empty() {
6701+
write!(f, " TO {}", display_comma_separated(&self.grantees))?;
6702+
}
6703+
if let Some(cascade) = &self.cascade {
6704+
write!(f, " {cascade}")?;
6705+
}
6706+
if let Some(granted_by) = &self.granted_by {
6707+
write!(f, " AS {granted_by}")?;
6708+
}
6709+
Ok(())
6710+
}
6711+
}
6712+
66776713
/// SQL assignment `foo = expr` as used in SQLUpdate
66786714
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
66796715
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]

src/ast/spans.rs

+1
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,7 @@ impl Spanned for Statement {
486486
Statement::CreateStage { .. } => Span::empty(),
487487
Statement::Assert { .. } => Span::empty(),
488488
Statement::Grant { .. } => Span::empty(),
489+
Statement::Deny { .. } => Span::empty(),
489490
Statement::Revoke { .. } => Span::empty(),
490491
Statement::Deallocate { .. } => Span::empty(),
491492
Statement::Execute { .. } => Span::empty(),

src/keywords.rs

+1
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ define_keywords!(
273273
DELIMITER,
274274
DELTA,
275275
DENSE_RANK,
276+
DENY,
276277
DEREF,
277278
DESC,
278279
DESCRIBE,

src/parser/mod.rs

+38-4
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,10 @@ impl<'a> Parser<'a> {
575575
Keyword::SHOW => self.parse_show(),
576576
Keyword::USE => self.parse_use(),
577577
Keyword::GRANT => self.parse_grant(),
578+
Keyword::DENY => {
579+
self.prev_token();
580+
self.parse_deny()
581+
}
578582
Keyword::REVOKE => self.parse_revoke(),
579583
Keyword::START => self.parse_start_transaction(),
580584
Keyword::BEGIN => self.parse_begin(),
@@ -12987,7 +12991,7 @@ impl<'a> Parser<'a> {
1298712991

1298812992
/// Parse a GRANT statement.
1298912993
pub fn parse_grant(&mut self) -> Result<Statement, ParserError> {
12990-
let (privileges, objects) = self.parse_grant_revoke_privileges_objects()?;
12994+
let (privileges, objects) = self.parse_grant_deny_revoke_privileges_objects()?;
1299112995

1299212996
self.expect_keyword_is(Keyword::TO)?;
1299312997
let grantees = self.parse_grantees()?;
@@ -13066,7 +13070,7 @@ impl<'a> Parser<'a> {
1306613070
Ok(values)
1306713071
}
1306813072

13069-
pub fn parse_grant_revoke_privileges_objects(
13073+
pub fn parse_grant_deny_revoke_privileges_objects(
1307013074
&mut self,
1307113075
) -> Result<(Privileges, Option<GrantObjects>), ParserError> {
1307213076
let privileges = if self.parse_keyword(Keyword::ALL) {
@@ -13116,7 +13120,6 @@ impl<'a> Parser<'a> {
1311613120
let object_type = self.parse_one_of_keywords(&[
1311713121
Keyword::SEQUENCE,
1311813122
Keyword::DATABASE,
13119-
Keyword::DATABASE,
1312013123
Keyword::SCHEMA,
1312113124
Keyword::TABLE,
1312213125
Keyword::VIEW,
@@ -13409,9 +13412,40 @@ impl<'a> Parser<'a> {
1340913412
}
1341013413
}
1341113414

13415+
/// Parse [`Statement::Deny`]
13416+
pub fn parse_deny(&mut self) -> Result<Statement, ParserError> {
13417+
self.expect_keyword(Keyword::DENY)?;
13418+
13419+
let (privileges, objects) = self.parse_grant_deny_revoke_privileges_objects()?;
13420+
let objects = match objects {
13421+
Some(o) => o,
13422+
None => {
13423+
return parser_err!(
13424+
"DENY statements must specify an object",
13425+
self.peek_token().span.start
13426+
)
13427+
}
13428+
};
13429+
13430+
self.expect_keyword_is(Keyword::TO)?;
13431+
let grantees = self.parse_grantees()?;
13432+
let cascade = self.parse_cascade_option();
13433+
let granted_by = self
13434+
.parse_keywords(&[Keyword::AS])
13435+
.then(|| self.parse_identifier().unwrap());
13436+
13437+
Ok(Statement::Deny(DenyStatement {
13438+
privileges,
13439+
objects,
13440+
grantees,
13441+
cascade,
13442+
granted_by,
13443+
}))
13444+
}
13445+
1341213446
/// Parse a REVOKE statement
1341313447
pub fn parse_revoke(&mut self) -> Result<Statement, ParserError> {
13414-
let (privileges, objects) = self.parse_grant_revoke_privileges_objects()?;
13448+
let (privileges, objects) = self.parse_grant_deny_revoke_privileges_objects()?;
1341513449

1341613450
self.expect_keyword_is(Keyword::FROM)?;
1341713451
let grantees = self.parse_grantees()?;

tests/sqlparser_common.rs

+24
Original file line numberDiff line numberDiff line change
@@ -9325,6 +9325,30 @@ fn parse_grant() {
93259325
verified_stmt("GRANT SELECT ON VIEW view1 TO ROLE role1");
93269326
}
93279327

9328+
#[test]
9329+
fn parse_deny() {
9330+
let sql = "DENY INSERT, DELETE ON users TO analyst CASCADE AS admin";
9331+
match verified_stmt(sql) {
9332+
Statement::Deny(deny) => {
9333+
assert_eq!(
9334+
Privileges::Actions(vec![Action::Insert { columns: None }, Action::Delete]),
9335+
deny.privileges
9336+
);
9337+
assert_eq!(
9338+
&GrantObjects::Tables(vec![ObjectName::from(vec![Ident::new("users")])]),
9339+
&deny.objects
9340+
);
9341+
assert_eq_vec(&["analyst"], &deny.grantees);
9342+
assert_eq!(Some(CascadeOption::Cascade), deny.cascade);
9343+
assert_eq!(Some(Ident::from("admin")), deny.granted_by);
9344+
}
9345+
_ => unreachable!(),
9346+
}
9347+
9348+
verified_stmt("DENY SELECT, INSERT, UPDATE, DELETE ON db1.sc1 TO role1");
9349+
verified_stmt("DENY ALL ON db1.sc1 TO role1");
9350+
}
9351+
93289352
#[test]
93299353
fn test_revoke() {
93309354
let sql = "REVOKE ALL PRIVILEGES ON users, auth FROM analyst";

0 commit comments

Comments
 (0)