The world's most popular open source database
#include <sp_head.h>
Collaboration diagram for sp_head:

Definition at line 101 of file sp_head.h.
| anonymous enum |
| HAS_RETURN | |
| IN_SIMPLE_CASE | |
| IN_HANDLER | |
| MULTI_RESULTS | |
| CONTAINS_DYNAMIC_SQL | |
| IS_INVOKED | |
| HAS_SET_AUTOCOMMIT_STMT | |
| HAS_COMMIT_OR_ROLLBACK | |
| LOG_SLOW_STATEMENTS | |
| LOG_GENERAL_LOG | |
| BINLOG_ROW_BASED_IF_MIXED |
Definition at line 109 of file sp_head.h.
00109 { 00110 HAS_RETURN= 1, // For FUNCTIONs only: is set if has RETURN 00111 IN_SIMPLE_CASE= 2, // Is set if parsing a simple CASE 00112 IN_HANDLER= 4, // Is set if the parser is in a handler body 00113 MULTI_RESULTS= 8, // Is set if a procedure with SELECT(s) 00114 CONTAINS_DYNAMIC_SQL= 16, // Is set if a procedure with PREPARE/EXECUTE 00115 IS_INVOKED= 32, // Is set if this sp_head is being used 00116 HAS_SET_AUTOCOMMIT_STMT= 64,// Is set if a procedure with 'set autocommit' 00117 /* Is set if a procedure with COMMIT (implicit or explicit) | ROLLBACK */ 00118 HAS_COMMIT_OR_ROLLBACK= 128, 00119 LOG_SLOW_STATEMENTS= 256, // Used by events 00120 LOG_GENERAL_LOG= 512, // Used by events 00121 BINLOG_ROW_BASED_IF_MIXED= 1024 00122 };
| sp_head::sp_head | ( | const sp_head & | ) | [private] |
| sp_head::sp_head | ( | ) |
Definition at line 452 of file sp_head.cc.
References create_field::charset, DBUG_ENTER, DBUG_VOID_RETURN, base_list::empty(), hash_init, m_backpatch, m_cont_backpatch, m_db, m_lex, m_name, m_qname, m_return_field_def, m_sptabs, m_sroutines, NULL, sp_sroutine_key(), sp_table_key(), and system_charset_info.
00453 :Query_arena(&main_mem_root, INITIALIZED_FOR_SP), 00454 m_flags(0), m_recursion_level(0), m_next_cached_sp(0), 00455 m_first_instance(this), m_first_free_instance(this), m_last_cached_sp(this), 00456 m_cont_level(0) 00457 { 00458 const LEX_STRING str_reset= { NULL, 0 }; 00459 m_return_field_def.charset = NULL; 00460 /* 00461 FIXME: the only use case when name is NULL is events, and it should 00462 be rewritten soon. Remove the else part and replace 'if' with 00463 an assert when this is done. 00464 */ 00465 m_db= m_name= m_qname= str_reset; 00466 00467 extern byte * 00468 sp_table_key(const byte *ptr, uint *plen, my_bool first); 00469 DBUG_ENTER("sp_head::sp_head"); 00470 00471 m_backpatch.empty(); 00472 m_cont_backpatch.empty(); 00473 m_lex.empty(); 00474 hash_init(&m_sptabs, system_charset_info, 0, 0, 0, sp_table_key, 0, 0); 00475 hash_init(&m_sroutines, system_charset_info, 0, 0, 0, sp_sroutine_key, 0, 0); 00476 DBUG_VOID_RETURN; 00477 }
Here is the call graph for this function:

| sp_head::~sp_head | ( | ) | [virtual] |
Definition at line 653 of file sp_head.cc.
References destroy(), m_next_cached_sp, m_thd, and restore_thd_mem_root().
00654 { 00655 destroy(); 00656 delete m_next_cached_sp; 00657 if (m_thd) 00658 restore_thd_mem_root(m_thd); 00659 }
Here is the call graph for this function:

| void sp_head::add_cont_backpatch | ( | sp_instr_opt_meta * | i | ) |
Definition at line 1955 of file sp_head.cc.
References m_cont_backpatch, sp_instr_opt_meta::m_cont_dest, m_cont_level, and List< T >::push_front().
01956 { 01957 i->m_cont_dest= m_cont_level; 01958 (void)m_cont_backpatch.push_front(i); 01959 }
Here is the call graph for this function:

| void sp_head::add_instr | ( | sp_instr * | instr | ) |
Definition at line 2140 of file sp_head.cc.
References insert_dynamic(), m_instr, m_thd, and main_mem_root.
02141 { 02142 instr->free_list= m_thd->free_list; 02143 m_thd->free_list= 0; 02144 /* 02145 Memory root of every instruction is designated for permanent 02146 transformations (optimizations) made on the parsed tree during 02147 the first execution. It points to the memory root of the 02148 entire stored procedure, as their life span is equal. 02149 */ 02150 instr->mem_root= &main_mem_root; 02151 insert_dynamic(&m_instr, (gptr)&instr); 02152 }
Here is the call graph for this function:

| bool sp_head::add_used_tables_to_table_list | ( | THD * | thd, | |
| TABLE_LIST *** | query_tables_last_ptr, | |||
| TABLE_LIST * | belong_to_view | |||
| ) |
Definition at line 3535 of file sp_head.cc.
References st_table_list::alias, ALIGN_SIZE, backup, st_table_list::belong_to_view, st_table_list::cacheable_table, st_table_list::db, st_sp_table::db_length, st_table_list::db_length, DBUG_ENTER, DBUG_RETURN, FALSE, hash_element(), LEX_STRING::length, st_sp_table::lock_count, st_sp_table::lock_type, st_table_list::lock_type, m_sptabs, st_table_list::next_global, st_table_list::prelocking_placeholder, st_table_list::prev_global, st_sp_table::qname, st_hash::records, LEX_STRING::str, st_table_list::table_name, st_sp_table::table_name_length, st_table_list::table_name_length, st_sp_table::temp, and TRUE.
03538 { 03539 uint i; 03540 Query_arena *arena, backup; 03541 bool result= FALSE; 03542 DBUG_ENTER("sp_head::add_used_tables_to_table_list"); 03543 03544 /* 03545 Use persistent arena for table list allocation to be PS/SP friendly. 03546 Note that we also have to copy database/table names and alias to PS/SP 03547 memory since current instance of sp_head object can pass away before 03548 next execution of PS/SP for which tables are added to prelocking list. 03549 This will be fixed by introducing of proper invalidation mechanism 03550 once new TDC is ready. 03551 */ 03552 arena= thd->activate_stmt_arena_if_needed(&backup); 03553 03554 for (i=0 ; i < m_sptabs.records ; i++) 03555 { 03556 char *tab_buff, *key_buff; 03557 TABLE_LIST *table; 03558 SP_TABLE *stab= (SP_TABLE *)hash_element(&m_sptabs, i); 03559 if (stab->temp) 03560 continue; 03561 03562 if (!(tab_buff= (char *)thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST)) * 03563 stab->lock_count)) || 03564 !(key_buff= (char*)thd->memdup(stab->qname.str, 03565 stab->qname.length + 1))) 03566 DBUG_RETURN(FALSE); 03567 03568 for (uint j= 0; j < stab->lock_count; j++) 03569 { 03570 table= (TABLE_LIST *)tab_buff; 03571 03572 table->db= key_buff; 03573 table->db_length= stab->db_length; 03574 table->table_name= table->db + table->db_length + 1; 03575 table->table_name_length= stab->table_name_length; 03576 table->alias= table->table_name + table->table_name_length + 1; 03577 table->lock_type= stab->lock_type; 03578 table->cacheable_table= 1; 03579 table->prelocking_placeholder= 1; 03580 table->belong_to_view= belong_to_view; 03581 03582 /* Everyting else should be zeroed */ 03583 03584 **query_tables_last_ptr= table; 03585 table->prev_global= *query_tables_last_ptr; 03586 *query_tables_last_ptr= &table->next_global; 03587 03588 tab_buff+= ALIGN_SIZE(sizeof(TABLE_LIST)); 03589 result= TRUE; 03590 } 03591 } 03592 03593 if (arena) 03594 thd->restore_active_arena(arena, &backup); 03595 03596 DBUG_RETURN(result); 03597 }
Here is the call graph for this function:

| void sp_head::backpatch | ( | struct sp_label * | ) |
Definition at line 1877 of file sp_head.cc.
References sp_instr::backpatch(), sp_label::ctx, sp_head::bp_t::instr, instructions(), sp_head::bp_t::lab, and m_backpatch.
01878 { 01879 bp_t *bp; 01880 uint dest= instructions(); 01881 List_iterator_fast<bp_t> li(m_backpatch); 01882 01883 while ((bp= li++)) 01884 { 01885 if (bp->lab == lab) 01886 bp->instr->backpatch(dest, lab->ctx); 01887 } 01888 }
Here is the call graph for this function:

| int sp_head::create | ( | THD * | thd | ) |
Definition at line 616 of file sp_head.cc.
References String::append(), buf, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, get_instr(), m_body, m_name, m_params, m_qname, m_type, optimize(), sp_instr::print(), String::ptr(), sp_create_function(), sp_create_procedure(), LEX_STRING::str, and TYPE_ENUM_FUNCTION.
00617 { 00618 DBUG_ENTER("sp_head::create"); 00619 int ret; 00620 00621 DBUG_PRINT("info", ("type: %d name: %s params: %s body: %s", 00622 m_type, m_name.str, m_params.str, m_body.str)); 00623 00624 #ifndef DBUG_OFF 00625 optimize(); 00626 { 00627 String s; 00628 sp_instr *i; 00629 uint ip= 0; 00630 while ((i = get_instr(ip))) 00631 { 00632 char buf[8]; 00633 00634 sprintf(buf, "%4u: ", ip); 00635 s.append(buf); 00636 i->print(&s); 00637 s.append('\n'); 00638 ip+= 1; 00639 } 00640 s.append('\0'); 00641 DBUG_PRINT("info", ("Code %s\n%s", m_qname.str, s.ptr())); 00642 } 00643 #endif 00644 00645 if (m_type == TYPE_ENUM_FUNCTION) 00646 ret= sp_create_function(thd, this); 00647 else 00648 ret= sp_create_procedure(thd, this); 00649 00650 DBUG_RETURN(ret); 00651 }
Here is the call graph for this function:

| Field * sp_head::create_result_field | ( | uint | field_max_length, | |
| const char * | field_name, | |||
| TABLE * | table | |||
| ) |
Definition at line 703 of file sp_head.cc.
References create_field::charset, DBUG_ENTER, DBUG_RETURN, create_field::geom_type, Field::init(), create_field::interval, create_field::length, m_name, m_return_field_def, make_field(), Field::NONE, create_field::pack_flag, st_table::s, create_field::sql_type, and LEX_STRING::str.
Referenced by Item_func_sp::sp_result_field(), sp_returns_type(), and Item_func_sp::tmp_table_field().
00705 { 00706 uint field_length; 00707 Field *field; 00708 00709 DBUG_ENTER("sp_head::create_result_field"); 00710 00711 field_length= !m_return_field_def.length ? 00712 field_max_length : m_return_field_def.length; 00713 00714 field= ::make_field(table->s, /* TABLE_SHARE ptr */ 00715 (char*) 0, /* field ptr */ 00716 field_length, /* field [max] length */ 00717 (uchar*) "", /* null ptr */ 00718 0, /* null bit */ 00719 m_return_field_def.pack_flag, 00720 m_return_field_def.sql_type, 00721 m_return_field_def.charset, 00722 m_return_field_def.geom_type, 00723 Field::NONE, /* unreg check */ 00724 m_return_field_def.interval, 00725 field_name ? field_name : (const char *) m_name.str); 00726 00727 if (field) 00728 field->init(table); 00729 00730 DBUG_RETURN(field); 00731 }
Here is the call graph for this function:

Here is the caller graph for this function:

| char* sp_head::create_string | ( | THD * | thd, | |
| ulong * | lenp | |||
| ) |
| void sp_head::destroy | ( | ) |
Definition at line 662 of file sp_head.cc.
References DBUG_ASSERT, DBUG_ENTER, DBUG_PRINT, DBUG_VOID_RETURN, delete_dynamic(), sp_pcontext::destroy(), free_items(), get_instr(), hash_free(), base_list::is_empty(), lex_end(), m_instr, m_lex, m_name, m_pcont, m_sptabs, m_sroutines, m_thd, List< T >::pop(), and LEX_STRING::str.
Referenced by ~sp_head().
00663 { 00664 sp_instr *i; 00665 LEX *lex; 00666 DBUG_ENTER("sp_head::destroy"); 00667 DBUG_PRINT("info", ("name: %s", m_name.str)); 00668 00669 for (uint ip = 0 ; (i = get_instr(ip)) ; ip++) 00670 delete i; 00671 delete_dynamic(&m_instr); 00672 m_pcont->destroy(); 00673 free_items(); 00674 00675 /* 00676 If we have non-empty LEX stack then we just came out of parser with 00677 error. Now we should delete all auxilary LEXes and restore original 00678 THD::lex (In this case sp_head::restore_thd_mem_root() was not called 00679 too, so m_thd points to the current thread context). 00680 It is safe to not update LEX::ptr because further query string parsing 00681 and execution will be stopped anyway. 00682 */ 00683 DBUG_ASSERT(m_lex.is_empty() || m_thd); 00684 while ((lex= (LEX *)m_lex.pop())) 00685 { 00686 lex_end(m_thd->lex); 00687 delete m_thd->lex; 00688 m_thd->lex= lex; 00689 } 00690 00691 hash_free(&m_sptabs); 00692 hash_free(&m_sroutines); 00693 DBUG_VOID_RETURN; 00694 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void sp_head::do_cont_backpatch | ( | ) |
Definition at line 1962 of file sp_head.cc.
References List< T >::head(), instructions(), m_cont_backpatch, sp_instr_opt_meta::m_cont_dest, m_cont_level, and List< T >::pop().
01963 { 01964 uint dest= instructions(); 01965 uint lev= m_cont_level--; 01966 sp_instr_opt_meta *i; 01967 01968 while ((i= m_cont_backpatch.head()) && i->m_cont_dest == lev) 01969 { 01970 i->m_cont_dest= dest; 01971 (void)m_cont_backpatch.pop(); 01972 } 01973 }
Here is the call graph for this function:

| bool sp_head::execute | ( | THD * | thd | ) | [private] |
Definition at line 948 of file sp_head.cc.
References check_stack_overrun(), cleanup_items(), ctx, DBUG_ASSERT, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, sp_instr::execute(), FALSE, free_root(), get_instr(), init_alloc_root(), IS_INVOKED, LEX_STRING::length, m_db, m_first_free_instance, m_first_instance, m_flags, m_last_cached_sp, m_next_cached_sp, m_recursion_level, m_sql_mode, MEM_ROOT_BLOCK_SIZE, MODE_STRICT_ALL_TABLES, MODE_STRICT_TRANS_TABLES, MYF, mysql_change_db(), NAME_LEN, NULL, reset_dynamic, SP_HANDLER_CONTINUE, SP_HANDLER_NONE, sp_use_new_db(), STACK_MIN_SIZE, LEX_STRING::str, and TRUE.
Referenced by execute_function(), execute_procedure(), and execute_trigger().
00949 { 00950 DBUG_ENTER("sp_head::execute"); 00951 char old_db_buf[NAME_LEN+1]; 00952 LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) }; 00953 bool dbchanged; 00954 sp_rcontext *ctx; 00955 bool err_status= FALSE; 00956 uint ip= 0; 00957 ulong save_sql_mode; 00958 bool save_abort_on_warning; 00959 Query_arena *old_arena; 00960 /* per-instruction arena */ 00961 MEM_ROOT execute_mem_root; 00962 Query_arena execute_arena(&execute_mem_root, INITIALIZED_FOR_SP), 00963 backup_arena; 00964 query_id_t old_query_id; 00965 TABLE *old_derived_tables; 00966 LEX *old_lex; 00967 Item_change_list old_change_list; 00968 String old_packet; 00969 00970 /* Use some extra margin for possible SP recursion and functions */ 00971 if (check_stack_overrun(thd, 8 * STACK_MIN_SIZE, (char*)&old_packet)) 00972 DBUG_RETURN(TRUE); 00973 00974 /* init per-instruction memroot */ 00975 init_alloc_root(&execute_mem_root, MEM_ROOT_BLOCK_SIZE, 0); 00976 00977 DBUG_ASSERT(!(m_flags & IS_INVOKED)); 00978 m_flags|= IS_INVOKED; 00979 m_first_instance->m_first_free_instance= m_next_cached_sp; 00980 if (m_next_cached_sp) 00981 { 00982 DBUG_PRINT("info", 00983 ("first free for 0x%lx ++: 0x%lx->0x%lx level: %lu flags %x", 00984 (ulong)m_first_instance, (ulong) this, 00985 (ulong) m_next_cached_sp, 00986 m_next_cached_sp->m_recursion_level, 00987 m_next_cached_sp->m_flags)); 00988 } 00989 /* 00990 Check that if there are not any instances after this one then 00991 pointer to the last instance points on this instance or if there are 00992 some instances after this one then recursion level of next instance 00993 greater then recursion level of current instance on 1 00994 */ 00995 DBUG_ASSERT((m_next_cached_sp == 0 && 00996 m_first_instance->m_last_cached_sp == this) || 00997 (m_recursion_level + 1 == m_next_cached_sp->m_recursion_level)); 00998 00999 if (m_db.length && 01000 (err_status= sp_use_new_db(thd, m_db, &old_db, 0, &dbchanged))) 01001 goto done; 01002 01003 if ((ctx= thd->spcont)) 01004 ctx->clear_handler(); 01005 thd->query_error= 0; 01006 old_arena= thd->stmt_arena; 01007 01008 /* 01009 We have to save/restore this info when we are changing call level to 01010 be able properly do close_thread_tables() in instructions. 01011 */ 01012 old_query_id= thd->query_id; 01013 old_derived_tables= thd->derived_tables; 01014 thd->derived_tables= 0; 01015 save_sql_mode= thd->variables.sql_mode; 01016 thd->variables.sql_mode= m_sql_mode; 01017 save_abort_on_warning= thd->abort_on_warning; 01018 thd->abort_on_warning= 01019 (m_sql_mode & (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)); 01020 01021 /* 01022 It is also more efficient to save/restore current thd->lex once when 01023 do it in each instruction 01024 */ 01025 old_lex= thd->lex; 01026 /* 01027 We should also save Item tree change list to avoid rollback something 01028 too early in the calling query. 01029 */ 01030 old_change_list= thd->change_list; 01031 thd->change_list.empty(); 01032 /* 01033 Cursors will use thd->packet, so they may corrupt data which was prepared 01034 for sending by upper level. OTOH cursors in the same routine can share this 01035 buffer safely so let use use routine-local packet instead of having own 01036 packet buffer for each cursor. 01037 01038 It is probably safe to use same thd->convert_buff everywhere. 01039 */ 01040 old_packet.swap(thd->packet); 01041 01042 /* 01043 Switch to per-instruction arena here. We can do it since we cleanup 01044 arena after every instruction. 01045 */ 01046 thd->set_n_backup_active_arena(&execute_arena, &backup_arena); 01047 01048 /* 01049 Save callers arena in order to store instruction results and out 01050 parameters in it later during sp_eval_func_item() 01051 */ 01052 thd->spcont->callers_arena= &backup_arena; 01053 01054 do 01055 { 01056 sp_instr *i; 01057 uint hip; // Handler ip 01058 01059 i = get_instr(ip); // Returns NULL when we're done. 01060 if (i == NULL) 01061 break; 01062 DBUG_PRINT("execute", ("Instruction %u", ip)); 01063 /* Don't change NOW() in FUNCTION or TRIGGER */ 01064 if (!thd->in_sub_stmt) 01065 thd->set_time(); // Make current_time() et al work 01066 01067 /* 01068 We have to set thd->stmt_arena before executing the instruction 01069 to store in the instruction free_list all new items, created 01070 during the first execution (for example expanding of '*' or the 01071 items made during other permanent subquery transformations). 01072 */ 01073 thd->stmt_arena= i; 01074 01075 /* 01076 Will write this SP statement into binlog separately 01077 (TODO: consider changing the condition to "not inside event union") 01078 */ 01079 if (thd->prelocked_mode == NON_PRELOCKED) 01080 thd->user_var_events_alloc= thd->mem_root; 01081 01082 err_status= i->execute(thd, &ip); 01083 01084 /* 01085 If this SP instruction have sent eof, it has caused no_send_error to be 01086 set. Clear it back to allow the next instruction to send error. (multi- 01087 statement execution code clears no_send_error between statements too) 01088 */ 01089 thd->net.no_send_error= 0; 01090 if (i->free_list) 01091 cleanup_items(i->free_list); 01092 01093 /* 01094 If we've set thd->user_var_events_alloc to mem_root of this SP 01095 statement, clean all the events allocated in it. 01096 */ 01097 if (thd->prelocked_mode == NON_PRELOCKED) 01098 { 01099 reset_dynamic(&thd->user_var_events); 01100 thd->user_var_events_alloc= NULL;//DEBUG 01101 } 01102 01103 /* we should cleanup free_list and memroot, used by instruction */ 01104 thd->cleanup_after_query(); 01105 free_root(&execute_mem_root, MYF(0)); 01106 01107 /* 01108 Check if an exception has occurred and a handler has been found 01109 Note: We have to check even if err_status == FALSE, since warnings (and 01110 some errors) don't return a non-zero value. We also have to check even 01111 if thd->killed != 0, since some errors return with this even when a 01112 handler has been found (e.g. "bad data"). 01113 */ 01114 if (ctx) 01115 { 01116 uint hf; 01117 01118 switch (ctx->found_handler(&hip, &hf)) { 01119 case SP_HANDLER_NONE: 01120 break; 01121 case SP_HANDLER_CONTINUE: 01122 thd->restore_active_arena(&execute_arena, &backup_arena); 01123 thd->set_n_backup_active_arena(&execute_arena, &backup_arena); 01124 ctx->push_hstack(ip); 01125 // Fall through 01126 default: 01127 ip= hip; 01128 err_status= FALSE; 01129 ctx->clear_handler(); 01130 ctx->enter_handler(hip); 01131 thd->clear_error(); 01132 thd->killed= THD::NOT_KILLED; 01133 continue; 01134 } 01135 }

