Below is the list of changes that have just been committed into a local
5.0 repository of antony. When antony does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet
1.1947 05/05/15 23:21:38 antony@stripped +14 -0
Bug#10246 - Parser: bad syntax for GRANT EXECUTE
Amend grammar to be less ambigious for procedure and function privileges
Allow specific function privileges to be distinct and seperate from specific procedure privileges
BitKeeper/etc/logging_ok
1.312 05/05/15 23:21:36 antony@stripped +1 -0
Logging to logging@stripped accepted
sql/sql_yacc.yy
1.372 05/05/15 23:21:16 antony@stripped +73 -7
when parsing grant/revoke statements,
lex->type is 0 for table grants
1 for procedures
2 for functions
sql/sql_show.cc
1.245 05/05/15 23:21:16 antony@stripped +2 -1
check_some_routine_access takes 1 more argument
sql/sql_parse.cc
1.451 05/05/15 23:21:16 antony@stripped +24 -22
when parsing grant/revoke statements,
lex->type is 0 for table grants
1 for procedures
2 for functions
sql/sql_acl.h
1.43 05/05/15 23:21:16 antony@stripped +11 -8
Rename functions
sql/sql_acl.cc
1.151 05/05/15 23:21:16 antony@stripped +124 -67
Bug#10246
must be able to grant privileges on procedures and functions seperately
sql/sp_head.cc
1.134 05/05/15 23:21:15 antony@stripped +1 -1
Rename functions
sql/mysql_priv.h
1.296 05/05/15 23:21:15 antony@stripped +3 -3
Rename functions
sql/item_func.cc
1.194 05/05/15 23:21:15 antony@stripped +4 -4
Rename functions
scripts/mysql_fix_privilege_tables.sql
1.26 05/05/15 23:21:15 antony@stripped +7 -2
Change in procs_priv table
scripts/mysql_create_system_tables.sh
1.23 05/05/15 23:21:15 antony@stripped +3 -2
Change in procs_priv table
mysql-test/t/sp-security.test
1.15 05/05/15 23:21:15 antony@stripped +14 -14
Change syntax as reqd by Bug#10246
mysql-test/r/system_mysql_db.result
1.22 05/05/15 23:21:15 antony@stripped +3 -2
Change in procs_priv table
mysql-test/r/sp-security.result
1.13 05/05/15 23:21:15 antony@stripped +24 -24
Change syntax as reqd by Bug#10246
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: antony
# Host: ltantony.xiphis.org
# Root: /usr/home/antony/work2/p1-bug10246
--- 1.193/sql/item_func.cc 2005-05-13 10:28:28 +01:00
+++ 1.194/sql/item_func.cc 2005-05-15 23:21:15 +01:00
@@ -4766,13 +4766,13 @@
#endif
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- if (check_procedure_access(thd, EXECUTE_ACL,
- m_sp->m_db.str, m_sp->m_name.str, 0))
+ if (check_routine_access(thd, EXECUTE_ACL,
+ m_sp->m_db.str, m_sp->m_name.str, 0, 0))
DBUG_RETURN(-1);
sp_change_security_context(thd, m_sp, &save_ctx);
if (save_ctx.changed &&
- check_procedure_access(thd, EXECUTE_ACL,
- m_sp->m_db.str, m_sp->m_name.str, 0))
+ check_routine_access(thd, EXECUTE_ACL,
+ m_sp->m_db.str, m_sp->m_name.str, 0, 0))
{
sp_restore_security_context(thd, m_sp, &save_ctx);
thd->client_capabilities|= old_client_capabilites & CLIENT_MULTI_RESULTS;
--- 1.295/sql/mysql_priv.h 2005-05-09 17:44:21 +01:00
+++ 1.296/sql/mysql_priv.h 2005-05-15 23:21:15 +01:00
@@ -473,12 +473,12 @@
TABLE *stopper= 0);
bool check_one_table_access(THD *thd, ulong privilege,
TABLE_LIST *tables);
-bool check_procedure_access(THD *thd,ulong want_access,char *db,char *name,
- bool no_errors);
+bool check_routine_access(THD *thd,ulong want_access,char *db,char *name,
+ bool is_proc, bool no_errors);
bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table);
bool check_merge_table_access(THD *thd, char *db,
TABLE_LIST *table_list);
-bool check_some_routine_access(THD *thd, const char *db, const char *name);
+bool check_some_routine_access(THD *thd, const char *db, const char *name, bool is_proc);
bool multi_update_precheck(THD *thd, TABLE_LIST *tables);
bool multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count);
bool mysql_multi_update_prepare(THD *thd);
--- 1.150/sql/sql_acl.cc 2005-05-07 14:55:41 +01:00
+++ 1.151/sql/sql_acl.cc 2005-05-15 23:21:16 +01:00
@@ -60,7 +60,7 @@
static MEM_ROOT mem, memex;
static bool initialized=0;
static bool allow_all_hosts=1;
-static HASH acl_check_hosts, column_priv_hash, proc_priv_hash;
+static HASH acl_check_hosts, column_priv_hash, proc_priv_hash, func_priv_hash;
static DYNAMIC_ARRAY acl_wild_hosts;
static hash_filo *acl_cache;
static uint grant_version=0; /* Version of priv tables. incremented by acl_init */
@@ -2136,11 +2136,12 @@
inline GRANT_NAME *
-proc_hash_search(const char *host, const char *ip, const char *db,
- const char *user, const char *tname, bool exact)
+routine_hash_search(const char *host, const char *ip, const char *db,
+ const char *user, const char *tname, bool proc, bool exact)
{
- return (GRANT_TABLE*) name_hash_search(&proc_priv_hash, host, ip, db,
- user, tname, exact);
+ return (GRANT_TABLE*)
+ name_hash_search(proc ? &proc_priv_hash : &func_priv_hash,
+ host, ip, db, user, tname, exact);
}
@@ -2466,16 +2467,17 @@
}
-static int replace_proc_table(THD *thd, GRANT_NAME *grant_name,
+static int replace_routine_table(THD *thd, GRANT_NAME *grant_name,
TABLE *table, const LEX_USER &combo,
- const char *db, const char *proc_name,
- ulong rights, bool revoke_grant)
+ const char *db, const char *routine_name,
+ bool is_proc, ulong rights, bool revoke_grant)
{
char grantor[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
int old_row_exists= 1;
int error=0;
ulong store_proc_rights;
- DBUG_ENTER("replace_proc_table");
+ byte *key;
+ DBUG_ENTER("replace_routine_table");
if (!initialized)
{
@@ -2499,7 +2501,8 @@
table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1);
table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1);
table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1);
- table->field[3]->store(proc_name,(uint) strlen(proc_name), &my_charset_latin1);
+ table->field[3]->store(routine_name,(uint) strlen(routine_name), &my_charset_latin1);
+ table->field[4]->store(is_proc ? 1LL : 2LL);
store_record(table,record[1]); // store at pos 1
if (table->file->index_read_idx(table->record[0],0,
@@ -2514,7 +2517,7 @@
if (revoke_grant)
{ // no row, no revoke
my_error(ER_NONEXISTING_PROC_GRANT, MYF(0),
- combo.user.str, combo.host.str, proc_name);
+ combo.user.str, combo.host.str, routine_name);
DBUG_RETURN(-1);
}
old_row_exists= 0;
@@ -2539,7 +2542,7 @@
}
}
- table->field[4]->store(grantor,(uint) strlen(grantor), &my_charset_latin1);
+ table->field[5]->store(grantor,(uint) strlen(grantor), &my_charset_latin1);
table->field[6]->store((longlong) store_proc_rights);
rights=fix_rights_for_procedure(store_proc_rights);
@@ -2566,7 +2569,7 @@
}
else
{
- hash_delete(&proc_priv_hash,(byte*) grant_name);
+ hash_delete(is_proc ? &proc_priv_hash : &func_priv_hash,(byte*) grant_name);
}
DBUG_RETURN(0);
@@ -2841,12 +2844,13 @@
/*
- Store procedure level grants in the privilege tables
+ Store routine level grants in the privilege tables
SYNOPSIS
- mysql_procedure_grant()
+ mysql_routine_grant()
thd Thread handle
- table_list List of procedures to give grant
+ table_list List of routines to give grant
+ is_proc true indicates routine list are procedures
user_list List of users to give grant
rights Table level grant
revoke_grant Set to 1 if this is a REVOKE command
@@ -2856,16 +2860,16 @@
1 error
*/
-bool mysql_procedure_grant(THD *thd, TABLE_LIST *table_list,
- List <LEX_USER> &user_list, ulong rights,
- bool revoke_grant, bool no_error)
+bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
+ List <LEX_USER> &user_list, ulong rights,
+ bool revoke_grant, bool no_error)
{
List_iterator <LEX_USER> str_list (user_list);
LEX_USER *Str;
TABLE_LIST tables[2];
bool create_new_users=0, result=0;
char *db_name, *table_name;
- DBUG_ENTER("mysql_procedure_grant");
+ DBUG_ENTER("mysql_routine_grant");
if (!initialized)
{
@@ -2884,7 +2888,7 @@
if (!revoke_grant)
{
- if (sp_exists_routine(thd, table_list, 0, no_error)<0)
+ if (sp_exists_routine(thd, table_list, is_proc, no_error)<0)
DBUG_RETURN(TRUE);
}
@@ -2957,8 +2961,8 @@
db_name= table_list->db;
table_name= table_list->table_name;
- grant_name= proc_hash_search(Str->host.str, NullS, db_name,
- Str->user.str, table_name, 1);
+ grant_name= routine_hash_search(Str->host.str, NullS, db_name,
+ Str->user.str, table_name, is_proc, 1);
if (!grant_name)
{
if (revoke_grant)
@@ -2977,11 +2981,11 @@
result= TRUE;
continue;
}
- my_hash_insert(&proc_priv_hash,(byte*) grant_name);
+ my_hash_insert(is_proc ? &proc_priv_hash : &func_priv_hash,(byte*) grant_name);
}
- if (replace_proc_table(thd, grant_name, tables[1].table, *Str,
- db_name, table_name, rights, revoke_grant))
+ if (replace_routine_table(thd, grant_name, tables[1].table, *Str,
+ db_name, table_name, is_proc, rights, revoke_grant))
{
result= TRUE;
continue;
@@ -3133,6 +3137,9 @@
(void) hash_init(&proc_priv_hash,system_charset_info,
0,0,0, (hash_get_key) get_grant_table,
0,0);
+ (void) hash_init(&func_priv_hash,system_charset_info,
+ 0,0,0, (hash_get_key) get_grant_table,
+ 0,0);
init_sql_alloc(&memex, ACL_ALLOC_BLOCK_SIZE, 0);
/* Don't do anything if running with --skip-grant */
@@ -3206,6 +3213,8 @@
do
{
GRANT_NAME *mem_check;
+ longlong proc_type;
+ HASH *hash;
if (!(mem_check=new GRANT_NAME(p_table)))
{
/* This could only happen if we are out memory */
@@ -3224,11 +3233,25 @@
continue;
}
}
+ switch (proc_type= p_table->field[4]->val_int())
+ {
+ case 1LL:
+ hash= &proc_priv_hash;
+ break;
+ case 2LL:
+ hash= &func_priv_hash;
+ break;
+ default:
+ sql_print_warning("'procs_priv' entry '%s' "
+ "ignored, bad routine type",
+ mem_check->tname);
+ continue;
+ }
mem_check->privs= fix_rights_for_procedure(mem_check->privs);
if (! mem_check->ok())
delete mem_check;
- else if (my_hash_insert(&proc_priv_hash,(byte*) mem_check))
+ else if (my_hash_insert(hash, (byte*) mem_check))
{
delete mem_check;
grant_option= FALSE;
@@ -3272,7 +3295,7 @@
void grant_reload(THD *thd)
{
- HASH old_column_priv_hash, old_proc_priv_hash;
+ HASH old_column_priv_hash, old_proc_priv_hash, old_func_priv_hash;
bool old_grant_option;
MEM_ROOT old_mem;
DBUG_ENTER("grant_reload");
@@ -3281,6 +3304,7 @@
grant_version++;
old_column_priv_hash= column_priv_hash;
old_proc_priv_hash= proc_priv_hash;
+ old_func_priv_hash= func_priv_hash;
old_grant_option= grant_option;
old_mem= memex;
@@ -3290,6 +3314,7 @@
grant_free(); /* purecov: deadcode */
column_priv_hash= old_column_priv_hash; /* purecov: deadcode */
proc_priv_hash= old_proc_priv_hash;
+ func_priv_hash= old_func_priv_hash;
grant_option= old_grant_option; /* purecov: deadcode */
memex= old_mem; /* purecov: deadcode */
}
@@ -3297,6 +3322,7 @@
{
hash_free(&old_column_priv_hash);
hash_free(&old_proc_priv_hash);
+ hash_free(&old_func_priv_hash);
free_root(&old_mem,MYF(0));
}
rw_unlock(&LOCK_grant);
@@ -3540,13 +3566,14 @@
/****************************************************************************
- Check procedure level grants
+ Check routine level grants
SYNPOSIS
- bool check_grant_procedure()
+ bool check_grant_routine()
thd Thread handler
want_access Bits of privileges user needs to have
- procs List of procedures to check. The user should have 'want_access'
+ procs List of routines to check. The user should have 'want_access'
+ is_proc True if the list is all procedures, else functions
no_errors If 0 then we write an error. The error is sent directly to
the client
@@ -3555,13 +3582,13 @@
1 Error: User did not have the requested privielges
****************************************************************************/
-bool check_grant_procedure(THD *thd, ulong want_access,
- TABLE_LIST *procs, bool no_errors)
+bool check_grant_routine(THD *thd, ulong want_access,
+ TABLE_LIST *procs, bool is_proc, bool no_errors)
{
TABLE_LIST *table;
char *user= thd->priv_user;
char *host= thd->priv_host;
- DBUG_ENTER("check_grant_procedure");
+ DBUG_ENTER("check_grant_routine");
want_access&= ~thd->master_access;
if (!want_access)
@@ -3571,8 +3598,8 @@
for (table= procs; table; table= table->next_global)
{
GRANT_NAME *grant_proc;
- if ((grant_proc= proc_hash_search(host,thd->ip,
- table->db, user, table->table_name, 0)))
+ if ((grant_proc= routine_hash_search(host,thd->ip, table->db, user,
+ table->table_name, is_proc, 0)))
table->grant.privilege|= grant_proc->privs;
if (want_access & ~table->grant.privilege)
@@ -3594,7 +3621,7 @@
if (want_access & EXECUTE_ACL)
command= "execute";
else if (want_access & ALTER_PROC_ACL)
- command= "alter procedure";
+ command= "alter routine";
else if (want_access & GRANT_ACL)
command= "grant";
my_error(ER_PROCACCESS_DENIED_ERROR, MYF(0),
@@ -3606,7 +3633,7 @@
/*
Check if routine has any of the
- procedure level grants
+ routine level grants
SYNPOSIS
bool check_routine_level_acl()
@@ -3619,15 +3646,15 @@
1 error
*/
-bool check_routine_level_acl(THD *thd, const char *db, const char *name)
+bool check_routine_level_acl(THD *thd, const char *db, const char *name, bool is_proc)
{
bool no_routine_acl= 1;
if (grant_option)
{
GRANT_NAME *grant_proc;
rw_rdlock(&LOCK_grant);
- if ((grant_proc= proc_hash_search(thd->priv_host, thd->ip, db,
- thd->priv_user, name, 0)))
+ if ((grant_proc= routine_hash_search(thd->priv_host, thd->ip, db,
+ thd->priv_user, name, is_proc, 0)))
no_routine_acl= !(grant_proc->privs & SHOW_PROC_ACLS);
rw_unlock(&LOCK_grant);
}
@@ -3730,6 +3757,11 @@
};
+static int show_routine_grants(THD *thd, LEX_USER *lex_user, HASH *hash,
+ const char *type, int typelen,
+ char *buff, int buffsize);
+
+
/*
SHOW GRANTS; Send grants for a user to the client
@@ -4076,12 +4108,40 @@
}
}
- /* Add procedure access */
- for (index=0 ; index < proc_priv_hash.records ; index++)
+ if (show_routine_grants(thd, lex_user, &proc_priv_hash,
+ "PROCEDURE", 9, buff, sizeof(buff)))
+ {
+ error= -1;
+ goto end;
+ }
+
+ if (show_routine_grants(thd, lex_user, &func_priv_hash,
+ "FUNCTION", 8, buff, sizeof(buff)))
+ {
+ error= -1;
+ goto end;
+ }
+
+end:
+ VOID(pthread_mutex_unlock(&acl_cache->lock));
+ rw_unlock(&LOCK_grant);
+
+ send_eof(thd);
+ DBUG_RETURN(error);
+}
+
+static int show_routine_grants(THD* thd, LEX_USER *lex_user, HASH *hash,
+ const char *type, int typelen,
+ char *buff, int buffsize)
+{
+ uint counter, index;
+ int error= 0;
+ Protocol *protocol= thd->protocol;
+ /* Add routine access */
+ for (index=0 ; index < hash->records ; index++)
{
const char *user;
- GRANT_NAME *grant_proc= (GRANT_NAME*) hash_element(&proc_priv_hash,
- index);
+ GRANT_NAME *grant_proc= (GRANT_NAME*) hash_element(hash, index);
if (!(user=grant_proc->user))
user= "";
@@ -4093,7 +4153,7 @@
ulong proc_access= grant_proc->privs;
if (proc_access != 0)
{
- String global(buff, sizeof(buff), system_charset_info);
+ String global(buff, buffsize, system_charset_info);
ulong test_access= proc_access & ~GRANT_ACL;
global.length(0);
@@ -4119,6 +4179,8 @@
}
}
global.append(" ON ",4);
+ global.append(type,typelen);
+ global.append(' ');
append_identifier(thd, &global, grant_proc->db,
strlen(grant_proc->db));
global.append('.');
@@ -4143,15 +4205,9 @@
}
}
}
-end:
- VOID(pthread_mutex_unlock(&acl_cache->lock));
- rw_unlock(&LOCK_grant);
-
- send_eof(thd);
- DBUG_RETURN(error);
+ return error;
}
-
/*
Make a clear-text version of the requested privilege.
*/
@@ -4977,7 +5033,7 @@
bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
{
- uint counter, revoked;
+ uint counter, revoked, is_proc;
int result;
ACL_DB *acl_db;
TABLE_LIST tables[GRANT_TABLES];
@@ -5092,12 +5148,12 @@
} while (revoked);
/* Remove procedure access */
- do {
- for (counter= 0, revoked= 0 ; counter < proc_priv_hash.records ; )
+ for (is_proc=0; is_proc<2; is_proc++) do {
+ HASH *hash= is_proc ? &proc_priv_hash : &func_priv_hash;
+ for (counter= 0, revoked= 0 ; counter < hash->records ; )
{
const char *user,*host;
- GRANT_NAME *grant_proc= (GRANT_NAME*) hash_element(&proc_priv_hash,
- counter);
+ GRANT_NAME *grant_proc= (GRANT_NAME*) hash_element(hash, counter);
if (!(user=grant_proc->user))
user= "";
if (!(host=grant_proc->host.hostname))
@@ -5106,9 +5162,10 @@
if (!strcmp(lex_user->user.str,user) &&
!my_strcasecmp(system_charset_info, lex_user->host.str, host))
{
- if (!replace_proc_table(thd,grant_proc,tables[4].table,*lex_user,
+ if (!replace_routine_table(thd,grant_proc,tables[4].table,*lex_user,
grant_proc->db,
grant_proc->tname,
+ is_proc,
~0, 1))
{
revoked= 1;
@@ -5146,11 +5203,12 @@
< 0 Error. Error message not yet sent.
*/
-bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name)
+bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, bool is_proc)
{
uint counter, revoked;
int result;
TABLE_LIST tables[GRANT_TABLES];
+ HASH *hash= is_proc ? &proc_priv_hash : &func_priv_hash;
DBUG_ENTER("sp_revoke_privileges");
if ((result= open_grant_tables(thd, tables)))
@@ -5162,10 +5220,9 @@
/* Remove procedure access */
do
{
- for (counter= 0, revoked= 0 ; counter < proc_priv_hash.records ; )
+ for (counter= 0, revoked= 0 ; counter < hash->records ; )
{
- GRANT_NAME *grant_proc= (GRANT_NAME*) hash_element(&proc_priv_hash,
- counter);
+ GRANT_NAME *grant_proc= (GRANT_NAME*) hash_element(hash, counter);
if (!my_strcasecmp(system_charset_info, grant_proc->db, sp_db) &&
!my_strcasecmp(system_charset_info, grant_proc->tname, sp_name))
{
@@ -5174,8 +5231,8 @@
lex_user.user.length= strlen(grant_proc->user);
lex_user.host.str= grant_proc->host.hostname;
lex_user.host.length= strlen(grant_proc->host.hostname);
- if (!replace_proc_table(thd,grant_proc,tables[4].table,lex_user,
- grant_proc->db, grant_proc->tname, ~0, 1))
+ if (!replace_routine_table(thd,grant_proc,tables[4].table,lex_user,
+ grant_proc->db, grant_proc->tname, is_proc, ~0, 1))
{
revoked= 1;
continue;
@@ -5211,7 +5268,7 @@
< 0 Error. Error message not yet sent.
*/
-bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name)
+bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, bool is_proc)
{
LEX_USER *combo;
TABLE_LIST tables[1];
@@ -5249,7 +5306,7 @@
thd->lex->ssl_type= SSL_TYPE_NOT_SPECIFIED;
bzero((char*) &thd->lex->mqh, sizeof(thd->lex->mqh));
- result= mysql_procedure_grant(thd, tables, user_list,
+ result= mysql_routine_grant(thd, tables, is_proc, user_list,
DEFAULT_CREATE_PROC_ACLS, 0, 1);
DBUG_RETURN(result);
}
--- 1.42/sql/sql_acl.h 2005-03-23 08:42:16 +00:00
+++ 1.43/sql/sql_acl.h 2005-05-15 23:21:16 +01:00
@@ -185,9 +185,9 @@
bool mysql_table_grant(THD *thd, TABLE_LIST *table, List <LEX_USER> &user_list,
List <LEX_COLUMN> &column_list, ulong rights,
bool revoke);
-bool mysql_procedure_grant(THD *thd, TABLE_LIST *table,
- List <LEX_USER> &user_list, ulong rights,
- bool revoke, bool no_error);
+bool mysql_routine_grant(THD *thd, TABLE_LIST *table, bool is_proc,
+ List <LEX_USER> &user_list, ulong rights,
+ bool revoke, bool no_error);
ACL_USER *check_acl_user(LEX_USER *user_name, uint *acl_acl_userdx);
my_bool grant_init(THD *thd);
void grant_free(void);
@@ -200,8 +200,8 @@
bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant,
const char* db_name, const char *table_name,
Field_iterator *fields);
-bool check_grant_procedure(THD *thd, ulong want_access,
- TABLE_LIST *procs, bool no_error);
+bool check_grant_routine(THD *thd, ulong want_access,
+ TABLE_LIST *procs, bool is_proc, bool no_error);
bool check_grant_db(THD *thd,const char *db);
ulong get_table_grant(THD *thd, TABLE_LIST *table);
ulong get_column_grant(THD *thd, GRANT_INFO *grant,
@@ -216,9 +216,12 @@
bool mysql_revoke_all(THD *thd, List <LEX_USER> &list);
void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant,
const char *db, const char *table);
-bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name);
-bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name);
-bool check_routine_level_acl(THD *thd, const char *db, const char *name);
+bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name,
+ bool is_proc);
+bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name,
+ bool is_proc);
+bool check_routine_level_acl(THD *thd, const char *db, const char *name,
+ bool is_proc);
#ifdef NO_EMBEDDED_ACCESS_CHECKS
#define check_grant(A,B,C,D,E,F) 0
--- 1.450/sql/sql_parse.cc 2005-05-11 00:37:38 +01:00
+++ 1.451/sql/sql_parse.cc 2005-05-15 23:21:16 +01:00
@@ -3669,17 +3669,17 @@
}
if (first_table)
{
- if (!lex->columns.elements &&
- sp_exists_routine(thd, all_tables, 1, 1))
+ if (lex->type != 0)
{
uint grants= lex->all_privileges
? (PROC_ACLS & ~GRANT_ACL) | (lex->grant & GRANT_ACL)
: lex->grant;
if (grant_option &&
- check_grant_procedure(thd, grants | GRANT_ACL, all_tables, 0))
+ check_grant_routine(thd, grants | GRANT_ACL, all_tables, lex->type == 1, 0))
goto error;
- res= mysql_procedure_grant(thd, all_tables, lex->users_list,
- grants, lex->sql_command == SQLCOM_REVOKE,0);
+ res= mysql_routine_grant(thd, all_tables, lex->type == 1,
+ lex->users_list, grants,
+ lex->sql_command == SQLCOM_REVOKE, 0);
}
else
{
@@ -3701,7 +3701,7 @@
}
else
{
- if (lex->columns.elements)
+ if (lex->columns.elements || lex->type)
{
my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER(ER_ILLEGAL_GRANT_FOR_TABLE),
MYF(0));
@@ -3983,11 +3983,11 @@
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* only add privileges if really neccessary */
if (sp_automatic_privileges &&
- check_procedure_access(thd, DEFAULT_CREATE_PROC_ACLS,
- db, name, 1))
+ check_routine_access(thd, DEFAULT_CREATE_PROC_ACLS,
+ db, name, lex->sql_command == SQLCOM_CREATE_PROCEDURE, 1))
{
close_thread_tables(thd);
- if (sp_grant_privileges(thd, db, name))
+ if (sp_grant_privileges(thd, db, name, lex->sql_command == SQLCOM_CREATE_PROCEDURE))
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_PROC_AUTO_GRANT_FAIL,
ER(ER_PROC_AUTO_GRANT_FAIL));
@@ -4072,8 +4072,8 @@
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
- if (check_procedure_access(thd, EXECUTE_ACL,
- sp->m_db.str, sp->m_name.str, 0))
+ if (check_routine_access(thd, EXECUTE_ACL,
+ sp->m_db.str, sp->m_name.str, 1, 0))
{
#ifndef EMBEDDED_LIBRARY
thd->net.no_send_ok= nsok;
@@ -4082,8 +4082,8 @@
}
sp_change_security_context(thd, sp, &save_ctx);
if (save_ctx.changed &&
- check_procedure_access(thd, EXECUTE_ACL,
- sp->m_db.str, sp->m_name.str, 0))
+ check_routine_access(thd, EXECUTE_ACL,
+ sp->m_db.str, sp->m_name.str, 1, 0))
{
#ifndef EMBEDDED_LIBRARY
thd->net.no_send_ok= nsok;
@@ -4185,8 +4185,9 @@
}
else
{
- if (check_procedure_access(thd, ALTER_PROC_ACL, sp->m_db.str,
- sp->m_name.str, 0))
+ if (check_routine_access(thd, ALTER_PROC_ACL, sp->m_db.str,
+ sp->m_name.str,
+ lex->sql_command == SQLCOM_ALTER_PROCEDURE, 0))
goto error;
memcpy(&lex->sp_chistics, &chistics, sizeof(lex->sp_chistics));
if (!trust_routine_creators && mysql_bin_log.is_open() &&
@@ -4244,11 +4245,12 @@
{
db= thd->strdup(sp->m_db.str);
name= thd->strdup(sp->m_name.str);
- if (check_procedure_access(thd, ALTER_PROC_ACL, db, name, 0))
+ if (check_routine_access(thd, ALTER_PROC_ACL, db, name,
+ lex->sql_command == SQLCOM_DROP_PROCEDURE, 0))
goto error;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (sp_automatic_privileges &&
- sp_revoke_privileges(thd, db, name))
+ sp_revoke_privileges(thd, db, name, lex->sql_command == SQLCOM_DROP_PROCEDURE))
{
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_PROC_AUTO_REVOKE_FAIL,
@@ -4832,8 +4834,8 @@
bool
-check_procedure_access(THD *thd, ulong want_access,char *db, char *name,
- bool no_errors)
+check_routine_access(THD *thd, ulong want_access,char *db, char *name,
+ bool is_proc, bool no_errors)
{
TABLE_LIST tables[1];
@@ -4849,7 +4851,7 @@
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (grant_option)
- return check_grant_procedure(thd, want_access, tables, no_errors);
+ return check_grant_routine(thd, want_access, tables, is_proc, no_errors);
#endif
return FALSE;
@@ -4870,7 +4872,7 @@
1 error
*/
-bool check_some_routine_access(THD *thd, const char *db, const char *name)
+bool check_some_routine_access(THD *thd, const char *db, const char *name, bool is_proc)
{
ulong save_priv;
if (thd->master_access & SHOW_PROC_ACLS)
@@ -4878,7 +4880,7 @@
if (!check_access(thd, SHOW_PROC_ACLS, db, &save_priv, 0, 1) ||
(save_priv & SHOW_PROC_ACLS))
return FALSE;
- return check_routine_level_acl(thd, db, name);
+ return check_routine_level_acl(thd, db, name, is_proc);
}
--- 1.244/sql/sql_show.cc 2005-05-10 19:35:10 +01:00
+++ 1.245/sql/sql_show.cc 2005-05-15 23:21:16 +01:00
@@ -2599,7 +2599,8 @@
definer= get_field(thd->mem_root, proc_table->field[11]);
if (!full_access)
full_access= !strcmp(sp_user, definer);
- if (!full_access && check_some_routine_access(thd, sp_db, sp_name))
+ if (!full_access && check_some_routine_access(thd, sp_db, sp_name,
+ proc_table->field[2]->val_int() == TYPE_ENUM_PROCEDURE))
return 0;
if (lex->orig_sql_command == SQLCOM_SHOW_STATUS_PROC &&
--- 1.371/sql/sql_yacc.yy 2005-05-09 17:40:16 +01:00
+++ 1.372/sql/sql_yacc.yy 2005-05-15 23:21:16 +01:00
@@ -804,7 +804,7 @@
opt_delete_options opt_delete_option varchar nchar nvarchar
opt_outer table_list table_name opt_option opt_place
opt_attribute opt_attribute_list attribute column_list column_list_id
- opt_column_list grant_privileges opt_table grant_list grant_option
+ opt_column_list grant_privileges grant_ident grant_list grant_option
object_privilege object_privilege_list user_list rename_list
clear_privileges flush_options flush_option
equal optional_braces opt_key_definition key_usage_list2
@@ -7915,9 +7915,36 @@
;
revoke_command:
- grant_privileges ON opt_table FROM grant_list
+ grant_privileges ON opt_table grant_ident FROM grant_list
{
- Lex->sql_command = SQLCOM_REVOKE;
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_REVOKE;
+ lex->type= 0;
+ }
+ |
+ grant_privileges ON FUNCTION_SYM grant_ident FROM grant_list
+ {
+ LEX *lex= Lex;
+ if (lex->columns.elements)
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+ lex->sql_command= SQLCOM_REVOKE;
+ lex->type= 2;
+
+ }
+ |
+ grant_privileges ON PROCEDURE grant_ident FROM grant_list
+ {
+ LEX *lex= Lex;
+ if (lex->columns.elements)
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+ lex->sql_command= SQLCOM_REVOKE;
+ lex->type= 1;
}
|
ALL opt_privileges ',' GRANT OPTION FROM grant_list
@@ -7927,11 +7954,50 @@
;
grant:
- GRANT clear_privileges grant_privileges ON opt_table TO_SYM grant_list
+ GRANT clear_privileges grant_command
+ {}
+ ;
+
+grant_command:
+ grant_privileges ON opt_table grant_ident TO_SYM grant_list
require_clause grant_options
- { Lex->sql_command= SQLCOM_GRANT; }
- ;
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_GRANT;
+ lex->type= 0;
+ }
+ |
+ grant_privileges ON FUNCTION_SYM grant_ident TO_SYM grant_list
+ require_clause grant_options
+ {
+ LEX *lex= Lex;
+ if (lex->columns.elements)
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+ lex->sql_command= SQLCOM_GRANT;
+ lex->type= 2;
+ }
+ |
+ grant_privileges ON PROCEDURE grant_ident TO_SYM grant_list
+ require_clause grant_options
+ {
+ LEX *lex= Lex;
+ if (lex->columns.elements)
+ {
+ yyerror(ER(ER_SYNTAX_ERROR));
+ YYABORT;
+ }
+ lex->sql_command= SQLCOM_GRANT;
+ lex->type= 1;
+ }
+ ;
+opt_table:
+ /* Empty */
+ | TABLE_SYM ;
+
grant_privileges:
object_privilege_list { }
| ALL opt_privileges
@@ -8024,7 +8090,7 @@
}
;
-opt_table:
+grant_ident:
'*'
{
LEX *lex= Lex;
--- 1.311/BitKeeper/etc/logging_ok 2005-05-13 12:21:44 +01:00
+++ 1.312/BitKeeper/etc/logging_ok 2005-05-15 23:21:36 +01:00
@@ -18,6 +18,7 @@
antony@stripped
antony@stripped
antony@stripped
+antony@stripped
arjen@stripped
arjen@stripped
arjen@stripped
--- 1.25/scripts/mysql_fix_privilege_tables.sql 2005-05-02 18:25:45 +01:00
+++ 1.26/scripts/mysql_fix_privilege_tables.sql 2005-05-15 23:21:15 +01:00
@@ -67,6 +67,10 @@
ALTER TABLE procs_priv ENGINE=MyISAM, CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;
ALTER TABLE procs_priv
modify Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL;
+ALTER TABLE procs_priv
+ add Routine_type enum('PROCEDURE','FUNCTION') COLLATE utf8_general_ci NOT NULL AFTER Routine_name;
+ALTER TABLE procs_priv
+ modify Timestamp timestamp(14) AFTER Proc_priv;
CREATE TABLE IF NOT EXISTS columns_priv (
Host char(60) DEFAULT '' NOT NULL,
@@ -316,10 +320,11 @@
Db char(64) binary DEFAULT '' NOT NULL,
User char(16) binary DEFAULT '' NOT NULL,
Routine_name char(64) binary DEFAULT '' NOT NULL,
+Routine_type enum("PROCEDURE","FUNCTION") NOT NULL,
Grantor char(77) DEFAULT '' NOT NULL,
-Timestamp timestamp(14),
Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL,
-PRIMARY KEY (Host,Db,User,Routine_name),
+Timestamp timestamp(14),
+PRIMARY KEY (Host,Db,User,Routine_name,Routine_type),
KEY Grantor (Grantor)
) CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges';
--- 1.12/mysql-test/r/sp-security.result 2004-12-31 16:57:44 +00:00
+++ 1.13/mysql-test/r/sp-security.result 2005-05-15 23:21:15 +01:00
@@ -23,10 +23,10 @@
select db();
db()
db1_secret
-grant execute on db1_secret.stamp to user1@'%';
-grant execute on db1_secret.db to user1@'%';
-grant execute on db1_secret.stamp to ''@'%';
-grant execute on db1_secret.db to ''@'%';
+grant execute on procedure db1_secret.stamp to user1@'%';
+grant execute on function db1_secret.db to user1@'%';
+grant execute on procedure db1_secret.stamp to ''@'%';
+grant execute on function db1_secret.db to ''@'%';
call db1_secret.stamp(2);
select db1_secret.db();
db1_secret.db()
@@ -105,8 +105,8 @@
s1
0
2
-grant usage on db2.q to user2@localhost with grant option;
-grant execute on db2.q to user1@localhost;
+grant usage on procedure db2.q to user2@localhost with grant option;
+grant execute on procedure db2.q to user1@localhost;
use db2;
call q();
select * from t2;
@@ -117,9 +117,9 @@
alter procedure p modifies sql data;
drop procedure p;
alter procedure q modifies sql data;
-ERROR 42000: alter procedure command denied to user 'user1'@'localhost' for routine 'db2.q'
+ERROR 42000: alter routine command denied to user 'user1'@'localhost' for routine 'db2.q'
drop procedure q;
-ERROR 42000: alter procedure command denied to user 'user1'@'localhost' for routine 'db2.q'
+ERROR 42000: alter routine command denied to user 'user1'@'localhost' for routine 'db2.q'
use db2;
alter procedure q modifies sql data;
drop procedure q;
@@ -141,52 +141,52 @@
create table t1 ( u varchar(64), i int );
create procedure sptest.p1(i int) insert into test.t1 values (user(), i);
grant insert on t1 to usera@localhost;
-grant execute on sptest.p1 to usera@localhost;
+grant execute on procedure sptest.p1 to usera@localhost;
show grants for usera@localhost;
Grants for usera@localhost
GRANT USAGE ON *.* TO 'usera'@'localhost'
GRANT INSERT ON `test`.`t1` TO 'usera'@'localhost'
-GRANT EXECUTE ON `sptest`.`p1` TO 'usera'@'localhost'
-grant execute on sptest.p1 to userc@localhost with grant option;
+GRANT EXECUTE ON PROCEDURE `sptest`.`p1` TO 'usera'@'localhost'
+grant execute on procedure sptest.p1 to userc@localhost with grant option;
show grants for userc@localhost;
Grants for userc@localhost
GRANT USAGE ON *.* TO 'userc'@'localhost'
-GRANT EXECUTE ON `sptest`.`p1` TO 'userc'@'localhost' WITH GRANT OPTION
+GRANT EXECUTE ON PROCEDURE `sptest`.`p1` TO 'userc'@'localhost' WITH GRANT OPTION
call sptest.p1(1);
-grant execute on sptest.p1 to userb@localhost;
+grant execute on procedure sptest.p1 to userb@localhost;
ERROR 42000: grant command denied to user 'usera'@'localhost' for routine 'sptest.p1'
drop procedure sptest.p1;
-ERROR 42000: alter procedure command denied to user 'usera'@'localhost' for routine 'sptest.p1'
+ERROR 42000: alter routine command denied to user 'usera'@'localhost' for routine 'sptest.p1'
call sptest.p1(2);
ERROR 42000: execute command denied to user 'userb'@'localhost' for routine 'sptest.p1'
-grant execute on sptest.p1 to userb@localhost;
+grant execute on procedure sptest.p1 to userb@localhost;
ERROR 42000: execute command denied to user 'userb'@'localhost' for routine 'sptest.p1'
drop procedure sptest.p1;
-ERROR 42000: alter procedure command denied to user 'userb'@'localhost' for routine 'sptest.p1'
+ERROR 42000: alter routine command denied to user 'userb'@'localhost' for routine 'sptest.p1'
call sptest.p1(3);
-grant execute on sptest.p1 to userb@localhost;
+grant execute on procedure sptest.p1 to userb@localhost;
drop procedure sptest.p1;
-ERROR 42000: alter procedure command denied to user 'userc'@'localhost' for routine 'sptest.p1'
+ERROR 42000: alter routine command denied to user 'userc'@'localhost' for routine 'sptest.p1'
call sptest.p1(4);
-grant execute on sptest.p1 to userb@localhost;
+grant execute on procedure sptest.p1 to userb@localhost;
ERROR 42000: grant command denied to user 'userb'@'localhost' for routine 'sptest.p1'
drop procedure sptest.p1;
-ERROR 42000: alter procedure command denied to user 'userb'@'localhost' for routine 'sptest.p1'
+ERROR 42000: alter routine command denied to user 'userb'@'localhost' for routine 'sptest.p1'
select * from t1;
u i
usera@localhost 1
userc@localhost 3
userb@localhost 4
-grant all privileges on sptest.p1 to userc@localhost;
+grant all privileges on procedure sptest.p1 to userc@localhost;
show grants for userc@localhost;
Grants for userc@localhost
GRANT USAGE ON *.* TO 'userc'@'localhost'
-GRANT EXECUTE, ALTER ROUTINE ON `sptest`.`p1` TO 'userc'@'localhost' WITH GRANT OPTION
+GRANT EXECUTE, ALTER ROUTINE ON PROCEDURE `sptest`.`p1` TO 'userc'@'localhost' WITH GRANT OPTION
show grants for userb@localhost;
Grants for userb@localhost
GRANT USAGE ON *.* TO 'userb'@'localhost'
-GRANT EXECUTE ON `sptest`.`p1` TO 'userb'@'localhost'
-revoke all privileges on sptest.p1 from userb@localhost;
+GRANT EXECUTE ON PROCEDURE `sptest`.`p1` TO 'userb'@'localhost'
+revoke all privileges on procedure sptest.p1 from userb@localhost;
show grants for userb@localhost;
Grants for userb@localhost
GRANT USAGE ON *.* TO 'userb'@'localhost'
--- 1.14/mysql-test/t/sp-security.test 2005-04-04 20:43:55 +01:00
+++ 1.15/mysql-test/t/sp-security.test 2005-05-15 23:21:15 +01:00
@@ -43,10 +43,10 @@
select * from t1;
select db();
-grant execute on db1_secret.stamp to user1@'%';
-grant execute on db1_secret.db to user1@'%';
-grant execute on db1_secret.stamp to ''@'%';
-grant execute on db1_secret.db to ''@'%';
+grant execute on procedure db1_secret.stamp to user1@'%';
+grant execute on function db1_secret.db to user1@'%';
+grant execute on procedure db1_secret.stamp to ''@'%';
+grant execute on function db1_secret.db to ''@'%';
connect (con2user1,localhost,user1,,);
connect (con3anon,localhost,anon,,);
@@ -183,10 +183,10 @@
select * from t2;
connection con1root;
-grant usage on db2.q to user2@localhost with grant option;
+grant usage on procedure db2.q to user2@localhost with grant option;
connection con4user2;
-grant execute on db2.q to user1@localhost;
+grant execute on procedure db2.q to user1@localhost;
connection con2user1;
use db2;
@@ -245,9 +245,9 @@
create table t1 ( u varchar(64), i int );
create procedure sptest.p1(i int) insert into test.t1 values (user(), i);
grant insert on t1 to usera@localhost;
-grant execute on sptest.p1 to usera@localhost;
+grant execute on procedure sptest.p1 to usera@localhost;
show grants for usera@localhost;
-grant execute on sptest.p1 to userc@localhost with grant option;
+grant execute on procedure sptest.p1 to userc@localhost with grant option;
show grants for userc@localhost;
connect (con2usera,localhost,usera,,);
@@ -257,7 +257,7 @@
connection con2usera;
call sptest.p1(1);
--error 1370
-grant execute on sptest.p1 to userb@localhost;
+grant execute on procedure sptest.p1 to userb@localhost;
--error 1370
drop procedure sptest.p1;
@@ -265,32 +265,32 @@
--error 1370
call sptest.p1(2);
--error 1370
-grant execute on sptest.p1 to userb@localhost;
+grant execute on procedure sptest.p1 to userb@localhost;
--error 1370
drop procedure sptest.p1;
connection con4userc;
call sptest.p1(3);
-grant execute on sptest.p1 to userb@localhost;
+grant execute on procedure sptest.p1 to userb@localhost;
--error 1370
drop procedure sptest.p1;
connection con3userb;
call sptest.p1(4);
--error 1370
-grant execute on sptest.p1 to userb@localhost;
+grant execute on procedure sptest.p1 to userb@localhost;
--error 1370
drop procedure sptest.p1;
connection con1root;
select * from t1;
-grant all privileges on sptest.p1 to userc@localhost;
+grant all privileges on procedure sptest.p1 to userc@localhost;
show grants for userc@localhost;
show grants for userb@localhost;
connection con4userc;
-revoke all privileges on sptest.p1 from userb@localhost;
+revoke all privileges on procedure sptest.p1 from userb@localhost;
connection con1root;
show grants for userb@localhost;
--- 1.133/sql/sp_head.cc 2005-05-09 00:01:23 +01:00
+++ 1.134/sql/sp_head.cc 2005-05-15 23:21:15 +01:00
@@ -1111,7 +1111,7 @@
(!strcmp(sp->m_definer_user.str, thd->priv_user) &&
!strcmp(sp->m_definer_host.str, thd->priv_host)));
if (!*full_access)
- return check_some_routine_access(thd, sp->m_db.str, sp->m_name.str);
+ return check_some_routine_access(thd, sp->m_db.str, sp->m_name.str, sp->m_type == TYPE_ENUM_PROCEDURE);
return 0;
}
--- 1.21/mysql-test/r/system_mysql_db.result 2005-05-02 18:25:45 +01:00
+++ 1.22/mysql-test/r/system_mysql_db.result 2005-05-15 23:21:15 +01:00
@@ -152,10 +152,11 @@
`Db` char(64) collate utf8_bin NOT NULL default '',
`User` char(16) collate utf8_bin NOT NULL default '',
`Routine_name` char(64) collate utf8_bin NOT NULL default '',
+ `Routine_type` enum('PROCEDURE','FUNCTION') collate utf8_bin NOT NULL default 'PROCEDURE',
`Grantor` char(77) collate utf8_bin NOT NULL default '',
- `Timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
`Proc_priv` set('Execute','Alter Routine','Grant') character set utf8 NOT NULL default '',
- PRIMARY KEY (`Host`,`Db`,`User`,`Routine_name`),
+ `Timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
+ PRIMARY KEY (`Host`,`Db`,`User`,`Routine_name`,`Routine_type`),
KEY `Grantor` (`Grantor`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Procedure privileges'
show create table proc;
--- 1.22/scripts/mysql_create_system_tables.sh 2005-05-02 18:25:45 +01:00
+++ 1.23/scripts/mysql_create_system_tables.sh 2005-05-15 23:21:15 +01:00
@@ -255,10 +255,11 @@
c_pp="$c_pp Db char(64) binary DEFAULT '' NOT NULL,"
c_pp="$c_pp User char(16) binary DEFAULT '' NOT NULL,"
c_pp="$c_pp Routine_name char(64) binary DEFAULT '' NOT NULL,"
+ c_pp="$c_pp Routine_type enum('PROCEDURE','FUNCTION') NOT NULL,"
c_pp="$c_pp Grantor char(77) DEFAULT '' NOT NULL,"
- c_pp="$c_pp Timestamp timestamp(14),"
c_pp="$c_pp Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL,"
- c_pp="$c_pp PRIMARY KEY (Host,Db,User,Routine_name),"
+ c_pp="$c_pp Timestamp timestamp(14),"
+ c_pp="$c_pp PRIMARY KEY (Host,Db,User,Routine_name,Routine_type),"
c_pp="$c_pp KEY Grantor (Grantor)"
c_pp="$c_pp ) engine=MyISAM"
c_pp="$c_pp CHARACTER SET utf8 COLLATE utf8_bin"
| Thread |
|---|
| • bk commit into 5.0 tree (antony:1.1947) BUG#10246 | antony | 16 May |