1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

MDEV-21689 Add Sql_cmd for GRANT/REVOKE statements

Rewriting GRANT/REVOKE grammar to use more bison stack and use Sql_cmd_ style

1. Removing a few members from LEX:
   - uint grant, grant_to_col, which_columns
   - List<LEX_COLUMN> columns
   - bool all_privileges
2. Adding classes Grand_object_name, Lex_grant_object_name
3. Adding classes Grand_privilege, Lex_grand_privilege
4. Adding struct Lex_column_list_privilege_st, class Lex_column_list_privilege
5. Rewriting the GRANT/REVOKE grammar to use new classes and pass them through
   bison stack (rather than directly access LEX members)
6. Adding classes Sql_cmd_grant* and Sql_cmd_revoke*,
   changing GRANT/REVOKE to use LEX::m_sql_cmd.
7. Adding the "sp_handler" grammar rule and removing some duplicate grammar
   for GRANT/REVOKE for different kinds of SP objects.
8. Adding a new rule comma_separated_ident_list, reusing it in:
   - with_column_list
   - colum_list_privilege
This commit is contained in:
Alexander Barkov
2020-02-05 12:43:17 +04:00
parent 06b0623adb
commit 77c6382312
13 changed files with 814 additions and 318 deletions

View File

@ -5261,113 +5261,6 @@ mysql_execute_command(THD *thd)
my_ok(thd);
break;
}
case SQLCOM_REVOKE:
case SQLCOM_GRANT:
{
if (lex->type != TYPE_ENUM_PROXY &&
check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL,
first_table ? first_table->db.str : select_lex->db.str,
first_table ? &first_table->grant.privilege : NULL,
first_table ? &first_table->grant.m_internal : NULL,
first_table ? 0 : 1, 0))
goto error;
/* Replicate current user as grantor */
thd->binlog_invoker(false);
if (thd->security_ctx->user) // If not replication
{
LEX_USER *user;
bool first_user= TRUE;
List_iterator <LEX_USER> user_list(lex->users_list);
while ((user= user_list++))
{
if (specialflag & SPECIAL_NO_RESOLVE &&
hostname_requires_resolving(user->host.str))
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_WARN_HOSTNAME_WONT_WORK,
ER_THD(thd, ER_WARN_HOSTNAME_WONT_WORK));
/*
GRANT/REVOKE PROXY has the target user as a first entry in the list.
*/
if (lex->type == TYPE_ENUM_PROXY && first_user)
{
if (!(user= get_current_user(thd, user)) || !user->host.str)
goto error;
first_user= FALSE;
if (acl_check_proxy_grant_access (thd, user->host.str, user->user.str,
lex->grant & GRANT_ACL))
goto error;
}
}
}
if (first_table)
{
const Sp_handler *sph= Sp_handler::handler((stored_procedure_type)
lex->type);
if (sph)
{
uint grants= lex->all_privileges
? (PROC_ACLS & ~GRANT_ACL) | (lex->grant & GRANT_ACL)
: lex->grant;
if (check_grant_routine(thd, grants | GRANT_ACL, all_tables, sph, 0))
goto error;
/* Conditionally writes to binlog */
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
res= mysql_routine_grant(thd, all_tables, sph,
lex->users_list, grants,
lex->sql_command == SQLCOM_REVOKE, TRUE);
if (!res)
my_ok(thd);
}
else
{
if (check_grant(thd,(lex->grant | lex->grant_tot_col | GRANT_ACL),
all_tables, FALSE, UINT_MAX, FALSE))
goto error;
/* Conditionally writes to binlog */
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
res= mysql_table_grant(thd, all_tables, lex->users_list,
lex->columns, lex->grant,
lex->sql_command == SQLCOM_REVOKE);
}
}
else
{
if (lex->columns.elements || (lex->type && lex->type != TYPE_ENUM_PROXY))
{
my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER_THD(thd, ER_ILLEGAL_GRANT_FOR_TABLE),
MYF(0));
goto error;
}
else
{
WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/* Conditionally writes to binlog */
res= mysql_grant(thd, select_lex->db.str, lex->users_list, lex->grant,
lex->sql_command == SQLCOM_REVOKE,
lex->type == TYPE_ENUM_PROXY);
}
if (!res)
{
if (lex->sql_command == SQLCOM_GRANT)
{
List_iterator <LEX_USER> str_list(lex->users_list);
LEX_USER *user, *tmp_user;
while ((tmp_user=str_list++))
{
if (!(user= get_current_user(thd, tmp_user)))
goto error;
reset_mqh(user, 0);
}
}
}
}
break;
}
case SQLCOM_REVOKE_ROLE:
case SQLCOM_GRANT_ROLE:
{
@ -5955,6 +5848,8 @@ mysql_execute_command(THD *thd)
case SQLCOM_RESIGNAL:
case SQLCOM_GET_DIAGNOSTICS:
case SQLCOM_CALL:
case SQLCOM_REVOKE:
case SQLCOM_GRANT:
DBUG_ASSERT(lex->m_sql_cmd != NULL);
res= lex->m_sql_cmd->execute(thd);
DBUG_PRINT("result", ("res: %d killed: %d is_error: %d",