Commit 6c1a2b7f authored by unknown's avatar unknown

WL#1241: SHOW PROCEDURE/FUNCTION

WL#1263: Support for the attributes COMMENT and SUID
         in CREATE/ALTER PROCEDURE/FUNCTION


include/mysqld_error.h:
  Error code for 'alter procedure'
mysql-test/r/sp-error.result:
  Test for WL#1241&WL#1263
mysql-test/r/sp.result:
  Test for WL#1241&WL#1263
mysql-test/t/sp-error.test:
  Test for WL#1241&WL#1263
mysql-test/t/sp.test:
  Test for WL#1241&WL#1263
sql/share/czech/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/danish/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/dutch/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/english/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/estonian/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/french/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/german/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/greek/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/hungarian/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/italian/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/japanese/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/korean/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/norwegian-ny/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/norwegian/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/polish/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/portuguese/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/romanian/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/russian/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/serbian/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/slovak/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/spanish/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/swedish/errmsg.txt:
  Error massage for 'alter procedure'
sql/share/ukrainian/errmsg.txt:
  Error massage for 'alter procedure'
parent 7b4a8505
......@@ -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
......@@ -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);
......
......@@ -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;
......@@ -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
......
......@@ -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;
......@@ -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},
......
......@@ -323,3 +323,4 @@ character-set=latin2
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -317,3 +317,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -325,3 +325,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -314,3 +314,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -319,3 +319,4 @@ character-set=latin7
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -314,3 +314,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -326,3 +326,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -314,3 +314,4 @@ character-set=greek
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -316,3 +316,4 @@ character-set=latin2
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -314,3 +314,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -316,3 +316,4 @@ character-set=ujis
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -314,3 +314,4 @@ character-set=euckr
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -316,3 +316,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -316,3 +316,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -318,3 +318,4 @@ character-set=latin2
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -315,3 +315,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -318,3 +318,4 @@ character-set=latin2
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -316,3 +316,4 @@ character-set=koi8r
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -309,3 +309,4 @@ character-set=cp1250
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -322,3 +322,4 @@ character-set=latin2
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -316,3 +316,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -314,3 +314,4 @@ character-set=latin1
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -319,3 +319,4 @@ character-set=koi8u
"Duplicate variable: %s"
"Duplicate condition: %s"
"Duplicate cursor: %s"
"Failed to ALTER %s %s"
......@@ -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)
......
......@@ -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);
......
......@@ -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);
}
// ------------------------------------------------------------------
//
......
......@@ -66,7 +66,21 @@ class sp_head : public Sql_alloc
// 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 @@ class sp_head : public Sql_alloc
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)
{
......
......@@ -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;
......
......@@ -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;
......
......@@ -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 {}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment