Commit d72eebaa authored by Marko Mäkelä's avatar Marko Mäkelä

Merge 10.1 into 10.2

parents 4832b751 49854811
...@@ -14,7 +14,7 @@ set default role role_a for user_a@localhost; ...@@ -14,7 +14,7 @@ set default role role_a for user_a@localhost;
set default role invalid_role for user_a@localhost; set default role invalid_role for user_a@localhost;
ERROR OP000: Invalid role specification `invalid_role` ERROR OP000: Invalid role specification `invalid_role`
set default role role_b for user_a@localhost; set default role role_b for user_a@localhost;
ERROR OP000: Invalid role specification `role_b` ERROR OP000: User `user_a@localhost` has not been granted role `role_b`
set default role role_b for user_b@localhost; set default role role_b for user_b@localhost;
show grants; show grants;
Grants for user_a@localhost Grants for user_a@localhost
...@@ -36,7 +36,7 @@ user host default_role ...@@ -36,7 +36,7 @@ user host default_role
user_a localhost role_a user_a localhost role_a
user_b localhost role_b user_b localhost role_b
set default role role_b for current_user; set default role role_b for current_user;
ERROR OP000: Invalid role specification `role_b` ERROR OP000: User `user_a@localhost` has not been granted role `role_b`
show grants; show grants;
Grants for user_b@localhost Grants for user_b@localhost
GRANT role_b TO 'user_b'@'localhost' GRANT role_b TO 'user_b'@'localhost'
......
...@@ -38,3 +38,90 @@ ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'us ...@@ -38,3 +38,90 @@ ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'us
drop role test_role; drop role test_role;
drop role not_granted_role; drop role not_granted_role;
drop user test_user@localhost; drop user test_user@localhost;
#
# MDEV-22312: Bad error message for SET DEFAULT ROLE when user account
# is not granted the role
#
CREATE USER a;
CREATE USER b;
CREATE ROLE r1;
CREATE ROLE r2;
SET DEFAULT ROLE r1 FOR a;
ERROR OP000: User `a@%` has not been granted role `r1`
GRANT r1 TO b;
GRANT r2 TO b;
SET DEFAULT ROLE r1 FOR b;
# Change user b
SELECT CURRENT_ROLE;
CURRENT_ROLE
r1
SET ROLE r2;
SELECT CURRENT_ROLE;
CURRENT_ROLE
r2
SET DEFAULT ROLE r1 FOR a;
ERROR 42000: Access denied for user 'b'@'%' to database 'mysql'
SET DEFAULT ROLE r2;
# Change user root (session 1: select_priv to b)
GRANT SELECT ON mysql.* TO b;
# Change user b (session 1: select_priv)
SHOW GRANTS FOR b;
Grants for b@%
GRANT r1 TO 'b'@'%'
GRANT r2 TO 'b'@'%'
GRANT USAGE ON *.* TO 'b'@'%'
GRANT SELECT ON `mysql`.* TO 'b'@'%'
SET DEFAULT ROLE r1 FOR a;
ERROR 42000: Access denied for user 'b'@'%' to database 'mysql'
SELECT CURRENT_ROLE;
CURRENT_ROLE
r2
SET DEFAULT ROLE NONE;
SELECT CURRENT_ROLE;
CURRENT_ROLE
r2
SET DEFAULT ROLE current_role FOR current_user;
SET DEFAULT ROLE invalid_role;
ERROR OP000: Invalid role specification `invalid_role`
SET DEFAULT ROLE invalid_role FOR a;
ERROR 42000: Access denied for user 'b'@'%' to database 'mysql'
SET DEFAULT ROLE none FOR a;
ERROR 42000: Access denied for user 'b'@'%' to database 'mysql'
# Change user root (session 2: adding update_priv to user b)
GRANT UPDATE ON mysql.* TO b;
# Change user b
SHOW GRANTS FOR b;
Grants for b@%
GRANT r1 TO 'b'@'%'
GRANT r2 TO 'b'@'%'
GRANT USAGE ON *.* TO 'b'@'%'
GRANT SELECT, UPDATE ON `mysql`.* TO 'b'@'%'
SET DEFAULT ROLE r1 FOR a;
ERROR OP000: User `a@%` has not been granted role `r1`
SET DEFAULT ROLE invalid_role;
ERROR OP000: Invalid role specification `invalid_role`
SET DEFAULT ROLE invalid_role FOR a;
ERROR OP000: Invalid role specification `invalid_role`
SET DEFAULT ROLE none FOR a;
# Change user root (session 3: Grant role to user a)
GRANT r1 TO a;
SET DEFAULT ROLE r1 FOR a;
# Change user a (verify session 3)
SELECT CURRENT_ROLE;
CURRENT_ROLE
r1
SET DEFAULT ROLE None;
# Change user b (session 3: role granted to user a)
SET DEFAULT ROLE r1 FOR a;
SET DEFAULT ROLE r2 FOR a;
ERROR OP000: User `a@%` has not been granted role `r2`
SET DEFAULT ROLE invalid_role;
ERROR OP000: Invalid role specification `invalid_role`
SET DEFAULT ROLE invalid_role FOR a;
ERROR OP000: Invalid role specification `invalid_role`
SELECT user, host, default_role FROM mysql.user where user='a' or user='b';
user host default_role
a % r1
b % r2
DROP ROLE r1, r2;
DROP USER a, b;
...@@ -60,3 +60,110 @@ change_user 'root'; ...@@ -60,3 +60,110 @@ change_user 'root';
drop role test_role; drop role test_role;
drop role not_granted_role; drop role not_granted_role;
drop user test_user@localhost; drop user test_user@localhost;
--echo #
--echo # MDEV-22312: Bad error message for SET DEFAULT ROLE when user account
--echo # is not granted the role
--echo #
CREATE USER a;
CREATE USER b;
CREATE ROLE r1;
CREATE ROLE r2;
# Role has not been granted to user a, but the role is visible to current_user
--error ER_INVALID_ROLE
SET DEFAULT ROLE r1 FOR a;
# Granting roles to user b
GRANT r1 TO b;
GRANT r2 TO b;
# After granting the role, role can be set as default
SET DEFAULT ROLE r1 FOR b;
--echo # Change user b
change_user b;
SELECT CURRENT_ROLE;
SET ROLE r2;
SELECT CURRENT_ROLE;
# User b has no UPDATE_PRIV for mysql.user
--error ER_DBACCESS_DENIED_ERROR
SET DEFAULT ROLE r1 FOR a;
SET DEFAULT ROLE r2;
--echo # Change user root (session 1: select_priv to b)
change_user root;
# Let's grant select_priv to user b
GRANT SELECT ON mysql.* TO b;
--echo # Change user b (session 1: select_priv)
change_user b;
SHOW GRANTS FOR b;
# User must have update_priv before setting the role
--error ER_DBACCESS_DENIED_ERROR
SET DEFAULT ROLE r1 FOR a;
# Testing the `CURRENT_ROLE` as a special case
SELECT CURRENT_ROLE;
SET DEFAULT ROLE NONE;
SELECT CURRENT_ROLE;
SET DEFAULT ROLE current_role FOR current_user;
# Testing of non-existing role
--error ER_INVALID_ROLE
SET DEFAULT ROLE invalid_role;
# Testing of non-existing role for different user
--error ER_DBACCESS_DENIED_ERROR
SET DEFAULT ROLE invalid_role FOR a;
# Testing the `None` role for different user
-- error ER_DBACCESS_DENIED_ERROR
SET DEFAULT ROLE none FOR a;
--echo # Change user root (session 2: adding update_priv to user b)
change_user root;
# update_priv are enough
GRANT UPDATE ON mysql.* TO b;
--echo # Change user b
change_user b;
SHOW GRANTS FOR b;
# In all tests in session user a has not been granted the role
# Testing setting role for different user, should fail with new error
--error ER_INVALID_ROLE
SET DEFAULT ROLE r1 FOR a;
# Testing of non-existing role
--error ER_INVALID_ROLE
SET DEFAULT ROLE invalid_role;
# Testing of non-existing role for different user with update_priv
--error ER_INVALID_ROLE
SET DEFAULT ROLE invalid_role FOR a;
# Testing the `None` role for different user with update_priv
SET DEFAULT ROLE none FOR a;
--echo # Change user root (session 3: Grant role to user a)
change_user root;
# After granting the privilege for a, user b can set default role
GRANT r1 TO a;
SET DEFAULT ROLE r1 FOR a;
--echo # Change user a (verify session 3)
change_user a;
SELECT CURRENT_ROLE;
SET DEFAULT ROLE None;
--echo # Change user b (session 3: role granted to user a)
change_user b;
# This should set role because b has update_priv
SET DEFAULT ROLE r1 FOR a;
# Testing non-granted role r2 still should fail
-- error ER_INVALID_ROLE
SET DEFAULT ROLE r2 FOR a;
# Testing of non-existing role
--error ER_INVALID_ROLE
SET DEFAULT ROLE invalid_role;
# Testing of non-existing role for different user
--error ER_INVALID_ROLE
SET DEFAULT ROLE invalid_role FOR a;
# Clear the workspace
change_user root;
--sorted_result
SELECT user, host, default_role FROM mysql.user where user='a' or user='b';
DROP ROLE r1, r2;
DROP USER a, b;
...@@ -66,7 +66,7 @@ Grants for test_user@localhost ...@@ -66,7 +66,7 @@ Grants for test_user@localhost
GRANT USAGE ON *.* TO 'test_user'@'localhost' GRANT USAGE ON *.* TO 'test_user'@'localhost'
GRANT test_role1 TO 'test_user'@'localhost' GRANT test_role1 TO 'test_user'@'localhost'
set role test_role2; set role test_role2;
ERROR OP000: Invalid role specification `test_role2` ERROR OP000: User `test_user@localhost` has not been granted role `test_role2`
select current_user(), current_role(); select current_user(), current_role();
current_user() current_role() current_user() current_role()
test_user@localhost NULL test_user@localhost NULL
......
...@@ -815,7 +815,6 @@ String *Item_nodeset_func_attributebyname::val_nodeset(String *nodeset) ...@@ -815,7 +815,6 @@ String *Item_nodeset_func_attributebyname::val_nodeset(String *nodeset)
String *Item_nodeset_func_predicate::val_nodeset(String *str) String *Item_nodeset_func_predicate::val_nodeset(String *str)
{ {
Item_nodeset_func *nodeset_func= (Item_nodeset_func*) args[0]; Item_nodeset_func *nodeset_func= (Item_nodeset_func*) args[0];
Item_func *comp_func= (Item_func*)args[1];
uint pos= 0, size; uint pos= 0, size;
prepare(str); prepare(str);
size= (uint)(fltend - fltbeg); size= (uint)(fltend - fltbeg);
...@@ -825,7 +824,7 @@ String *Item_nodeset_func_predicate::val_nodeset(String *str) ...@@ -825,7 +824,7 @@ String *Item_nodeset_func_predicate::val_nodeset(String *str)
((XPathFilter*)(&nodeset_func->context_cache))->append_element(flt->num, ((XPathFilter*)(&nodeset_func->context_cache))->append_element(flt->num,
flt->pos, flt->pos,
size); size);
if (comp_func->val_int()) if (args[1]->val_int())
((XPathFilter*)str)->append_element(flt->num, pos++); ((XPathFilter*)str)->append_element(flt->num, pos++);
} }
return str; return str;
......
...@@ -971,8 +971,17 @@ int set_var_default_role::check(THD *thd) ...@@ -971,8 +971,17 @@ int set_var_default_role::check(THD *thd)
{ {
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
real_user= get_current_user(thd, user); real_user= get_current_user(thd, user);
int status= acl_check_set_default_role(thd, real_user->host.str, real_user->user.str); real_role= role.str;
return status; if (role.str == current_role.str)
{
if (!thd->security_ctx->priv_role[0])
real_role= "NONE";
else
real_role= thd->security_ctx->priv_role;
}
return acl_check_set_default_role(thd, real_user->host.str,
real_user->user.str, real_role);
#else #else
return 0; return 0;
#endif #endif
...@@ -983,7 +992,8 @@ int set_var_default_role::update(THD *thd) ...@@ -983,7 +992,8 @@ int set_var_default_role::update(THD *thd)
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer; Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer;
thd->m_reprepare_observer= 0; thd->m_reprepare_observer= 0;
int res= acl_set_default_role(thd, real_user->host.str, real_user->user.str, role.str); int res= acl_set_default_role(thd, real_user->host.str, real_user->user.str,
real_role);
thd->m_reprepare_observer= save_reprepare_observer; thd->m_reprepare_observer= save_reprepare_observer;
return res; return res;
#else #else
......
...@@ -350,6 +350,7 @@ class set_var_default_role: public set_var_base ...@@ -350,6 +350,7 @@ class set_var_default_role: public set_var_base
{ {
LEX_USER *user, *real_user; LEX_USER *user, *real_user;
LEX_STRING role; LEX_STRING role;
const char *real_role;
public: public:
set_var_default_role(LEX_USER *user_arg, LEX_STRING role_arg) : set_var_default_role(LEX_USER *user_arg, LEX_STRING role_arg) :
user(user_arg), role(role_arg) {} user(user_arg), role(role_arg) {}
......
/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. /* Copyright (c) 2000, 2018, Oracle and/or its affiliates.
Copyright (c) 2009, 2018, MariaDB Copyright (c) 2009, 2020, MariaDB
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
...@@ -201,7 +201,6 @@ LEX_STRING current_user= { C_STRING_WITH_LEN("*current_user") }; ...@@ -201,7 +201,6 @@ LEX_STRING current_user= { C_STRING_WITH_LEN("*current_user") };
LEX_STRING current_role= { C_STRING_WITH_LEN("*current_role") }; LEX_STRING current_role= { C_STRING_WITH_LEN("*current_role") };
LEX_STRING current_user_and_current_role= { C_STRING_WITH_LEN("*current_user_and_current_role") }; LEX_STRING current_user_and_current_role= { C_STRING_WITH_LEN("*current_user_and_current_role") };
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
static plugin_ref old_password_plugin; static plugin_ref old_password_plugin;
#endif #endif
...@@ -2618,8 +2617,43 @@ bool acl_getroot(Security_context *sctx, char *user, char *host, ...@@ -2618,8 +2617,43 @@ bool acl_getroot(Security_context *sctx, char *user, char *host,
DBUG_RETURN(res); DBUG_RETURN(res);
} }
static int check_user_can_set_role(const char *user, const char *host, static int check_role_is_granted_callback(ACL_USER_BASE *grantee, void *data)
const char *ip, const char *rolename, ulonglong *access) {
LEX_CSTRING *rolename= static_cast<LEX_CSTRING *>(data);
if (rolename->length == grantee->user.length &&
!strcmp(rolename->str, grantee->user.str))
return -1; // End search, we've found our role.
/* Keep looking, we haven't found our role yet. */
return 0;
}
/*
unlike find_user_exact and find_user_wild,
this function finds anonymous users too, it's when a
user is not empty, but priv_user (acl_user->user) is empty.
*/
static ACL_USER *find_user_or_anon(const char *host, const char *user, const char *ip)
{
ACL_USER *result= NULL;
mysql_mutex_assert_owner(&acl_cache->lock);
for (uint i=0; i < acl_users.elements; i++)
{
ACL_USER *acl_user_tmp= dynamic_element(&acl_users, i, ACL_USER*);
if ((!acl_user_tmp->user.str ||
!strcmp(user, acl_user_tmp->user.str)) &&
compare_hostname(&acl_user_tmp->host, host, ip))
{
result= acl_user_tmp;
break;
}
}
return result;
}
static int check_user_can_set_role(THD *thd, const char *user, const char *host,
const char *ip, const char *rolename,
ulonglong *access)
{ {
ACL_ROLE *role; ACL_ROLE *role;
ACL_USER_BASE *acl_user_base; ACL_USER_BASE *acl_user_base;
...@@ -2636,10 +2670,7 @@ static int check_user_can_set_role(const char *user, const char *host, ...@@ -2636,10 +2670,7 @@ static int check_user_can_set_role(const char *user, const char *host,
/* get the current user */ /* get the current user */
acl_user= find_user_wild(host, user, ip); acl_user= find_user_wild(host, user, ip);
if (acl_user == NULL) if (acl_user == NULL)
{ result= ER_INVALID_CURRENT_USER;
my_error(ER_INVALID_CURRENT_USER, MYF(0));
result= -1;
}
else if (access) else if (access)
*access= acl_user->access; *access= acl_user->access;
...@@ -2649,9 +2680,9 @@ static int check_user_can_set_role(const char *user, const char *host, ...@@ -2649,9 +2680,9 @@ static int check_user_can_set_role(const char *user, const char *host,
role= find_acl_role(rolename); role= find_acl_role(rolename);
/* According to SQL standard, the same error message must be presented */ /* According to SQL standard, the same error message must be presented */
if (role == NULL) { if (role == NULL)
my_error(ER_INVALID_ROLE, MYF(0), rolename); {
result= -1; result= ER_INVALID_ROLE;
goto end; goto end;
} }
...@@ -2672,7 +2703,6 @@ static int check_user_can_set_role(const char *user, const char *host, ...@@ -2672,7 +2703,6 @@ static int check_user_can_set_role(const char *user, const char *host,
/* According to SQL standard, the same error message must be presented */ /* According to SQL standard, the same error message must be presented */
if (!is_granted) if (!is_granted)
{ {
my_error(ER_INVALID_ROLE, MYF(0), rolename);
result= 1; result= 1;
goto end; goto end;
} }
...@@ -2681,17 +2711,66 @@ static int check_user_can_set_role(const char *user, const char *host, ...@@ -2681,17 +2711,66 @@ static int check_user_can_set_role(const char *user, const char *host,
{ {
*access = acl_user->access | role->access; *access = acl_user->access | role->access;
} }
end: end:
mysql_mutex_unlock(&acl_cache->lock); mysql_mutex_unlock(&acl_cache->lock);
return result;
/* We present different error messages depending if the user has sufficient
privileges to know if the INVALID_ROLE exists. */
switch (result)
{
case ER_INVALID_CURRENT_USER:
my_error(ER_INVALID_CURRENT_USER, MYF(0), rolename);
break;
case ER_INVALID_ROLE:
/* Role doesn't exist at all */
my_error(ER_INVALID_ROLE, MYF(0), rolename);
break;
case 1:
StringBuffer<1024> c_usr;
LEX_CSTRING role_lex;
/* First, check if current user can see mysql database. */
bool read_access= !check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 1);
role_lex.str= rolename;
role_lex.length= strlen(rolename);
mysql_mutex_lock(&acl_cache->lock);
ACL_USER *cur_user= find_user_or_anon(thd->security_ctx->priv_host,
thd->security_ctx->priv_user,
thd->security_ctx->ip);
/* If the current user does not have select priv to mysql database,
see if the current user can discover the role if it was granted to him.
*/
if (cur_user && (read_access ||
traverse_role_graph_down(cur_user, &role_lex,
check_role_is_granted_callback,
NULL) == -1))
{
/* Role is not granted but current user can see the role */
c_usr.append(user, strlen(user));
c_usr.append('@');
c_usr.append(host, strlen(host));
my_printf_error(ER_INVALID_ROLE, "User %`s has not been granted role %`s",
MYF(0), c_usr.c_ptr(), rolename);
}
else
{
/* Role is not granted and current user cannot see the role */
my_error(ER_INVALID_ROLE, MYF(0), rolename);
}
mysql_mutex_unlock(&acl_cache->lock);
break;
}
return result;
} }
int acl_check_setrole(THD *thd, char *rolename, ulonglong *access) int acl_check_setrole(THD *thd, char *rolename, ulonglong *access)
{ {
/* Yes! priv_user@host. Don't ask why - that's what check_access() does. */ return check_user_can_set_role(thd, thd->security_ctx->priv_user,
return check_user_can_set_role(thd->security_ctx->priv_user, thd->security_ctx->host, thd->security_ctx->ip, rolename, access);
thd->security_ctx->host, thd->security_ctx->ip, rolename, access);
} }
...@@ -3471,9 +3550,12 @@ bool change_password(THD *thd, LEX_USER *user) ...@@ -3471,9 +3550,12 @@ bool change_password(THD *thd, LEX_USER *user)
DBUG_RETURN(result); DBUG_RETURN(result);
} }
int acl_check_set_default_role(THD *thd, const char *host, const char *user) int acl_check_set_default_role(THD *thd, const char *host, const char *user,
const char *role)
{ {
return check_alter_user(thd, host, user); DBUG_ENTER("acl_check_set_default_role");
DBUG_RETURN(check_alter_user(thd, host, user) ||
check_user_can_set_role(thd, user, host, NULL, role, NULL));
} }
int acl_set_default_role(THD *thd, const char *host, const char *user, int acl_set_default_role(THD *thd, const char *host, const char *user,
...@@ -3494,16 +3576,6 @@ int acl_set_default_role(THD *thd, const char *host, const char *user, ...@@ -3494,16 +3576,6 @@ int acl_set_default_role(THD *thd, const char *host, const char *user,
DBUG_PRINT("enter",("host: '%s' user: '%s' rolename: '%s'", DBUG_PRINT("enter",("host: '%s' user: '%s' rolename: '%s'",
safe_str(user), safe_str(host), safe_str(rolename))); safe_str(user), safe_str(host), safe_str(rolename)));
if (rolename == current_role.str) {
if (!thd->security_ctx->priv_role[0])
rolename= "NONE";
else
rolename= thd->security_ctx->priv_role;
}
if (check_user_can_set_role(user, host, host, rolename, NULL))
DBUG_RETURN(result);
if (!strcasecmp(rolename, "NONE")) if (!strcasecmp(rolename, "NONE"))
clear_role= TRUE; clear_role= TRUE;
...@@ -3667,31 +3739,6 @@ bool is_acl_user(const char *host, const char *user) ...@@ -3667,31 +3739,6 @@ bool is_acl_user(const char *host, const char *user)
return res; return res;
} }
/*
unlike find_user_exact and find_user_wild,
this function finds anonymous users too, it's when a
user is not empty, but priv_user (acl_user->user) is empty.
*/
static ACL_USER *find_user_or_anon(const char *host, const char *user, const char *ip)
{
ACL_USER *result= NULL;
mysql_mutex_assert_owner(&acl_cache->lock);
for (uint i=0; i < acl_users.elements; i++)
{
ACL_USER *acl_user_tmp= dynamic_element(&acl_users, i, ACL_USER*);
if ((!acl_user_tmp->user.str ||
!strcmp(user, acl_user_tmp->user.str)) &&
compare_hostname(&acl_user_tmp->host, host, ip))
{
result= acl_user_tmp;
break;
}
}
return result;
}
/* /*
Find first entry that matches the specified user@host pair Find first entry that matches the specified user@host pair
*/ */
...@@ -3997,7 +4044,7 @@ static bool test_if_create_new_users(THD *thd) ...@@ -3997,7 +4044,7 @@ static bool test_if_create_new_users(THD *thd)
if (!(db_access & INSERT_ACL)) if (!(db_access & INSERT_ACL))
{ {
if (check_grant(thd, INSERT_ACL, &tl, FALSE, UINT_MAX, TRUE)) if (check_grant(thd, INSERT_ACL, &tl, FALSE, UINT_MAX, TRUE))
create_new_users=0; create_new_users=0;
} }
} }
return create_new_users; return create_new_users;
...@@ -9244,17 +9291,6 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc) ...@@ -9244,17 +9291,6 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc)
mysql_mutex_unlock(&acl_cache->lock); mysql_mutex_unlock(&acl_cache->lock);
} }
static int check_role_is_granted_callback(ACL_USER_BASE *grantee, void *data)
{
LEX_CSTRING *rolename= static_cast<LEX_CSTRING *>(data);
if (rolename->length == grantee->user.length &&
!strcmp(rolename->str, grantee->user.str))
return -1; // End search, we've found our role.
/* Keep looking, we haven't found our role yet. */
return 0;
}
/* /*
Modify a privilege table. Modify a privilege table.
...@@ -11094,7 +11130,7 @@ acl_check_proxy_grant_access(THD *thd, const char *host, const char *user, ...@@ -11094,7 +11130,7 @@ acl_check_proxy_grant_access(THD *thd, const char *host, const char *user,
Security context in THD contains two pairs of (user,host): Security context in THD contains two pairs of (user,host):
1. (user,host) pair referring to inbound connection. 1. (user,host) pair referring to inbound connection.
2. (priv_user,priv_host) pair obtained from mysql.user table after doing 2. (priv_user,priv_host) pair obtained from mysql.user table after doing
authnetication of incoming connection. authentication of incoming connection.
Privileges should be checked wrt (priv_user, priv_host) tuple, because Privileges should be checked wrt (priv_user, priv_host) tuple, because
(user,host) pair obtained from inbound connection may have different (user,host) pair obtained from inbound connection may have different
values than what is actually stored in mysql.user table and while granting values than what is actually stored in mysql.user table and while granting
...@@ -11511,7 +11547,7 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond) ...@@ -11511,7 +11547,7 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
ulong j,test_access= want_access & ~GRANT_ACL; ulong j,test_access= want_access & ~GRANT_ACL;
for (priv_id=0, j = SELECT_ACL;j <= GLOBAL_ACLS; priv_id++,j <<= 1) for (priv_id=0, j = SELECT_ACL;j <= GLOBAL_ACLS; priv_id++,j <<= 1)
{ {
if (test_access & j) if (test_access & j)
{ {
if (update_schema_privilege(thd, table, buff, 0, 0, 0, 0, if (update_schema_privilege(thd, table, buff, 0, 0, 0, 0,
command_array[priv_id], command_array[priv_id],
......
...@@ -409,7 +409,7 @@ bool acl_check_proxy_grant_access (THD *thd, const char *host, const char *user, ...@@ -409,7 +409,7 @@ bool acl_check_proxy_grant_access (THD *thd, const char *host, const char *user,
bool with_grant); bool with_grant);
int acl_setrole(THD *thd, char *rolename, ulonglong access); int acl_setrole(THD *thd, char *rolename, ulonglong access);
int acl_check_setrole(THD *thd, char *rolename, ulonglong *access); int acl_check_setrole(THD *thd, char *rolename, ulonglong *access);
int acl_check_set_default_role(THD *thd, const char *host, const char *user); int acl_check_set_default_role(THD *thd, const char *host, const char *user, const char *role);
int acl_set_default_role(THD *thd, const char *host, const char *user, int acl_set_default_role(THD *thd, const char *host, const char *user,
const char *rolename); const char *rolename);
......
This diff is collapsed.
...@@ -280,7 +280,6 @@ class Table_statistics ...@@ -280,7 +280,6 @@ class Table_statistics
Column_statistics *column_stats; /* Array of statistical data for columns */ Column_statistics *column_stats; /* Array of statistical data for columns */
Index_statistics *index_stats; /* Array of statistical data for indexes */ Index_statistics *index_stats; /* Array of statistical data for indexes */
ulong *idx_avg_frequency; /* Array of records per key for index prefixes */ ulong *idx_avg_frequency; /* Array of records per key for index prefixes */
ulong total_hist_size; /* Total size of all histograms */
uchar *histograms; /* Sequence of histograms */ uchar *histograms; /* Sequence of histograms */
}; };
......
...@@ -440,10 +440,6 @@ void TABLE_SHARE::destroy() ...@@ -440,10 +440,6 @@ void TABLE_SHARE::destroy()
delete_stat_values_for_table_share(this); delete_stat_values_for_table_share(this);
free_root(&stats_cb.mem_root, MYF(0)); free_root(&stats_cb.mem_root, MYF(0));
stats_cb.stats_can_be_read= FALSE;
stats_cb.stats_is_read= FALSE;
stats_cb.histograms_can_be_read= FALSE;
stats_cb.histograms_are_read= FALSE;
/* The mutexes are initialized only for shares that are part of the TDC */ /* The mutexes are initialized only for shares that are part of the TDC */
if (tmp_table == NO_TMP_TABLE) if (tmp_table == NO_TMP_TABLE)
......
...@@ -567,15 +567,94 @@ enum open_frm_error { ...@@ -567,15 +567,94 @@ enum open_frm_error {
from persistent statistical tables from persistent statistical tables
*/ */
struct TABLE_STATISTICS_CB class TABLE_STATISTICS_CB
{ {
class Statistics_state
{
enum state_codes
{
EMPTY, /** data is not loaded */
LOADING, /** data is being loaded in some connection */
READY /** data is loaded and available for use */
};
int32 state;
public:
/** No state copy */
Statistics_state &operator=(const Statistics_state &) { return *this; }
/** Checks if data loading have been completed */
bool is_ready() const
{
return my_atomic_load32_explicit(const_cast<int32*>(&state),
MY_MEMORY_ORDER_ACQUIRE) == READY;
}
/**
Sets mutual exclusion for data loading
If stats are in LOADING state, waits until state change.
@return
@retval true atomic EMPTY -> LOADING transfer completed, ok to load
@retval false stats are in READY state, no need to load
*/
bool start_load()
{
for (;;)
{
int32 expected= EMPTY;
if (my_atomic_cas32_weak_explicit(&state, &expected, LOADING,
MY_MEMORY_ORDER_RELAXED,
MY_MEMORY_ORDER_RELAXED))
return true;
if (expected == READY)
return false;
(void) LF_BACKOFF;
}
}
/** Marks data available for subsequent use */
void end_load()
{
DBUG_ASSERT(my_atomic_load32_explicit(&state, MY_MEMORY_ORDER_RELAXED) ==
LOADING);
my_atomic_store32_explicit(&state, READY, MY_MEMORY_ORDER_RELEASE);
}
/** Restores empty state on error (e.g. OOM) */
void abort_load()
{
DBUG_ASSERT(my_atomic_load32_explicit(&state, MY_MEMORY_ORDER_RELAXED) ==
LOADING);
my_atomic_store32_explicit(&state, EMPTY, MY_MEMORY_ORDER_RELAXED);
}
};
class Statistics_state stats_state;
class Statistics_state hist_state;
public:
MEM_ROOT mem_root; /* MEM_ROOT to allocate statistical data for the table */ MEM_ROOT mem_root; /* MEM_ROOT to allocate statistical data for the table */
Table_statistics *table_stats; /* Structure to access the statistical data */ Table_statistics *table_stats; /* Structure to access the statistical data */
bool stats_can_be_read; /* Memory for statistical data is allocated */ ulong total_hist_size; /* Total size of all histograms */
bool stats_is_read; /* Statistical data for table has been read
from statistical tables */ bool histograms_are_ready() const
bool histograms_can_be_read; {
bool histograms_are_read; return !total_hist_size || hist_state.is_ready();
}
bool start_histograms_load()
{
return total_hist_size && hist_state.start_load();
}
void end_histograms_load() { hist_state.end_load(); }
void abort_histograms_load() { hist_state.abort_load(); }
bool stats_are_ready() const { return stats_state.is_ready(); }
bool start_stats_load() { return stats_state.start_load(); }
void end_stats_load() { stats_state.end_load(); }
void abort_stats_load() { stats_state.abort_load(); }
}; };
......
...@@ -932,7 +932,7 @@ MRN_SHARE *mrn_get_share(const char *table_name, TABLE *table, int *error) ...@@ -932,7 +932,7 @@ MRN_SHARE *mrn_get_share(const char *table_name, TABLE *table, int *error)
share->wrap_key_info = NULL; share->wrap_key_info = NULL;
share->wrap_primary_key = MAX_KEY; share->wrap_primary_key = MAX_KEY;
} }
memcpy(wrap_table_share, table->s, sizeof(*wrap_table_share)); *wrap_table_share= *table->s;
mrn_init_sql_alloc(current_thd, &(wrap_table_share->mem_root)); mrn_init_sql_alloc(current_thd, &(wrap_table_share->mem_root));
wrap_table_share->keys = share->wrap_keys; wrap_table_share->keys = share->wrap_keys;
wrap_table_share->key_info = share->wrap_key_info; wrap_table_share->key_info = share->wrap_key_info;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment