00001 /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 00018 /***************************************************************************** 00019 ** 00020 ** This file implements classes defined in sql_class.h 00021 ** Especially the classes to handle a result from a select 00022 ** 00023 *****************************************************************************/ 00024 00025 #ifdef USE_PRAGMA_IMPLEMENTATION 00026 #pragma implementation // gcc: Class implementation 00027 #endif 00028 00029 #include "mysql_priv.h" 00030 #include <my_bitmap.h> 00031 #include "log_event.h" 00032 #include <m_ctype.h> 00033 #include <sys/stat.h> 00034 #include <thr_alarm.h> 00035 #ifdef __WIN__ 00036 #include <io.h> 00037 #endif 00038 #include <mysys_err.h> 00039 00040 #include "sp_rcontext.h" 00041 #include "sp_cache.h" 00042 00043 /* 00044 The following is used to initialise Table_ident with a internal 00045 table name 00046 */ 00047 char internal_table_name[2]= "*"; 00048 char empty_c_string[1]= {0}; /* used for not defined db */ 00049 00050 const char * const THD::DEFAULT_WHERE= "field list"; 00051 00052 00053 /***************************************************************************** 00054 ** Instansiate templates 00055 *****************************************************************************/ 00056 00057 #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION 00058 /* Used templates */ 00059 template class List<Key>; 00060 template class List_iterator<Key>; 00061 template class List<key_part_spec>; 00062 template class List_iterator<key_part_spec>; 00063 template class List<Alter_drop>; 00064 template class List_iterator<Alter_drop>; 00065 template class List<Alter_column>; 00066 template class List_iterator<Alter_column>; 00067 #endif 00068 00069 /**************************************************************************** 00070 ** User variables 00071 ****************************************************************************/ 00072 00073 extern "C" byte *get_var_key(user_var_entry *entry, uint *length, 00074 my_bool not_used __attribute__((unused))) 00075 { 00076 *length=(uint) entry->name.length; 00077 return (byte*) entry->name.str; 00078 } 00079 00080 extern "C" void free_user_var(user_var_entry *entry) 00081 { 00082 char *pos= (char*) entry+ALIGN_SIZE(sizeof(*entry)); 00083 if (entry->value && entry->value != pos) 00084 my_free(entry->value, MYF(0)); 00085 my_free((char*) entry,MYF(0)); 00086 } 00087 00088 bool key_part_spec::operator==(const key_part_spec& other) const 00089 { 00090 return length == other.length && !strcmp(field_name, other.field_name); 00091 } 00092 00093 00094 /* 00095 Test if a foreign key (= generated key) is a prefix of the given key 00096 (ignoring key name, key type and order of columns) 00097 00098 NOTES: 00099 This is only used to test if an index for a FOREIGN KEY exists 00100 00101 IMPLEMENTATION 00102 We only compare field names 00103 00104 RETURN 00105 0 Generated key is a prefix of other key 00106 1 Not equal 00107 */ 00108 00109 bool foreign_key_prefix(Key *a, Key *b) 00110 { 00111 /* Ensure that 'a' is the generated key */ 00112 if (a->generated) 00113 { 00114 if (b->generated && a->columns.elements > b->columns.elements) 00115 swap_variables(Key*, a, b); // Put shorter key in 'a' 00116 } 00117 else 00118 { 00119 if (!b->generated) 00120 return TRUE; // No foreign key 00121 swap_variables(Key*, a, b); // Put generated key in 'a' 00122 } 00123 00124 /* Test if 'a' is a prefix of 'b' */ 00125 if (a->columns.elements > b->columns.elements) 00126 return TRUE; // Can't be prefix 00127 00128 List_iterator<key_part_spec> col_it1(a->columns); 00129 List_iterator<key_part_spec> col_it2(b->columns); 00130 const key_part_spec *col1, *col2; 00131 00132 #ifdef ENABLE_WHEN_INNODB_CAN_HANDLE_SWAPED_FOREIGN_KEY_COLUMNS 00133 while ((col1= col_it1++)) 00134 { 00135 bool found= 0; 00136 col_it2.rewind(); 00137 while ((col2= col_it2++)) 00138 { 00139 if (*col1 == *col2) 00140 { 00141 found= TRUE; 00142 break; 00143 } 00144 } 00145 if (!found) 00146 return TRUE; // Error 00147 } 00148 return FALSE; // Is prefix 00149 #else 00150 while ((col1= col_it1++)) 00151 { 00152 col2= col_it2++; 00153 if (!(*col1 == *col2)) 00154 return TRUE; 00155 } 00156 return FALSE; // Is prefix 00157 #endif 00158 } 00159 00160 00161 /**************************************************************************** 00162 ** Thread specific functions 00163 ****************************************************************************/ 00164 00165 Open_tables_state::Open_tables_state(ulong version_arg) 00166 :version(version_arg), state_flags(0U) 00167 { 00168 reset_open_tables_state(); 00169 } 00170 00171 my_bool thd_in_lock_tables(const THD *thd) 00172 { 00173 return thd->in_lock_tables; 00174 } 00175 00176 00177 my_bool thd_tablespace_op(const THD *thd) 00178 { 00179 return thd->tablespace_op; 00180 } 00181 00182 00183 const char *thd_proc_info(THD *thd, const char *info) 00184 { 00185 const char *old_info= thd->proc_info; 00186 thd->proc_info= info; 00187 return old_info; 00188 } 00189 00190 void **thd_ha_data(const THD *thd, const struct handlerton *hton) 00191 { 00192 return (void **) thd->ha_data + hton->slot; 00193 } 00194 00195 00196 /* 00197 Pass nominal parameters to Statement constructor only to ensure that 00198 the destructor works OK in case of error. The main_mem_root will be 00199 re-initialized in init(). 00200 */ 00201 00202 THD::THD() 00203 :Statement(CONVENTIONAL_EXECUTION, 0, ALLOC_ROOT_MIN_BLOCK_SIZE, 0), 00204 Open_tables_state(refresh_version), rli_fake(0), 00205 lock_id(&main_lock_id), 00206 user_time(0), in_sub_stmt(0), 00207 #ifdef HAVE_ROW_BASED_REPLICATION 00208 binlog_table_maps(0), 00209 #endif /*HAVE_ROW_BASED_REPLICATION*/ 00210 global_read_lock(0), is_fatal_error(0), 00211 rand_used(0), time_zone_used(0), 00212 arg_of_last_insert_id_function(FALSE), 00213 first_successful_insert_id_in_prev_stmt(0), 00214 first_successful_insert_id_in_prev_stmt_for_binlog(0), 00215 first_successful_insert_id_in_cur_stmt(0), 00216 in_lock_tables(0), bootstrap(0), derived_tables_processing(FALSE), 00217 stmt_depends_on_first_successful_insert_id_in_prev_stmt(FALSE), 00218 spcont(NULL) 00219 { 00220 stmt_arena= this; 00221 thread_stack= 0; 00222 db= 0; 00223 catalog= (char*)"std"; // the only catalog we have for now 00224 main_security_ctx.init(); 00225 security_ctx= &main_security_ctx; 00226 locked=some_tables_deleted=no_errors=password= 0; 00227 query_start_used= 0; 00228 count_cuted_fields= CHECK_FIELD_IGNORE; 00229 killed= NOT_KILLED; 00230 db_length= col_access=0; 00231 query_error= tmp_table_used= 0; 00232 hash_clear(&handler_tables_hash); 00233 tmp_table=0; 00234 used_tables=0; 00235 cuted_fields= sent_row_count= row_count= 0L; 00236 limit_found_rows= 0; 00237 statement_id_counter= 0UL; 00238 #ifdef ERROR_INJECT_SUPPORT 00239 error_inject_value= 0UL; 00240 #endif 00241 // Must be reset to handle error with THD's created for init of mysqld 00242 lex->current_select= 0; 00243 start_time=(time_t) 0; 00244 current_linfo = 0; 00245 slave_thread = 0; 00246 variables.pseudo_thread_id= 0; 00247 one_shot_set= 0; 00248 file_id = 0; 00249 query_id= 0; 00250 warn_id= 0; 00251 db_charset= global_system_variables.collation_database; 00252 bzero(ha_data, sizeof(ha_data)); 00253 mysys_var=0; 00254 binlog_evt_union.do_union= FALSE; 00255 enable_slow_log= 0; 00256 #ifndef DBUG_OFF 00257 dbug_sentry=THD_SENTRY_MAGIC; 00258 #endif 00259 #ifndef EMBEDDED_LIBRARY 00260 net.vio=0; 00261 #endif 00262 client_capabilities= 0; // minimalistic client 00263 net.last_error[0]=0; // If error on boot 00264 net.query_cache_query=0; // If error on boot 00265 ull=0; 00266 system_thread= NON_SYSTEM_THREAD; 00267 cleanup_done= abort_on_warning= no_warnings_for_error= 0; 00268 peer_port= 0; // For SHOW PROCESSLIST 00269 #ifdef HAVE_ROW_BASED_REPLICATION 00270 transaction.m_pending_rows_event= 0; 00271 #endif 00272 #ifdef __WIN__ 00273 real_id = 0; 00274 #endif 00275 #ifdef SIGNAL_WITH_VIO_CLOSE 00276 active_vio = 0; 00277 #endif 00278 pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST); 00279 00280 /* Variables with default values */ 00281 proc_info="login"; 00282 where= THD::DEFAULT_WHERE; 00283 server_id = ::server_id; 00284 slave_net = 0; 00285 command=COM_CONNECT; 00286 *scramble= '\0'; 00287 00288 init(); 00289 /* Initialize sub structures */ 00290 init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE); 00291 user_connect=(USER_CONN *)0; 00292 hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0, 00293 (hash_get_key) get_var_key, 00294 (hash_free_key) free_user_var, 0); 00295 00296 sp_proc_cache= NULL; 00297 sp_func_cache= NULL; 00298 00299 /* For user vars replication*/ 00300 if (opt_bin_log) 00301 my_init_dynamic_array(&user_var_events, 00302 sizeof(BINLOG_USER_VAR_EVENT *), 16, 16); 00303 else 00304 bzero((char*) &user_var_events, sizeof(user_var_events)); 00305 00306 /* Protocol */ 00307 protocol= &protocol_simple; // Default protocol 00308 protocol_simple.init(this); 00309 protocol_prep.init(this); 00310 00311 tablespace_op=FALSE; 00312 ulong tmp=sql_rnd_with_mutex(); 00313 randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::query_id); 00314 substitute_null_with_insert_id = FALSE; 00315 thr_lock_info_init(&lock_info); /* safety: will be reset after start */ 00316 thr_lock_owner_init(&main_lock_id, &lock_info); 00317 } 00318 00319 00320 /* 00321 Init common variables that has to be reset on start and on change_user 00322 */ 00323 00324 void THD::init(void) 00325 { 00326 pthread_mutex_lock(&LOCK_global_system_variables); 00327 variables= global_system_variables; 00328 variables.time_format= date_time_format_copy((THD*) 0, 00329 variables.time_format); 00330 variables.date_format= date_time_format_copy((THD*) 0, 00331 variables.date_format); 00332 variables.datetime_format= date_time_format_copy((THD*) 0, 00333 variables.datetime_format); 00334 #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE 00335 variables.ndb_use_transactions= 1; 00336 #endif 00337 pthread_mutex_unlock(&LOCK_global_system_variables); 00338 server_status= SERVER_STATUS_AUTOCOMMIT; 00339 if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) 00340 server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES; 00341 options= thd_startup_options; 00342 open_options=ha_open_options; 00343 update_lock_default= (variables.low_priority_updates ? 00344 TL_WRITE_LOW_PRIORITY : 00345 TL_WRITE); 00346 session_tx_isolation= (enum_tx_isolation) variables.tx_isolation; 00347 warn_list.empty(); 00348 bzero((char*) warn_count, sizeof(warn_count)); 00349 total_warn_count= 0; 00350 update_charset(); 00351 #ifdef HAVE_ROW_BASED_REPLICATION 00352 reset_current_stmt_binlog_row_based(); 00353 #endif /*HAVE_ROW_BASED_REPLICATION*/ 00354 bzero((char *) &status_var, sizeof(status_var)); 00355 variables.lc_time_names = &my_locale_en_US; 00356 } 00357 00358 00359 /* 00360 Init THD for query processing. 00361 This has to be called once before we call mysql_parse. 00362 See also comments in sql_class.h. 00363 */ 00364 00365 void THD::init_for_queries() 00366 { 00367 ha_enable_transaction(this,TRUE); 00368 00369 reset_root_defaults(mem_root, variables.query_alloc_block_size, 00370 variables.query_prealloc_size); 00371 #ifdef USING_TRANSACTIONS 00372 reset_root_defaults(&transaction.mem_root, 00373 variables.trans_alloc_block_size, 00374 variables.trans_prealloc_size); 00375 #endif 00376 transaction.xid_state.xid.null(); 00377 transaction.xid_state.in_thd=1; 00378 } 00379 00380 00381 /* 00382 Do what's needed when one invokes change user 00383 00384 SYNOPSIS 00385 change_user() 00386 00387 IMPLEMENTATION 00388 Reset all resources that are connection specific 00389 */ 00390 00391 00392 void THD::change_user(void) 00393 { 00394 cleanup(); 00395 cleanup_done= 0; 00396 init(); 00397 stmt_map.reset(); 00398 hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0, 00399 (hash_get_key) get_var_key, 00400 (hash_free_key) free_user_var, 0); 00401 sp_cache_clear(&sp_proc_cache); 00402 sp_cache_clear(&sp_func_cache); 00403 } 00404 00405 00406 /* Do operations that may take a long time */ 00407 00408 void THD::cleanup(void) 00409 { 00410 DBUG_ENTER("THD::cleanup"); 00411 #ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE 00412 if (transaction.xid_state.xa_state == XA_PREPARED) 00413 { 00414 #error xid_state in the cache should be replaced by the allocated value 00415 } 00416 #endif 00417 { 00418 ha_rollback(this); 00419 xid_cache_delete(&transaction.xid_state); 00420 } 00421 if (locked_tables) 00422 { 00423 lock=locked_tables; locked_tables=0; 00424 close_thread_tables(this); 00425 } 00426 mysql_ha_flush(this, (TABLE_LIST*) 0, 00427 MYSQL_HA_CLOSE_FINAL | MYSQL_HA_FLUSH_ALL, FALSE); 00428 hash_free(&handler_tables_hash); 00429 delete_dynamic(&user_var_events); 00430 hash_free(&user_vars); 00431 close_temporary_tables(this); 00432 my_free((char*) variables.time_format, MYF(MY_ALLOW_ZERO_PTR)); 00433 my_free((char*) variables.date_format, MYF(MY_ALLOW_ZERO_PTR)); 00434 my_free((char*) variables.datetime_format, MYF(MY_ALLOW_ZERO_PTR)); 00435 00436 sp_cache_clear(&sp_proc_cache); 00437 sp_cache_clear(&sp_func_cache); 00438 00439 if (global_read_lock) 00440 unlock_global_read_lock(this); 00441 if (ull) 00442 { 00443 pthread_mutex_lock(&LOCK_user_locks); 00444 item_user_lock_release(ull); 00445 pthread_mutex_unlock(&LOCK_user_locks); 00446 ull= 0; 00447 } 00448 00449 cleanup_done=1; 00450 DBUG_VOID_RETURN; 00451 } 00452 00453 00454 THD::~THD() 00455 { 00456 THD_CHECK_SENTRY(this); 00457 DBUG_ENTER("~THD()"); 00458 /* Ensure that no one is using THD */ 00459 pthread_mutex_lock(&LOCK_delete); 00460 pthread_mutex_unlock(&LOCK_delete); 00461 add_to_status(&global_status_var, &status_var); 00462 00463 /* Close connection */ 00464 #ifndef EMBEDDED_LIBRARY 00465 if (net.vio) 00466 { 00467 vio_delete(net.vio); 00468 net_end(&net); 00469 } 00470 #endif 00471 stmt_map.reset(); /* close all prepared statements */ 00472 DBUG_ASSERT(lock_info.n_cursors == 0); 00473 if (!cleanup_done) 00474 cleanup(); 00475 00476 ha_close_connection(this); 00477 00478 DBUG_PRINT("info", ("freeing security context")); 00479 main_security_ctx.destroy(); 00480 safeFree(db); 00481 free_root(&warn_root,MYF(0)); 00482 #ifdef USING_TRANSACTIONS 00483 free_root(&transaction.mem_root,MYF(0)); 00484 #endif 00485 mysys_var=0; // Safety (shouldn't be needed) 00486 pthread_mutex_destroy(&LOCK_delete); 00487 #ifndef DBUG_OFF 00488 dbug_sentry= THD_SENTRY_GONE; 00489 #endif 00490 #ifndef EMBEDDED_LIBRARY 00491 if (rli_fake) 00492 delete rli_fake; 00493 #endif 00494 00495 DBUG_VOID_RETURN; 00496 } 00497 00498 00499 /* 00500 Add all status variables to another status variable array 00501 00502 SYNOPSIS 00503 add_to_status() 00504 to_var add to this array 00505 from_var from this array 00506 00507 NOTES 00508 This function assumes that all variables are long/ulong. 00509 If this assumption will change, then we have to explictely add 00510 the other variables after the while loop 00511 */ 00512 00513 void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var) 00514 { 00515 ulong *end= (ulong*) ((byte*) to_var + offsetof(STATUS_VAR, 00516 last_system_status_var) + 00517 sizeof(ulong)); 00518 ulong *to= (ulong*) to_var, *from= (ulong*) from_var; 00519 00520 while (to != end) 00521 *(to++)+= *(from++); 00522 /* it doesn't make sense to add last_query_cost values */ 00523 } 00524 00525 /* 00526 Add the difference between two status variable arrays to another one. 00527 00528 SYNOPSIS 00529 add_diff_to_status 00530 to_var add to this array 00531 from_var from this array 00532 dec_var minus this array 00533 00534 NOTE 00535 This function assumes that all variables are long/ulong. 00536 */ 00537 00538 void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var, 00539 STATUS_VAR *dec_var) 00540 { 00541 ulong *end= (ulong*) ((byte*) to_var + offsetof(STATUS_VAR, 00542 last_system_status_var) + 00543 sizeof(ulong)); 00544 ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var; 00545 00546 while (to != end) 00547 *(to++)+= *(from++) - *(dec++); 00548 } 00549 00550 00551 void THD::awake(THD::killed_state state_to_set) 00552 { 00553 DBUG_ENTER("THD::awake"); 00554 DBUG_PRINT("enter", ("this=0x%lx", this)); 00555 THD_CHECK_SENTRY(this); 00556 safe_mutex_assert_owner(&LOCK_delete); 00557 00558 killed= state_to_set; 00559 if (state_to_set != THD::KILL_QUERY) 00560 { 00561 thr_alarm_kill(real_id); 00562 #ifdef SIGNAL_WITH_VIO_CLOSE 00563 close_active_vio(); 00564 #endif 00565 } 00566 if (mysys_var) 00567 { 00568 pthread_mutex_lock(&mysys_var->mutex); 00569 if (!system_thread) // Don't abort locks 00570 mysys_var->abort=1; 00571 /* 00572 This broadcast could be up in the air if the victim thread 00573 exits the cond in the time between read and broadcast, but that is 00574 ok since all we want to do is to make the victim thread get out 00575 of waiting on current_cond. 00576 If we see a non-zero current_cond: it cannot be an old value (because 00577 then exit_cond() should have run and it can't because we have mutex); so 00578 it is the true value but maybe current_mutex is not yet non-zero (we're 00579 in the middle of enter_cond() and there is a "memory order 00580 inversion"). So we test the mutex too to not lock 0. 00581 00582 Note that there is a small chance we fail to kill. If victim has locked 00583 current_mutex, but hasn't yet entered enter_cond() (which means that 00584 current_cond and current_mutex are 0), then the victim will not get 00585 a signal and it may wait "forever" on the cond (until 00586 we issue a second KILL or the status it's waiting for happens). 00587 It's true that we have set its thd->killed but it may not 00588 see it immediately and so may have time to reach the cond_wait(). 00589 */ 00590 if (mysys_var->current_cond && mysys_var->current_mutex) 00591 { 00592 pthread_mutex_lock(mysys_var->current_mutex); 00593 pthread_cond_broadcast(mysys_var->current_cond); 00594 pthread_mutex_unlock(mysys_var->current_mutex); 00595 } 00596 pthread_mutex_unlock(&mysys_var->mutex); 00597 } 00598 DBUG_VOID_RETURN; 00599 } 00600 00601 /* 00602 Remember the location of thread info, the structure needed for 00603 sql_alloc() and the structure for the net buffer 00604 */ 00605 00606 bool THD::store_globals() 00607 { 00608 /* 00609 Assert that thread_stack is initialized: it's necessary to be able 00610 to track stack overrun. 00611 */ 00612 DBUG_ASSERT(this->thread_stack); 00613 00614 if (my_pthread_setspecific_ptr(THR_THD, this) || 00615 my_pthread_setspecific_ptr(THR_MALLOC, &mem_root)) 00616 return 1; 00617 mysys_var=my_thread_var; 00618 dbug_thread_id=my_thread_id(); 00619 /* 00620 By default 'slave_proxy_id' is 'thread_id'. They may later become different 00621 if this is the slave SQL thread. 00622 */ 00623 variables.pseudo_thread_id= thread_id; 00624 /* 00625 We have to call thr_lock_info_init() again here as THD may have been 00626 created in another thread 00627 */ 00628 thr_lock_info_init(&lock_info); 00629 return 0; 00630 } 00631 00632 00633 /* Cleanup after a query */ 00634 00635 void THD::cleanup_after_query() 00636 { 00637 if (first_successful_insert_id_in_cur_stmt > 0) 00638 { 00639 /* set what LAST_INSERT_ID() will return */ 00640 first_successful_insert_id_in_prev_stmt= 00641 first_successful_insert_id_in_cur_stmt; 00642 first_successful_insert_id_in_cur_stmt= 0; 00643 substitute_null_with_insert_id= TRUE; 00644 } 00645 arg_of_last_insert_id_function= 0; 00646 /* Free Items that were created during this execution */ 00647 free_items(); 00648 /* Reset where. */ 00649 where= THD::DEFAULT_WHERE; 00650 } 00651 00652 /* 00653 Convert a string to another character set 00654 00655 SYNOPSIS 00656 convert_string() 00657 to Store new allocated string here 00658 to_cs New character set for allocated string 00659 from String to convert 00660 from_length Length of string to convert 00661 from_cs Original character set 00662 00663 NOTES 00664 to will be 0-terminated to make it easy to pass to system funcs 00665 00666 RETURN 00667 0 ok 00668 1 End of memory. 00669 In this case to->str will point to 0 and to->length will be 0. 00670 */ 00671 00672 bool THD::convert_string(LEX_STRING *to, CHARSET_INFO *to_cs, 00673 const char *from, uint from_length, 00674 CHARSET_INFO *from_cs) 00675 { 00676 DBUG_ENTER("convert_string"); 00677 size_s new_length= to_cs->mbmaxlen * from_length; 00678 uint dummy_errors; 00679 if (!(to->str= alloc(new_length+1))) 00680 { 00681 to->length= 0; // Safety fix 00682 DBUG_RETURN(1); // EOM 00683 } 00684 to->length= copy_and_convert((char*) to->str, new_length, to_cs, 00685 from, from_length, from_cs, &dummy_errors); 00686 to->str[to->length]=0; // Safety 00687 DBUG_RETURN(0); 00688 } 00689 00690 00691 /* 00692 Convert string from source character set to target character set inplace. 00693 00694 SYNOPSIS 00695 THD::convert_string 00696 00697 DESCRIPTION 00698 Convert string using convert_buffer - buffer for character set 00699 conversion shared between all protocols. 00700 00701 RETURN 00702 0 ok 00703 !0 out of memory 00704 */ 00705 00706 bool THD::convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs) 00707 { 00708 uint dummy_errors; 00709 if (convert_buffer.copy(s->ptr(), s->length(), from_cs, to_cs, &dummy_errors)) 00710 return TRUE; 00711 /* If convert_buffer >> s copying is more efficient long term */ 00712 if (convert_buffer.alloced_length() >= convert_buffer.length() * 2 || 00713 !s->is_alloced()) 00714 { 00715 return s->copy(convert_buffer); 00716 } 00717 s->swap(convert_buffer); 00718 return FALSE; 00719 } 00720 00721 00722 /* 00723 Update some cache variables when character set changes 00724 */ 00725 00726 void THD::update_charset() 00727 { 00728 uint32 not_used; 00729 charset_is_system_charset= !String::needs_conversion(0,charset(), 00730 system_charset_info, 00731 ¬_used); 00732 charset_is_collation_connection= 00733 !String::needs_conversion(0,charset(),variables.collation_connection, 00734 ¬_used); 00735 charset_is_character_set_filesystem= 00736 !String::needs_conversion(0, charset(), 00737 variables.character_set_filesystem, ¬_used); 00738 } 00739 00740 00741 /* routings to adding tables to list of changed in transaction tables */ 00742 00743 inline static void list_include(CHANGED_TABLE_LIST** prev, 00744 CHANGED_TABLE_LIST* curr, 00745 CHANGED_TABLE_LIST* new_table) 00746 { 00747 if (new_table) 00748 { 00749 *prev = new_table; 00750 (*prev)->next = curr; 00751 } 00752 } 00753 00754 /* add table to list of changed in transaction tables */ 00755 00756 void THD::add_changed_table(TABLE *table) 00757 { 00758 DBUG_ENTER("THD::add_changed_table(table)"); 00759 00760 DBUG_ASSERT((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && 00761 table->file->has_transactions()); 00762 add_changed_table(table->s->table_cache_key.str, 00763 table->s->table_cache_key.length); 00764 DBUG_VOID_RETURN; 00765 } 00766 00767 00768 void THD::add_changed_table(const char *key, long key_length) 00769 { 00770 DBUG_ENTER("THD::add_changed_table(key)"); 00771 CHANGED_TABLE_LIST **prev_changed = &transaction.changed_tables; 00772 CHANGED_TABLE_LIST *curr = transaction.changed_tables; 00773 00774 for (; curr; prev_changed = &(curr->next), curr = curr->next) 00775 { 00776 int cmp = (long)curr->key_length - (long)key_length; 00777 if (cmp < 0) 00778 { 00779 list_include(prev_changed, curr, changed_table_dup(key, key_length)); 00780 DBUG_PRINT("info", 00781 ("key_length %u %u", key_length, (*prev_changed)->key_length)); 00782 DBUG_VOID_RETURN; 00783 } 00784 else if (cmp == 0) 00785 { 00786 cmp = memcmp(curr->key, key, curr->key_length); 00787 if (cmp < 0) 00788 { 00789 list_include(prev_changed, curr, changed_table_dup(key, key_length)); 00790 DBUG_PRINT("info", 00791 ("key_length %u %u", key_length, 00792 (*prev_changed)->key_length)); 00793 DBUG_VOID_RETURN; 00794 } 00795 else if (cmp == 0) 00796 { 00797 DBUG_PRINT("info", ("already in list")); 00798 DBUG_VOID_RETURN; 00799 } 00800 } 00801 } 00802 *prev_changed = changed_table_dup(key, key_length); 00803 DBUG_PRINT("info", ("key_length %u %u", key_length, 00804 (*prev_changed)->key_length)); 00805 DBUG_VOID_RETURN; 00806 } 00807 00808 00809 CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, long key_length) 00810 { 00811 CHANGED_TABLE_LIST* new_table = 00812 (CHANGED_TABLE_LIST*) trans_alloc(ALIGN_SIZE(sizeof(CHANGED_TABLE_LIST))+ 00813 key_length + 1); 00814 if (!new_table) 00815 { 00816 my_error(EE_OUTOFMEMORY, MYF(ME_BELL), 00817 ALIGN_SIZE(sizeof(TABLE_LIST)) + key_length + 1); 00818 killed= KILL_CONNECTION; 00819 return 0; 00820 } 00821 00822 new_table->key = (char *) (((byte*)new_table)+ 00823 ALIGN_SIZE(sizeof(CHANGED_TABLE_LIST))); 00824 new_table->next = 0; 00825 new_table->key_length = key_length; 00826 ::memcpy(new_table->key, key, key_length); 00827 return new_table; 00828 } 00829 00830 00831 int THD::send_explain_fields(select_result *result) 00832 { 00833 List<Item> field_list; 00834 Item *item; 00835 CHARSET_INFO *cs= system_charset_info; 00836 field_list.push_back(new Item_return_int("id",3, MYSQL_TYPE_LONGLONG)); 00837 field_list.push_back(new Item_empty_string("select_type", 19, cs)); 00838 field_list.push_back(item= new Item_empty_string("table", NAME_LEN, cs)); 00839 item->maybe_null= 1; 00840 #ifdef WITH_PARTITION_STORAGE_ENGINE 00841 if (lex->describe & DESCRIBE_PARTITIONS) 00842 { 00843 /* Maximum length of string that make_used_partitions_str() can produce */ 00844 item= new Item_empty_string("partitions", MAX_PARTITIONS * (1 + FN_LEN), 00845 cs); 00846 field_list.push_back(item); 00847 item->maybe_null= 1; 00848 } 00849 #endif 00850 field_list.push_back(item= new Item_empty_string("type", 10, cs)); 00851 item->maybe_null= 1; 00852 field_list.push_back(item=new Item_empty_string("possible_keys", 00853 NAME_LEN*MAX_KEY, cs)); 00854 item->maybe_null=1; 00855 field_list.push_back(item=new Item_empty_string("key", NAME_LEN, cs)); 00856 item->maybe_null=1; 00857 field_list.push_back(item=new Item_empty_string("key_len", 00858 NAME_LEN*MAX_KEY)); 00859 item->maybe_null=1; 00860 field_list.push_back(item=new Item_empty_string("ref", 00861 NAME_LEN*MAX_REF_PARTS, cs)); 00862 item->maybe_null=1; 00863 field_list.push_back(item= new Item_return_int("rows", 10, 00864 MYSQL_TYPE_LONGLONG)); 00865 if (lex->describe & DESCRIBE_EXTENDED) 00866 { 00867 field_list.push_back(item= new Item_float("filtered", 0.1234, 2, 4)); 00868 item->maybe_null=1; 00869 } 00870 item->maybe_null= 1; 00871 field_list.push_back(new Item_empty_string("Extra", 255, cs)); 00872 return (result->send_fields(field_list, 00873 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)); 00874 } 00875 00876 #ifdef SIGNAL_WITH_VIO_CLOSE 00877 void THD::close_active_vio() 00878 { 00879 DBUG_ENTER("close_active_vio"); 00880 safe_mutex_assert_owner(&LOCK_delete); 00881 #ifndef EMBEDDED_LIBRARY 00882 if (active_vio) 00883 { 00884 vio_close(active_vio); 00885 active_vio = 0; 00886 } 00887 #endif 00888 DBUG_VOID_RETURN; 00889 } 00890 #endif 00891 00892 00893 struct Item_change_record: public ilink 00894 { 00895 Item **place; 00896 Item *old_value; 00897 /* Placement new was hidden by `new' in ilink (TODO: check): */ 00898 static void *operator new(size_t size, void *mem) { return mem; } 00899 static void operator delete(void *ptr, size_t size) {} 00900 static void operator delete(void *ptr, void *mem) { /* never called */ } 00901 }; 00902 00903 00904 /* 00905 Register an item tree tree transformation, performed by the query 00906 optimizer. We need a pointer to runtime_memroot because it may be != 00907 thd->mem_root (due to possible set_n_backup_active_arena called for thd). 00908 */ 00909 00910 void THD::nocheck_register_item_tree_change(Item **place, Item *old_value, 00911 MEM_ROOT *runtime_memroot) 00912 { 00913 Item_change_record *change; 00914 /* 00915 Now we use one node per change, which adds some memory overhead, 00916 but still is rather fast as we use alloc_root for allocations. 00917 A list of item tree changes of an average query should be short. 00918 */ 00919 void *change_mem= alloc_root(runtime_memroot, sizeof(*change)); 00920 if (change_mem == 0) 00921 { 00922 /* 00923 OOM, thd->fatal_error() is called by the error handler of the 00924 memroot. Just return. 00925 */ 00926 return; 00927 } 00928 change= new (change_mem) Item_change_record; 00929 change->place= place; 00930 change->old_value= old_value; 00931 change_list.append(change); 00932 } 00933 00934 00935 void THD::rollback_item_tree_changes() 00936 { 00937 I_List_iterator<Item_change_record> it(change_list); 00938 Item_change_record *change; 00939 DBUG_ENTER("rollback_item_tree_changes"); 00940 00941 while ((change= it++)) 00942 *change->place= change->old_value; 00943 /* We can forget about changes memory: it's allocated in runtime memroot */ 00944 change_list.empty(); 00945 DBUG_VOID_RETURN; 00946 } 00947 00948 00949 /***************************************************************************** 00950 ** Functions to provide a interface to select results 00951 *****************************************************************************/ 00952 00953 select_result::select_result() 00954 { 00955 thd=current_thd; 00956 } 00957 00958 void select_result::send_error(uint errcode,const char *err) 00959 { 00960 my_message(errcode, err, MYF(0)); 00961 } 00962 00963 00964 void select_result::cleanup() 00965 { 00966 /* do nothing */ 00967 } 00968 00969 static String default_line_term("\n",default_charset_info); 00970 static String default_escaped("\\",default_charset_info); 00971 static String default_field_term("\t",default_charset_info); 00972 00973 sql_exchange::sql_exchange(char *name,bool flag) 00974 :file_name(name), opt_enclosed(0), dumpfile(flag), skip_lines(0) 00975 { 00976 field_term= &default_field_term; 00977 enclosed= line_start= &my_empty_string; 00978 line_term= &default_line_term; 00979 escaped= &default_escaped; 00980 } 00981 00982 bool select_send::send_fields(List<Item> &list, uint flags) 00983 { 00984 bool res; 00985 if (!(res= thd->protocol->send_fields(&list, flags))) 00986 status= 1; 00987 return res; 00988 } 00989 00990 void select_send::abort() 00991 { 00992 DBUG_ENTER("select_send::abort"); 00993 if (status && thd->spcont && 00994 thd->spcont->find_handler(thd->net.last_errno, 00995 MYSQL_ERROR::WARN_LEVEL_ERROR)) 00996 { 00997 /* 00998 Executing stored procedure without a handler. 00999 Here we should actually send an error to the client, 01000 but as an error will break a multiple result set, the only thing we 01001 can do for now is to nicely end the current data set and remembering 01002 the error so that the calling routine will abort 01003 */ 01004 thd->net.report_error= 0; 01005 send_eof(); 01006 thd->net.report_error= 1; // Abort SP 01007 } 01008 DBUG_VOID_RETURN; 01009 } 01010 01011 01012 /* Send data to client. Returns 0 if ok */ 01013 01014 bool select_send::send_data(List<Item> &items) 01015 { 01016 if (unit->offset_limit_cnt) 01017 { // using limit offset,count 01018 unit->offset_limit_cnt--; 01019 return 0; 01020 } 01021 01022 /* 01023 We may be passing the control from mysqld to the client: release the 01024 InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved 01025 by thd 01026 */ 01027 ha_release_temporary_latches(thd); 01028 01029 List_iterator_fast<Item> li(items); 01030 Protocol *protocol= thd->protocol; 01031 char buff[MAX_FIELD_WIDTH]; 01032 String buffer(buff, sizeof(buff), &my_charset_bin); 01033 DBUG_ENTER("select_send::send_data"); 01034 01035 protocol->prepare_for_resend(); 01036 Item *item; 01037 while ((item=li++)) 01038 { 01039 if (item->send(protocol, &buffer)) 01040 { 01041 protocol->free(); // Free used buffer 01042 my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); 01043 break; 01044 } 01045 } 01046 thd->sent_row_count++; 01047 if (!thd->vio_ok()) 01048 DBUG_RETURN(0); 01049 if (!thd->net.report_error) 01050 DBUG_RETURN(protocol->write()); 01051 protocol->remove_last_row(); 01052 DBUG_RETURN(1); 01053 } 01054 01055 bool select_send::send_eof() 01056 { 01057 /* 01058 We may be passing the control from mysqld to the client: release the 01059 InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved 01060 by thd 01061 */ 01062 ha_release_temporary_latches(thd); 01063 01064 /* Unlock tables before sending packet to gain some speed */ 01065 if (thd->lock) 01066 { 01067 mysql_unlock_tables(thd, thd->lock); 01068 thd->lock=0; 01069 } 01070 if (!thd->net.report_error) 01071 { 01072 ::send_eof(thd); 01073 status= 0; 01074 return 0; 01075 } 01076 else 01077 return 1; 01078 } 01079 01080 01081 /************************************************************************ 01082 Handling writing to file 01083 ************************************************************************/ 01084 01085 void select_to_file::send_error(uint errcode,const char *err) 01086 { 01087 my_message(errcode, err, MYF(0)); 01088 if (file > 0) 01089 { 01090 (void) end_io_cache(&cache); 01091 (void) my_close(file,MYF(0)); 01092 (void) my_delete(path,MYF(0)); // Delete file on error 01093 file= -1; 01094 } 01095 } 01096 01097 01098 bool select_to_file::send_eof() 01099 { 01100 int error= test(end_io_cache(&cache)); 01101 if (my_close(file,MYF(MY_WME))) 01102 error= 1; 01103 if (!error) 01104 ::send_ok(thd,row_count); 01105 file= -1; 01106 return error; 01107 } 01108 01109 01110 void select_to_file::cleanup() 01111 { 01112 /* In case of error send_eof() may be not called: close the file here. */ 01113 if (file >= 0) 01114 { 01115 (void) end_io_cache(&cache); 01116 (void) my_close(file,MYF(0)); 01117 file= -1; 01118 } 01119 path[0]= '\0'; 01120 row_count= 0; 01121 } 01122 01123 01124 select_to_file::~select_to_file() 01125 { 01126 if (file >= 0) 01127 { // This only happens in case of error 01128 (void) end_io_cache(&cache); 01129 (void) my_close(file,MYF(0)); 01130 file= -1; 01131 } 01132 } 01133 01134 /*************************************************************************** 01135 ** Export of select to textfile 01136 ***************************************************************************/ 01137 01138 select_export::~select_export() 01139 { 01140 thd->sent_row_count=row_count; 01141 } 01142 01143 01144 /* 01145 Create file with IO cache 01146 01147 SYNOPSIS 01148 create_file() 01149 thd Thread handle 01150 path File name 01151 exchange Excange class 01152 cache IO cache 01153 01154 RETURN 01155 >= 0 File handle 01156 -1 Error 01157 */ 01158 01159 01160 static File create_file(THD *thd, char *path, sql_exchange *exchange, 01161 IO_CACHE *cache) 01162 { 01163 File file; 01164 uint option= MY_UNPACK_FILENAME; 01165 01166 #ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS 01167 option|= MY_REPLACE_DIR; // Force use of db directory 01168 #endif 01169 01170 if (!dirname_length(exchange->file_name)) 01171 { 01172 strxnmov(path, FN_REFLEN-1, mysql_real_data_home, thd->db ? thd->db : "", 01173 NullS); 01174 (void) fn_format(path, exchange->file_name, path, "", option); 01175 } 01176 else 01177 (void) fn_format(path, exchange->file_name, mysql_real_data_home, "", option); 01178 01179 if (!access(path, F_OK)) 01180 { 01181 my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name); 01182 return -1; 01183 } 01184 /* Create the file world readable */ 01185 if ((file= my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0) 01186 return file; 01187 #ifdef HAVE_FCHMOD 01188 (void) fchmod(file, 0666); // Because of umask() 01189 #else 01190 (void) chmod(path, 0666); 01191 #endif 01192 if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME))) 01193 { 01194 my_close(file, MYF(0)); 01195 my_delete(path, MYF(0)); // Delete file on error, it was just created 01196 return -1; 01197 } 01198 return file; 01199 } 01200 01201 01202 int 01203 select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u) 01204 { 01205 bool blob_flag=0; 01206 unit= u; 01207 if ((uint) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN) 01208 strmake(path,exchange->file_name,FN_REFLEN-1); 01209 01210 if ((file= create_file(thd, path, exchange, &cache)) < 0) 01211 return 1; 01212 /* Check if there is any blobs in data */ 01213 { 01214 List_iterator_fast<Item> li(list); 01215 Item *item; 01216 while ((item=li++)) 01217 { 01218 if (item->max_length >= MAX_BLOB_WIDTH) 01219 { 01220 blob_flag=1; 01221 break; 01222 } 01223 } 01224 } 01225 field_term_length=exchange->field_term->length(); 01226 if (!exchange->line_term->length()) 01227 exchange->line_term=exchange->field_term; // Use this if it exists 01228 field_sep_char= (exchange->enclosed->length() ? (*exchange->enclosed)[0] : 01229 field_term_length ? (*exchange->field_term)[0] : INT_MAX); 01230 escape_char= (exchange->escaped->length() ? (*exchange->escaped)[0] : -1); 01231 line_sep_char= (exchange->line_term->length() ? 01232 (*exchange->line_term)[0] : INT_MAX); 01233 if (!field_term_length) 01234 exchange->opt_enclosed=0; 01235 if (!exchange->enclosed->length()) 01236 exchange->opt_enclosed=1; // A little quicker loop 01237 fixed_row_size= (!field_term_length && !exchange->enclosed->length() && 01238 !blob_flag); 01239 return 0; 01240 } 01241 01242 01243 bool select_export::send_data(List<Item> &items) 01244 { 01245 01246 DBUG_ENTER("select_export::send_data"); 01247 char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH]; 01248 bool space_inited=0; 01249 String tmp(buff,sizeof(buff),&my_charset_bin),*res; 01250 tmp.length(0); 01251 01252 if (unit->offset_limit_cnt) 01253 { // using limit offset,count 01254 unit->offset_limit_cnt--; 01255 DBUG_RETURN(0); 01256 } 01257 row_count++; 01258 Item *item; 01259 char *buff_ptr=buff; 01260 uint used_length=0,items_left=items.elements; 01261 List_iterator_fast<Item> li(items); 01262 01263 if (my_b_write(&cache,(byte*) exchange->line_start->ptr(), 01264 exchange->line_start->length())) 01265 goto err; 01266 while ((item=li++)) 01267 { 01268 Item_result result_type=item->result_type(); 01269 res=item->str_result(&tmp); 01270 if (res && (!exchange->opt_enclosed || result_type == STRING_RESULT)) 01271 { 01272 if (my_b_write(&cache,(byte*) exchange->enclosed->ptr(), 01273 exchange->enclosed->length())) 01274 goto err; 01275 } 01276 if (!res) 01277 { // NULL 01278 if (!fixed_row_size) 01279 { 01280 if (escape_char != -1) // Use \N syntax 01281 { 01282 null_buff[0]=escape_char; 01283 null_buff[1]='N'; 01284 if (my_b_write(&cache,(byte*) null_buff,2)) 01285 goto err; 01286 } 01287 else if (my_b_write(&cache,(byte*) "NULL",4)) 01288 goto err; 01289 } 01290 else 01291 { 01292 used_length=0; // Fill with space 01293 } 01294 } 01295 else 01296 { 01297 if (fixed_row_size) 01298 used_length=min(res->length(),item->max_length); 01299 else 01300 used_length=res->length(); 01301 if (result_type == STRING_RESULT && escape_char != -1) 01302 { 01303 char *pos,*start,*end; 01304 01305 for (start=pos=(char*) res->ptr(),end=pos+used_length ; 01306 pos != end ; 01307 pos++) 01308 { 01309 #ifdef USE_MB 01310 CHARSET_INFO *res_charset=res->charset(); 01311 if (use_mb(res_charset)) 01312 { 01313 int l; 01314 if ((l=my_ismbchar(res_charset, pos, end))) 01315 { 01316 pos += l-1; 01317 continue; 01318 } 01319 } 01320 #endif 01321 if ((int) *pos == escape_char || (int) *pos == field_sep_char || 01322 (int) *pos == line_sep_char || !*pos) 01323 { 01324 char tmp_buff[2]; 01325 tmp_buff[0]= escape_char; 01326 tmp_buff[1]= *pos ? *pos : '0'; 01327 if (my_b_write(&cache,(byte*) start,(uint) (pos-start)) || 01328 my_b_write(&cache,(byte*) tmp_buff,2)) 01329 goto err; 01330 start=pos+1; 01331 } 01332 } 01333 if (my_b_write(&cache,(byte*) start,(uint) (pos-start))) 01334 goto err; 01335 } 01336 else if (my_b_write(&cache,(byte*) res->ptr(),used_length)) 01337 goto err; 01338 } 01339 if (fixed_row_size) 01340 { // Fill with space 01341 if (item->max_length > used_length) 01342 { 01343 /* QQ: Fix by adding a my_b_fill() function */ 01344 if (!space_inited) 01345 { 01346 space_inited=1; 01347 bfill(space,sizeof(space),' '); 01348 } 01349 uint length=item->max_length-used_length; 01350 for (; length > sizeof(space) ; length-=sizeof(space)) 01351 { 01352 if (my_b_write(&cache,(byte*) space,sizeof(space))) 01353 goto err; 01354 } 01355 if (my_b_write(&cache,(byte*) space,length)) 01356 goto err; 01357 } 01358 } 01359 buff_ptr=buff; // Place separators here 01360 if (res && (!exchange->opt_enclosed || result_type == STRING_RESULT)) 01361 { 01362 memcpy(buff_ptr,exchange->enclosed->ptr(),exchange->enclosed->length()); 01363 buff_ptr+=exchange->enclosed->length(); 01364 } 01365 if (--items_left) 01366 { 01367 memcpy(buff_ptr,exchange->field_term->ptr(),field_term_length); 01368 buff_ptr+=field_term_length; 01369 } 01370 if (my_b_write(&cache,(byte*) buff,(uint) (buff_ptr-buff))) 01371 goto err; 01372 } 01373 if (my_b_write(&cache,(byte*) exchange->line_term->ptr(), 01374 exchange->line_term->length())) 01375 goto err; 01376 DBUG_RETURN(0); 01377 err: 01378 DBUG_RETURN(1); 01379 } 01380 01381 01382 /*************************************************************************** 01383 ** Dump of select to a binary file 01384 ***************************************************************************/ 01385 01386 01387 int 01388 select_dump::prepare(List<Item> &list __attribute__((unused)), 01389 SELECT_LEX_UNIT *u) 01390 { 01391 unit= u; 01392 return (int) ((file= create_file(thd, path, exchange, &cache)) < 0); 01393 } 01394 01395 01396 bool select_dump::send_data(List<Item> &items) 01397 { 01398 List_iterator_fast<Item> li(items); 01399 char buff[MAX_FIELD_WIDTH]; 01400 String tmp(buff,sizeof(buff),&my_charset_bin),*res; 01401 tmp.length(0); 01402 Item *item; 01403 DBUG_ENTER("select_dump::send_data"); 01404 01405 if (unit->offset_limit_cnt) 01406 { // using limit offset,count 01407 unit->offset_limit_cnt--; 01408 DBUG_RETURN(0); 01409 } 01410 if (row_count++ > 1) 01411 { 01412 my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0)); 01413 goto err; 01414 } 01415 while ((item=li++)) 01416 { 01417 res=item->str_result(&tmp); 01418 if (!res) // If NULL 01419 { 01420 if (my_b_write(&cache,(byte*) "",1)) 01421 goto err; 01422 } 01423 else if (my_b_write(&cache,(byte*) res->ptr(),res->length())) 01424 { 01425 my_error(ER_ERROR_ON_WRITE, MYF(0), path, my_errno); 01426 goto err; 01427 } 01428 } 01429 DBUG_RETURN(0); 01430 err: 01431 DBUG_RETURN(1); 01432 } 01433 01434 01435 select_subselect::select_subselect(Item_subselect *item_arg) 01436 { 01437 item= item_arg; 01438 } 01439 01440 01441 bool select_singlerow_subselect::send_data(List<Item> &items) 01442 { 01443 DBUG_ENTER("select_singlerow_subselect::send_data"); 01444 Item_singlerow_subselect *it= (Item_singlerow_subselect *)item; 01445 if (it->assigned()) 01446 { 01447 my_message(ER_SUBQUERY_NO_1_ROW, ER(ER_SUBQUERY_NO_1_ROW), MYF(0)); 01448 DBUG_RETURN(1); 01449 } 01450 if (unit->offset_limit_cnt) 01451 { // Using limit offset,count 01452 unit->offset_limit_cnt--; 01453 DBUG_RETURN(0); 01454 } 01455 List_iterator_fast<Item> li(items); 01456 Item *val_item; 01457 for (uint i= 0; (val_item= li++); i++) 01458 it->store(i, val_item); 01459 it->assigned(1); 01460 DBUG_RETURN(0); 01461 } 01462 01463 01464 void select_max_min_finder_subselect::cleanup() 01465 { 01466 DBUG_ENTER("select_max_min_finder_subselect::cleanup"); 01467 cache= 0; 01468 DBUG_VOID_RETURN; 01469 } 01470 01471 01472 bool select_max_min_finder_subselect::send_data(List<Item> &items) 01473 { 01474 DBUG_ENTER("select_max_min_finder_subselect::send_data"); 01475 Item_maxmin_subselect *it= (Item_maxmin_subselect *)item; 01476 List_iterator_fast<Item> li(items); 01477 Item *val_item= li++; 01478 it->register_value(); 01479 if (it->assigned()) 01480 { 01481 cache->store(val_item); 01482 if ((this->*op)()) 01483 it->store(0, cache); 01484 } 01485 else 01486 { 01487 if (!cache) 01488 { 01489 cache= Item_cache::get_cache(val_item->result_type()); 01490 switch (val_item->result_type()) 01491 { 01492 case REAL_RESULT: 01493 op= &select_max_min_finder_subselect::cmp_real; 01494 break; 01495 case INT_RESULT: 01496 op= &select_max_min_finder_subselect::cmp_int; 01497 break; 01498 case STRING_RESULT: 01499 op= &select_max_min_finder_subselect::cmp_str; 01500 break; 01501 case DECIMAL_RESULT: 01502 op= &select_max_min_finder_subselect::cmp_decimal; 01503 break; 01504 case ROW_RESULT: 01505 // This case should never be choosen 01506 DBUG_ASSERT(0); 01507 op= 0; 01508 } 01509 } 01510 cache->store(val_item); 01511 it->store(0, cache); 01512 } 01513 it->assigned(1); 01514 DBUG_RETURN(0); 01515 } 01516 01517 bool select_max_min_finder_subselect::cmp_real() 01518 { 01519 Item *maxmin= ((Item_singlerow_subselect *)item)->el(0); 01520 double val1= cache->val_real(), val2= maxmin->val_real(); 01521 if (fmax) 01522 return (cache->null_value && !maxmin->null_value) || 01523 (!cache->null_value && !maxmin->null_value && 01524 val1 > val2); 01525 return (maxmin->null_value && !cache->null_value) || 01526 (!cache->null_value && !maxmin->null_value && 01527 val1 < val2); 01528 } 01529 01530 bool select_max_min_finder_subselect::cmp_int() 01531 { 01532 Item *maxmin= ((Item_singlerow_subselect *)item)->el(0); 01533 longlong val1= cache->val_int(), val2= maxmin->val_int(); 01534 if (fmax) 01535 return (cache->null_value && !maxmin->null_value) || 01536 (!cache->null_value && !maxmin->null_value && 01537 val1 > val2); 01538 return (maxmin->null_value && !cache->null_value) || 01539 (!cache->null_value && !maxmin->null_value && 01540 val1 < val2); 01541 } 01542 01543 bool select_max_min_finder_subselect::cmp_decimal() 01544 { 01545 Item *maxmin= ((Item_singlerow_subselect *)item)->el(0); 01546 my_decimal cval, *cvalue= cache->val_decimal(&cval); 01547 my_decimal mval, *mvalue= maxmin->val_decimal(&mval); 01548 if (fmax) 01549 return (cache->null_value && !maxmin->null_value) || 01550 (!cache->null_value && !maxmin->null_value && 01551 my_decimal_cmp(cvalue, mvalue) > 0) ; 01552 return (maxmin->null_value && !cache->null_value) || 01553 (!cache->null_value && !maxmin->null_value && 01554 my_decimal_cmp(cvalue,mvalue) < 0); 01555 } 01556 01557 bool select_max_min_finder_subselect::cmp_str() 01558 { 01559 String *val1, *val2, buf1, buf2; 01560 Item *maxmin= ((Item_singlerow_subselect *)item)->el(0); 01561 /* 01562 as far as both operand is Item_cache buf1 & buf2 will not be used, 01563 but added for safety 01564 */ 01565 val1= cache->val_str(&buf1); 01566 val2= maxmin->val_str(&buf1); 01567 if (fmax) 01568 return (cache->null_value && !maxmin->null_value) || 01569 (!cache->null_value && !maxmin->null_value && 01570 sortcmp(val1, val2, cache->collation.collation) > 0) ; 01571 return (maxmin->null_value && !cache->null_value) || 01572 (!cache->null_value && !maxmin->null_value && 01573 sortcmp(val1, val2, cache->collation.collation) < 0); 01574 } 01575 01576 bool select_exists_subselect::send_data(List<Item> &items) 01577 { 01578 DBUG_ENTER("select_exists_subselect::send_data"); 01579 Item_exists_subselect *it= (Item_exists_subselect *)item; 01580 if (unit->offset_limit_cnt) 01581 { // Using limit offset,count 01582 unit->offset_limit_cnt--; 01583 DBUG_RETURN(0); 01584 } 01585 it->value= 1; 01586 it->assigned(1); 01587 DBUG_RETURN(0); 01588 } 01589 01590 01591 /*************************************************************************** 01592 Dump of select to variables 01593 ***************************************************************************/ 01594 01595 int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u) 01596 { 01597 List_iterator_fast<Item> li(list); 01598 List_iterator_fast<my_var> gl(var_list); 01599 Item *item; 01600 01601 local_vars.empty(); // Clear list if SP 01602 unit= u; 01603 row_count= 0; 01604 01605 if (var_list.elements != list.elements) 01606 { 01607 my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT, 01608 ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT), MYF(0)); 01609 return 1; 01610 } 01611 while ((item=li++)) 01612 { 01613 my_var *mv= gl++; 01614 if (mv->local) 01615 { 01616 Item_splocal *var= new Item_splocal(mv->s, mv->offset, mv->type); 01617 (void)local_vars.push_back(var); 01618 #ifndef DBUG_OFF 01619 var->m_sp= mv->sp; 01620 #endif 01621 } 01622 else 01623 { 01624 Item_func_set_user_var *var= new Item_func_set_user_var(mv->s, item); 01625 /* 01626 Item_func_set_user_var can't substitute something else on its place => 01627 0 can be passed as last argument (reference on item) 01628 Item_func_set_user_var can't be fixed after creation, so we do not 01629 check var->fixed 01630 */ 01631 var->fix_fields(thd, 0); 01632 var->fix_length_and_dec(); 01633 vars.push_back(var); 01634 } 01635 } 01636 return 0; 01637 } 01638 01639 01640 void select_dumpvar::cleanup() 01641 { 01642 vars.empty(); 01643 row_count=0; 01644 } 01645 01646 01647 Query_arena::Type Query_arena::type() const 01648 { 01649 DBUG_ASSERT(0); /* Should never be called */ 01650 return STATEMENT; 01651 } 01652 01653 01654 void Query_arena::free_items() 01655 { 01656 Item *next; 01657 DBUG_ENTER("Query_arena::free_items"); 01658 /* This works because items are allocated with sql_alloc() */ 01659 for (; free_list; free_list= next) 01660 { 01661 next= free_list->next; 01662 free_list->delete_self(); 01663 } 01664 /* Postcondition: free_list is 0 */ 01665 DBUG_VOID_RETURN; 01666 } 01667 01668 01669 void Query_arena::set_query_arena(Query_arena *set) 01670 { 01671 mem_root= set->mem_root; 01672 free_list= set->free_list; 01673 state= set->state; 01674 } 01675 01676 01677 void Query_arena::cleanup_stmt() 01678 { 01679 DBUG_ASSERT("Query_arena::cleanup_stmt()" == "not implemented"); 01680 } 01681 01682 /* 01683 Statement functions 01684 */ 01685 01686 Statement::Statement(enum enum_state state_arg, ulong id_arg, 01687 ulong alloc_block_size, ulong prealloc_size) 01688 :Query_arena(&main_mem_root, state_arg), 01689 id(id_arg), 01690 mark_used_columns(MARK_COLUMNS_READ), 01691 lex(&main_lex), 01692 query(0), 01693 query_length(0), 01694 cursor(0) 01695 { 01696 name.str= NULL; 01697 init_sql_alloc(&main_mem_root, alloc_block_size, prealloc_size); 01698 } 01699 01700 01701 Query_arena::Type Statement::type() const 01702 { 01703 return STATEMENT; 01704 } 01705 01706 01707 void Statement::set_statement(Statement *stmt) 01708 { 01709 id= stmt->id; 01710 mark_used_columns= stmt->mark_used_columns; 01711 lex= stmt->lex; 01712 query= stmt->query; 01713 query_length= stmt->query_length; 01714 cursor= stmt->cursor; 01715 } 01716 01717 01718 void 01719 Statement::set_n_backup_statement(Statement *stmt, Statement *backup) 01720 { 01721 DBUG_ENTER("Statement::set_n_backup_statement"); 01722 backup->set_statement(this); 01723 set_statement(stmt); 01724 DBUG_VOID_RETURN; 01725 } 01726 01727 01728 void Statement::restore_backup_statement(Statement *stmt, Statement *backup) 01729 { 01730 DBUG_ENTER("Statement::restore_backup_statement"); 01731 stmt->set_statement(this); 01732 set_statement(backup); 01733 DBUG_VOID_RETURN; 01734 } 01735 01736 01737 void THD::end_statement() 01738 { 01739 /* Cleanup SQL processing state to resuse this statement in next query. */ 01740 lex_end(lex); 01741 delete lex->result; 01742 lex->result= 0; 01743 /* Note that free_list is freed in cleanup_after_query() */ 01744 01745 /* 01746 Don't free mem_root, as mem_root is freed in the end of dispatch_command 01747 (once for any command). 01748 */ 01749 } 01750 01751 01752 void THD::set_n_backup_active_arena(Query_arena *set, Query_arena *backup) 01753 { 01754 DBUG_ENTER("THD::set_n_backup_active_arena"); 01755 DBUG_ASSERT(backup->is_backup_arena == FALSE); 01756 01757 backup->set_query_arena(this); 01758 set_query_arena(set); 01759 #ifndef DBUG_OFF 01760 backup->is_backup_arena= TRUE; 01761 #endif 01762 DBUG_VOID_RETURN; 01763 } 01764 01765 01766 void THD::restore_active_arena(Query_arena *set, Query_arena *backup) 01767 { 01768 DBUG_ENTER("THD::restore_active_arena"); 01769 DBUG_ASSERT(backup->is_backup_arena); 01770 set->set_query_arena(this); 01771 set_query_arena(backup); 01772 #ifndef DBUG_OFF 01773 backup->is_backup_arena= FALSE; 01774 #endif 01775 DBUG_VOID_RETURN; 01776 } 01777 01778 Statement::~Statement() 01779 { 01780 /* 01781 We must free `main_mem_root', not `mem_root' (pointer), to work 01782 correctly if this statement is used as a backup statement, 01783 for which `mem_root' may point to some other statement. 01784 */ 01785 free_root(&main_mem_root, MYF(0)); 01786 } 01787 01788 C_MODE_START 01789 01790 static byte * 01791 get_statement_id_as_hash_key(const byte *record, uint *key_length, 01792 my_bool not_used __attribute__((unused))) 01793 { 01794 const Statement *statement= (const Statement *) record; 01795 *key_length= sizeof(statement->id); 01796 return (byte *) &((const Statement *) statement)->id; 01797 } 01798 01799 static void delete_statement_as_hash_key(void *key) 01800 { 01801 delete (Statement *) key; 01802 } 01803 01804 static byte *get_stmt_name_hash_key(Statement *entry, uint *length, 01805 my_bool not_used __attribute__((unused))) 01806 { 01807 *length=(uint) entry->name.length; 01808 return (byte*) entry->name.str; 01809 } 01810 01811 C_MODE_END 01812 01813 Statement_map::Statement_map() : 01814 last_found_statement(0) 01815 { 01816 enum 01817 { 01818 START_STMT_HASH_SIZE = 16, 01819 START_NAME_HASH_SIZE = 16 01820 }; 01821 hash_init(&st_hash, &my_charset_bin, START_STMT_HASH_SIZE, 0, 0, 01822 get_statement_id_as_hash_key, 01823 delete_statement_as_hash_key, MYF(0)); 01824 hash_init(&names_hash, system_charset_info, START_NAME_HASH_SIZE, 0, 0, 01825 (hash_get_key) get_stmt_name_hash_key, 01826 NULL,MYF(0)); 01827 } 01828 01829 01830 /* 01831 Insert a new statement to the thread-local statement map. 01832 01833 DESCRIPTION 01834 If there was an old statement with the same name, replace it with the 01835 new one. Otherwise, check if max_prepared_stmt_count is not reached yet, 01836 increase prepared_stmt_count, and insert the new statement. It's okay 01837 to delete an old statement and fail to insert the new one. 01838 01839 POSTCONDITIONS 01840 All named prepared statements are also present in names_hash. 01841 Statement names in names_hash are unique. 01842 The statement is added only if prepared_stmt_count < max_prepard_stmt_count 01843 last_found_statement always points to a valid statement or is 0 01844 01845 RETURN VALUE 01846 0 success 01847 1 error: out of resources or max_prepared_stmt_count limit has been 01848 reached. An error is sent to the client, the statement is deleted. 01849 */ 01850 01851 int Statement_map::insert(THD *thd, Statement *statement) 01852 { 01853 if (my_hash_insert(&st_hash, (byte*) statement)) 01854 { 01855 /* 01856 Delete is needed only in case of an insert failure. In all other 01857 cases hash_delete will also delete the statement. 01858 */ 01859 delete statement; 01860 my_error(ER_OUT_OF_RESOURCES, MYF(0)); 01861 goto err_st_hash; 01862 } 01863 if (statement->name.str && my_hash_insert(&names_hash, (byte*) statement)) 01864 { 01865 my_error(ER_OUT_OF_RESOURCES, MYF(0)); 01866 goto err_names_hash; 01867 } 01868 pthread_mutex_lock(&LOCK_prepared_stmt_count); 01869 /* 01870 We don't check that prepared_stmt_count is <= max_prepared_stmt_count 01871 because we would like to allow to lower the total limit 01872 of prepared statements below the current count. In that case 01873 no new statements can be added until prepared_stmt_count drops below 01874 the limit. 01875 */ 01876 if (prepared_stmt_count >= max_prepared_stmt_count) 01877 { 01878 pthread_mutex_unlock(&LOCK_prepared_stmt_count); 01879 my_error(ER_MAX_PREPARED_STMT_COUNT_REACHED, MYF(0), 01880 max_prepared_stmt_count); 01881 goto err_max; 01882 } 01883 prepared_stmt_count++; 01884 pthread_mutex_unlock(&LOCK_prepared_stmt_count); 01885 01886 last_found_statement= statement; 01887 return 0; 01888 01889 err_max: 01890 if (statement->name.str) 01891 hash_delete(&names_hash, (byte*) statement); 01892 err_names_hash: 01893 hash_delete(&st_hash, (byte*) statement); 01894 err_st_hash: 01895 return 1; 01896 } 01897 01898 01899 void Statement_map::close_transient_cursors() 01900 { 01901 #ifdef TO_BE_IMPLEMENTED 01902 Statement *stmt; 01903 while ((stmt= transient_cursor_list.head())) 01904 stmt->close_cursor(); /* deletes itself from the list */ 01905 #endif 01906 } 01907 01908 01909 void Statement_map::erase(Statement *statement) 01910 { 01911 if (statement == last_found_statement) 01912 last_found_statement= 0; 01913 if (statement->name.str) 01914 hash_delete(&names_hash, (byte *) statement); 01915 01916 hash_delete(&st_hash, (byte *) statement); 01917 pthread_mutex_lock(&LOCK_prepared_stmt_count); 01918 DBUG_ASSERT(prepared_stmt_count > 0); 01919 prepared_stmt_count--; 01920 pthread_mutex_unlock(&LOCK_prepared_stmt_count); 01921 } 01922 01923 01924 void Statement_map::reset() 01925 { 01926 /* Must be first, hash_free will reset st_hash.records */ 01927 pthread_mutex_lock(&LOCK_prepared_stmt_count); 01928 DBUG_ASSERT(prepared_stmt_count >= st_hash.records); 01929 prepared_stmt_count-= st_hash.records; 01930 pthread_mutex_unlock(&LOCK_prepared_stmt_count); 01931 01932 my_hash_reset(&names_hash); 01933 my_hash_reset(&st_hash); 01934 last_found_statement= 0; 01935 } 01936 01937 01938 Statement_map::~Statement_map() 01939 { 01940 /* Must go first, hash_free will reset st_hash.records */ 01941 pthread_mutex_lock(&LOCK_prepared_stmt_count); 01942 DBUG_ASSERT(prepared_stmt_count >= st_hash.records); 01943 prepared_stmt_count-= st_hash.records; 01944 pthread_mutex_unlock(&LOCK_prepared_stmt_count); 01945 01946 hash_free(&names_hash); 01947 hash_free(&st_hash); 01948 } 01949 01950 bool select_dumpvar::send_data(List<Item> &items) 01951 { 01952 List_iterator_fast<Item_func_set_user_var> li(vars); 01953 List_iterator_fast<Item_splocal> var_li(local_vars); 01954 List_iterator_fast<my_var> my_li(var_list); 01955 List_iterator<Item> it(items); 01956 Item_func_set_user_var *xx; 01957 Item_splocal *yy; 01958 my_var *zz; 01959 DBUG_ENTER("select_dumpvar::send_data"); 01960 01961 if (unit->offset_limit_cnt) 01962 { // using limit offset,count 01963 unit->offset_limit_cnt--; 01964 DBUG_RETURN(0); 01965 } 01966 if (row_count++) 01967 { 01968 my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0)); 01969 DBUG_RETURN(1); 01970 } 01971 while ((zz=my_li++) && (it++)) 01972 { 01973 if (zz->local) 01974 { 01975 if ((yy=var_li++)) 01976 { 01977 if (thd->spcont->set_variable(current_thd, yy->get_var_idx(), 01978 it.ref())) 01979 DBUG_RETURN(1); 01980 } 01981 } 01982 else 01983 { 01984 if ((xx=li++)) 01985 { 01986 xx->check(); 01987 xx->update(); 01988 } 01989 } 01990 } 01991 DBUG_RETURN(0); 01992 } 01993 01994 bool select_dumpvar::send_eof() 01995 { 01996 if (! row_count) 01997 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 01998 ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA)); 01999 ::send_ok(thd,row_count); 02000 return 0; 02001 } 02002 02003 /**************************************************************************** 02004 TMP_TABLE_PARAM 02005 ****************************************************************************/ 02006 02007 void TMP_TABLE_PARAM::init() 02008 { 02009 DBUG_ENTER("TMP_TABLE_PARAM::init"); 02010 DBUG_PRINT("enter", ("this: 0x%lx", (ulong)this)); 02011 field_count= sum_func_count= func_count= hidden_field_count= 0; 02012 group_parts= group_length= group_null_parts= 0; 02013 quick_group= 1; 02014 table_charset= 0; 02015 precomputed_group_by= 0; 02016 DBUG_VOID_RETURN; 02017 } 02018 02019 02020 void thd_increment_bytes_sent(ulong length) 02021 { 02022 THD *thd=current_thd; 02023 if (likely(thd != 0)) 02024 { /* current_thd==0 when close_connection() calls net_send_error() */ 02025 thd->status_var.bytes_sent+= length; 02026 } 02027 } 02028 02029 02030 void thd_increment_bytes_received(ulong length) 02031 { 02032 current_thd->status_var.bytes_received+= length; 02033 } 02034 02035 02036 void thd_increment_net_big_packet_count(ulong length) 02037 { 02038 current_thd->status_var.net_big_packet_count+= length; 02039 } 02040 02041 02042 void THD::set_status_var_init() 02043 { 02044 bzero((char*) &status_var, sizeof(status_var)); 02045 } 02046 02047 02048 void Security_context::init() 02049 { 02050 host= user= priv_user= ip= 0; 02051 host_or_ip= "connecting host"; 02052 priv_host[0]= '\0'; 02053 #ifndef NO_EMBEDDED_ACCESS_CHECKS 02054 db_access= NO_ACCESS; 02055 #endif 02056 } 02057 02058 02059 void Security_context::destroy() 02060 { 02061 // If not pointer to constant 02062 if (host != my_localhost) 02063 safeFree(host); 02064 if (user != delayed_user) 02065 safeFree(user); 02066 safeFree(ip); 02067 } 02068 02069 02070 void Security_context::skip_grants() 02071 { 02072 /* privileges for the user are unknown everything is allowed */ 02073 host_or_ip= (char *)""; 02074 master_access= ~NO_ACCESS; 02075 priv_user= (char *)""; 02076 *priv_host= '\0'; 02077 } 02078 02079 02080 bool Security_context::set_user(char *user_arg) 02081 { 02082 safeFree(user); 02083 user= my_strdup(user_arg, MYF(0)); 02084 return user == 0; 02085 } 02086 02087 /**************************************************************************** 02088 Handling of open and locked tables states. 02089 02090 This is used when we want to open/lock (and then close) some tables when 02091 we already have a set of tables open and locked. We use these methods for 02092 access to mysql.proc table to find definitions of stored routines. 02093 ****************************************************************************/ 02094 02095 void THD::reset_n_backup_open_tables_state(Open_tables_state *backup) 02096 { 02097 DBUG_ENTER("reset_n_backup_open_tables_state"); 02098 backup->set_open_tables_state(this); 02099 reset_open_tables_state(); 02100 state_flags|= Open_tables_state::BACKUPS_AVAIL; 02101 DBUG_VOID_RETURN; 02102 } 02103 02104 02105 void THD::restore_backup_open_tables_state(Open_tables_state *backup) 02106 { 02107 DBUG_ENTER("restore_backup_open_tables_state"); 02108 /* 02109 Before we will throw away current open tables state we want 02110 to be sure that it was properly cleaned up. 02111 */ 02112 DBUG_ASSERT(open_tables == 0 && temporary_tables == 0 && 02113 handler_tables == 0 && derived_tables == 0 && 02114 lock == 0 && locked_tables == 0 && 02115 prelocked_mode == NON_PRELOCKED); 02116 set_open_tables_state(backup); 02117 DBUG_VOID_RETURN; 02118 } 02119 02120 02121 02122 /**************************************************************************** 02123 Handling of statement states in functions and triggers. 02124 02125 This is used to ensure that the function/trigger gets a clean state 02126 to work with and does not cause any side effects of the calling statement. 02127 02128 It also allows most stored functions and triggers to replicate even 02129 if they are used items that would normally be stored in the binary 02130 replication (like last_insert_id() etc...) 02131 02132 The following things is done 02133 - Disable binary logging for the duration of the statement 02134 - Disable multi-result-sets for the duration of the statement 02135 - Value of last_insert_id() is saved and restored 02136 - Value set by 'SET INSERT_ID=#' is reset and restored 02137 - Value for found_rows() is reset and restored 02138 - examined_row_count is added to the total 02139 - cuted_fields is added to the total 02140 - new savepoint level is created and destroyed 02141 02142 NOTES: 02143 Seed for random() is saved for the first! usage of RAND() 02144 We reset examined_row_count and cuted_fields and add these to the 02145 result to ensure that if we have a bug that would reset these within 02146 a function, we are not loosing any rows from the main statement. 02147 02148 We do not reset value of last_insert_id(). 02149 ****************************************************************************/ 02150 02151 void THD::reset_sub_statement_state(Sub_statement_state *backup, 02152 uint new_state) 02153 { 02154 backup->options= options; 02155 backup->in_sub_stmt= in_sub_stmt; 02156 backup->no_send_ok= net.no_send_ok; 02157 backup->enable_slow_log= enable_slow_log; 02158 backup->limit_found_rows= limit_found_rows; 02159 backup->examined_row_count= examined_row_count; 02160 backup->sent_row_count= sent_row_count; 02161 backup->cuted_fields= cuted_fields; 02162 backup->client_capabilities= client_capabilities; 02163 backup->savepoints= transaction.savepoints; 02164 backup->first_successful_insert_id_in_prev_stmt= 02165 first_successful_insert_id_in_prev_stmt; 02166 backup->first_successful_insert_id_in_cur_stmt= 02167 first_successful_insert_id_in_cur_stmt; 02168 02169 if ((!lex->requires_prelocking() || is_update_query(lex->sql_command)) && 02170 !current_stmt_binlog_row_based) 02171 { 02172 options&= ~OPTION_BIN_LOG; 02173 } 02174 /* Disable result sets */ 02175 client_capabilities &= ~CLIENT_MULTI_RESULTS; 02176 in_sub_stmt|= new_state; 02177 examined_row_count= 0; 02178 sent_row_count= 0; 02179 cuted_fields= 0; 02180 transaction.savepoints= 0; 02181 first_successful_insert_id_in_cur_stmt= 0; 02182 02183 /* Surpress OK packets in case if we will execute statements */ 02184 net.no_send_ok= TRUE; 02185 } 02186 02187 02188 void THD::restore_sub_statement_state(Sub_statement_state *backup) 02189 { 02190 /* 02191 To save resources we want to release savepoints which were created 02192 during execution of function or trigger before leaving their savepoint 02193 level. It is enough to release first savepoint set on this level since 02194 all later savepoints will be released automatically. 02195 */ 02196 if (transaction.savepoints) 02197 { 02198 SAVEPOINT *sv; 02199 for (sv= transaction.savepoints; sv->prev; sv= sv->prev) 02200 {} 02201 /* ha_release_savepoint() never returns error. */ 02202 (void)ha_release_savepoint(this, sv); 02203 } 02204 transaction.savepoints= backup->savepoints; 02205 options= backup->options; 02206 in_sub_stmt= backup->in_sub_stmt; 02207 net.no_send_ok= backup->no_send_ok; 02208 enable_slow_log= backup->enable_slow_log; 02209 first_successful_insert_id_in_prev_stmt= 02210 backup->first_successful_insert_id_in_prev_stmt; 02211 first_successful_insert_id_in_cur_stmt= 02212 backup->first_successful_insert_id_in_cur_stmt; 02213 limit_found_rows= backup->limit_found_rows; 02214 sent_row_count= backup->sent_row_count; 02215 client_capabilities= backup->client_capabilities; 02216 02217 /* 02218 The following is added to the old values as we are interested in the 02219 total complexity of the query 02220 */ 02221 examined_row_count+= backup->examined_row_count; 02222 cuted_fields+= backup->cuted_fields; 02223 } 02224 02225 02226 /*************************************************************************** 02227 Handling of XA id cacheing 02228 ***************************************************************************/ 02229 02230 pthread_mutex_t LOCK_xid_cache; 02231 HASH xid_cache; 02232 02233 static byte *xid_get_hash_key(const byte *ptr,uint *length, 02234 my_bool not_used __attribute__((unused))) 02235 { 02236 *length=((XID_STATE*)ptr)->xid.key_length(); 02237 return ((XID_STATE*)ptr)->xid.key(); 02238 } 02239 02240 static void xid_free_hash (void *ptr) 02241 { 02242 if (!((XID_STATE*)ptr)->in_thd) 02243 my_free((gptr)ptr, MYF(0)); 02244 } 02245 02246 bool xid_cache_init() 02247 { 02248 pthread_mutex_init(&LOCK_xid_cache, MY_MUTEX_INIT_FAST); 02249 return hash_init(&xid_cache, &my_charset_bin, 100, 0, 0, 02250 xid_get_hash_key, xid_free_hash, 0) != 0; 02251 } 02252 02253 void xid_cache_free() 02254 { 02255 if (hash_inited(&xid_cache)) 02256 { 02257 hash_free(&xid_cache); 02258 pthread_mutex_destroy(&LOCK_xid_cache); 02259 } 02260 } 02261 02262 XID_STATE *xid_cache_search(XID *xid) 02263 { 02264 pthread_mutex_lock(&LOCK_xid_cache); 02265 XID_STATE *res=(XID_STATE *)hash_search(&xid_cache, xid->key(), xid->key_length()); 02266 pthread_mutex_unlock(&LOCK_xid_cache); 02267 return res; 02268 } 02269 02270 02271 bool xid_cache_insert(XID *xid, enum xa_states xa_state) 02272 { 02273 XID_STATE *xs; 02274 my_bool res; 02275 pthread_mutex_lock(&LOCK_xid_cache); 02276 if (hash_search(&xid_cache, xid->key(), xid->key_length())) 02277 res=0; 02278 else if (!(xs=(XID_STATE *)my_malloc(sizeof(*xs), MYF(MY_WME)))) 02279 res=1; 02280 else 02281 { 02282 xs->xa_state=xa_state; 02283 xs->xid.set(xid); 02284 xs->in_thd=0; 02285 res=my_hash_insert(&xid_cache, (byte*)xs); 02286 } 02287 pthread_mutex_unlock(&LOCK_xid_cache); 02288 return res; 02289 } 02290 02291 02292 bool xid_cache_insert(XID_STATE *xid_state) 02293 { 02294 pthread_mutex_lock(&LOCK_xid_cache); 02295 DBUG_ASSERT(hash_search(&xid_cache, xid_state->xid.key(), 02296 xid_state->xid.key_length())==0); 02297 my_bool res=my_hash_insert(&xid_cache, (byte*)xid_state); 02298 pthread_mutex_unlock(&LOCK_xid_cache); 02299 return res; 02300 } 02301 02302 02303 void xid_cache_delete(XID_STATE *xid_state) 02304 { 02305 pthread_mutex_lock(&LOCK_xid_cache); 02306 hash_delete(&xid_cache, (byte *)xid_state); 02307 pthread_mutex_unlock(&LOCK_xid_cache); 02308 } 02309 02310 /* 02311 Implementation of interface to write rows to the binary log through the 02312 thread. The thread is responsible for writing the rows it has 02313 inserted/updated/deleted. 02314 */ 02315 02316 #ifndef MYSQL_CLIENT 02317 #ifdef HAVE_ROW_BASED_REPLICATION 02318 02319 /* 02320 Template member function for ensuring that there is an rows log 02321 event of the apropriate type before proceeding. 02322 02323 PRE CONDITION: 02324 - Events of type 'RowEventT' have the type code 'type_code'. 02325 02326 POST CONDITION: 02327 If a non-NULL pointer is returned, the pending event for thread 'thd' will 02328 be an event of type 'RowEventT' (which have the type code 'type_code') 02329 will either empty or have enough space to hold 'needed' bytes. In 02330 addition, the columns bitmap will be correct for the row, meaning that 02331 the pending event will be flushed if the columns in the event differ from 02332 the columns suppled to the function. 02333 02334 RETURNS 02335 If no error, a non-NULL pending event (either one which already existed or 02336 the newly created one). 02337 If error, NULL. 02338 */ 02339 02340 template <class RowsEventT> Rows_log_event* 02341 THD::binlog_prepare_pending_rows_event(TABLE* table, uint32 serv_id, 02342 MY_BITMAP const* cols, 02343 my_size_t colcnt, 02344 my_size_t needed, 02345 bool is_transactional, 02346 RowsEventT *hint __attribute__((unused))) 02347 { 02348 DBUG_ENTER("binlog_prepare_pending_rows_event"); 02349 /* Pre-conditions */ 02350 DBUG_ASSERT(table->s->table_map_id != ~0UL); 02351 02352 /* Fetch the type code for the RowsEventT template parameter */ 02353 int const type_code= RowsEventT::TYPE_CODE; 02354 02355 /* 02356 There is no good place to set up the transactional data, so we 02357 have to do it here. 02358 */ 02359 if (binlog_setup_trx_data()) 02360 DBUG_RETURN(NULL); 02361 02362 Rows_log_event* pending= binlog_get_pending_rows_event(); 02363 02364 if (unlikely(pending && !pending->is_valid())) 02365 DBUG_RETURN(NULL); 02366 02367 /* 02368 Check if the current event is non-NULL and a write-rows 02369 event. Also check if the table provided is mapped: if it is not, 02370 then we have switched to writing to a new table. 02371 If there is no pending event, we need to create one. If there is a pending 02372 event, but it's not about the same table id, or not of the same type 02373 (between Write, Update and Delete), or not the same affected columns, or 02374 going to be too big, flush this event to disk and create a new pending 02375 event. 02376 */ 02377 if (!pending || 02378 pending->server_id != serv_id || 02379 pending->get_table_id() != table->s->table_map_id || 02380 pending->get_type_code() != type_code || 02381 pending->get_data_size() + needed > opt_binlog_rows_event_max_size || 02382 pending->get_width() != colcnt || 02383 !bitmap_cmp(pending->get_cols(), cols)) 02384 { 02385 /* Create a new RowsEventT... */ 02386 Rows_log_event* const 02387 ev= new RowsEventT(this, table, table->s->table_map_id, cols, 02388 is_transactional); 02389 if (unlikely(!ev)) 02390 DBUG_RETURN(NULL); 02391 ev->server_id= serv_id; // I don't like this, it's too easy to forget. 02392 /* 02393 flush the pending event and replace it with the newly created 02394 event... 02395 */ 02396 if (unlikely(mysql_bin_log.flush_and_set_pending_rows_event(this, ev))) 02397 { 02398 delete ev; 02399 DBUG_RETURN(NULL); 02400 } 02401 02402 DBUG_RETURN(ev); /* This is the new pending event */ 02403 } 02404 DBUG_RETURN(pending); /* This is the current pending event */ 02405 } 02406 02407 #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION 02408 /* 02409 Instantiate the versions we need, we have -fno-implicit-template as 02410 compiling option. 02411 */ 02412 template Rows_log_event* 02413 THD::binlog_prepare_pending_rows_event(TABLE*, uint32, MY_BITMAP const*, 02414 my_size_t, my_size_t, bool, 02415 Write_rows_log_event*); 02416 02417 template Rows_log_event* 02418 THD::binlog_prepare_pending_rows_event(TABLE*, uint32, MY_BITMAP const*, 02419 my_size_t colcnt, my_size_t, bool, 02420 Delete_rows_log_event *); 02421 02422 template Rows_log_event* 02423 THD::binlog_prepare_pending_rows_event(TABLE*, uint32, MY_BITMAP const*, 02424 my_size_t colcnt, my_size_t, bool, 02425 Update_rows_log_event *); 02426 #endif 02427 static char const* 02428 field_type_name(enum_field_types type) 02429 { 02430 switch (type) 02431 { 02432 case MYSQL_TYPE_DECIMAL: 02433 return "MYSQL_TYPE_DECIMAL"; 02434 case MYSQL_TYPE_TINY: 02435 return "MYSQL_TYPE_TINY"; 02436 case MYSQL_TYPE_SHORT: 02437 return "MYSQL_TYPE_SHORT"; 02438 case MYSQL_TYPE_LONG: 02439 return "MYSQL_TYPE_LONG"; 02440 case MYSQL_TYPE_FLOAT: 02441 return "MYSQL_TYPE_FLOAT"; 02442 case MYSQL_TYPE_DOUBLE: 02443 return "MYSQL_TYPE_DOUBLE"; 02444 case MYSQL_TYPE_NULL: 02445 return "MYSQL_TYPE_NULL"; 02446 case MYSQL_TYPE_TIMESTAMP: 02447 return "MYSQL_TYPE_TIMESTAMP"; 02448 case MYSQL_TYPE_LONGLONG: 02449 return "MYSQL_TYPE_LONGLONG"; 02450 case MYSQL_TYPE_INT24: 02451 return "MYSQL_TYPE_INT24"; 02452 case MYSQL_TYPE_DATE: 02453 return "MYSQL_TYPE_DATE"; 02454 case MYSQL_TYPE_TIME: 02455 return "MYSQL_TYPE_TIME"; 02456 case MYSQL_TYPE_DATETIME: 02457 return "MYSQL_TYPE_DATETIME"; 02458 case MYSQL_TYPE_YEAR: 02459 return "MYSQL_TYPE_YEAR"; 02460 case MYSQL_TYPE_NEWDATE: 02461 return "MYSQL_TYPE_NEWDATE"; 02462 case MYSQL_TYPE_VARCHAR: 02463 return "MYSQL_TYPE_VARCHAR"; 02464 case MYSQL_TYPE_BIT: 02465 return "MYSQL_TYPE_BIT"; 02466 case MYSQL_TYPE_NEWDECIMAL: 02467 return "MYSQL_TYPE_NEWDECIMAL"; 02468 case MYSQL_TYPE_ENUM: 02469 return "MYSQL_TYPE_ENUM"; 02470 case MYSQL_TYPE_SET: 02471 return "MYSQL_TYPE_SET"; 02472 case MYSQL_TYPE_TINY_BLOB: 02473 return "MYSQL_TYPE_TINY_BLOB"; 02474 case MYSQL_TYPE_MEDIUM_BLOB: 02475 return "MYSQL_TYPE_MEDIUM_BLOB"; 02476 case MYSQL_TYPE_LONG_BLOB: 02477 return "MYSQL_TYPE_LONG_BLOB"; 02478 case MYSQL_TYPE_BLOB: 02479 return "MYSQL_TYPE_BLOB"; 02480 case MYSQL_TYPE_VAR_STRING: 02481 return "MYSQL_TYPE_VAR_STRING"; 02482 case MYSQL_TYPE_STRING: 02483 return "MYSQL_TYPE_STRING"; 02484 case MYSQL_TYPE_GEOMETRY: 02485 return "MYSQL_TYPE_GEOMETRY"; 02486 } 02487 return "Unknown"; 02488 } 02489 02490 02491 my_size_t THD::max_row_length_blob(TABLE *table, const byte *data) const 02492 { 02493 my_size_t length= 0; 02494 TABLE_SHARE *table_s= table->s; 02495 uint* const beg= table_s->blob_field; 02496 uint* const end= beg + table_s->blob_fields; 02497 02498 for (uint *ptr= beg ; ptr != end ; ++ptr) 02499 { 02500 Field_blob* const blob= (Field_blob*) table->field[*ptr]; 02501 length+= blob->get_length((const char *) (data + blob->offset())) + 2; 02502 } 02503 02504 return length; 02505 } 02506 02507 02508 my_size_t THD::pack_row(TABLE *table, MY_BITMAP const* cols, byte *row_data, 02509 const byte *record) const 02510 { 02511 Field **p_field= table->field, *field; 02512 int n_null_bytes= table->s->null_bytes; 02513 byte *ptr; 02514 uint i; 02515 my_ptrdiff_t const rec_offset= record - table->record[0]; 02516 my_ptrdiff_t const def_offset= table->s->default_values - table->record[0]; 02517 memcpy(row_data, record, n_null_bytes); 02518 ptr= row_data+n_null_bytes; 02519 02520 for (i= 0 ; (field= *p_field) ; i++, p_field++) 02521 { 02522 if (bitmap_is_set(cols,i)) 02523 { 02524 my_ptrdiff_t const offset= 02525 field->is_null(rec_offset) ? def_offset : rec_offset; 02526 ptr= (byte*)field->pack((char *) ptr, field->ptr + offset); 02527 } 02528 } 02529 return (static_cast<my_size_t>(ptr - row_data)); 02530 } 02531 02532 02533 int THD::binlog_write_row(TABLE* table, bool is_trans, 02534 MY_BITMAP const* cols, my_size_t colcnt, 02535 byte const *record) 02536 { 02537 DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open()); 02538 02539 /* 02540 Pack records into format for transfer. We are allocating more 02541 memory than needed, but that doesn't matter. 02542 */ 02543 bool error= 0; 02544 byte *row_data= table->write_row_record; 02545 my_size_t const max_len= max_row_length(table, record); 02546 my_size_t len; 02547 Rows_log_event *ev; 02548 02549 /* Allocate room for a row (if needed) */ 02550 if (!row_data) 02551 { 02552 if (!table->s->blob_fields) 02553 { 02554 /* multiply max_len by 2 so it can be used for update_row as well */ 02555 table->write_row_record= (byte *) alloc_root(&table->mem_root, 02556 2*max_len); 02557 if (!table->write_row_record) 02558 return HA_ERR_OUT_OF_MEM; 02559 row_data= table->write_row_record; 02560 } 02561 else if (unlikely(!(row_data= (byte *) my_malloc(max_len, MYF(MY_WME))))) 02562 return HA_ERR_OUT_OF_MEM; 02563 } 02564 len= pack_row(table, cols, row_data, record); 02565 02566 ev= binlog_prepare_pending_rows_event(table, server_id, cols, colcnt, 02567 len, is_trans, 02568 static_cast<Write_rows_log_event*>(0)); 02569 02570 /* add_row_data copies row_data to internal buffer */ 02571 error= likely(ev != 0) ? ev->add_row_data(row_data,len) : HA_ERR_OUT_OF_MEM ; 02572 02573 if (table->write_row_record == 0) 02574 my_free((gptr) row_data, MYF(MY_WME)); 02575 02576 return error; 02577 } 02578 02579 int THD::binlog_update_row(TABLE* table, bool is_trans, 02580 MY_BITMAP const* cols, my_size_t colcnt, 02581 const byte *before_record, 02582 const byte *after_record) 02583 { 02584 DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open()); 02585 02586 bool error= 0; 02587 my_size_t const before_maxlen = max_row_length(table, before_record); 02588 my_size_t const after_maxlen = max_row_length(table, after_record); 02589 02590 byte *row_data= table->write_row_record; 02591 byte *before_row, *after_row; 02592 if (row_data != 0) 02593 { 02594 before_row= row_data; 02595 after_row= before_row + before_maxlen; 02596 } 02597 else 02598 { 02599 if (unlikely(!(row_data= (byte*)my_multi_malloc(MYF(MY_WME), 02600 &before_row, before_maxlen, 02601 &after_row, after_maxlen, 02602 NULL)))) 02603 return HA_ERR_OUT_OF_MEM; 02604 } 02605 02606 my_size_t const before_size= pack_row(table, cols, before_row, 02607 before_record); 02608 my_size_t const after_size= pack_row(table, cols, after_row, 02609 after_record); 02610 02611 Rows_log_event* const ev= 02612 binlog_prepare_pending_rows_event(table, server_id, cols, colcnt, 02613 before_size + after_size, is_trans, 02614 static_cast<Update_rows_log_event*>(0)); 02615 02616 error= (unlikely(!ev)) || ev->add_row_data(before_row, before_size) || 02617 ev->add_row_data(after_row, after_size); 02618 02619 if (!table->write_row_record) 02620 { 02621 /* add_row_data copies row_data to internal buffer */ 02622 my_free((gptr)row_data, MYF(MY_WME)); 02623 } 02624 02625 return error; 02626 } 02627 02628 int THD::binlog_delete_row(TABLE* table, bool is_trans, 02629 MY_BITMAP const* cols, my_size_t colcnt, 02630 byte const *record) 02631 { 02632 DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open()); 02633 02634 /* 02635 Pack records into format for transfer. We are allocating more 02636 memory than needed, but that doesn't matter. 02637 */ 02638 bool error= 0; 02639 my_size_t const max_len= max_row_length(table, record); 02640 byte *row_data= table->write_row_record; 02641 if (!row_data && unlikely(!(row_data= (byte*)my_malloc(max_len, MYF(MY_WME))))) 02642 return HA_ERR_OUT_OF_MEM; 02643 my_size_t const len= pack_row(table, cols, row_data, record); 02644 02645 Rows_log_event* const ev= 02646 binlog_prepare_pending_rows_event(table, server_id, cols, colcnt, 02647 len, is_trans, 02648 static_cast<Delete_rows_log_event*>(0)); 02649 02650 error= (unlikely(!ev)) || ev->add_row_data(row_data, len); 02651 02652 /* add_row_data copies row_data */ 02653 if (table->write_row_record == 0) 02654 my_free((gptr)row_data, MYF(MY_WME)); 02655 02656 return error; 02657 } 02658 02659 02660 int THD::binlog_flush_pending_rows_event(bool stmt_end) 02661 { 02662 DBUG_ENTER("THD::binlog_flush_pending_rows_event"); 02663 if (!current_stmt_binlog_row_based || !mysql_bin_log.is_open()) 02664 DBUG_RETURN(0); 02665 02666 /* 02667 Mark the event as the last event of a statement if the stmt_end 02668 flag is set. 02669 */ 02670 int error= 0; 02671 if (Rows_log_event *pending= binlog_get_pending_rows_event()) 02672 { 02673 if (stmt_end) 02674 { 02675 pending->set_flags(Rows_log_event::STMT_END_F); 02676 pending->flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F; 02677 binlog_table_maps= 0; 02678 } 02679 02680 error= mysql_bin_log.flush_and_set_pending_rows_event(this, 0); 02681 } 02682 02683 DBUG_RETURN(error); 02684 } 02685 02686 02687 void THD::binlog_delete_pending_rows_event() 02688 { 02689 if (Rows_log_event *pending= binlog_get_pending_rows_event()) 02690 { 02691 delete pending; 02692 binlog_set_pending_rows_event(0); 02693 } 02694 } 02695 02696 #endif /* HAVE_ROW_BASED_REPLICATION */ 02697 02698 /* 02699 Member function that will log query, either row-based or 02700 statement-based depending on the value of the 'current_stmt_binlog_row_based' 02701 the value of the 'qtype' flag. 02702 02703 This function should be called after the all calls to ha_*_row() 02704 functions have been issued, but before tables are unlocked and 02705 closed. 02706 02707 OBSERVE 02708 There shall be no writes to any system table after calling 02709 binlog_query(), so these writes has to be moved to before the call 02710 of binlog_query() for correct functioning. 02711 02712 This is necessesary not only for RBR, but the master might crash 02713 after binlogging the query but before changing the system tables. 02714 This means that the slave and the master are not in the same state 02715 (after the master has restarted), so therefore we have to 02716 eliminate this problem. 02717 02718 RETURN VALUE 02719 Error code, or 0 if no error. 02720 */ 02721 int THD::binlog_query(THD::enum_binlog_query_type qtype, 02722 char const *query, ulong query_len, 02723 bool is_trans, bool suppress_use) 02724 { 02725 DBUG_ENTER("THD::binlog_query"); 02726 DBUG_PRINT("enter", ("qtype=%d, query='%s'", qtype, query)); 02727 DBUG_ASSERT(query && mysql_bin_log.is_open()); 02728 02729 switch (qtype) { 02730 case THD::MYSQL_QUERY_TYPE: 02731 /* 02732 Using this query type is a conveniece hack, since we have been 02733 moving back and forth between using RBR for replication of 02734 system tables and not using it. 02735 02736 Make sure to change in check_table_binlog_row_based() according 02737 to how you treat this. 02738 */ 02739 case THD::ROW_QUERY_TYPE: 02740 #ifdef HAVE_ROW_BASED_REPLICATION 02741 if (current_stmt_binlog_row_based) 02742 { 02743 /* 02744 If thd->lock is set, then we are not inside a stored function. 02745 In that case, mysql_unlock_tables() will be called after this 02746 binlog_query(), so we have to flush the pending rows event 02747 with the STMT_END_F set to unlock all tables at the slave side 02748 as well. 02749 02750 We will not flush the pending event, if thd->lock is NULL. 02751 This means that we are inside a stored function or trigger, so 02752 the flushing will be done inside the top-most 02753 close_thread_tables(). 02754 */ 02755 #ifdef HAVE_ROW_BASED_REPLICATION 02756 if (this->lock) 02757 DBUG_RETURN(binlog_flush_pending_rows_event(TRUE)); 02758 #endif /*HAVE_ROW_BASED_REPLICATION*/ 02759 DBUG_RETURN(0); 02760 } 02761 #endif 02762 /* Otherwise, we fall through */ 02763 case THD::STMT_QUERY_TYPE: 02764 /* 02765 The MYSQL_LOG::write() function will set the STMT_END_F flag and 02766 flush the pending rows event if necessary. 02767 */ 02768 { 02769 Query_log_event qinfo(this, query, query_len, is_trans, suppress_use); 02770 #ifdef HAVE_ROW_BASED_REPLICATION 02771 qinfo.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F; 02772 #endif 02773 /* 02774 Binlog table maps will be irrelevant after a Query_log_event 02775 (they are just removed on the slave side) so after the query 02776 log event is written to the binary log, we pretend that no 02777 table maps were written. 02778 */ 02779 int error= mysql_bin_log.write(&qinfo); 02780 #ifdef HAVE_ROW_BASED_REPLICATION 02781 binlog_table_maps= 0; 02782 #endif /*HAVE_ROW_BASED_REPLICATION*/ 02783 DBUG_RETURN(error); 02784 } 02785 break; 02786 02787 case THD::QUERY_TYPE_COUNT: 02788 default: 02789 DBUG_ASSERT(0 <= qtype && qtype < QUERY_TYPE_COUNT); 02790 } 02791 DBUG_RETURN(0); 02792 } 02793 02794 bool Discrete_intervals_list::append(ulonglong start, ulonglong val, 02795 ulonglong incr) 02796 { 02797 DBUG_ENTER("Discrete_intervals_list::append"); 02798 /* first, see if this can be merged with previous */ 02799 if ((head == NULL) || tail->merge_if_contiguous(start, val, incr)) 02800 { 02801 /* it cannot, so need to add a new interval */ 02802 Discrete_interval *new_interval= new Discrete_interval(start, val, incr); 02803 if (unlikely(new_interval == NULL)) // out of memory 02804 DBUG_RETURN(1); 02805 DBUG_PRINT("info",("adding new auto_increment interval")); 02806 if (head == NULL) 02807 head= current= new_interval; 02808 else 02809 tail->next= new_interval; 02810 tail= new_interval; 02811 elements++; 02812 } 02813 DBUG_RETURN(0); 02814 } 02815 02816 #endif /* !defined(MYSQL_CLIENT) */
1.4.7

