Commit d71d1242 authored by pem@mysql.com's avatar pem@mysql.com

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

into  mysql.com:/usr/home/pem/show-sp-code/mysql-5.0
parents a0487a82 962d2df6
-- 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[] = {
{ "CIPHER", SYM(CIPHER_SYM)},
{ "CLIENT", SYM(CLIENT_SYM)},
{ "CLOSE", SYM(CLOSE_SYM)},
{ "CODE", SYM(CODE_SYM)},
{ "COLLATE", SYM(COLLATE_SYM)},
{ "COLLATION", SYM(COLLATION_SYM)},
{ "COLUMN", SYM(COLUMN_SYM)},
......
This diff is collapsed.
......@@ -304,6 +304,12 @@ public:
return test(m_flags &
(CONTAINS_DYNAMIC_SQL|MULTI_RESULTS|HAS_SET_AUTOCOMMIT_STMT));
}
#ifndef DBUG_OFF
int show_routine_code(THD *thd);
#endif
private:
MEM_ROOT *m_thd_root; // Temp. store for thd's mem_root
......@@ -865,8 +871,8 @@ class sp_instr_cpush : public sp_instr
public:
sp_instr_cpush(uint ip, sp_pcontext *ctx, LEX *lex)
: sp_instr(ip, ctx), m_lex_keeper(lex, TRUE)
sp_instr_cpush(uint ip, sp_pcontext *ctx, LEX *lex, uint offset)
: sp_instr(ip, ctx), m_lex_keeper(lex, TRUE), m_cursor(offset)
{}
virtual ~sp_instr_cpush()
......@@ -885,6 +891,7 @@ public:
private:
sp_lex_keeper m_lex_keeper;
uint m_cursor; /* Frame offset (for debugging) */
}; // class sp_instr_cpush : public sp_instr
......
......@@ -169,6 +169,28 @@ sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped)
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
sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type,
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 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 *
find_pvar(LEX_STRING *name, my_bool scoped=0);
// Find by index
// Find by offset
sp_pvar_t *
find_pvar(uint i)
{
sp_pvar_t *p;
if (i < m_pvar.elements)
get_dynamic(&m_pvar, (gptr)&p, i);
else
p= NULL;
return p;
}
find_pvar(uint offset);
//
// Labels
......@@ -261,6 +252,10 @@ class sp_pcontext : public Sql_alloc
my_bool
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
max_cursors()
{
......
......@@ -90,6 +90,7 @@ enum enum_sql_command {
SQLCOM_CREATE_TRIGGER, SQLCOM_DROP_TRIGGER,
SQLCOM_XA_START, SQLCOM_XA_END, SQLCOM_XA_PREPARE,
SQLCOM_XA_COMMIT, SQLCOM_XA_ROLLBACK, SQLCOM_XA_RECOVER,
SQLCOM_SHOW_PROC_CODE, SQLCOM_SHOW_FUNC_CODE,
/* This should be the last !!! */
SQLCOM_END
......
......@@ -4548,6 +4548,31 @@ end_with_restore_list:
lex->wild->ptr() : NullS));
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:
{
if (end_active_trans(thd))
......
......@@ -175,6 +175,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token CLIENT_SYM
%token CLOSE_SYM
%token COALESCE
%token CODE_SYM
%token COLLATE_SYM
%token COLLATION_SYM
%token COLUMNS
......@@ -1693,7 +1694,8 @@ sp_decl:
delete $5;
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);
ctx->push_cursor(&$2);
$$.vars= $$.conds= $$.hndlrs= 0;
......@@ -6587,7 +6589,28 @@ show_param:
YYABORT;
if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
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:
STATUS_SYM
......@@ -7496,6 +7519,7 @@ keyword_sp:
| CHANGED {}
| CIPHER_SYM {}
| CLIENT_SYM {}
| CODE_SYM {}
| COLLATION_SYM {}
| COLUMNS {}
| 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