diff options
36 files changed, 600 insertions, 32 deletions
diff --git a/include/mysqld_error.h b/include/mysqld_error.h index 4031d64602f..196e4cd5154 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -327,4 +327,5 @@ #define ER_SP_DUP_VAR 1308 #define ER_SP_DUP_COND 1309 #define ER_SP_DUP_CURS 1310 -#define ER_ERROR_MESSAGES 311 +#define ER_SP_CANT_ALTER 1311 +#define ER_ERROR_MESSAGES 312 diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 82da4e0cb2e..58905a74507 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -187,6 +187,11 @@ end; call p(); ERROR HY000: Cursor is not open drop procedure p; +alter procedure bar3 SECURITY INVOKER; +ERROR HY000: PROCEDURE bar3 does not exist +alter procedure bar3 name +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; +ERROR 42000: Identifier name 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' is too long drop table t1; drop table if exists t1; create table t1 (val int, x float); diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 4f66dafbe81..990a8b7c2da 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -734,6 +734,9 @@ n f 19 121645100408832000 20 2432902008176640000 drop table fac; +show function status like '%f%'; +Name Type Creator Modified Created Suid Comment +fac function root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 Y drop procedure ifac; drop function fac; drop table if exists primes; @@ -794,6 +797,38 @@ set p = p+2; end; end while; end; +show create procedure opp; +Procedure Create Procedure +opp create procedure opp(n bigint unsigned, out pp bool) +begin +declare r double; +declare b, s bigint unsigned default 0; +set r = sqrt(n); +again: +loop +if s = 45 then +set b = b+200, s = 0; +else +begin +declare p bigint unsigned; +select t.p into p from test.primes t where t.i = s; +if b+p > r then +set pp = 1; +leave again; +end if; +if mod(n, b+p) = 0 then +set pp = 0; +leave again; +end if; +set s = s+1; +end; +end if; +end loop; +end +show procedure status like '%p%'; +Name Type Creator Modified Created Suid Comment +ip procedure root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 Y +opp procedure root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 Y call ip(200); select * from primes where i=45 or i=100 or i=199; i p @@ -803,5 +838,22 @@ i p drop table primes; drop procedure opp; drop procedure ip; +create procedure bar(x char(16), y int) +comment "111111111111" SECURITY INVOKER +insert into test.t1 values (x, y); +show procedure status like 'bar'; +Name Type Creator Modified Created Suid Comment +bar procedure root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 N 111111111111 +alter procedure bar name bar2 comment "2222222222" SECURITY DEFINER; +alter procedure bar2 name bar comment "3333333333"; +alter procedure bar; +show create procedure bar; +Procedure Create Procedure +bar create procedure bar(x char(16), y int) +comment "111111111111" SECURITY INVOKER +insert into test.t1 values (x, y) +show procedure status like 'bar'; +Name Type Creator Modified Created Suid Comment +bar procedure root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 Y 3333333333 drop table t1; drop table t2; diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index d98385b42e0..38f5a34a7bb 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -256,6 +256,12 @@ end| call p()| drop procedure p| +--error 1282 +alter procedure bar3 SECURITY INVOKER| +--error 1059 +alter procedure bar3 name +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA| + drop table t1| --disable_warnings diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index b9f62d4fb0a..5b2c9bf18f5 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -852,6 +852,8 @@ end| call ifac(20)| select * from fac| drop table fac| +--replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00' +show function status like '%f%'| drop procedure ifac| drop function fac| @@ -928,6 +930,9 @@ begin end; end while; end| +show create procedure opp| +--replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00' +show procedure status like '%p%'| # This isn't the fastest way in the world to compute prime numbers, so # don't be too ambitious. ;-) @@ -939,6 +944,19 @@ drop table primes| drop procedure opp| drop procedure ip| +# Comment & suid +create procedure bar(x char(16), y int) + comment "111111111111" SECURITY INVOKER + insert into test.t1 values (x, y)| +--replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00' +show procedure status like 'bar'| +alter procedure bar name bar2 comment "2222222222" SECURITY DEFINER| +alter procedure bar2 name bar comment "3333333333"| +alter procedure bar| +show create procedure bar| +--replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00' +show procedure status like 'bar'| + delimiter ;| drop table t1; drop table t2; diff --git a/sql/lex.h b/sql/lex.h index f4368cacb5d..b267cdda66a 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -130,6 +130,7 @@ static SYMBOL symbols[] = { { "DECLARE", SYM(DECLARE_SYM),0,0}, { "DES_KEY_FILE", SYM(DES_KEY_FILE),0,0}, { "DEFAULT", SYM(DEFAULT),0,0}, + { "DEFINER", SYM(DEFINER),0,0}, { "DELAYED", SYM(DELAYED_SYM),0,0}, { "DELAY_KEY_WRITE", SYM(DELAY_KEY_WRITE_SYM),0,0}, { "DELETE", SYM(DELETE_SYM),0,0}, @@ -232,6 +233,7 @@ static SYMBOL symbols[] = { { "ISOLATION", SYM(ISOLATION),0,0}, { "ISSUER", SYM(ISSUER_SYM),0,0}, { "ITERATE", SYM(ITERATE_SYM),0,0}, + { "INVOKER", SYM(INVOKER),0,0}, { "JOIN", SYM(JOIN_SYM),0,0}, { "KEY", SYM(KEY_SYM),0,0}, { "KEYS", SYM(KEYS),0,0}, @@ -295,6 +297,7 @@ static SYMBOL symbols[] = { { "MULTILINESTRING", SYM(MULTILINESTRING),0,0}, { "MULTIPOINT", SYM(MULTIPOINT),0,0}, { "MULTIPOLYGON", SYM(MULTIPOLYGON),0,0}, + { "NAME", SYM(NAME_SYM),0,0}, { "NAMES", SYM(NAMES_SYM),0,0}, { "NATURAL", SYM(NATURAL),0,0}, { "NATIONAL", SYM(NATIONAL_SYM),0,0}, @@ -367,6 +370,7 @@ static SYMBOL symbols[] = { { "SAVEPOINT", SYM(SAVEPOINT_SYM),0,0}, { "SECOND", SYM(SECOND_SYM),0,0}, { "SECOND_MICROSECOND", SYM(SECOND_MICROSECOND_SYM),0,0}, + { "SECURITY", SYM(SECURITY),0,0}, { "SEPARATOR", SYM(SEPARATOR_SYM),0,0}, { "SELECT", SYM(SELECT_SYM),0,0}, { "SENSITIVE", SYM(SENSITIVE_SYM),0,0}, diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index abad832511f..56a99100a79 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -323,3 +323,4 @@ character-set=latin2 "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index f3ee18e586f..cc3f0ef1fff 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -317,3 +317,4 @@ character-set=latin1 "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index df1445d3758..e8f8a396f60 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -325,3 +325,4 @@ character-set=latin1 "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index c38969b778c..82e6a3e17ef 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -314,3 +314,4 @@ character-set=latin1 "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 885e9cd5c11..b61d44a940b 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -319,3 +319,4 @@ character-set=latin7 "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index acb003fb8a4..c77f93548fe 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -314,3 +314,4 @@ character-set=latin1 "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 855db0ee094..fc7866ef5f0 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -326,3 +326,4 @@ character-set=latin1 "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index 60e3adf5aae..8fc2f6ed574 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -314,3 +314,4 @@ character-set=greek "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index aef2808cdd2..74ad4ce490f 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -316,3 +316,4 @@ character-set=latin2 "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 429909cfa08..fc8ceedcad9 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -314,3 +314,4 @@ character-set=latin1 "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 1f7e4b4c103..5693caae10a 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -316,3 +316,4 @@ character-set=ujis "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index ba2ab18f1f5..cc2a774374f 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -314,3 +314,4 @@ character-set=euckr "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index a72f78540f2..faed3c53ec2 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -316,3 +316,4 @@ character-set=latin1 "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 8dbef326260..f2474e7924f 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -316,3 +316,4 @@ character-set=latin1 "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index 60d7b4d83cf..a86855291df 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -318,3 +318,4 @@ character-set=latin2 "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index 95f959c4a18..86146dddaaa 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -315,3 +315,4 @@ character-set=latin1 "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 976a897eb39..7648c0d224d 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -318,3 +318,4 @@ character-set=latin2 "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index a446d69cd12..8d6c56bb9b6 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -316,3 +316,4 @@ character-set=koi8r "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index bd44ade9b72..fe735ff8374 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -309,3 +309,4 @@ character-set=cp1250 "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 85bbced043b..4310239f772 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -322,3 +322,4 @@ character-set=latin2 "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index ae76b53b130..05f5f8d7a71 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -316,3 +316,4 @@ character-set=latin1 "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 5282e9e1fab..c41dfd9b268 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -314,3 +314,4 @@ character-set=latin1 "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 2059e1f1cea..dee93450ccf 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -319,3 +319,4 @@ character-set=koi8u "Duplicate variable: %s" "Duplicate condition: %s" "Duplicate cursor: %s" +"Failed to ALTER %s %s" diff --git a/sql/sp.cc b/sql/sp.cc index 6ca020b5eaa..bf8cf37f293 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -230,8 +230,8 @@ db_create_routine(THD *thd, int type, (uint)strlen(creator), system_charset_info); ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_CREATED])->set_time(); - if (suid) - table->field[MYSQL_PROC_FIELD_SUID]->store((longlong)suid); + if (!suid) + table->field[MYSQL_PROC_FIELD_SUID]->store((longlong) 1); if (comment) table->field[MYSQL_PROC_FIELD_COMMENT]->store(comment, commentlen, system_charset_info); @@ -268,6 +268,182 @@ db_drop_routine(THD *thd, int type, char *name, uint namelen) DBUG_RETURN(ret); } +static int +db_update_routine(THD *thd, int type, char *name, uint namelen, + char *newname, uint newnamelen, + char *comment, uint commentlen, enum suid_behaviour suid) +{ + DBUG_ENTER("db_update_routine"); + DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name)); + TABLE *table; + int ret; + bool opened; + + ret= db_find_routine_aux(thd, type, name, namelen, TL_WRITE, &table, &opened); + if (ret == SP_OK) + { + store_record(table,record[1]); + ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time(); + if (suid) + table->field[MYSQL_PROC_FIELD_SUID]->store((longlong) suid); + if (newname) + table->field[MYSQL_PROC_FIELD_NAME]->store(newname, + newnamelen, + system_charset_info); + if (comment) + table->field[MYSQL_PROC_FIELD_COMMENT]->store(comment, + commentlen, + system_charset_info); + if ((table->file->update_row(table->record[1],table->record[0]))) + ret= SP_WRITE_ROW_FAILED; + } + if (opened) + close_thread_tables(thd); + DBUG_RETURN(ret); +} + +struct st_used_field +{ + const char *field_name; + uint field_length; + enum enum_field_types field_type; + Field *field; +}; + +static struct st_used_field init_fields[]= +{ + { "Name", NAME_LEN, MYSQL_TYPE_STRING, 0}, + { "Type", 9, MYSQL_TYPE_STRING, 0}, + { "Creator", 77, MYSQL_TYPE_STRING, 0}, + { "Modified", 0, MYSQL_TYPE_TIMESTAMP, 0}, + { "Created", 0, MYSQL_TYPE_TIMESTAMP, 0}, + { "Suid", 1, MYSQL_TYPE_STRING, 0}, + { "Comment", NAME_LEN, MYSQL_TYPE_STRING, 0}, + { 0, 0, MYSQL_TYPE_STRING, 0} +}; + +int print_field_values(THD *thd, TABLE *table, + struct st_used_field *used_fields, + int type, const char *wild) +{ + Protocol *protocol= thd->protocol; + + if (table->field[MYSQL_PROC_FIELD_TYPE]->val_int() == type) + { + String *tmp_string= new String(); + struct st_used_field *used_field= used_fields; + get_field(&thd->mem_root, + used_field->field, + tmp_string); + if (!wild || !wild[0] || !wild_compare(tmp_string->ptr(), wild, 0)) + { + protocol->prepare_for_resend(); + protocol->store(tmp_string); + for (used_field++; + used_field->field_name; + used_field++) + { + switch (used_field->field_type) { + case MYSQL_TYPE_TIMESTAMP: + { + TIME tmp_time; + ((Field_timestamp *) used_field->field)->get_time(&tmp_time); + protocol->store(&tmp_time); + } + break; + default: + { + String *tmp_string1= new String(); + get_field(&thd->mem_root, used_field->field, tmp_string1); + protocol->store(tmp_string1); + } + break; + } + } + if (protocol->write()) + return 1; + } + } + return 0; +} + +int +db_show_routine_status(THD *thd, int type, const char *wild) +{ + DBUG_ENTER("db_show_routine_status"); + + TABLE *table; + TABLE_LIST tables; + + memset(&tables, 0, sizeof(tables)); + tables.db= (char*)"mysql"; + tables.real_name= tables.alias= (char*)"proc"; + + if (! (table= open_ltable(thd, &tables, TL_READ))) + { + DBUG_RETURN(1); + } + else + { + Item *item; + List<Item> field_list; + struct st_used_field *used_field; + st_used_field used_fields[array_elements(init_fields)]; + memcpy((char*) used_fields, (char*) init_fields, sizeof(used_fields)); + /* Init header */ + for (used_field= &used_fields[0]; + used_field->field_name; + used_field++) + { + switch (used_field->field_type) { + case MYSQL_TYPE_TIMESTAMP: + field_list.push_back(item=new Item_datetime(used_field->field_name)); + break; + default: + field_list.push_back(item=new Item_empty_string(used_field->field_name, + used_field-> + field_length)); + break; + } + } + /* Print header */ + if (thd->protocol->send_fields(&field_list,1)) + goto err_case; + + /* Init fields */ + setup_tables(&tables); + for (used_field= &used_fields[0]; + used_field->field_name; + used_field++) + { + TABLE_LIST *not_used; + Item_field *field= new Item_field("mysql", "proc", + used_field->field_name); + if (!(used_field->field= find_field_in_tables(thd, field, &tables, + ¬_used, TRUE))) + goto err_case1; + } + + table->file->index_init(0); + table->file->index_first(table->record[0]); + if (print_field_values(thd, table, used_fields, type, wild)) + goto err_case1; + while (!table->file->index_next(table->record[0])) + { + if (print_field_values(thd, table, used_fields, type, wild)) + goto err_case1; + } + send_eof(thd); + close_thread_tables(thd); + DBUG_RETURN(0); + } +err_case1: + send_eof(thd); +err_case: + close_thread_tables(thd); + DBUG_RETURN(1); +} + /* * @@ -326,6 +502,46 @@ sp_drop_procedure(THD *thd, char *name, uint namelen) DBUG_RETURN(ret); } +int +sp_update_procedure(THD *thd, char *name, uint namelen, + char *newname, uint newnamelen, + char *comment, uint commentlen, enum suid_behaviour suid) +{ + DBUG_ENTER("sp_update_procedure"); + DBUG_PRINT("enter", ("name: %*s", namelen, name)); + sp_head *sp; + int ret; + + sp= sp_cache_remove(&thd->sp_proc_cache, name, namelen); + if (sp) + delete sp; + ret= db_update_routine(thd, TYPE_ENUM_PROCEDURE, name, namelen, + newname, newnamelen, + comment, commentlen, suid); + + DBUG_RETURN(ret); +} + +int +sp_show_create_procedure(THD *thd, LEX_STRING *name) +{ + DBUG_ENTER("sp_show_create_procedure"); + DBUG_PRINT("enter", ("name: %*s", name->length, name->str)); + sp_head *sp; + + sp= sp_find_procedure(thd, name); + if (sp) + DBUG_RETURN(sp->show_create_procedure(thd)); + + DBUG_RETURN(1); +} + +int +db_show_status_procedure(THD *thd, const char *wild) +{ + DBUG_ENTER("db_show_status_procedure"); + DBUG_RETURN(db_show_routine_status(thd, TYPE_ENUM_PROCEDURE, wild)); +} /* * @@ -381,6 +597,47 @@ sp_drop_function(THD *thd, char *name, uint namelen) DBUG_RETURN(ret); } +int +sp_update_function(THD *thd, char *name, uint namelen, + char *newname, uint newnamelen, + char *comment, uint commentlen, enum suid_behaviour suid) +{ + DBUG_ENTER("sp_update_procedure"); + DBUG_PRINT("enter", ("name: %*s", namelen, name)); + sp_head *sp; + int ret; + + sp= sp_cache_remove(&thd->sp_func_cache, name, namelen); + if (sp) + delete sp; + ret= db_update_routine(thd, TYPE_ENUM_FUNCTION, name, namelen, + newname, newnamelen, + comment, commentlen, suid); + + DBUG_RETURN(ret); +} + +int +sp_show_create_function(THD *thd, LEX_STRING *name) +{ + DBUG_ENTER("sp_show_create_function"); + DBUG_PRINT("enter", ("name: %*s", name->length, name->str)); + sp_head *sp; + + sp= sp_find_function(thd, name); + if (sp) + DBUG_RETURN(sp->show_create_function(thd)); + + DBUG_RETURN(1); +} + +int +db_show_status_function(THD *thd, const char *wild) +{ + DBUG_ENTER("db_show_status_function"); + DBUG_RETURN(db_show_routine_status(thd, TYPE_ENUM_FUNCTION, wild)); +} + // QQ Temporary until the function call detection in sql_lex has been reworked. bool sp_function_exists(THD *thd, LEX_STRING *name) @@ -38,6 +38,17 @@ int sp_drop_procedure(THD *thd, char *name, uint namelen); +int +sp_update_procedure(THD *thd, char *name, uint namelen, + char *newname, uint newnamelen, + char *comment, uint commentlen, enum suid_behaviour suid); + +int +sp_show_create_procedure(THD *thd, LEX_STRING *name); + +int +db_show_status_procedure(THD *thd, const char *wild); + sp_head * sp_find_function(THD *thd, LEX_STRING *name); @@ -48,6 +59,17 @@ sp_create_function(THD *thd, char *name, uint namelen, char *def, uint deflen, int sp_drop_function(THD *thd, char *name, uint namelen); +int +sp_update_function(THD *thd, char *name, uint namelen, + char *newname, uint newnamelen, + char *comment, uint commentlen, enum suid_behaviour suid); + +int +sp_show_create_function(THD *thd, LEX_STRING *name); + +int +db_show_status_function(THD *thd, const char *wild); + // QQ Temporary until the function call detection in sql_lex has been reworked. bool sp_function_exists(THD *thd, LEX_STRING *name); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 88bd299ccd5..626addf08b0 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -131,7 +131,7 @@ sp_head::sp_head() } void -sp_head::init(LEX_STRING *name, LEX *lex, LEX_STRING *comment, char suid) +sp_head::init(LEX_STRING *name, LEX *lex) { DBUG_ENTER("sp_head::init"); const char *dstr = (const char*)lex->buf; @@ -141,16 +141,6 @@ sp_head::init(LEX_STRING *name, LEX *lex, LEX_STRING *comment, char suid) m_name.str= lex->thd->strmake(name->str, name->length); m_defstr.length= lex->end_of_query - lex->buf; m_defstr.str= lex->thd->strmake(dstr, m_defstr.length); - - m_comment.length= 0; - m_comment.str= 0; - if (comment) - { - m_comment.length= comment->length; - m_comment.str= comment->str; - } - - m_suid= suid; lex->spcont= m_pcont= new sp_pcontext(); my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8); DBUG_VOID_RETURN; @@ -605,7 +595,56 @@ sp_head::backpatch(sp_label_t *lab) } } +int +sp_head::show_create_procedure(THD *thd) +{ + Protocol *protocol= thd->protocol; + char buff[2048]; + String buffer(buff, sizeof(buff), system_charset_info); + int res; + List<Item> field_list; + + DBUG_ENTER("sp_head::show_create_procedure"); + DBUG_PRINT("info", ("procedure %s", m_name.str)); + + field_list.push_back(new Item_empty_string("Procedure",NAME_LEN)); + // 1024 is for not to confuse old clients + field_list.push_back(new Item_empty_string("Create Procedure", + max(buffer.length(),1024))); + if (protocol->send_fields(&field_list, 1)) + DBUG_RETURN(1); + protocol->prepare_for_resend(); + protocol->store(m_name.str, m_name.length, system_charset_info); + protocol->store(m_defstr.str, m_defstr.length, system_charset_info); + res= protocol->write(); + send_eof(thd); + DBUG_RETURN(res); +} + +int +sp_head::show_create_function(THD *thd) +{ + Protocol *protocol= thd->protocol; + char buff[2048]; + String buffer(buff, sizeof(buff), system_charset_info); + int res; + List<Item> field_list; + + DBUG_ENTER("sp_head::show_create_function"); + DBUG_PRINT("info", ("procedure %s", m_name.str)); + field_list.push_back(new Item_empty_string("Function",NAME_LEN)); + field_list.push_back(new Item_empty_string("Create Function", + max(buffer.length(),1024))); + if (protocol->send_fields(&field_list, 1)) + DBUG_RETURN(1); + protocol->prepare_for_resend(); + protocol->store(m_name.str, m_name.length, system_charset_info); + protocol->store(m_defstr.str, m_defstr.length, system_charset_info); + res= protocol->write(); + send_eof(thd); + DBUG_RETURN(res); +} // ------------------------------------------------------------------ // diff --git a/sql/sp_head.h b/sql/sp_head.h index b582d37a185..2a8f8a1e017 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -66,7 +66,21 @@ public: // Initialize after we have reset mem_root void - init(LEX_STRING *name, LEX *lex, LEX_STRING *comment, char suid); + init(LEX_STRING *name, LEX *lex); + + void + init_options(LEX_STRING *comment, enum suid_behaviour suid) + { + m_comment.length= 0; + m_comment.str= 0; + if (comment) + { + m_comment.length= comment->length; + m_comment.str= comment->str; + } + m_suid= suid ? suid - 1 : 1; + } + int create(THD *thd); @@ -83,6 +97,12 @@ public: int execute_procedure(THD *thd, List<Item> *args); + int + show_create_procedure(THD *thd); + + int + show_create_function(THD *thd); + inline void add_instr(sp_instr *i) { diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 463205e78b0..e9cd64450fc 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -79,11 +79,18 @@ enum enum_sql_command { SQLCOM_HELP, SQLCOM_DROP_USER, SQLCOM_REVOKE_ALL, SQLCOM_CHECKSUM, SQLCOM_CREATE_PROCEDURE, SQLCOM_CREATE_SPFUNCTION, SQLCOM_CALL, SQLCOM_DROP_PROCEDURE, SQLCOM_ALTER_PROCEDURE,SQLCOM_ALTER_FUNCTION, + SQLCOM_SHOW_CREATE_PROC, SQLCOM_SHOW_CREATE_FUNC, + SQLCOM_SHOW_STATUS_PROC, SQLCOM_SHOW_STATUS_FUNC, /* This should be the last !!! */ SQLCOM_END }; +enum suid_behaviour +{ + IS_DEFAULT_SUID= 0, IS_NOT_SUID, IS_SUID +}; + typedef List<Item> List_item; typedef struct st_lex_master_info @@ -544,6 +551,7 @@ typedef struct st_lex enum enum_enable_or_disable alter_keys_onoff; enum enum_var_type option_type; enum tablespace_op_type tablespace_op; + enum suid_behaviour suid; uint uint_geom_type; uint grant, grant_tot_col, which_columns; uint fk_delete_opt, fk_update_opt, fk_match_option; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1fbf57d8cb3..b78aa73aa47 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3394,22 +3394,34 @@ mysql_execute_command(THD *thd) case SQLCOM_ALTER_PROCEDURE: case SQLCOM_ALTER_FUNCTION: { - sp_head *sp; - - if (lex->sql_command == SQLCOM_ALTER_PROCEDURE) - sp= sp_find_procedure(thd, &lex->udf.name); - else - sp= sp_find_function(thd, &lex->udf.name); - if (! sp) + res= -1; + uint newname_len= 0; + if (lex->name) + newname_len= strlen(lex->name); + if (newname_len > NAME_LEN) { - net_printf(thd, ER_SP_DOES_NOT_EXIST, SP_COM_STRING(lex),lex->udf.name); + net_printf(thd, ER_TOO_LONG_IDENT, lex->name); goto error; } + if (lex->sql_command == SQLCOM_ALTER_PROCEDURE) + res= sp_update_procedure(thd, lex->udf.name.str, lex->udf.name.length, + lex->name, newname_len, lex->comment->str, + lex->comment->length, lex->suid); else + res= sp_update_function(thd, lex->udf.name.str, lex->udf.name.length, + lex->name, newname_len, lex->comment->str, + lex->comment->length, lex->suid); + switch (res) { - /* QQ This is an no-op right now, since we haven't - put the characteristics in yet. */ + case SP_OK: send_ok(thd); + break; + case SP_KEY_NOT_FOUND: + net_printf(thd, ER_SP_DOES_NOT_EXIST, SP_COM_STRING(lex),lex->udf.name); + goto error; + default: + net_printf(thd, ER_SP_CANT_ALTER, SP_COM_STRING(lex),lex->udf.name); + goto error; } break; } @@ -3463,6 +3475,51 @@ mysql_execute_command(THD *thd) } break; } + case SQLCOM_SHOW_CREATE_PROC: + { + res= -1; + if (lex->udf.name.length > NAME_LEN) + { + net_printf(thd, ER_TOO_LONG_IDENT, lex->udf.name.str); + goto error; + } + res= sp_show_create_procedure(thd, &lex->udf.name); + if (res == SP_KEY_NOT_FOUND) + { + net_printf(thd, ER_SP_DOES_NOT_EXIST, + SP_COM_STRING(lex), lex->udf.name.str); + goto error; + } + break; + } + case SQLCOM_SHOW_CREATE_FUNC: + { + if (lex->udf.name.length > NAME_LEN) + { + net_printf(thd, ER_TOO_LONG_IDENT, lex->udf.name.str); + goto error; + } + res= sp_show_create_function(thd, &lex->udf.name); + if (res == SP_KEY_NOT_FOUND) + { + net_printf(thd, ER_SP_DOES_NOT_EXIST, + SP_COM_STRING(lex), lex->udf.name.str); + goto error; + } + break; + } + case SQLCOM_SHOW_STATUS_PROC: + { + res= db_show_status_procedure(thd, (lex->wild ? + lex->wild->ptr() : NullS)); + break; + } + case SQLCOM_SHOW_STATUS_FUNC: + { + res= db_show_status_function(thd, (lex->wild ? + lex->wild->ptr() : NullS)); + break; + } default: /* Impossible */ send_ok(thd); break; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 0af4b774615..2e76989c558 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -137,6 +137,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token CREATE %token CROSS %token CUBE_SYM +%token DEFINER %token DELETE_SYM %token DUAL_SYM %token DO_SYM @@ -269,6 +270,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token INOUT_SYM %token INTO %token IN_SYM +%token INVOKER %token ISOLATION %token JOIN_SYM %token KEYS @@ -311,6 +313,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token MEDIUM_SYM %token MIN_ROWS %token NAMES_SYM +%token NAME_SYM %token NATIONAL_SYM %token NATURAL %token NEW_SYM @@ -361,6 +364,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token ROW_FORMAT_SYM %token ROW_SYM %token RTREE_SYM +%token SECURITY %token SET %token SEPARATOR_SYM %token SERIAL_SYM @@ -619,7 +623,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ULONGLONG_NUM field_ident select_alias ident ident_or_text UNDERSCORE_CHARSET IDENT_sys TEXT_STRING_sys TEXT_STRING_literal NCHAR_STRING opt_component - SP_FUNC ident_or_spfunc sp_opt_label + SP_FUNC ident_or_spfunc sp_opt_label sp_comment sp_newname %type <lex_str_ptr> opt_table_alias @@ -745,7 +749,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); union_clause union_list union_option precision subselect_start opt_and charset subselect_end select_var_list select_var_list_init help opt_len - statement + statement sp_suid END_OF_INPUT %type <NONE> call sp_proc_stmts sp_proc_stmt @@ -1021,7 +1025,7 @@ create: /* Order is important here: new - reset - init */ sp= new sp_head(); sp->reset_thd_mem_root(YYTHD); - sp->init(&$3, lex, 0, 0); + sp->init(&$3, lex); sp->m_type= TYPE_ENUM_PROCEDURE; lex->sphead= sp; @@ -1037,6 +1041,10 @@ create: { Lex->spcont->set_params(); } + sp_comment sp_suid + { + Lex->sphead->init_options(&$9, Lex->suid); + } sp_proc_stmt { LEX *lex= Lex; @@ -1075,7 +1083,7 @@ create_function_tail: /* Order is important here: new - reset - init */ sp= new sp_head(); sp->reset_thd_mem_root(YYTHD); - sp->init(&lex->udf.name, lex, 0, 0); + sp->init(&lex->udf.name, lex); sp->m_type= TYPE_ENUM_FUNCTION; lex->sphead= sp; @@ -1095,6 +1103,10 @@ create_function_tail: { Lex->sphead->m_returns= (enum enum_field_types)$7; } + sp_comment sp_suid + { + Lex->sphead->init_options(&$9, Lex->suid); + } sp_proc_stmt { LEX *lex= Lex; @@ -1107,6 +1119,23 @@ create_function_tail: } ; +sp_comment: + /* Empty */ { $$.str=0; } + | COMMENT_SYM TEXT_STRING_sys { $$= $2; } + ; + +sp_newname: + /* Empty */ { $$.str=0; } + | NAME_SYM ident { $$= $2; } + ; + + +sp_suid: + /* Empty */ { Lex->suid= IS_DEFAULT_SUID; } + | SECURITY DEFINER { Lex->suid= IS_SUID; } + | SECURITY INVOKER { Lex->suid= IS_NOT_SUID; } + ; + call: CALL_SYM ident_or_spfunc { @@ -2573,7 +2602,7 @@ alter: lex->sql_command=SQLCOM_ALTER_DB; lex->name=$3.str; } - | ALTER PROCEDURE ident + | ALTER PROCEDURE ident sp_newname sp_comment sp_suid /* QQ Characteristics missing for now */ opt_restrict { @@ -2583,8 +2612,10 @@ alter: put the characteristics in yet. */ lex->sql_command= SQLCOM_ALTER_PROCEDURE; lex->udf.name= $3; + lex->name= $4.str; + lex->comment= &$5; } - | ALTER FUNCTION_SYM ident + | ALTER FUNCTION_SYM ident sp_newname sp_comment sp_suid /* QQ Characteristics missing for now */ opt_restrict { @@ -2594,6 +2625,8 @@ alter: put the characteristics in yet. */ lex->sql_command= SQLCOM_ALTER_FUNCTION; lex->udf.name= $3; + lex->name= $4.str; + lex->comment= &$5; } ; @@ -5012,7 +5045,26 @@ show_param: | SLAVE STATUS_SYM { Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT; - }; + } + | CREATE PROCEDURE ident + { + Lex->sql_command = SQLCOM_SHOW_CREATE_PROC; + Lex->udf.name= $3; + } + | CREATE FUNCTION_SYM ident + { + Lex->sql_command = SQLCOM_SHOW_CREATE_FUNC; + Lex->udf.name= $3; + } + | PROCEDURE STATUS_SYM wild + { + Lex->sql_command = SQLCOM_SHOW_STATUS_PROC; + } + | FUNCTION_SYM STATUS_SYM wild + { + Lex->sql_command = SQLCOM_SHOW_STATUS_FUNC; + }; + master_or_binary: MASTER_SYM @@ -5560,6 +5612,7 @@ keyword: | DATETIME {} | DATE_SYM {} | DAY_SYM {} + | DEFINER {} | DELAY_KEY_WRITE_SYM {} | DES_KEY_FILE {} | DIRECTORY_SYM {} @@ -5595,6 +5648,7 @@ keyword: | HOSTS_SYM {} | HOUR_SYM {} | IDENTIFIED_SYM {} + | INVOKER {} | IMPORT {} | INDEXES {} | ISOLATION {} @@ -5637,6 +5691,7 @@ keyword: | MULTILINESTRING {} | MULTIPOINT {} | MULTIPOLYGON {} + | NAME_SYM {} | NAMES_SYM {} | NATIONAL_SYM {} | NCHAR_SYM {} @@ -5680,6 +5735,7 @@ keyword: | RTREE_SYM {} | SAVEPOINT_SYM {} | SECOND_SYM {} + | SECURITY {} | SERIAL_SYM {} | SERIALIZABLE_SYM {} | SESSION_SYM {} |