diff options
author | Jon Olav Hauglid <jon.hauglid@sun.com> | 2010-06-06 13:19:29 +0200 |
---|---|---|
committer | Jon Olav Hauglid <jon.hauglid@sun.com> | 2010-06-06 13:19:29 +0200 |
commit | 142a162c665704ce5b4d5b671d05a068661c088a (patch) | |
tree | def1ebab09889a8f09a9fcd074c8a672689376af /sql/sp_head.cc | |
parent | cbf4019a1b3ec82bdcd9a65db114908a920fb01c (diff) | |
parent | 60a9d9bbb94ac03159bcc2d75b649abb1c9dc956 (diff) | |
download | mariadb-git-142a162c665704ce5b4d5b671d05a068661c088a.tar.gz |
manual merge from mysql-trunk-bugfixing
Conflicts:
Text conflict in mysql-test/r/archive.result
Contents conflict in mysql-test/r/innodb_bug38231.result
Text conflict in mysql-test/r/mdl_sync.result
Text conflict in mysql-test/suite/binlog/t/disabled.def
Text conflict in mysql-test/suite/rpl_ndb/r/rpl_ndb_binlog_format_errors.result
Text conflict in mysql-test/t/archive.test
Contents conflict in mysql-test/t/innodb_bug38231.test
Text conflict in mysql-test/t/mdl_sync.test
Text conflict in sql/sp_head.cc
Text conflict in sql/sql_show.cc
Text conflict in sql/table.cc
Text conflict in sql/table.h
Diffstat (limited to 'sql/sp_head.cc')
-rw-r--r-- | sql/sp_head.cc | 234 |
1 files changed, 113 insertions, 121 deletions
diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 2d5b648e82e..61f00fdf59a 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -125,10 +125,10 @@ sp_get_item_value(THD *thd, Item *item, String *str) case STRING_RESULT: { String *result= item->val_str(str); - + if (!result) return NULL; - + { char buf_holder[STRING_BUFFER_USUAL_SIZE]; String buf(buf_holder, sizeof(buf_holder), result->charset()); @@ -366,7 +366,7 @@ sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr) Save original values and restore them after save. */ - + thd->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL; thd->abort_on_warning= thd->variables.sql_mode & @@ -465,7 +465,7 @@ check_routine_name(LEX_STRING *ident) { if (!ident || !ident->str || !ident->str[0] || ident->str[ident->length-1] == ' ') - { + { my_error(ER_SP_WRONG_NAME, MYF(0), ident->str); return TRUE; } @@ -502,7 +502,7 @@ sp_head::operator new(size_t size) throw() DBUG_RETURN(sp); } -void +void sp_head::operator delete(void *ptr, size_t size) throw() { DBUG_ENTER("sp_head::operator delete"); @@ -718,7 +718,7 @@ create_typelib(MEM_ROOT *mem_root, Create_field *field_def, List<String> *src) String *tmp= it++; if (String::needs_conversion(tmp->length(), tmp->charset(), - cs, &dummy)) + cs, &dummy)) { uint cnv_errs; conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs); @@ -747,21 +747,12 @@ create_typelib(MEM_ROOT *mem_root, Create_field *field_def, List<String> *src) sp_head::~sp_head() { + LEX *lex; + sp_instr *i; DBUG_ENTER("sp_head::~sp_head"); - destroy(); - delete m_next_cached_sp; - if (m_thd) - restore_thd_mem_root(m_thd); - DBUG_VOID_RETURN; -} -void -sp_head::destroy() -{ - sp_instr *i; - LEX *lex; - DBUG_ENTER("sp_head::destroy"); - DBUG_PRINT("info", ("name: %s", m_name.str)); + /* sp_head::restore_thd_mem_root() must already have been called. */ + DBUG_ASSERT(m_thd == NULL); for (uint ip = 0 ; (i = get_instr(ip)) ; ip++) delete i; @@ -772,21 +763,22 @@ sp_head::destroy() /* If we have non-empty LEX stack then we just came out of parser with error. Now we should delete all auxilary LEXes and restore original - THD::lex (In this case sp_head::restore_thd_mem_root() was not called - too, so m_thd points to the current thread context). - It is safe to not update LEX::ptr because further query string parsing - and execution will be stopped anyway. + THD::lex. It is safe to not update LEX::ptr because further query + string parsing and execution will be stopped anyway. */ - DBUG_ASSERT(m_lex.is_empty() || m_thd); while ((lex= (LEX *)m_lex.pop())) { - lex_end(m_thd->lex); - delete m_thd->lex; - m_thd->lex= lex; + THD *thd= lex->thd; + lex_end(thd->lex); + delete thd->lex; + thd->lex= lex; } my_hash_free(&m_sptabs); my_hash_free(&m_sroutines); + + delete m_next_cached_sp; + DBUG_VOID_RETURN; } @@ -823,7 +815,7 @@ sp_head::create_result_field(uint field_max_length, const char *field_name, if (field) field->init(table); - + DBUG_RETURN(field); } @@ -852,7 +844,7 @@ int cmp_splocal_locations(Item_splocal * const *a, Item_splocal * const *b) Statements that have is_update_query(stmt) == FALSE (e.g. SELECTs) are not written into binary log. Instead we catch function calls the statement makes and write it into binary log separately (see #3). - + 2. PROCEDURE calls CALL statements are not written into binary log. Instead @@ -865,8 +857,8 @@ int cmp_splocal_locations(Item_splocal * const *a, Item_splocal * const *b) This substitution is done in subst_spvars(). 3. FUNCTION calls - - In sp_head::execute_function(), we check + + In sp_head::execute_function(), we check * If this function invocation is done from a statement that is written into the binary log. * If there were any attempts to write events to the binary log during @@ -874,28 +866,28 @@ int cmp_splocal_locations(Item_splocal * const *a, Item_splocal * const *b) If the answers are No and Yes, we write the function call into the binary log as "SELECT spfunc(<param1value>, <param2value>, ...)" - - + + 4. Miscellaneous issues. - - 4.1 User variables. + + 4.1 User variables. When we call mysql_bin_log.write() for an SP statement, thd->user_var_events - must hold set<{var_name, value}> pairs for all user variables used during + must hold set<{var_name, value}> pairs for all user variables used during the statement execution. This set is produced by tracking user variable reads during statement - execution. + execution. For SPs, this has the following implications: - 1) thd->user_var_events may contain events from several SP statements and - needs to be valid after exection of these statements was finished. In + 1) thd->user_var_events may contain events from several SP statements and + needs to be valid after exection of these statements was finished. In order to achieve that, we * Allocate user_var_events array elements on appropriate mem_root (grep for user_var_events_alloc). * Use is_query_in_union() to determine if user_var_event is created. - + 2) We need to empty thd->user_var_events after we have wrote a function - call. This is currently done by making + call. This is currently done by making reset_dynamic(&thd->user_var_events); calls in several different places. (TODO cosider moving this into mysql_bin_log.write() function) @@ -914,7 +906,7 @@ int cmp_splocal_locations(Item_splocal * const *a, Item_splocal * const *b) Replace thd->query{_length} with a string that one can write to the binlog. - The binlog-suitable string is produced by replacing references to SP local + The binlog-suitable string is produced by replacing references to SP local variables with NAME_CONST('sp_var_name', value) calls. @param thd Current thread. @@ -951,11 +943,11 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) } if (!sp_vars_uses.elements()) DBUG_RETURN(FALSE); - + /* Sort SP var refs by their occurences in the query */ sp_vars_uses.sort(cmp_splocal_locations); - /* + /* Construct a statement string where SP local var refs are replaced with "NAME_CONST(name, value)" */ @@ -963,7 +955,7 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) cur= query_str->str; prev_pos= res= 0; thd->query_name_consts= 0; - + for (Item_splocal **splocal= sp_vars_uses.front(); splocal < sp_vars_uses.back(); splocal++) { @@ -973,13 +965,13 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) String str_value_holder(str_buffer, sizeof(str_buffer), &my_charset_latin1); String *str_value; - + /* append the text between sp ref occurences */ res|= qbuf.append(cur + prev_pos, (*splocal)->pos_in_query - prev_pos); prev_pos= (*splocal)->pos_in_query + (*splocal)->len_in_query; - + res|= (*splocal)->fix_fields(thd, (Item **) splocal); - if (res) + if (res) break; if ((*splocal)->limit_clause_param) @@ -1006,7 +998,7 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) res|= qbuf.append(')'); if (res) break; - + thd->query_name_consts++; } res|= qbuf.append(cur + prev_pos, query_str->length - prev_pos); @@ -1032,16 +1024,14 @@ subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str) } -/* +/** Return appropriate error about recursion limit reaching - SYNOPSIS - sp_head::recursion_level_error() - thd Thread handle + @param thd Thread handle - NOTE - For functions and triggers we return error about prohibited recursion. - For stored procedures we return about reaching recursion limit. + @remark For functions and triggers we return error about + prohibited recursion. For stored procedures we + return about reaching recursion limit. */ void sp_head::recursion_level_error(THD *thd) @@ -1061,7 +1051,7 @@ void sp_head::recursion_level_error(THD *thd) Execute the routine. The main instruction jump loop is there. Assume the parameters already set. @todo - - Will write this SP statement into binlog separately + - Will write this SP statement into binlog separately (TODO: consider changing the condition to "not inside event union") @retval @@ -1225,10 +1215,10 @@ sp_head::execute(THD *thd) do { sp_instr *i; - uint hip; // Handler ip + uint hip; #if defined(ENABLED_PROFILING) - /* + /* Treat each "instr" of a routine as discrete unit that could be profiled. Profiling only records information for segments of code that set the source of the query, and almost all kinds of instructions in s-p do not. @@ -1237,7 +1227,8 @@ sp_head::execute(THD *thd) thd->profiling.start_new_query("continuing inside routine"); #endif - i = get_instr(ip); // Returns NULL when we're done. + /* get_instr returns NULL when we're done. */ + i = get_instr(ip); if (i == NULL) { #if defined(ENABLED_PROFILING) @@ -1248,10 +1239,13 @@ sp_head::execute(THD *thd) DBUG_PRINT("execute", ("Instruction %u", ip)); - /* Don't change NOW() in FUNCTION or TRIGGER */ + /* + Make current_time() et al work. But don't change NOW() in FUNCTION + or TRIGGER. + */ if (!thd->in_sub_stmt) - thd->set_time(); // Make current_time() et al work - + thd->set_time(); + /* We have to set thd->stmt_arena before executing the instruction to store in the instruction free_list all new items, created @@ -1259,10 +1253,10 @@ sp_head::execute(THD *thd) items made during other permanent subquery transformations). */ thd->stmt_arena= i; - - /* - Will write this SP statement into binlog separately - (TODO: consider changing the condition to "not inside event union") + + /* + Will write this SP statement into binlog separately. + TODO: consider changing the condition to "not inside event union". */ if (thd->locked_tables_mode <= LTM_LOCK_TABLES) thd->user_var_events_alloc= thd->mem_root; @@ -1271,8 +1265,8 @@ sp_head::execute(THD *thd) if (i->free_list) cleanup_items(i->free_list); - - /* + + /* If we've set thd->user_var_events_alloc to mem_root of this SP statement, clean all the events allocated in it. */ @@ -1284,7 +1278,7 @@ sp_head::execute(THD *thd) /* we should cleanup free_list and memroot, used by instruction */ thd->cleanup_after_query(); - free_root(&execute_mem_root, MYF(0)); + free_root(&execute_mem_root, MYF(0)); /* Check if an exception has occurred and a handler has been found @@ -1299,7 +1293,7 @@ sp_head::execute(THD *thd) switch (ctx->found_handler(& hip, & handler_index)) { case SP_HANDLER_NONE: - break; + break; case SP_HANDLER_CONTINUE: thd->restore_active_arena(&execute_arena, &backup_arena); thd->set_n_backup_active_arena(&execute_arena, &backup_arena); @@ -1308,15 +1302,15 @@ sp_head::execute(THD *thd) default: if (ctx->end_partial_result_set) thd->protocol->end_partial_result_set(thd); - ip= hip; - err_status= FALSE; - ctx->clear_handler(); - ctx->enter_handler(hip, handler_index); + ip= hip; + err_status= FALSE; + ctx->clear_handler(); + ctx->enter_handler(hip, handler_index); thd->clear_error(); thd->is_fatal_error= 0; - thd->killed= THD::NOT_KILLED; + thd->killed= THD::NOT_KILLED; thd->mysys_var->abort= 0; - continue; + continue; } ctx->end_partial_result_set= FALSE; @@ -1359,7 +1353,7 @@ sp_head::execute(THD *thd) done: DBUG_PRINT("info", ("err_status: %d killed: %d is_slave_error: %d report_error: %d", - err_status, thd->killed, thd->is_slave_error, + err_status, thd->killed, thd->is_slave_error, thd->is_error())); if (thd->killed) @@ -1847,10 +1841,10 @@ err_with_cleanup: /** - Execute a procedure. + Execute a procedure. The function does the following steps: - - Set all parameters + - Set all parameters - changes security context for SUID routines - call sp_head::execute - copy back values of INOUT and OUT parameters @@ -1888,14 +1882,14 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) save_spcont= octx= thd->spcont; if (! octx) - { // Create a temporary old context - if (!(octx= new sp_rcontext(m_pcont, NULL, octx)) || - octx->init(thd)) + { + /* 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); } - + #ifndef DBUG_OFF octx->sp= 0; #endif @@ -2155,7 +2149,7 @@ sp_head::restore_lex(THD *thd) oldlex= (LEX *)m_lex.pop(); if (! oldlex) - DBUG_RETURN(FALSE); // Nothing to restore + DBUG_RETURN(FALSE); // Nothing to restore oldlex->trg_table_fields.push_back(&sublex->trg_table_fields); @@ -2308,7 +2302,7 @@ sp_head::do_cont_backpatch() void sp_head::set_info(longlong created, longlong modified, - st_sp_chistics *chistics, ulong sql_mode) + st_sp_chistics *chistics, ulong sql_mode) { m_created= created; m_modified= modified; @@ -2318,8 +2312,8 @@ sp_head::set_info(longlong created, longlong modified, m_chistics->comment.str= 0; else m_chistics->comment.str= strmake_root(mem_root, - m_chistics->comment.str, - m_chistics->comment.length); + m_chistics->comment.str, + m_chistics->comment.length); m_sql_mode= sql_mode; } @@ -2360,7 +2354,7 @@ sp_head::reset_thd_mem_root(THD *thd) DBUG_PRINT("info", ("mem_root 0x%lx moved to thd mem root 0x%lx", (ulong) &mem_root, (ulong) &thd->mem_root)); free_list= thd->free_list; // Keep the old list - thd->free_list= NULL; // Start a new one + thd->free_list= NULL; // Start a new one m_thd= thd; DBUG_VOID_RETURN; } @@ -2369,13 +2363,13 @@ void sp_head::restore_thd_mem_root(THD *thd) { DBUG_ENTER("sp_head::restore_thd_mem_root"); - Item *flist= free_list; // The old list + Item *flist= free_list; // The old list set_query_arena(thd); // Get new free_list and mem_root state= INITIALIZED_FOR_SP; DBUG_PRINT("info", ("mem_root 0x%lx returned from thd mem root 0x%lx", (ulong) &mem_root, (ulong) &thd->mem_root)); - thd->free_list= flist; // Restore the old one + thd->free_list= flist; // Restore the old one thd->mem_root= m_thd_root; m_thd= NULL; DBUG_VOID_RETURN; @@ -2385,10 +2379,10 @@ sp_head::restore_thd_mem_root(THD *thd) /** Check if a user has access right to a routine. - @param thd Thread handler - @param sp SP - @param full_access Set to 1 if the user has SELECT right to the - 'mysql.proc' able or is the owner of the routine + @param thd Thread handler + @param sp SP + @param full_access Set to 1 if the user has SELECT right to the + 'mysql.proc' able or is the owner of the routine @retval false ok @retval @@ -2517,8 +2511,6 @@ sp_head::show_create_routine(THD *thd, int type) } - - /** Add instruction to SP. @@ -2578,11 +2570,11 @@ void sp_head::optimize() if (src != dst) { /* Move the instruction and update prev. jumps */ - sp_instr *ibp; - List_iterator_fast<sp_instr> li(bp); + sp_instr *ibp; + List_iterator_fast<sp_instr> li(bp); - set_dynamic(&m_instr, (uchar*)&i, dst); - while ((ibp= li++)) + set_dynamic(&m_instr, (uchar*)&i, dst); + while ((ibp= li++)) { sp_instr_opt_meta *im= static_cast<sp_instr_opt_meta *>(ibp); im->set_destination(src, dst); @@ -2677,7 +2669,7 @@ sp_head::show_routine_code(THD *thd) for (ip= 0; (i = get_instr(ip)) ; ip++) { - /* + /* Consistency check. If these are different something went wrong during optimization. */ @@ -2740,7 +2732,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, int res= 0; DBUG_ENTER("reset_lex_and_exec_core"); - /* + /* The flag is saved at the entry to the following substatement. It's reset further in the common code part. It's merged with the saved parent's value at the exit of this func. @@ -2902,9 +2894,8 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) if (unlikely((thd->variables.option_bits & OPTION_LOG_OFF)==0)) general_log_write(thd, COM_QUERY, thd->query(), thd->query_length()); - if (query_cache_send_result_to_client(thd, - thd->query(), - thd->query_length()) <= 0) + if (query_cache_send_result_to_client(thd, thd->query(), + thd->query_length()) <= 0) { res= m_lex_keeper.reset_lex_and_exec_core(thd, nextp, FALSE, this); @@ -3007,7 +2998,7 @@ sp_instr_set::exec_core(THD *thd, uint *nextp) /* If this also failed, let's abort. */ sp_rcontext *spcont= thd->spcont; - + thd->spcont= NULL; /* Avoid handlers */ my_error(ER_OUT_OF_RESOURCES, MYF(0)); spcont->clear_handler(); @@ -3051,6 +3042,7 @@ int sp_instr_set_trigger_field::execute(THD *thd, uint *nextp) { DBUG_ENTER("sp_instr_set_trigger_field::execute"); + thd->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL; DBUG_RETURN(m_lex_keeper.reset_lex_and_exec_core(thd, nextp, TRUE, this)); } @@ -3110,7 +3102,7 @@ uint sp_instr_jump::opt_mark(sp_head *sp, List<sp_instr> *leads) { m_dest= opt_shortcut_jump(sp, this); - if (m_dest != m_ip+1) /* Jumping to following instruction? */ + if (m_dest != m_ip+1) /* Jumping to following instruction? */ marked= 1; m_optdest= sp->get_instr(m_dest); return m_dest; @@ -3140,9 +3132,9 @@ void sp_instr_jump::opt_move(uint dst, List<sp_instr> *bp) { if (m_dest > m_ip) - bp->push_back(this); // Forward + bp->push_back(this); // Forward else if (m_optdest) - m_dest= m_optdest->m_ip; // Backward + m_dest= m_optdest->m_ip; // Backward m_ip= dst; } @@ -3415,7 +3407,7 @@ uint sp_instr_hreturn::opt_mark(sp_head *sp, List<sp_instr> *leads) { marked= 1; - + if (m_dest) { /* @@ -3423,7 +3415,7 @@ sp_instr_hreturn::opt_mark(sp_head *sp, List<sp_instr> *leads) */ return m_dest; } - + /* This is a CONTINUE handler; next instruction step will come from the handler stack and not from opt_mark. @@ -3740,14 +3732,14 @@ sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp) */ Item *null_item= new Item_null(); - + if (!null_item || thd->spcont->set_case_expr(thd, m_case_expr_id, &null_item)) { /* If this also failed, we have to abort. */ sp_rcontext *spcont= thd->spcont; - + thd->spcont= NULL; /* Avoid handlers */ my_error(ER_OUT_OF_RESOURCES, MYF(0)); spcont->clear_handler(); @@ -3913,13 +3905,13 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) } else { - if (!(tab= (SP_TABLE *)thd->calloc(sizeof(SP_TABLE)))) - return FALSE; - if (lex_for_tmp_check->sql_command == SQLCOM_CREATE_TABLE && - lex_for_tmp_check->query_tables == table && - lex_for_tmp_check->create_info.options & HA_LEX_CREATE_TMP_TABLE) + if (!(tab= (SP_TABLE *)thd->calloc(sizeof(SP_TABLE)))) + return FALSE; + if (lex_for_tmp_check->sql_command == SQLCOM_CREATE_TABLE && + lex_for_tmp_check->query_tables == table && + lex_for_tmp_check->create_info.options & HA_LEX_CREATE_TMP_TABLE) { - tab->temp= TRUE; + tab->temp= TRUE; tab->qname.length= tlen - alen - 1; } else @@ -3932,7 +3924,7 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) tab->lock_type= table->lock_type; tab->lock_count= tab->query_lock_count= 1; tab->trg_event_map= table->trg_event_map; - if (my_hash_insert(&m_sptabs, (uchar *)tab)) + if (my_hash_insert(&m_sptabs, (uchar *)tab)) return FALSE; } } |