#At file:///home/malff/BZR-TREE/mysql-6.0-wl2110-review/
2680 Marc Alff 2008-08-25 [merge]
Partial merge
modified:
sql/item.cc
sql/sp_head.cc
sql/sp_head.h
sql/sp_pcontext.h
sql/sp_rcontext.cc
sql/sp_rcontext.h
=== modified file 'sql/item.cc'
--- a/sql/item.cc 2008-08-07 03:05:33 +0000
+++ b/sql/item.cc 2008-08-25 22:07:23 +0000
@@ -1109,7 +1109,7 @@ Item_splocal::Item_splocal(const LEX_STR
Item *
Item_splocal::this_item()
{
- DBUG_ASSERT(m_sp == m_thd->spcont->sp);
+ DBUG_ASSERT(m_sp == m_thd->spcont->m_sp);
return m_thd->spcont->get_item(m_var_idx);
}
@@ -1117,7 +1117,7 @@ Item_splocal::this_item()
const Item *
Item_splocal::this_item() const
{
- DBUG_ASSERT(m_sp == m_thd->spcont->sp);
+ DBUG_ASSERT(m_sp == m_thd->spcont->m_sp);
return m_thd->spcont->get_item(m_var_idx);
}
@@ -1126,7 +1126,7 @@ Item_splocal::this_item() const
Item **
Item_splocal::this_item_addr(THD *thd, Item **)
{
- DBUG_ASSERT(m_sp == thd->spcont->sp);
+ DBUG_ASSERT(m_sp == thd->spcont->m_sp);
return thd->spcont->get_item_addr(m_var_idx);
}
@@ -1161,7 +1161,7 @@ Item_case_expr::Item_case_expr(uint case
Item *
Item_case_expr::this_item()
{
- DBUG_ASSERT(m_sp == m_thd->spcont->sp);
+ DBUG_ASSERT(m_sp == m_thd->spcont->m_sp);
return m_thd->spcont->get_case_expr(m_case_expr_id);
}
@@ -1171,7 +1171,7 @@ Item_case_expr::this_item()
const Item *
Item_case_expr::this_item() const
{
- DBUG_ASSERT(m_sp == m_thd->spcont->sp);
+ DBUG_ASSERT(m_sp == m_thd->spcont->m_sp);
return m_thd->spcont->get_case_expr(m_case_expr_id);
}
@@ -1180,7 +1180,7 @@ Item_case_expr::this_item() const
Item **
Item_case_expr::this_item_addr(THD *thd, Item **)
{
- DBUG_ASSERT(m_sp == thd->spcont->sp);
+ DBUG_ASSERT(m_sp == thd->spcont->m_sp);
return thd->spcont->get_case_expr_addr(m_case_expr_id);
}
=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc 2008-08-18 18:12:46 +0000
+++ b/sql/sp_head.cc 2008-08-25 22:07:23 +0000
@@ -1263,9 +1263,9 @@ sp_head::execute(THD *thd)
*/
if (ctx)
{
- uint hf;
+ uint handler_index;
- switch (ctx->found_handler(&hip, &hf)) {
+ switch (ctx->found_handler(& hip, & handler_index)) {
case SP_HANDLER_NONE:
break;
case SP_HANDLER_CONTINUE:
@@ -1274,16 +1274,20 @@ sp_head::execute(THD *thd)
ctx->push_hstack(i->get_cont_dest());
/* Fall through */
default:
+ if (thd->end_partial_result_set)
+ thd->protocol->end_partial_result_set(thd);
ip= hip;
err_status= FALSE;
ctx->clear_handler();
- ctx->enter_handler(hip);
+ ctx->enter_handler(hip, handler_index);
thd->clear_error();
thd->is_fatal_error= 0;
thd->killed= THD::NOT_KILLED;
thd->mysys_var->abort= 0;
continue;
}
+
+ thd->end_partial_result_set= FALSE;
}
} while (!err_status && !thd->killed && !thd->is_fatal_error);
@@ -1525,17 +1529,13 @@ sp_head::execute_trigger(THD *thd,
init_sql_alloc(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0);
thd->set_n_backup_active_arena(&call_arena, &backup_arena);
- if (!(nctx= new sp_rcontext(m_pcont, 0, octx)) ||
+ if (!(nctx= new sp_rcontext(this, m_pcont, 0, octx)) ||
nctx->init(thd))
{
err_status= TRUE;
goto err_with_cleanup;
}
-#ifndef DBUG_OFF
- nctx->sp= this;
-#endif
-
thd->spcont= nctx;
err_status= execute(thd);
@@ -1642,7 +1642,7 @@ sp_head::execute_function(THD *thd, Item
init_sql_alloc(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0);
thd->set_n_backup_active_arena(&call_arena, &backup_arena);
- if (!(nctx= new sp_rcontext(m_pcont, return_value_fld, octx)) ||
+ if (!(nctx= new sp_rcontext(this, m_pcont, return_value_fld, octx)) ||
nctx->init(thd))
{
thd->restore_active_arena(&call_arena, &backup_arena);
@@ -1658,10 +1658,6 @@ sp_head::execute_function(THD *thd, Item
*/
thd->restore_active_arena(&call_arena, &backup_arena);
-#ifndef DBUG_OFF
- nctx->sp= this;
-#endif
-
/* Pass arguments. */
for (arg_no= 0; arg_no < argcount; arg_no++)
{
@@ -1846,32 +1842,26 @@ sp_head::execute_procedure(THD *thd, Lis
save_spcont= octx= thd->spcont;
if (! octx)
{ // Create a temporary old context
- if (!(octx= new sp_rcontext(m_pcont, NULL, octx)) ||
+ if (!(octx= new sp_rcontext(this, m_pcont, NULL, octx)) ||
octx->init(thd))
{
delete octx; /* Delete octx if it was init() that failed. */
DBUG_RETURN(TRUE);
}
-#ifndef DBUG_OFF
- octx->sp= 0;
-#endif
thd->spcont= octx;
/* set callers_arena to thd, for upper-level function to work */
thd->spcont->callers_arena= thd;
}
- if (!(nctx= new sp_rcontext(m_pcont, NULL, octx)) ||
+ if (!(nctx= new sp_rcontext(this, m_pcont, NULL, octx)) ||
nctx->init(thd))
{
delete nctx; /* Delete nctx if it was init() that failed. */
thd->spcont= save_spcont;
DBUG_RETURN(TRUE);
}
-#ifndef DBUG_OFF
- nctx->sp= this;
-#endif
if (params > 0)
{
@@ -3218,7 +3208,7 @@ sp_instr_hpush_jump::execute(THD *thd, u
sp_cond_type_t *p;
while ((p= li++))
- thd->spcont->push_handler(p, m_ip+1, m_type, m_frame);
+ thd->spcont->push_handler(p, m_ip+1, m_type);
*nextp= m_dest;
DBUG_RETURN(0);
=== modified file 'sql/sp_head.h'
--- a/sql/sp_head.h 2008-07-07 23:15:08 +0000
+++ b/sql/sp_head.h 2008-07-23 00:27:12 +0000
@@ -152,8 +152,9 @@ class sp_head :private Query_arena
sp_head(const sp_head &); /**< Prevent use of these */
void operator=(sp_head &);
- MEM_ROOT main_mem_root;
public:
+ MEM_ROOT main_mem_root;
+
/** Possible values of m_flags */
enum {
HAS_RETURN= 1, // For FUNCTIONs only: is set if has RETURN
=== modified file 'sql/sp_pcontext.h'
--- a/sql/sp_pcontext.h 2007-06-10 10:43:57 +0000
+++ b/sql/sp_pcontext.h 2008-07-23 00:27:12 +0000
@@ -71,7 +71,7 @@ typedef struct sp_label
typedef struct sp_cond_type
{
enum { number, state, warning, notfound, exception } type;
- char sqlstate[6];
+ char sqlstate[SQLSTATE_LENGTH+1];
uint mysqlerr;
} sp_cond_type_t;
=== modified file 'sql/sp_rcontext.cc'
--- a/sql/sp_rcontext.cc 2008-01-23 22:36:57 +0000
+++ b/sql/sp_rcontext.cc 2008-08-14 17:49:58 +0000
@@ -29,10 +29,11 @@
#include "sp_pcontext.h"
-sp_rcontext::sp_rcontext(sp_pcontext *root_parsing_ctx,
+sp_rcontext::sp_rcontext(sp_head *sp, sp_pcontext *root_parsing_ctx,
Field *return_value_fld,
sp_rcontext *prev_runtime_ctx)
- :m_root_parsing_ctx(root_parsing_ctx),
+ :m_sp(sp),
+ m_root_parsing_ctx(root_parsing_ctx),
m_var_table(0),
m_var_items(0),
m_return_value_fld(return_value_fld),
@@ -68,27 +69,37 @@ sp_rcontext::~sp_rcontext()
bool sp_rcontext::init(THD *thd)
{
+ uint i;
+ uint handler_count= m_root_parsing_ctx->max_handler_index();
+
in_sub_stmt= thd->in_sub_stmt;
if (init_var_table(thd) || init_var_items())
return TRUE;
- return
+ if (
!(m_handler=
- (sp_handler_t*)thd->alloc(m_root_parsing_ctx->max_handler_index() *
- sizeof(sp_handler_t))) ||
+ (sp_handler_t*)thd->alloc(handler_count * sizeof(sp_handler_t))) ||
+ !(m_raised_conditions=
+ (SQL_condition**)thd->alloc(handler_count * sizeof(SQL_condition*))) ||
!(m_hstack=
- (uint*)thd->alloc(m_root_parsing_ctx->max_handler_index() *
- sizeof(uint))) ||
+ (uint*)thd->alloc(handler_count * sizeof(uint))) ||
!(m_in_handler=
- (uint*)thd->alloc(m_root_parsing_ctx->max_handler_index() *
- sizeof(uint))) ||
+ (sp_active_handler_t*)thd->alloc(handler_count *
+ sizeof(sp_active_handler_t))) ||
!(m_cstack=
(sp_cursor**)thd->alloc(m_root_parsing_ctx->max_cursor_index() *
sizeof(sp_cursor*))) ||
!(m_case_expr_holders=
(Item_cache**)thd->calloc(m_root_parsing_ctx->get_num_case_exprs() *
- sizeof (Item_cache*)));
+ sizeof (Item_cache*)))
+ )
+ return TRUE;
+
+ for (i = 0; i < handler_count; i++)
+ m_raised_conditions[i]= NULL;
+
+ return FALSE;
}
@@ -194,13 +205,15 @@ sp_rcontext::set_return_value(THD *thd,
*/
bool
-sp_rcontext::find_handler(THD *thd, uint sql_errno,
- MYSQL_ERROR::enum_warning_level level)
+sp_rcontext::find_handler(THD *thd, const SQL_condition *cond)
{
if (m_hfound >= 0)
return 1; // Already got one
- const char *sqlstate= mysql_errno_to_sqlstate(sql_errno);
+ uint sql_errno= cond->get_sql_errno();
+ MYSQL_ERROR::enum_warning_level level= cond->get_level();
+
+ const char *sqlstate= cond->get_sqlstate();
int i= m_hcount, found= -1;
/*
@@ -220,7 +233,7 @@ sp_rcontext::find_handler(THD *thd, uint
/* Check active handlers, to avoid invoking one recursively */
while (j--)
- if (m_in_handler[j] == m_handler[i].handler)
+ if (m_in_handler[j].ip == m_handler[i].handler)
break;
if (j >= 0)
continue; // Already executing this handler
@@ -264,10 +277,16 @@ sp_rcontext::find_handler(THD *thd, uint
*/
if (m_prev_runtime_ctx && IS_EXCEPTION_CONDITION(sqlstate) &&
level == MYSQL_ERROR::WARN_LEVEL_ERROR)
- return m_prev_runtime_ctx->find_handler(thd, sql_errno, level);
+ return m_prev_runtime_ctx->find_handler(thd, cond);
return FALSE;
}
+
m_hfound= found;
+
+ SQL_condition *raised;
+ raised= SQL_condition::deep_copy(thd, & m_sp->main_mem_root, cond) ;
+ m_raised_conditions[m_hfound]= raised;
+
return TRUE;
}
@@ -293,22 +312,22 @@ sp_rcontext::find_handler(THD *thd, uint
FALSE if no handler was found.
*/
bool
-sp_rcontext::handle_error(uint sql_errno,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd)
+sp_rcontext::handle_condition(THD *thd, const SQL_condition *cond)
{
- MYSQL_ERROR::enum_warning_level elevated_level= level;
-
-
/* Depending on the sql_mode of execution,
warnings may be considered errors */
- if ((level == MYSQL_ERROR::WARN_LEVEL_WARN) &&
+ if ((cond->m_level == MYSQL_ERROR::WARN_LEVEL_WARN) &&
thd->really_abort_on_warning())
{
- elevated_level= MYSQL_ERROR::WARN_LEVEL_ERROR;
+ SQL_condition elevated_cond(thd->mem_root);
+ elevated_cond.set(thd, cond->m_sql_errno,
+ cond->get_message_text(),
+ MYSQL_ERROR::WARN_LEVEL_ERROR,
+ MYF(0));
+ return find_handler(thd, & elevated_cond);
}
- return find_handler(thd, sql_errno, elevated_level);
+ return find_handler(thd, cond);
}
void
@@ -335,7 +354,7 @@ sp_rcontext::pop_cursors(uint count)
}
void
-sp_rcontext::push_handler(struct sp_cond_type *cond, uint h, int type, uint f)
+sp_rcontext::push_handler(struct sp_cond_type *cond, uint h, int type)
{
DBUG_ENTER("sp_rcontext::push_handler");
DBUG_ASSERT(m_hcount < m_root_parsing_ctx->max_handler_index());
@@ -343,7 +362,6 @@ sp_rcontext::push_handler(struct sp_cond
m_handler[m_hcount].cond= cond;
m_handler[m_hcount].handler= h;
m_handler[m_hcount].type= type;
- m_handler[m_hcount].foffset= f;
m_hcount+= 1;
DBUG_PRINT("info", ("m_hcount: %d", m_hcount));
@@ -382,11 +400,13 @@ sp_rcontext::pop_hstack()
}
void
-sp_rcontext::enter_handler(int hid)
+sp_rcontext::enter_handler(uint hip, uint hindex)
{
DBUG_ENTER("sp_rcontext::enter_handler");
DBUG_ASSERT(m_ihsp < m_root_parsing_ctx->max_handler_index());
- m_in_handler[m_ihsp++]= hid;
+ m_in_handler[m_ihsp].ip= hip;
+ m_in_handler[m_ihsp].index= hindex;
+ m_ihsp++;
DBUG_PRINT("info", ("m_ihsp: %d", m_ihsp));
DBUG_VOID_RETURN;
}
@@ -396,11 +416,32 @@ sp_rcontext::exit_handler()
{
DBUG_ENTER("sp_rcontext::exit_handler");
DBUG_ASSERT(m_ihsp);
+ uint hindex= m_in_handler[m_ihsp-1].index;
+ DBUG_ASSERT(m_raised_conditions[hindex]);
+ delete m_raised_conditions[hindex];
+ m_raised_conditions[hindex]= NULL;
m_ihsp-= 1;
DBUG_PRINT("info", ("m_ihsp: %d", m_ihsp));
DBUG_VOID_RETURN;
}
+SQL_condition*
+sp_rcontext::raised_condition() const
+{
+ if (m_ihsp > 0)
+ {
+ uint hindex= m_in_handler[m_ihsp - 1].index;
+ SQL_condition *raised= m_raised_conditions[hindex];
+ DBUG_ASSERT(raised);
+ return raised;
+ }
+
+ if (m_prev_runtime_ctx)
+ return m_prev_runtime_ctx->raised_condition();
+
+ return NULL;
+}
+
int
sp_rcontext::set_variable(THD *thd, uint var_idx, Item **value)
=== modified file 'sql/sp_rcontext.h'
--- a/sql/sp_rcontext.h 2008-01-23 20:26:41 +0000
+++ b/sql/sp_rcontext.h 2008-07-23 00:27:12 +0000
@@ -34,12 +34,21 @@ class sp_instr_cpush;
typedef struct
{
+ /** Condition caught by this HANDLER. */
struct sp_cond_type *cond;
- uint handler; // Location of handler
+ /** Location (instruction pointer) of the handler code. */
+ uint handler;
+ /** Handler type (EXIT, CONTINUE). */
int type;
- uint foffset; // Frame offset for the handlers declare level
} sp_handler_t;
+typedef struct
+{
+ /** Instruction pointer of the active handler. */
+ uint ip;
+ /** Handler index of the active handler. */
+ uint index;
+} sp_active_handler_t;
/*
This class is a runtime context of a Stored Routine. It is used in an
@@ -75,16 +84,10 @@ class sp_rcontext : public Sql_alloc
*/
Query_arena *callers_arena;
-#ifndef DBUG_OFF
- /*
- The routine for which this runtime context is created. Used for checking
- if correct runtime context is used for variable handling.
- */
- sp_head *sp;
-#endif
+ sp_head *m_sp;
- sp_rcontext(sp_pcontext *root_parsing_ctx, Field *return_value_fld,
- sp_rcontext *prev_runtime_ctx);
+ sp_rcontext(sp_head *sp, sp_pcontext *root_parsing_ctx,
+ Field *return_value_fld, sp_rcontext *prev_runtime_ctx);
bool init(THD *thd);
~sp_rcontext();
@@ -107,31 +110,31 @@ class sp_rcontext : public Sql_alloc
return m_return_value_set;
}
- void push_handler(struct sp_cond_type *cond, uint h, int type, uint f);
+ void push_handler(struct sp_cond_type *cond, uint h, int type);
void pop_handlers(uint count);
// Returns 1 if a handler was found, 0 otherwise.
bool
- find_handler(THD *thd, uint sql_errno,MYSQL_ERROR::enum_warning_level level);
+ find_handler(THD *thd, const SQL_condition *cond);
// If there is an error handler for this error, handle it and return TRUE.
- bool
- handle_error(uint sql_errno,
- MYSQL_ERROR::enum_warning_level level,
- THD *thd);
+ bool handle_condition(THD *thd, const SQL_condition *cond);
+
// Returns handler type and sets *ip to location if one was found
inline int
- found_handler(uint *ip, uint *fp)
+ found_handler(uint *ip, uint *index)
{
if (m_hfound < 0)
return SP_HANDLER_NONE;
*ip= m_handler[m_hfound].handler;
- *fp= m_handler[m_hfound].foffset;
+ *index= m_hfound;
return m_handler[m_hfound].type;
}
+ SQL_condition* raised_condition() const;
+
// Returns true if we found a handler in this context
inline bool
found_handler_here()
@@ -150,7 +153,12 @@ class sp_rcontext : public Sql_alloc
uint pop_hstack();
- void enter_handler(int hid);
+ /**
+ Enter a SQL exception handler.
+ @param hip the handler instruction pointer
+ @param index the handler index
+ */
+ void enter_handler(uint hip, uint index);
void exit_handler();
@@ -214,10 +222,18 @@ private:
bool in_sub_stmt;
sp_handler_t *m_handler; // Visible handlers
+
+ /**
+ SQL conditions caught by each handler.
+ This is an array indexed by handler index.
+ */
+ SQL_condition ** m_raised_conditions;
+
uint m_hcount; // Stack pointer for m_handler
uint *m_hstack; // Return stack for continue handlers
uint m_hsp; // Stack pointer for m_hstack
- uint *m_in_handler; // Active handler, for recursion check
+ /** Active handler stack. */
+ sp_active_handler_t *m_in_handler;
uint m_ihsp; // Stack pointer for m_in_handler
int m_hfound; // Set by find_handler; -1 if not found
| Thread |
|---|
| • bzr commit into mysql-6.0-wl2110-review branch (marc.alff:2680) | Marc Alff | 26 Aug |