Skip to content

feat: add show grant on object and show grant of share sql #7181

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Aug 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 41 additions & 13 deletions src/meta/api/src/share_api_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ impl<KV: KVApi> ShareApi for KV {
debug!(req = debug(&req), "ShareApi: {}", func_name!());

// Get all outbound share accounts.
let outbound_accounts = get_outbound_shared_accounts_by_tenant(self, &req.tenant).await?;
let outbound_accounts = get_outbound_share_infos_by_tenant(self, &req.tenant).await?;

// Get all inbound share accounts.
let inbound_accounts = get_inbound_shared_accounts_by_tenant(self, &req.tenant).await?;
let inbound_accounts = get_inbound_share_infos_by_tenant(self, &req.tenant).await?;

Ok(ShowSharesReply {
outbound_accounts,
Expand Down Expand Up @@ -759,11 +759,9 @@ impl<KV: KVApi> ShareApi for KV {
&self,
req: GetShareGrantTenantsReq,
) -> MetaResult<GetShareGrantTenantsReply> {
let reply = get_outbound_shared_accounts_by_name(self, &req.share_name).await?;
let accounts = get_outbound_share_tenants_by_name(self, &req.share_name).await?;

Ok(GetShareGrantTenantsReply {
accounts: reply.accounts.unwrap_or_default(),
})
Ok(GetShareGrantTenantsReply { accounts })
}

// Return all the grant privileges of the object
Expand Down Expand Up @@ -920,7 +918,37 @@ async fn get_share_database_name(
}
}

async fn get_outbound_shared_accounts_by_name(
async fn get_outbound_share_tenants_by_name(
kv_api: &(impl KVApi + ?Sized),
share_name: &ShareNameIdent,
) -> Result<Vec<GetShareGrantTenants>, MetaError> {
let res = get_share_or_err(kv_api, share_name, format!("get_share: {share_name}")).await?;
let (_share_id_seq, share_id, _share_meta_seq, share_meta) = res;

let mut accounts = vec![];
for account in share_meta.get_accounts() {
let share_account_key = ShareAccountNameIdent {
account: account.clone(),
share_id,
};

let (_seq, meta) = get_share_account_meta_or_err(
kv_api,
&share_account_key,
format!("get_outbound_share_tenants_by_name's account: {share_id}/{account}"),
)
.await?;

accounts.push(GetShareGrantTenants {
account,
grant_on: meta.share_on,
});
}

Ok(accounts)
}

async fn get_outbound_share_info_by_name(
kv_api: &(impl KVApi + ?Sized),
share_name: &ShareNameIdent,
) -> Result<ShareAccountReply, MetaError> {
Expand Down Expand Up @@ -948,7 +976,7 @@ async fn get_outbound_shared_accounts_by_name(
})
}

async fn get_outbound_shared_accounts_by_tenant(
async fn get_outbound_share_infos_by_tenant(
kv_api: &(impl KVApi + ?Sized),
tenant: &str,
) -> Result<Vec<ShareAccountReply>, MetaError> {
Expand All @@ -961,7 +989,7 @@ async fn get_outbound_shared_accounts_by_tenant(
let share_name_keys = list_keys(kv_api, &tenant_share_name_key).await?;

for share_name in share_name_keys {
let reply = get_outbound_shared_accounts_by_name(kv_api, &share_name).await;
let reply = get_outbound_share_info_by_name(kv_api, &share_name).await;
if let Ok(reply) = reply {
outbound_share_accounts.push(reply)
}
Expand All @@ -970,7 +998,7 @@ async fn get_outbound_shared_accounts_by_tenant(
Ok(outbound_share_accounts)
}

async fn get_inbound_shared_accounts_by_tenant(
async fn get_inbound_share_infos_by_tenant(
kv_api: &(impl KVApi + ?Sized),
tenant: &String,
) -> Result<Vec<ShareAccountReply>, MetaError> {
Expand All @@ -986,14 +1014,14 @@ async fn get_inbound_shared_accounts_by_tenant(
let (_share_meta_seq, share_meta) = get_share_meta_by_id_or_err(
kv_api,
share_id,
format!("get_inbound_shared_accounts_by_tenant: {}", share_id),
format!("get_inbound_share_infos_by_tenant: {}", share_id),
)
.await?;

let (_seq, share_name) = get_share_id_to_name_or_err(
kv_api,
share_id,
format!("get_inbound_shared_accounts_by_tenant: {}", share_id),
format!("get_inbound_share_infos_by_tenant: {}", share_id),
)
.await?;
let database_name = get_share_database_name(kv_api, &share_meta, &share_name).await?;
Expand All @@ -1006,7 +1034,7 @@ async fn get_inbound_shared_accounts_by_tenant(
kv_api,
&share_account_key,
format!(
"get_inbound_shared_accounts_by_tenant's account: {}/{}",
"get_inbound_share_infos_by_tenant's account: {}/{}",
share_id, tenant
),
)
Expand Down
2 changes: 1 addition & 1 deletion src/meta/api/src/share_api_test_suite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ impl ShareApiTestSuite {
assert!(resp.is_ok());
let resp = resp.unwrap();
assert_eq!(resp.accounts.len(), 1);
assert_eq!(resp.accounts[0], account.to_string());
assert_eq!(resp.accounts[0].account, account.to_string());
}

info!("--- share tenant2.share2 to tenant1");
Expand Down
1 change: 1 addition & 0 deletions src/meta/app/src/share/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub use share::GetObjectGrantPrivilegesReply;
pub use share::GetObjectGrantPrivilegesReq;
pub use share::GetShareGrantObjectReply;
pub use share::GetShareGrantObjectReq;
pub use share::GetShareGrantTenants;
pub use share::GetShareGrantTenantsReply;
pub use share::GetShareGrantTenantsReq;
pub use share::GrantShareObjectReply;
Expand Down
8 changes: 7 additions & 1 deletion src/meta/app/src/share/share.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,15 @@ pub struct GetShareGrantTenantsReq {
pub share_name: ShareNameIdent,
}

#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct GetShareGrantTenants {
pub account: String,
pub grant_on: DateTime<Utc>,
}

#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
pub struct GetShareGrantTenantsReply {
pub accounts: Vec<String>,
pub accounts: Vec<GetShareGrantTenants>,
}

#[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, Eq)]
Expand Down
26 changes: 26 additions & 0 deletions src/query/ast/src/ast/statements/share.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,29 @@ impl Display for ShowSharesStmt {
Ok(())
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ShowObjectGrantPrivilegesStmt {
pub object: ShareGrantObjectName,
}

impl Display for ShowObjectGrantPrivilegesStmt {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
write!(f, "SHOW GRANTS ON {}", self.object)?;

Ok(())
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ShowGrantsOfShareStmt {
pub share_name: String,
}

impl Display for ShowGrantsOfShareStmt {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
write!(f, "SHOW GRANTS OF SHARE {}", self.share_name)?;

Ok(())
}
}
4 changes: 4 additions & 0 deletions src/query/ast/src/ast/statements/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ pub enum Statement<'a> {
AlterShareTenants(AlterShareTenantsStmt<'a>),
DescShare(DescShareStmt<'a>),
ShowShares(ShowSharesStmt),
ShowObjectGrantPrivileges(ShowObjectGrantPrivilegesStmt),
ShowGrantsOfShare(ShowGrantsOfShareStmt),
}

#[derive(Debug, Clone, PartialEq)]
Expand Down Expand Up @@ -376,6 +378,8 @@ impl<'a> Display for Statement<'a> {
Statement::AlterShareTenants(stmt) => write!(f, "{stmt}")?,
Statement::DescShare(stmt) => write!(f, "{stmt}")?,
Statement::ShowShares(stmt) => write!(f, "{stmt}")?,
Statement::ShowObjectGrantPrivileges(stmt) => write!(f, "{stmt}")?,
Statement::ShowGrantsOfShare(stmt) => write!(f, "{stmt}")?,
}
Ok(())
}
Expand Down
52 changes: 48 additions & 4 deletions src/query/ast/src/parser/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ use crate::rule;
use crate::util::*;
use crate::ErrorKind;

pub enum ShowGrantOption {
PrincipalIdentity(PrincipalIdentity),
ShareGrantObjectName(ShareGrantObjectName),
ShareName(String),
}

pub fn statement(i: Input) -> IResult<StatementMsg> {
let explain = map_res(
rule! {
Expand Down Expand Up @@ -544,10 +550,19 @@ pub fn statement(i: Input) -> IResult<StatementMsg> {
);
let show_grants = map(
rule! {
SHOW ~ GRANTS ~ (FOR ~ #grant_option)?
SHOW ~ GRANTS ~ #show_grant_option?
},
|(_, _, opt_principal)| Statement::ShowGrants {
principal: opt_principal.map(|(_, principal)| principal),
|(_, _, show_grant_option)| match show_grant_option {
Some(ShowGrantOption::PrincipalIdentity(principal)) => Statement::ShowGrants {
principal: Some(principal),
},
Some(ShowGrantOption::ShareGrantObjectName(object)) => {
Statement::ShowObjectGrantPrivileges(ShowObjectGrantPrivilegesStmt { object })
}
Some(ShowGrantOption::ShareName(share_name)) => {
Statement::ShowGrantsOfShare(ShowGrantsOfShareStmt { share_name })
}
None => Statement::ShowGrants { principal: None },
},
);
let revoke = map(
Expand Down Expand Up @@ -906,7 +921,7 @@ pub fn statement(i: Input) -> IResult<StatementMsg> {
),
rule!(
#grant : "`GRANT { ROLE <role_name> | schemaObjectPrivileges | ALL [ PRIVILEGES ] ON <privileges_level> } TO { [ROLE <role_name>] | [USER] <user> }`"
| #show_grants : "`SHOW GRANTS [FOR { ROLE <role_name> | [USER] <user> }]`"
| #show_grants : "`SHOW GRANTS {FOR { ROLE <role_name> | USER <user> }] | ON {DATABASE <db_name> | TABLE <db_name>.<table_name>} }`"
| #revoke : "`REVOKE { ROLE <role_name> | schemaObjectPrivileges | ALL [ PRIVILEGES ] ON <privileges_level> } FROM { [ROLE <role_name>] | [USER] <user> }`"
),
rule!(
Expand Down Expand Up @@ -1146,6 +1161,35 @@ pub fn grant_level(i: Input) -> IResult<AccountMgrLevel> {
)(i)
}

pub fn show_grant_option(i: Input) -> IResult<ShowGrantOption> {
let grant_role = map(
rule! {
FOR ~ #grant_option
},
|(_, opt_principal)| ShowGrantOption::PrincipalIdentity(opt_principal),
);

let share_object_name = map(
rule! {
ON ~ #grant_share_object_name
},
|(_, object_name)| ShowGrantOption::ShareGrantObjectName(object_name),
);

let share_name = map(
rule! {
OF ~ SHARE ~ #ident
},
|(_, _, share_name)| ShowGrantOption::ShareName(share_name.to_string()),
);

rule!(
#grant_role: "FOR { ROLE <role_name> | [USER] <user> }"
| #share_object_name: "ON {DATABASE <db_name> | TABLE <db_name>.<table_name>}"
| #share_name: "OF SHARE <share_name>"
)(i)
}

pub fn grant_option(i: Input) -> IResult<PrincipalIdentity> {
let role = map(
rule! {
Expand Down
4 changes: 4 additions & 0 deletions src/query/ast/src/parser/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,8 @@ pub enum TokenKind {
NULL,
#[token("OBJECT", ignore(ascii_case))]
OBJECT,
#[token("OF", ignore(ascii_case))]
OF,
#[token("OFFSET", ignore(ascii_case))]
OFFSET,
#[token("ON", ignore(ascii_case))]
Expand Down Expand Up @@ -917,6 +919,7 @@ impl TokenKind {
| TokenKind::LIMIT
| TokenKind::OFFSET
| TokenKind::ON
| TokenKind::OF
| TokenKind::ORDER
// | TokenKind::PRECISION
// | TokenKind::RETURNING
Expand Down Expand Up @@ -1027,6 +1030,7 @@ impl TokenKind {
// | TokenKind::NOTNULL
| TokenKind::OFFSET
| TokenKind::ON
| TokenKind::OF
| TokenKind::ORDER
// | TokenKind::OVERLAPS
// | TokenKind::RETURNING
Expand Down
3 changes: 3 additions & 0 deletions src/query/ast/tests/it/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,9 @@ fn test_statement() {
r#"DESC SHARE b;"#,
r#"DESCRIBE SHARE b;"#,
r#"SHOW SHARES;"#,
r#"SHOW GRANTS ON TABLE db1.tb1;"#,
r#"SHOW GRANTS ON DATABASE db;"#,
r#"SHOW GRANTS OF SHARE t;"#,
];

for case in cases {
Expand Down
41 changes: 41 additions & 0 deletions src/query/ast/tests/it/testdata/statement.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6222,3 +6222,44 @@ ShowShares(
)


---------- Input ----------
SHOW GRANTS ON TABLE db1.tb1;
---------- Output ---------
SHOW GRANTS ON TABLE db1.tb1
---------- AST ------------
ShowObjectGrantPrivileges(
ShowObjectGrantPrivilegesStmt {
object: Table(
"db1",
"tb1",
),
},
)


---------- Input ----------
SHOW GRANTS ON DATABASE db;
---------- Output ---------
SHOW GRANTS ON DATABASE db
---------- AST ------------
ShowObjectGrantPrivileges(
ShowObjectGrantPrivilegesStmt {
object: Database(
"db",
),
},
)


---------- Input ----------
SHOW GRANTS OF SHARE t;
---------- Output ---------
SHOW GRANTS OF SHARE t
---------- AST ------------
ShowGrantsOfShare(
ShowGrantsOfShareStmt {
share_name: "t",
},
)


6 changes: 6 additions & 0 deletions src/query/service/src/interpreters/interpreter_factory_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,12 @@ impl InterpreterFactoryV2 {
ctx,
*p.clone(),
)?)),
Plan::ShowObjectGrantPrivileges(p) => Ok(Arc::new(
ShowObjectGrantPrivilegesInterpreter::try_create(ctx, *p.clone())?,
)),
Plan::ShowGrantTenantsOfShare(p) => Ok(Arc::new(
ShowGrantTenantsOfShareInterpreter::try_create(ctx, *p.clone())?,
)),
}
}
}
Loading