mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
Merge mysql.com:/usr/local/bk/mysql-5.0
into mysql.com:/usr/home/pem/show-sp-code/mysql-5.0
This commit is contained in:
4
mysql-test/include/is_debug_build.inc
Normal file
4
mysql-test/include/is_debug_build.inc
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
-- require r/is_debug_build.require
|
||||||
|
--disable_query_log
|
||||||
|
select instr(version(), "debug") > 0;
|
||||||
|
--enable_query_log
|
2
mysql-test/r/is_debug_build.require
Normal file
2
mysql-test/r/is_debug_build.require
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
instr(version(), "debug") > 0
|
||||||
|
1
|
62
mysql-test/r/sp-code.result
Normal file
62
mysql-test/r/sp-code.result
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
create procedure empty()
|
||||||
|
begin
|
||||||
|
end;
|
||||||
|
show procedure code empty;
|
||||||
|
Pos Instruction
|
||||||
|
drop procedure empty;
|
||||||
|
create function almost_empty()
|
||||||
|
returns int
|
||||||
|
return 0;
|
||||||
|
show function code almost_empty;
|
||||||
|
Pos Instruction
|
||||||
|
0 freturn 3 0
|
||||||
|
drop function almost_empty;
|
||||||
|
create procedure code_sample(x int, out err int, out nulls int)
|
||||||
|
begin
|
||||||
|
declare count int default 0;
|
||||||
|
set nulls = 0;
|
||||||
|
begin
|
||||||
|
declare c cursor for select name from t1;
|
||||||
|
declare exit handler for not found close c;
|
||||||
|
open c;
|
||||||
|
loop
|
||||||
|
begin
|
||||||
|
declare n varchar(20);
|
||||||
|
declare continue handler for sqlexception set err=1;
|
||||||
|
fetch c into n;
|
||||||
|
if isnull(n) then
|
||||||
|
set nulls = nulls + 1;
|
||||||
|
else
|
||||||
|
set count = count + 1;
|
||||||
|
update t2 set idx = count where name=n;
|
||||||
|
end if;
|
||||||
|
end;
|
||||||
|
end loop;
|
||||||
|
end;
|
||||||
|
select t.name, t.idx from t2 t order by idx asc;
|
||||||
|
end//
|
||||||
|
show procedure code code_sample;
|
||||||
|
Pos Instruction
|
||||||
|
0 set count@3 0
|
||||||
|
1 set nulls@2 0
|
||||||
|
2 cpush c@0
|
||||||
|
3 hpush_jump 6 4 EXIT
|
||||||
|
4 cclose c@0
|
||||||
|
5 hreturn 0 19
|
||||||
|
6 copen c@0
|
||||||
|
7 set n@4 NULL
|
||||||
|
8 hpush_jump 11 5 CONTINUE
|
||||||
|
9 set err@1 1
|
||||||
|
10 hreturn 5
|
||||||
|
11 cfetch c@0 n@4
|
||||||
|
12 jump_if_not 15 isnull(n@4)
|
||||||
|
13 set nulls@2 (nulls@2 + 1)
|
||||||
|
14 jump 17
|
||||||
|
15 set count@3 (count@3 + 1)
|
||||||
|
16 stmt 4 "update t2 set idx = count where name=n"
|
||||||
|
17 hpop 1
|
||||||
|
18 jump 7
|
||||||
|
19 hpop 1
|
||||||
|
20 cpop 1
|
||||||
|
21 stmt 0 "select t.name, t.idx from t2 t order ..."
|
||||||
|
drop procedure code_sample;
|
49
mysql-test/t/sp-code.test
Normal file
49
mysql-test/t/sp-code.test
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#
|
||||||
|
# Test the debugging feature "show procedure/function code <name>"
|
||||||
|
#
|
||||||
|
|
||||||
|
-- source include/is_debug_build.inc
|
||||||
|
|
||||||
|
create procedure empty()
|
||||||
|
begin
|
||||||
|
end;
|
||||||
|
show procedure code empty;
|
||||||
|
drop procedure empty;
|
||||||
|
|
||||||
|
create function almost_empty()
|
||||||
|
returns int
|
||||||
|
return 0;
|
||||||
|
show function code almost_empty;
|
||||||
|
drop function almost_empty;
|
||||||
|
|
||||||
|
delimiter //;
|
||||||
|
create procedure code_sample(x int, out err int, out nulls int)
|
||||||
|
begin
|
||||||
|
declare count int default 0;
|
||||||
|
|
||||||
|
set nulls = 0;
|
||||||
|
begin
|
||||||
|
declare c cursor for select name from t1;
|
||||||
|
declare exit handler for not found close c;
|
||||||
|
|
||||||
|
open c;
|
||||||
|
loop
|
||||||
|
begin
|
||||||
|
declare n varchar(20);
|
||||||
|
declare continue handler for sqlexception set err=1;
|
||||||
|
|
||||||
|
fetch c into n;
|
||||||
|
if isnull(n) then
|
||||||
|
set nulls = nulls + 1;
|
||||||
|
else
|
||||||
|
set count = count + 1;
|
||||||
|
update t2 set idx = count where name=n;
|
||||||
|
end if;
|
||||||
|
end;
|
||||||
|
end loop;
|
||||||
|
end;
|
||||||
|
select t.name, t.idx from t2 t order by idx asc;
|
||||||
|
end//
|
||||||
|
delimiter ;//
|
||||||
|
show procedure code code_sample;
|
||||||
|
drop procedure code_sample;
|
@@ -110,6 +110,7 @@ static SYMBOL symbols[] = {
|
|||||||
{ "CIPHER", SYM(CIPHER_SYM)},
|
{ "CIPHER", SYM(CIPHER_SYM)},
|
||||||
{ "CLIENT", SYM(CLIENT_SYM)},
|
{ "CLIENT", SYM(CLIENT_SYM)},
|
||||||
{ "CLOSE", SYM(CLOSE_SYM)},
|
{ "CLOSE", SYM(CLOSE_SYM)},
|
||||||
|
{ "CODE", SYM(CODE_SYM)},
|
||||||
{ "COLLATE", SYM(COLLATE_SYM)},
|
{ "COLLATE", SYM(COLLATE_SYM)},
|
||||||
{ "COLLATION", SYM(COLLATION_SYM)},
|
{ "COLLATION", SYM(COLLATION_SYM)},
|
||||||
{ "COLUMN", SYM(COLUMN_SYM)},
|
{ "COLUMN", SYM(COLUMN_SYM)},
|
||||||
|
280
sql/sp_head.cc
280
sql/sp_head.cc
@@ -105,6 +105,8 @@ sp_get_flags_for_command(LEX *lex)
|
|||||||
case SQLCOM_SHOW_TABLES:
|
case SQLCOM_SHOW_TABLES:
|
||||||
case SQLCOM_SHOW_VARIABLES:
|
case SQLCOM_SHOW_VARIABLES:
|
||||||
case SQLCOM_SHOW_WARNS:
|
case SQLCOM_SHOW_WARNS:
|
||||||
|
case SQLCOM_SHOW_PROC_CODE:
|
||||||
|
case SQLCOM_SHOW_FUNC_CODE:
|
||||||
flags= sp_head::MULTI_RESULTS;
|
flags= sp_head::MULTI_RESULTS;
|
||||||
break;
|
break;
|
||||||
/*
|
/*
|
||||||
@@ -1740,7 +1742,7 @@ sp_head::show_create_procedure(THD *thd)
|
|||||||
LINT_INIT(sql_mode_len);
|
LINT_INIT(sql_mode_len);
|
||||||
|
|
||||||
if (check_show_routine_access(thd, this, &full_access))
|
if (check_show_routine_access(thd, this, &full_access))
|
||||||
return 1;
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
sql_mode_str=
|
sql_mode_str=
|
||||||
sys_var_thd_sql_mode::symbolic_mode_representation(thd,
|
sys_var_thd_sql_mode::symbolic_mode_representation(thd,
|
||||||
@@ -1753,10 +1755,7 @@ sp_head::show_create_procedure(THD *thd)
|
|||||||
max(buffer.length(), 1024)));
|
max(buffer.length(), 1024)));
|
||||||
if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
|
if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
|
||||||
Protocol::SEND_EOF))
|
Protocol::SEND_EOF))
|
||||||
{
|
DBUG_RETURN(1);
|
||||||
res= 1;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
protocol->prepare_for_resend();
|
protocol->prepare_for_resend();
|
||||||
protocol->store(m_name.str, m_name.length, system_charset_info);
|
protocol->store(m_name.str, m_name.length, system_charset_info);
|
||||||
protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
|
protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
|
||||||
@@ -1765,7 +1764,6 @@ sp_head::show_create_procedure(THD *thd)
|
|||||||
res= protocol->write();
|
res= protocol->write();
|
||||||
send_eof(thd);
|
send_eof(thd);
|
||||||
|
|
||||||
done:
|
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1810,7 +1808,7 @@ sp_head::show_create_function(THD *thd)
|
|||||||
LINT_INIT(sql_mode_len);
|
LINT_INIT(sql_mode_len);
|
||||||
|
|
||||||
if (check_show_routine_access(thd, this, &full_access))
|
if (check_show_routine_access(thd, this, &full_access))
|
||||||
return 1;
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
sql_mode_str=
|
sql_mode_str=
|
||||||
sys_var_thd_sql_mode::symbolic_mode_representation(thd,
|
sys_var_thd_sql_mode::symbolic_mode_representation(thd,
|
||||||
@@ -1822,10 +1820,7 @@ sp_head::show_create_function(THD *thd)
|
|||||||
max(buffer.length(),1024)));
|
max(buffer.length(),1024)));
|
||||||
if (protocol->send_fields(&field_list,
|
if (protocol->send_fields(&field_list,
|
||||||
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
|
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
|
||||||
{
|
DBUG_RETURN(1);
|
||||||
res= 1;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
protocol->prepare_for_resend();
|
protocol->prepare_for_resend();
|
||||||
protocol->store(m_name.str, m_name.length, system_charset_info);
|
protocol->store(m_name.str, m_name.length, system_charset_info);
|
||||||
protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
|
protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
|
||||||
@@ -1834,7 +1829,6 @@ sp_head::show_create_function(THD *thd)
|
|||||||
res= protocol->write();
|
res= protocol->write();
|
||||||
send_eof(thd);
|
send_eof(thd);
|
||||||
|
|
||||||
done:
|
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1894,6 +1888,50 @@ sp_head::opt_mark(uint ip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
int
|
||||||
|
sp_head::show_routine_code(THD *thd)
|
||||||
|
{
|
||||||
|
Protocol *protocol= thd->protocol;
|
||||||
|
char buff[2048];
|
||||||
|
String buffer(buff, sizeof(buff), system_charset_info);
|
||||||
|
List<Item> field_list;
|
||||||
|
sp_instr *i;
|
||||||
|
bool full_access;
|
||||||
|
int res;
|
||||||
|
uint ip;
|
||||||
|
DBUG_ENTER("sp_head::show_routine_code");
|
||||||
|
DBUG_PRINT("info", ("procedure: %s", m_name.str));
|
||||||
|
|
||||||
|
if (check_show_routine_access(thd, this, &full_access) || !full_access)
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
|
field_list.push_back(new Item_uint("Pos", 9));
|
||||||
|
// 1024 is for not to confuse old clients
|
||||||
|
field_list.push_back(new Item_empty_string("Instruction",
|
||||||
|
max(buffer.length(), 1024)));
|
||||||
|
if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
|
||||||
|
Protocol::SEND_EOF))
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
|
for (ip= 0; (i = get_instr(ip)) ; ip++)
|
||||||
|
{
|
||||||
|
protocol->prepare_for_resend();
|
||||||
|
protocol->store((longlong)ip);
|
||||||
|
|
||||||
|
buffer.set("", 0, system_charset_info);
|
||||||
|
i->print(&buffer);
|
||||||
|
protocol->store(buffer.ptr(), buffer.length(), system_charset_info);
|
||||||
|
if ((res= protocol->write()))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
send_eof(thd);
|
||||||
|
|
||||||
|
DBUG_RETURN(res);
|
||||||
|
}
|
||||||
|
#endif // ifndef DBUG_OFF
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Prepare LEX and thread for execution of instruction, if requested open
|
Prepare LEX and thread for execution of instruction, if requested open
|
||||||
and lock LEX's tables, execute instruction's core function, perform
|
and lock LEX's tables, execute instruction's core function, perform
|
||||||
@@ -2052,14 +2090,43 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
|
|||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Sufficient max length of printed destinations and frame offsets (all uints).
|
||||||
|
*/
|
||||||
|
#define SP_INSTR_UINT_MAXLEN 8
|
||||||
|
|
||||||
|
#define SP_STMT_PRINT_MAXLEN 40
|
||||||
void
|
void
|
||||||
sp_instr_stmt::print(String *str)
|
sp_instr_stmt::print(String *str)
|
||||||
{
|
{
|
||||||
str->reserve(12);
|
uint i, len;
|
||||||
str->append(STRING_WITH_LEN("stmt "));
|
|
||||||
str->qs_append((uint)m_lex_keeper.sql_command());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* stmt CMD "..." */
|
||||||
|
if (str->reserve(SP_STMT_PRINT_MAXLEN+SP_INSTR_UINT_MAXLEN+8))
|
||||||
|
return;
|
||||||
|
str->qs_ append(STRING_WITH_LEN("stmt "));
|
||||||
|
str->qs_append((uint)m_lex_keeper.sql_command());
|
||||||
|
str->qs_append(" \"", 2);
|
||||||
|
len= m_query.length;
|
||||||
|
/*
|
||||||
|
Print the query string (but not too much of it), just to indicate which
|
||||||
|
statement it is.
|
||||||
|
*/
|
||||||
|
if (len > SP_STMT_PRINT_MAXLEN)
|
||||||
|
len= SP_STMT_PRINT_MAXLEN-3;
|
||||||
|
/* Copy the query string and replace '\n' with ' ' in the process */
|
||||||
|
for (i= 0 ; i < len ; i++)
|
||||||
|
{
|
||||||
|
if (m_query.str[i] == '\n')
|
||||||
|
str->qs_append(' ');
|
||||||
|
else
|
||||||
|
str->qs_append(m_query.str[i]);
|
||||||
|
}
|
||||||
|
if (m_query.length > SP_STMT_PRINT_MAXLEN)
|
||||||
|
str->qs_append("...", 3); /* Indicate truncated string */
|
||||||
|
str->qs_append('"');
|
||||||
|
}
|
||||||
|
#undef SP_STMT_PRINT_MAXLEN
|
||||||
|
|
||||||
int
|
int
|
||||||
sp_instr_stmt::exec_core(THD *thd, uint *nextp)
|
sp_instr_stmt::exec_core(THD *thd, uint *nextp)
|
||||||
@@ -2096,10 +2163,23 @@ sp_instr_set::exec_core(THD *thd, uint *nextp)
|
|||||||
void
|
void
|
||||||
sp_instr_set::print(String *str)
|
sp_instr_set::print(String *str)
|
||||||
{
|
{
|
||||||
str->reserve(12);
|
/* set name@offset ... */
|
||||||
str->append(STRING_WITH_LEN("set "));
|
int rsrv = SP_INSTR_UINT_MAXLEN+6;
|
||||||
|
sp_pvar_t *var = m_ctx->find_pvar(m_offset);
|
||||||
|
|
||||||
|
/* 'var' should always be non-null, but just in case... */
|
||||||
|
if (var)
|
||||||
|
rsrv+= var->name.length;
|
||||||
|
if (str->reserve(rsrv))
|
||||||
|
return;
|
||||||
|
str->qs_append(STRING_WITH_LEN("set "));
|
||||||
|
if (var)
|
||||||
|
{
|
||||||
|
str->qs_append(var->name.str, var->name.length);
|
||||||
|
str->qs_append('@');
|
||||||
|
}
|
||||||
str->qs_append(m_offset);
|
str->qs_append(m_offset);
|
||||||
str->append(' ');
|
str->qs_append(' ');
|
||||||
m_value->print(str);
|
m_value->print(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2132,7 +2212,7 @@ sp_instr_set_trigger_field::exec_core(THD *thd, uint *nextp)
|
|||||||
void
|
void
|
||||||
sp_instr_set_trigger_field::print(String *str)
|
sp_instr_set_trigger_field::print(String *str)
|
||||||
{
|
{
|
||||||
str->append(STRING_WITH_LEN("set "));
|
str->append(STRING_WITH_LEN("set_trigger_field "));
|
||||||
trigger_field->print(str);
|
trigger_field->print(str);
|
||||||
str->append(STRING_WITH_LEN(":="));
|
str->append(STRING_WITH_LEN(":="));
|
||||||
value->print(str);
|
value->print(str);
|
||||||
@@ -2156,8 +2236,10 @@ sp_instr_jump::execute(THD *thd, uint *nextp)
|
|||||||
void
|
void
|
||||||
sp_instr_jump::print(String *str)
|
sp_instr_jump::print(String *str)
|
||||||
{
|
{
|
||||||
str->reserve(12);
|
/* jump dest */
|
||||||
str->append(STRING_WITH_LEN("jump "));
|
if (str->reserve(SP_INSTR_UINT_MAXLEN+5))
|
||||||
|
return;
|
||||||
|
str->qs_append(STRING_WITH_LEN("jump "));
|
||||||
str->qs_append(m_dest);
|
str->qs_append(m_dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2238,10 +2320,12 @@ sp_instr_jump_if::exec_core(THD *thd, uint *nextp)
|
|||||||
void
|
void
|
||||||
sp_instr_jump_if::print(String *str)
|
sp_instr_jump_if::print(String *str)
|
||||||
{
|
{
|
||||||
str->reserve(12);
|
/* jump_if dest ... */
|
||||||
str->append(STRING_WITH_LEN("jump_if "));
|
if (str->reserve(SP_INSTR_UINT_MAXLEN+8+32)) // Add some for the expr. too
|
||||||
|
return;
|
||||||
|
str->qs_append(STRING_WITH_LEN("jump_if "));
|
||||||
str->qs_append(m_dest);
|
str->qs_append(m_dest);
|
||||||
str->append(' ');
|
str->qs_append(' ');
|
||||||
m_expr->print(str);
|
m_expr->print(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2299,10 +2383,12 @@ sp_instr_jump_if_not::exec_core(THD *thd, uint *nextp)
|
|||||||
void
|
void
|
||||||
sp_instr_jump_if_not::print(String *str)
|
sp_instr_jump_if_not::print(String *str)
|
||||||
{
|
{
|
||||||
str->reserve(16);
|
/* jump_if_not dest ... */
|
||||||
str->append(STRING_WITH_LEN("jump_if_not "));
|
if (str->reserve(SP_INSTR_UINT_MAXLEN+12+32)) // Add some for the expr. too
|
||||||
|
return;
|
||||||
|
str->qs_append(STRING_WITH_LEN("jump_if_not "));
|
||||||
str->qs_append(m_dest);
|
str->qs_append(m_dest);
|
||||||
str->append(' ');
|
str->qs_append(' ');
|
||||||
m_expr->print(str);
|
m_expr->print(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2357,10 +2443,12 @@ sp_instr_freturn::exec_core(THD *thd, uint *nextp)
|
|||||||
void
|
void
|
||||||
sp_instr_freturn::print(String *str)
|
sp_instr_freturn::print(String *str)
|
||||||
{
|
{
|
||||||
str->reserve(12);
|
/* freturn type expr... */
|
||||||
str->append(STRING_WITH_LEN("freturn "));
|
if (str->reserve(UINT_MAX+8+32)) // Add some for the expr. too
|
||||||
|
return;
|
||||||
|
str->qs_append(STRING_WITH_LEN("freturn "));
|
||||||
str->qs_append((uint)m_type);
|
str->qs_append((uint)m_type);
|
||||||
str->append(' ');
|
str->qs_append(' ');
|
||||||
m_value->print(str);
|
m_value->print(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2385,15 +2473,31 @@ sp_instr_hpush_jump::execute(THD *thd, uint *nextp)
|
|||||||
void
|
void
|
||||||
sp_instr_hpush_jump::print(String *str)
|
sp_instr_hpush_jump::print(String *str)
|
||||||
{
|
{
|
||||||
str->reserve(32);
|
/* hpush_jump dest fsize type */
|
||||||
str->append(STRING_WITH_LEN("hpush_jump "));
|
if (str->reserve(SP_INSTR_UINT_MAXLEN*2 + 21))
|
||||||
|
return;
|
||||||
|
str->qs_append(STRING_WITH_LEN("hpush_jump "));
|
||||||
str->qs_append(m_dest);
|
str->qs_append(m_dest);
|
||||||
str->append(STRING_WITH_LEN(" t="));
|
str->qs_append(' ');
|
||||||
str->qs_append(m_type);
|
|
||||||
str->append(STRING_WITH_LEN(" f="));
|
|
||||||
str->qs_append(m_frame);
|
str->qs_append(m_frame);
|
||||||
str->append(STRING_WITH_LEN(" h="));
|
switch (m_type)
|
||||||
str->qs_append(m_ip+1);
|
{
|
||||||
|
case SP_HANDLER_NONE:
|
||||||
|
str->qs_append(" NONE", 5); // This would be a bug
|
||||||
|
break;
|
||||||
|
case SP_HANDLER_EXIT:
|
||||||
|
str->qs_append(" EXIT", 5);
|
||||||
|
break;
|
||||||
|
case SP_HANDLER_CONTINUE:
|
||||||
|
str->qs_append(" CONTINUE", 9);
|
||||||
|
break;
|
||||||
|
case SP_HANDLER_UNDO:
|
||||||
|
str->qs_append(" UNDO", 5);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
str->qs_append(" UNKNOWN:", 9); // This would be a bug as well
|
||||||
|
str->qs_append(m_type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint
|
uint
|
||||||
@@ -2428,8 +2532,10 @@ sp_instr_hpop::execute(THD *thd, uint *nextp)
|
|||||||
void
|
void
|
||||||
sp_instr_hpop::print(String *str)
|
sp_instr_hpop::print(String *str)
|
||||||
{
|
{
|
||||||
str->reserve(12);
|
/* hpop count */
|
||||||
str->append(STRING_WITH_LEN("hpop "));
|
if (str->reserve(SP_INSTR_UINT_MAXLEN+5))
|
||||||
|
return;
|
||||||
|
str->qs_append(STRING_WITH_LEN("hpop "));
|
||||||
str->qs_append(m_count);
|
str->qs_append(m_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2463,12 +2569,14 @@ sp_instr_hreturn::execute(THD *thd, uint *nextp)
|
|||||||
void
|
void
|
||||||
sp_instr_hreturn::print(String *str)
|
sp_instr_hreturn::print(String *str)
|
||||||
{
|
{
|
||||||
str->reserve(16);
|
/* hreturn framesize dest */
|
||||||
str->append(STRING_WITH_LEN("hreturn "));
|
if (str->reserve(SP_INSTR_UINT_MAXLEN*2 + 9))
|
||||||
|
return;
|
||||||
|
str->qs_append(STRING_WITH_LEN("hreturn "));
|
||||||
str->qs_append(m_frame);
|
str->qs_append(m_frame);
|
||||||
if (m_dest)
|
if (m_dest)
|
||||||
{
|
{
|
||||||
str->append(' ');
|
str->qs_append(' ');
|
||||||
str->qs_append(m_dest);
|
str->qs_append(m_dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2516,7 +2624,22 @@ sp_instr_cpush::execute(THD *thd, uint *nextp)
|
|||||||
void
|
void
|
||||||
sp_instr_cpush::print(String *str)
|
sp_instr_cpush::print(String *str)
|
||||||
{
|
{
|
||||||
str->append(STRING_WITH_LEN("cpush"));
|
LEX_STRING n;
|
||||||
|
my_bool found= m_ctx->find_cursor(m_cursor, &n);
|
||||||
|
/* cpush name@offset */
|
||||||
|
uint rsrv= SP_INSTR_UINT_MAXLEN+7;
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
rsrv+= n.length;
|
||||||
|
if (str->reserve(rsrv))
|
||||||
|
return;
|
||||||
|
str->qs_append(STRING_WITH_LENGTH("cpush "));
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
str->qs_append(n.str, n.length);
|
||||||
|
str->qs_append('@');
|
||||||
|
}
|
||||||
|
str->qs_append(m_cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2537,8 +2660,10 @@ sp_instr_cpop::execute(THD *thd, uint *nextp)
|
|||||||
void
|
void
|
||||||
sp_instr_cpop::print(String *str)
|
sp_instr_cpop::print(String *str)
|
||||||
{
|
{
|
||||||
str->reserve(12);
|
/* cpop count */
|
||||||
str->append(STRING_WITH_LEN("cpop "));
|
if (str->reserve(SP_INSTR_UINT_MAXLEN+5))
|
||||||
|
return;
|
||||||
|
str->qs_append(STRING_WITH_LEN("cpop "));
|
||||||
str->qs_append(m_count);
|
str->qs_append(m_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2612,8 +2737,21 @@ sp_instr_copen::exec_core(THD *thd, uint *nextp)
|
|||||||
void
|
void
|
||||||
sp_instr_copen::print(String *str)
|
sp_instr_copen::print(String *str)
|
||||||
{
|
{
|
||||||
str->reserve(12);
|
LEX_STRING n;
|
||||||
str->append(STRING_WITH_LEN("copen "));
|
my_bool found= m_ctx->find_cursor(m_cursor, &n);
|
||||||
|
/* copen name@offset */
|
||||||
|
uint rsrv= SP_INSTR_UINT_MAXLEN+7;
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
rsrv+= n.length;
|
||||||
|
if (str->reserve(rsrv))
|
||||||
|
return;
|
||||||
|
str->qs_append(STRING_WITH_LEN("copen "));
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
str->qs_append(n.str, n.length);
|
||||||
|
str->qs_append('@');
|
||||||
|
}
|
||||||
str->qs_append(m_cursor);
|
str->qs_append(m_cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2641,8 +2779,21 @@ sp_instr_cclose::execute(THD *thd, uint *nextp)
|
|||||||
void
|
void
|
||||||
sp_instr_cclose::print(String *str)
|
sp_instr_cclose::print(String *str)
|
||||||
{
|
{
|
||||||
str->reserve(12);
|
LEX_STRING n;
|
||||||
str->append(STRING_WITH_LEN("cclose "));
|
my_bool found= m_ctx->find_cursor(m_cursor, &n);
|
||||||
|
/* cclose name@offset */
|
||||||
|
uint rsrv= SP_INSTR_UINT_MAXLEN+8;
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
rsrv+= n.length;
|
||||||
|
if (str->reserve(rsrv))
|
||||||
|
return;
|
||||||
|
str->qs_append(STRING_WITH_LEN("cclose "));
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
str->qs_append(n.str, n.length);
|
||||||
|
str->qs_append('@');
|
||||||
|
}
|
||||||
str->qs_append(m_cursor);
|
str->qs_append(m_cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2671,14 +2822,29 @@ sp_instr_cfetch::print(String *str)
|
|||||||
{
|
{
|
||||||
List_iterator_fast<struct sp_pvar> li(m_varlist);
|
List_iterator_fast<struct sp_pvar> li(m_varlist);
|
||||||
sp_pvar_t *pv;
|
sp_pvar_t *pv;
|
||||||
|
LEX_STRING n;
|
||||||
|
my_bool found= m_ctx->find_cursor(m_cursor, &n);
|
||||||
|
/* cfetch name@offset vars... */
|
||||||
|
uint rsrv= SP_INSTR_UINT_MAXLEN+8;
|
||||||
|
|
||||||
str->reserve(12);
|
if (found)
|
||||||
str->append(STRING_WITH_LEN("cfetch "));
|
rsrv+= n.length;
|
||||||
|
if (str->reserve(rsrv))
|
||||||
|
return;
|
||||||
|
str->qs_append(STRING_WITH_LEN("cfetch "));
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
str->qs_append(n.str, n.length);
|
||||||
|
str->qs_append('@');
|
||||||
|
}
|
||||||
str->qs_append(m_cursor);
|
str->qs_append(m_cursor);
|
||||||
while ((pv= li++))
|
while ((pv= li++))
|
||||||
{
|
{
|
||||||
str->reserve(8);
|
if (str->reserve(pv->name.length+SP_INSTR_UINT_MAXLEN+2))
|
||||||
str->append(' ');
|
return;
|
||||||
|
str->qs_append(' ');
|
||||||
|
str->qs_append(pv->name.str, pv->name.length);
|
||||||
|
str->qs_append('@');
|
||||||
str->qs_append(pv->offset);
|
str->qs_append(pv->offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2702,8 +2868,10 @@ sp_instr_error::execute(THD *thd, uint *nextp)
|
|||||||
void
|
void
|
||||||
sp_instr_error::print(String *str)
|
sp_instr_error::print(String *str)
|
||||||
{
|
{
|
||||||
str->reserve(12);
|
/* error code */
|
||||||
str->append(STRING_WITH_LEN("error "));
|
if (str->reserve(SP_INSTR_UINT_MAXLEN+6))
|
||||||
|
return;
|
||||||
|
str->qs_append(STRING_WITH_LEN("error "));
|
||||||
str->qs_append(m_errcode);
|
str->qs_append(m_errcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -304,6 +304,12 @@ public:
|
|||||||
return test(m_flags &
|
return test(m_flags &
|
||||||
(CONTAINS_DYNAMIC_SQL|MULTI_RESULTS|HAS_SET_AUTOCOMMIT_STMT));
|
(CONTAINS_DYNAMIC_SQL|MULTI_RESULTS|HAS_SET_AUTOCOMMIT_STMT));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
int show_routine_code(THD *thd);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
MEM_ROOT *m_thd_root; // Temp. store for thd's mem_root
|
MEM_ROOT *m_thd_root; // Temp. store for thd's mem_root
|
||||||
@@ -865,8 +871,8 @@ class sp_instr_cpush : public sp_instr
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
sp_instr_cpush(uint ip, sp_pcontext *ctx, LEX *lex)
|
sp_instr_cpush(uint ip, sp_pcontext *ctx, LEX *lex, uint offset)
|
||||||
: sp_instr(ip, ctx), m_lex_keeper(lex, TRUE)
|
: sp_instr(ip, ctx), m_lex_keeper(lex, TRUE), m_cursor(offset)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual ~sp_instr_cpush()
|
virtual ~sp_instr_cpush()
|
||||||
@@ -885,6 +891,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
sp_lex_keeper m_lex_keeper;
|
sp_lex_keeper m_lex_keeper;
|
||||||
|
uint m_cursor; /* Frame offset (for debugging) */
|
||||||
|
|
||||||
}; // class sp_instr_cpush : public sp_instr
|
}; // class sp_instr_cpush : public sp_instr
|
||||||
|
|
||||||
|
@@ -169,6 +169,28 @@ sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Find a variable by offset from the top.
|
||||||
|
This used for two things:
|
||||||
|
- When evaluating parameters at the beginning, and setting out parameters
|
||||||
|
at the end, of invokation. (Top frame only, so no recursion then.)
|
||||||
|
- For printing of sp_instr_set. (Debug mode only.)
|
||||||
|
*/
|
||||||
|
sp_pvar_t *
|
||||||
|
sp_pcontext::find_pvar(uint offset)
|
||||||
|
{
|
||||||
|
if (m_poffset <= offset && offset < m_poffset + m_pvar.elements)
|
||||||
|
{ // This frame
|
||||||
|
sp_pvar_t *p;
|
||||||
|
|
||||||
|
get_dynamic(&m_pvar, (gptr)&p, offset - m_poffset);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
if (m_parent)
|
||||||
|
return m_parent->find_pvar(offset); // Some previous frame
|
||||||
|
return NULL; // index out of bounds
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type,
|
sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type,
|
||||||
sp_param_mode_t mode)
|
sp_param_mode_t mode)
|
||||||
@@ -331,3 +353,21 @@ sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped)
|
|||||||
return m_parent->find_cursor(name, poff, scoped);
|
return m_parent->find_cursor(name, poff, scoped);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Find a cursor by offset from the top.
|
||||||
|
This is only used for debugging.
|
||||||
|
*/
|
||||||
|
my_bool
|
||||||
|
sp_pcontext::find_cursor(uint offset, LEX_STRING *n)
|
||||||
|
{
|
||||||
|
if (m_coffset <= offset && offset < m_coffset + m_cursor.elements)
|
||||||
|
{ // This frame
|
||||||
|
get_dynamic(&m_cursor, (gptr)n, offset - m_coffset);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
if (m_parent)
|
||||||
|
return m_parent->find_cursor(offset, n); // Some previous frame
|
||||||
|
return FALSE; // index out of bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -170,18 +170,9 @@ class sp_pcontext : public Sql_alloc
|
|||||||
sp_pvar_t *
|
sp_pvar_t *
|
||||||
find_pvar(LEX_STRING *name, my_bool scoped=0);
|
find_pvar(LEX_STRING *name, my_bool scoped=0);
|
||||||
|
|
||||||
// Find by index
|
// Find by offset
|
||||||
sp_pvar_t *
|
sp_pvar_t *
|
||||||
find_pvar(uint i)
|
find_pvar(uint offset);
|
||||||
{
|
|
||||||
sp_pvar_t *p;
|
|
||||||
|
|
||||||
if (i < m_pvar.elements)
|
|
||||||
get_dynamic(&m_pvar, (gptr)&p, i);
|
|
||||||
else
|
|
||||||
p= NULL;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Labels
|
// Labels
|
||||||
@@ -261,6 +252,10 @@ class sp_pcontext : public Sql_alloc
|
|||||||
my_bool
|
my_bool
|
||||||
find_cursor(LEX_STRING *name, uint *poff, my_bool scoped=0);
|
find_cursor(LEX_STRING *name, uint *poff, my_bool scoped=0);
|
||||||
|
|
||||||
|
/* Find by offset (for debugging only) */
|
||||||
|
my_bool
|
||||||
|
find_cursor(uint offset, LEX_STRING *n);
|
||||||
|
|
||||||
inline uint
|
inline uint
|
||||||
max_cursors()
|
max_cursors()
|
||||||
{
|
{
|
||||||
|
@@ -90,6 +90,7 @@ enum enum_sql_command {
|
|||||||
SQLCOM_CREATE_TRIGGER, SQLCOM_DROP_TRIGGER,
|
SQLCOM_CREATE_TRIGGER, SQLCOM_DROP_TRIGGER,
|
||||||
SQLCOM_XA_START, SQLCOM_XA_END, SQLCOM_XA_PREPARE,
|
SQLCOM_XA_START, SQLCOM_XA_END, SQLCOM_XA_PREPARE,
|
||||||
SQLCOM_XA_COMMIT, SQLCOM_XA_ROLLBACK, SQLCOM_XA_RECOVER,
|
SQLCOM_XA_COMMIT, SQLCOM_XA_ROLLBACK, SQLCOM_XA_RECOVER,
|
||||||
|
SQLCOM_SHOW_PROC_CODE, SQLCOM_SHOW_FUNC_CODE,
|
||||||
/* This should be the last !!! */
|
/* This should be the last !!! */
|
||||||
|
|
||||||
SQLCOM_END
|
SQLCOM_END
|
||||||
|
@@ -4548,6 +4548,31 @@ end_with_restore_list:
|
|||||||
lex->wild->ptr() : NullS));
|
lex->wild->ptr() : NullS));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
case SQLCOM_SHOW_PROC_CODE:
|
||||||
|
case SQLCOM_SHOW_FUNC_CODE:
|
||||||
|
{
|
||||||
|
sp_head *sp;
|
||||||
|
|
||||||
|
if (lex->spname->m_name.length > NAME_LEN)
|
||||||
|
{
|
||||||
|
my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (lex->sql_command == SQLCOM_SHOW_PROC_CODE)
|
||||||
|
sp= sp_find_procedure(thd, lex->spname);
|
||||||
|
else
|
||||||
|
sp= sp_find_function(thd, lex->spname);
|
||||||
|
if (!sp || !sp->show_routine_code(thd))
|
||||||
|
{
|
||||||
|
/* We don't distinguish between errors for now */
|
||||||
|
my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
|
||||||
|
SP_COM_STRING(lex), lex->spname->m_name.str);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif // ifndef DBUG_OFF
|
||||||
case SQLCOM_CREATE_VIEW:
|
case SQLCOM_CREATE_VIEW:
|
||||||
{
|
{
|
||||||
if (end_active_trans(thd))
|
if (end_active_trans(thd))
|
||||||
|
@@ -175,6 +175,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
|||||||
%token CLIENT_SYM
|
%token CLIENT_SYM
|
||||||
%token CLOSE_SYM
|
%token CLOSE_SYM
|
||||||
%token COALESCE
|
%token COALESCE
|
||||||
|
%token CODE_SYM
|
||||||
%token COLLATE_SYM
|
%token COLLATE_SYM
|
||||||
%token COLLATION_SYM
|
%token COLLATION_SYM
|
||||||
%token COLUMNS
|
%token COLUMNS
|
||||||
@@ -1693,7 +1694,8 @@ sp_decl:
|
|||||||
delete $5;
|
delete $5;
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
i= new sp_instr_cpush(sp->instructions(), ctx, $5);
|
i= new sp_instr_cpush(sp->instructions(), ctx, $5,
|
||||||
|
ctx->current_cursors());
|
||||||
sp->add_instr(i);
|
sp->add_instr(i);
|
||||||
ctx->push_cursor(&$2);
|
ctx->push_cursor(&$2);
|
||||||
$$.vars= $$.conds= $$.hndlrs= 0;
|
$$.vars= $$.conds= $$.hndlrs= 0;
|
||||||
@@ -6587,7 +6589,28 @@ show_param:
|
|||||||
YYABORT;
|
YYABORT;
|
||||||
if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
|
if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
};
|
}
|
||||||
|
| PROCEDURE CODE_SYM sp_name
|
||||||
|
{
|
||||||
|
#ifdef DBUG_OFF
|
||||||
|
yyerror(ER(ER_SYNTAX_ERROR));
|
||||||
|
YYABORT;
|
||||||
|
#else
|
||||||
|
Lex->sql_command= SQLCOM_SHOW_PROC_CODE;
|
||||||
|
Lex->spname= $3;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
| FUNCTION_SYM CODE_SYM sp_name
|
||||||
|
{
|
||||||
|
#ifdef DBUG_OFF
|
||||||
|
yyerror(ER(ER_SYNTAX_ERROR));
|
||||||
|
YYABORT;
|
||||||
|
#else
|
||||||
|
Lex->sql_command= SQLCOM_SHOW_FUNC_CODE;
|
||||||
|
Lex->spname= $3;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
show_engine_param:
|
show_engine_param:
|
||||||
STATUS_SYM
|
STATUS_SYM
|
||||||
@@ -7496,6 +7519,7 @@ keyword_sp:
|
|||||||
| CHANGED {}
|
| CHANGED {}
|
||||||
| CIPHER_SYM {}
|
| CIPHER_SYM {}
|
||||||
| CLIENT_SYM {}
|
| CLIENT_SYM {}
|
||||||
|
| CODE_SYM {}
|
||||||
| COLLATION_SYM {}
|
| COLLATION_SYM {}
|
||||||
| COLUMNS {}
|
| COLUMNS {}
|
||||||
| COMMITTED_SYM {}
|
| COMMITTED_SYM {}
|
||||||
|
Reference in New Issue
Block a user