summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mysqld_error.h3
-rw-r--r--mysql-test/r/sp-error.result5
-rw-r--r--mysql-test/r/sp.result52
-rw-r--r--mysql-test/t/sp-error.test6
-rw-r--r--mysql-test/t/sp.test18
-rw-r--r--sql/lex.h4
-rw-r--r--sql/share/czech/errmsg.txt1
-rw-r--r--sql/share/danish/errmsg.txt1
-rw-r--r--sql/share/dutch/errmsg.txt1
-rw-r--r--sql/share/english/errmsg.txt1
-rw-r--r--sql/share/estonian/errmsg.txt1
-rw-r--r--sql/share/french/errmsg.txt1
-rw-r--r--sql/share/german/errmsg.txt1
-rw-r--r--sql/share/greek/errmsg.txt1
-rw-r--r--sql/share/hungarian/errmsg.txt1
-rw-r--r--sql/share/italian/errmsg.txt1
-rw-r--r--sql/share/japanese/errmsg.txt1
-rw-r--r--sql/share/korean/errmsg.txt1
-rw-r--r--sql/share/norwegian-ny/errmsg.txt1
-rw-r--r--sql/share/norwegian/errmsg.txt1
-rw-r--r--sql/share/polish/errmsg.txt1
-rw-r--r--sql/share/portuguese/errmsg.txt1
-rw-r--r--sql/share/romanian/errmsg.txt1
-rw-r--r--sql/share/russian/errmsg.txt1
-rw-r--r--sql/share/serbian/errmsg.txt1
-rw-r--r--sql/share/slovak/errmsg.txt1
-rw-r--r--sql/share/spanish/errmsg.txt1
-rw-r--r--sql/share/swedish/errmsg.txt1
-rw-r--r--sql/share/ukrainian/errmsg.txt1
-rw-r--r--sql/sp.cc261
-rw-r--r--sql/sp.h22
-rw-r--r--sql/sp_head.cc61
-rw-r--r--sql/sp_head.h22
-rw-r--r--sql/sql_lex.h8
-rw-r--r--sql/sql_parse.cc77
-rw-r--r--sql/sql_yacc.yy70
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,
+ &not_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)
diff --git a/sql/sp.h b/sql/sp.h
index bbf8832d55d..e7c2fba3bba 100644
--- a/sql/sp.h
+++ b/sql/sp.h
@@ -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 {}