Commit d5c97122 authored by Sergei Golubchik's avatar Sergei Golubchik

post-review cleanup

parent e46eea86
# #
# MDEV-5176 Server crashes in fill_schema_applicable_roles on select from APPLICABLE_ROLES after a suicide # MDEV-5176 Server crashes in fill_schema_applicable_roles on select from APPLICABLE_ROLES after a suicide
# #
--source include/not_embedded.inc
grant create user on *.* to foo@localhost; grant create user on *.* to foo@localhost;
--connect (foo,localhost,foo,,) --connect (foo,localhost,foo,,)
......
...@@ -2866,7 +2866,7 @@ bool Query_log_event::write(IO_CACHE* file) ...@@ -2866,7 +2866,7 @@ bool Query_log_event::write(IO_CACHE* file)
else else
{ {
user.str= ctx->priv_role; user.str= ctx->priv_role;
host= null_lex_str; // XXX FIXME or empty_lex_str ? host= empty_lex_str;
} }
user.length= strlen(user.str); user.length= strlen(user.str);
} }
......
...@@ -185,8 +185,7 @@ static LEX_STRING old_password_plugin_name= { ...@@ -185,8 +185,7 @@ static LEX_STRING old_password_plugin_name= {
LEX_STRING *default_auth_plugin_name= &native_password_plugin_name; LEX_STRING *default_auth_plugin_name= &native_password_plugin_name;
/* /*
Constant used for differentiating specified user names and non specified Wildcard host, matches any hostname
usernames. Example: userA -- userA@%
*/ */
LEX_STRING host_not_specified= { C_STRING_WITH_LEN("%") }; LEX_STRING host_not_specified= { C_STRING_WITH_LEN("%") };
...@@ -317,14 +316,15 @@ class ACL_ROLE :public ACL_USER_BASE ...@@ -317,14 +316,15 @@ class ACL_ROLE :public ACL_USER_BASE
via a bit OR operation and placed in the ACL_USER::access field. via a bit OR operation and placed in the ACL_USER::access field.
When rebuilding role_grants via the rebuild_role_grant function, When rebuilding role_grants via the rebuild_role_grant function,
the ACL_USER::access field needs to be reset aswell. The field the ACL_USER::access field needs to be reset first. The field
initial_role_access holds the initial grants present in the table row. initial_role_access holds initial grants, as granted directly to the role
*/ */
ulong initial_role_access; ulong initial_role_access;
/* /*
In subgraph traversal, when we need to traverse only a part of the graph In subgraph traversal, when we need to traverse only a part of the graph
(e.g. all direct and indirect grantees of a role X), the counter holds the (e.g. all direct and indirect grantees of a role X), the counter holds the
number of affected neighbour nodes. number of affected neighbour nodes.
See also propagate_role_grants()
*/ */
uint counter; uint counter;
DYNAMIC_ARRAY parent_grantee; // array of backlinks to elements granted DYNAMIC_ARRAY parent_grantee; // array of backlinks to elements granted
...@@ -622,15 +622,6 @@ struct ROLE_GRANT_PAIR : public Sql_alloc ...@@ -622,15 +622,6 @@ struct ROLE_GRANT_PAIR : public Sql_alloc
bool with_admin_option); bool with_admin_option);
}; };
/*
Struct to hold the state of a node during a Depth First Search exploration
*/
struct NODE_STATE
{
ACL_USER_BASE *node_data; /* pointer to the node data */
uint neigh_idx; /* the neighbour that needs to be evaluated next */
};
static uchar* acl_role_map_get_key(ROLE_GRANT_PAIR *entry, size_t *length, static uchar* acl_role_map_get_key(ROLE_GRANT_PAIR *entry, size_t *length,
my_bool not_used __attribute__((unused))) my_bool not_used __attribute__((unused)))
{ {
...@@ -1150,7 +1141,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) ...@@ -1150,7 +1141,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
if (is_role && is_invalid_role_name(username)) if (is_role && is_invalid_role_name(username))
{ {
thd->clear_error(); thd->clear_error(); // the warning is still issued
continue; continue;
} }
...@@ -1212,7 +1203,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) ...@@ -1212,7 +1203,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
if (table->s->fields <= 38 && (user.access & SUPER_ACL)) if (table->s->fields <= 38 && (user.access & SUPER_ACL))
user.access|= TRIGGER_ACL; user.access|= TRIGGER_ACL;
user.sort= get_sort(2,user.host.hostname,user.user); user.sort= get_sort(2, user.host.hostname, user.user.str);
user.hostname_length= (user.host.hostname ? user.hostname_length= (user.host.hostname ?
(uint) strlen(user.host.hostname) : 0); (uint) strlen(user.host.hostname) : 0);
...@@ -1427,7 +1418,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) ...@@ -1427,7 +1418,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
table->use_all_columns(); table->use_all_columns();
/* account for every role mapping */ /* account for every role mapping */
(void) my_hash_init2(&acl_roles_mappings,50,system_charset_info, (void) my_hash_init2(&acl_roles_mappings, 50, system_charset_info,
0,0,0, (my_hash_get_key) acl_role_map_get_key, 0,0); 0,0,0, (my_hash_get_key) acl_role_map_get_key, 0,0);
MEM_ROOT temp_root; MEM_ROOT temp_root;
init_alloc_root(&temp_root, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0)); init_alloc_root(&temp_root, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0));
...@@ -1664,13 +1655,10 @@ static bool check_is_role(TABLE *form) ...@@ -1664,13 +1655,10 @@ static bool check_is_role(TABLE *form)
char buff[2]; char buff[2];
String res(buff, sizeof(buff), &my_charset_latin1); String res(buff, sizeof(buff), &my_charset_latin1);
/* Table version does not support roles */ /* Table version does not support roles */
if (form->s->fields <= 42) if (form->s->fields <= ROLE_ASSIGN_COLUMN_IDX)
return FALSE; return FALSE;
if (get_YN_as_bool(form->field[ROLE_ASSIGN_COLUMN_IDX])) return get_YN_as_bool(form->field[ROLE_ASSIGN_COLUMN_IDX]);
return TRUE;
return FALSE;
} }
...@@ -2061,7 +2049,7 @@ static void acl_insert_user(const char *user, const char *host, ...@@ -2061,7 +2049,7 @@ static void acl_insert_user(const char *user, const char *host,
acl_user.flags= 0; acl_user.flags= 0;
acl_user.access=privileges; acl_user.access=privileges;
acl_user.user_resource = *mqh; acl_user.user_resource = *mqh;
acl_user.sort=get_sort(2,acl_user.host.hostname,acl_user.user); acl_user.sort=get_sort(2, acl_user.host.hostname, acl_user.user.str);
acl_user.hostname_length=(uint) strlen(host); acl_user.hostname_length=(uint) strlen(host);
acl_user.ssl_type= (ssl_type != SSL_TYPE_NOT_SPECIFIED ? acl_user.ssl_type= (ssl_type != SSL_TYPE_NOT_SPECIFIED ?
ssl_type : SSL_TYPE_NONE); ssl_type : SSL_TYPE_NONE);
...@@ -2080,8 +2068,11 @@ static void acl_insert_user(const char *user, const char *host, ...@@ -2080,8 +2068,11 @@ static void acl_insert_user(const char *user, const char *host,
/* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */ /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */
rebuild_check_host(); rebuild_check_host();
/* Rebuild every user's role_grants because the acl_user has been modified
and some grants might now be invalid */ /*
Rebuild every user's role_grants since 'acl_users' has been sorted
and old pointers to ACL_USER elements are no longer valid
*/
rebuild_role_grants(); rebuild_role_grants();
} }
...@@ -2135,15 +2126,14 @@ static void acl_update_db(const char *user, const char *host, const char *db, ...@@ -2135,15 +2126,14 @@ static void acl_update_db(const char *user, const char *host, const char *db,
*/ */
static void acl_insert_db(const char *user, const char *host, const char *db, static void acl_insert_db(const char *user, const char *host, const char *db,
ulong privileges, bool set_initial_access) ulong privileges)
{ {
ACL_DB acl_db; ACL_DB acl_db;
mysql_mutex_assert_owner(&acl_cache->lock); mysql_mutex_assert_owner(&acl_cache->lock);
acl_db.user=strdup_root(&mem,user); acl_db.user=strdup_root(&mem,user);
update_hostname(&acl_db.host, safe_strdup_root(&mem, host)); update_hostname(&acl_db.host, safe_strdup_root(&mem, host));
acl_db.db=strdup_root(&mem,db); acl_db.db=strdup_root(&mem,db);
acl_db.access=privileges; acl_db.initial_access= acl_db.access= privileges;
acl_db.initial_access= set_initial_access ? acl_db.access : 0;
acl_db.sort=get_sort(3,acl_db.host.hostname,acl_db.db,acl_db.user); acl_db.sort=get_sort(3,acl_db.host.hostname,acl_db.db,acl_db.user);
(void) push_dynamic(&acl_dbs,(uchar*) &acl_db); (void) push_dynamic(&acl_dbs,(uchar*) &acl_db);
my_qsort((uchar*) dynamic_element(&acl_dbs,0,ACL_DB*),acl_dbs.elements, my_qsort((uchar*) dynamic_element(&acl_dbs,0,ACL_DB*),acl_dbs.elements,
...@@ -2321,8 +2311,6 @@ void rebuild_check_host(void) ...@@ -2321,8 +2311,6 @@ void rebuild_check_host(void)
/* /*
Reset a role role_grants dynamic array. Reset a role role_grants dynamic array.
Also, the role's access bits are reset to the ones present in the table. Also, the role's access bits are reset to the ones present in the table.
The function can be used as a walk action for hash elements aswell.
*/ */
static my_bool acl_role_reset_role_arrays(void *ptr, static my_bool acl_role_reset_role_arrays(void *ptr,
void * not_used __attribute__((unused))) void * not_used __attribute__((unused)))
...@@ -2345,6 +2333,9 @@ static bool add_role_user_mapping(ACL_USER_BASE *grantee, ACL_ROLE *role) ...@@ -2345,6 +2333,9 @@ static bool add_role_user_mapping(ACL_USER_BASE *grantee, ACL_ROLE *role)
} }
/*
Revert the last add_role_user_mapping() action
*/
static void undo_add_role_user_mapping(ACL_USER_BASE *grantee, ACL_ROLE *role) static void undo_add_role_user_mapping(ACL_USER_BASE *grantee, ACL_ROLE *role)
{ {
void *pop __attribute__((unused)); void *pop __attribute__((unused));
...@@ -2713,7 +2704,7 @@ static ACL_USER *find_user_or_anon(const char *host, const char *user, const cha ...@@ -2713,7 +2704,7 @@ static ACL_USER *find_user_or_anon(const char *host, const char *user, const cha
/* /*
Find first entry that matches the current user Find first entry that matches the specified user@host pair
*/ */
static ACL_USER * find_user_exact(const char *host, const char *user) static ACL_USER * find_user_exact(const char *host, const char *user)
{ {
...@@ -2729,7 +2720,7 @@ static ACL_USER * find_user_exact(const char *host, const char *user) ...@@ -2729,7 +2720,7 @@ static ACL_USER * find_user_exact(const char *host, const char *user)
} }
/* /*
Find first entry that matches the current user Find first entry that matches the specified user@host pair
*/ */
static ACL_USER * find_user_wild(const char *host, const char *user, const char *ip) static ACL_USER * find_user_wild(const char *host, const char *user, const char *ip)
{ {
...@@ -2745,18 +2736,18 @@ static ACL_USER * find_user_wild(const char *host, const char *user, const char ...@@ -2745,18 +2736,18 @@ static ACL_USER * find_user_wild(const char *host, const char *user, const char
} }
/* /*
Find first entry that matches the current user Find a role with the specified name
*/ */
static ACL_ROLE *find_acl_role(const char *user) static ACL_ROLE *find_acl_role(const char *role)
{ {
DBUG_ENTER("find_acl_role"); DBUG_ENTER("find_acl_role");
DBUG_PRINT("enter",("user: '%s'", user)); DBUG_PRINT("enter",("role: '%s'", role));
DBUG_PRINT("info", ("Hash elements: %ld", acl_roles.records)); DBUG_PRINT("info", ("Hash elements: %ld", acl_roles.records));
mysql_mutex_assert_owner(&acl_cache->lock); mysql_mutex_assert_owner(&acl_cache->lock);
ACL_ROLE *r= (ACL_ROLE *)my_hash_search(&acl_roles, (uchar *)user, ACL_ROLE *r= (ACL_ROLE *)my_hash_search(&acl_roles, (uchar *)role,
user ? strlen(user) : 0); role ? strlen(role) : 0);
DBUG_RETURN(r); DBUG_RETURN(r);
} }
...@@ -3022,10 +3013,10 @@ static int replace_user_table(THD *thd, TABLE *table, LEX_USER &combo, ...@@ -3022,10 +3013,10 @@ static int replace_user_table(THD *thd, TABLE *table, LEX_USER &combo,
combo.password= empty_lex_str; combo.password= empty_lex_str;
/* if the user table is not up to date, we can't handle role updates */ /* if the user table is not up to date, we can't handle role updates */
if (table->s->fields <= 42 && handle_as_role) if (table->s->fields <= ROLE_ASSIGN_COLUMN_IDX && handle_as_role)
{ {
my_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, MYF(0), table->alias.c_ptr(), my_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, MYF(0),
43, table->s->fields, table->alias.c_ptr(), ROLE_ASSIGN_COLUMN_IDX + 1, table->s->fields,
static_cast<int>(table->s->mysql_version), MYSQL_VERSION_ID); static_cast<int>(table->s->mysql_version), MYSQL_VERSION_ID);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
...@@ -3373,7 +3364,7 @@ static int replace_db_table(TABLE *table, const char *db, ...@@ -3373,7 +3364,7 @@ static int replace_db_table(TABLE *table, const char *db,
acl_update_db(combo.user.str,combo.host.str,db,rights); acl_update_db(combo.user.str,combo.host.str,db,rights);
else else
if (rights) if (rights)
acl_insert_db(combo.user.str,combo.host.str,db,rights, 1); acl_insert_db(combo.user.str,combo.host.str,db,rights);
DBUG_RETURN(0); DBUG_RETURN(0);
/* This could only happen if the grant tables got corrupted */ /* This could only happen if the grant tables got corrupted */
...@@ -4554,6 +4545,13 @@ static void propagate_role_grants(ACL_ROLE *role, ...@@ -4554,6 +4545,13 @@ static void propagate_role_grants(ACL_ROLE *role,
} }
// State of a node during a Depth First Search exploration
struct NODE_STATE
{
ACL_USER_BASE *node_data; /* pointer to the node data */
uint neigh_idx; /* the neighbour that needs to be evaluated next */
};
/** /**
Traverse the role grant graph and invoke callbacks at the specified points. Traverse the role grant graph and invoke callbacks at the specified points.
...@@ -4588,7 +4586,6 @@ static int traverse_role_graph_impl(ACL_USER_BASE *user, void *context, ...@@ -4588,7 +4586,6 @@ static int traverse_role_graph_impl(ACL_USER_BASE *user, void *context,
int (*on_node) (ACL_USER_BASE *role, void *context), int (*on_node) (ACL_USER_BASE *role, void *context),
int (*on_edge) (ACL_USER_BASE *current, ACL_ROLE *neighbour, void *context)) int (*on_edge) (ACL_USER_BASE *current, ACL_ROLE *neighbour, void *context))
{ {
DBUG_ENTER("traverse_role_graph_impl"); DBUG_ENTER("traverse_role_graph_impl");
DBUG_ASSERT(user); DBUG_ASSERT(user);
DBUG_PRINT("enter",("role: '%s'", user->user.str)); DBUG_PRINT("enter",("role: '%s'", user->user.str));
...@@ -4730,7 +4727,7 @@ static int traverse_role_graph_up(ACL_ROLE *role, void *context, ...@@ -4730,7 +4727,7 @@ static int traverse_role_graph_up(ACL_ROLE *role, void *context,
return traverse_role_graph_impl(role, context, return traverse_role_graph_impl(role, context,
my_offsetof(ACL_ROLE, parent_grantee), my_offsetof(ACL_ROLE, parent_grantee),
(int (*)(ACL_USER_BASE *, void *))on_node, (int (*)(ACL_USER_BASE *, void *))on_node,
(int (*) (ACL_USER_BASE *, ACL_ROLE *, void *))on_edge); (int (*)(ACL_USER_BASE *, ACL_ROLE *, void *))on_edge);
} }
/** /**
...@@ -4751,7 +4748,7 @@ static int traverse_role_graph_down(ACL_USER_BASE *user, void *context, ...@@ -4751,7 +4748,7 @@ static int traverse_role_graph_down(ACL_USER_BASE *user, void *context,
/* /*
To find all db/table/routine privilege for a specific role To find all db/table/routine privilege for a specific role
we need to scan the array of privileges it can be big. we need to scan the array of privileges. It can be big.
But the set of privileges granted to a role in question (or But the set of privileges granted to a role in question (or
to roles directly granted to the role in question) is supposedly to roles directly granted to the role in question) is supposedly
much smaller. much smaller.
...@@ -5058,14 +5055,11 @@ static int update_role_table_columns(GRANT_TABLE *merged, ...@@ -5058,14 +5055,11 @@ static int update_role_table_columns(GRANT_TABLE *merged,
else else
{ {
bool changed= merged->cols != cols || merged->privs != privs; bool changed= merged->cols != cols || merged->privs != privs;
/*
note that 'changed' above is a sufficient, but not necessary condition.
even if neither cols nor privs have changed, the set of columns
could've been changed, and we have to return 1 even if changed==0
*/
merged->cols= cols; merged->cols= cols;
merged->privs= privs; merged->privs= privs;
return update_role_columns(merged, first, last) || changed; if (update_role_columns(merged, first, last))
changed= true;
return changed;
} }
} }
...@@ -5212,10 +5206,10 @@ static bool merge_role_routine_grant_privileges(ACL_ROLE *grantee, ...@@ -5212,10 +5206,10 @@ static bool merge_role_routine_grant_privileges(ACL_ROLE *grantee,
for (uint i=0 ; i < hash->records ; i++) for (uint i=0 ; i < hash->records ; i++)
{ {
GRANT_NAME *grant= (GRANT_NAME *) my_hash_element(hash, i); GRANT_NAME *grant= (GRANT_NAME *) my_hash_element(hash, i);
if (tname && (strcmp(grant->db, db) || strcmp(grant->tname, tname)))
continue;
if (grant->host.hostname[0]) if (grant->host.hostname[0])
continue; continue;
if (tname && (strcmp(grant->db, db) || strcmp(grant->tname, tname)))
continue;
ACL_ROLE *r= rhash->find(grant->user, strlen(grant->user)); ACL_ROLE *r= rhash->find(grant->user, strlen(grant->user));
if (!r) if (!r)
continue; continue;
...@@ -7147,7 +7141,7 @@ bool check_routine_level_acl(THD *thd, const char *db, const char *name, ...@@ -7147,7 +7141,7 @@ bool check_routine_level_acl(THD *thd, const char *db, const char *name,
name, is_proc, 0))) name, is_proc, 0)))
no_routine_acl= !(grant_proc->privs & SHOW_PROC_ACLS); no_routine_acl= !(grant_proc->privs & SHOW_PROC_ACLS);
if (sctx->priv_role[0]) /* current set role check */ if (no_routine_acl && sctx->priv_role[0]) /* current set role check */
{ {
if ((grant_proc= routine_hash_search("", if ((grant_proc= routine_hash_search("",
NULL, db, NULL, db,
...@@ -9187,8 +9181,8 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list, bool handle_as_role) ...@@ -9187,8 +9181,8 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list, bool handle_as_role)
rebuild_check_host(); rebuild_check_host();
/* /*
Rebuild every user's role_grants because the acl_users has been modified Rebuild every user's role_grants since 'acl_users' has been sorted
and pointers to ACL_USER's might now be invalid and old pointers to ACL_USER elements are no longer valid
*/ */
rebuild_role_grants(); rebuild_role_grants();
} }
...@@ -9276,8 +9270,11 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) ...@@ -9276,8 +9270,11 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
/* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */ /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */
rebuild_check_host(); rebuild_check_host();
/* Rebuild every user's role_grants because the acl_user has been modified
and some grants might now be invalid */ /*
Rebuild every user's role_grants since 'acl_users' has been sorted
and old pointers to ACL_USER elements are no longer valid
*/
rebuild_role_grants(); rebuild_role_grants();
mysql_mutex_unlock(&acl_cache->lock); mysql_mutex_unlock(&acl_cache->lock);
...@@ -9921,7 +9918,7 @@ struct APPLICABLE_ROLES_DATA ...@@ -9921,7 +9918,7 @@ struct APPLICABLE_ROLES_DATA
{ {
TABLE *table; TABLE *table;
const LEX_STRING host; const LEX_STRING host;
const LEX_STRING used_and_host; const LEX_STRING user_and_host;
ACL_USER_BASE *user; ACL_USER_BASE *user;
}; };
...@@ -9932,12 +9929,12 @@ applicable_roles_insert(ACL_USER_BASE *grantee, ACL_ROLE *role, void *ptr) ...@@ -9932,12 +9929,12 @@ applicable_roles_insert(ACL_USER_BASE *grantee, ACL_ROLE *role, void *ptr)
CHARSET_INFO *cs= system_charset_info; CHARSET_INFO *cs= system_charset_info;
TABLE *table= data->table; TABLE *table= data->table;
bool is_role= grantee != data->user; bool is_role= grantee != data->user;
const LEX_STRING *used_and_host= is_role ? &grantee->user const LEX_STRING *user_and_host= is_role ? &grantee->user
: &data->used_and_host; : &data->user_and_host;
const LEX_STRING *host= is_role ? &empty_lex_str : &data->host; const LEX_STRING *host= is_role ? &empty_lex_str : &data->host;
restore_record(table, s->default_values); restore_record(table, s->default_values);
table->field[0]->store(used_and_host->str, used_and_host->length, cs); table->field[0]->store(user_and_host->str, user_and_host->length, cs);
table->field[1]->store(role->user.str, role->user.length, cs); table->field[1]->store(role->user.str, role->user.length, cs);
ROLE_GRANT_PAIR *pair= ROLE_GRANT_PAIR *pair=
...@@ -10490,10 +10487,11 @@ bool check_routine_level_acl(THD *thd, const char *db, const char *name, ...@@ -10490,10 +10487,11 @@ bool check_routine_level_acl(THD *thd, const char *db, const char *name,
#endif #endif
/** /**
Retuns information about user or current user. Return information about user or current user.
@param[in] thd thread handler @param[in] thd thread handler
@param[in] user user @param[in] user user
@param[in] lock whether &acl_cache->lock mutex needs to be locked
@return @return
- On success, return a valid pointer to initialized - On success, return a valid pointer to initialized
......
...@@ -3908,8 +3908,6 @@ case SQLCOM_PREPARE: ...@@ -3908,8 +3908,6 @@ case SQLCOM_PREPARE:
case SQLCOM_REVOKE_ROLE: case SQLCOM_REVOKE_ROLE:
case SQLCOM_GRANT_ROLE: case SQLCOM_GRANT_ROLE:
{ {
/* TODO access check */
if (!(res= mysql_grant_role(thd, lex->users_list, if (!(res= mysql_grant_role(thd, lex->users_list,
lex->sql_command != SQLCOM_GRANT_ROLE))) lex->sql_command != SQLCOM_GRANT_ROLE)))
my_ok(thd); my_ok(thd);
......
...@@ -822,6 +822,10 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, ...@@ -822,6 +822,10 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
goto err; goto err;
} }
/*
version 1 - before 10.0.5
version 2 - empty definer_host means a role
*/
view->file_version= 2; view->file_version= 2;
view->calc_md5(md5); view->calc_md5(md5);
if (!(view->md5.str= (char*) thd->memdup(md5, 32))) if (!(view->md5.str= (char*) thd->memdup(md5, 32)))
......
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