summaryrefslogtreecommitdiff
path: root/sql/sp_head.cc
diff options
context:
space:
mode:
authorunknown <sanja@montyprogram.com>2013-06-19 14:32:14 +0300
committerunknown <sanja@montyprogram.com>2013-06-19 14:32:14 +0300
commitdfcc502ab540b4d93fe3d40d0bac15fa3ae449dd (patch)
treeab179c039dab8cb251a20efcdd65f96a1eabf9a6 /sql/sp_head.cc
parent2534521f9a7d66b48cb9ca9402e82a0c58b156d8 (diff)
downloadmariadb-git-dfcc502ab540b4d93fe3d40d0bac15fa3ae449dd.tar.gz
Finished merging wl5986 started by Igor.
Diffstat (limited to 'sql/sp_head.cc')
-rw-r--r--sql/sp_head.cc264
1 files changed, 70 insertions, 194 deletions
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 59363a7a04a..03631e107db 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -772,7 +772,7 @@ sp_head::~sp_head()
for (uint ip = 0 ; (i = get_instr(ip)) ; ip++)
delete i;
delete_dynamic(&m_instr);
- m_pcont->destroy();
+ delete m_pcont;
free_items();
/*
@@ -1078,104 +1078,6 @@ void sp_head::recursion_level_error(THD *thd)
}
-/**
- Find an SQL handler for any condition (warning or error) after execution
- of a stored routine instruction. Basically, this function looks for an
- appropriate SQL handler in RT-contexts. If an SQL handler is found, it is
- remembered in the RT-context for future activation (the context can be
- inactive at the moment).
-
- If there is no pending condition, the function just returns.
-
- If there was an error during the execution, an SQL handler for it will be
- searched within the current and outer scopes.
-
- There might be several errors in the Warning Info (that's possible by using
- SIGNAL/RESIGNAL in nested scopes) -- the function is looking for an SQL
- handler for the latest (current) error only.
-
- If there was a warning during the execution, an SQL handler for it will be
- searched within the current scope only.
-
- If several warnings were thrown during the execution and there are different
- SQL handlers for them, it is not determined which SQL handler will be chosen.
- Only one SQL handler will be executed.
-
- If warnings and errors were thrown during the execution, the error takes
- precedence. I.e. error handler will be executed. If there is no handler
- for that error, condition will remain unhandled.
-
- Once a warning or an error has been handled it is not removed from
- Warning Info.
-
- According to The Standard (quoting PeterG):
-
- An SQL procedure statement works like this ...
- SQL/Foundation 13.5 <SQL procedure statement>
- (General Rules) (greatly summarized) says:
- (1) Empty diagnostics area, thus clearing the condition.
- (2) Execute statement.
- During execution, if Exception Condition occurs,
- set Condition Area = Exception Condition and stop
- statement.
- During execution, if No Data occurs,
- set Condition Area = No Data Condition and continue
- statement.
- During execution, if Warning occurs,
- and Condition Area is not already full due to
- an earlier No Data condition, set Condition Area
- = Warning and continue statement.
- (3) Finish statement.
- At end of execution, if Condition Area is not
- already full due to an earlier No Data or Warning,
- set Condition Area = Successful Completion.
- In effect, this system means there is a precedence:
- Exception trumps No Data, No Data trumps Warning,
- Warning trumps Successful Completion.
-
- NB: "Procedure statements" include any DDL or DML or
- control statements. So CREATE and DELETE and WHILE
- and CALL and RETURN are procedure statements. But
- DECLARE and END are not procedure statements.
-
- @param thd thread handle
- @param ctx runtime context of the stored routine
-*/
-
-static void
-find_handler_after_execution(THD *thd, sp_rcontext *ctx)
-{
- if (thd->is_error())
- {
- ctx->find_handler(thd,
- thd->get_stmt_da()->sql_errno(),
- thd->get_stmt_da()->get_sqlstate(),
- Sql_condition::WARN_LEVEL_ERROR,
- thd->get_stmt_da()->message());
- }
- else if (thd->get_stmt_da()->statement_warn_count())
- {
- Diagnostics_area::Sql_condition_iterator it=
- thd->get_stmt_da()->sql_conditions();
- const Sql_condition *err;
- while ((err= it++))
- {
- if (err->get_level() != Sql_condition::WARN_LEVEL_WARN &&
- err->get_level() != Sql_condition::WARN_LEVEL_NOTE)
- continue;
-
- if (ctx->find_handler(thd,
- err->get_sql_errno(),
- err->get_sqlstate(),
- err->get_level(),
- err->get_message_text()))
- {
- break;
- }
- }
- }
-}
-
/**
Execute the routine. The main instruction jump loop is there.
@@ -1445,19 +1347,10 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
errors are not catchable by SQL handlers) or the connection has been
killed during execution.
*/
- if (!thd->is_fatal_error && !thd->killed_errno())
+ if (!thd->is_fatal_error && !thd->killed_errno() &&
+ ctx->handle_sql_condition(thd, &ip, i))
{
- /*
- Find SQL handler in the appropriate RT-contexts:
- - warnings can be handled by SQL handlers within
- the current scope only;
- - errors can be handled by any SQL handler from outer scope.
- */
- find_handler_after_execution(thd, ctx);
-
- /* If found, activate handler for the current scope. */
- if (ctx->activate_handler(thd, &ip, i, &execute_arena, &backup_arena))
- err_status= FALSE;
+ err_status= FALSE;
}
/* Reset sp_rcontext::end_partial_result_set flag. */
@@ -1743,8 +1636,7 @@ sp_head::execute_trigger(THD *thd,
init_sql_alloc(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0, MYF(0));
thd->set_n_backup_active_arena(&call_arena, &backup_arena);
- if (!(nctx= new sp_rcontext(m_pcont, 0, octx)) ||
- nctx->init(thd))
+ if (!(nctx= sp_rcontext::create(thd, m_pcont, NULL)))
{
err_status= TRUE;
goto err_with_cleanup;
@@ -1860,8 +1752,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount,
init_sql_alloc(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0, MYF(0));
thd->set_n_backup_active_arena(&call_arena, &backup_arena);
- if (!(nctx= new sp_rcontext(m_pcont, return_value_fld, octx)) ||
- nctx->init(thd))
+ if (!(nctx= sp_rcontext::create(thd, m_pcont, return_value_fld)))
{
thd->restore_active_arena(&call_arena, &backup_arena);
err_status= TRUE;
@@ -2078,7 +1969,6 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
if (! octx)
{
/* Create a temporary old context. */
- if (!(octx= new sp_rcontext(m_pcont, NULL, octx)) || octx->init(thd))
{
delete octx; /* Delete octx if it was init() that failed. */
DBUG_RETURN(TRUE);
@@ -2093,8 +1983,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
thd->spcont->callers_arena= thd;
}
- if (!(nctx= new sp_rcontext(m_pcont, NULL, octx)) ||
- nctx->init(thd))
+ if (!(nctx= sp_rcontext::create(thd, m_pcont, NULL)))
{
delete nctx; /* Delete nctx if it was init() that failed. */
thd->spcont= save_spcont;
@@ -2117,12 +2006,12 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
if (!arg_item)
break;
- sp_variable_t *spvar= m_pcont->find_variable(i);
+ sp_variable *spvar= m_pcont->find_variable(i);
if (!spvar)
continue;
- if (spvar->mode != sp_param_in)
+ if (spvar->mode != sp_variable::MODE_IN)
{
Settable_routine_parameter *srp=
arg_item->get_settable_routine_parameter();
@@ -2134,10 +2023,10 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
break;
}
- srp->set_required_privilege(spvar->mode == sp_param_inout);
+ srp->set_required_privilege(spvar->mode == sp_variable::MODE_INOUT);
}
- if (spvar->mode == sp_param_out)
+ if (spvar->mode == sp_variable::MODE_OUT)
{
Item_null *null_item= new Item_null();
Item *tmp_item= null_item;
@@ -2237,9 +2126,9 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
if (!arg_item)
break;
- sp_variable_t *spvar= m_pcont->find_variable(i);
+ sp_variable *spvar= m_pcont->find_variable(i);
- if (spvar->mode == sp_param_in)
+ if (spvar->mode == sp_variable::MODE_IN)
continue;
Settable_routine_parameter *srp=
@@ -2399,7 +2288,7 @@ sp_head::restore_lex(THD *thd)
Put the instruction on the backpatch list, associated with the label.
*/
int
-sp_head::push_backpatch(sp_instr *i, sp_label_t *lab)
+sp_head::push_backpatch(sp_instr *i, sp_label *lab)
{
bp_t *bp= (bp_t *)sql_alloc(sizeof(bp_t));
@@ -2415,7 +2304,7 @@ sp_head::push_backpatch(sp_instr *i, sp_label_t *lab)
the current position.
*/
void
-sp_head::backpatch(sp_label_t *lab)
+sp_head::backpatch(sp_label *lab)
{
bp_t *bp;
uint dest= instructions();
@@ -2427,7 +2316,7 @@ sp_head::backpatch(sp_label_t *lab)
if (bp->lab == lab)
{
DBUG_PRINT("info", ("backpatch: (m_ip %d, label 0x%lx <%s>) to dest %d",
- bp->instr->m_ip, (ulong) lab, lab->name, dest));
+ bp->instr->m_ip, (ulong) lab, lab->name.str, dest));
bp->instr->backpatch(dest, lab->ctx);
}
}
@@ -3107,7 +2996,7 @@ int sp_instr::exec_open_and_lock_tables(THD *thd, TABLE_LIST *tables)
return result;
}
-uint sp_instr::get_cont_dest()
+uint sp_instr::get_cont_dest() const
{
return (m_ip+1);
}
@@ -3261,7 +3150,7 @@ sp_instr_set::print(String *str)
{
/* set name@offset ... */
int rsrv = SP_INSTR_UINT_MAXLEN+6;
- sp_variable_t *var = m_ctx->find_variable(m_offset);
+ sp_variable *var = m_ctx->find_variable(m_offset);
/* 'var' should always be non-null, but just in case... */
if (var)
@@ -3314,7 +3203,7 @@ sp_instr_set_trigger_field::print(String *str)
sp_instr_opt_meta
*/
-uint sp_instr_opt_meta::get_cont_dest()
+uint sp_instr_opt_meta::get_cont_dest() const
{
return m_cont_dest;
}
@@ -3532,14 +3421,12 @@ int
sp_instr_hpush_jump::execute(THD *thd, uint *nextp)
{
DBUG_ENTER("sp_instr_hpush_jump::execute");
- List_iterator_fast<sp_cond_type_t> li(m_cond);
- sp_cond_type_t *p;
- while ((p= li++))
- thd->spcont->push_handler(p, m_ip+1, m_type);
+ int ret= thd->spcont->push_handler(m_handler, m_ip + 1);
*nextp= m_dest;
- DBUG_RETURN(0);
+
+ DBUG_RETURN(ret);
}
@@ -3549,27 +3436,22 @@ sp_instr_hpush_jump::print(String *str)
/* hpush_jump dest fsize type */
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(' ');
str->qs_append(m_frame);
- switch (m_type) {
- case SP_HANDLER_NONE:
- str->qs_append(STRING_WITH_LEN(" NONE")); // This would be a bug
- break;
- case SP_HANDLER_EXIT:
+
+ switch (m_handler->type) {
+ case sp_handler::EXIT:
str->qs_append(STRING_WITH_LEN(" EXIT"));
break;
- case SP_HANDLER_CONTINUE:
+ case sp_handler::CONTINUE:
str->qs_append(STRING_WITH_LEN(" CONTINUE"));
break;
- case SP_HANDLER_UNDO:
- str->qs_append(STRING_WITH_LEN(" UNDO"));
- break;
default:
- // This would be a bug as well
- str->qs_append(STRING_WITH_LEN(" UNKNOWN:"));
- str->qs_append(m_type);
+ // The handler type must be either CONTINUE or EXIT.
+ DBUG_ASSERT(0);
}
}
@@ -3597,7 +3479,7 @@ sp_instr_hpush_jump::opt_mark(sp_head *sp, List<sp_instr> *leads)
above, so we start on m_dest+1 here.
m_opt_hpop is the hpop marking the end of the handler scope.
*/
- if (m_type == SP_HANDLER_CONTINUE)
+ if (m_handler->type == sp_handler::CONTINUE)
{
for (uint scope_ip= m_dest+1; scope_ip <= m_opt_hpop; scope_ip++)
sp->add_mark_lead(scope_ip, leads);
@@ -3639,13 +3521,11 @@ int
sp_instr_hreturn::execute(THD *thd, uint *nextp)
{
DBUG_ENTER("sp_instr_hreturn::execute");
- if (m_dest)
- *nextp= m_dest;
- else
- {
- *nextp= thd->spcont->pop_hstack();
- }
- thd->spcont->exit_handler();
+
+ uint continue_ip= thd->spcont->exit_handler(thd->get_stmt_da());
+
+ *nextp= m_dest ? m_dest : continue_ip;
+
DBUG_RETURN(0);
}
@@ -3657,12 +3537,17 @@ sp_instr_hreturn::print(String *str)
if (str->reserve(SP_INSTR_UINT_MAXLEN*2 + 9))
return;
str->qs_append(STRING_WITH_LEN("hreturn "));
- str->qs_append(m_frame);
if (m_dest)
{
- str->qs_append(' ');
+ // NOTE: this is legacy: hreturn instruction for EXIT handler
+ // should print out 0 as frame index.
+ str->qs_append(STRING_WITH_LEN("0 "));
str->qs_append(m_dest);
}
+ else
+ {
+ str->qs_append(m_frame);
+ }
}
@@ -3694,41 +3579,32 @@ sp_instr_hreturn::opt_mark(sp_head *sp, List<sp_instr> *leads)
int
sp_instr_cpush::execute(THD *thd, uint *nextp)
{
- Query_arena backup_arena;
DBUG_ENTER("sp_instr_cpush::execute");
- /*
- We should create cursors in the callers arena, as
- it could be (and usually is) used in several instructions.
- */
- thd->set_n_backup_active_arena(thd->spcont->callers_arena, &backup_arena);
-
- thd->spcont->push_cursor(&m_lex_keeper, this);
-
- thd->restore_active_arena(thd->spcont->callers_arena, &backup_arena);
+ int ret= thd->spcont->push_cursor(&m_lex_keeper, this);
*nextp= m_ip+1;
- DBUG_RETURN(0);
+ DBUG_RETURN(ret);
}
void
sp_instr_cpush::print(String *str)
{
- LEX_STRING n;
- my_bool found= m_ctx->find_cursor(m_cursor, &n);
+ const LEX_STRING *cursor_name= m_ctx->find_cursor(m_cursor);
+
/* cpush name@offset */
uint rsrv= SP_INSTR_UINT_MAXLEN+7;
- if (found)
- rsrv+= n.length;
+ if (cursor_name)
+ rsrv+= cursor_name->length;
if (str->reserve(rsrv))
return;
str->qs_append(STRING_WITH_LEN("cpush "));
- if (found)
+ if (cursor_name)
{
- str->qs_append(n.str, n.length);
+ str->qs_append(cursor_name->str, cursor_name->length);
str->qs_append('@');
}
str->qs_append(m_cursor);
@@ -3816,19 +3692,19 @@ sp_instr_copen::exec_core(THD *thd, uint *nextp)
void
sp_instr_copen::print(String *str)
{
- LEX_STRING n;
- my_bool found= m_ctx->find_cursor(m_cursor, &n);
+ const LEX_STRING *cursor_name= m_ctx->find_cursor(m_cursor);
+
/* copen name@offset */
uint rsrv= SP_INSTR_UINT_MAXLEN+7;
- if (found)
- rsrv+= n.length;
+ if (cursor_name)
+ rsrv+= cursor_name->length;
if (str->reserve(rsrv))
return;
str->qs_append(STRING_WITH_LEN("copen "));
- if (found)
+ if (cursor_name)
{
- str->qs_append(n.str, n.length);
+ str->qs_append(cursor_name->str, cursor_name->length);
str->qs_append('@');
}
str->qs_append(m_cursor);
@@ -3858,19 +3734,19 @@ sp_instr_cclose::execute(THD *thd, uint *nextp)
void
sp_instr_cclose::print(String *str)
{
- LEX_STRING n;
- my_bool found= m_ctx->find_cursor(m_cursor, &n);
+ const LEX_STRING *cursor_name= m_ctx->find_cursor(m_cursor);
+
/* cclose name@offset */
uint rsrv= SP_INSTR_UINT_MAXLEN+8;
- if (found)
- rsrv+= n.length;
+ if (cursor_name)
+ rsrv+= cursor_name->length;
if (str->reserve(rsrv))
return;
str->qs_append(STRING_WITH_LEN("cclose "));
- if (found)
+ if (cursor_name)
{
- str->qs_append(n.str, n.length);
+ str->qs_append(cursor_name->str, cursor_name->length);
str->qs_append('@');
}
str->qs_append(m_cursor);
@@ -3899,21 +3775,21 @@ sp_instr_cfetch::execute(THD *thd, uint *nextp)
void
sp_instr_cfetch::print(String *str)
{
- List_iterator_fast<struct sp_variable> li(m_varlist);
- sp_variable_t *pv;
- LEX_STRING n;
- my_bool found= m_ctx->find_cursor(m_cursor, &n);
+ List_iterator_fast<sp_variable> li(m_varlist);
+ sp_variable *pv;
+ const LEX_STRING *cursor_name= m_ctx->find_cursor(m_cursor);
+
/* cfetch name@offset vars... */
uint rsrv= SP_INSTR_UINT_MAXLEN+8;
- if (found)
- rsrv+= n.length;
+ if (cursor_name)
+ rsrv+= cursor_name->length;
if (str->reserve(rsrv))
return;
str->qs_append(STRING_WITH_LEN("cfetch "));
- if (found)
+ if (cursor_name)
{
- str->qs_append(n.str, n.length);
+ str->qs_append(cursor_name->str, cursor_name->length);
str->qs_append('@');
}
str->qs_append(m_cursor);