Commit d213bf04 authored by unknown's avatar unknown

Merge mysql.com:/usr/local/bk/mysql-5.0

into  mysql.com:/usr/home/pem/show-sp-code/mysql-5.0


sql/sp_head.h:
  Auto merged
sql/sql_parse.cc:
  Auto merged
sql/sql_yacc.yy:
  Auto merged
sql/sp_head.cc:
  Merge fixes (STRING_WITH_LEN in string append calls).
parents 929e6e05 6553362b
-- require r/is_debug_build.require
--disable_query_log
select instr(version(), "debug") > 0;
--enable_query_log
instr(version(), "debug") > 0
1
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;
#
# 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[] = { ...@@ -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)},
......
...@@ -105,6 +105,8 @@ sp_get_flags_for_command(LEX *lex) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 "));
/* 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((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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
str->reserve(12); my_bool found= m_ctx->find_cursor(m_cursor, &n);
str->append(STRING_WITH_LEN("cfetch ")); /* cfetch name@offset vars... */
uint rsrv= SP_INSTR_UINT_MAXLEN+8;
if (found)
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) ...@@ -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: ...@@ -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 ...@@ -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: ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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 ...@@ -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 { ...@@ -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: ...@@ -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); ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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 {}
......
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