Skip to content

Commit

Permalink
Calcite parse ROLE and PRIVILEGE commands
Browse files Browse the repository at this point in the history
* Calcite parse ROLE and PRIVILEGE commands
* Update tests for new Error messages, comments, formatting
* Handle DistributedQuery for Privilege commands that are aggregator_only
  • Loading branch information
danielligman authored and andrewseidl committed Aug 5, 2021
1 parent d2feb86 commit ddae962
Show file tree
Hide file tree
Showing 18 changed files with 976 additions and 89 deletions.
50 changes: 47 additions & 3 deletions Catalog/DdlCommandExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,31 @@ ExecutionResult DdlCommandExecutor::execute() {
auto rename_user_stmt = Parser::RenameUserStmt(extractPayload(*ddl_data_));
rename_user_stmt.execute(*session_ptr_);
return result;
} else if (ddl_command_ == "CREATE_ROLE") {
auto create_role_stmt = Parser::CreateRoleStmt(extractPayload(*ddl_data_));
create_role_stmt.execute(*session_ptr_);
return result;
} else if (ddl_command_ == "DROP_ROLE") {
auto drop_role_stmt = Parser::DropRoleStmt(extractPayload(*ddl_data_));
drop_role_stmt.execute(*session_ptr_);
return result;
} else if (ddl_command_ == "GRANT_ROLE") {
auto grant_role_stmt = Parser::GrantRoleStmt(extractPayload(*ddl_data_));
grant_role_stmt.execute(*session_ptr_);
return result;
} else if (ddl_command_ == "REVOKE_ROLE") {
auto revoke_role_stmt = Parser::RevokeRoleStmt(extractPayload(*ddl_data_));
revoke_role_stmt.execute(*session_ptr_);
return result;
} else if (ddl_command_ == "GRANT_PRIVILEGE") {
auto grant_privilege_stmt = Parser::GrantPrivilegesStmt(extractPayload(*ddl_data_));
grant_privilege_stmt.execute(*session_ptr_);
return result;
} else if (ddl_command_ == "REVOKE_PRIVILEGE") {
auto revoke_privileges_stmt =
Parser::RevokePrivilegesStmt(extractPayload(*ddl_data_));
revoke_privileges_stmt.execute(*session_ptr_);
return result;
}

// the following commands require a global unique lock until proper table locking has
Expand Down Expand Up @@ -447,11 +472,30 @@ DistributedExecutionDetails DdlCommandExecutor::getDistributedExecutionDetails()
ddl_command_ == "CREATE_TABLE" || ddl_command_ == "DROP_TABLE" ||
ddl_command_ == "RENAME_TABLE" || ddl_command_ == "ALTER_TABLE" ||
ddl_command_ == "CREATE_DB" || ddl_command_ == "DROP_DB" ||
ddl_command_ == "RENAME_DB" || ddl_command_ == "CREATE_USER" ||
ddl_command_ == "DROP_USER" || ddl_command_ == "ALTER_USER" ||
ddl_command_ == "RENAME_USER") {
ddl_command_ == "RENAME_DB") {
// commands
execution_details.execution_location = ExecutionLocation::ALL_NODES;
execution_details.aggregation_type = AggregationType::NONE;
} else if (ddl_command_ == "CREATE_USER" || ddl_command_ == "DROP_USER" ||
ddl_command_ == "ALTER_USER" || ddl_command_ == "RENAME_USER" ||
ddl_command_ == "CREATE_ROLE" || ddl_command_ == "DROP_ROLE" ||
ddl_command_ == "GRANT_ROLE" || ddl_command_ == "REVOKE_ROLE") {
// group user/role/db commands
execution_details.execution_location = ExecutionLocation::ALL_NODES;
execution_details.aggregation_type = AggregationType::NONE;
} else if (ddl_command_ == "GRANT_PRIVILEGE" || ddl_command_ == "REVOKE_PRIVILEGE") {
auto& ddl_payload = extractPayload(*ddl_data_);
CHECK(ddl_payload.HasMember("type"));
const std::string& targetType = ddl_payload["type"].GetString();
if (targetType == "DASHBOARD") {
// dashboard commands should run on Aggregator alone
execution_details.execution_location = ExecutionLocation::AGGREGATOR_ONLY;
execution_details.aggregation_type = AggregationType::NONE;
} else {
execution_details.execution_location = ExecutionLocation::ALL_NODES;
execution_details.aggregation_type = AggregationType::NONE;
}

} else if (ddl_command_ == "SHOW_TABLE_DETAILS") {
execution_details.execution_location = ExecutionLocation::LEAVES_ONLY;
execution_details.aggregation_type = AggregationType::UNION;
Expand Down
116 changes: 115 additions & 1 deletion Parser/ParserNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4861,6 +4861,11 @@ void CopyTableStmt::execute(const Catalog_Namespace::SessionInfo& session,
} // namespace Parser

// CREATE ROLE payroll_dept_role;
CreateRoleStmt::CreateRoleStmt(const rapidjson::Value& payload) {
CHECK(payload.HasMember("role"));
role_ = std::make_unique<std::string>(json_str(payload["role"]));
}

void CreateRoleStmt::execute(const Catalog_Namespace::SessionInfo& session) {
const auto& currentUser = session.get_currentUser();
if (!currentUser.isSuper) {
Expand All @@ -4872,6 +4877,11 @@ void CreateRoleStmt::execute(const Catalog_Namespace::SessionInfo& session) {
}

// DROP ROLE payroll_dept_role;
DropRoleStmt::DropRoleStmt(const rapidjson::Value& payload) {
CHECK(payload.HasMember("role"));
role_ = std::make_unique<std::string>(json_str(payload["role"]));
}

void DropRoleStmt::execute(const Catalog_Namespace::SessionInfo& session) {
const auto& currentUser = session.get_currentUser();
if (!currentUser.isSuper) {
Expand Down Expand Up @@ -5071,6 +5081,32 @@ static void verifyObject(Catalog_Namespace::Catalog& sessionCatalog,
}

// GRANT SELECT/INSERT/CREATE ON TABLE payroll_table TO payroll_dept_role;
GrantPrivilegesStmt::GrantPrivilegesStmt(const rapidjson::Value& payload) {
CHECK(payload.HasMember("type"));
type_ = std::make_unique<std::string>(json_str(payload["type"]));

CHECK(payload.HasMember("target"));
target_ = std::make_unique<std::string>(json_str(payload["target"]));

if (payload.HasMember("privileges")) {
CHECK(payload["privileges"].IsArray());
for (auto& privilege : payload["privileges"].GetArray()) {
auto r = json_str(privilege);
// privilege was a StringLiteral
// and is wrapped with quotes which need to get removed
boost::algorithm::trim_if(r, boost::is_any_of(" \"'`"));
privileges_.emplace_back(r);
}
}
if (payload.HasMember("grantees")) {
CHECK(payload["grantees"].IsArray());
for (auto& grantee : payload["grantees"].GetArray()) {
std::string g = json_str(grantee);
grantees_.emplace_back(g);
}
}
}

void GrantPrivilegesStmt::execute(const Catalog_Namespace::SessionInfo& session) {
auto& catalog = session.getCatalog();
const auto& currentUser = session.get_currentUser();
Expand Down Expand Up @@ -5108,6 +5144,32 @@ void GrantPrivilegesStmt::execute(const Catalog_Namespace::SessionInfo& session)
}

// REVOKE SELECT/INSERT/CREATE ON TABLE payroll_table FROM payroll_dept_role;
RevokePrivilegesStmt::RevokePrivilegesStmt(const rapidjson::Value& payload) {
CHECK(payload.HasMember("type"));
type_ = std::make_unique<std::string>(json_str(payload["type"]));

CHECK(payload.HasMember("target"));
target_ = std::make_unique<std::string>(json_str(payload["target"]));

if (payload.HasMember("privileges")) {
CHECK(payload["privileges"].IsArray());
for (auto& privilege : payload["privileges"].GetArray()) {
auto r = json_str(privilege);
// privilege was a StringLiteral
// and is wrapped with quotes which need to get removed
boost::algorithm::trim_if(r, boost::is_any_of(" \"'`"));
privileges_.emplace_back(r);
}
}
if (payload.HasMember("grantees")) {
CHECK(payload["grantees"].IsArray());
for (auto& grantee : payload["grantees"].GetArray()) {
std::string g = json_str(grantee);
grantees_.emplace_back(g);
}
}
}

void RevokePrivilegesStmt::execute(const Catalog_Namespace::SessionInfo& session) {
auto& catalog = session.getCatalog();
const auto& currentUser = session.get_currentUser();
Expand Down Expand Up @@ -5241,6 +5303,23 @@ void ShowPrivilegesStmt::execute(const Catalog_Namespace::SessionInfo& session)
}

// GRANT payroll_dept_role TO joe;
GrantRoleStmt::GrantRoleStmt(const rapidjson::Value& payload) {
if (payload.HasMember("roles")) {
CHECK(payload["roles"].IsArray());
for (auto& role : payload["roles"].GetArray()) {
std::string r = json_str(role);
roles_.emplace_back(r);
}
}
if (payload.HasMember("grantees")) {
CHECK(payload["grantees"].IsArray());
for (auto& grantee : payload["grantees"].GetArray()) {
std::string g = json_str(grantee);
grantees_.emplace_back(g);
}
}
}

void GrantRoleStmt::execute(const Catalog_Namespace::SessionInfo& session) {
const auto& currentUser = session.get_currentUser();
if (!currentUser.isSuper) {
Expand All @@ -5256,7 +5335,24 @@ void GrantRoleStmt::execute(const Catalog_Namespace::SessionInfo& session) {
SysCatalog::instance().grantRoleBatch(get_roles(), get_grantees());
}

// REVOKE payroll_dept_role FROM joe;get_users
// REVOKE payroll_dept_role FROM joe;
RevokeRoleStmt::RevokeRoleStmt(const rapidjson::Value& payload) {
if (payload.HasMember("roles")) {
CHECK(payload["roles"].IsArray());
for (auto& role : payload["roles"].GetArray()) {
std::string r = json_str(role);
roles_.emplace_back(r);
}
}
if (payload.HasMember("grantees")) {
CHECK(payload["grantees"].IsArray());
for (auto& grantee : payload["grantees"].GetArray()) {
std::string g = json_str(grantee);
grantees_.emplace_back(g);
}
}
}

void RevokeRoleStmt::execute(const Catalog_Namespace::SessionInfo& session) {
const auto& currentUser = session.get_currentUser();
if (!currentUser.isSuper) {
Expand Down Expand Up @@ -6028,6 +6124,24 @@ void execute_calcite_ddl(
} else if (ddl_command == "RENAME_USER") {
auto rename_user_stmt = Parser::RenameUserStmt(payload);
rename_user_stmt.execute(*session_ptr);
} else if (ddl_command == "CREATE_ROLE") {
auto create_role_stmt = Parser::CreateRoleStmt(payload);
create_role_stmt.execute(*session_ptr);
} else if (ddl_command == "DROP_ROLE") {
auto drop_role_stmt = Parser::DropRoleStmt(payload);
drop_role_stmt.execute(*session_ptr);
} else if (ddl_command == "GRANT_ROLE") {
auto grant_role_stmt = Parser::GrantRoleStmt(payload);
grant_role_stmt.execute(*session_ptr);
} else if (ddl_command == "REVOKE_ROLE") {
auto revoke_role_stmt = Parser::RevokeRoleStmt(payload);
revoke_role_stmt.execute(*session_ptr);
} else if (ddl_command == "GRANT_PRIVILEGE") {
auto grant_privilege_stmt = Parser::GrantPrivilegesStmt(payload);
grant_privilege_stmt.execute(*session_ptr);
} else if (ddl_command == "REVOKE_PRIVILEGE") {
auto revoke_privilege_stmt = Parser::RevokePrivilegesStmt(payload);
revoke_privilege_stmt.execute(*session_ptr);
} else {
throw std::runtime_error("Unsupported DDL command");
}
Expand Down
40 changes: 24 additions & 16 deletions Parser/ParserNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -1542,6 +1542,7 @@ class CopyTableStmt : public DDLStmt {
class CreateRoleStmt : public DDLStmt {
public:
CreateRoleStmt(std::string* r) : role_(r) {}
CreateRoleStmt(const rapidjson::Value& payload);
const std::string& get_role() const { return *role_; }
void execute(const Catalog_Namespace::SessionInfo& session) override;

Expand All @@ -1556,6 +1557,7 @@ class CreateRoleStmt : public DDLStmt {
class DropRoleStmt : public DDLStmt {
public:
DropRoleStmt(std::string* r) : role_(r) {}
DropRoleStmt(const rapidjson::Value& payload);
const std::string& get_role() const { return *role_; }
void execute(const Catalog_Namespace::SessionInfo& session) override;

Expand Down Expand Up @@ -1583,21 +1585,22 @@ class GrantPrivilegesStmt : public DDLStmt {
std::string* t,
std::string* o,
std::list<std::string*>* g)
: object_type_(t), object_(o) {
parser_slistval_to_vector(p, privs_);
: type_(t), target_(o) {
parser_slistval_to_vector(p, privileges_);
parser_slistval_to_vector(g, grantees_);
}
GrantPrivilegesStmt(const rapidjson::Value& payload);

const std::vector<std::string>& get_privs() const { return privs_; }
const std::string& get_object_type() const { return *object_type_; }
const std::string& get_object() const { return *object_; }
const std::vector<std::string>& get_privs() const { return privileges_; }
const std::string& get_object_type() const { return *type_; }
const std::string& get_object() const { return *target_; }
const std::vector<std::string>& get_grantees() const { return grantees_; }
void execute(const Catalog_Namespace::SessionInfo& session) override;

private:
std::vector<std::string> privs_;
std::unique_ptr<std::string> object_type_;
std::unique_ptr<std::string> object_;
std::vector<std::string> privileges_;
std::unique_ptr<std::string> type_;
std::unique_ptr<std::string> target_;
std::vector<std::string> grantees_;
};

Expand All @@ -1611,21 +1614,22 @@ class RevokePrivilegesStmt : public DDLStmt {
std::string* t,
std::string* o,
std::list<std::string*>* g)
: object_type_(t), object_(o) {
parser_slistval_to_vector(p, privs_);
: type_(t), target_(o) {
parser_slistval_to_vector(p, privileges_);
parser_slistval_to_vector(g, grantees_);
}
RevokePrivilegesStmt(const rapidjson::Value& payload);

const std::vector<std::string>& get_privs() const { return privs_; }
const std::string& get_object_type() const { return *object_type_; }
const std::string& get_object() const { return *object_; }
const std::vector<std::string>& get_privs() const { return privileges_; }
const std::string& get_object_type() const { return *type_; }
const std::string& get_object() const { return *target_; }
const std::vector<std::string>& get_grantees() const { return grantees_; }
void execute(const Catalog_Namespace::SessionInfo& session) override;

private:
std::vector<std::string> privs_;
std::unique_ptr<std::string> object_type_;
std::unique_ptr<std::string> object_;
std::vector<std::string> privileges_;
std::unique_ptr<std::string> type_;
std::unique_ptr<std::string> target_;
std::vector<std::string> grantees_;
};

Expand Down Expand Up @@ -1658,6 +1662,8 @@ class GrantRoleStmt : public DDLStmt {
parser_slistval_to_vector(r, roles_);
parser_slistval_to_vector(g, grantees_);
}
GrantRoleStmt(const rapidjson::Value& payload);

const std::vector<std::string>& get_roles() const { return roles_; }
const std::vector<std::string>& get_grantees() const { return grantees_; }
void execute(const Catalog_Namespace::SessionInfo& session) override;
Expand All @@ -1677,6 +1683,8 @@ class RevokeRoleStmt : public DDLStmt {
parser_slistval_to_vector(r, roles_);
parser_slistval_to_vector(g, grantees_);
}
RevokeRoleStmt(const rapidjson::Value& payload);

const std::vector<std::string>& get_roles() const { return roles_; }
const std::vector<std::string>& get_grantees() const { return grantees_; }
void execute(const Catalog_Namespace::SessionInfo& session) override;
Expand Down
25 changes: 22 additions & 3 deletions Parser/ParserWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ ParserWrapper::ParserWrapper(std::string query_string) {
is_legacy_ddl_ = true;
}
} else {
boost::regex create_regex{R"(CREATE\s+(TABLE|VIEW|DATABASE|USER).*)",
boost::regex create_regex{R"(CREATE\s+(TABLE|ROLE|VIEW|DATABASE|USER).*)",
boost::regex::extended | boost::regex::icase};
if (g_enable_calcite_ddl_parser &&
boost::regex_match(query_string, create_regex)) {
Expand Down Expand Up @@ -188,9 +188,10 @@ ParserWrapper::ParserWrapper(std::string query_string) {
return;
}
} else if (ddl == "DROP") {
boost::regex drop_regex{R"(DROP\s+(TABLE|VIEW|DATABASE|USER).*)",
boost::regex drop_regex{R"(DROP\s+(TABLE|ROLE|VIEW|DATABASE|USER).*)",
boost::regex::extended | boost::regex::icase};
if (g_enable_calcite_ddl_parser && boost::regex_match(query_string, drop_regex)) {
if (g_enable_calcite_ddl_parser &&
(boost::regex_match(query_string, drop_regex))) {
is_calcite_ddl_ = true;
is_legacy_ddl_ = false;
return;
Expand Down Expand Up @@ -220,6 +221,24 @@ ParserWrapper::ParserWrapper(std::string query_string) {
is_legacy_ddl_ = false;
return;
}
} else if (ddl == "GRANT") {
boost::regex grant_regex{R"(GRANT.*)",
boost::regex::extended | boost::regex::icase};
if (g_enable_calcite_ddl_parser &&
boost::regex_match(query_string, grant_regex)) {
is_calcite_ddl_ = true;
is_legacy_ddl_ = false;
return;
}
} else if (ddl == "REVOKE") {
boost::regex revoke_regex{R"(REVOKE.*)",
boost::regex::extended | boost::regex::icase};
if (g_enable_calcite_ddl_parser &&
boost::regex_match(query_string, revoke_regex)) {
is_calcite_ddl_ = true;
is_legacy_ddl_ = false;
return;
}
}
// ctas may look like ddl, but is neither legacy_dll nor calcite_ddl
if (!is_ctas) {
Expand Down
2 changes: 1 addition & 1 deletion Parser/Parser_wnd_pregen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1405,7 +1405,7 @@ static const char* const yytname[] = {"$",
"restore_table_statement",
"create_role_statement",
"drop_role_statement",
"grant_privileges_statement",
"grant_privilege_statement",
"revoke_privileges_statement",
"grant_role_statement",
"revoke_role_statement",
Expand Down
Loading

0 comments on commit ddae962

Please sign in to comment.