X-Account-Key: account4 X-UIDL: 1153746480.180772 X-Mozilla-Status: 0001 X-Mozilla-Status2: 00000000 X-Mozilla-Keys: Return-Path: Received: from mailget.mysql.com ([unix socket]) by mailget (Cyrus v2.3.1-Invoca-RPM-2.3.1-2.8.fc5) with LMTPA; Wed, 23 Jul 2008 02:27:32 +0200 X-Sieve: CMU Sieve 2.3 Received: from mail.mysql.com (mail.mysql.com [10.100.1.21]) by mailget.mysql.com (8.13.8/8.13.8) with ESMTP id m6N0RWkb010084 for ; Wed, 23 Jul 2008 02:27:32 +0200 Received: from mailgate-b.mysql.com (mailgate-b.mysql.com [10.128.18.33]) by mail.mysql.com (8.13.3/8.13.3) with ESMTP id m6N0RUja007246 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 23 Jul 2008 02:27:30 +0200 Received: from lists.mysql.com (lists.mysql.com [10.100.1.37]) by mailgate-b.mysql.com (8.13.8/8.13.8) with SMTP id m6N0RTsx014181 for ; Wed, 23 Jul 2008 02:27:29 +0200 Received: (qmail 23500 invoked by uid 510); 23 Jul 2008 00:27:28 -0000 Mailing-List: contact commits-help@lists.mysql.com; run by ezmlm List-ID: Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Archive: http://lists.mysql.com/commits/50236 Delivered-To: mailing list commits@lists.mysql.com Received: (qmail 23475 invoked by uid 509); 23 Jul 2008 00:27:28 -0000 MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit From: Marc Alff Subject: bzr commit into mysql-6.0-wl2110-review branch (marc.alff:2675) WL#2110 To: commits@lists.mysql.com User-Agent: Bazaar (1.4) X-CSetKey: marc.alff@sun.com-20080723002712-t4quq03kuea5ugcx X-Worklog: 2110 X-bzr-action: commit X-bzr-revid: marc.alff@sun.com-20080723002712-t4quq03kuea5ugcx X-bzr-revno: 2675 Message-Id: <20080723002718.5EDB21DC614@lambda.WEBLAB> Date: Tue, 22 Jul 2008 18:27:18 -0600 (MDT) X-Cxn-Txn: 56108100,34985433 #At file:///home/malff/BZR-TREE/mysql-6.0-wl2110-review-part5/ 2675 Marc Alff 2008-07-22 WL#2110 (Stored Procedures: Implement SIGNAL) Formal review part 5/10: Stored procedures This patch implements changes in stored procedures, to support RESIGNAL. In particular, a SQL condition caught by a stored procedure SQL HANDLER is preserved, so it can be re-thrown using the RESIGNAL statement in the HANDLER. modified: sql/item.cc sql/sp_head.cc sql/sp_head.h sql/sp_pcontext.cc sql/sp_pcontext.h sql/sp_rcontext.cc sql/sp_rcontext.h === modified file 'sql/item.cc' --- a/sql/item.cc 2008-07-14 14:56:49 +0000 +++ b/sql/item.cc 2008-07-23 00:27:12 +0000 @@ -1106,7 +1106,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); } @@ -1114,7 +1114,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); } @@ -1123,7 +1123,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); } @@ -1158,7 +1158,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); } @@ -1168,7 +1168,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); } @@ -1177,7 +1177,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-06-28 11:00:59 +0000 +++ b/sql/sp_head.cc 2008-07-23 00:27:12 +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) { @@ -3210,7 +3200,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.cc' --- a/sql/sp_pcontext.cc 2008-04-09 00:56:49 +0000 +++ b/sql/sp_pcontext.cc 2008-07-23 00:27:12 +0000 @@ -51,7 +51,7 @@ sp_cond_check(LEX_STRING *sqlstate) (c < 'A' || 'Z' < c)) return FALSE; } - if (strcmp(sqlstate->str, "00000") == 0) + if (strncmp(sqlstate->str, "00", 2) == 0) return FALSE; return TRUE; } === 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-07-23 00:27:12 +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->m_sql_errno; + MYSQL_ERROR::enum_warning_level level= cond->m_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 -- MySQL Code Commits Mailing List For list archives: http://lists.mysql.com/commits To unsubscribe: http://lists.mysql.com/commits?unsub=marc.alff@mysql.com