Skip to content

Commit d7e84be

Browse files
blxalamb
andauthored
Add basic support for GRANT and REVOKE (apache#365)
* Add basic support for GRANT privileges on tables and sequences * Cargo fmt * Make enum for granted privileges * Implement and use Display for GrantObjects * Simplify Display for GrantPrivileges * Add column privileges * Add second column privilege to test * Add REVOKE privileges and reformat * Fix some clippy warnings * Fix more clippy Co-authored-by: Andrew Lamb <[email protected]>
1 parent d33bacf commit d7e84be

File tree

4 files changed

+528
-0
lines changed

4 files changed

+528
-0
lines changed

src/ast/mod.rs

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,22 @@ pub enum Statement {
763763
condition: Expr,
764764
message: Option<Expr>,
765765
},
766+
/// GRANT privileges ON objects TO grantees
767+
Grant {
768+
privileges: Privileges,
769+
objects: GrantObjects,
770+
grantees: Vec<Ident>,
771+
with_grant_option: bool,
772+
granted_by: Option<Ident>,
773+
},
774+
/// REVOKE privileges ON objects FROM grantees
775+
Revoke {
776+
privileges: Privileges,
777+
objects: GrantObjects,
778+
grantees: Vec<Ident>,
779+
granted_by: Option<Ident>,
780+
cascade: bool,
781+
},
766782
/// `DEALLOCATE [ PREPARE ] { name | ALL }`
767783
///
768784
/// Note: this is a PostgreSQL-specific statement.
@@ -1330,6 +1346,40 @@ impl fmt::Display for Statement {
13301346
}
13311347
Ok(())
13321348
}
1349+
Statement::Grant {
1350+
privileges,
1351+
objects,
1352+
grantees,
1353+
with_grant_option,
1354+
granted_by,
1355+
} => {
1356+
write!(f, "GRANT {} ", privileges)?;
1357+
write!(f, "ON {} ", objects)?;
1358+
write!(f, "TO {}", display_comma_separated(grantees))?;
1359+
if *with_grant_option {
1360+
write!(f, " WITH GRANT OPTION")?;
1361+
}
1362+
if let Some(grantor) = granted_by {
1363+
write!(f, " GRANTED BY {}", grantor)?;
1364+
}
1365+
Ok(())
1366+
}
1367+
Statement::Revoke {
1368+
privileges,
1369+
objects,
1370+
grantees,
1371+
granted_by,
1372+
cascade,
1373+
} => {
1374+
write!(f, "REVOKE {} ", privileges)?;
1375+
write!(f, "ON {} ", objects)?;
1376+
write!(f, "FROM {}", display_comma_separated(grantees))?;
1377+
if let Some(grantor) = granted_by {
1378+
write!(f, " GRANTED BY {}", grantor)?;
1379+
}
1380+
write!(f, " {}", if *cascade { "CASCADE" } else { "RESTRICT" })?;
1381+
Ok(())
1382+
}
13331383
Statement::Deallocate { name, prepare } => write!(
13341384
f,
13351385
"DEALLOCATE {prepare}{name}",
@@ -1358,6 +1408,137 @@ impl fmt::Display for Statement {
13581408
}
13591409
}
13601410

1411+
/// Privileges granted in a GRANT statement or revoked in a REVOKE statement.
1412+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1413+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1414+
pub enum Privileges {
1415+
/// All privileges applicable to the object type
1416+
All {
1417+
/// Optional keyword from the spec, ignored in practice
1418+
with_privileges_keyword: bool,
1419+
},
1420+
/// Specific privileges (e.g. `SELECT`, `INSERT`)
1421+
Actions(Vec<Action>),
1422+
}
1423+
1424+
impl fmt::Display for Privileges {
1425+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1426+
match self {
1427+
Privileges::All {
1428+
with_privileges_keyword,
1429+
} => {
1430+
write!(
1431+
f,
1432+
"ALL{}",
1433+
if *with_privileges_keyword {
1434+
" PRIVILEGES"
1435+
} else {
1436+
""
1437+
}
1438+
)
1439+
}
1440+
Privileges::Actions(actions) => {
1441+
write!(f, "{}", display_comma_separated(actions).to_string())
1442+
}
1443+
}
1444+
}
1445+
}
1446+
1447+
/// A privilege on a database object (table, sequence, etc.).
1448+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1449+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1450+
pub enum Action {
1451+
Connect,
1452+
Create,
1453+
Delete,
1454+
Execute,
1455+
Insert { columns: Option<Vec<Ident>> },
1456+
References { columns: Option<Vec<Ident>> },
1457+
Select { columns: Option<Vec<Ident>> },
1458+
Temporary,
1459+
Trigger,
1460+
Truncate,
1461+
Update { columns: Option<Vec<Ident>> },
1462+
Usage,
1463+
}
1464+
1465+
impl fmt::Display for Action {
1466+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1467+
match self {
1468+
Action::Connect => f.write_str("CONNECT")?,
1469+
Action::Create => f.write_str("CREATE")?,
1470+
Action::Delete => f.write_str("DELETE")?,
1471+
Action::Execute => f.write_str("EXECUTE")?,
1472+
Action::Insert { .. } => f.write_str("INSERT")?,
1473+
Action::References { .. } => f.write_str("REFERENCES")?,
1474+
Action::Select { .. } => f.write_str("SELECT")?,
1475+
Action::Temporary => f.write_str("TEMPORARY")?,
1476+
Action::Trigger => f.write_str("TRIGGER")?,
1477+
Action::Truncate => f.write_str("TRUNCATE")?,
1478+
Action::Update { .. } => f.write_str("UPDATE")?,
1479+
Action::Usage => f.write_str("USAGE")?,
1480+
};
1481+
match self {
1482+
Action::Insert { columns }
1483+
| Action::References { columns }
1484+
| Action::Select { columns }
1485+
| Action::Update { columns } => {
1486+
if let Some(columns) = columns {
1487+
write!(f, " ({})", display_comma_separated(columns))?;
1488+
}
1489+
}
1490+
_ => (),
1491+
};
1492+
Ok(())
1493+
}
1494+
}
1495+
1496+
/// Objects on which privileges are granted in a GRANT statement.
1497+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1498+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1499+
pub enum GrantObjects {
1500+
/// Grant privileges on `ALL SEQUENCES IN SCHEMA <schema_name> [, ...]`
1501+
AllSequencesInSchema { schemas: Vec<ObjectName> },
1502+
/// Grant privileges on `ALL TABLES IN SCHEMA <schema_name> [, ...]`
1503+
AllTablesInSchema { schemas: Vec<ObjectName> },
1504+
/// Grant privileges on specific schemas
1505+
Schemas(Vec<ObjectName>),
1506+
/// Grant privileges on specific sequences
1507+
Sequences(Vec<ObjectName>),
1508+
/// Grant privileges on specific tables
1509+
Tables(Vec<ObjectName>),
1510+
}
1511+
1512+
impl fmt::Display for GrantObjects {
1513+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1514+
match self {
1515+
GrantObjects::Sequences(sequences) => {
1516+
write!(f, "SEQUENCE {}", display_comma_separated(sequences))
1517+
}
1518+
GrantObjects::Schemas(schemas) => {
1519+
write!(f, "SCHEMA {}", display_comma_separated(schemas))
1520+
}
1521+
GrantObjects::Tables(tables) => {
1522+
write!(f, "{}", display_comma_separated(tables))
1523+
}
1524+
GrantObjects::AllSequencesInSchema { schemas } => {
1525+
write!(
1526+
f,
1527+
"ALL SEQUENCES IN SCHEMA {}",
1528+
display_comma_separated(schemas)
1529+
)
1530+
}
1531+
GrantObjects::AllTablesInSchema { schemas } => {
1532+
write!(
1533+
f,
1534+
"ALL TABLES IN SCHEMA {}",
1535+
display_comma_separated(schemas)
1536+
)
1537+
}
1538+
}
1539+
}
1540+
}
1541+
13611542
/// SQL assignment `foo = expr` as used in SQLUpdate
13621543
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
13631544
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]

src/keywords.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ define_keywords!(
225225
GET,
226226
GLOBAL,
227227
GRANT,
228+
GRANTED,
228229
GROUP,
229230
GROUPING,
230231
GROUPS,
@@ -318,6 +319,7 @@ define_keywords!(
318319
ON,
319320
ONLY,
320321
OPEN,
322+
OPTION,
321323
OR,
322324
ORC,
323325
ORDER,
@@ -348,6 +350,7 @@ define_keywords!(
348350
PRECISION,
349351
PREPARE,
350352
PRIMARY,
353+
PRIVILEGES,
351354
PROCEDURE,
352355
PURGE,
353356
RANGE,
@@ -395,7 +398,9 @@ define_keywords!(
395398
SECOND,
396399
SELECT,
397400
SENSITIVE,
401+
SEQUENCE,
398402
SEQUENCEFILE,
403+
SEQUENCES,
399404
SERDE,
400405
SERIALIZABLE,
401406
SESSION,
@@ -432,6 +437,7 @@ define_keywords!(
432437
SYSTEM_TIME,
433438
SYSTEM_USER,
434439
TABLE,
440+
TABLES,
435441
TABLESAMPLE,
436442
TBLPROPERTIES,
437443
TEMP,
@@ -468,6 +474,7 @@ define_keywords!(
468474
UNNEST,
469475
UPDATE,
470476
UPPER,
477+
USAGE,
471478
USER,
472479
USING,
473480
UUID,

0 commit comments

Comments
 (0)