mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Bugfixes in SHOW CREATE PROCEDURE/FUNCTION and SHOW PROCEDURE/FUNCTION STATUS;
- dropped routines should not show up in status - error handling for non-existing routines + some cleanup. mysql-test/r/sp-error.result: Test SHOW CREATE PROCEDURE for non-existing procedure. mysql-test/r/sp.result: Additional SHOW FUNCTION/PROCEDURE STATUS calls (make sure they don't show after being dropped). mysql-test/t/sp-error.test: Test SHOW CREATE PROCEDURE for non-existing procedure. mysql-test/t/sp.test: Additional SHOW FUNCTION/PROCEDURE STATUS calls (make sure they don't show after being dropped). sql/sp.cc: Fixed bug in SHOW ... STATUS after a routine has been dropped, and fixed the error return codes (for correct error handling). Also some general cleanup. sql/sp.h: Fixed prefix for external functions (should be sp_, not db_). sql/sql_parse.cc: Fixed error handling in SHOW CREATE PROCEDURE/FUNCTION.
This commit is contained in:
@ -36,6 +36,8 @@ ERROR HY000: PROCEDURE foo does not exist
|
|||||||
drop procedure if exists foo;
|
drop procedure if exists foo;
|
||||||
Warnings:
|
Warnings:
|
||||||
Warning 1286 PROCEDURE foo does not exist
|
Warning 1286 PROCEDURE foo does not exist
|
||||||
|
show create procedure foo;
|
||||||
|
ERROR HY000: PROCEDURE foo does not exist
|
||||||
create procedure foo()
|
create procedure foo()
|
||||||
foo: loop
|
foo: loop
|
||||||
leave bar;
|
leave bar;
|
||||||
|
@ -809,6 +809,8 @@ Name Type Creator Modified Created Suid Comment
|
|||||||
fac function root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 Y
|
fac function root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 Y
|
||||||
drop procedure ifac;
|
drop procedure ifac;
|
||||||
drop function fac;
|
drop function fac;
|
||||||
|
show function status like '%f%';
|
||||||
|
Name Type Creator Modified Created Suid Comment
|
||||||
drop table if exists primes;
|
drop table if exists primes;
|
||||||
create table primes (
|
create table primes (
|
||||||
i int unsigned not null primary key,
|
i int unsigned not null primary key,
|
||||||
@ -908,6 +910,8 @@ i p
|
|||||||
drop table primes;
|
drop table primes;
|
||||||
drop procedure opp;
|
drop procedure opp;
|
||||||
drop procedure ip;
|
drop procedure ip;
|
||||||
|
show procedure status like '%p%';
|
||||||
|
Name Type Creator Modified Created Suid Comment
|
||||||
create procedure bar(x char(16), y int)
|
create procedure bar(x char(16), y int)
|
||||||
comment "111111111111" sql security invoker
|
comment "111111111111" sql security invoker
|
||||||
insert into test.t1 values (x, y);
|
insert into test.t1 values (x, y);
|
||||||
|
@ -62,6 +62,8 @@ drop function foo|
|
|||||||
--error 1286
|
--error 1286
|
||||||
call foo()|
|
call foo()|
|
||||||
drop procedure if exists foo|
|
drop procedure if exists foo|
|
||||||
|
--error 1286
|
||||||
|
show create procedure foo|
|
||||||
|
|
||||||
# LEAVE/ITERATE with no match
|
# LEAVE/ITERATE with no match
|
||||||
--error 1289
|
--error 1289
|
||||||
|
@ -947,6 +947,8 @@ drop table fac|
|
|||||||
show function status like '%f%'|
|
show function status like '%f%'|
|
||||||
drop procedure ifac|
|
drop procedure ifac|
|
||||||
drop function fac|
|
drop function fac|
|
||||||
|
--replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
|
||||||
|
show function status like '%f%'|
|
||||||
|
|
||||||
|
|
||||||
# primes
|
# primes
|
||||||
@ -1034,6 +1036,8 @@ select * from primes where i=45 or i=100 or i=199|
|
|||||||
drop table primes|
|
drop table primes|
|
||||||
drop procedure opp|
|
drop procedure opp|
|
||||||
drop procedure ip|
|
drop procedure ip|
|
||||||
|
--replace_column 4 '0000-00-00 00:00:00' 5 '0000-00-00 00:00:00'
|
||||||
|
show procedure status like '%p%'|
|
||||||
|
|
||||||
# Comment & suid
|
# Comment & suid
|
||||||
create procedure bar(x char(16), y int)
|
create procedure bar(x char(16), y int)
|
||||||
|
94
sql/sp.cc
94
sql/sp.cc
@ -322,9 +322,10 @@ static struct st_used_field init_fields[]=
|
|||||||
{ 0, 0, MYSQL_TYPE_STRING, 0}
|
{ 0, 0, MYSQL_TYPE_STRING, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
int print_field_values(THD *thd, TABLE *table,
|
static int
|
||||||
struct st_used_field *used_fields,
|
print_field_values(THD *thd, TABLE *table,
|
||||||
int type, const char *wild)
|
struct st_used_field *used_fields,
|
||||||
|
int type, const char *wild)
|
||||||
{
|
{
|
||||||
Protocol *protocol= thd->protocol;
|
Protocol *protocol= thd->protocol;
|
||||||
|
|
||||||
@ -332,9 +333,8 @@ int print_field_values(THD *thd, TABLE *table,
|
|||||||
{
|
{
|
||||||
String *tmp_string= new String();
|
String *tmp_string= new String();
|
||||||
struct st_used_field *used_field= used_fields;
|
struct st_used_field *used_field= used_fields;
|
||||||
get_field(&thd->mem_root,
|
|
||||||
used_field->field,
|
get_field(&thd->mem_root, used_field->field, tmp_string);
|
||||||
tmp_string);
|
|
||||||
if (!wild || !wild[0] || !wild_compare(tmp_string->ptr(), wild, 0))
|
if (!wild || !wild[0] || !wild_compare(tmp_string->ptr(), wild, 0))
|
||||||
{
|
{
|
||||||
protocol->prepare_for_resend();
|
protocol->prepare_for_resend();
|
||||||
@ -345,35 +345,36 @@ int print_field_values(THD *thd, TABLE *table,
|
|||||||
{
|
{
|
||||||
switch (used_field->field_type) {
|
switch (used_field->field_type) {
|
||||||
case MYSQL_TYPE_TIMESTAMP:
|
case MYSQL_TYPE_TIMESTAMP:
|
||||||
{
|
{
|
||||||
TIME tmp_time;
|
TIME tmp_time;
|
||||||
((Field_timestamp *) used_field->field)->get_time(&tmp_time);
|
((Field_timestamp *) used_field->field)->get_time(&tmp_time);
|
||||||
protocol->store(&tmp_time);
|
protocol->store(&tmp_time);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
String *tmp_string1= new String();
|
String *tmp_string1= new String();
|
||||||
get_field(&thd->mem_root, used_field->field, tmp_string1);
|
get_field(&thd->mem_root, used_field->field, tmp_string1);
|
||||||
protocol->store(tmp_string1);
|
protocol->store(tmp_string1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (protocol->write())
|
if (protocol->write())
|
||||||
return 1;
|
return SP_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return SP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
db_show_routine_status(THD *thd, int type, const char *wild)
|
db_show_routine_status(THD *thd, int type, const char *wild)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("db_show_routine_status");
|
DBUG_ENTER("db_show_routine_status");
|
||||||
|
|
||||||
TABLE *table;
|
TABLE *table;
|
||||||
TABLE_LIST tables;
|
TABLE_LIST tables;
|
||||||
|
int res;
|
||||||
|
|
||||||
memset(&tables, 0, sizeof(tables));
|
memset(&tables, 0, sizeof(tables));
|
||||||
tables.db= (char*)"mysql";
|
tables.db= (char*)"mysql";
|
||||||
@ -381,7 +382,8 @@ db_show_routine_status(THD *thd, int type, const char *wild)
|
|||||||
|
|
||||||
if (! (table= open_ltable(thd, &tables, TL_READ)))
|
if (! (table= open_ltable(thd, &tables, TL_READ)))
|
||||||
{
|
{
|
||||||
DBUG_RETURN(1);
|
res= SP_OPEN_TABLE_FAILED;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -389,6 +391,7 @@ db_show_routine_status(THD *thd, int type, const char *wild)
|
|||||||
List<Item> field_list;
|
List<Item> field_list;
|
||||||
struct st_used_field *used_field;
|
struct st_used_field *used_field;
|
||||||
st_used_field used_fields[array_elements(init_fields)];
|
st_used_field used_fields[array_elements(init_fields)];
|
||||||
|
|
||||||
memcpy((char*) used_fields, (char*) init_fields, sizeof(used_fields));
|
memcpy((char*) used_fields, (char*) init_fields, sizeof(used_fields));
|
||||||
/* Init header */
|
/* Init header */
|
||||||
for (used_field= &used_fields[0];
|
for (used_field= &used_fields[0];
|
||||||
@ -408,7 +411,10 @@ db_show_routine_status(THD *thd, int type, const char *wild)
|
|||||||
}
|
}
|
||||||
/* Print header */
|
/* Print header */
|
||||||
if (thd->protocol->send_fields(&field_list,1))
|
if (thd->protocol->send_fields(&field_list,1))
|
||||||
|
{
|
||||||
|
res= SP_INTERNAL_ERROR;
|
||||||
goto err_case;
|
goto err_case;
|
||||||
|
}
|
||||||
|
|
||||||
/* Init fields */
|
/* Init fields */
|
||||||
setup_tables(&tables);
|
setup_tables(&tables);
|
||||||
@ -421,27 +427,37 @@ db_show_routine_status(THD *thd, int type, const char *wild)
|
|||||||
used_field->field_name);
|
used_field->field_name);
|
||||||
if (!(used_field->field= find_field_in_tables(thd, field, &tables,
|
if (!(used_field->field= find_field_in_tables(thd, field, &tables,
|
||||||
¬_used, TRUE)))
|
¬_used, TRUE)))
|
||||||
|
{
|
||||||
|
res= SP_INTERNAL_ERROR;
|
||||||
goto err_case1;
|
goto err_case1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
table->file->index_init(0);
|
table->file->index_init(0);
|
||||||
table->file->index_first(table->record[0]);
|
if ((res= table->file->index_first(table->record[0])))
|
||||||
if (print_field_values(thd, table, used_fields, type, wild))
|
{
|
||||||
|
if (res == HA_ERR_END_OF_FILE)
|
||||||
|
res= 0;
|
||||||
|
else
|
||||||
|
res= SP_INTERNAL_ERROR;
|
||||||
|
goto err_case1;
|
||||||
|
}
|
||||||
|
if ((res= print_field_values(thd, table, used_fields, type, wild)))
|
||||||
goto err_case1;
|
goto err_case1;
|
||||||
while (!table->file->index_next(table->record[0]))
|
while (!table->file->index_next(table->record[0]))
|
||||||
{
|
{
|
||||||
if (print_field_values(thd, table, used_fields, type, wild))
|
if ((res= print_field_values(thd, table, used_fields, type, wild)))
|
||||||
goto err_case1;
|
goto err_case1;
|
||||||
}
|
}
|
||||||
send_eof(thd);
|
res= SP_OK;
|
||||||
close_thread_tables(thd);
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
}
|
||||||
err_case1:
|
|
||||||
|
err_case1:
|
||||||
send_eof(thd);
|
send_eof(thd);
|
||||||
err_case:
|
err_case:
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
DBUG_RETURN(1);
|
done:
|
||||||
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -530,16 +546,16 @@ sp_show_create_procedure(THD *thd, LEX_STRING *name)
|
|||||||
sp_head *sp;
|
sp_head *sp;
|
||||||
|
|
||||||
sp= sp_find_procedure(thd, name);
|
sp= sp_find_procedure(thd, name);
|
||||||
if (sp)
|
if (sp)
|
||||||
DBUG_RETURN(sp->show_create_procedure(thd));
|
DBUG_RETURN(sp->show_create_procedure(thd));
|
||||||
|
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(SP_KEY_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
db_show_status_procedure(THD *thd, const char *wild)
|
sp_show_status_procedure(THD *thd, const char *wild)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("db_show_status_procedure");
|
DBUG_ENTER("sp_show_status_procedure");
|
||||||
DBUG_RETURN(db_show_routine_status(thd, TYPE_ENUM_PROCEDURE, wild));
|
DBUG_RETURN(db_show_routine_status(thd, TYPE_ENUM_PROCEDURE, wild));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -628,13 +644,13 @@ sp_show_create_function(THD *thd, LEX_STRING *name)
|
|||||||
if (sp)
|
if (sp)
|
||||||
DBUG_RETURN(sp->show_create_function(thd));
|
DBUG_RETURN(sp->show_create_function(thd));
|
||||||
|
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(SP_KEY_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
db_show_status_function(THD *thd, const char *wild)
|
sp_show_status_function(THD *thd, const char *wild)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("db_show_status_function");
|
DBUG_ENTER("sp_show_status_function");
|
||||||
DBUG_RETURN(db_show_routine_status(thd, TYPE_ENUM_FUNCTION, wild));
|
DBUG_RETURN(db_show_routine_status(thd, TYPE_ENUM_FUNCTION, wild));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
7
sql/sp.h
7
sql/sp.h
@ -18,7 +18,7 @@
|
|||||||
#ifndef _SP_H_
|
#ifndef _SP_H_
|
||||||
#define _SP_H_
|
#define _SP_H_
|
||||||
|
|
||||||
// Return codes from sp_create_* and sp_drop_*:
|
// Return codes from sp_create_*, sp_drop_*, and sp_show_*:
|
||||||
#define SP_OK 0
|
#define SP_OK 0
|
||||||
#define SP_KEY_NOT_FOUND -1
|
#define SP_KEY_NOT_FOUND -1
|
||||||
#define SP_OPEN_TABLE_FAILED -2
|
#define SP_OPEN_TABLE_FAILED -2
|
||||||
@ -26,6 +26,7 @@
|
|||||||
#define SP_DELETE_ROW_FAILED -4
|
#define SP_DELETE_ROW_FAILED -4
|
||||||
#define SP_GET_FIELD_FAILED -5
|
#define SP_GET_FIELD_FAILED -5
|
||||||
#define SP_PARSE_ERROR -6
|
#define SP_PARSE_ERROR -6
|
||||||
|
#define SP_INTERNAL_ERROR -7
|
||||||
|
|
||||||
sp_head *
|
sp_head *
|
||||||
sp_find_procedure(THD *thd, LEX_STRING *name);
|
sp_find_procedure(THD *thd, LEX_STRING *name);
|
||||||
@ -47,7 +48,7 @@ int
|
|||||||
sp_show_create_procedure(THD *thd, LEX_STRING *name);
|
sp_show_create_procedure(THD *thd, LEX_STRING *name);
|
||||||
|
|
||||||
int
|
int
|
||||||
db_show_status_procedure(THD *thd, const char *wild);
|
sp_show_status_procedure(THD *thd, const char *wild);
|
||||||
|
|
||||||
sp_head *
|
sp_head *
|
||||||
sp_find_function(THD *thd, LEX_STRING *name);
|
sp_find_function(THD *thd, LEX_STRING *name);
|
||||||
@ -68,7 +69,7 @@ int
|
|||||||
sp_show_create_function(THD *thd, LEX_STRING *name);
|
sp_show_create_function(THD *thd, LEX_STRING *name);
|
||||||
|
|
||||||
int
|
int
|
||||||
db_show_status_function(THD *thd, const char *wild);
|
sp_show_status_function(THD *thd, const char *wild);
|
||||||
|
|
||||||
// QQ Temporary until the function call detection in sql_lex has been reworked.
|
// QQ Temporary until the function call detection in sql_lex has been reworked.
|
||||||
bool
|
bool
|
||||||
|
@ -3592,10 +3592,11 @@ mysql_execute_command(THD *thd)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
res= sp_show_create_procedure(thd, &lex->udf.name);
|
res= sp_show_create_procedure(thd, &lex->udf.name);
|
||||||
if (res == SP_KEY_NOT_FOUND)
|
if (res != SP_OK)
|
||||||
{
|
{ /* We don't distinguish between errors for now */
|
||||||
net_printf(thd, ER_SP_DOES_NOT_EXIST,
|
net_printf(thd, ER_SP_DOES_NOT_EXIST,
|
||||||
SP_COM_STRING(lex), lex->udf.name.str);
|
SP_COM_STRING(lex), lex->udf.name.str);
|
||||||
|
res= 0;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -3608,23 +3609,24 @@ mysql_execute_command(THD *thd)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
res= sp_show_create_function(thd, &lex->udf.name);
|
res= sp_show_create_function(thd, &lex->udf.name);
|
||||||
if (res == SP_KEY_NOT_FOUND)
|
if (res != SP_OK)
|
||||||
{
|
{ /* We don't distinguish between errors for now */
|
||||||
net_printf(thd, ER_SP_DOES_NOT_EXIST,
|
net_printf(thd, ER_SP_DOES_NOT_EXIST,
|
||||||
SP_COM_STRING(lex), lex->udf.name.str);
|
SP_COM_STRING(lex), lex->udf.name.str);
|
||||||
|
res= 0;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SQLCOM_SHOW_STATUS_PROC:
|
case SQLCOM_SHOW_STATUS_PROC:
|
||||||
{
|
{
|
||||||
res= db_show_status_procedure(thd, (lex->wild ?
|
res= sp_show_status_procedure(thd, (lex->wild ?
|
||||||
lex->wild->ptr() : NullS));
|
lex->wild->ptr() : NullS));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SQLCOM_SHOW_STATUS_FUNC:
|
case SQLCOM_SHOW_STATUS_FUNC:
|
||||||
{
|
{
|
||||||
res= db_show_status_function(thd, (lex->wild ?
|
res= sp_show_status_function(thd, (lex->wild ?
|
||||||
lex->wild->ptr() : NullS));
|
lex->wild->ptr() : NullS));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user