diff options
Diffstat (limited to 'sql')
147 files changed, 19806 insertions, 23390 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 15c2d950ff9..99b1a3dc206 100755..100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -53,7 +53,7 @@ SET (SQL_SOURCE log_event.cc rpl_record.cc rpl_reporting.cc log_event_old.cc rpl_record_old.cc message.h mf_iocache.cc my_decimal.cc ../sql-common/my_time.c - mysqld.cc net_serv.cc + mysqld.cc net_serv.cc keycaches.cc nt_servc.cc nt_servc.h opt_range.cc opt_range.h opt_sum.cc ../sql-common/pack.c parse_file.cc password.c procedure.cc protocol.cc records.cc repl_failsafe.cc rpl_filter.cc set_var.cc @@ -73,10 +73,10 @@ SET (SQL_SOURCE event_queue.cc event_db_repository.cc sql_tablespace.cc events.cc ../sql-common/my_user.c partition_info.cc rpl_utility.cc rpl_injector.cc sql_locale.cc - rpl_rli.cc rpl_mi.cc sql_servers.cc + rpl_rli.cc rpl_mi.cc sql_servers.cc sql_audit.cc sql_connect.cc scheduler.cc sql_profile.cc event_parse_data.cc - sql_signal.cc rpl_handler.cc + sql_signal.cc rpl_handler.cc sys_vars.cc ${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc ${PROJECT_SOURCE_DIR}/sql/sql_yacc.h ${PROJECT_SOURCE_DIR}/include/mysqld_error.h diff --git a/sql/Makefile.am b/sql/Makefile.am index 15ee0d588c4..e22de4931db 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -101,9 +101,9 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ sql_repl.h slave.h rpl_filter.h rpl_injector.h \ log_event.h rpl_record.h \ log_event_old.h rpl_record_old.h \ - sql_sort.h sql_cache.h set_var.h \ + sql_sort.h sql_cache.h set_var.h sys_vars_shared.h \ spatial.h gstream.h client_settings.h tzfile.h \ - tztime.h my_decimal.h\ + tztime.h my_decimal.h keycaches.h \ sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \ parse_file.h sql_view.h sql_trigger.h \ sql_array.h sql_cursor.h events.h scheduler.h \ @@ -111,8 +111,9 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ sql_plugin.h authors.h event_parse_data.h \ event_data_objects.h event_scheduler.h \ sql_partition.h partition_info.h partition_element.h \ + sql_audit.h \ contributors.h sql_servers.h sql_signal.h records.h \ - sql_prepare.h rpl_handler.h replication.h + sql_prepare.h rpl_handler.h replication.h sys_vars.h mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \ item.cc item_sum.cc item_buff.cc item_func.cc \ @@ -125,7 +126,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \ sql_string.cc sql_manager.cc sql_map.cc \ mysqld.cc password.c hash_filo.cc hostname.cc \ sql_connect.cc scheduler.cc sql_parse.cc \ - set_var.cc sql_yacc.yy \ + keycaches.cc set_var.cc sql_yacc.yy sys_vars.cc \ sql_base.cc table.cc sql_select.cc sql_insert.cc \ sql_profile.cc \ sql_prepare.cc sql_error.cc sql_locale.cc \ @@ -157,7 +158,8 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \ event_queue.cc event_db_repository.cc events.cc \ sql_plugin.cc sql_binlog.cc \ sql_builtin.cc sql_tablespace.cc partition_info.cc \ - sql_servers.cc event_parse_data.cc sql_signal.cc \ + sql_servers.cc sql_audit.cc \ + event_parse_data.cc sql_signal.cc \ rpl_handler.cc nodist_mysqld_SOURCES = mini_client_errors.c pack.c client.c my_time.c my_user.c diff --git a/sql/authors.h b/sql/authors.h index ec46e368f5f..555fe2ae43a 100644 --- a/sql/authors.h +++ b/sql/authors.h @@ -39,7 +39,7 @@ struct show_table_authors_st { struct show_table_authors_st show_table_authors[]= { { "Brian (Krow) Aker", "Seattle, WA, USA", "Architecture, archive, federated, bunch of little stuff :)" }, - { "Marc Alff", "Denver, CO, USA", "Signal, Resignal" }, + { "Marc Alff", "Denver, CO, USA", "Signal, Resignal, Performance schema" }, { "Venu Anuganti", "", "Client/server protocol (4.1)" }, { "David Axmark", "Uppsala, Sweden", "Small stuff long time ago, Monty ripped it out!" }, diff --git a/sql/client_settings.h b/sql/client_settings.h index fd50bfdbb88..7d103d5904d 100644 --- a/sql/client_settings.h +++ b/sql/client_settings.h @@ -30,10 +30,6 @@ #define set_sigpipe(mysql) #define reset_sigpipe(mysql) #define read_user_name(A) {} -#define mysql_rpl_query_type(A,B) MYSQL_RPL_ADMIN -#define mysql_master_send_query(A, B, C) 1 -#define mysql_slave_send_query(A, B, C) 1 -#define mysql_rpl_probe(mysql) 0 #undef HAVE_SMEM #undef _CUSTOMCONFIG_ diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc index 81870e6b7a3..517aab93707 100644 --- a/sql/debug_sync.cc +++ b/sql/debug_sync.cc @@ -221,14 +221,14 @@ There are quite a few places in MySQL, where we use a synchronization pattern like this: - pthread_mutex_lock(&mutex); + mysql_mutex_lock(&mutex); thd->enter_cond(&condition_variable, &mutex, new_message); #if defined(ENABLE_DEBUG_SYNC) if (!thd->killed && !end_of_wait_condition) DEBUG_SYNC(thd, "sync_point_name"); #endif while (!thd->killed && !end_of_wait_condition) - pthread_cond_wait(&condition_variable, &mutex); + mysql_cond_wait(&condition_variable, &mutex); thd->exit_cond(old_message); Here some explanations: @@ -264,12 +264,12 @@ while (!thd->killed && !end_of_wait_condition) { - pthread_mutex_lock(&mutex); + mysql_mutex_lock(&mutex); thd->enter_cond(&condition_variable, &mutex, new_message); if (!thd->killed [&& !end_of_wait_condition]) { [DEBUG_SYNC(thd, "sync_point_name");] - pthread_cond_wait(&condition_variable, &mutex); + mysql_cond_wait(&condition_variable, &mutex); } thd->exit_cond(old_message); } @@ -285,7 +285,7 @@ before sleeping, we hold the mutex, which is registered in mysys_var. The killing thread would try to acquire the mutex before signaling the condition variable. Since the mutex is only released implicitly in - pthread_cond_wait(), the signaling happens at the right place. We + mysql_cond_wait(), the signaling happens at the right place. We have a safe synchronization. === Co-work with the DBUG facility === @@ -373,8 +373,8 @@ struct st_debug_sync_control struct st_debug_sync_globals { String ds_signal; /* signal variable */ - pthread_cond_t ds_cond; /* condition variable */ - pthread_mutex_t ds_mutex; /* mutex variable */ + mysql_cond_t ds_cond; /* condition variable */ + mysql_mutex_t ds_mutex; /* mutex variable */ ulonglong dsp_hits; /* statistics */ ulonglong dsp_executed; /* statistics */ ulonglong dsp_max_active; /* statistics */ @@ -425,6 +425,37 @@ static void debug_sync_C_callback(const char *sync_point_name, debug_sync(current_thd, sync_point_name, name_len); } +#ifdef HAVE_PSI_INTERFACE +static PSI_mutex_key key_debug_sync_globals_ds_mutex; + +static PSI_mutex_info all_debug_sync_mutexes[]= +{ + { &key_debug_sync_globals_ds_mutex, "DEBUG_SYNC::mutex", PSI_FLAG_GLOBAL} +}; + +static PSI_cond_key key_debug_sync_globals_ds_cond; + +static PSI_cond_info all_debug_sync_conds[]= +{ + { &key_debug_sync_globals_ds_cond, "DEBUG_SYNC::cond", PSI_FLAG_GLOBAL} +}; + +static void init_debug_sync_psi_keys(void) +{ + const char* category= "sql"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_debug_sync_mutexes); + PSI_server->register_mutex(category, all_debug_sync_mutexes, count); + + count= array_elements(all_debug_sync_conds); + PSI_server->register_cond(category, all_debug_sync_conds, count); +} +#endif /* HAVE_PSI_INTERFACE */ + /** Initialize the debug sync facility at server start. @@ -438,15 +469,21 @@ int debug_sync_init(void) { DBUG_ENTER("debug_sync_init"); +#ifdef HAVE_PSI_INTERFACE + init_debug_sync_psi_keys(); +#endif + if (opt_debug_sync_timeout) { int rc; /* Initialize the global variables. */ debug_sync_global.ds_signal.length(0); - if ((rc= pthread_cond_init(&debug_sync_global.ds_cond, NULL)) || - (rc= pthread_mutex_init(&debug_sync_global.ds_mutex, - MY_MUTEX_INIT_FAST))) + if ((rc= mysql_cond_init(key_debug_sync_globals_ds_cond, + &debug_sync_global.ds_cond, NULL)) || + (rc= mysql_mutex_init(key_debug_sync_globals_ds_mutex, + &debug_sync_global.ds_mutex, + MY_MUTEX_INIT_FAST))) DBUG_RETURN(rc); /* purecov: inspected */ /* Set the call back pointer in C files. */ @@ -476,8 +513,8 @@ void debug_sync_end(void) /* Destroy the global variables. */ debug_sync_global.ds_signal.free(); - (void) pthread_cond_destroy(&debug_sync_global.ds_cond); - (void) pthread_mutex_destroy(&debug_sync_global.ds_mutex); + mysql_cond_destroy(&debug_sync_global.ds_cond); + mysql_mutex_destroy(&debug_sync_global.ds_mutex); /* Print statistics. */ { @@ -585,12 +622,12 @@ void debug_sync_end_thread(THD *thd) } /* Statistics. */ - pthread_mutex_lock(&debug_sync_global.ds_mutex); + mysql_mutex_lock(&debug_sync_global.ds_mutex); debug_sync_global.dsp_hits+= ds_control->dsp_hits; debug_sync_global.dsp_executed+= ds_control->dsp_executed; if (debug_sync_global.dsp_max_active < ds_control->dsp_max_active) debug_sync_global.dsp_max_active= ds_control->dsp_max_active; - pthread_mutex_unlock(&debug_sync_global.ds_mutex); + mysql_mutex_unlock(&debug_sync_global.ds_mutex); my_free(ds_control, MYF(0)); thd->debug_sync_control= NULL; @@ -824,9 +861,9 @@ static void debug_sync_reset(THD *thd) ds_control->ds_active= 0; /* Clear the global signal. */ - pthread_mutex_lock(&debug_sync_global.ds_mutex); + mysql_mutex_lock(&debug_sync_global.ds_mutex); debug_sync_global.ds_signal.length(0); - pthread_mutex_unlock(&debug_sync_global.ds_mutex); + mysql_mutex_unlock(&debug_sync_global.ds_mutex); DBUG_VOID_RETURN; } @@ -1524,56 +1561,6 @@ static bool debug_sync_eval_action(THD *thd, char *action_str) DBUG_RETURN(FALSE); } - -/** - Check if the system variable 'debug_sync' can be set. - - @param[in] thd thread handle - @param[in] var set variable request - - @return status - @retval FALSE ok, variable can be set - @retval TRUE error, variable cannot be set -*/ - -bool sys_var_debug_sync::check(THD *thd, set_var *var) -{ - DBUG_ENTER("sys_var_debug_sync::check"); - DBUG_ASSERT(thd); - DBUG_ASSERT(var); - - /* - Variable can be set for the session only. - - This could be changed later. Then we need to have a global array of - actions in addition to the thread local ones. SET GLOBAL would - manage the global array, SET [SESSION] the local array. A sync point - would need to look for a local and a global action. Setting and - executing of global actions need to be protected by a mutex. - - The purpose of global actions could be to allow synchronizing with - connectionless threads that cannot execute SET statements. - */ - if (var->type == OPT_GLOBAL) - { - my_error(ER_LOCAL_VARIABLE, MYF(0), name); - DBUG_RETURN(TRUE); - } - - /* - Do not check for disabled facility. Test result should not - unnecessarily differ from enabled facility. - */ - - /* - Facility requires SUPER privilege. Sync points could be inside - global mutexes (e.g. LOCK_open). Waiting there forever would - stall the whole server. - */ - DBUG_RETURN(check_global_access(thd, SUPER_ACL)); -} - - /** Set the system variable 'debug_sync'. @@ -1594,28 +1581,9 @@ bool sys_var_debug_sync::check(THD *thd, set_var *var) terminators in the string. So we need to take a copy here. */ -bool sys_var_debug_sync::update(THD *thd, set_var *var) +bool debug_sync_update(THD *thd, char *val_str) { - char *val_str; - String *val_ptr; - String val_buf; - DBUG_ENTER("sys_var_debug_sync::update"); - DBUG_ASSERT(thd); - - /* - Depending on the value type (string literal, user variable, ...) - val_buf receives a copy of the value or not. But we always need - a copy. So we take a copy, if it is not done by val_str(). - If val_str() puts a copy into val_buf, then it returns &val_buf, - otherwise it returns a pointer to the string object that we need - to copy. - */ - val_ptr= var ? var->value->val_str(&val_buf) : &val_buf; - if (val_ptr != &val_buf) - { - val_buf.copy(*val_ptr); - } - val_str= val_buf.c_ptr(); + DBUG_ENTER("debug_sync_update"); DBUG_PRINT("debug_sync", ("set action: '%s'", val_str)); /* @@ -1632,8 +1600,6 @@ bool sys_var_debug_sync::update(THD *thd, set_var *var) Retrieve the value of the system variable 'debug_sync'. @param[in] thd thread handle - @param[in] type variable type, unused - @param[in] base variable base, unused @return string @retval != NULL ok, string pointer @@ -1646,20 +1612,17 @@ bool sys_var_debug_sync::update(THD *thd, set_var *var) When "ON", the current signal is added. */ -uchar *sys_var_debug_sync::value_ptr(THD *thd, - enum_var_type type __attribute__((unused)), - LEX_STRING *base __attribute__((unused))) +uchar *debug_sync_value_ptr(THD *thd) { char *value; - DBUG_ENTER("sys_var_debug_sync::value_ptr"); - DBUG_ASSERT(thd); + DBUG_ENTER("debug_sync_value_ptr"); if (opt_debug_sync_timeout) { static char on[]= "ON - current signal: '"; // Ensure exclusive access to debug_sync_global.ds_signal - pthread_mutex_lock(&debug_sync_global.ds_mutex); + mysql_mutex_lock(&debug_sync_global.ds_mutex); size_t lgt= (sizeof(on) /* includes '\0' */ + debug_sync_global.ds_signal.length() + 1 /* for '\'' */); @@ -1676,12 +1639,12 @@ uchar *sys_var_debug_sync::value_ptr(THD *thd, *(vptr++)= '\''; *vptr= '\0'; /* We have one byte reserved for the worst case. */ } - pthread_mutex_unlock(&debug_sync_global.ds_mutex); + mysql_mutex_unlock(&debug_sync_global.ds_mutex); } else { /* purecov: begin tested */ - value= strmake_root(thd->mem_root, STRING_WITH_LEN("OFF")); + value= const_cast<char*>("OFF"); /* purecov: end */ } @@ -1744,7 +1707,7 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) read access too, to create a memory barrier in order to avoid that threads just reads an old cached version of the signal. */ - pthread_mutex_lock(&debug_sync_global.ds_mutex); + mysql_mutex_lock(&debug_sync_global.ds_mutex); if (action->signal.length()) { @@ -1758,15 +1721,15 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) debug_sync_emergency_disable(); /* purecov: tested */ } /* Wake threads waiting in a sync point. */ - pthread_cond_broadcast(&debug_sync_global.ds_cond); + mysql_cond_broadcast(&debug_sync_global.ds_cond); DBUG_PRINT("debug_sync_exec", ("signal '%s' at: '%s'", sig_emit, dsp_name)); } /* end if (action->signal.length()) */ if (action->wait_for.length()) { - pthread_mutex_t *old_mutex; - pthread_cond_t *old_cond; + mysql_mutex_t *old_mutex; + mysql_cond_t *old_cond; int error= 0; struct timespec abstime; @@ -1797,9 +1760,9 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) while (stringcmp(&debug_sync_global.ds_signal, &action->wait_for) && !thd->killed && opt_debug_sync_timeout) { - error= pthread_cond_timedwait(&debug_sync_global.ds_cond, - &debug_sync_global.ds_mutex, - &abstime); + error= mysql_cond_timedwait(&debug_sync_global.ds_cond, + &debug_sync_global.ds_mutex, + &abstime); DBUG_EXECUTE("debug_sync", { /* Functions as DBUG_PRINT args can change keyword and line nr. */ const char *sig_glob= debug_sync_global.ds_signal.c_ptr(); @@ -1832,18 +1795,17 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action) protected mutex must always unlocked _before_ mysys_var->mutex is locked. (See comment in THD::exit_cond().) */ - pthread_mutex_unlock(&debug_sync_global.ds_mutex); - pthread_mutex_lock(&thd->mysys_var->mutex); + mysql_mutex_unlock(&debug_sync_global.ds_mutex); + mysql_mutex_lock(&thd->mysys_var->mutex); thd->mysys_var->current_mutex= old_mutex; thd->mysys_var->current_cond= old_cond; thd_proc_info(thd, old_proc_info); - pthread_mutex_unlock(&thd->mysys_var->mutex); - + mysql_mutex_unlock(&thd->mysys_var->mutex); } else { /* In case we don't wait, we just release the mutex. */ - pthread_mutex_unlock(&debug_sync_global.ds_mutex); + mysql_mutex_unlock(&debug_sync_global.ds_mutex); } /* end if (action->wait_for.length()) */ } /* end if (action->execute) */ diff --git a/sql/derror.cc b/sql/derror.cc index 3073f37eba3..8e47dda7bbe 100644 --- a/sql/derror.cc +++ b/sql/derror.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2005 MySQL AB +/* Copyright (C) 2000-2005 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -107,10 +107,10 @@ bool read_texts(const char *file_name, const char *language, funktpos=0; convert_dirname(lang_path, language, NullS); (void) my_load_path(lang_path, lang_path, lc_messages_dir); - if ((file=my_open(fn_format(name,file_name, - lang_path, "", 4), - O_RDONLY | O_SHARE | O_BINARY, - MYF(0))) < 0) + if ((file= mysql_file_open(key_file_ERRMSG, + fn_format(name, file_name, lang_path, "", 4), + O_RDONLY | O_SHARE | O_BINARY, + MYF(0))) < 0) { /* Trying pre-5.4 sematics of the --language parameter. @@ -118,16 +118,18 @@ bool read_texts(const char *file_name, const char *language, --language=/path/to/english/ */ - if ((file= my_open(fn_format(name, file_name, lc_messages_dir, "", 4), - O_RDONLY | O_SHARE | O_BINARY, - MYF(0))) < 0) + if ((file= mysql_file_open(key_file_ERRMSG, + fn_format(name, file_name, lc_messages_dir, "", 4), + O_RDONLY | O_SHARE | O_BINARY, + MYF(0))) < 0) goto err; sql_print_error("An old style --language value with language specific part detected: %s", lc_messages_dir); sql_print_error("Use --lc-messages-dir without language specific part instead."); } funktpos=1; - if (my_read(file,(uchar*) head,32,MYF(MY_NABP))) goto err; + if (mysql_file_read(file, (uchar*) head, 32, MYF(MY_NABP))) + goto err; if (head[0] != (uchar) 254 || head[1] != (uchar) 254 || head[2] != 2 || head[3] != 1) goto err; /* purecov: inspected */ @@ -143,7 +145,7 @@ Error message file '%s' had only %d error messages,\n\ but it should contain at least %d error messages.\n\ Check that the above file is the right version for this program!", name,count,error_messages); - VOID(my_close(file,MYF(MY_WME))); + (void) mysql_file_close(file, MYF(MY_WME)); DBUG_RETURN(1); } @@ -156,21 +158,21 @@ Check that the above file is the right version for this program!", } buff= (uchar*) (*point + count); - if (my_read(file, buff, (size_t) count*2,MYF(MY_NABP))) + if (mysql_file_read(file, buff, (size_t) count*2, MYF(MY_NABP))) goto err; for (i=0, pos= buff ; i< count ; i++) { (*point)[i]= (char*) buff+uint2korr(pos); pos+=2; } - if (my_read(file, buff, length, MYF(MY_NABP))) + if (mysql_file_read(file, buff, length, MYF(MY_NABP))) goto err; for (i=1 ; i < textcount ; i++) { point[i]= *point +uint2korr(head+10+i+i); } - VOID(my_close(file,MYF(0))); + (void) mysql_file_close(file, MYF(0)); DBUG_RETURN(0); err: @@ -187,7 +189,7 @@ err: } sql_print_error(errmsg, name); if (file != FERR) - VOID(my_close(file,MYF(MY_WME))); + (void) mysql_file_close(file, MYF(MY_WME)); DBUG_RETURN(1); } /* read_texts */ diff --git a/sql/des_key_file.cc b/sql/des_key_file.cc index 317cb237360..c2b632e521b 100644 --- a/sql/des_key_file.cc +++ b/sql/des_key_file.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2003, 2005 MySQL AB +/* Copyright (C) 2001-2003, 2005 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -43,8 +43,9 @@ load_des_key_file(const char *file_name) DBUG_ENTER("load_des_key_file"); DBUG_PRINT("enter",("name: %s",file_name)); - VOID(pthread_mutex_lock(&LOCK_des_key_file)); - if ((file=my_open(file_name,O_RDONLY | O_BINARY ,MYF(MY_WME))) < 0 || + mysql_mutex_lock(&LOCK_des_key_file); + if ((file= mysql_file_open(key_file_des_key_file, file_name, + O_RDONLY | O_BINARY, MYF(MY_WME))) < 0 || init_io_cache(&io, file, IO_SIZE*2, READ_CACHE, 0, 0, MYF(MY_WME))) goto error; @@ -93,10 +94,10 @@ load_des_key_file(const char *file_name) error: if (file >= 0) { - my_close(file,MYF(0)); + mysql_file_close(file, MYF(0)); end_io_cache(&io); } - VOID(pthread_mutex_unlock(&LOCK_des_key_file)); + mysql_mutex_unlock(&LOCK_des_key_file); DBUG_RETURN(result); } #endif /* HAVE_OPENSSL */ diff --git a/sql/discover.cc b/sql/discover.cc index 56dc00cc5c4..fcc26042fe2 100644 --- a/sql/discover.cc +++ b/sql/discover.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2004 MySQL AB +/* Copyright (C) 2004 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -57,15 +57,16 @@ int readfrm(const char *name, uchar **frmdata, size_t *len) *frmdata= NULL; // In case of errors *len= 0; error= 1; - if ((file=my_open(fn_format(index_file,name,"",reg_ext, - MY_UNPACK_FILENAME|MY_APPEND_EXT), - O_RDONLY | O_SHARE, - MYF(0))) < 0) + if ((file= mysql_file_open(key_file_frm, + fn_format(index_file, name, "", reg_ext, + MY_UNPACK_FILENAME|MY_APPEND_EXT), + O_RDONLY | O_SHARE, + MYF(0))) < 0) goto err_end; // Get length of file error= 2; - if (my_fstat(file, &state, MYF(0))) + if (mysql_file_fstat(file, &state, MYF(0))) goto err; read_len= state.st_size; @@ -82,7 +83,7 @@ int readfrm(const char *name, uchar **frmdata, size_t *len) err: if (file > 0) - VOID(my_close(file,MYF(MY_WME))); + (void) mysql_file_close(file, MYF(MY_WME)); err_end: /* Here when no file */ DBUG_RETURN (error); @@ -112,13 +113,15 @@ int writefrm(const char *name, const uchar *frmdata, size_t len) DBUG_PRINT("enter",("name: '%s' len: %lu ",name, (ulong) len)); error= 0; - if ((file=my_create(fn_format(index_file,name,"",reg_ext, - MY_UNPACK_FILENAME|MY_APPEND_EXT), - CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0) + if ((file= mysql_file_create(key_file_frm, + fn_format(index_file, name, "", reg_ext, + MY_UNPACK_FILENAME | MY_APPEND_EXT), + CREATE_MODE, O_RDWR | O_TRUNC, + MYF(MY_WME))) >= 0) { - if (my_write(file, frmdata, len,MYF(MY_WME | MY_NABP))) + if (mysql_file_write(file, frmdata, len, MYF(MY_WME | MY_NABP))) error= 2; - VOID(my_close(file,MYF(0))); + (void) mysql_file_close(file, MYF(0)); } DBUG_RETURN(error); } /* writefrm */ diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index 235f6a37eeb..7f4104f4a77 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2004-2006 MySQL AB +/* Copyright (C) 2004-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -196,7 +196,7 @@ Event_basic::Event_basic() { DBUG_ENTER("Event_basic::Event_basic"); /* init memory root */ - init_alloc_root(&mem_root, 256, 512); + init_sql_alloc(&mem_root, 256, 512); dbname.str= name.str= NULL; dbname.length= name.length= 0; time_zone= NULL; @@ -834,8 +834,9 @@ bool get_next_time(const Time_zone *time_zone, my_time_t *next, } else { - long diff_months= (long) (local_now.year - local_start.year)*12 + - (local_now.month - local_start.month); + long diff_months= ((long) local_now.year - (long) local_start.year)*12 + + ((long) local_now.month - (long) local_start.month); + /* Unlike for seconds above, the formula below returns the interval that, when added to the local_start, will give the time in the @@ -1402,8 +1403,7 @@ Event_job_data::execute(THD *thd, bool drop) } #endif - if (check_access(thd, EVENT_ACL, dbname.str, - 0, 0, 0, is_schema_db(dbname.str, dbname.length))) + if (check_access(thd, EVENT_ACL, dbname.str, NULL, NULL, 0, 0)) { /* This aspect of behavior is defined in the worklog, diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc index 753e9d21b65..fd2c5a556a8 100644 --- a/sql/event_db_repository.cc +++ b/sql/event_db_repository.cc @@ -1053,8 +1053,8 @@ update_timing_fields_for_event(THD *thd, Turn off row binlogging of event timing updates. These are not used for RBR of events replicated to the slave. */ - save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); + thd->clear_current_stmt_binlog_format_row(); DBUG_ASSERT(thd->security_ctx->master_access & SUPER_ACL); diff --git a/sql/event_queue.cc b/sql/event_queue.cc index 04d4f858b43..225029040b0 100644 --- a/sql/event_queue.cc +++ b/sql/event_queue.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2004-2006 MySQL AB +/* Copyright (C) 2004-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,6 +16,7 @@ #include "mysql_priv.h" #include "event_queue.h" #include "event_data_objects.h" +#include "sql_audit.h" /** @addtogroup Event_Scheduler @@ -94,16 +95,16 @@ Event_queue::Event_queue() mutex_queue_data_attempting_lock(FALSE), waiting_on_cond(FALSE) { - pthread_mutex_init(&LOCK_event_queue, MY_MUTEX_INIT_FAST); - pthread_cond_init(&COND_queue_state, NULL); + mysql_mutex_init(key_LOCK_event_queue, &LOCK_event_queue, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_queue_state, &COND_queue_state, NULL); } Event_queue::~Event_queue() { deinit_queue(); - pthread_mutex_destroy(&LOCK_event_queue); - pthread_cond_destroy(&COND_queue_state); + mysql_mutex_destroy(&LOCK_event_queue); + mysql_cond_destroy(&COND_queue_state); } @@ -210,7 +211,7 @@ Event_queue::create_event(THD *thd, Event_queue_element *new_element, LOCK_QUEUE_DATA(); *created= (queue_insert_safe(&queue, (uchar *) new_element) == FALSE); dbug_dump_queue(thd->query_start()); - pthread_cond_broadcast(&COND_queue_state); + mysql_cond_broadcast(&COND_queue_state); UNLOCK_QUEUE_DATA(); DBUG_RETURN(!*created); @@ -258,7 +259,7 @@ Event_queue::update_event(THD *thd, LEX_STRING dbname, LEX_STRING name, { DBUG_PRINT("info", ("new event in the queue: 0x%lx", (long) new_element)); queue_insert_safe(&queue, (uchar *) new_element); - pthread_cond_broadcast(&COND_queue_state); + mysql_cond_broadcast(&COND_queue_state); } dbug_dump_queue(thd->query_start()); @@ -343,7 +344,7 @@ Event_queue::drop_matching_events(THD *thd, LEX_STRING pattern, i++; } /* - We don't call pthread_cond_broadcast(&COND_queue_state); + We don't call mysql_cond_broadcast(&COND_queue_state); If we remove the top event: 1. The queue is empty. The scheduler will wake up at some time and realize that the queue is empty. If create_event() comes inbetween @@ -581,6 +582,9 @@ Event_queue::get_top_for_execution_if_time(THD *thd, /* There are no events in the queue */ next_activation_at= 0; + /* Release any held audit resources before waiting */ + mysql_audit_release(thd); + /* Wait on condition until signaled. Release LOCK_queue while waiting. */ cond_wait(thd, NULL, queue_empty_msg, SCHED_FUNC, __LINE__); @@ -600,6 +604,10 @@ Event_queue::get_top_for_execution_if_time(THD *thd, */ struct timespec top_time; set_timespec(top_time, next_activation_at - thd->query_start()); + + /* Release any held audit resources before waiting */ + mysql_audit_release(thd); + cond_wait(thd, &top_time, queue_wait_msg, SCHED_FUNC, __LINE__); continue; @@ -669,7 +677,7 @@ Event_queue::lock_data(const char *func, uint line) mutex_last_attempted_lock_in_func= func; mutex_last_attempted_lock_at_line= line; mutex_queue_data_attempting_lock= TRUE; - pthread_mutex_lock(&LOCK_event_queue); + mysql_mutex_lock(&LOCK_event_queue); mutex_last_attempted_lock_in_func= ""; mutex_last_attempted_lock_at_line= 0; mutex_queue_data_attempting_lock= FALSE; @@ -700,19 +708,19 @@ Event_queue::unlock_data(const char *func, uint line) mutex_last_unlocked_at_line= line; mutex_queue_data_locked= FALSE; mutex_last_unlocked_in_func= func; - pthread_mutex_unlock(&LOCK_event_queue); + mysql_mutex_unlock(&LOCK_event_queue); DBUG_VOID_RETURN; } /* - Wrapper for pthread_cond_wait/timedwait + Wrapper for mysql_cond_wait/timedwait SYNOPSIS Event_queue::cond_wait() thd Thread (Could be NULL during shutdown procedure) msg Message for thd->proc_info - abstime If not null then call pthread_cond_timedwait() + abstime If not null then call mysql_cond_timedwait() func Which function is requesting cond_wait line On which line cond_wait is requested */ @@ -729,11 +737,11 @@ Event_queue::cond_wait(THD *thd, struct timespec *abstime, const char* msg, thd->enter_cond(&COND_queue_state, &LOCK_event_queue, msg); - DBUG_PRINT("info", ("pthread_cond_%swait", abstime? "timed":"")); + DBUG_PRINT("info", ("mysql_cond_%swait", abstime? "timed":"")); if (!abstime) - pthread_cond_wait(&COND_queue_state, &LOCK_event_queue); + mysql_cond_wait(&COND_queue_state, &LOCK_event_queue); else - pthread_cond_timedwait(&COND_queue_state, &LOCK_event_queue, abstime); + mysql_cond_timedwait(&COND_queue_state, &LOCK_event_queue, abstime); mutex_last_locked_in_func= func; mutex_last_locked_at_line= line; diff --git a/sql/event_queue.h b/sql/event_queue.h index 2870ecb4d0b..aac9eb04e98 100644 --- a/sql/event_queue.h +++ b/sql/event_queue.h @@ -1,6 +1,6 @@ #ifndef _EVENT_QUEUE_H_ #define _EVENT_QUEUE_H_ -/* Copyright (C) 2004-2006 MySQL AB +/* Copyright (C) 2004-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,6 +25,11 @@ Queue of events awaiting execution. */ +#ifdef HAVE_PSI_INTERFACE +extern PSI_mutex_key key_LOCK_event_queue; +extern PSI_cond_key key_COND_queue_state; +#endif /* HAVE_PSI_INTERFACE */ + class Event_basic; class Event_queue_element; class Event_queue_element_for_exec; @@ -101,8 +106,8 @@ private: dbug_dump_queue(time_t now); /* LOCK_event_queue is the mutex which protects the access to the queue. */ - pthread_mutex_t LOCK_event_queue; - pthread_cond_t COND_queue_state; + mysql_mutex_t LOCK_event_queue; + mysql_cond_t COND_queue_state; /* The sorted queue with the Event_queue_element objects */ QUEUE queue; diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index 065d67bdb6a..733f2a7167f 100755 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2004-2006 MySQL AB +/* Copyright (C) 2004-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -128,14 +128,12 @@ post_init_event_thread(THD *thd) thd->cleanup(); return TRUE; } - lex_start(thd); - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); threads.append(thd); thread_count++; - thread_running++; - pthread_mutex_unlock(&LOCK_thread_count); - + inc_thread_running(); + mysql_mutex_unlock(&LOCK_thread_count); return FALSE; } @@ -155,17 +153,17 @@ deinit_event_thread(THD *thd) DBUG_ASSERT(thd->net.buff != 0); net_end(&thd->net); DBUG_PRINT("exit", ("Event thread finishing")); - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thread_count--; - thread_running--; + dec_thread_running(); delete thd; - pthread_cond_broadcast(&COND_thread_count); - pthread_mutex_unlock(&LOCK_thread_count); + mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); } /* - Performs pre- pthread_create() initialisation of THD. Do this + Performs pre- mysql_thread_create() initialisation of THD. Do this in the thread that will pass THD to the child thread. In the child thread call post_init_event_thread(). @@ -190,11 +188,11 @@ pre_init_event_thread(THD* thd) thd->security_ctx->set_user((char*)"event_scheduler"); thd->net.read_timeout= slave_net_timeout; thd->slave_thread= 0; - thd->options|= OPTION_AUTO_IS_NULL; + thd->variables.option_bits|= OPTION_AUTO_IS_NULL; thd->client_capabilities|= CLIENT_MULTI_RESULTS; - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); /* Guarantees that we will see the thread in SHOW PROCESSLIST though its @@ -229,6 +227,9 @@ event_scheduler_thread(void *arg) bool res; thd->thread_stack= (char *)&thd; // remember where our stack is + + mysql_thread_set_psi_id(thd->thread_id); + res= post_init_event_thread(thd); DBUG_ENTER("event_scheduler_thread"); @@ -262,6 +263,8 @@ event_worker_thread(void *arg) thd= event->thd; + mysql_thread_set_psi_id(thd->thread_id); + Event_worker_thread worker_thread; worker_thread.run(thd, event); @@ -338,16 +341,17 @@ Event_scheduler::Event_scheduler(Event_queue *queue_arg) waiting_on_cond(FALSE), started_events(0) { - pthread_mutex_init(&LOCK_scheduler_state, MY_MUTEX_INIT_FAST); - pthread_cond_init(&COND_state, NULL); + mysql_mutex_init(key_event_scheduler_LOCK_scheduler_state, + &LOCK_scheduler_state, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_event_scheduler_COND_state, &COND_state, NULL); } Event_scheduler::~Event_scheduler() { stop(); /* does nothing if not running */ - pthread_mutex_destroy(&LOCK_scheduler_state); - pthread_cond_destroy(&COND_state); + mysql_mutex_destroy(&LOCK_scheduler_state); + mysql_cond_destroy(&COND_state); } @@ -406,8 +410,9 @@ Event_scheduler::start() DBUG_PRINT("info", ("Setting state go RUNNING")); state= RUNNING; DBUG_PRINT("info", ("Forking new thread for scheduler. THD: 0x%lx", (long) new_thd)); - if (pthread_create(&th, &connection_attrib, event_scheduler_thread, - (void*)scheduler_param_value)) + if (mysql_thread_create(key_thread_event_scheduler, + &th, &connection_attrib, event_scheduler_thread, + (void*)scheduler_param_value)) { DBUG_PRINT("error", ("cannot create a new thread")); state= INITIALIZED; @@ -417,12 +422,12 @@ Event_scheduler::start() new_thd->proc_info= "Clearing"; DBUG_ASSERT(new_thd->net.buff != 0); net_end(&new_thd->net); - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thread_count--; - thread_running--; + dec_thread_running(); delete new_thd; - pthread_cond_broadcast(&COND_thread_count); - pthread_mutex_unlock(&LOCK_thread_count); + mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); } end: UNLOCK_DATA(); @@ -490,7 +495,7 @@ Event_scheduler::run(THD *thd) scheduler_thd= NULL; state= INITIALIZED; DBUG_PRINT("info", ("Signalling back to the stopper COND_state")); - pthread_cond_signal(&COND_state); + mysql_cond_signal(&COND_state); UNLOCK_DATA(); DBUG_RETURN(res); @@ -534,8 +539,9 @@ Event_scheduler::execute_top(Event_queue_element_for_exec *event_name) reasonable level. */ /* Major failure */ - if ((res= pthread_create(&th, &connection_attrib, event_worker_thread, - event_name))) + if ((res= mysql_thread_create(key_thread_event_worker, + &th, &connection_attrib, event_worker_thread, + event_name))) goto error; ++started_events; @@ -550,12 +556,12 @@ error: new_thd->proc_info= "Clearing"; DBUG_ASSERT(new_thd->net.buff != 0); net_end(&new_thd->net); - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thread_count--; - thread_running--; + dec_thread_running(); delete new_thd; - pthread_cond_broadcast(&COND_thread_count); - pthread_mutex_unlock(&LOCK_thread_count); + mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); } delete event_name; DBUG_RETURN(TRUE); @@ -635,13 +641,13 @@ Event_scheduler::stop() DBUG_PRINT("info", ("Scheduler thread has id %lu", scheduler_thd->thread_id)); /* Lock from delete */ - pthread_mutex_lock(&scheduler_thd->LOCK_thd_data); + mysql_mutex_lock(&scheduler_thd->LOCK_thd_data); /* This will wake up the thread if it waits on Queue's conditional */ sql_print_information("Event Scheduler: Killing the scheduler thread, " "thread id %lu", scheduler_thd->thread_id); scheduler_thd->awake(THD::KILL_CONNECTION); - pthread_mutex_unlock(&scheduler_thd->LOCK_thd_data); + mysql_mutex_unlock(&scheduler_thd->LOCK_thd_data); /* thd could be 0x0, when shutting down */ sql_print_information("Event Scheduler: " @@ -670,12 +676,12 @@ Event_scheduler::workers_count() uint count= 0; DBUG_ENTER("Event_scheduler::workers_count"); - pthread_mutex_lock(&LOCK_thread_count); // For unlink from list + mysql_mutex_lock(&LOCK_thread_count); // For unlink from list I_List_iterator<THD> it(threads); while ((tmp=it++)) if (tmp->system_thread == SYSTEM_THREAD_EVENT_WORKER) ++count; - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); DBUG_PRINT("exit", ("%d", count)); DBUG_RETURN(count); } @@ -696,7 +702,7 @@ Event_scheduler::lock_data(const char *func, uint line) { DBUG_ENTER("Event_scheduler::lock_data"); DBUG_PRINT("enter", ("func=%s line=%u", func, line)); - pthread_mutex_lock(&LOCK_scheduler_state); + mysql_mutex_lock(&LOCK_scheduler_state); mutex_last_locked_in_func= func; mutex_last_locked_at_line= line; mutex_scheduler_data_locked= TRUE; @@ -722,18 +728,18 @@ Event_scheduler::unlock_data(const char *func, uint line) mutex_last_unlocked_at_line= line; mutex_scheduler_data_locked= FALSE; mutex_last_unlocked_in_func= func; - pthread_mutex_unlock(&LOCK_scheduler_state); + mysql_mutex_unlock(&LOCK_scheduler_state); DBUG_VOID_RETURN; } /* - Wrapper for pthread_cond_wait/timedwait + Wrapper for mysql_cond_wait/timedwait SYNOPSIS Event_scheduler::cond_wait() thd Thread (Could be NULL during shutdown procedure) - abstime If not null then call pthread_cond_timedwait() + abstime If not null then call mysql_cond_timedwait() msg Message for thd->proc_info func Which function is requesting cond_wait line On which line cond_wait is requested @@ -751,11 +757,11 @@ Event_scheduler::cond_wait(THD *thd, struct timespec *abstime, const char* msg, if (thd) thd->enter_cond(&COND_state, &LOCK_scheduler_state, msg); - DBUG_PRINT("info", ("pthread_cond_%swait", abstime? "timed":"")); + DBUG_PRINT("info", ("mysql_cond_%swait", abstime? "timed":"")); if (!abstime) - pthread_cond_wait(&COND_state, &LOCK_scheduler_state); + mysql_cond_wait(&COND_state, &LOCK_scheduler_state); else - pthread_cond_timedwait(&COND_state, &LOCK_scheduler_state, abstime); + mysql_cond_timedwait(&COND_state, &LOCK_scheduler_state, abstime); if (thd) { /* diff --git a/sql/event_scheduler.h b/sql/event_scheduler.h index 0be93a65d33..2988f354f63 100644 --- a/sql/event_scheduler.h +++ b/sql/event_scheduler.h @@ -1,6 +1,6 @@ #ifndef _EVENT_SCHEDULER_H_ #define _EVENT_SCHEDULER_H_ -/* Copyright (C) 2004-2006 MySQL AB +/* Copyright (C) 2004-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -115,7 +115,7 @@ private: cond_wait(THD *thd, struct timespec *abstime, const char* msg, const char *func, uint line); - pthread_mutex_t LOCK_scheduler_state; + mysql_mutex_t LOCK_scheduler_state; enum enum_state { @@ -129,7 +129,7 @@ private: THD *scheduler_thd; - pthread_cond_t COND_state; + mysql_cond_t COND_state; Event_queue *queue; diff --git a/sql/events.cc b/sql/events.cc index f6c4ea6d54f..73f3427607d 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2004-2006 MySQL AB +/* Copyright (C) 2004-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ #include "event_queue.h" #include "event_scheduler.h" #include "sp_head.h" // for Stored_program_creation_ctx +#include "set_var.h" /** @addtogroup Event_Scheduler @@ -63,44 +64,11 @@ eligible for execution. */ -/* - Keep the order of the first to as in var_typelib - sys_var_event_scheduler::value_ptr() references this array. Keep in - mind! -*/ -static const char *opt_event_scheduler_state_names[]= - { "OFF", "ON", "0", "1", "DISABLED", NullS }; - -const TYPELIB Events::opt_typelib= -{ - array_elements(opt_event_scheduler_state_names)-1, - "", - opt_event_scheduler_state_names, - NULL -}; - - -/* - The order should not be changed. We consider OFF to be equivalent of INT 0 - And ON of 1. If OFF & ON are interchanged the logic in - sys_var_event_scheduler::update() will be broken! -*/ -static const char *var_event_scheduler_state_names[]= { "OFF", "ON", NullS }; - -const TYPELIB Events::var_typelib= -{ - array_elements(var_event_scheduler_state_names)-1, - "", - var_event_scheduler_state_names, - NULL -}; - Event_queue *Events::event_queue; Event_scheduler *Events::scheduler; Event_db_repository *Events::db_repository; -enum Events::enum_opt_event_scheduler -Events::opt_event_scheduler= Events::EVENTS_OFF; -pthread_mutex_t Events::LOCK_event_metadata; +uint Events::opt_event_scheduler= Events::EVENTS_OFF; +mysql_mutex_t Events::LOCK_event_metadata; bool Events::check_system_tables_error= FALSE; @@ -127,69 +95,6 @@ int sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs) /** - @brief Initialize the start up option of the Events scheduler. - - Do not initialize the scheduler subsystem yet - the initialization - is split into steps as it has to fit into the common MySQL - initialization framework. - No locking as this is called only at start up. - - @param[in,out] argument The value of the argument. If this value - is found in the typelib, the argument is - updated. - - @retval TRUE unknown option value - @retval FALSE success -*/ - -bool -Events::set_opt_event_scheduler(char *argument) -{ - if (argument == NULL) - opt_event_scheduler= Events::EVENTS_ON; - else - { - int type; - /* - type= 1 2 3 4 5 - (OFF | ON) - (0 | 1) (DISABLE ) - */ - const static enum enum_opt_event_scheduler type2state[]= - { EVENTS_OFF, EVENTS_ON, EVENTS_OFF, EVENTS_ON, EVENTS_DISABLED }; - - type= find_type(argument, &opt_typelib, 1); - - DBUG_ASSERT(type >= 0 && type <= 5); /* guaranteed by find_type */ - - if (type == 0) - { - fprintf(stderr, "Unknown option to event-scheduler: %s\n", argument); - return TRUE; - } - opt_event_scheduler= type2state[type-1]; - } - return FALSE; -} - - -/** - Return a string representation of the current scheduler mode. -*/ - -const char * -Events::get_opt_event_scheduler_str() -{ - const char *str; - - pthread_mutex_lock(&LOCK_event_metadata); - str= opt_typelib.type_names[(int) opt_event_scheduler]; - pthread_mutex_unlock(&LOCK_event_metadata); - - return str; -} - - -/** Push an error into the error stack if the system tables are not up to date. */ @@ -415,9 +320,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, /* At create, one of them must be set */ DBUG_ASSERT(parse_data->expression || parse_data->execute_at); - if (check_access(thd, EVENT_ACL, parse_data->dbname.str, 0, 0, 0, - is_schema_db(parse_data->dbname.str, - parse_data->dbname.length))) + if (check_access(thd, EVENT_ACL, parse_data->dbname.str, NULL, NULL, 0, 0)) DBUG_RETURN(TRUE); if (check_db_dir_existence(parse_data->dbname.str)) @@ -432,10 +335,10 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for CREATE EVENT command. */ - save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); + thd->clear_current_stmt_binlog_format_row(); - pthread_mutex_lock(&LOCK_event_metadata); + mysql_mutex_lock(&LOCK_event_metadata); /* On error conditions my_error() is called so no need to handle here */ if (!(ret= db_repository->create_event(thd, parse_data, if_not_exists))) @@ -482,7 +385,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, ret= write_bin_log(thd, TRUE, log_query.c_ptr(), log_query.length()); } } - pthread_mutex_unlock(&LOCK_event_metadata); + mysql_mutex_unlock(&LOCK_event_metadata); /* Restore the state of binlog format */ thd->current_stmt_binlog_row_based= save_binlog_row_based; @@ -532,9 +435,7 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, if (parse_data->check_parse_data(thd) || parse_data->do_not_create) DBUG_RETURN(TRUE); - if (check_access(thd, EVENT_ACL, parse_data->dbname.str, 0, 0, 0, - is_schema_db(parse_data->dbname.str, - parse_data->dbname.length))) + if (check_access(thd, EVENT_ACL, parse_data->dbname.str, NULL, NULL, 0, 0)) DBUG_RETURN(TRUE); if (new_dbname) /* It's a rename */ @@ -555,8 +456,7 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, to tell the user that a database doesn't exist if they can not access it. */ - if (check_access(thd, EVENT_ACL, new_dbname->str, 0, 0, 0, - is_schema_db(new_dbname->str, new_dbname->length))) + if (check_access(thd, EVENT_ACL, new_dbname->str, NULL, NULL, 0, 0)) DBUG_RETURN(TRUE); /* Check that the target database exists */ @@ -571,10 +471,10 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for UPDATE EVENT command. */ - save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); + thd->clear_current_stmt_binlog_format_row(); - pthread_mutex_lock(&LOCK_event_metadata); + mysql_mutex_lock(&LOCK_event_metadata); /* On error conditions my_error() is called so no need to handle here */ if (!(ret= db_repository->update_event(thd, parse_data, @@ -607,7 +507,7 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, ret= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } } - pthread_mutex_unlock(&LOCK_event_metadata); + mysql_mutex_unlock(&LOCK_event_metadata); /* Restore the state of binlog format */ thd->current_stmt_binlog_row_based= save_binlog_row_based; @@ -663,18 +563,17 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists) if (check_if_system_tables_error()) DBUG_RETURN(TRUE); - if (check_access(thd, EVENT_ACL, dbname.str, 0, 0, 0, - is_schema_db(dbname.str, dbname.length))) + if (check_access(thd, EVENT_ACL, dbname.str, NULL, NULL, 0, 0)) DBUG_RETURN(TRUE); /* Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for DROP EVENT command. */ - save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); + thd->clear_current_stmt_binlog_format_row(); - pthread_mutex_lock(&LOCK_event_metadata); + mysql_mutex_lock(&LOCK_event_metadata); /* On error conditions my_error() is called so no need to handle here */ if (!(ret= db_repository->drop_event(thd, dbname, name, if_exists))) { @@ -684,7 +583,7 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists) DBUG_ASSERT(thd->query() && thd->query_length()); ret= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } - pthread_mutex_unlock(&LOCK_event_metadata); + mysql_mutex_unlock(&LOCK_event_metadata); /* Restore the state of binlog format */ thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(ret); @@ -715,11 +614,11 @@ Events::drop_schema_events(THD *thd, char *db) are damaged, as intended. */ - pthread_mutex_lock(&LOCK_event_metadata); + mysql_mutex_lock(&LOCK_event_metadata); if (event_queue) event_queue->drop_schema_events(thd, db_lex); db_repository->drop_schema_events(thd, db_lex); - pthread_mutex_unlock(&LOCK_event_metadata); + mysql_mutex_unlock(&LOCK_event_metadata); DBUG_VOID_RETURN; } @@ -747,8 +646,7 @@ send_show_create_event(THD *thd, Event_timed *et, Protocol *protocol) field_list.push_back(new Item_empty_string("Event", NAME_CHAR_LEN)); - if (sys_var_thd_sql_mode::symbolic_mode_representation(thd, et->sql_mode, - &sql_mode)) + if (sql_mode_string_representation(thd, et->sql_mode, &sql_mode)) DBUG_RETURN(TRUE); field_list.push_back(new Item_empty_string("sql_mode", (uint) sql_mode.length)); @@ -823,8 +721,7 @@ Events::show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name) if (check_if_system_tables_error()) DBUG_RETURN(TRUE); - if (check_access(thd, EVENT_ACL, dbname.str, 0, 0, 0, - is_schema_db(dbname.str, dbname.length))) + if (check_access(thd, EVENT_ACL, dbname.str, NULL, NULL, 0, 0)) DBUG_RETURN(TRUE); /* @@ -882,8 +779,9 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */) if (thd->lex->sql_command == SQLCOM_SHOW_EVENTS) { DBUG_ASSERT(thd->lex->select_lex.db); - if (!is_schema_db(thd->lex->select_lex.db) && // There is no events in I_S - check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0, 0)) + if (!is_infoschema_db(thd->lex->select_lex.db) && // There is no events in I_S + check_access(thd, EVENT_ACL, thd->lex->select_lex.db, + NULL, NULL, 0, 0)) DBUG_RETURN(1); db= thd->lex->select_lex.db; } @@ -938,7 +836,6 @@ Events::init(my_bool opt_noacl_or_bootstrap) */ thd->thread_stack= (char*) &thd; thd->store_globals(); - lex_start(thd); /* We will need Event_db_repository anyway, even if the scheduler is @@ -1044,6 +941,51 @@ Events::deinit() DBUG_VOID_RETURN; } +#ifdef HAVE_PSI_INTERFACE +PSI_mutex_key key_LOCK_event_metadata, key_LOCK_event_queue, + key_event_scheduler_LOCK_scheduler_state; + +static PSI_mutex_info all_events_mutexes[]= +{ + { &key_LOCK_event_metadata, "LOCK_event_metadata", PSI_FLAG_GLOBAL}, + { &key_LOCK_event_queue, "LOCK_event_queue", PSI_FLAG_GLOBAL}, + { &key_event_scheduler_LOCK_scheduler_state, "Event_scheduler::LOCK_scheduler_state", PSI_FLAG_GLOBAL} +}; + +PSI_cond_key key_event_scheduler_COND_state, key_COND_queue_state; + +static PSI_cond_info all_events_conds[]= +{ + { &key_event_scheduler_COND_state, "Event_scheduler::COND_state", PSI_FLAG_GLOBAL}, + { &key_COND_queue_state, "COND_queue_state", PSI_FLAG_GLOBAL}, +}; + +PSI_thread_key key_thread_event_scheduler, key_thread_event_worker; + +static PSI_thread_info all_events_threads[]= +{ + { &key_thread_event_scheduler, "event_scheduler", PSI_FLAG_GLOBAL}, + { &key_thread_event_worker, "event_worker", 0} +}; + +static void init_events_psi_keys(void) +{ + const char* category= "sql"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_events_mutexes); + PSI_server->register_mutex(category, all_events_mutexes, count); + + count= array_elements(all_events_conds); + PSI_server->register_cond(category, all_events_conds, count); + + count= array_elements(all_events_threads); + PSI_server->register_thread(category, all_events_threads, count); +} +#endif /* HAVE_PSI_INTERFACE */ /** Inits Events mutexes @@ -1056,7 +998,12 @@ Events::deinit() void Events::init_mutexes() { - pthread_mutex_init(&LOCK_event_metadata, MY_MUTEX_INIT_FAST); +#ifdef HAVE_PSI_INTERFACE + init_events_psi_keys(); +#endif + + mysql_mutex_init(key_LOCK_event_metadata, + &LOCK_event_metadata, MY_MUTEX_INIT_FAST); } @@ -1070,7 +1017,7 @@ Events::init_mutexes() void Events::destroy_mutexes() { - pthread_mutex_destroy(&LOCK_event_metadata); + mysql_mutex_destroy(&LOCK_event_metadata); } @@ -1092,7 +1039,7 @@ Events::dump_internal_status() puts("LLA = Last Locked At LUA = Last Unlocked At"); puts("WOC = Waiting On Condition DL = Data Locked"); - pthread_mutex_lock(&LOCK_event_metadata); + mysql_mutex_lock(&LOCK_event_metadata); if (opt_event_scheduler == EVENTS_DISABLED) puts("The Event Scheduler is disabled"); else @@ -1101,64 +1048,19 @@ Events::dump_internal_status() event_queue->dump_internal_status(); } - pthread_mutex_unlock(&LOCK_event_metadata); + mysql_mutex_unlock(&LOCK_event_metadata); DBUG_VOID_RETURN; } - -/** - Starts or stops the event scheduler thread. - - @retval FALSE success - @retval TRUE error -*/ - -bool -Events::switch_event_scheduler_state(enum_opt_event_scheduler new_state) +bool Events::start() { - bool ret= FALSE; - - DBUG_ENTER("Events::switch_event_scheduler_state"); - - DBUG_ASSERT(new_state == Events::EVENTS_ON || - new_state == Events::EVENTS_OFF); - - /* - If the scheduler was disabled because there are no/bad - system tables, produce a more meaningful error message - than ER_OPTION_PREVENTS_STATEMENT - */ - if (check_if_system_tables_error()) - DBUG_RETURN(TRUE); - - pthread_mutex_lock(&LOCK_event_metadata); - - if (opt_event_scheduler == EVENTS_DISABLED) - { - my_error(ER_OPTION_PREVENTS_STATEMENT, - MYF(0), "--event-scheduler=DISABLED or --skip-grant-tables"); - ret= TRUE; - goto end; - } - - if (new_state == EVENTS_ON) - ret= scheduler->start(); - else - ret= scheduler->stop(); - - if (ret) - { - my_error(ER_EVENT_SET_VAR_ERROR, MYF(0)); - goto end; - } - - opt_event_scheduler= new_state; - -end: - pthread_mutex_unlock(&LOCK_event_metadata); - DBUG_RETURN(ret); + return scheduler->start(); } +bool Events::stop() +{ + return scheduler->stop(); +} /** Loads all ENABLED events from mysql.event into a prioritized diff --git a/sql/events.h b/sql/events.h index 2bc87517748..881ade37cbf 100644 --- a/sql/events.h +++ b/sql/events.h @@ -1,6 +1,6 @@ #ifndef _EVENT_H_ #define _EVENT_H_ -/* Copyright (C) 2004-2006 MySQL AB +/* Copyright (C) 2004-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,6 +25,13 @@ A public interface of Events_Scheduler module. */ +#ifdef HAVE_PSI_INTERFACE +extern PSI_mutex_key key_LOCK_event_metadata, + key_event_scheduler_LOCK_scheduler_state; +extern PSI_cond_key key_event_scheduler_COND_state; +extern PSI_thread_key key_thread_event_scheduler, key_thread_event_worker; +#endif /* HAVE_PSI_INTERFACE */ + class Event_parse_data; class Event_db_repository; class Event_queue; @@ -56,7 +63,7 @@ sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs); The life cycle of the Events module is the following: At server start up: - set_opt_event_scheduler() -> init_mutexes() -> init() + init_mutexes() -> init() When the server is running: create_event(), drop_event(), start_or_stop_event_scheduler(), etc At shutdown: @@ -70,23 +77,19 @@ sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs); class Events { public: - /* The order should match the order in opt_typelib */ - enum enum_opt_event_scheduler - { - EVENTS_OFF= 0, - EVENTS_ON= 1, - EVENTS_DISABLED= 4 - }; - - /* Possible values of @@event_scheduler variable */ - static const TYPELIB var_typelib; - - static bool - set_opt_event_scheduler(char *argument); - - static const char * - get_opt_event_scheduler_str(); + /* + the following block is to support --event-scheduler command line option + and the @@global.event_scheduler SQL variable. + See sys_var.cc + */ + enum enum_opt_event_scheduler { EVENTS_OFF, EVENTS_ON, EVENTS_DISABLED }; + static uint opt_event_scheduler; + static mysql_mutex_t LOCK_event_metadata; + static bool check_if_system_tables_error(); + static bool start(); + static bool stop(); +public: /* A hack needed for Event_queue_element */ static Event_db_repository * get_db_repository() { return db_repository; } @@ -134,20 +137,14 @@ public: dump_internal_status(); private: - static bool check_if_system_tables_error(); static bool load_events_from_db(THD *thd); private: - /* Command line option names */ - static const TYPELIB opt_typelib; - static pthread_mutex_t LOCK_event_metadata; static Event_queue *event_queue; static Event_scheduler *scheduler; static Event_db_repository *db_repository; - /* Current state of Event Scheduler */ - static enum enum_opt_event_scheduler opt_event_scheduler; /* Set to TRUE if an error at start up */ static bool check_system_tables_error; diff --git a/sql/field.cc b/sql/field.cc index 64ad2dc180e..51bb527fc85 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -31,9 +31,6 @@ #include "slave.h" // Pull in rpl_master_has_bug() #include <m_ctype.h> #include <errno.h> -#ifdef HAVE_FCONVERT -#include <floatingpoint.h> -#endif // Maximum allowed exponent value for converting string to decimal #define MAX_EXPONENT 1024 @@ -50,7 +47,7 @@ template class List_iterator<Create_field>; uchar Field_null::null[1]={1}; const char field_separator=','; -#define DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE 320 +#define DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE FLOATING_POINT_BUFFER #define LONGLONG_TO_STRING_CONVERSION_BUFFER_SIZE 128 #define DECIMAL_TO_STRING_CONVERSION_BUFFER_SIZE 128 #define BLOB_PACK_LENGTH_TO_MAX_LENGH(arg) \ @@ -59,6 +56,8 @@ const char field_separator=','; #define ASSERT_COLUMN_MARKED_FOR_READ DBUG_ASSERT(!table || (!table->read_set || bitmap_is_set(table->read_set, field_index))) #define ASSERT_COLUMN_MARKED_FOR_WRITE DBUG_ASSERT(!table || (!table->write_set || bitmap_is_set(table->write_set, field_index))) +#define FLAGSTR(S,F) ((S) & (F) ? #F " " : "") + /* Rules for merging different types of fields in UNION @@ -997,6 +996,22 @@ test_if_important_data(CHARSET_INFO *cs, const char *str, const char *strend) /** + Function to compare two unsigned integers for their relative order. + Used below. In an anonymous namespace to not clash with definitions + in other files. + */ +namespace { + int compare(unsigned int a, unsigned int b) + { + if (a < b) + return -1; + if (b < a) + return 1; + return 0; +} +} + +/** Detect Item_result by given field type of UNION merge result. @param field_type given field type @@ -1395,22 +1410,48 @@ bool Field::send_binary(Protocol *protocol) /** Check to see if field size is compatible with destination. - This method is used in row-based replication to verify that the slave's - field size is less than or equal to the master's field size. The - encoded field metadata (from the master or source) is decoded and compared - to the size of this field (the slave or destination). + This method is used in row-based replication to verify that the + slave's field size is less than or equal to the master's field + size. The encoded field metadata (from the master or source) is + decoded and compared to the size of this field (the slave or + destination). + + @note + + The comparison is made so that if the source data (from the master) + is less than the target data (on the slave), -1 is returned in @c + <code>*order_var</code>. This implies that a conversion is + necessary, but that it is lossy and can result in truncation of the + value. + + If the source data is strictly greater than the target data, 1 is + returned in <code>*order_var</code>. This implies that the source + type can is contained in the target type and that a conversion is + necessary but is non-lossy. + + If no conversion is required to fit the source type in the target + type, 0 is returned in <code>*order_var</code>. @param field_metadata Encoded size in field metadata + @param mflags Flags from the table map event for the table. + @param order_var Pointer to variable where the order + between the source field and this field + will be returned. - @retval 0 if this field's size is < the source field's size - @retval 1 if this field's size is >= the source field's size + @return @c true if this field's size is compatible with the + master's field size, @c false otherwise. */ -int Field::compatible_field_size(uint field_metadata, - const Relay_log_info *rli_arg __attribute__((unused))) +bool Field::compatible_field_size(uint field_metadata, + Relay_log_info *rli_arg __attribute__((unused)), + uint16 mflags __attribute__((unused)), + int *order_var) { uint const source_size= pack_length_from_metadata(field_metadata); uint const destination_size= row_pack_length(); - return (source_size <= destination_size); + DBUG_PRINT("debug", ("real_type: %d, source_size: %u, destination_size: %u", + real_type(), source_size, destination_size)); + *order_var = compare(source_size, destination_size); + return true; } @@ -2304,13 +2345,7 @@ int Field_decimal::store(double nr) char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE]; fyllchar = zerofill ? (char) '0' : (char) ' '; -#ifdef HAVE_SNPRINTF - buff[sizeof(buff)-1]=0; // Safety - snprintf(buff,sizeof(buff)-1, "%.*f",(int) dec,nr); - length= strlen(buff); -#else - length= my_sprintf(buff,(buff,"%.*f",dec,nr)); -#endif + length= my_fcvt(nr, dec, buff, NULL); if (length > field_length) { @@ -2723,17 +2758,6 @@ int Field_new_decimal::store(double nr) err= double2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, nr, &decimal_value); - /* - TODO: fix following when double2my_decimal when double2decimal - will return E_DEC_TRUNCATED always correctly - */ - if (!err) - { - double nr2; - my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &nr2); - if (nr2 != nr) - err= E_DEC_TRUNCATED; - } if (err) { if (check_overflow(err)) @@ -2893,33 +2917,16 @@ uint Field_new_decimal::pack_length_from_metadata(uint field_metadata) } -/** - Check to see if field size is compatible with destination. - - This method is used in row-based replication to verify that the slave's - field size is less than or equal to the master's field size. The - encoded field metadata (from the master or source) is decoded and compared - to the size of this field (the slave or destination). - - @param field_metadata Encoded size in field metadata - - @retval 0 if this field's size is < the source field's size - @retval 1 if this field's size is >= the source field's size -*/ -int Field_new_decimal::compatible_field_size(uint field_metadata, - const Relay_log_info * __attribute__((unused))) +bool Field_new_decimal::compatible_field_size(uint field_metadata, + Relay_log_info * __attribute__((unused)), + uint16 mflags __attribute__((unused)), + int *order_var) { - int compatible= 0; uint const source_precision= (field_metadata >> 8U) & 0x00ff; uint const source_decimal= field_metadata & 0x00ff; - uint const source_size= my_decimal_get_binary_size(source_precision, - source_decimal); - uint const destination_size= row_pack_length(); - compatible= (source_size <= destination_size); - if (compatible) - compatible= (source_precision <= precision) && - (source_decimal <= decimals()); - return (compatible); + int order= compare(source_precision, precision); + *order_var= order != 0 ? order : compare(source_decimal, dec); + return true; } @@ -4231,67 +4238,20 @@ String *Field_float::val_str(String *val_buffer, uint to_length=max(field_length,70); val_buffer->alloc(to_length); char *to=(char*) val_buffer->ptr(); + size_t len; if (dec >= NOT_FIXED_DEC) - { - sprintf(to,"%-*.*g",(int) field_length,FLT_DIG,nr); - to=strcend(to,' '); - *to=0; - } + len= my_gcvt(nr, MY_GCVT_ARG_FLOAT, to_length - 1, to, NULL); else { -#ifdef HAVE_FCONVERT - char buff[70],*pos=buff; - int decpt,sign,tmp_dec=dec; - - VOID(sfconvert(&nr,tmp_dec,&decpt,&sign,buff)); - if (sign) - { - *to++='-'; - } - if (decpt < 0) - { /* val_buffer is < 0 */ - *to++='0'; - if (!tmp_dec) - goto end; - *to++='.'; - if (-decpt > tmp_dec) - decpt= - (int) tmp_dec; - tmp_dec=(uint) ((int) tmp_dec+decpt); - while (decpt++ < 0) - *to++='0'; - } - else if (decpt == 0) - { - *to++= '0'; - if (!tmp_dec) - goto end; - *to++='.'; - } - else - { - while (decpt-- > 0) - *to++= *pos++; - if (!tmp_dec) - goto end; - *to++='.'; - } - while (tmp_dec--) - *to++= *pos++; -#else -#ifdef HAVE_SNPRINTF - to[to_length-1]=0; // Safety - snprintf(to,to_length-1,"%.*f",dec,nr); - to=strend(to); -#else - to+= my_sprintf(to,(to,"%.*f",dec,nr)); -#endif -#endif + /* + We are safe here because the buffer length is >= 70, and + fabs(float) < 10^39, dec < NOT_FIXED_DEC. So the resulting string + will be not longer than 69 chars + terminating '\0'. + */ + len= my_fcvt(nr, dec, to, NULL); } -#ifdef HAVE_FCONVERT - end: -#endif - val_buffer->length((uint) (to-val_buffer->ptr())); + val_buffer->length((uint) len); if (zerofill) prepend_zeros(val_buffer); return val_buffer; @@ -4479,8 +4439,12 @@ int Field_real::truncate(double *nr, double max_value) max_value*= log_10[order]; max_value-= 1.0 / log_10[dec]; - double tmp= rint((res - floor(res)) * log_10[dec]) / log_10[dec]; - res= floor(res) + tmp; + /* Check for infinity so we don't get NaN in calculations */ + if (!my_isinf(res)) + { + double tmp= rint((res - floor(res)) * log_10[dec]) / log_10[dec]; + res= floor(res) + tmp; + } } if (res < -max_value) @@ -4590,68 +4554,14 @@ String *Field_double::val_str(String *val_buffer, uint to_length=max(field_length, DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE); val_buffer->alloc(to_length); char *to=(char*) val_buffer->ptr(); + size_t len; if (dec >= NOT_FIXED_DEC) - { - sprintf(to,"%-*.*g",(int) field_length,DBL_DIG,nr); - to=strcend(to,' '); - } + len= my_gcvt(nr, MY_GCVT_ARG_DOUBLE, to_length - 1, to, NULL); else - { -#ifdef HAVE_FCONVERT - char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE]; - char *pos= buff; - int decpt,sign,tmp_dec=dec; - - VOID(fconvert(nr,tmp_dec,&decpt,&sign,buff)); - if (sign) - { - *to++='-'; - } - if (decpt < 0) - { /* val_buffer is < 0 */ - *to++='0'; - if (!tmp_dec) - goto end; - *to++='.'; - if (-decpt > tmp_dec) - decpt= - (int) tmp_dec; - tmp_dec=(uint) ((int) tmp_dec+decpt); - while (decpt++ < 0) - *to++='0'; - } - else if (decpt == 0) - { - *to++= '0'; - if (!tmp_dec) - goto end; - *to++='.'; - } - else - { - while (decpt-- > 0) - *to++= *pos++; - if (!tmp_dec) - goto end; - *to++='.'; - } - while (tmp_dec--) - *to++= *pos++; -#else -#ifdef HAVE_SNPRINTF - to[to_length-1]=0; // Safety - snprintf(to,to_length-1,"%.*f",dec,nr); - to=strend(to); -#else - to+= my_sprintf(to,(to,"%.*f",dec,nr)); -#endif -#endif - } -#ifdef HAVE_FCONVERT - end: -#endif + len= my_fcvt(nr, dec, to, NULL); - val_buffer->length((uint) (to-val_buffer->ptr())); + val_buffer->length((uint) len); if (zerofill) prepend_zeros(val_buffer); return val_buffer; @@ -6448,84 +6358,18 @@ int Field_str::store(double nr) { ASSERT_COLUMN_MARKED_FOR_WRITE; char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE]; - uint length; uint local_char_length= field_length / charset()->mbmaxlen; - double anr= fabs(nr); - bool fractional= (anr != floor(anr)); - int neg= (nr < 0.0) ? 1 : 0; - uint max_length; - int exp; - uint digits; - uint i; - - /* Calculate the exponent from the 'e'-format conversion */ - if (anr < 1.0 && anr > 0) - { - for (exp= 0; anr < 1e-100; exp-= 100, anr*= 1e100) ; - for (; anr < 1e-10; exp-= 10, anr*= 1e10) ; - for (i= 1; anr < 1 / log_10[i]; exp--, i++) ; - exp--; - } - else - { - for (exp= 0; anr > 1e100; exp+= 100, anr/= 1e100) ; - for (; anr > 1e10; exp+= 10, anr/= 1e10) ; - for (i= 1; anr > log_10[i]; exp++, i++) ; - } - - max_length= local_char_length - neg; - - /* - Since in sprintf("%g") precision means the number of significant digits, - calculate the maximum number of significant digits if the 'f'-format - would be used (+1 for decimal point if the number has a fractional part). - */ - digits= max(1, (int) max_length - fractional); - /* - If the exponent is negative, decrease digits by the number of leading zeros - after the decimal point that do not count as significant digits. - */ - if (exp < 0) - digits= max(1, (int) digits + exp); - /* - 'e'-format is used only if the exponent is less than -4 or greater than or - equal to the precision. In this case we need to adjust the number of - significant digits to take "e+NN" + decimal point into account (hence -5). - We also have to reserve one additional character if abs(exp) >= 100. - */ - if (exp >= (int) digits || exp < -4) - digits= max(1, (int) (max_length - 5 - (exp >= 100 || exp <= -100))); - - /* Limit precision to DBL_DIG to avoid garbage past significant digits */ - set_if_smaller(digits, DBL_DIG); - - length= (uint) my_sprintf(buff, (buff, "%-.*g", digits, nr)); + size_t length; + my_bool error; -#ifdef __WIN__ - /* - Windows always zero-pads the exponent to 3 digits, we want to remove the - leading 0 to match the sprintf() output on other platforms. - */ - if ((exp >= (int) digits || exp < -4) && exp > -100 && exp < 100) + length= my_gcvt(nr, MY_GCVT_ARG_DOUBLE, local_char_length, buff, &error); + if (error) { - DBUG_ASSERT(length >= 6); /* 1e+NNN */ - uint tmp= length - 3; - buff[tmp]= buff[tmp + 1]; - tmp++; - buff[tmp]= buff[tmp + 1]; - length--; + if (table->in_use->abort_on_warning) + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_DATA_TOO_LONG, 1); + else + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); } -#endif - - /* - +1 below is because "precision" in %g above means the - max. number of significant digits, not the output width. - Thus the width can be larger than number of significant digits by 1 - (for decimal point) - the test for local_char_length < 5 is for extreme cases, - like inserting 500.0 in char(1) - */ - DBUG_ASSERT(local_char_length < 5 || length <= local_char_length+1); return store(buff, length, charset()); } @@ -6675,8 +6519,11 @@ check_field_for_37426(const void *param_arg) } #endif -int Field_string::compatible_field_size(uint field_metadata, - const Relay_log_info *rli_arg) +bool +Field_string::compatible_field_size(uint field_metadata, + Relay_log_info *rli_arg, + uint16 mflags __attribute__((unused)), + int *order_var) { #ifdef HAVE_REPLICATION const Check_field_param check_param = { this }; @@ -6684,7 +6531,7 @@ int Field_string::compatible_field_size(uint field_metadata, check_field_for_37426, &check_param)) return FALSE; // Not compatible field sizes #endif - return Field::compatible_field_size(field_metadata, rli_arg); + return Field::compatible_field_size(field_metadata, rli_arg, mflags, order_var); } @@ -6745,6 +6592,8 @@ uchar *Field_string::pack(uchar *to, const uchar *from, { uint length= min(field_length,max_length); uint local_char_length= max_length/field_charset->mbmaxlen; + DBUG_PRINT("debug", ("Packing field '%s' - length: %u ", field_name, length)); + if (length > local_char_length) local_char_length= my_charpos(field_charset, from, from+length, local_char_length); @@ -6863,86 +6712,6 @@ int Field_string::do_save_field_metadata(uchar *metadata_ptr) } -/* - Compare two packed keys - - SYNOPSIS - pack_cmp() - a New key - b Original key - length Key length - insert_or_update 1 if this is an insert or update - - RETURN - < 0 a < b - 0 a = b - > 0 a > b -*/ - -int Field_string::pack_cmp(const uchar *a, const uchar *b, uint length, - my_bool insert_or_update) -{ - uint a_length, b_length; - if (length > 255) - { - a_length= uint2korr(a); - b_length= uint2korr(b); - a+= 2; - b+= 2; - } - else - { - a_length= (uint) *a++; - b_length= (uint) *b++; - } - return field_charset->coll->strnncollsp(field_charset, - a, a_length, - b, b_length, - insert_or_update); -} - - -/** - Compare a packed key against row. - - @param key Original key - @param length Key length. (May be less than field length) - @param insert_or_update 1 if this is an insert or update - - @return - < 0 row < key - @return - 0 row = key - @return - > 0 row > key -*/ - -int Field_string::pack_cmp(const uchar *key, uint length, - my_bool insert_or_update) -{ - uint row_length, local_key_length; - uchar *end; - if (length > 255) - { - local_key_length= uint2korr(key); - key+= 2; - } - else - local_key_length= (uint) *key++; - - /* Only use 'length' of key, not field_length */ - end= ptr + length; - while (end > ptr && end[-1] == ' ') - end--; - row_length= (uint) (end - ptr); - - return field_charset->coll->strnncollsp(field_charset, - ptr, row_length, - key, local_key_length, - insert_or_update); -} - - uint Field_string::packed_col_length(const uchar *data_ptr, uint length) { if (length > 255) @@ -7302,90 +7071,6 @@ uchar *Field_varstring::pack(uchar *to, const uchar *from, } -uchar * -Field_varstring::pack_key(uchar *to, const uchar *key, uint max_length, - bool low_byte_first __attribute__((unused))) -{ - uint length= length_bytes == 1 ? (uint) *key : uint2korr(key); - uint local_char_length= ((field_charset->mbmaxlen > 1) ? - max_length/field_charset->mbmaxlen : max_length); - key+= length_bytes; - if (length > local_char_length) - { - local_char_length= my_charpos(field_charset, key, key+length, - local_char_length); - set_if_smaller(length, local_char_length); - } - *to++= (char) (length & 255); - if (max_length > 255) - *to++= (char) (length >> 8); - if (length) - memcpy(to, key, length); - return to+length; -} - - -/** - Unpack a key into a record buffer. - - A VARCHAR key has a maximum size of 64K-1. - In its packed form, the length field is one or two bytes long, - depending on 'max_length'. - - @param to Pointer into the record buffer. - @param key Pointer to the packed key. - @param max_length Key length limit from key description. - - @return - Pointer to end of 'key' (To the next key part if multi-segment key) -*/ - -const uchar * -Field_varstring::unpack_key(uchar *to, const uchar *key, uint max_length, - bool low_byte_first __attribute__((unused))) -{ - /* get length of the blob key */ - uint32 length= *key++; - if (max_length > 255) - length+= (*key++) << 8; - - /* put the length into the record buffer */ - if (length_bytes == 1) - *ptr= (uchar) length; - else - int2store(ptr, length); - memcpy(ptr + length_bytes, key, length); - return key + length; -} - -/** - Create a packed key that will be used for storage in the index tree. - - @param to Store packed key segment here - @param from Key segment (as given to index_read()) - @param max_length Max length of key - - @return - end of key storage -*/ - -uchar * -Field_varstring::pack_key_from_key_image(uchar *to, const uchar *from, uint max_length, - bool low_byte_first __attribute__((unused))) -{ - /* Key length is always stored as 2 bytes */ - uint length= uint2korr(from); - if (length > max_length) - length= max_length; - *to++= (char) (length & 255); - if (max_length > 255) - *to++= (char) (length >> 8); - if (length) - memcpy(to, from+HA_KEY_BLOB_LENGTH, length); - return to+length; -} - - /** Unpack a varstring field from row data. @@ -7428,59 +7113,6 @@ Field_varstring::unpack(uchar *to, const uchar *from, } -int Field_varstring::pack_cmp(const uchar *a, const uchar *b, - uint key_length_arg, - my_bool insert_or_update) -{ - uint a_length, b_length; - if (key_length_arg > 255) - { - a_length=uint2korr(a); a+= 2; - b_length=uint2korr(b); b+= 2; - } - else - { - a_length= (uint) *a++; - b_length= (uint) *b++; - } - return field_charset->coll->strnncollsp(field_charset, - a, a_length, - b, b_length, - insert_or_update); -} - - -int Field_varstring::pack_cmp(const uchar *b, uint key_length_arg, - my_bool insert_or_update) -{ - uchar *a= ptr+ length_bytes; - uint a_length= length_bytes == 1 ? (uint) *ptr : uint2korr(ptr); - uint b_length; - uint local_char_length= ((field_charset->mbmaxlen > 1) ? - key_length_arg / field_charset->mbmaxlen : - key_length_arg); - - if (key_length_arg > 255) - { - b_length=uint2korr(b); b+= HA_KEY_BLOB_LENGTH; - } - else - b_length= (uint) *b++; - - if (a_length > local_char_length) - { - local_char_length= my_charpos(field_charset, a, a+a_length, - local_char_length); - set_if_smaller(a_length, local_char_length); - } - - return field_charset->coll->strnncollsp(field_charset, - a, a_length, - b, b_length, - insert_or_update); -} - - uint Field_varstring::packed_col_length(const uchar *data_ptr, uint length) { if (length > 255) @@ -7624,6 +7256,7 @@ Field_blob::Field_blob(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg, cs), packlength(blob_pack_length) { + DBUG_ASSERT(blob_pack_length <= 4); // Only pack lengths 1-4 supported currently flags|= BLOB_FLAG; share->blob_fields++; /* TODO: why do not fill table->s->blob_field array here? */ @@ -7818,7 +7451,7 @@ oom_error: int Field_blob::store(double nr) { CHARSET_INFO *cs=charset(); - value.set_real(nr, 2, cs); + value.set_real(nr, NOT_FIXED_DEC, cs); return Field_blob::store(value.ptr(),(uint) value.length(), cs); } @@ -8034,8 +7667,10 @@ int Field_blob::key_cmp(const uchar *a,const uchar *b) */ int Field_blob::do_save_field_metadata(uchar *metadata_ptr) { + DBUG_ENTER("Field_blob::do_save_field_metadata"); *metadata_ptr= pack_length_no_ptr(); - return 1; + DBUG_PRINT("debug", ("metadata: %u (pack_length_no_ptr)", *metadata_ptr)); + DBUG_RETURN(1); } @@ -8179,139 +7814,6 @@ const uchar *Field_blob::unpack(uchar *to, DBUG_RETURN(from + master_packlength + length); } -/* Keys for blobs are like keys on varchars */ - -int Field_blob::pack_cmp(const uchar *a, const uchar *b, uint key_length_arg, - my_bool insert_or_update) -{ - uint a_length, b_length; - if (key_length_arg > 255) - { - a_length=uint2korr(a); a+=2; - b_length=uint2korr(b); b+=2; - } - else - { - a_length= (uint) *a++; - b_length= (uint) *b++; - } - return field_charset->coll->strnncollsp(field_charset, - a, a_length, - b, b_length, - insert_or_update); -} - - -int Field_blob::pack_cmp(const uchar *b, uint key_length_arg, - my_bool insert_or_update) -{ - uchar *a; - uint a_length, b_length; - memcpy_fixed(&a,ptr+packlength,sizeof(char*)); - if (!a) - return key_length_arg > 0 ? -1 : 0; - - a_length= get_length(ptr); - if (key_length_arg > 255) - { - b_length= uint2korr(b); b+=2; - } - else - b_length= (uint) *b++; - return field_charset->coll->strnncollsp(field_charset, - a, a_length, - b, b_length, - insert_or_update); -} - -/** Create a packed key that will be used for storage from a MySQL row. */ - -uchar * -Field_blob::pack_key(uchar *to, const uchar *from, uint max_length, - bool low_byte_first __attribute__((unused))) -{ - uchar *save= ptr; - ptr= (uchar*) from; - uint32 length=get_length(); // Length of from string - uint local_char_length= ((field_charset->mbmaxlen > 1) ? - max_length/field_charset->mbmaxlen : max_length); - if (length) - get_ptr((uchar**) &from); - if (length > local_char_length) - local_char_length= my_charpos(field_charset, from, from+length, - local_char_length); - set_if_smaller(length, local_char_length); - *to++= (uchar) length; - if (max_length > 255) // 2 byte length - *to++= (uchar) (length >> 8); - memcpy(to, from, length); - ptr=save; // Restore org row pointer - return to+length; -} - - -/** - Unpack a blob key into a record buffer. - - A blob key has a maximum size of 64K-1. - In its packed form, the length field is one or two bytes long, - depending on 'max_length'. - Depending on the maximum length of a blob, its length field is - put into 1 to 4 bytes. This is a property of the blob object, - described by 'packlength'. - Blobs are internally stored apart from the record buffer, which - contains a pointer to the blob buffer. - - - @param to Pointer into the record buffer. - @param from Pointer to the packed key. - @param max_length Key length limit from key description. - - @return - Pointer into 'from' past the last byte copied from packed key. -*/ - -const uchar * -Field_blob::unpack_key(uchar *to, const uchar *from, uint max_length, - bool low_byte_first __attribute__((unused))) -{ - /* get length of the blob key */ - uint32 length= *from++; - if (max_length > 255) - length+= *from++ << 8; - - /* put the length into the record buffer */ - put_length(to, length); - - /* put the address of the blob buffer or NULL */ - if (length) - memcpy_fixed(to + packlength, &from, sizeof(from)); - else - bzero(to + packlength, sizeof(from)); - - /* point to first byte of next field in 'from' */ - return from + length; -} - - -/** Create a packed key that will be used for storage from a MySQL key. */ - -uchar * -Field_blob::pack_key_from_key_image(uchar *to, const uchar *from, uint max_length, - bool low_byte_first __attribute__((unused))) -{ - uint length=uint2korr(from); - if (length > max_length) - length=max_length; - *to++= (char) (length & 255); - if (max_length > 255) - *to++= (char) (length >> 8); - if (length) - memcpy(to, from+HA_KEY_BLOB_LENGTH, length); - return to+length; -} - - uint Field_blob::packed_col_length(const uchar *data_ptr, uint length) { if (length > 255) @@ -8975,6 +8477,9 @@ Field_bit::Field_bit(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, bit_ptr(bit_ptr_arg), bit_ofs(bit_ofs_arg), bit_len(len_arg & 7), bytes_in_rec(len_arg / 8) { + DBUG_ENTER("Field_bit::Field_bit"); + DBUG_PRINT("enter", ("ptr_arg: %p, null_ptr_arg: %p, len_arg: %u, bit_len: %u, bytes_in_rec: %u", + ptr_arg, null_ptr_arg, len_arg, bit_len, bytes_in_rec)); flags|= UNSIGNED_FLAG; /* Ensure that Field::eq() can distinguish between two different bit fields. @@ -8982,6 +8487,7 @@ Field_bit::Field_bit(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, */ if (!null_ptr_arg) null_bit= bit_ofs_arg; + DBUG_VOID_RETURN; } @@ -9266,9 +8772,17 @@ uint Field_bit::get_key_image(uchar *buff, uint length, imagetype type_arg) */ int Field_bit::do_save_field_metadata(uchar *metadata_ptr) { - *metadata_ptr= bit_len; - *(metadata_ptr + 1)= bytes_in_rec; - return 2; + DBUG_ENTER("Field_bit::do_save_field_metadata"); + DBUG_PRINT("debug", ("bit_len: %d, bytes_in_rec: %d", + bit_len, bytes_in_rec)); + /* + Since this class and Field_bit_as_char have different ideas of + what should be stored here, we compute the values of the metadata + explicitly using the field_length. + */ + metadata_ptr[0]= field_length % 8; + metadata_ptr[1]= field_length / 8; + DBUG_RETURN(2); } @@ -9293,34 +8807,34 @@ uint Field_bit::pack_length_from_metadata(uint field_metadata) } -/** - Check to see if field size is compatible with destination. - - This method is used in row-based replication to verify that the slave's - field size is less than or equal to the master's field size. The - encoded field metadata (from the master or source) is decoded and compared - to the size of this field (the slave or destination). +bool +Field_bit::compatible_field_size(uint field_metadata, + Relay_log_info * __attribute__((unused)), + uint16 mflags, + int *order_var) +{ + DBUG_ENTER("Field_bit::compatible_field_size"); + DBUG_ASSERT((field_metadata >> 16) == 0); + uint from_bit_len= + 8 * (field_metadata >> 8) + (field_metadata & 0xff); + uint to_bit_len= max_display_length(); + DBUG_PRINT("debug", ("from_bit_len: %u, to_bit_len: %u", + from_bit_len, to_bit_len)); + /* + If the bit length exact flag is clear, we are dealing with an old + master, so we allow some less strict behaviour if replicating by + moving both bit lengths to an even multiple of 8. - @param field_metadata Encoded size in field metadata + We do this by computing the number of bytes to store the field + instead, and then compare the result. + */ + if (!(mflags & Table_map_log_event::TM_BIT_LEN_EXACT_F)) { + from_bit_len= (from_bit_len + 7) / 8; + to_bit_len= (to_bit_len + 7) / 8; + } - @retval 0 if this field's size is < the source field's size - @retval 1 if this field's size is >= the source field's size -*/ -int Field_bit::compatible_field_size(uint field_metadata, - const Relay_log_info * __attribute__((unused))) -{ - int compatible= 0; - uint const source_size= pack_length_from_metadata(field_metadata); - uint const destination_size= row_pack_length(); - uint const from_bit_len= field_metadata & 0x00ff; - uint const from_len= (field_metadata >> 8U) & 0x00ff; - if ((bit_len == 0) || (from_bit_len == 0)) - compatible= (source_size <= destination_size); - else if (from_bit_len > bit_len) - compatible= (from_len < bytes_in_rec); - else - compatible= ((from_bit_len <= bit_len) && (from_len <= bytes_in_rec)); - return (compatible); + *order_var= compare(from_bit_len, to_bit_len); + DBUG_RETURN(TRUE); } @@ -9386,8 +8900,15 @@ const uchar * Field_bit::unpack(uchar *to, const uchar *from, uint param_data, bool low_byte_first __attribute__((unused))) { + DBUG_ENTER("Field_bit::unpack"); + DBUG_PRINT("enter", ("to: %p, from: %p, param_data: 0x%x", + to, from, param_data)); + DBUG_PRINT("debug", ("bit_ptr: %p, bit_len: %u, bit_ofs: %u", + bit_ptr, bit_len, bit_ofs)); uint const from_len= (param_data >> 8U) & 0x00ff; uint const from_bit_len= param_data & 0x00ff; + DBUG_PRINT("debug", ("from_len: %u, from_bit_len: %u", + from_len, from_bit_len)); /* If the parameter data is zero (i.e., undefined), or if the master and slave have the same sizes, then use the old unpack() method. @@ -9408,7 +8929,7 @@ Field_bit::unpack(uchar *to, const uchar *from, uint param_data, from++; } memcpy(to, from, bytes_in_rec); - return from + bytes_in_rec; + DBUG_RETURN(from + bytes_in_rec); } /* @@ -9434,7 +8955,7 @@ Field_bit::unpack(uchar *to, const uchar *from, uint param_data, bitmap_set_bit(table->write_set,field_index); store(value, new_len, system_charset_info); my_afree(value); - return from + len; + DBUG_RETURN(from + len); } @@ -9562,8 +9083,11 @@ void Create_field::create_length_to_internal_length(void) */ void Create_field::init_for_tmp_table(enum_field_types sql_type_arg, uint32 length_arg, uint32 decimals_arg, - bool maybe_null, bool is_unsigned) + bool maybe_null, bool is_unsigned, + uint pack_length) { + DBUG_ENTER("Create_field::init_for_tmp_table"); + field_name= ""; sql_type= sql_type_arg; char_length= length= length_arg;; @@ -9571,10 +9095,92 @@ void Create_field::init_for_tmp_table(enum_field_types sql_type_arg, interval= 0; charset= &my_charset_bin; geom_type= Field::GEOM_GEOMETRY; - pack_flag= (FIELDFLAG_NUMBER | - ((decimals_arg & FIELDFLAG_MAX_DEC) << FIELDFLAG_DEC_SHIFT) | - (maybe_null ? FIELDFLAG_MAYBE_NULL : 0) | - (is_unsigned ? 0 : FIELDFLAG_DECIMAL)); + + DBUG_PRINT("enter", ("sql_type: %d, length: %u, pack_length: %u", + sql_type_arg, length_arg, pack_length)); + + /* + These pack flags are crafted to get it correctly through the + branches of make_field(). + */ + switch (sql_type_arg) + { + case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_SET: + pack_flag= 0; + break; + + case MYSQL_TYPE_GEOMETRY: + pack_flag= FIELDFLAG_GEOM; + break; + + case MYSQL_TYPE_ENUM: + pack_flag= FIELDFLAG_INTERVAL; + break; + + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + pack_flag= FIELDFLAG_DECIMAL | FIELDFLAG_NUMBER | + (decimals_arg & FIELDFLAG_MAX_DEC) << FIELDFLAG_DEC_SHIFT; + break; + + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_BLOB: + pack_flag= FIELDFLAG_BLOB; + break; + + case MYSQL_TYPE_BIT: + pack_flag= FIELDFLAG_NUMBER | FIELDFLAG_TREAT_BIT_AS_CHAR; + break; + + default: + pack_flag= FIELDFLAG_NUMBER; + break; + } + + /* + Set the pack flag correctly for the blob-like types. This sets the + packtype to something that make_field can use. If the pack type is + not set correctly, the packlength will be reeeeally wierd (like + 129 or so). + */ + switch (sql_type_arg) + { + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_SET: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_GEOMETRY: + // If you are going to use the above types, you have to pass a + // pack_length as parameter. Assert that is really done. + DBUG_ASSERT(pack_length != ~0U); + pack_flag|= pack_length_to_packflag(pack_length); + break; + default: + /* Nothing */ + break; + } + + pack_flag|= + (maybe_null ? FIELDFLAG_MAYBE_NULL : 0) | + (is_unsigned ? 0 : FIELDFLAG_DECIMAL); + + DBUG_PRINT("debug", ("pack_flag: %s%s%s%s%s, pack_type: %d", + FLAGSTR(pack_flag, FIELDFLAG_BINARY), + FLAGSTR(pack_flag, FIELDFLAG_NUMBER), + FLAGSTR(pack_flag, FIELDFLAG_INTERVAL), + FLAGSTR(pack_flag, FIELDFLAG_GEOM), + FLAGSTR(pack_flag, FIELDFLAG_BLOB), + f_packtype(pack_flag))); + DBUG_VOID_RETURN; } @@ -10080,6 +9686,14 @@ Field *make_field(TABLE_SHARE *share, uchar *ptr, uint32 field_length, default: break; } + DBUG_PRINT("debug", ("field_type: %d, field_length: %u, interval: %p, pack_flag: %s%s%s%s%s", + field_type, field_length, interval, + FLAGSTR(pack_flag, FIELDFLAG_BINARY), + FLAGSTR(pack_flag, FIELDFLAG_INTERVAL), + FLAGSTR(pack_flag, FIELDFLAG_NUMBER), + FLAGSTR(pack_flag, FIELDFLAG_PACK), + FLAGSTR(pack_flag, FIELDFLAG_BLOB))); + if (f_is_alpha(pack_flag)) { if (!f_is_packed(pack_flag)) diff --git a/sql/field.h b/sql/field.h index 8cfed9647f7..c30bbfae879 100644 --- a/sql/field.h +++ b/sql/field.h @@ -25,7 +25,6 @@ #pragma interface /* gcc class implementation */ #endif -#define NOT_FIXED_DEC 31 #define DATETIME_DEC 6 const uint32 max_field_size= (uint32) 4294967295U; @@ -167,22 +166,13 @@ public: table, which is located on disk). */ virtual uint32 pack_length_in_rec() const { return pack_length(); } - virtual int compatible_field_size(uint field_metadata, - const Relay_log_info *); + virtual bool compatible_field_size(uint metadata, Relay_log_info *rli, + uint16 mflags, int *order); virtual uint pack_length_from_metadata(uint field_metadata) - { return field_metadata; } - /* - This method is used to return the size of the data in a row-based - replication row record. The default implementation of returning 0 is - designed to allow fields that do not use metadata to return TRUE (1) - from compatible_field_size() which uses this function in the comparison. - The default value for field metadata for fields that do not have - metadata is 0. Thus, 0 == 0 means the fields are compatible in size. - - Note: While most classes that override this method return pack_length(), - the classes Field_string, Field_varstring, and Field_blob return - field_length + 1, field_length, and pack_length_no_ptr() respectfully. - */ + { + DBUG_ENTER("Field::pack_length_from_metadata"); + DBUG_RETURN(field_metadata); + } virtual uint row_pack_length() { return 0; } virtual int save_field_metadata(uchar *first_byte) { return do_save_field_metadata(first_byte); } @@ -410,32 +400,11 @@ public: DBUG_RETURN(result); } - virtual uchar *pack_key(uchar* to, const uchar *from, - uint max_length, bool low_byte_first) - { - return pack(to, from, max_length, low_byte_first); - } - virtual uchar *pack_key_from_key_image(uchar* to, const uchar *from, - uint max_length, bool low_byte_first) - { - return pack(to, from, max_length, low_byte_first); - } - virtual const uchar *unpack_key(uchar* to, const uchar *from, - uint max_length, bool low_byte_first) - { - return unpack(to, from, max_length, low_byte_first); - } virtual uint packed_col_length(const uchar *to, uint length) { return length;} virtual uint max_packed_col_length(uint max_length) { return max_length;} - virtual int pack_cmp(const uchar *a,const uchar *b, uint key_length_arg, - my_bool insert_or_update) - { return cmp(a,b); } - virtual int pack_cmp(const uchar *b, uint key_length_arg, - my_bool insert_or_update) - { return cmp(ptr,b); } uint offset(uchar *record) { return (uint) (ptr - record); @@ -641,6 +610,13 @@ public: int store_decimal(const my_decimal *); my_decimal *val_decimal(my_decimal *); uint is_equal(Create_field *new_field); + uint row_pack_length() { return pack_length(); } + uint32 pack_length_from_metadata(uint field_metadata) { + uint32 length= pack_length(); + DBUG_PRINT("result", ("pack_length_from_metadata(%d): %u", + field_metadata, length)); + return length; + } int check_int(CHARSET_INFO *cs, const char *str, int length, const char *int_end, int error); bool get_int(CHARSET_INFO *cs, const char *from, uint len, @@ -805,8 +781,8 @@ public: uint32 pack_length() const { return (uint32) bin_size; } uint pack_length_from_metadata(uint field_metadata); uint row_pack_length() { return pack_length(); } - int compatible_field_size(uint field_metadata, - const Relay_log_info *rli); + bool compatible_field_size(uint field_metadata, Relay_log_info *rli, + uint16 mflags, int *order_var); uint is_equal(Create_field *new_field); virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data, bool low_byte_first); @@ -1501,9 +1477,9 @@ public: return row_pack_length(); return (((field_metadata >> 4) & 0x300) ^ 0x300) + (field_metadata & 0x00ff); } - int compatible_field_size(uint field_metadata, - const Relay_log_info *rli); - uint row_pack_length() { return (field_length + 1); } + bool compatible_field_size(uint field_metadata, Relay_log_info *rli, + uint16 mflags, int *order_var); + uint row_pack_length() { return field_length; } int pack_cmp(const uchar *a,const uchar *b,uint key_length, my_bool insert_or_update); int pack_cmp(const uchar *b,uint key_length,my_bool insert_or_update); @@ -1580,16 +1556,8 @@ public: void sql_type(String &str) const; virtual uchar *pack(uchar *to, const uchar *from, uint max_length, bool low_byte_first); - uchar *pack_key(uchar *to, const uchar *from, uint max_length, bool low_byte_first); - uchar *pack_key_from_key_image(uchar* to, const uchar *from, - uint max_length, bool low_byte_first); virtual const uchar *unpack(uchar* to, const uchar *from, uint param_data, bool low_byte_first); - const uchar *unpack_key(uchar* to, const uchar *from, - uint max_length, bool low_byte_first); - int pack_cmp(const uchar *a, const uchar *b, uint key_length, - my_bool insert_or_update); - int pack_cmp(const uchar *b, uint key_length,my_bool insert_or_update); int cmp_binary(const uchar *a,const uchar *b, uint32 max_length=~0L); int key_cmp(const uchar *,const uchar*); int key_cmp(const uchar *str, uint length); @@ -1765,17 +1733,8 @@ public: } virtual uchar *pack(uchar *to, const uchar *from, uint max_length, bool low_byte_first); - uchar *pack_key(uchar *to, const uchar *from, - uint max_length, bool low_byte_first); - uchar *pack_key_from_key_image(uchar* to, const uchar *from, - uint max_length, bool low_byte_first); virtual const uchar *unpack(uchar *to, const uchar *from, uint param_data, bool low_byte_first); - const uchar *unpack_key(uchar* to, const uchar *from, - uint max_length, bool low_byte_first); - int pack_cmp(const uchar *a, const uchar *b, uint key_length, - my_bool insert_or_update); - int pack_cmp(const uchar *b, uint key_length,my_bool insert_or_update); uint packed_col_length(const uchar *col_ptr, uint length); uint max_packed_col_length(uint max_length); void free() { value.free(); } @@ -1973,8 +1932,8 @@ public: uint pack_length_from_metadata(uint field_metadata); uint row_pack_length() { return (bytes_in_rec + ((bit_len > 0) ? 1 : 0)); } - int compatible_field_size(uint field_metadata, - const Relay_log_info *rli); + bool compatible_field_size(uint metadata, Relay_log_info *rli, + uint16 mflags, int *order_var); void sql_type(String &str) const; virtual uchar *pack(uchar *to, const uchar *from, uint max_length, bool low_byte_first); @@ -2077,7 +2036,8 @@ public: /* Init for a tmp table field. To be extended if need be. */ void init_for_tmp_table(enum_field_types sql_type_arg, uint32 max_length, uint32 decimals, - bool maybe_null, bool is_unsigned); + bool maybe_null, bool is_unsigned, + uint pack_length = ~0U); bool init(THD *thd, char *field_name, enum_field_types type, char *length, char *decimals, uint type_modifier, Item *default_value, diff --git a/sql/filesort.cc b/sql/filesort.cc index 9528d10dba7..79887577f8f 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright (C) 2000-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1121,8 +1121,9 @@ uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek, if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count))) { - if (my_pread(fromfile->file,(uchar*) buffpek->base, - (length= rec_length*count),buffpek->file_pos,MYF_RW)) + if (mysql_file_pread(fromfile->file, (uchar*) buffpek->base, + (length= rec_length*count), + buffpek->file_pos, MYF_RW)) return((uint) -1); /* purecov: inspected */ buffpek->key=buffpek->base; buffpek->file_pos+= length; /* New filepos */ @@ -1320,7 +1321,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file, if (!(error= (int) read_to_buffer(from_file,buffpek, rec_length))) { - VOID(queue_remove(&queue,0)); + (void) queue_remove(&queue,0); reuse_freed_buff(&queue, buffpek, rec_length); break; /* One buffer have been removed */ } diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 83cceb0da76..63716e8960e 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -56,26 +56,125 @@ int ha_ndb_dummy; #define assert(x) do { if(x) break; ::printf("%s %d: assert failed: %s\n", __FILE__, __LINE__, #x); ::fflush(stdout); ::signal(SIGABRT,SIG_DFL); ::abort(); ::kill(::getpid(),6); ::kill(::getpid(),9); } while (0) #endif -// options from from mysqld.cc -extern my_bool opt_ndb_optimized_node_selection; -extern const char *opt_ndbcluster_connectstring; -extern ulong opt_ndb_cache_check_time; - -// ndb interface initialization/cleanup -#ifdef __cplusplus -extern "C" { -#endif -extern void ndb_init_internal(); -extern void ndb_end_internal(); -#ifdef __cplusplus -} -#endif - -const char *ndb_distribution_names[]= {"KEYHASH", "LINHASH", NullS}; -TYPELIB ndb_distribution_typelib= { array_elements(ndb_distribution_names)-1, - "", ndb_distribution_names, NULL }; -const char *opt_ndb_distribution= ndb_distribution_names[ND_KEYHASH]; -enum ndb_distribution opt_ndb_distribution_id= ND_KEYHASH; +// ndb interface initialization/cleanup functions +extern "C" void ndb_init_internal(); +extern "C" void ndb_end_internal(); + +static const int DEFAULT_PARALLELISM= 0; +static const ha_rows DEFAULT_AUTO_PREFETCH= 32; +static const ulong ONE_YEAR_IN_SECONDS= (ulong) 3600L*24L*365L; + +ulong opt_ndb_extra_logging; +static ulong opt_ndb_cache_check_time; +static char* opt_ndb_connectstring; +static char* opt_ndb_mgmd_host; +static uint opt_ndb_nodeid; + + +static MYSQL_THDVAR_UINT( + autoincrement_prefetch_sz, /* name */ + PLUGIN_VAR_RQCMDARG, + "Specify number of autoincrement values that are prefetched.", + NULL, /* check func. */ + NULL, /* update func. */ + 1, /* default */ + 1, /* min */ + 256, /* max */ + 0 /* block */ +); + + +static MYSQL_THDVAR_BOOL( + force_send, /* name */ + PLUGIN_VAR_OPCMDARG, + "Force send of buffers to ndb immediately without waiting for " + "other threads.", + NULL, /* check func. */ + NULL, /* update func. */ + 1 /* default */ +); + + +static MYSQL_THDVAR_BOOL( + use_exact_count, /* name */ + PLUGIN_VAR_OPCMDARG, + "Use exact records count during query planning and for fast " + "select count(*), disable for faster queries.", + NULL, /* check func. */ + NULL, /* update func. */ + 1 /* default */ +); + + +static MYSQL_THDVAR_BOOL( + use_transactions, /* name */ + PLUGIN_VAR_OPCMDARG, + "Use transactions for large inserts, if enabled then large " + "inserts will be split into several smaller transactions", + NULL, /* check func. */ + NULL, /* update func. */ + 1 /* default */ +); + + +static MYSQL_THDVAR_BOOL( + use_copying_alter_table, /* name */ + PLUGIN_VAR_OPCMDARG, + "Force ndbcluster to always copy tables at alter table (should " + "only be used if on-line alter table fails).", + NULL, /* check func. */ + NULL, /* update func. */ + 0 /* default */ +); + + +static MYSQL_THDVAR_UINT( + optimized_node_selection, /* name */ + PLUGIN_VAR_OPCMDARG, + "Select nodes for transactions in a more optimal way.", + NULL, /* check func. */ + NULL, /* update func. */ + 3, /* default */ + 0, /* min */ + 3, /* max */ + 0 /* block */ +); + + +static MYSQL_THDVAR_BOOL( + index_stat_enable, /* name */ + PLUGIN_VAR_OPCMDARG, + "Use ndb index statistics in query optimization.", + NULL, /* check func. */ + NULL, /* update func. */ + FALSE /* default */ +); + + +static MYSQL_THDVAR_ULONG( + index_stat_cache_entries, /* name */ + PLUGIN_VAR_NOCMDARG, + "", + NULL, /* check func. */ + NULL, /* update func. */ + 32, /* default */ + 0, /* min */ + ULONG_MAX, /* max */ + 0 /* block */ +); + + +static MYSQL_THDVAR_ULONG( + index_stat_update_freq, /* name */ + PLUGIN_VAR_NOCMDARG, + "", + NULL, /* check func. */ + NULL, /* update func. */ + 20, /* default */ + 0, /* min */ + ULONG_MAX, /* max */ + 0 /* block */ +); // Default value for parallelism static const int parallelism= 0; @@ -94,6 +193,11 @@ static bool ndbcluster_show_status(handlerton *hton, THD*, static int ndbcluster_alter_tablespace(handlerton *hton, THD* thd, st_alter_tablespace *info); +static int ndbcluster_fill_is_table(handlerton *hton, + THD *thd, + TABLE_LIST *tables, + COND *cond, + enum enum_schema_tables); static int ndbcluster_fill_files_table(handlerton *hton, THD *thd, TABLE_LIST *tables, @@ -160,7 +264,7 @@ Ndb_cluster_connection* g_ndb_cluster_connection= NULL; uchar g_node_id_map[max_ndb_nodes]; /// Handler synchronization -pthread_mutex_t ndbcluster_mutex; +mysql_mutex_t ndbcluster_mutex; /// Table lock handling HASH ndbcluster_open_tables; @@ -177,11 +281,10 @@ static int ndb_get_table_statistics(ha_ndbcluster*, bool, Ndb*, const NDBTAB *, // Util thread variables pthread_t ndb_util_thread; int ndb_util_thread_running= 0; -pthread_mutex_t LOCK_ndb_util_thread; -pthread_cond_t COND_ndb_util_thread; -pthread_cond_t COND_ndb_util_ready; +mysql_mutex_t LOCK_ndb_util_thread; +mysql_cond_t COND_ndb_util_thread; +mysql_cond_t COND_ndb_util_ready; pthread_handler_t ndb_util_thread_func(void *arg); -ulong ndb_cache_check_time; /** Dummy buffer to read zero pack_length fields @@ -316,7 +419,7 @@ int execute_commit(THD *thd, NdbTransaction *trans) { return trans->execute(NdbTransaction::Commit, NdbOperation::AbortOnError, - thd->variables.ndb_force_send); + THDVAR(thd, force_send)); } inline @@ -1245,11 +1348,11 @@ int ha_ndbcluster::add_index_handle(THD *thd, NDBDICT *dict, KEY *key_info, NDB_INDEX_DATA& d=m_index[index_no]; delete d.index_stat; d.index_stat=NULL; - if (thd->variables.ndb_index_stat_enable) + if (THDVAR(thd, index_stat_enable)) { d.index_stat=new NdbIndexStat(index); - d.index_stat_cache_entries=thd->variables.ndb_index_stat_cache_entries; - d.index_stat_update_freq=thd->variables.ndb_index_stat_update_freq; + d.index_stat_cache_entries=THDVAR(thd, index_stat_cache_entries); + d.index_stat_update_freq=THDVAR(thd, index_stat_update_freq); d.index_stat_query_count=0; d.index_stat->alloc_cache(d.index_stat_cache_entries); DBUG_PRINT("info", ("index %s stat=on cache_entries=%u update_freq=%u", @@ -1309,10 +1412,12 @@ int ha_ndbcluster::open_indexes(Ndb *ndb, TABLE *tab, bool ignore_error) for (i= 0; i < tab->s->keys; i++, key_info++, key_name++) { if ((error= add_index_handle(thd, dict, key_info, *key_name, i))) + { if (ignore_error) m_index[i].index= m_index[i].unique_index= NULL; else break; + } m_index[i].null_in_unique_index= FALSE; if (check_index_fields_not_null(key_info)) m_index[i].null_in_unique_index= TRUE; @@ -4077,7 +4182,7 @@ int ha_ndbcluster::info(uint flag) { DBUG_RETURN(my_errno= HA_ERR_OUT_OF_MEM); } - if (current_thd->variables.ndb_use_exact_count && + if (THDVAR(current_thd, use_exact_count) && (result= ndb_get_table_statistics(this, TRUE, ndb, m_table, &stat)) == 0) { @@ -4407,12 +4512,12 @@ THR_LOCK_DATA **ha_ndbcluster::store_lock(THD *thd, #ifndef DBUG_OFF #define PRINT_OPTION_FLAGS(t) { \ - if (t->options & OPTION_NOT_AUTOCOMMIT) \ - DBUG_PRINT("thd->options", ("OPTION_NOT_AUTOCOMMIT")); \ - if (t->options & OPTION_BEGIN) \ - DBUG_PRINT("thd->options", ("OPTION_BEGIN")); \ - if (t->options & OPTION_TABLE_LOCK) \ - DBUG_PRINT("thd->options", ("OPTION_TABLE_LOCK")); \ + if (t->variables.option_bits & OPTION_NOT_AUTOCOMMIT) \ + DBUG_PRINT("thd->variables.option_bits", ("OPTION_NOT_AUTOCOMMIT")); \ + if (t->variables.option_bits & OPTION_BEGIN) \ + DBUG_PRINT("thd->variables.option_bits", ("OPTION_BEGIN")); \ + if (t->variables.option_bits & OPTION_TABLE_LOCK) \ + DBUG_PRINT("thd->variables.option_bits", ("OPTION_TABLE_LOCK")); \ } #else #define PRINT_OPTION_FLAGS(t) @@ -4499,7 +4604,7 @@ void ha_ndbcluster::transaction_checks(THD *thd) else if (!thd->transaction.on) m_transaction_on= FALSE; else - m_transaction_on= thd->variables.ndb_use_transactions; + m_transaction_on= THDVAR(thd, use_transactions); } int ha_ndbcluster::start_statement(THD *thd, @@ -4512,7 +4617,7 @@ int ha_ndbcluster::start_statement(THD *thd, trans_register_ha(thd, FALSE, ndbcluster_hton); if (!thd_ndb->trans) { - if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) + if (thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) trans_register_ha(thd, TRUE, ndbcluster_hton); DBUG_PRINT("trans",("Starting transaction")); thd_ndb->trans= ndb->startTransaction(); @@ -4522,7 +4627,7 @@ int ha_ndbcluster::start_statement(THD *thd, thd_ndb->query_state&= NDB_QUERY_NORMAL; thd_ndb->trans_options= 0; thd_ndb->m_slow_path= FALSE; - if (!(thd->options & OPTION_BIN_LOG) || + if (!(thd->variables.option_bits & OPTION_BIN_LOG) || thd->variables.binlog_format == BINLOG_FORMAT_STMT) { thd_ndb->trans_options|= TNTO_NO_LOGGING; @@ -4537,7 +4642,7 @@ int ha_ndbcluster::start_statement(THD *thd, Check if it should be read or write lock */ - if (thd->options & (OPTION_TABLE_LOCK)) + if (thd->variables.option_bits & OPTION_TABLE_LOCK) { //lockThisTable(); DBUG_PRINT("info", ("Locking the table..." )); @@ -4561,13 +4666,13 @@ int ha_ndbcluster::init_handler_for_statement(THD *thd, Thd_ndb *thd_ndb) DBUG_ENTER("ha_ndbcluster::init_handler_for_statement"); // store thread specific data first to set the right context - m_force_send= thd->variables.ndb_force_send; - m_ha_not_exact_count= !thd->variables.ndb_use_exact_count; + m_force_send= THDVAR(thd, force_send); + m_ha_not_exact_count= !THDVAR(thd, use_exact_count); m_autoincrement_prefetch= - (thd->variables.ndb_autoincrement_prefetch_sz > - NDB_DEFAULT_AUTO_PREFETCH) ? - (ha_rows) thd->variables.ndb_autoincrement_prefetch_sz - : (ha_rows) NDB_DEFAULT_AUTO_PREFETCH; + (THDVAR(thd, autoincrement_prefetch_sz) > + DEFAULT_AUTO_PREFETCH) ? + (ha_rows) THDVAR(thd, autoincrement_prefetch_sz) + : (ha_rows) DEFAULT_AUTO_PREFETCH; m_active_trans= thd_ndb->trans; DBUG_ASSERT(m_active_trans); // Start of transaction @@ -4582,7 +4687,7 @@ int ha_ndbcluster::init_handler_for_statement(THD *thd, Thd_ndb *thd_ndb) } #endif - if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) + if (thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { const void *key= m_table; HASH_SEARCH_STATE state; @@ -4663,21 +4768,21 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) { DBUG_PRINT("info", ("lock_type == F_UNLCK")); - if (ndb_cache_check_time && m_rows_changed) + if (opt_ndb_cache_check_time && m_rows_changed) { DBUG_PRINT("info", ("Rows has changed and util thread is running")); - if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) + if (thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { DBUG_PRINT("info", ("Add share to list of tables to be invalidated")); /* NOTE push_back allocates memory using transactions mem_root! */ thd_ndb->changed_tables.push_back(m_share, &thd->transaction.mem_root); } - pthread_mutex_lock(&m_share->mutex); + mysql_mutex_lock(&m_share->mutex); DBUG_PRINT("info", ("Invalidating commit_count")); m_share->commit_count= 0; m_share->commit_count_lock++; - pthread_mutex_unlock(&m_share->mutex); + mysql_mutex_unlock(&m_share->mutex); } if (!--thd_ndb->lock_count) @@ -4685,7 +4790,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) DBUG_PRINT("trans", ("Last external_lock")); PRINT_OPTION_FLAGS(thd); - if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) + if (!(thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { if (thd_ndb->trans) { @@ -4796,7 +4901,7 @@ static int ndbcluster_commit(handlerton *hton, THD *thd, bool all) DBUG_PRINT("enter", ("Commit %s", (all ? "all" : "stmt"))); thd_ndb->start_stmt_count= 0; if (trans == NULL || (!all && - thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) + thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { /* An odditity in the handler interface is that commit on handlerton @@ -4838,12 +4943,12 @@ static int ndbcluster_commit(handlerton *hton, THD *thd, bool all) List_iterator_fast<NDB_SHARE> it(thd_ndb->changed_tables); while ((share= it++)) { - pthread_mutex_lock(&share->mutex); + mysql_mutex_lock(&share->mutex); DBUG_PRINT("info", ("Invalidate commit_count for %s, share->commit_count: %lu", share->table_name, (ulong) share->commit_count)); share->commit_count= 0; share->commit_count_lock++; - pthread_mutex_unlock(&share->mutex); + mysql_mutex_unlock(&share->mutex); } thd_ndb->changed_tables.empty(); @@ -4866,7 +4971,7 @@ static int ndbcluster_rollback(handlerton *hton, THD *thd, bool all) DBUG_ASSERT(ndb); thd_ndb->start_stmt_count= 0; if (trans == NULL || (!all && - thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) + thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { /* Ignore end-of-statement until real rollback or commit is called */ DBUG_PRINT("info", ("Rollback before start or end-of-statement only")); @@ -5517,7 +5622,7 @@ int ha_ndbcluster::create(const char *name, if (!my_errno) { NDB_SHARE *share= 0; - pthread_mutex_lock(&ndbcluster_mutex); + mysql_mutex_lock(&ndbcluster_mutex); /* First make sure we get a "fresh" share here, not an old trailing one... */ @@ -5542,7 +5647,7 @@ int ha_ndbcluster::create(const char *name, DBUG_PRINT("NDB_SHARE", ("%s binlog create use_count: %u", share->key, share->use_count)); } - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); while (!IS_TMP_PREFIX(m_tabname)) { @@ -5562,7 +5667,7 @@ int ha_ndbcluster::create(const char *name, if (!ndbcluster_create_event(ndb, m_table, event_name.c_ptr(), share, share && do_event_op ? 2 : 1/* push warning */)) { - if (ndb_extra_logging) + if (opt_ndb_extra_logging) sql_print_information("NDB Binlog: CREATE TABLE Event: %s", event_name.c_ptr()); if (share && @@ -6005,7 +6110,7 @@ int ha_ndbcluster::rename_table(const char *from, const char *to) if (!ndbcluster_create_event(ndb, ndbtab, event_name.c_ptr(), share, share && ndb_binlog_running ? 2 : 1/* push warning */)) { - if (ndb_extra_logging) + if (opt_ndb_extra_logging) sql_print_information("NDB Binlog: RENAME Event: %s", event_name.c_ptr()); if (share && @@ -6181,7 +6286,7 @@ retry_temporary_error1: /* the drop table failed for some reason, drop the share anyways */ if (share) { - pthread_mutex_lock(&ndbcluster_mutex); + mysql_mutex_lock(&ndbcluster_mutex); if (share->state != NSS_DROPPED) { /* @@ -6197,7 +6302,7 @@ retry_temporary_error1: DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", share->key, share->use_count)); free_share(&share, TRUE); - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); } #endif DBUG_RETURN(res); @@ -6238,7 +6343,7 @@ retry_temporary_error1: if (share) { - pthread_mutex_lock(&ndbcluster_mutex); + mysql_mutex_lock(&ndbcluster_mutex); if (share->state != NSS_DROPPED) { /* @@ -6254,7 +6359,7 @@ retry_temporary_error1: DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", share->key, share->use_count)); free_share(&share, TRUE); - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); } #endif DBUG_RETURN(0); @@ -6308,10 +6413,9 @@ void ha_ndbcluster::get_auto_increment(ulonglong offset, ulonglong increment, m_rows_to_insert+= m_autoincrement_prefetch; } uint remaining= m_rows_to_insert - m_rows_inserted; + ha_rows prefetch= THDVAR(thd, autoincrement_prefetch_sz); uint min_prefetch= - (remaining < thd->variables.ndb_autoincrement_prefetch_sz) ? - thd->variables.ndb_autoincrement_prefetch_sz - : remaining; + (remaining < prefetch) ? prefetch : remaining; cache_size= ((remaining < m_autoincrement_prefetch) ? min_prefetch : remaining); @@ -6401,7 +6505,7 @@ ha_ndbcluster::ha_ndbcluster(handlerton *hton, TABLE_SHARE *table_arg): m_dupkey((uint) -1), m_ha_not_exact_count(FALSE), m_force_send(TRUE), - m_autoincrement_prefetch((ha_rows) NDB_DEFAULT_AUTO_PREFETCH), + m_autoincrement_prefetch(DEFAULT_AUTO_PREFETCH), m_transaction_on(TRUE), m_cond(NULL), m_multi_cursor(NULL) @@ -6904,7 +7008,7 @@ int ndbcluster_drop_database_impl(const char *path) while ((tabname=it++)) { tablename_to_filename(tabname, tmp, FN_REFLEN - (tmp - full_path)-1); - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); if (ha_ndbcluster::delete_table(0, ndb, full_path, dbname, tabname)) { const NdbError err= dict->getNdbError(); @@ -6914,7 +7018,7 @@ int ndbcluster_drop_database_impl(const char *path) ret= ndb_to_mysql_error(&err); } } - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); } DBUG_RETURN(ret); } @@ -6952,7 +7056,6 @@ int ndb_create_table_from_engine(THD *thd, const char *db, LEX *old_lex= thd->lex, newlex; thd->lex= &newlex; newlex.current_select= NULL; - lex_start(thd); int res= ha_create_table_from_engine(thd, db, table_name); thd->lex= old_lex; return res; @@ -7067,7 +7170,7 @@ int ndbcluster_find_all_files(THD *thd) my_free((char*) data, MYF(MY_ALLOW_ZERO_PTR)); my_free((char*) pack_data, MYF(MY_ALLOW_ZERO_PTR)); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (discover) { /* ToDo 4.1 database needs to be created if missing */ @@ -7085,7 +7188,7 @@ int ndbcluster_find_all_files(THD *thd) TRUE); } #endif - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } } while (unhandled && retries); @@ -7178,19 +7281,19 @@ int ndbcluster_find_files(handlerton *hton, THD *thd, file_name->str, reg_ext, 0); if (my_access(name, F_OK)) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); DBUG_PRINT("info", ("Table %s listed and need discovery", file_name->str)); if (ndb_create_table_from_engine(thd, db, file_name->str)) { - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_TABLE_EXISTS_ERROR, "Discover of table %s.%s failed", db, file_name->str); continue; } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } DBUG_PRINT("info", ("%s existed in NDB _and_ on disk ", file_name->str)); file_on_disk= TRUE; @@ -7247,10 +7350,10 @@ int ndbcluster_find_files(handlerton *hton, THD *thd, file_name_str= (char*)my_hash_element(&ok_tables, i); end= end1 + tablename_to_filename(file_name_str, end1, sizeof(name) - (end1 - name)); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); ndbcluster_create_binlog_setup(ndb, name, end-name, db, file_name_str, TRUE); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } } #endif @@ -7299,7 +7402,7 @@ int ndbcluster_find_files(handlerton *hton, THD *thd, } } - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); // Create new files List_iterator_fast<char> it2(create_list); while ((file_name_str=it2++)) @@ -7314,7 +7417,7 @@ int ndbcluster_find_files(handlerton *hton, THD *thd, } } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); my_hash_free(&ok_tables); my_hash_free(&ndb_tables); @@ -7348,7 +7451,7 @@ int ndbcluster_find_files(handlerton *hton, THD *thd, /* Call back after cluster connect */ static int connect_callback() { - pthread_mutex_lock(&LOCK_ndb_util_thread); + mysql_mutex_lock(&LOCK_ndb_util_thread); update_status_variables(g_ndb_cluster_connection); uint node_id, i= 0; @@ -7357,13 +7460,91 @@ static int connect_callback() while ((node_id= g_ndb_cluster_connection->get_next_node(node_iter))) g_node_id_map[node_id]= i++; - pthread_cond_signal(&COND_ndb_util_thread); - pthread_mutex_unlock(&LOCK_ndb_util_thread); + mysql_cond_signal(&COND_ndb_util_thread); + mysql_mutex_unlock(&LOCK_ndb_util_thread); return 0; } extern int ndb_dictionary_is_mysqld; -extern pthread_mutex_t LOCK_plugin; + +#ifdef HAVE_PSI_INTERFACE + +#ifdef HAVE_NDB_BINLOG +PSI_mutex_key key_injector_mutex, key_ndb_schema_share_mutex, + key_ndb_schema_object_mutex; +#endif /* HAVE_NDB_BINLOG */ + +PSI_mutex_key key_NDB_SHARE_mutex, key_ndbcluster_mutex, + key_LOCK_ndb_util_thread; + +static PSI_mutex_info all_ndbcluster_mutexes[]= +{ +#ifdef HAVE_NDB_BINLOG + {& key_injector_mutex, "injector_mutex", PSI_FLAG_GLOBAL}, + {& key_ndb_schema_share_mutex, "ndb_schema_share_mutex", PSI_FLAG_GLOBAL}, + {& key_ndb_schema_object_mutex, "ndb_schema_object_mutex", PSI_FLAG_GLOBAL}, +#endif /* HAVE_NDB_BINLOG */ + {& key_NDB_SHARE_mutex, "NDB_SHARE::mutex", PSI_FLAG_GLOBAL}, + {& key_ndbcluster_mutex, "ndbcluster_mutex", PSI_FLAG_GLOBAL}, + {& key_LOCK_ndb_util_thread, "LOCK_ndb_util_thread", PSI_FLAG_GLOBAL} +}; + +#ifdef HAVE_NDB_BINLOG +PSI_cond_key key_injector_cond; +#endif /* HAVE_NDB_BINLOG */ + +PSI_cond_key key_COND_ndb_util_thread, key_COND_ndb_util_ready; + +static PSI_cond_info all_ndbcluster_conds[]= +{ +#ifdef HAVE_NDB_BINLOG + {& key_injector_cond, "injector_cond", PSI_FLAG_GLOBAL}, +#endif /* HAVE_NDB_BINLOG */ + {& key_COND_ndb_util_thread, "COND_ndb_util_thread", PSI_FLAG_GLOBAL}, + {& key_COND_ndb_util_ready, "COND_ndb_util_ready", PSI_FLAG_GLOBAL} +}; + +#ifdef HAVE_NDB_BINLOG +PSI_thread_key key_thread_ndb_binlog; +#endif /* HAVE_NDB_BINLOG */ +PSI_thread_key key_thread_ndb_util; + +static PSI_thread_info all_ndbcluster_threads[]= +{ +#ifdef HAVE_NDB_BINLOG + { &key_thread_ndb_binlog, "ndb_binlog", PSI_FLAG_GLOBAL}, +#endif /* HAVE_NDB_BINLOG */ + { &key_thread_ndb_util, "ndb_util", PSI_FLAG_GLOBAL} +}; + +PSI_file_key key_file_ndb; + +static PSI_file_info all_ndbcluster_files[]= +{ + { &key_file_ndb, "ndb", 0} +}; + +void init_ndbcluster_psi_keys() +{ + const char* category= "ndbcluster"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_ndbcluster_mutexes); + PSI_server->register_mutex(category, all_ndbcluster_mutexes, count); + + count= array_elements(all_ndbcluster_conds); + PSI_server->register_cond(category, all_ndbcluster_conds, count); + + count= array_elements(all_ndbcluster_threads); + PSI_server->register_thread(category, all_ndbcluster_threads, count); + + count= array_elements(all_ndbcluster_files); + PSI_server->register_file(category, all_ndbcluster_files, count); +} +#endif /* HAVE_PSI_INTERFACE */ static int ndbcluster_init(void *p) { @@ -7373,17 +7554,16 @@ static int ndbcluster_init(void *p) if (ndbcluster_inited) DBUG_RETURN(FALSE); - /* - Below we create new THD's. They'll need LOCK_plugin, but it's taken now by - plugin initialization code. Release it to avoid deadlocks. It's safe, as - there're no threads that may concurrently access plugin control structures. - */ - pthread_mutex_unlock(&LOCK_plugin); +#ifdef HAVE_PSI_INTERFACE + init_ndbcluster_psi_keys(); +#endif - pthread_mutex_init(&ndbcluster_mutex,MY_MUTEX_INIT_FAST); - pthread_mutex_init(&LOCK_ndb_util_thread, MY_MUTEX_INIT_FAST); - pthread_cond_init(&COND_ndb_util_thread, NULL); - pthread_cond_init(&COND_ndb_util_ready, NULL); + mysql_mutex_init(key_ndbcluster_mutex, + &ndbcluster_mutex, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_ndb_util_thread, + &LOCK_ndb_util_thread, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_ndb_util_thread, &COND_ndb_util_thread, NULL); + mysql_cond_init(key_COND_ndb_util_ready, &COND_ndb_util_ready, NULL); ndb_util_thread_running= -1; ndbcluster_terminating= 0; ndb_dictionary_is_mysqld= 1; @@ -7403,7 +7583,7 @@ static int ndbcluster_init(void *p) h->alter_tablespace= ndbcluster_alter_tablespace; /* Show status */ h->partition_flags= ndbcluster_partition_flags; /* Partition flags */ h->alter_table_flags=ndbcluster_alter_table_flags; /* Alter table flags */ - h->fill_files_table= ndbcluster_fill_files_table; + h->fill_is_table= ndbcluster_fill_is_table; #ifdef HAVE_NDB_BINLOG ndbcluster_binlog_init_handlerton(); #endif @@ -7413,17 +7593,31 @@ static int ndbcluster_init(void *p) h->table_exists_in_engine= ndbcluster_table_exists_in_engine; } + // Format the connect string to be used for connecting to the cluster + int pos= 0; + char connectstring_buf[1024] = {0}; + if (opt_ndb_nodeid != 0) + pos+= my_snprintf(connectstring_buf, sizeof(connectstring_buf), + "nodeid=%u", opt_ndb_nodeid); + if (opt_ndb_mgmd_host) + pos+= my_snprintf(connectstring_buf+pos, sizeof(connectstring_buf)-pos, + "%s%s", pos ? "," : "", opt_ndb_mgmd_host); + if (opt_ndb_connectstring) + pos+= my_snprintf(connectstring_buf+pos, sizeof(connectstring_buf)-pos, + "%s%s", pos ? "," : "", opt_ndb_connectstring); + + // Initialize ndb interface ndb_init_internal(); // Set connectstring if specified - if (opt_ndbcluster_connectstring != 0) - DBUG_PRINT("connectstring", ("%s", opt_ndbcluster_connectstring)); + if (opt_ndb_connectstring != 0) + DBUG_PRINT("connectstring", ("%s", opt_ndb_connectstring)); if ((g_ndb_cluster_connection= - new Ndb_cluster_connection(opt_ndbcluster_connectstring)) == 0) + new Ndb_cluster_connection(opt_ndb_connectstring)) == 0) { DBUG_PRINT("error",("Ndb_cluster_connection(%s)", - opt_ndbcluster_connectstring)); + opt_ndb_connectstring)); my_errno= HA_ERR_OUT_OF_MEM; goto ndbcluster_init_error; } @@ -7433,7 +7627,7 @@ static int ndbcluster_init(void *p) g_ndb_cluster_connection->set_name(buf); } g_ndb_cluster_connection->set_optimized_node_selection - (opt_ndb_optimized_node_selection); + (THDVAR(0, optimized_node_selection)); // Create a Ndb object to open the connection to NDB if ( (g_ndb= new Ndb(g_ndb_cluster_connection, "sys")) == 0 ) @@ -7489,39 +7683,37 @@ static int ndbcluster_init(void *p) goto ndbcluster_init_error; #endif /* HAVE_NDB_BINLOG */ - ndb_cache_check_time = opt_ndb_cache_check_time; // Create utility thread pthread_t tmp; - if (pthread_create(&tmp, &connection_attrib, ndb_util_thread_func, 0)) + if (mysql_thread_create(key_thread_ndb_util, + &tmp, &connection_attrib, ndb_util_thread_func, 0)) { DBUG_PRINT("error", ("Could not create ndb utility thread")); my_hash_free(&ndbcluster_open_tables); - pthread_mutex_destroy(&ndbcluster_mutex); - pthread_mutex_destroy(&LOCK_ndb_util_thread); - pthread_cond_destroy(&COND_ndb_util_thread); - pthread_cond_destroy(&COND_ndb_util_ready); + mysql_mutex_destroy(&ndbcluster_mutex); + mysql_mutex_destroy(&LOCK_ndb_util_thread); + mysql_cond_destroy(&COND_ndb_util_thread); + mysql_cond_destroy(&COND_ndb_util_ready); goto ndbcluster_init_error; } /* Wait for the util thread to start */ - pthread_mutex_lock(&LOCK_ndb_util_thread); + mysql_mutex_lock(&LOCK_ndb_util_thread); while (ndb_util_thread_running < 0) - pthread_cond_wait(&COND_ndb_util_ready, &LOCK_ndb_util_thread); - pthread_mutex_unlock(&LOCK_ndb_util_thread); + mysql_cond_wait(&COND_ndb_util_ready, &LOCK_ndb_util_thread); + mysql_mutex_unlock(&LOCK_ndb_util_thread); if (!ndb_util_thread_running) { DBUG_PRINT("error", ("ndb utility thread exited prematurely")); my_hash_free(&ndbcluster_open_tables); - pthread_mutex_destroy(&ndbcluster_mutex); - pthread_mutex_destroy(&LOCK_ndb_util_thread); - pthread_cond_destroy(&COND_ndb_util_thread); - pthread_cond_destroy(&COND_ndb_util_ready); + mysql_mutex_destroy(&ndbcluster_mutex); + mysql_mutex_destroy(&LOCK_ndb_util_thread); + mysql_cond_destroy(&COND_ndb_util_thread); + mysql_cond_destroy(&COND_ndb_util_ready); goto ndbcluster_init_error; } - pthread_mutex_lock(&LOCK_plugin); - ndbcluster_inited= 1; DBUG_RETURN(FALSE); @@ -7534,11 +7726,37 @@ ndbcluster_init_error: g_ndb_cluster_connection= NULL; ndbcluster_hton->state= SHOW_OPTION_DISABLED; // If we couldn't use handler - pthread_mutex_lock(&LOCK_plugin); - DBUG_RETURN(TRUE); } +/** + Used to fill in INFORMATION_SCHEMA* tables. + + @param hton handle to the handlerton structure + @param thd the thread/connection descriptor + @param[in,out] tables the information schema table that is filled up + @param cond used for conditional pushdown to storage engine + @param schema_table_idx the table id that distinguishes the type of table + + @return Operation status + */ +static int ndbcluster_fill_is_table(handlerton *hton, + THD *thd, + TABLE_LIST *tables, + COND *cond, + enum enum_schema_tables schema_table_idx) +{ + int ret= 0; + + if (schema_table_idx == SCH_FILES) + { + ret= ndbcluster_fill_files_table(hton, thd, tables, cond); + } + + return ret; +} + + static int ndbcluster_end(handlerton *hton, ha_panic_function type) { DBUG_ENTER("ndbcluster_end"); @@ -7549,17 +7767,17 @@ static int ndbcluster_end(handlerton *hton, ha_panic_function type) /* wait for util thread to finish */ sql_print_information("Stopping Cluster Utility thread"); - pthread_mutex_lock(&LOCK_ndb_util_thread); + mysql_mutex_lock(&LOCK_ndb_util_thread); ndbcluster_terminating= 1; - pthread_cond_signal(&COND_ndb_util_thread); + mysql_cond_signal(&COND_ndb_util_thread); while (ndb_util_thread_running > 0) - pthread_cond_wait(&COND_ndb_util_ready, &LOCK_ndb_util_thread); - pthread_mutex_unlock(&LOCK_ndb_util_thread); + mysql_cond_wait(&COND_ndb_util_ready, &LOCK_ndb_util_thread); + mysql_mutex_unlock(&LOCK_ndb_util_thread); #ifdef HAVE_NDB_BINLOG { - pthread_mutex_lock(&ndbcluster_mutex); + mysql_mutex_lock(&ndbcluster_mutex); while (ndbcluster_open_tables.records) { NDB_SHARE *share= @@ -7570,7 +7788,7 @@ static int ndbcluster_end(handlerton *hton, ha_panic_function type) #endif ndbcluster_real_free_share(&share); } - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); } #endif my_hash_free(&ndbcluster_open_tables); @@ -7599,10 +7817,10 @@ static int ndbcluster_end(handlerton *hton, ha_panic_function type) // cleanup ndb interface ndb_end_internal(); - pthread_mutex_destroy(&ndbcluster_mutex); - pthread_mutex_destroy(&LOCK_ndb_util_thread); - pthread_cond_destroy(&COND_ndb_util_thread); - pthread_cond_destroy(&COND_ndb_util_ready); + mysql_mutex_destroy(&ndbcluster_mutex); + mysql_mutex_destroy(&LOCK_ndb_util_thread); + mysql_cond_destroy(&COND_ndb_util_thread); + mysql_cond_destroy(&COND_ndb_util_ready); DBUG_RETURN(0); } @@ -7905,12 +8123,12 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname, build_table_filename(name, sizeof(name) - 1, dbname, tabname, "", 0); DBUG_PRINT("enter", ("name: %s", name)); - pthread_mutex_lock(&ndbcluster_mutex); + mysql_mutex_lock(&ndbcluster_mutex); if (!(share=(NDB_SHARE*) my_hash_search(&ndbcluster_open_tables, (uchar*) name, strlen(name)))) { - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); DBUG_PRINT("info", ("Table %s not found in ndbcluster_open_tables", name)); DBUG_RETURN(1); } @@ -7918,10 +8136,10 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname, share->use_count++; DBUG_PRINT("NDB_SHARE", ("%s temporary use_count: %u", share->key, share->use_count)); - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); - pthread_mutex_lock(&share->mutex); - if (ndb_cache_check_time > 0) + mysql_mutex_lock(&share->mutex); + if (opt_ndb_cache_check_time > 0) { if (share->commit_count != 0) { @@ -7931,7 +8149,7 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname, #endif DBUG_PRINT("info", ("Getting commit_count: %s from share", llstr(share->commit_count, buff))); - pthread_mutex_unlock(&share->mutex); + mysql_mutex_unlock(&share->mutex); /* ndb_share reference temporary free */ DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", share->key, share->use_count)); @@ -7948,7 +8166,7 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname, ERR_RETURN(ndb->getNdbError()); } uint lock= share->commit_count_lock; - pthread_mutex_unlock(&share->mutex); + mysql_mutex_unlock(&share->mutex); struct Ndb_statistics stat; { @@ -7964,7 +8182,7 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname, } } - pthread_mutex_lock(&share->mutex); + mysql_mutex_lock(&share->mutex); if (share->commit_count_lock == lock) { #ifndef DBUG_OFF @@ -7980,7 +8198,7 @@ uint ndb_get_commitcount(THD *thd, char *dbname, char *tabname, DBUG_PRINT("info", ("Discarding commit_count, comit_count_lock changed")); *commit_count= 0; } - pthread_mutex_unlock(&share->mutex); + mysql_mutex_unlock(&share->mutex); /* ndb_share reference temporary free */ DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", share->key, share->use_count)); @@ -8024,7 +8242,7 @@ ndbcluster_cache_retrieval_allowed(THD *thd, ulonglong *engine_data) { Uint64 commit_count; - bool is_autocommit= !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); + bool is_autocommit= !(thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); char *dbname= full_name; char *tabname= dbname+strlen(dbname)+1; #ifndef DBUG_OFF @@ -8099,7 +8317,7 @@ ha_ndbcluster::register_query_cache_table(THD *thd, #ifndef DBUG_OFF char buff[22]; #endif - bool is_autocommit= !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); + bool is_autocommit= !(thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); DBUG_ENTER("ha_ndbcluster::register_query_cache_table"); DBUG_PRINT("enter",("dbname: %s, tabname: %s, is_autocommit: %d", m_dbname, m_tabname, is_autocommit)); @@ -8196,7 +8414,7 @@ static void print_ndbcluster_open_tables() to avoid segmentation faults. There is a risk that the memory for this trailing share leaks. - Must be called with previous pthread_mutex_lock(&ndbcluster_mutex) + Must be called with previous mysql_mutex_lock(&ndbcluster_mutex) */ int handle_trailing_share(NDB_SHARE *share) { @@ -8208,22 +8426,22 @@ int handle_trailing_share(NDB_SHARE *share) ++share->use_count; DBUG_PRINT("NDB_SHARE", ("%s temporary use_count: %u", share->key, share->use_count)); - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); TABLE_LIST table_list; bzero((char*) &table_list,sizeof(table_list)); table_list.db= share->db; table_list.alias= table_list.table_name= share->table_name; - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); close_cached_tables(thd, &table_list, TRUE, FALSE, FALSE); - pthread_mutex_lock(&ndbcluster_mutex); + mysql_mutex_lock(&ndbcluster_mutex); /* ndb_share reference temporary free */ DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", share->key, share->use_count)); if (!--share->use_count) { - if (ndb_extra_logging) + if (opt_ndb_extra_logging) sql_print_information("NDB_SHARE: trailing share " "%s(connect_count: %u) " "released by close_cached_tables at " @@ -8249,7 +8467,7 @@ int handle_trailing_share(NDB_SHARE *share) if (share->use_count == 0) { - if (ndb_extra_logging) + if (opt_ndb_extra_logging) sql_print_information("NDB_SHARE: trailing share " "%s(connect_count: %u) " "released after NSS_DROPPED check " @@ -8308,7 +8526,7 @@ int handle_trailing_share(NDB_SHARE *share) static int rename_share(NDB_SHARE *share, const char *new_key) { NDB_SHARE *tmp; - pthread_mutex_lock(&ndbcluster_mutex); + mysql_mutex_lock(&ndbcluster_mutex); uint new_length= (uint) strlen(new_key); DBUG_PRINT("rename_share", ("old_key: %s old__length: %d", share->key, share->key_length)); @@ -8346,7 +8564,7 @@ static int rename_share(NDB_SHARE *share, const char *new_key) share->key)); } dbug_print_open_tables(); - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); return -1; } dbug_print_open_tables(); @@ -8371,7 +8589,7 @@ static int rename_share(NDB_SHARE *share, const char *new_key) share->old_names= old_key; // ToDo free old_names after ALTER EVENT - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); return 0; } #endif @@ -8382,12 +8600,12 @@ static int rename_share(NDB_SHARE *share, const char *new_key) */ NDB_SHARE *ndbcluster_get_share(NDB_SHARE *share) { - pthread_mutex_lock(&ndbcluster_mutex); + mysql_mutex_lock(&ndbcluster_mutex); share->use_count++; dbug_print_open_tables(); dbug_print_share("ndbcluster_get_share:", share); - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); return share; } @@ -8404,7 +8622,7 @@ NDB_SHARE *ndbcluster_get_share(NDB_SHARE *share) create_if_not_exists == FALSE: returns 0 if share does not exist - have_lock == TRUE, pthread_mutex_lock(&ndbcluster_mutex) already taken + have_lock == TRUE, mysql_mutex_lock(&ndbcluster_mutex) already taken */ NDB_SHARE *ndbcluster_get_share(const char *key, TABLE *table, @@ -8417,7 +8635,7 @@ NDB_SHARE *ndbcluster_get_share(const char *key, TABLE *table, DBUG_PRINT("enter", ("key: '%s'", key)); if (!have_lock) - pthread_mutex_lock(&ndbcluster_mutex); + mysql_mutex_lock(&ndbcluster_mutex); if (!(share= (NDB_SHARE*) my_hash_search(&ndbcluster_open_tables, (uchar*) key, length))) @@ -8426,7 +8644,7 @@ NDB_SHARE *ndbcluster_get_share(const char *key, TABLE *table, { DBUG_PRINT("error", ("get_share: %s does not exist", key)); if (!have_lock) - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); DBUG_RETURN(0); } if ((share= (NDB_SHARE*) my_malloc(sizeof(*share), @@ -8448,11 +8666,11 @@ NDB_SHARE *ndbcluster_get_share(const char *key, TABLE *table, my_free((uchar*) share, 0); *root_ptr= old_root; if (!have_lock) - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); DBUG_RETURN(0); } thr_lock_init(&share->lock); - pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_NDB_SHARE_mutex, &share->mutex, MY_MUTEX_INIT_FAST); share->commit_count= 0; share->commit_count_lock= 0; share->db= share->key + length + 1; @@ -8466,7 +8684,7 @@ NDB_SHARE *ndbcluster_get_share(const char *key, TABLE *table, ndbcluster_real_free_share(&share); *root_ptr= old_root; if (!have_lock) - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); DBUG_RETURN(0); } #endif @@ -8476,7 +8694,7 @@ NDB_SHARE *ndbcluster_get_share(const char *key, TABLE *table, { DBUG_PRINT("error", ("get_share: failed to alloc share")); if (!have_lock) - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); my_error(ER_OUTOFMEMORY, MYF(0), sizeof(*share)); DBUG_RETURN(0); } @@ -8486,7 +8704,7 @@ NDB_SHARE *ndbcluster_get_share(const char *key, TABLE *table, dbug_print_open_tables(); dbug_print_share("ndbcluster_get_share:", share); if (!have_lock) - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); DBUG_RETURN(share); } @@ -8498,7 +8716,7 @@ void ndbcluster_real_free_share(NDB_SHARE **share) my_hash_delete(&ndbcluster_open_tables, (uchar*) *share); thr_lock_delete(&(*share)->lock); - pthread_mutex_destroy(&(*share)->mutex); + mysql_mutex_destroy(&(*share)->mutex); #ifdef HAVE_NDB_BINLOG if ((*share)->table) @@ -8527,7 +8745,7 @@ void ndbcluster_real_free_share(NDB_SHARE **share) void ndbcluster_free_share(NDB_SHARE **share, bool have_lock) { if (!have_lock) - pthread_mutex_lock(&ndbcluster_mutex); + mysql_mutex_lock(&ndbcluster_mutex); if ((*share)->util_lock == current_thd) (*share)->util_lock= 0; if (!--(*share)->use_count) @@ -8540,7 +8758,7 @@ void ndbcluster_free_share(NDB_SHARE **share, bool have_lock) dbug_print_share("ndbcluster_free_share:", *share); } if (!have_lock) - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); } @@ -8700,11 +8918,12 @@ int ha_ndbcluster::write_ndb_file(const char *name) (void)strxnmov(path, FN_REFLEN-1, mysql_data_home,"/",name,ha_ndb_ext,NullS); - if ((file=my_create(path, CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0) + if ((file= mysql_file_create(key_file_ndb, path, CREATE_MODE, + O_RDWR | O_TRUNC, MYF(MY_WME))) >= 0) { // It's an empty file error=0; - my_close(file,MYF(0)); + mysql_file_close(file, MYF(0)); } DBUG_RETURN(error); } @@ -9255,9 +9474,9 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) my_thread_init(); DBUG_ENTER("ndb_util_thread"); - DBUG_PRINT("enter", ("ndb_cache_check_time: %lu", ndb_cache_check_time)); + DBUG_PRINT("enter", ("cache_check_time: %lu", opt_ndb_cache_check_time)); - pthread_mutex_lock(&LOCK_ndb_util_thread); + mysql_mutex_lock(&LOCK_ndb_util_thread); thd= new THD; /* note that contructor of THD uses DBUG_ */ if (thd == NULL) @@ -9272,7 +9491,6 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) thd->thread_stack= (char*)&thd; /* remember where our stack is */ if (thd->store_globals()) goto ndb_util_thread_fail; - lex_start(thd); thd->init_for_queries(); thd->version=refresh_version; thd->main_security_ctx.host_or_ip= ""; @@ -9291,52 +9509,52 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) /* Signal successful initialization */ ndb_util_thread_running= 1; - pthread_cond_signal(&COND_ndb_util_ready); - pthread_mutex_unlock(&LOCK_ndb_util_thread); + mysql_cond_signal(&COND_ndb_util_ready); + mysql_mutex_unlock(&LOCK_ndb_util_thread); /* wait for mysql server to start */ - pthread_mutex_lock(&LOCK_server_started); + mysql_mutex_lock(&LOCK_server_started); while (!mysqld_server_started) { set_timespec(abstime, 1); - pthread_cond_timedwait(&COND_server_started, &LOCK_server_started, - &abstime); + mysql_cond_timedwait(&COND_server_started, &LOCK_server_started, + &abstime); if (ndbcluster_terminating) { - pthread_mutex_unlock(&LOCK_server_started); - pthread_mutex_lock(&LOCK_ndb_util_thread); + mysql_mutex_unlock(&LOCK_server_started); + mysql_mutex_lock(&LOCK_ndb_util_thread); goto ndb_util_thread_end; } } - pthread_mutex_unlock(&LOCK_server_started); + mysql_mutex_unlock(&LOCK_server_started); /* Wait for cluster to start */ - pthread_mutex_lock(&LOCK_ndb_util_thread); + mysql_mutex_lock(&LOCK_ndb_util_thread); while (!ndb_cluster_node_id && (ndbcluster_hton->slot != ~(uint)0)) { /* ndb not connected yet */ - pthread_cond_wait(&COND_ndb_util_thread, &LOCK_ndb_util_thread); + mysql_cond_wait(&COND_ndb_util_thread, &LOCK_ndb_util_thread); if (ndbcluster_terminating) goto ndb_util_thread_end; } - pthread_mutex_unlock(&LOCK_ndb_util_thread); + mysql_mutex_unlock(&LOCK_ndb_util_thread); /* Get thd_ndb for this thread */ if (!(thd_ndb= ha_ndbcluster::seize_thd_ndb())) { sql_print_error("Could not allocate Thd_ndb object"); - pthread_mutex_lock(&LOCK_ndb_util_thread); + mysql_mutex_lock(&LOCK_ndb_util_thread); goto ndb_util_thread_end; } set_thd_ndb(thd, thd_ndb); thd_ndb->options|= TNO_NO_LOG_SCHEMA_OP; #ifdef HAVE_NDB_BINLOG - if (ndb_extra_logging && ndb_binlog_running) + if (opt_ndb_extra_logging && ndb_binlog_running) sql_print_information("NDB Binlog: Ndb tables initially read only."); /* create tables needed by the replication */ ndbcluster_setup_binlog_table_shares(thd); @@ -9350,17 +9568,17 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) set_timespec(abstime, 0); for (;;) { - pthread_mutex_lock(&LOCK_ndb_util_thread); + mysql_mutex_lock(&LOCK_ndb_util_thread); if (!ndbcluster_terminating) - pthread_cond_timedwait(&COND_ndb_util_thread, - &LOCK_ndb_util_thread, - &abstime); + mysql_cond_timedwait(&COND_ndb_util_thread, + &LOCK_ndb_util_thread, + &abstime); if (ndbcluster_terminating) /* Shutting down server */ goto ndb_util_thread_end; - pthread_mutex_unlock(&LOCK_ndb_util_thread); + mysql_mutex_unlock(&LOCK_ndb_util_thread); #ifdef NDB_EXTRA_DEBUG_UTIL_THREAD - DBUG_PRINT("ndb_util_thread", ("Started, ndb_cache_check_time: %lu", - ndb_cache_check_time)); + DBUG_PRINT("ndb_util_thread", ("Started, opt_ndb_cache_check_time: %lu", + opt_ndb_cache_check_time)); #endif #ifdef HAVE_NDB_BINLOG @@ -9373,7 +9591,7 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) ndbcluster_setup_binlog_table_shares(thd); #endif - if (ndb_cache_check_time == 0) + if (opt_ndb_cache_check_time == 0) { /* Wake up in 1 second to check if value has changed */ set_timespec(abstime, 1); @@ -9382,7 +9600,7 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) /* Lock mutex and fill list with pointers to all open tables */ NDB_SHARE *share; - pthread_mutex_lock(&ndbcluster_mutex); + mysql_mutex_lock(&ndbcluster_mutex); uint i, open_count, record_count= ndbcluster_open_tables.records; if (share_list_size < record_count) { @@ -9391,7 +9609,7 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) { sql_print_warning("ndb util thread: malloc failure, " "query cache not maintained properly"); - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); goto next; // At least do not crash } delete [] share_list; @@ -9418,7 +9636,7 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) /* Store pointer to table */ share_list[open_count++]= share; } - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); /* Iterate through the open files list */ for (i= 0; i < open_count; i++) @@ -9443,9 +9661,9 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) struct Ndb_statistics stat; uint lock; - pthread_mutex_lock(&share->mutex); + mysql_mutex_lock(&share->mutex); lock= share->commit_count_lock; - pthread_mutex_unlock(&share->mutex); + mysql_mutex_unlock(&share->mutex); { /* Contact NDB to get commit count for table */ Ndb* ndb= thd_ndb->ndb; @@ -9476,10 +9694,10 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) } } loop_next: - pthread_mutex_lock(&share->mutex); + mysql_mutex_lock(&share->mutex); if (share->commit_count_lock == lock) share->commit_count= stat.commit_count; - pthread_mutex_unlock(&share->mutex); + mysql_mutex_unlock(&share->mutex); /* ndb_share reference temporary free */ DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u", @@ -9489,7 +9707,7 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) next: /* Calculate new time to wake up */ int secs= 0; - int msecs= ndb_cache_check_time; + int msecs= opt_ndb_cache_check_time; struct timeval tick_time; gettimeofday(&tick_time, 0); @@ -9509,7 +9727,7 @@ next: } } - pthread_mutex_lock(&LOCK_ndb_util_thread); + mysql_mutex_lock(&LOCK_ndb_util_thread); ndb_util_thread_end: net_end(&thd->net); @@ -9521,8 +9739,8 @@ ndb_util_thread_fail: /* signal termination */ ndb_util_thread_running= 0; - pthread_cond_signal(&COND_ndb_util_ready); - pthread_mutex_unlock(&LOCK_ndb_util_thread); + mysql_cond_signal(&COND_ndb_util_ready); + mysql_mutex_unlock(&LOCK_ndb_util_thread); DBUG_PRINT("exit", ("ndb_util_thread")); DBUG_LEAVE; // Must match DBUG_ENTER() @@ -9765,12 +9983,33 @@ int ha_ndbcluster::get_default_no_partitions(HA_CREATE_INFO *create_info) and partition by hidden key otherwise. */ + +enum ndb_distribution_enum { ND_KEYHASH= 0, ND_LINHASH= 1 }; +static const char* distribution_names[]= { "KEYHASH", "LINHASH", NullS }; +static ulong default_ndb_distribution= ND_KEYHASH; +static TYPELIB distribution_typelib= { + array_elements(distribution_names) - 1, + "", + distribution_names, + NULL +}; +static MYSQL_SYSVAR_ENUM( + distribution, /* name */ + default_ndb_distribution, /* var */ + PLUGIN_VAR_RQCMDARG, + "Default distribution for new tables in ndb", + NULL, /* check func. */ + NULL, /* update func. */ + ND_KEYHASH, /* default */ + &distribution_typelib /* typelib */ +); + void ha_ndbcluster::set_auto_partitions(partition_info *part_info) { DBUG_ENTER("ha_ndbcluster::set_auto_partitions"); part_info->list_of_part_fields= TRUE; part_info->part_type= HASH_PARTITION; - switch (opt_ndb_distribution_id) + switch (default_ndb_distribution) { case ND_KEYHASH: part_info->linear_hash_ind= FALSE; @@ -10006,7 +10245,7 @@ bool ha_ndbcluster::check_if_incompatible_data(HA_CREATE_INFO *create_info, uint i; const NDBTAB *tab= (const NDBTAB *) m_table; - if (current_thd->variables.ndb_use_copying_alter_table) + if (THDVAR(current_thd, use_copying_alter_table)) { DBUG_PRINT("info", ("On-line alter table disabled")); DBUG_RETURN(COMPATIBLE_DATA_NO); @@ -10638,6 +10877,132 @@ SHOW_VAR ndb_status_variables_export[]= { {NullS, NullS, SHOW_LONG} }; +static MYSQL_SYSVAR_ULONG( + cache_check_time, /* name */ + opt_ndb_cache_check_time, /* var */ + PLUGIN_VAR_RQCMDARG, + "A dedicated thread is created to, at the given " + "millisecond interval, invalidate the query cache " + "if another MySQL server in the cluster has changed " + "the data in the database.", + NULL, /* check func. */ + NULL, /* update func. */ + 0, /* default */ + 0, /* min */ + ONE_YEAR_IN_SECONDS, /* max */ + 0 /* block */ +); + + +static MYSQL_SYSVAR_ULONG( + extra_logging, /* name */ + opt_ndb_extra_logging, /* var */ + PLUGIN_VAR_OPCMDARG, + "Turn on more logging in the error log.", + NULL, /* check func. */ + NULL, /* update func. */ + 1, /* default */ + 0, /* min */ + 0, /* max */ + 0 /* block */ +); + + +ulong opt_ndb_report_thresh_binlog_epoch_slip; +static MYSQL_SYSVAR_ULONG( + report_thresh_binlog_epoch_slip, /* name */ + opt_ndb_report_thresh_binlog_epoch_slip,/* var */ + PLUGIN_VAR_RQCMDARG, + "Threshold on number of epochs to be behind before reporting binlog " + "status. E.g. 3 means that if the difference between what epoch has " + "been received from the storage nodes and what has been applied to " + "the binlog is 3 or more, a status message will be sent to the cluster " + "log.", + NULL, /* check func. */ + NULL, /* update func. */ + 3, /* default */ + 0, /* min */ + 256, /* max */ + 0 /* block */ +); + + +ulong opt_ndb_report_thresh_binlog_mem_usage; +static MYSQL_SYSVAR_ULONG( + report_thresh_binlog_mem_usage, /* name */ + opt_ndb_report_thresh_binlog_mem_usage,/* var */ + PLUGIN_VAR_RQCMDARG, + "Threshold on percentage of free memory before reporting binlog " + "status. E.g. 10 means that if amount of available memory for " + "receiving binlog data from the storage nodes goes below 10%, " + "a status message will be sent to the cluster log.", + NULL, /* check func. */ + NULL, /* update func. */ + 10, /* default */ + 0, /* min */ + 100, /* max */ + 0 /* block */ +); + + +static MYSQL_SYSVAR_STR( + connectstring, /* name */ + opt_ndb_connectstring, /* var */ + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "Connect string for ndbcluster.", + NULL, /* check func. */ + NULL, /* update func. */ + NULL /* default */ +); + + +static MYSQL_SYSVAR_STR( + mgmd_host, /* name */ + opt_ndb_mgmd_host, /* var */ + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "Set host and port for ndb_mgmd. Syntax: hostname[:port]", + NULL, /* check func. */ + NULL, /* update func. */ + NULL /* default */ +); + + +static MYSQL_SYSVAR_UINT( + nodeid, /* name */ + opt_ndb_nodeid, /* var */ + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, + "Nodeid for this mysqld in the cluster.", + NULL, /* check func. */ + NULL, /* update func. */ + 0, /* default */ + 0, /* min */ + 255, /* max */ + 0 /* block */ +); + +static struct st_mysql_sys_var* system_variables[]= { + MYSQL_SYSVAR(cache_check_time), + MYSQL_SYSVAR(extra_logging), + MYSQL_SYSVAR(report_thresh_binlog_mem_usage), + MYSQL_SYSVAR(report_thresh_binlog_epoch_slip), + MYSQL_SYSVAR(distribution), + MYSQL_SYSVAR(autoincrement_prefetch_sz), + MYSQL_SYSVAR(force_send), + MYSQL_SYSVAR(use_exact_count), + MYSQL_SYSVAR(use_transactions), + MYSQL_SYSVAR(use_copying_alter_table), + MYSQL_SYSVAR(optimized_node_selection), + MYSQL_SYSVAR(index_stat_enable), + MYSQL_SYSVAR(index_stat_cache_entries), + MYSQL_SYSVAR(index_stat_update_freq), + MYSQL_SYSVAR(connectstring), + MYSQL_SYSVAR(mgmd_host), + MYSQL_SYSVAR(nodeid), + + NULL +}; + + struct st_mysql_storage_engine ndbcluster_storage_engine= { MYSQL_HANDLERTON_INTERFACE_VERSION }; @@ -10653,7 +11018,7 @@ mysql_declare_plugin(ndbcluster) NULL, /* Plugin Deinit */ 0x0100 /* 1.0 */, ndb_status_variables_export,/* status variables */ - NULL, /* system variables */ + system_variables, /* system variables */ NULL /* config options */ } mysql_declare_plugin_end; diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index ac3e7329136..63da24e8dda 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -1,7 +1,7 @@ #ifndef HA_NDBCLUSTER_INCLUDED #define HA_NDBCLUSTER_INCLUDED -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -34,7 +34,10 @@ #include <ndbapi_limits.h> #define NDB_HIDDEN_PRIMARY_KEY_LENGTH 8 -#define NDB_DEFAULT_AUTO_PREFETCH 32 + +#ifdef HAVE_PSI_INTERFACE +extern PSI_file_key key_file_ndb; +#endif /* HAVE_PSI_INTERFACE */ class Ndb; // Forward declaration @@ -50,11 +53,6 @@ class ha_ndbcluster_cond; // connectstring to cluster if given by mysqld extern const char *ndbcluster_connectstring; -extern ulong ndb_cache_check_time; -#ifdef HAVE_NDB_BINLOG -extern ulong ndb_report_thresh_binlog_epoch_slip; -extern ulong ndb_report_thresh_binlog_mem_usage; -#endif typedef enum ndb_index_type { UNDEFINED_INDEX = 0, @@ -108,7 +106,7 @@ typedef struct st_ndbcluster_share { NDB_SHARE_STATE state; MEM_ROOT mem_root; THR_LOCK lock; - pthread_mutex_t mutex; + mysql_mutex_t mutex; char *key; uint key_length; THD *util_lock; @@ -137,9 +135,9 @@ NDB_SHARE_STATE get_ndb_share_state(NDB_SHARE *share) { NDB_SHARE_STATE state; - pthread_mutex_lock(&share->mutex); + mysql_mutex_lock(&share->mutex); state= share->state; - pthread_mutex_unlock(&share->mutex); + mysql_mutex_unlock(&share->mutex); return state; } @@ -147,19 +145,19 @@ inline void set_ndb_share_state(NDB_SHARE *share, NDB_SHARE_STATE state) { - pthread_mutex_lock(&share->mutex); + mysql_mutex_lock(&share->mutex); share->state= state; - pthread_mutex_unlock(&share->mutex); + mysql_mutex_unlock(&share->mutex); } struct Ndb_tuple_id_range_guard { Ndb_tuple_id_range_guard(NDB_SHARE* _share) : share(_share), range(share->tuple_id_range) { - pthread_mutex_lock(&share->mutex); + mysql_mutex_lock(&share->mutex); } ~Ndb_tuple_id_range_guard() { - pthread_mutex_unlock(&share->mutex); + mysql_mutex_unlock(&share->mutex); } NDB_SHARE* share; Ndb::TupleIdRange& range; @@ -584,6 +582,6 @@ static const char ndbcluster_hton_name[]= "ndbcluster"; static const int ndbcluster_hton_name_length=sizeof(ndbcluster_hton_name)-1; extern int ndbcluster_terminating; extern int ndb_util_thread_running; -extern pthread_cond_t COND_ndb_util_ready; +extern mysql_cond_t COND_ndb_util_ready; #endif /* HA_NDBCLUSTER_INCLUDED */ diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index e34a22cf9f4..eb46958398a 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,6 +33,8 @@ #define assert(x) do { if(x) break; ::printf("%s %d: assert failed: %s\n", __FILE__, __LINE__, #x); ::fflush(stdout); ::signal(SIGABRT,SIG_DFL); ::abort(); ::kill(::getpid(),6); ::kill(::getpid(),9); } while (0) #endif +extern my_bool opt_ndb_log_binlog_index; +extern ulong opt_ndb_extra_logging; /* defines for cluster replication table names */ @@ -44,14 +46,16 @@ Timeout for syncing schema events between mysql servers, and between mysql server and the binlog */ -const int opt_ndb_sync_timeout= 120; +static const int DEFAULT_SYNC_TIMEOUT= 120; + /* Flag showing if the ndb injector thread is running, if so == 1 -1 if it was started but later stopped for some reason 0 if never started */ -int ndb_binlog_thread_running= 0; +static int ndb_binlog_thread_running= 0; + /* Flag showing if the ndb binlog should be created, if so == TRUE FALSE if not @@ -75,7 +79,7 @@ THD *injector_thd= 0; to enable ndb injector thread receiving events. Must therefore always be used with a surrounding - pthread_mutex_lock(&injector_mutex), when doing create/dropEventOperation + mysql_mutex_lock(&injector_mutex), when doing create/dropEventOperation */ static Ndb *injector_ndb= 0; static Ndb *schema_ndb= 0; @@ -102,8 +106,8 @@ static int ndbcluster_binlog_terminating= 0; and injector thread */ pthread_t ndb_binlog_thread; -pthread_mutex_t injector_mutex; -pthread_cond_t injector_cond; +mysql_mutex_t injector_mutex; +mysql_cond_t injector_cond; /* NDB Injector thread (used for binlog creation) */ static ulonglong ndb_latest_applied_binlog_epoch= 0; @@ -112,7 +116,7 @@ static ulonglong ndb_latest_received_binlog_epoch= 0; NDB_SHARE *ndb_apply_status_share= 0; NDB_SHARE *ndb_schema_share= 0; -pthread_mutex_t ndb_schema_share_mutex; +mysql_mutex_t ndb_schema_share_mutex; extern my_bool opt_log_slave_updates; static my_bool g_ndb_log_slave_updates; @@ -120,7 +124,7 @@ static my_bool g_ndb_log_slave_updates; /* Schema object distribution handling */ HASH ndb_schema_objects; typedef struct st_ndb_schema_object { - pthread_mutex_t mutex; + mysql_mutex_t mutex; char *key; uint key_length; uint use_count; @@ -247,8 +251,8 @@ static void run_query(THD *thd, char *buf, char *end, struct system_status_var save_thd_status_var= thd->status_var; THD_TRANS save_thd_transaction_all= thd->transaction.all; THD_TRANS save_thd_transaction_stmt= thd->transaction.stmt; - ulonglong save_thd_options= thd->options; - DBUG_ASSERT(sizeof(save_thd_options) == sizeof(thd->options)); + ulonglong save_thd_options= thd->variables.option_bits; + DBUG_ASSERT(sizeof(save_thd_options) == sizeof(thd->variables.option_bits)); NET save_thd_net= thd->net; const char* found_semicolon= NULL; @@ -257,7 +261,7 @@ static void run_query(THD *thd, char *buf, char *end, thd->variables.pseudo_thread_id= thread_id; thd->transaction.stmt.modified_non_trans_table= FALSE; if (disable_binlog) - thd->options&= ~OPTION_BIN_LOG; + thd->variables.option_bits&= ~OPTION_BIN_LOG; DBUG_PRINT("query", ("%s", thd->query())); @@ -295,13 +299,14 @@ static void run_query(THD *thd, char *buf, char *end, */ thd->stmt_da->reset_diagnostics_area(); - thd->options= save_thd_options; + thd->variables.option_bits= save_thd_options; thd->set_query(save_thd_query, save_thd_query_length); thd->variables.pseudo_thread_id= save_thread_id; thd->status_var= save_thd_status_var; thd->transaction.all= save_thd_transaction_all; thd->transaction.stmt= save_thd_transaction_stmt; thd->net= save_thd_net; + thd->set_current_stmt_binlog_format_row(); if (thd == injector_thd) { @@ -343,7 +348,7 @@ ndbcluster_binlog_open_table(THD *thd, NDB_SHARE *share, int error; DBUG_ENTER("ndbcluster_binlog_open_table"); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); init_tmp_table_share(thd, table_share, share->db, 0, share->table_name, share->key); if ((error= open_table_def(thd, table_share, 0))) @@ -637,28 +642,28 @@ static int ndbcluster_binlog_end(THD *thd) however be a likely case as the ndbcluster_binlog_end is supposed to be called before ndb_cluster_end(). */ - pthread_mutex_lock(&LOCK_ndb_util_thread); + mysql_mutex_lock(&LOCK_ndb_util_thread); /* Ensure mutex are not freed if ndb_cluster_end is running at same time */ ndb_util_thread_running++; ndbcluster_terminating= 1; - pthread_cond_signal(&COND_ndb_util_thread); + mysql_cond_signal(&COND_ndb_util_thread); while (ndb_util_thread_running > 1) - pthread_cond_wait(&COND_ndb_util_ready, &LOCK_ndb_util_thread); + mysql_cond_wait(&COND_ndb_util_ready, &LOCK_ndb_util_thread); ndb_util_thread_running--; - pthread_mutex_unlock(&LOCK_ndb_util_thread); + mysql_mutex_unlock(&LOCK_ndb_util_thread); } /* wait for injector thread to finish */ ndbcluster_binlog_terminating= 1; - pthread_mutex_lock(&injector_mutex); - pthread_cond_signal(&injector_cond); + mysql_mutex_lock(&injector_mutex); + mysql_cond_signal(&injector_cond); while (ndb_binlog_thread_running > 0) - pthread_cond_wait(&injector_cond, &injector_mutex); - pthread_mutex_unlock(&injector_mutex); + mysql_cond_wait(&injector_cond, &injector_mutex); + mysql_mutex_unlock(&injector_mutex); - pthread_mutex_destroy(&injector_mutex); - pthread_cond_destroy(&injector_cond); - pthread_mutex_destroy(&ndb_schema_share_mutex); + mysql_mutex_destroy(&injector_mutex); + mysql_cond_destroy(&injector_cond); + mysql_mutex_destroy(&ndb_schema_share_mutex); #endif DBUG_RETURN(0); @@ -738,14 +743,14 @@ void ndbcluster_binlog_init_handlerton() */ static NDB_SHARE *ndbcluster_check_ndb_apply_status_share() { - pthread_mutex_lock(&ndbcluster_mutex); + mysql_mutex_lock(&ndbcluster_mutex); void *share= my_hash_search(&ndbcluster_open_tables, (uchar*) NDB_APPLY_TABLE_FILE, sizeof(NDB_APPLY_TABLE_FILE) - 1); DBUG_PRINT("info",("ndbcluster_check_ndb_apply_status_share %s 0x%lx", NDB_APPLY_TABLE_FILE, (long) share)); - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); return (NDB_SHARE*) share; } @@ -756,14 +761,14 @@ static NDB_SHARE *ndbcluster_check_ndb_apply_status_share() */ static NDB_SHARE *ndbcluster_check_ndb_schema_share() { - pthread_mutex_lock(&ndbcluster_mutex); + mysql_mutex_lock(&ndbcluster_mutex); void *share= my_hash_search(&ndbcluster_open_tables, (uchar*) NDB_SCHEMA_TABLE_FILE, sizeof(NDB_SCHEMA_TABLE_FILE) - 1); DBUG_PRINT("info",("ndbcluster_check_ndb_schema_share %s 0x%lx", NDB_SCHEMA_TABLE_FILE, (long) share)); - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); return (NDB_SHARE*) share; } @@ -788,7 +793,7 @@ static int ndbcluster_create_ndb_apply_status_table(THD *thd) char buf[1024 + 1], *end; - if (ndb_extra_logging) + if (opt_ndb_extra_logging) sql_print_information("NDB: Creating " NDB_REP_DB "." NDB_APPLY_TABLE); /* @@ -798,7 +803,7 @@ static int ndbcluster_create_ndb_apply_status_table(THD *thd) { build_table_filename(buf, sizeof(buf) - 1, NDB_REP_DB, NDB_APPLY_TABLE, reg_ext, 0); - my_delete(buf, MYF(0)); + mysql_file_delete(key_file_frm, buf, MYF(0)); } /* @@ -846,7 +851,7 @@ static int ndbcluster_create_schema_table(THD *thd) char buf[1024 + 1], *end; - if (ndb_extra_logging) + if (opt_ndb_extra_logging) sql_print_information("NDB: Creating " NDB_REP_DB "." NDB_SCHEMA_TABLE); /* @@ -856,7 +861,7 @@ static int ndbcluster_create_schema_table(THD *thd) { build_table_filename(buf, sizeof(buf) - 1, NDB_REP_DB, NDB_SCHEMA_TABLE, reg_ext, 0); - my_delete(buf, MYF(0)); + mysql_file_delete(key_file_frm, buf, MYF(0)); } /* @@ -891,9 +896,9 @@ int ndbcluster_setup_binlog_table_shares(THD *thd) if (!ndb_schema_share && ndbcluster_check_ndb_schema_share() == 0) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); ndb_create_table_from_engine(thd, NDB_REP_DB, NDB_SCHEMA_TABLE); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); if (!ndb_schema_share) { ndbcluster_create_schema_table(thd); @@ -905,9 +910,9 @@ int ndbcluster_setup_binlog_table_shares(THD *thd) if (!ndb_apply_status_share && ndbcluster_check_ndb_apply_status_share() == 0) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); ndb_create_table_from_engine(thd, NDB_REP_DB, NDB_APPLY_TABLE); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); if (!ndb_apply_status_share) { ndbcluster_create_ndb_apply_status_table(thd); @@ -917,14 +922,14 @@ int ndbcluster_setup_binlog_table_shares(THD *thd) } if (!ndbcluster_find_all_files(thd)) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); ndb_binlog_tables_inited= TRUE; - if (ndb_extra_logging) + if (opt_ndb_extra_logging) sql_print_information("NDB Binlog: ndb tables writable"); close_cached_tables(NULL, NULL, TRUE, FALSE, FALSE); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); /* Signal injector thread that all is setup */ - pthread_cond_signal(&injector_cond); + mysql_cond_signal(&injector_cond); } return 0; } @@ -1235,12 +1240,12 @@ static void ndb_report_waiting(const char *key, { ulonglong ndb_latest_epoch= 0; const char *proc_info= "<no info>"; - pthread_mutex_lock(&injector_mutex); + mysql_mutex_lock(&injector_mutex); if (injector_ndb) ndb_latest_epoch= injector_ndb->getLatestGCI(); if (injector_thd) proc_info= injector_thd->proc_info; - pthread_mutex_unlock(&injector_mutex); + mysql_mutex_unlock(&injector_mutex); sql_print_information("NDB %s:" " waiting max %u sec for %s %s." " epochs: (%u,%u,%u)" @@ -1353,15 +1358,15 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share, bitmap_set_all(&schema_subscribers); /* begin protect ndb_schema_share */ - pthread_mutex_lock(&ndb_schema_share_mutex); + mysql_mutex_lock(&ndb_schema_share_mutex); if (ndb_schema_share == 0) { - pthread_mutex_unlock(&ndb_schema_share_mutex); + mysql_mutex_unlock(&ndb_schema_share_mutex); if (ndb_schema_object) ndb_free_schema_object(&ndb_schema_object, FALSE); DBUG_RETURN(0); } - (void) pthread_mutex_lock(&ndb_schema_share->mutex); + mysql_mutex_lock(&ndb_schema_share->mutex); for (i= 0; i < no_storage_nodes; i++) { MY_BITMAP *table_subscribers= &ndb_schema_share->subscriber_bitmap[i]; @@ -1372,8 +1377,8 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share, updated= 1; } } - (void) pthread_mutex_unlock(&ndb_schema_share->mutex); - pthread_mutex_unlock(&ndb_schema_share_mutex); + mysql_mutex_unlock(&ndb_schema_share->mutex); + mysql_mutex_unlock(&ndb_schema_share_mutex); /* end protect ndb_schema_share */ if (updated) @@ -1393,10 +1398,10 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share, if (ndb_schema_object) { - (void) pthread_mutex_lock(&ndb_schema_object->mutex); + mysql_mutex_lock(&ndb_schema_object->mutex); memcpy(ndb_schema_object->slock, schema_subscribers.bitmap, sizeof(ndb_schema_object->slock)); - (void) pthread_mutex_unlock(&ndb_schema_object->mutex); + mysql_mutex_unlock(&ndb_schema_object->mutex); } DBUG_DUMP("schema_subscribers", (uchar*)schema_subscribers.bitmap, @@ -1498,7 +1503,7 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share, r|= op->setValue(SCHEMA_TYPE_I, log_type); DBUG_ASSERT(r == 0); /* any value */ - if (!(thd->options & OPTION_BIN_LOG)) + if (!(thd->variables.option_bits & OPTION_BIN_LOG)) r|= op->setAnyValue(NDB_ANYVALUE_FOR_NOLOGGING); else r|= op->setAnyValue(thd->server_id); @@ -1561,12 +1566,12 @@ end: else dict->forceGCPWait(); - int max_timeout= opt_ndb_sync_timeout; - (void) pthread_mutex_lock(&ndb_schema_object->mutex); + int max_timeout= DEFAULT_SYNC_TIMEOUT; + mysql_mutex_lock(&ndb_schema_object->mutex); if (have_lock_open) { - safe_mutex_assert_owner(&LOCK_open); - (void) pthread_mutex_unlock(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } while (1) { @@ -1574,20 +1579,20 @@ end: int i; int no_storage_nodes= g_ndb_cluster_connection->no_db_nodes(); set_timespec(abstime, 1); - int ret= pthread_cond_timedwait(&injector_cond, - &ndb_schema_object->mutex, - &abstime); + int ret= mysql_cond_timedwait(&injector_cond, + &ndb_schema_object->mutex, + &abstime); if (thd->killed) break; /* begin protect ndb_schema_share */ - pthread_mutex_lock(&ndb_schema_share_mutex); + mysql_mutex_lock(&ndb_schema_share_mutex); if (ndb_schema_share == 0) { - pthread_mutex_unlock(&ndb_schema_share_mutex); + mysql_mutex_unlock(&ndb_schema_share_mutex); break; } - (void) pthread_mutex_lock(&ndb_schema_share->mutex); + mysql_mutex_lock(&ndb_schema_share->mutex); for (i= 0; i < no_storage_nodes; i++) { /* remove any unsubscribed from schema_subscribers */ @@ -1595,8 +1600,8 @@ end: if (!bitmap_is_clear_all(tmp)) bitmap_intersect(&schema_subscribers, tmp); } - (void) pthread_mutex_unlock(&ndb_schema_share->mutex); - pthread_mutex_unlock(&ndb_schema_share_mutex); + mysql_mutex_unlock(&ndb_schema_share->mutex); + mysql_mutex_unlock(&ndb_schema_share_mutex); /* end protect ndb_schema_share */ /* remove any unsubscribed from ndb_schema_object->slock */ @@ -1618,16 +1623,16 @@ end: type_str, ndb_schema_object->key); break; } - if (ndb_extra_logging) + if (opt_ndb_extra_logging) ndb_report_waiting(type_str, max_timeout, "distributing", ndb_schema_object->key); } } if (have_lock_open) { - (void) pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); } - (void) pthread_mutex_unlock(&ndb_schema_object->mutex); + mysql_mutex_unlock(&ndb_schema_object->mutex); } if (ndb_schema_object) @@ -1709,7 +1714,7 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp, { DBUG_DUMP("frm", (uchar*) altered_table->getFrmData(), altered_table->getFrmLength()); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); Ndb_table_guard ndbtab_g(dict, tabname); const NDBTAB *old= ndbtab_g.get_table(); if (!old && @@ -1747,7 +1752,7 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp, dbname= table_share->db.str; tabname= table_share->table_name.str; - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } my_free((char*)data, MYF(MY_ALLOW_ZERO_PTR)); my_free((char*)pack_data, MYF(MY_ALLOW_ZERO_PTR)); @@ -1757,17 +1762,17 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp, if (is_online_alter_table) { /* Signal ha_ndbcluster::alter_table that drop is done */ - (void) pthread_cond_signal(&injector_cond); + mysql_cond_signal(&injector_cond); DBUG_RETURN(0); } - (void) pthread_mutex_lock(&share->mutex); + mysql_mutex_lock(&share->mutex); if (is_rename_table && !is_remote_change) { DBUG_PRINT("info", ("Detected name change of table %s.%s", share->db, share->table_name)); /* ToDo: remove printout */ - if (ndb_extra_logging) + if (opt_ndb_extra_logging) sql_print_information("NDB Binlog: rename table %s%s/%s -> %s.", share_prefix, share->table->s->db.str, share->table->s->table_name.str, @@ -1797,10 +1802,10 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp, // either just us or drop table handling as well /* Signal ha_ndbcluster::delete/rename_table that drop is done */ - (void) pthread_mutex_unlock(&share->mutex); - (void) pthread_cond_signal(&injector_cond); + mysql_mutex_unlock(&share->mutex); + mysql_cond_signal(&injector_cond); - pthread_mutex_lock(&ndbcluster_mutex); + mysql_mutex_lock(&ndbcluster_mutex); /* ndb_share reference binlog free */ DBUG_PRINT("NDB_SHARE", ("%s binlog free use_count: %u", share->key, share->use_count)); @@ -1826,14 +1831,14 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp, } else share= 0; - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); pOp->setCustomData(0); - pthread_mutex_lock(&injector_mutex); + mysql_mutex_lock(&injector_mutex); ndb->dropEventOperation(pOp); pOp= 0; - pthread_mutex_unlock(&injector_mutex); + mysql_mutex_unlock(&injector_mutex); if (do_close_cached_tables) { @@ -1870,7 +1875,7 @@ static void ndb_binlog_query(THD *thd, Cluster_schema *schema) thd->db= schema->db; int errcode = query_error_code(thd, thd->killed == THD::NOT_KILLED); thd->binlog_query(THD::STMT_QUERY_TYPE, schema->query, - schema->query_length, FALSE, + schema->query_length, FALSE, TRUE, schema->name[0] == 0 || thd->db[0] == 0, errcode); thd->server_id= thd_server_id_save; @@ -1974,7 +1979,7 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, } // fall through case SOT_CREATE_TABLE: - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (ndbcluster_check_if_local_table(schema->db, schema->name)) { DBUG_PRINT("info", ("NDB Binlog: Skipping locally defined table '%s.%s'", @@ -1988,7 +1993,7 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, { print_could_not_discover_error(thd, schema); } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); log_query= 1; break; case SOT_DROP_DB: @@ -2057,18 +2062,18 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, // skip break; case NDBEVENT::TE_CLUSTER_FAILURE: - if (ndb_extra_logging) + if (opt_ndb_extra_logging) sql_print_information("NDB Binlog: cluster failure for %s at epoch %u.", ndb_schema_share->key, (unsigned) pOp->getGCI()); // fall through case NDBEVENT::TE_DROP: - if (ndb_extra_logging && + if (opt_ndb_extra_logging && ndb_binlog_tables_inited && ndb_binlog_running) sql_print_information("NDB Binlog: ndb tables initially " "read only on reconnect."); /* begin protect ndb_schema_share */ - pthread_mutex_lock(&ndb_schema_share_mutex); + mysql_mutex_lock(&ndb_schema_share_mutex); /* ndb_share reference binlog extra free */ DBUG_PRINT("NDB_SHARE", ("%s binlog extra free use_count: %u", ndb_schema_share->key, @@ -2076,7 +2081,7 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, free_share(&ndb_schema_share); ndb_schema_share= 0; ndb_binlog_tables_inited= 0; - pthread_mutex_unlock(&ndb_schema_share_mutex); + mysql_mutex_unlock(&ndb_schema_share_mutex); /* end protect ndb_schema_share */ close_cached_tables(NULL, NULL, FALSE, FALSE, FALSE); @@ -2088,10 +2093,10 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, { uint8 node_id= g_node_id_map[pOp->getNdbdNodeId()]; DBUG_ASSERT(node_id != 0xFF); - (void) pthread_mutex_lock(&tmp_share->mutex); + mysql_mutex_lock(&tmp_share->mutex); bitmap_clear_all(&tmp_share->subscriber_bitmap[node_id]); DBUG_PRINT("info",("NODE_FAILURE UNSUBSCRIBE[%d]", node_id)); - if (ndb_extra_logging) + if (opt_ndb_extra_logging) { sql_print_information("NDB Binlog: Node: %d, down," " Subscriber bitmask %x%x", @@ -2099,8 +2104,8 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, tmp_share->subscriber_bitmap[node_id].bitmap[1], tmp_share->subscriber_bitmap[node_id].bitmap[0]); } - (void) pthread_mutex_unlock(&tmp_share->mutex); - (void) pthread_cond_signal(&injector_cond); + mysql_mutex_unlock(&tmp_share->mutex); + mysql_cond_signal(&injector_cond); break; } case NDBEVENT::TE_SUBSCRIBE: @@ -2108,10 +2113,10 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, uint8 node_id= g_node_id_map[pOp->getNdbdNodeId()]; uint8 req_id= pOp->getReqNodeId(); DBUG_ASSERT(req_id != 0 && node_id != 0xFF); - (void) pthread_mutex_lock(&tmp_share->mutex); + mysql_mutex_lock(&tmp_share->mutex); bitmap_set_bit(&tmp_share->subscriber_bitmap[node_id], req_id); DBUG_PRINT("info",("SUBSCRIBE[%d] %d", node_id, req_id)); - if (ndb_extra_logging) + if (opt_ndb_extra_logging) { sql_print_information("NDB Binlog: Node: %d, subscribe from node %d," " Subscriber bitmask %x%x", @@ -2120,8 +2125,8 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, tmp_share->subscriber_bitmap[node_id].bitmap[1], tmp_share->subscriber_bitmap[node_id].bitmap[0]); } - (void) pthread_mutex_unlock(&tmp_share->mutex); - (void) pthread_cond_signal(&injector_cond); + mysql_mutex_unlock(&tmp_share->mutex); + mysql_cond_signal(&injector_cond); break; } case NDBEVENT::TE_UNSUBSCRIBE: @@ -2129,10 +2134,10 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, uint8 node_id= g_node_id_map[pOp->getNdbdNodeId()]; uint8 req_id= pOp->getReqNodeId(); DBUG_ASSERT(req_id != 0 && node_id != 0xFF); - (void) pthread_mutex_lock(&tmp_share->mutex); + mysql_mutex_lock(&tmp_share->mutex); bitmap_clear_bit(&tmp_share->subscriber_bitmap[node_id], req_id); DBUG_PRINT("info",("UNSUBSCRIBE[%d] %d", node_id, req_id)); - if (ndb_extra_logging) + if (opt_ndb_extra_logging) { sql_print_information("NDB Binlog: Node: %d, unsubscribe from node %d," " Subscriber bitmask %x%x", @@ -2141,8 +2146,8 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, tmp_share->subscriber_bitmap[node_id].bitmap[1], tmp_share->subscriber_bitmap[node_id].bitmap[0]); } - (void) pthread_mutex_unlock(&tmp_share->mutex); - (void) pthread_cond_signal(&injector_cond); + mysql_mutex_unlock(&tmp_share->mutex); + mysql_cond_signal(&injector_cond); break; } default: @@ -2182,22 +2187,22 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd, build_table_filename(key, sizeof(key) - 1, schema->db, schema->name, "", 0); if (schema_type == SOT_CLEAR_SLOCK) { - pthread_mutex_lock(&ndbcluster_mutex); + mysql_mutex_lock(&ndbcluster_mutex); NDB_SCHEMA_OBJECT *ndb_schema_object= (NDB_SCHEMA_OBJECT*) my_hash_search(&ndb_schema_objects, (uchar*) key, strlen(key)); if (ndb_schema_object) { - pthread_mutex_lock(&ndb_schema_object->mutex); + mysql_mutex_lock(&ndb_schema_object->mutex); memcpy(ndb_schema_object->slock, schema->slock, sizeof(ndb_schema_object->slock)); DBUG_DUMP("ndb_schema_object->slock_bitmap.bitmap", (uchar*)ndb_schema_object->slock_bitmap.bitmap, no_bytes_in_map(&ndb_schema_object->slock_bitmap)); - pthread_mutex_unlock(&ndb_schema_object->mutex); - pthread_cond_signal(&injector_cond); + mysql_mutex_unlock(&ndb_schema_object->mutex); + mysql_cond_signal(&injector_cond); } - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); continue; } /* ndb_share reference temporary, free below */ @@ -2257,7 +2262,7 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd, free_share(&share); share= 0; } - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (ndbcluster_check_if_local_table(schema->db, schema->name)) { DBUG_PRINT("info", ("NDB Binlog: Skipping locally defined table '%s.%s'", @@ -2271,7 +2276,7 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd, { print_could_not_discover_error(thd, schema); } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } break; default: @@ -2369,8 +2374,8 @@ int ndb_add_ndb_binlog_index(THD *thd, void *_row) Turn of binlogging to prevent the table changes to be written to the binary log. */ - ulong saved_options= thd->options; - thd->options&= ~(OPTION_BIN_LOG); + ulong saved_options= thd->variables.option_bits; + thd->variables.option_bits&= ~OPTION_BIN_LOG; for ( ; ; ) /* loop for need_reopen */ { @@ -2420,12 +2425,12 @@ int ndb_add_ndb_binlog_index(THD *thd, void *_row) mysql_unlock_tables(thd, thd->lock); thd->lock= 0; - thd->options= saved_options; + thd->variables.option_bits= saved_options; return 0; add_ndb_binlog_index_err: close_thread_tables(thd); ndb_binlog_index= 0; - thd->options= saved_options; + thd->variables.option_bits= saved_options; return error; } @@ -2458,27 +2463,29 @@ int ndbcluster_binlog_start() DBUG_RETURN(-1); } - pthread_mutex_init(&injector_mutex, MY_MUTEX_INIT_FAST); - pthread_cond_init(&injector_cond, NULL); - pthread_mutex_init(&ndb_schema_share_mutex, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_injector_mutex, &injector_mutex, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_injector_cond, &injector_cond, NULL); + mysql_mutex_init(key_ndb_schema_share_mutex, + &ndb_schema_share_mutex, MY_MUTEX_INIT_FAST); /* Create injector thread */ - if (pthread_create(&ndb_binlog_thread, &connection_attrib, - ndb_binlog_thread_func, 0)) + if (mysql_thread_create(key_thread_ndb_binlog, + &ndb_binlog_thread, &connection_attrib, + ndb_binlog_thread_func, 0)) { DBUG_PRINT("error", ("Could not create ndb injector thread")); - pthread_cond_destroy(&injector_cond); - pthread_mutex_destroy(&injector_mutex); + mysql_cond_destroy(&injector_cond); + mysql_mutex_destroy(&injector_mutex); DBUG_RETURN(-1); } ndbcluster_binlog_inited= 1; /* Wait for the injector thread to start */ - pthread_mutex_lock(&injector_mutex); + mysql_mutex_lock(&injector_mutex); while (!ndb_binlog_thread_running) - pthread_cond_wait(&injector_cond, &injector_mutex); - pthread_mutex_unlock(&injector_mutex); + mysql_cond_wait(&injector_cond, &injector_mutex); + mysql_mutex_unlock(&injector_mutex); if (ndb_binlog_thread_running < 0) DBUG_RETURN(-1); @@ -2568,7 +2575,7 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key, DBUG_ASSERT(! IS_NDB_BLOB_PREFIX(table_name)); DBUG_ASSERT(strlen(key) == key_len); - pthread_mutex_lock(&ndbcluster_mutex); + mysql_mutex_lock(&ndbcluster_mutex); /* Handle any trailing share */ NDB_SHARE *share= (NDB_SHARE*) my_hash_search(&ndbcluster_open_tables, @@ -2580,7 +2587,7 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key, share->op != 0 || share->op_old != 0) { - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); DBUG_RETURN(0); // replication already setup, or should not } } @@ -2590,7 +2597,7 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key, if (share->op || share->op_old) { my_errno= HA_ERR_TABLE_EXIST; - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); DBUG_RETURN(1); } if (!share_may_exist || share->connect_count != @@ -2633,10 +2640,10 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key, if (!do_event_op) { share->flags|= NSF_NO_BINLOG; - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); DBUG_RETURN(0); } - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); while (share && !IS_TMP_PREFIX(table_name)) { @@ -2655,7 +2662,7 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key, const NDBTAB *ndbtab= ndbtab_g.get_table(); if (ndbtab == 0) { - if (ndb_extra_logging) + if (opt_ndb_extra_logging) sql_print_information("NDB Binlog: Failed to get table %s from ndb: " "%s, %d", key, dict->getNdbError().message, dict->getNdbError().code); @@ -2677,7 +2684,7 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key, event_name.c_ptr()); break; // error } - if (ndb_extra_logging) + if (opt_ndb_extra_logging) sql_print_information("NDB Binlog: " "CREATE (DISCOVER) TABLE Event: %s", event_name.c_ptr()); @@ -2685,7 +2692,7 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key, else { delete ev; - if (ndb_extra_logging) + if (opt_ndb_extra_logging) sql_print_information("NDB Binlog: DISCOVER TABLE Event: %s", event_name.c_ptr()); } @@ -2929,14 +2936,14 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, int retry_sleep= 100; while (1) { - pthread_mutex_lock(&injector_mutex); + mysql_mutex_lock(&injector_mutex); Ndb *ndb= injector_ndb; if (do_ndb_schema_share) ndb= schema_ndb; if (ndb == 0) { - pthread_mutex_unlock(&injector_mutex); + mysql_mutex_unlock(&injector_mutex); DBUG_RETURN(-1); } @@ -2961,7 +2968,7 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, ndb->getNdbError().code, ndb->getNdbError().message, "NDB"); - pthread_mutex_unlock(&injector_mutex); + mysql_mutex_unlock(&injector_mutex); DBUG_RETURN(-1); } @@ -3011,7 +3018,7 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, op->getNdbError().message, "NDB"); ndb->dropEventOperation(op); - pthread_mutex_unlock(&injector_mutex); + mysql_mutex_unlock(&injector_mutex); DBUG_RETURN(-1); } } @@ -3053,7 +3060,7 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, op->getNdbError().code, op->getNdbError().message); } ndb->dropEventOperation(op); - pthread_mutex_unlock(&injector_mutex); + mysql_mutex_unlock(&injector_mutex); if (retries) { my_sleep(retry_sleep); @@ -3061,7 +3068,7 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, } DBUG_RETURN(-1); } - pthread_mutex_unlock(&injector_mutex); + mysql_mutex_unlock(&injector_mutex); break; } @@ -3075,7 +3082,7 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, ndb_apply_status_share= get_share(share); DBUG_PRINT("NDB_SHARE", ("%s binlog extra use_count: %u", share->key, share->use_count)); - (void) pthread_cond_signal(&injector_cond); + mysql_cond_signal(&injector_cond); } else if (do_ndb_schema_share) { @@ -3083,13 +3090,13 @@ ndbcluster_create_event_ops(NDB_SHARE *share, const NDBTAB *ndbtab, ndb_schema_share= get_share(share); DBUG_PRINT("NDB_SHARE", ("%s binlog extra use_count: %u", share->key, share->use_count)); - (void) pthread_cond_signal(&injector_cond); + mysql_cond_signal(&injector_cond); } DBUG_PRINT("info",("%s share->op: 0x%lx share->use_count: %u", share->key, (long) share->op, share->use_count)); - if (ndb_extra_logging) + if (opt_ndb_extra_logging) sql_print_information("NDB Binlog: logging %s", share->key); DBUG_RETURN(0); } @@ -3154,17 +3161,17 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name, #define SYNC_DROP_ #ifdef SYNC_DROP_ thd->proc_info= "Syncing ndb table schema operation and binlog"; - (void) pthread_mutex_lock(&share->mutex); - safe_mutex_assert_owner(&LOCK_open); - (void) pthread_mutex_unlock(&LOCK_open); - int max_timeout= opt_ndb_sync_timeout; + mysql_mutex_lock(&share->mutex); + mysql_mutex_assert_owner(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); + int max_timeout= DEFAULT_SYNC_TIMEOUT; while (share->op) { struct timespec abstime; set_timespec(abstime, 1); - int ret= pthread_cond_timedwait(&injector_cond, - &share->mutex, - &abstime); + int ret= mysql_cond_timedwait(&injector_cond, + &share->mutex, + &abstime); if (thd->killed || share->op == 0) break; @@ -3177,18 +3184,18 @@ ndbcluster_handle_drop_table(Ndb *ndb, const char *event_name, type_str, share->key); break; } - if (ndb_extra_logging) + if (opt_ndb_extra_logging) ndb_report_waiting(type_str, max_timeout, type_str, share->key); } } - (void) pthread_mutex_lock(&LOCK_open); - (void) pthread_mutex_unlock(&share->mutex); + mysql_mutex_lock(&LOCK_open); + mysql_mutex_unlock(&share->mutex); #else - (void) pthread_mutex_lock(&share->mutex); + mysql_mutex_lock(&share->mutex); share->op_old= share->op; share->op= 0; - (void) pthread_mutex_unlock(&share->mutex); + mysql_mutex_unlock(&share->mutex); #endif thd->proc_info= save_proc_info; @@ -3255,12 +3262,12 @@ ndb_binlog_thread_handle_non_data_event(THD *thd, Ndb *ndb, switch (type) { case NDBEVENT::TE_CLUSTER_FAILURE: - if (ndb_extra_logging) + if (opt_ndb_extra_logging) sql_print_information("NDB Binlog: cluster failure for %s at epoch %u.", share->key, (unsigned) pOp->getGCI()); if (ndb_apply_status_share == share) { - if (ndb_extra_logging && + if (opt_ndb_extra_logging && ndb_binlog_tables_inited && ndb_binlog_running) sql_print_information("NDB Binlog: ndb tables initially " "read only on reconnect."); @@ -3280,7 +3287,7 @@ ndb_binlog_thread_handle_non_data_event(THD *thd, Ndb *ndb, case NDBEVENT::TE_DROP: if (ndb_apply_status_share == share) { - if (ndb_extra_logging && + if (opt_ndb_extra_logging && ndb_binlog_tables_inited && ndb_binlog_running) sql_print_information("NDB Binlog: ndb tables initially " "read only on reconnect."); @@ -3292,7 +3299,7 @@ ndb_binlog_thread_handle_non_data_event(THD *thd, Ndb *ndb, ndb_binlog_tables_inited= 0; } /* ToDo: remove printout */ - if (ndb_extra_logging) + if (opt_ndb_extra_logging) sql_print_information("NDB Binlog: drop table %s.", share->key); // fall through case NDBEVENT::TE_ALTER: @@ -3556,7 +3563,7 @@ static NDB_SCHEMA_OBJECT *ndb_get_schema_object(const char *key, DBUG_PRINT("enter", ("key: '%s'", key)); if (!have_lock) - pthread_mutex_lock(&ndbcluster_mutex); + mysql_mutex_lock(&ndbcluster_mutex); while (!(ndb_schema_object= (NDB_SCHEMA_OBJECT*) my_hash_search(&ndb_schema_objects, (uchar*) key, @@ -3582,7 +3589,7 @@ static NDB_SCHEMA_OBJECT *ndb_get_schema_object(const char *key, my_free((uchar*) ndb_schema_object, 0); break; } - pthread_mutex_init(&ndb_schema_object->mutex, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_ndb_schema_object_mutex, &ndb_schema_object->mutex, MY_MUTEX_INIT_FAST); bitmap_init(&ndb_schema_object->slock_bitmap, ndb_schema_object->slock, sizeof(ndb_schema_object->slock)*8, FALSE); bitmap_clear_all(&ndb_schema_object->slock_bitmap); @@ -3594,7 +3601,7 @@ static NDB_SCHEMA_OBJECT *ndb_get_schema_object(const char *key, DBUG_PRINT("info", ("use_count: %d", ndb_schema_object->use_count)); } if (!have_lock) - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); DBUG_RETURN(ndb_schema_object); } @@ -3605,12 +3612,12 @@ static void ndb_free_schema_object(NDB_SCHEMA_OBJECT **ndb_schema_object, DBUG_ENTER("ndb_free_schema_object"); DBUG_PRINT("enter", ("key: '%s'", (*ndb_schema_object)->key)); if (!have_lock) - pthread_mutex_lock(&ndbcluster_mutex); + mysql_mutex_lock(&ndbcluster_mutex); if (!--(*ndb_schema_object)->use_count) { DBUG_PRINT("info", ("use_count: %d", (*ndb_schema_object)->use_count)); my_hash_delete(&ndb_schema_objects, (uchar*) *ndb_schema_object); - pthread_mutex_destroy(&(*ndb_schema_object)->mutex); + mysql_mutex_destroy(&(*ndb_schema_object)->mutex); my_free((uchar*) *ndb_schema_object, MYF(0)); *ndb_schema_object= 0; } @@ -3619,10 +3626,12 @@ static void ndb_free_schema_object(NDB_SCHEMA_OBJECT **ndb_schema_object, DBUG_PRINT("info", ("use_count: %d", (*ndb_schema_object)->use_count)); } if (!have_lock) - pthread_mutex_unlock(&ndbcluster_mutex); + mysql_mutex_unlock(&ndbcluster_mutex); DBUG_VOID_RETURN; } +extern ulong opt_ndb_report_thresh_binlog_epoch_slip; +extern ulong opt_ndb_report_thresh_binlog_mem_usage; pthread_handler_t ndb_binlog_thread_func(void *arg) { @@ -3638,7 +3647,7 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) Timer main_timer; #endif - pthread_mutex_lock(&injector_mutex); + mysql_mutex_lock(&injector_mutex); /* Set up the Thread */ @@ -3647,13 +3656,16 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) thd= new THD; /* note that contructor of THD uses DBUG_ */ THD_CHECK_SENTRY(thd); + thd->set_current_stmt_binlog_format_row(); /* We need to set thd->thread_id before thd->store_globals, or it will set an invalid value for thd->variables.pseudo_thread_id. */ - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thd->thread_id= thread_id++; - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); + + mysql_thread_set_psi_id(thd->thread_id); thd->thread_stack= (char*) &thd; /* remember where our stack is */ if (thd->store_globals()) @@ -3661,15 +3673,14 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) thd->cleanup(); delete thd; ndb_binlog_thread_running= -1; - pthread_mutex_unlock(&injector_mutex); - pthread_cond_signal(&injector_cond); + mysql_mutex_unlock(&injector_mutex); + mysql_cond_signal(&injector_cond); DBUG_LEAVE; // Must match DBUG_ENTER() my_thread_end(); pthread_exit(0); return NULL; // Avoid compiler warnings } - lex_start(thd); thd->init_for_queries(); thd->command= COM_DAEMON; @@ -3688,9 +3699,9 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) pthread_detach_this_thread(); thd->real_id= pthread_self(); - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); threads.append(thd); - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); thd->lex->start_transaction_opt= 0; if (!(s_ndb= new Ndb(g_ndb_cluster_connection, "")) || @@ -3698,8 +3709,8 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) { sql_print_error("NDB Binlog: Getting Schema Ndb object failed"); ndb_binlog_thread_running= -1; - pthread_mutex_unlock(&injector_mutex); - pthread_cond_signal(&injector_cond); + mysql_mutex_unlock(&injector_mutex); + mysql_cond_signal(&injector_cond); goto err; } @@ -3709,8 +3720,8 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) { sql_print_error("NDB Binlog: Getting Ndb object failed"); ndb_binlog_thread_running= -1; - pthread_mutex_unlock(&injector_mutex); - pthread_cond_signal(&injector_cond); + mysql_mutex_unlock(&injector_mutex); + mysql_cond_signal(&injector_cond); goto err; } @@ -3723,7 +3734,7 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) Used by both sql client thread and binlog thread to interact with the storage - pthread_mutex_lock(&injector_mutex); + mysql_mutex_lock(&injector_mutex); */ injector_thd= thd; injector_ndb= i_ndb; @@ -3738,27 +3749,27 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) /* Thread start up completed */ ndb_binlog_thread_running= 1; - pthread_mutex_unlock(&injector_mutex); - pthread_cond_signal(&injector_cond); + mysql_mutex_unlock(&injector_mutex); + mysql_cond_signal(&injector_cond); /* wait for mysql server to start (so that the binlog is started and thus can receive the first GAP event) */ - pthread_mutex_lock(&LOCK_server_started); + mysql_mutex_lock(&LOCK_server_started); while (!mysqld_server_started) { struct timespec abstime; set_timespec(abstime, 1); - pthread_cond_timedwait(&COND_server_started, &LOCK_server_started, - &abstime); + mysql_cond_timedwait(&COND_server_started, &LOCK_server_started, + &abstime); if (ndbcluster_terminating) { - pthread_mutex_unlock(&LOCK_server_started); + mysql_mutex_unlock(&LOCK_server_started); goto err; } } - pthread_mutex_unlock(&LOCK_server_started); + mysql_mutex_unlock(&LOCK_server_started); restart: /* Main NDB Injector loop @@ -3801,21 +3812,21 @@ restart: { thd->proc_info= "Waiting for ndbcluster to start"; - pthread_mutex_lock(&injector_mutex); + mysql_mutex_lock(&injector_mutex); while (!ndb_schema_share || (ndb_binlog_running && !ndb_apply_status_share)) { /* ndb not connected yet */ struct timespec abstime; set_timespec(abstime, 1); - pthread_cond_timedwait(&injector_cond, &injector_mutex, &abstime); + mysql_cond_timedwait(&injector_cond, &injector_mutex, &abstime); if (ndbcluster_binlog_terminating) { - pthread_mutex_unlock(&injector_mutex); + mysql_mutex_unlock(&injector_mutex); goto err; } } - pthread_mutex_unlock(&injector_mutex); + mysql_mutex_unlock(&injector_mutex); if (thd_ndb == NULL) { @@ -3882,7 +3893,7 @@ restart: "Changes to the database that occured while " "disconnected will not be in the binlog"); } - if (ndb_extra_logging) + if (opt_ndb_extra_logging) { sql_print_information("NDB Binlog: starting log at epoch %u", (unsigned)schema_gci); @@ -3984,9 +3995,9 @@ restart: { thd->proc_info= "Processing events from schema table"; s_ndb-> - setReportThreshEventGCISlip(ndb_report_thresh_binlog_epoch_slip); + setReportThreshEventGCISlip(opt_ndb_report_thresh_binlog_epoch_slip); s_ndb-> - setReportThreshEventFreeMem(ndb_report_thresh_binlog_mem_usage); + setReportThreshEventFreeMem(opt_ndb_report_thresh_binlog_mem_usage); NdbEventOperation *pOp= s_ndb->nextEvent(); while (pOp != NULL) { @@ -4049,8 +4060,8 @@ restart: /* initialize some variables for this epoch */ g_ndb_log_slave_updates= opt_log_slave_updates; i_ndb-> - setReportThreshEventGCISlip(ndb_report_thresh_binlog_epoch_slip); - i_ndb->setReportThreshEventFreeMem(ndb_report_thresh_binlog_mem_usage); + setReportThreshEventGCISlip(opt_ndb_report_thresh_binlog_epoch_slip); + i_ndb->setReportThreshEventFreeMem(opt_ndb_report_thresh_binlog_mem_usage); bzero((char*) &row, sizeof(row)); thd->variables.character_set_client= &my_charset_latin1; @@ -4286,13 +4297,13 @@ err: DBUG_PRINT("info",("Shutting down cluster binlog thread")); thd->proc_info= "Shutting down"; close_thread_tables(thd); - pthread_mutex_lock(&injector_mutex); + mysql_mutex_lock(&injector_mutex); /* don't mess with the injector_ndb anymore from other threads */ injector_thd= 0; injector_ndb= 0; p_latest_trans_gci= 0; schema_ndb= 0; - pthread_mutex_unlock(&injector_mutex); + mysql_mutex_unlock(&injector_mutex); thd->db= 0; // as not to try to free memory if (ndb_apply_status_share) @@ -4307,7 +4318,7 @@ err: if (ndb_schema_share) { /* begin protect ndb_schema_share */ - pthread_mutex_lock(&ndb_schema_share_mutex); + mysql_mutex_lock(&ndb_schema_share_mutex); /* ndb_share reference binlog extra free */ DBUG_PRINT("NDB_SHARE", ("%s binlog extra free use_count: %u", ndb_schema_share->key, @@ -4315,7 +4326,7 @@ err: free_share(&ndb_schema_share); ndb_schema_share= 0; ndb_binlog_tables_inited= 0; - pthread_mutex_unlock(&ndb_schema_share_mutex); + mysql_mutex_unlock(&ndb_schema_share_mutex); /* end protect ndb_schema_share */ } @@ -4375,7 +4386,7 @@ err: ndb_binlog_thread_running= -1; ndb_binlog_running= FALSE; - (void) pthread_cond_signal(&injector_cond); + mysql_cond_signal(&injector_cond); DBUG_PRINT("exit", ("ndb_binlog_thread")); @@ -4394,12 +4405,12 @@ ndbcluster_show_status_binlog(THD* thd, stat_print_fn *stat_print, ulonglong ndb_latest_epoch= 0; DBUG_ENTER("ndbcluster_show_status_binlog"); - pthread_mutex_lock(&injector_mutex); + mysql_mutex_lock(&injector_mutex); if (injector_ndb) { char buff1[22],buff2[22],buff3[22],buff4[22],buff5[22]; ndb_latest_epoch= injector_ndb->getLatestGCI(); - pthread_mutex_unlock(&injector_mutex); + mysql_mutex_unlock(&injector_mutex); buflen= snprintf(buf, sizeof(buf), @@ -4419,7 +4430,7 @@ ndbcluster_show_status_binlog(THD* thd, stat_print_fn *stat_print, DBUG_RETURN(TRUE); } else - pthread_mutex_unlock(&injector_mutex); + mysql_mutex_unlock(&injector_mutex); DBUG_RETURN(FALSE); } diff --git a/sql/ha_ndbcluster_binlog.h b/sql/ha_ndbcluster_binlog.h index d80dfe9ee74..32dac553ee8 100644 --- a/sql/ha_ndbcluster_binlog.h +++ b/sql/ha_ndbcluster_binlog.h @@ -1,7 +1,7 @@ #ifndef HA_NDBCLUSTER_BINLOG_INCLUDED #define HA_NDBCLUSTER_BINLOG_INCLUDED -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,8 +27,6 @@ typedef NdbDictionary::Event NDBEVENT; #define IS_TMP_PREFIX(A) (is_prefix(A, tmp_file_prefix)) -extern ulong ndb_extra_logging; - #define INJECTOR_EVENT_LEN 200 #define NDB_INVALID_SCHEMA_OBJECT 241 @@ -106,16 +104,24 @@ private: }; #ifdef HAVE_NDB_BINLOG + +#ifdef HAVE_PSI_INTERFACE +extern PSI_mutex_key key_injector_mutex, key_ndb_schema_share_mutex, + key_ndb_schema_object_mutex; +extern PSI_cond_key key_injector_cond; +extern PSI_thread_key key_thread_ndb_binlog; +#endif /* HAVE_PSI_INTERFACE */ + extern pthread_t ndb_binlog_thread; -extern pthread_mutex_t injector_mutex; -extern pthread_cond_t injector_cond; +extern mysql_mutex_t injector_mutex; +extern mysql_cond_t injector_cond; extern unsigned char g_node_id_map[max_ndb_nodes]; extern pthread_t ndb_util_thread; -extern pthread_mutex_t LOCK_ndb_util_thread; -extern pthread_cond_t COND_ndb_util_thread; +extern mysql_mutex_t LOCK_ndb_util_thread; +extern mysql_cond_t COND_ndb_util_thread; extern int ndbcluster_util_inited; -extern pthread_mutex_t ndbcluster_mutex; +extern mysql_mutex_t ndbcluster_mutex; extern HASH ndbcluster_open_tables; extern Ndb_cluster_connection* g_ndb_cluster_connection; extern long ndb_number_of_storage_nodes; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 04b7e9d7523..2b8806b824c 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -500,9 +500,9 @@ int ha_partition::create_handler_files(const char *path, strxmov(name, path, ha_par_ext, NullS); strxmov(old_name, old_path, ha_par_ext, NullS); if ((action_flag == CHF_DELETE_FLAG && - my_delete(name, MYF(MY_WME))) || + mysql_file_delete(key_file_partition, name, MYF(MY_WME))) || (action_flag == CHF_RENAME_FLAG && - my_rename(old_name, name, MYF(MY_WME)))) + mysql_file_rename(key_file_partition, old_name, name, MYF(MY_WME)))) { DBUG_RETURN(TRUE); } @@ -641,7 +641,7 @@ int ha_partition::drop_partitions(const char *path) part_elem->part_state= PART_IS_DROPPED; } } while (++i < num_parts); - VOID(sync_ddl_log()); + (void) sync_ddl_log(); DBUG_RETURN(error); } @@ -739,7 +739,7 @@ int ha_partition::rename_partitions(const char *path) part_elem->log_entry= NULL; /* Indicate success */ } } while (++i < temp_partitions); - VOID(sync_ddl_log()); + (void) sync_ddl_log(); } i= 0; do @@ -791,7 +791,7 @@ int ha_partition::rename_partitions(const char *path) error= ret_error; else if (deactivate_ddl_log_entry(sub_elem->log_entry->entry_pos)) error= 1; - VOID(sync_ddl_log()); + (void) sync_ddl_log(); } file= m_new_file[part]; create_subpartition_name(part_name_buff, path, @@ -822,7 +822,7 @@ int ha_partition::rename_partitions(const char *path) error= ret_error; else if (deactivate_ddl_log_entry(part_elem->log_entry->entry_pos)) error= 1; - VOID(sync_ddl_log()); + (void) sync_ddl_log(); } file= m_new_file[i]; create_partition_name(part_name_buff, path, @@ -840,7 +840,7 @@ int ha_partition::rename_partitions(const char *path) } } } while (++i < num_parts); - VOID(sync_ddl_log()); + (void) sync_ddl_log(); DBUG_RETURN(error); } @@ -1145,7 +1145,7 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt, { if (part_elem->part_state == PART_ADMIN) part_elem->part_state= PART_NORMAL; - } while (part_elem= part_it++); + } while ((part_elem= part_it++)); DBUG_RETURN(error); } } while (++j < num_subparts); @@ -1177,7 +1177,7 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt, { if (part_elem->part_state == PART_ADMIN) part_elem->part_state= PART_NORMAL; - } while (part_elem= part_it++); + } while ((part_elem= part_it++)); DBUG_RETURN(error); } } @@ -1306,9 +1306,9 @@ int ha_partition::prepare_new_partition(TABLE *tbl, DBUG_RETURN(0); error_external_lock: - VOID(file->close()); + (void) file->close(); error_open: - VOID(file->ha_delete_table(part_name)); + (void) file->ha_delete_table(part_name); error_create: DBUG_RETURN(error); } @@ -2007,8 +2007,7 @@ partition_element *ha_partition::find_partition_element(uint part_id) return part_elem; } DBUG_ASSERT(0); - my_error(ER_OUT_OF_RESOURCES, MYF(0)); - current_thd->fatal_error(); // Abort + my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); return NULL; } @@ -2233,12 +2232,13 @@ bool ha_partition::create_handler_file(const char *name) to be used at open, delete_table and rename_table */ fn_format(file_name, name, "", ha_par_ext, MY_APPEND_EXT); - if ((file= my_create(file_name, CREATE_MODE, O_RDWR | O_TRUNC, - MYF(MY_WME))) >= 0) + if ((file= mysql_file_create(key_file_partition, + file_name, CREATE_MODE, O_RDWR | O_TRUNC, + MYF(MY_WME))) >= 0) { - result= my_write(file, (uchar *) file_buffer, tot_len_byte, - MYF(MY_WME | MY_NABP)) != 0; - VOID(my_close(file, MYF(0))); + result= mysql_file_write(file, (uchar *) file_buffer, tot_len_byte, + MYF(MY_WME | MY_NABP)) != 0; + (void) mysql_file_close(file, MYF(0)); } else result= TRUE; @@ -2415,17 +2415,18 @@ bool ha_partition::get_from_handler_file(const char *name, MEM_ROOT *mem_root) DBUG_RETURN(FALSE); fn_format(buff, name, "", ha_par_ext, MY_APPEND_EXT); - /* Following could be done with my_stat to read in whole file */ - if ((file= my_open(buff, O_RDONLY | O_SHARE, MYF(0))) < 0) + /* Following could be done with mysql_file_stat to read in whole file */ + if ((file= mysql_file_open(key_file_partition, + buff, O_RDONLY | O_SHARE, MYF(0))) < 0) DBUG_RETURN(TRUE); - if (my_read(file, (uchar *) & buff[0], 8, MYF(MY_NABP))) + if (mysql_file_read(file, (uchar *) &buff[0], 8, MYF(MY_NABP))) goto err1; len_words= uint4korr(buff); len_bytes= 4 * len_words; if (!(file_buffer= (char*) my_malloc(len_bytes, MYF(0)))) goto err1; - VOID(my_seek(file, 0, MY_SEEK_SET, MYF(0))); - if (my_read(file, (uchar *) file_buffer, len_bytes, MYF(MY_NABP))) + mysql_file_seek(file, 0, MY_SEEK_SET, MYF(0)); + if (mysql_file_read(file, (uchar *) file_buffer, len_bytes, MYF(MY_NABP))) goto err2; chksum= 0; @@ -2446,7 +2447,7 @@ bool ha_partition::get_from_handler_file(const char *name, MEM_ROOT *mem_root) if (len_words != (tot_partition_words + tot_name_words + 4)) goto err3; name_buffer_ptr= file_buffer + 16 + 4 * tot_partition_words; - VOID(my_close(file, MYF(0))); + (void) mysql_file_close(file, MYF(0)); m_file_buffer= file_buffer; // Will be freed in clear_handler_file() m_name_buffer_ptr= name_buffer_ptr; @@ -2471,7 +2472,7 @@ err3: err2: my_free(file_buffer, MYF(0)); err1: - VOID(my_close(file, MYF(0))); + (void) mysql_file_close(file, MYF(0)); DBUG_RETURN(TRUE); } @@ -2634,7 +2635,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) for the same table. */ if (is_not_tmp_table) - pthread_mutex_lock(&table_share->mutex); + mysql_mutex_lock(&table_share->mutex); if (!table_share->ha_data) { HA_DATA_PARTITION *ha_data; @@ -2645,7 +2646,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) if (!ha_data) { if (is_not_tmp_table) - pthread_mutex_unlock(&table_share->mutex); + mysql_mutex_unlock(&table_share->mutex); goto err_handler; } DBUG_PRINT("info", ("table_share->ha_data 0x%p", ha_data)); @@ -2654,7 +2655,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) pthread_mutex_init(&ha_data->mutex, MY_MUTEX_INIT_FAST); } if (is_not_tmp_table) - pthread_mutex_unlock(&table_share->mutex); + mysql_mutex_unlock(&table_share->mutex); /* Some handlers update statistics as part of the open call. This will in some cases corrupt the statistics of the partition handler and thus @@ -5872,9 +5873,9 @@ void ha_partition::late_extra_cache(uint partition_id) DBUG_VOID_RETURN; file= m_file[partition_id]; if (m_extra_cache_size == 0) - VOID(file->extra(HA_EXTRA_CACHE)); + (void) file->extra(HA_EXTRA_CACHE); else - VOID(file->extra_opt(HA_EXTRA_CACHE, m_extra_cache_size)); + (void) file->extra_opt(HA_EXTRA_CACHE, m_extra_cache_size); DBUG_VOID_RETURN; } @@ -5898,7 +5899,7 @@ void ha_partition::late_extra_no_cache(uint partition_id) if (!m_extra_cache) DBUG_VOID_RETURN; file= m_file[partition_id]; - VOID(file->extra(HA_EXTRA_NO_CACHE)); + (void) file->extra(HA_EXTRA_NO_CACHE); DBUG_VOID_RETURN; } @@ -6552,8 +6553,8 @@ void ha_partition::get_auto_increment(ulonglong offset, ulonglong increment, if (!auto_increment_safe_stmt_log_lock && thd->lex->sql_command != SQLCOM_INSERT && mysql_bin_log.is_open() && - !thd->current_stmt_binlog_row_based && - (thd->options & OPTION_BIN_LOG)) + !thd->is_current_stmt_binlog_format_row() && + (thd->variables.option_bits & OPTION_BIN_LOG)) { DBUG_PRINT("info", ("locking auto_increment_safe_stmt_log_lock")); auto_increment_safe_stmt_log_lock= TRUE; @@ -6703,7 +6704,7 @@ int ha_partition::indexes_are_disabled(void) #ifdef NOT_USED static HASH partition_open_tables; -static pthread_mutex_t partition_mutex; +static mysql_mutex_t partition_mutex; static int partition_init= 0; @@ -6741,17 +6742,17 @@ static PARTITION_SHARE *get_share(const char *table_name, TABLE *table) if (!partition_init) { /* Hijack a mutex for init'ing the storage engine */ - pthread_mutex_lock(&LOCK_mysql_create_db); + mysql_mutex_lock(&LOCK_mysql_create_db); if (!partition_init) { partition_init++; - VOID(pthread_mutex_init(&partition_mutex, MY_MUTEX_INIT_FAST)); + mysql_mutex_init(INSTRUMENT_ME, &partition_mutex, MY_MUTEX_INIT_FAST); (void) hash_init(&partition_open_tables, system_charset_info, 32, 0, 0, (hash_get_key) partition_get_key, 0, 0); } - pthread_mutex_unlock(&LOCK_mysql_create_db); + mysql_mutex_unlock(&LOCK_mysql_create_db); } - pthread_mutex_lock(&partition_mutex); + mysql_mutex_lock(&partition_mutex); length= (uint) strlen(table_name); if (!(share= (PARTITION_SHARE *) hash_search(&partition_open_tables, @@ -6762,7 +6763,7 @@ static PARTITION_SHARE *get_share(const char *table_name, TABLE *table) &share, (uint) sizeof(*share), &tmp_name, (uint) length + 1, NullS))) { - pthread_mutex_unlock(&partition_mutex); + mysql_mutex_unlock(&partition_mutex); return NULL; } @@ -6773,15 +6774,15 @@ static PARTITION_SHARE *get_share(const char *table_name, TABLE *table) if (my_hash_insert(&partition_open_tables, (uchar *) share)) goto error; thr_lock_init(&share->lock); - pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST); + mysql_mutex_init(INSTRUMENT_ME, &share->mutex, MY_MUTEX_INIT_FAST); } share->use_count++; - pthread_mutex_unlock(&partition_mutex); + mysql_mutex_unlock(&partition_mutex); return share; error: - pthread_mutex_unlock(&partition_mutex); + mysql_mutex_unlock(&partition_mutex); my_free((uchar*) share, MYF(0)); return NULL; @@ -6796,15 +6797,15 @@ error: static int free_share(PARTITION_SHARE *share) { - pthread_mutex_lock(&partition_mutex); + mysql_mutex_lock(&partition_mutex); if (!--share->use_count) { hash_delete(&partition_open_tables, (uchar *) share); thr_lock_delete(&share->lock); - pthread_mutex_destroy(&share->mutex); + mysql_mutex_destroy(&share->mutex); my_free((uchar*) share, MYF(0)); } - pthread_mutex_unlock(&partition_mutex); + mysql_mutex_unlock(&partition_mutex); return 0; } diff --git a/sql/ha_partition.h b/sql/ha_partition.h index b2021f4fd89..e6b7472786c 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -36,7 +36,7 @@ typedef struct st_partition_share { char *table_name; uint table_name_length, use_count; - pthread_mutex_t mutex; + mysql_mutex_t mutex; THR_LOCK lock; } PARTITION_SHARE; #endif @@ -945,7 +945,7 @@ private: if(table_share->tmp_table == NO_TMP_TABLE) { auto_increment_lock= TRUE; - pthread_mutex_lock(&table_share->mutex); + mysql_mutex_lock(&table_share->mutex); } } virtual void unlock_auto_increment() @@ -958,7 +958,7 @@ private: */ if(auto_increment_lock && !auto_increment_safe_stmt_log_lock) { - pthread_mutex_unlock(&table_share->mutex); + mysql_mutex_unlock(&table_share->mutex); auto_increment_lock= FALSE; } } diff --git a/sql/handler.cc b/sql/handler.cc index ad7e1ecfa80..d9bed4ec557 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -307,7 +307,6 @@ const char **get_handler_errmsgs() int ha_init_errors(void) { #define SETMSG(nr, msg) handler_errmsgs[(nr) - HA_ERR_FIRST]= (msg) - const char **errmsgs; /* Allocate a pointer array for the error message strings. */ /* Zerofill it to avoid uninitialized gaps. */ @@ -992,7 +991,7 @@ int ha_prepare(THD *thd) THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt; Ha_trx_info *ha_info= trans->ha_list; DBUG_ENTER("ha_prepare"); -#ifdef USING_TRANSACTIONS + if (ha_info) { for (; ha_info; ha_info= ha_info->next()) @@ -1018,7 +1017,7 @@ int ha_prepare(THD *thd) } } } -#endif /* USING_TRANSACTIONS */ + DBUG_RETURN(error); } @@ -1146,7 +1145,7 @@ int ha_commit_trans(THD *thd, bool all) my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); DBUG_RETURN(2); } -#ifdef USING_TRANSACTIONS + if (ha_info) { uint rw_ha_count; @@ -1227,7 +1226,6 @@ end: /* Free resources and perform other cleanup even for 'empty' transactions. */ else if (is_real_trans) thd->transaction.cleanup(); -#endif /* USING_TRANSACTIONS */ DBUG_RETURN(error); } @@ -1249,7 +1247,7 @@ int ha_commit_one_phase(THD *thd, bool all) bool is_real_trans=all || thd->transaction.all.ha_list == 0; Ha_trx_info *ha_info= trans->ha_list, *ha_info_next; DBUG_ENTER("ha_commit_one_phase"); -#ifdef USING_TRANSACTIONS + if (ha_info) { for (; ha_info; ha_info= ha_info_next) @@ -1279,7 +1277,7 @@ int ha_commit_one_phase(THD *thd, bool all) /* Free resources and perform other cleanup even for 'empty' transactions. */ if (is_real_trans) thd->transaction.cleanup(); -#endif /* USING_TRANSACTIONS */ + DBUG_RETURN(error); } @@ -1319,7 +1317,7 @@ int ha_rollback_trans(THD *thd, bool all) my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); DBUG_RETURN(1); } -#ifdef USING_TRANSACTIONS + if (ha_info) { /* Close all cursors that can not survive ROLLBACK */ @@ -1350,7 +1348,6 @@ int ha_rollback_trans(THD *thd, bool all) /* Always cleanup. Even if there nht==0. There may be savepoints. */ if (is_real_trans) thd->transaction.cleanup(); -#endif /* USING_TRANSACTIONS */ if (all) thd->transaction_rollback_request= FALSE; @@ -1386,7 +1383,7 @@ int ha_rollback_trans(THD *thd, bool all) int ha_autocommit_or_rollback(THD *thd, int error) { DBUG_ENTER("ha_autocommit_or_rollback"); -#ifdef USING_TRANSACTIONS + if (thd->transaction.stmt.ha_list) { if (!error) @@ -1404,7 +1401,6 @@ int ha_autocommit_or_rollback(THD *thd, int error) thd->variables.tx_isolation=thd->session_tx_isolation; } else -#endif { if (!error) RUN_HOOK(transaction, after_commit, (thd, FALSE)); @@ -1686,7 +1682,7 @@ bool mysql_xa_recover(THD *thd) Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(1); - pthread_mutex_lock(&LOCK_xid_cache); + mysql_mutex_lock(&LOCK_xid_cache); while ((xs= (XID_STATE*) my_hash_element(&xid_cache, i++))) { if (xs->xa_state==XA_PREPARED) @@ -1699,13 +1695,13 @@ bool mysql_xa_recover(THD *thd) &my_charset_bin); if (protocol->write()) { - pthread_mutex_unlock(&LOCK_xid_cache); + mysql_mutex_unlock(&LOCK_xid_cache); DBUG_RETURN(1); } } } - pthread_mutex_unlock(&LOCK_xid_cache); + mysql_mutex_unlock(&LOCK_xid_cache); my_eof(thd); DBUG_RETURN(0); } @@ -1812,7 +1808,7 @@ int ha_savepoint(THD *thd, SAVEPOINT *sv) &thd->transaction.all); Ha_trx_info *ha_info= trans->ha_list; DBUG_ENTER("ha_savepoint"); -#ifdef USING_TRANSACTIONS + for (; ha_info; ha_info= ha_info->next()) { int err; @@ -1836,7 +1832,7 @@ int ha_savepoint(THD *thd, SAVEPOINT *sv) engines are prepended to the beginning of the list. */ sv->ha_list= trans->ha_list; -#endif /* USING_TRANSACTIONS */ + DBUG_RETURN(error); } @@ -2108,6 +2104,10 @@ THD *handler::ha_thd(void) const return (table && table->in_use) ? table->in_use : current_thd; } +PSI_table_share *handler::ha_table_share_psi(const TABLE_SHARE *share) const +{ + return share->m_psi; +} /** @brief Open database-handler. @@ -2490,7 +2490,7 @@ int handler::update_auto_increment() variables->auto_increment_increment); auto_inc_intervals_count++; /* Row-based replication does not need to store intervals in binlog */ - if (mysql_bin_log.is_open() && !thd->current_stmt_binlog_row_based) + if (mysql_bin_log.is_open() && !thd->is_current_stmt_binlog_format_row()) thd->auto_inc_intervals_in_cur_stmt_for_binlog.append(auto_inc_interval_for_cur_row.minimum(), auto_inc_interval_for_cur_row.values(), variables->auto_increment_increment); @@ -2997,7 +2997,8 @@ static bool update_frm_version(TABLE *table) strxmov(path, table->s->normalized_path.str, reg_ext, NullS); - if ((file= my_open(path, O_RDWR|O_BINARY, MYF(MY_WME))) >= 0) + if ((file= mysql_file_open(key_file_frm, + path, O_RDWR|O_BINARY, MYF(MY_WME))) >= 0) { uchar version[4]; char *key= table->s->table_cache_key.str; @@ -3007,7 +3008,7 @@ static bool update_frm_version(TABLE *table) int4store(version, MYSQL_VERSION_ID); - if ((result= my_pwrite(file,(uchar*) version,4,51L,MYF_RW))) + if ((result= mysql_file_pwrite(file, (uchar*) version, 4, 51L, MYF_RW))) goto err; for (entry=(TABLE*) my_hash_first(&open_cache,(uchar*) key,key_length, &state); @@ -3017,7 +3018,7 @@ static bool update_frm_version(TABLE *table) } err: if (file >= 0) - VOID(my_close(file,MYF(MY_WME))); + (void) mysql_file_close(file, MYF(MY_WME)); DBUG_RETURN(result); } @@ -3064,7 +3065,7 @@ int handler::delete_table(const char *name) for (const char **ext=bas_ext(); *ext ; ext++) { fn_format(buff, name, "", *ext, MY_UNPACK_FILENAME|MY_APPEND_EXT); - if (my_delete_with_symlink(buff, MYF(0))) + if (mysql_file_delete_with_symlink(key_file_misc, buff, MYF(0))) { if (my_errno != ENOENT) { @@ -3250,36 +3251,6 @@ handler::ha_reset_auto_increment(ulonglong value) /** - Backup table: public interface. - - @sa handler::backup() -*/ - -int -handler::ha_backup(THD* thd, HA_CHECK_OPT* check_opt) -{ - mark_trx_read_write(); - - return backup(thd, check_opt); -} - - -/** - Restore table: public interface. - - @sa handler::restore() -*/ - -int -handler::ha_restore(THD* thd, HA_CHECK_OPT* check_opt) -{ - mark_trx_read_write(); - - return restore(thd, check_opt); -} - - -/** Optimize table: public interface. @sa handler::optimize() @@ -3650,7 +3621,7 @@ int ha_create_table(THD *thd, const char *path, name= get_canonical_filename(table.file, share.path.str, name_buff); error= table.file->ha_create(name, &table, create_info); - VOID(closefrm(&table, 0)); + (void) closefrm(&table, 0); if (error) { strxmov(name_buff, db, ".", table_name, NullS); @@ -3721,7 +3692,7 @@ int ha_create_table_from_engine(THD* thd, const char *db, const char *name) get_canonical_filename(table.file, path, path); error=table.file->ha_create(path, &table, &create_info); - VOID(closefrm(&table, 1)); + (void) closefrm(&table, 1); DBUG_RETURN(error != 0); } @@ -3729,7 +3700,6 @@ int ha_create_table_from_engine(THD* thd, const char *db, const char *name) void st_ha_check_opt::init() { flags= sql_flags= 0; - sort_buffer_size = current_thd->variables.myisam_sort_buff_size; } @@ -3752,12 +3722,12 @@ int ha_init_key_cache(const char *name, KEY_CACHE *key_cache) if (!key_cache->key_cache_inited) { - pthread_mutex_lock(&LOCK_global_system_variables); + mysql_mutex_lock(&LOCK_global_system_variables); size_t tmp_buff_size= (size_t) key_cache->param_buff_size; uint tmp_block_size= (uint) key_cache->param_block_size; uint division_limit= key_cache->param_division_limit; uint age_threshold= key_cache->param_age_threshold; - pthread_mutex_unlock(&LOCK_global_system_variables); + mysql_mutex_unlock(&LOCK_global_system_variables); DBUG_RETURN(!init_key_cache(key_cache, tmp_block_size, tmp_buff_size, @@ -3776,12 +3746,12 @@ int ha_resize_key_cache(KEY_CACHE *key_cache) if (key_cache->key_cache_inited) { - pthread_mutex_lock(&LOCK_global_system_variables); + mysql_mutex_lock(&LOCK_global_system_variables); size_t tmp_buff_size= (size_t) key_cache->param_buff_size; long tmp_block_size= (long) key_cache->param_block_size; uint division_limit= key_cache->param_division_limit; uint age_threshold= key_cache->param_age_threshold; - pthread_mutex_unlock(&LOCK_global_system_variables); + mysql_mutex_unlock(&LOCK_global_system_variables); DBUG_RETURN(!resize_key_cache(key_cache, tmp_block_size, tmp_buff_size, division_limit, age_threshold)); @@ -3797,25 +3767,16 @@ int ha_change_key_cache_param(KEY_CACHE *key_cache) { if (key_cache->key_cache_inited) { - pthread_mutex_lock(&LOCK_global_system_variables); + mysql_mutex_lock(&LOCK_global_system_variables); uint division_limit= key_cache->param_division_limit; uint age_threshold= key_cache->param_age_threshold; - pthread_mutex_unlock(&LOCK_global_system_variables); + mysql_mutex_unlock(&LOCK_global_system_variables); change_key_cache_param(key_cache, division_limit, age_threshold); } return 0; } /** - Free memory allocated by a key cache. -*/ -int ha_end_key_cache(KEY_CACHE *key_cache) -{ - end_key_cache(key_cache, 1); // Can never fail - return 0; -} - -/** Move all tables from one key cache to another one. */ int ha_change_key_cache(KEY_CACHE *old_key_cache, @@ -4520,9 +4481,9 @@ static bool check_table_binlog_row_based(THD *thd, TABLE *table) DBUG_ASSERT(table->s->cached_row_logging_check == 0 || table->s->cached_row_logging_check == 1); - return (thd->current_stmt_binlog_row_based && + return (thd->is_current_stmt_binlog_format_row() && table->s->cached_row_logging_check && - (thd->options & OPTION_BIN_LOG) && + (thd->variables.option_bits & OPTION_BIN_LOG) && mysql_bin_log.is_open()); } @@ -4582,7 +4543,21 @@ static int write_locked_table_maps(THD *thd) if (table->current_lock == F_WRLCK && check_table_binlog_row_based(thd, table)) { - int const has_trans= table->file->has_transactions(); + /* + We need to have a transactional behavior for SQLCOM_CREATE_TABLE + (e.g. CREATE TABLE... SELECT * FROM TABLE) in order to keep a + compatible behavior with the STMT based replication even when + the table is not transactional. In other words, if the operation + fails while executing the insert phase nothing is written to the + binlog. + + Note that at this point, we check the type of a set of tables to + create the table map events. In the function binlog_log_row(), + which calls the current function, we check the type of the table + of the current row. + */ + bool const has_trans= thd->lex->sql_command == SQLCOM_CREATE_TABLE || + table->file->has_transactions(); int const error= thd->binlog_write_table_map(table, has_trans); /* If an error occurs, it is the responsibility of the caller to @@ -4631,10 +4606,20 @@ static int binlog_log_row(TABLE* table, { bitmap_set_all(&cols); if (likely(!(error= write_locked_table_maps(thd)))) - error= (*log_func)(thd, table, table->file->has_transactions(), - &cols, table->s->fields, + { + /* + We need to have a transactional behavior for SQLCOM_CREATE_TABLE + (i.e. CREATE TABLE... SELECT * FROM TABLE) in order to keep a + compatible behavior with the STMT based replication even when + the table is not transactional. In other words, if the operation + fails while executing the insert phase nothing is written to the + binlog. + */ + bool const has_trans= thd->lex->sql_command == SQLCOM_CREATE_TABLE || + table->file->has_transactions(); + error= (*log_func)(thd, table, has_trans, &cols, table->s->fields, before_record, after_record); - + } if (!use_bitbuf) bitmap_free(&cols); } @@ -4838,7 +4823,8 @@ int example_of_iterator_using_for_logs_cleanup(handlerton *hton) { printf("%s\n", data.filename.str); if (data.status == HA_LOG_STATUS_FREE && - my_delete(data.filename.str, MYF(MY_WME))) + mysql_file_delete(INSTRUMENT_ME, + data.filename.str, MYF(MY_WME))) goto err; } res= 0; @@ -4866,7 +4852,7 @@ err: enum log_status fl_get_log_status(char *log) { MY_STAT stat_buff; - if (my_stat(log, &stat_buff, MYF(0))) + if (mysql_file_stat(INSTRUMENT_ME, log, &stat_buff, MYF(0))) return HA_LOG_STATUS_INUSE; return HA_LOG_STATUS_NOSUCHLOG; } diff --git a/sql/handler.h b/sql/handler.h index 05a9e13653c..f4064b51de9 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1,7 +1,7 @@ #ifndef HANDLER_INCLUDED #define HANDLER_INCLUDED -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,7 +16,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - /* Definitions for parameters to do with handler-routines */ #ifdef USE_PRAGMA_INTERFACE @@ -31,8 +30,6 @@ #define NO_HASH /* Not yet implemented */ #endif -#define USING_TRANSACTIONS - // the following is for checking tables #define HA_ADMIN_ALREADY_DONE 1 @@ -127,6 +124,29 @@ */ #define HA_BINLOG_ROW_CAPABLE (LL(1) << 34) #define HA_BINLOG_STMT_CAPABLE (LL(1) << 35) +/* + When a multiple key conflict happens in a REPLACE command mysql + expects the conflicts to be reported in the ascending order of + key names. + + For e.g. + + CREATE TABLE t1 (a INT, UNIQUE (a), b INT NOT NULL, UNIQUE (b), c INT NOT + NULL, INDEX(c)); + + REPLACE INTO t1 VALUES (1,1,1),(2,2,2),(2,1,3); + + MySQL expects the conflict with 'a' to be reported before the conflict with + 'b'. + + If the underlying storage engine does not report the conflicting keys in + ascending order, it causes unexpected errors when the REPLACE command is + executed. + + This flag helps the underlying SE to inform the server that the keys are not + ordered. +*/ +#define HA_DUPLICATE_KEY_NOT_IN_ORDER (LL(1) << 36) /* Set of all binlog flags. Currently only contain the capabilities @@ -284,6 +304,8 @@ enum legacy_db_type DB_TYPE_MEMCACHE, DB_TYPE_FALCON, DB_TYPE_MARIA, + /** Performance schema engine. */ + DB_TYPE_PERFORMANCE_SCHEMA, DB_TYPE_FIRST_DYNAMIC=42, DB_TYPE_DEFAULT=127 // Must be last }; @@ -515,6 +537,48 @@ class st_alter_tablespace : public Sql_alloc /* The handler for a table type. Will be included in the TABLE structure */ struct TABLE; + +/* + Make sure that the order of schema_tables and enum_schema_tables are the same. +*/ +enum enum_schema_tables +{ + SCH_CHARSETS= 0, + SCH_COLLATIONS, + SCH_COLLATION_CHARACTER_SET_APPLICABILITY, + SCH_COLUMNS, + SCH_COLUMN_PRIVILEGES, + SCH_ENGINES, + SCH_EVENTS, + SCH_FILES, + SCH_GLOBAL_STATUS, + SCH_GLOBAL_VARIABLES, + SCH_KEY_COLUMN_USAGE, + SCH_OPEN_TABLES, + SCH_PARAMETERS, + SCH_PARTITIONS, + SCH_PLUGINS, + SCH_PROCESSLIST, + SCH_PROFILES, + SCH_REFERENTIAL_CONSTRAINTS, + SCH_PROCEDURES, + SCH_SCHEMATA, + SCH_SCHEMA_PRIVILEGES, + SCH_SESSION_STATUS, + SCH_SESSION_VARIABLES, + SCH_STATISTICS, + SCH_STATUS, + SCH_TABLES, + SCH_TABLESPACES, + SCH_TABLE_CONSTRAINTS, + SCH_TABLE_NAMES, + SCH_TABLE_PRIVILEGES, + SCH_TRIGGERS, + SCH_USER_PRIVILEGES, + SCH_VARIABLES, + SCH_VIEWS +}; + struct TABLE_SHARE; struct st_foreign_key_info; typedef struct st_foreign_key_info FOREIGN_KEY_INFO; @@ -679,9 +743,9 @@ struct handlerton uint (*partition_flags)(); uint (*alter_table_flags)(uint flags); int (*alter_tablespace)(handlerton *hton, THD *thd, st_alter_tablespace *ts_info); - int (*fill_files_table)(handlerton *hton, THD *thd, - TABLE_LIST *tables, - class Item *cond); + int (*fill_is_table)(handlerton *hton, THD *thd, TABLE_LIST *tables, + class Item *cond, + enum enum_schema_tables); uint32 flags; /* global handler flags */ /* Those handlerton functions below are properly initialized at handler @@ -879,9 +943,6 @@ enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED, ISO_REPEATABLE_READ, ISO_SERIALIZABLE}; -enum ndb_distribution { ND_KEYHASH= 0, ND_LINHASH= 1 }; - - typedef struct { ulonglong data_file_length; ulonglong max_data_file_length; @@ -1013,7 +1074,6 @@ typedef class Item COND; typedef struct st_ha_check_opt { st_ha_check_opt() {} /* Remove gcc warning */ - ulong sort_buffer_size; uint flags; /* isam layer flags (e.g. for myisamchk) */ uint sql_flags; /* sql layer flags - for something myisamchk cannot do */ KEY_CACHE *key_cache; /* new key cache when changing key cache */ @@ -1158,6 +1218,20 @@ public: */ uint auto_inc_intervals_count; + /** + Instrumented table associated with this handler. + This member should be set to NULL when no instrumentation is in place, + so that linking an instrumented/non instrumented server/plugin works. + For example: + - the server is compiled with the instrumentation. + The server expects either NULL or valid pointers in m_psi. + - an engine plugin is compiled without instrumentation. + The plugin can not leave this pointer uninitialized, + or can not leave a trash value on purpose in this pointer, + as this would crash the server. + */ + PSI_table *m_psi; + handler(handlerton *ht_arg, TABLE_SHARE *share_arg) :table_share(share_arg), table(0), estimation_rows_to_insert(0), ht(ht_arg), @@ -1166,7 +1240,8 @@ public: ft_handler(0), inited(NONE), locked(FALSE), implicit_emptied(0), pushed_cond(0), next_insert_id(0), insert_id_for_cur_row(0), - auto_inc_intervals_count(0) + auto_inc_intervals_count(0), + m_psi(NULL) {} virtual ~handler(void) { @@ -1254,8 +1329,6 @@ public: uint *dup_key_found); int ha_delete_all_rows(); int ha_reset_auto_increment(ulonglong value); - int ha_backup(THD* thd, HA_CHECK_OPT* check_opt); - int ha_restore(THD* thd, HA_CHECK_OPT* check_opt); int ha_optimize(THD* thd, HA_CHECK_OPT* check_opt); int ha_analyze(THD* thd, HA_CHECK_OPT* check_opt); bool ha_check_and_repair(THD *thd); @@ -1541,9 +1614,7 @@ public: { return HA_ADMIN_NOT_IMPLEMENTED; } /* end of the list of admin commands */ - virtual int dump(THD* thd, int fd = -1) { return HA_ERR_WRONG_COMMAND; } virtual int indexes_are_disabled(void) {return 0;} - virtual int net_read_dump(NET* net) { return HA_ERR_WRONG_COMMAND; } virtual char *update_table_comment(const char * comment) { return (char*) comment;} virtual void append_create_info(String *packet) {} @@ -1771,6 +1842,39 @@ protected: THD *ha_thd(void) const; /** + Acquire the instrumented table information from a table share. + @param share a table share + @return an instrumented table share, or NULL. + */ + PSI_table_share *ha_table_share_psi(const TABLE_SHARE *share) const; + + inline void psi_open() + { + DBUG_ASSERT(m_psi == NULL); + DBUG_ASSERT(table_share != NULL); +#ifdef HAVE_PSI_INTERFACE + if (PSI_server) + { + PSI_table_share *share_psi= ha_table_share_psi(table_share); + if (share_psi) + m_psi= PSI_server->open_table(share_psi, this); + } +#endif + } + + inline void psi_close() + { +#ifdef HAVE_PSI_INTERFACE + if (PSI_server && m_psi) + { + PSI_server->close_table(m_psi); + m_psi= NULL; /* instrumentation handle, invalid after close_table() */ + } +#endif + DBUG_ASSERT(m_psi == NULL); + } + + /** Default rename_table() and delete_table() rename/delete files with a given name and extensions from bas_ext(). @@ -1911,14 +2015,6 @@ private: */ virtual int reset_auto_increment(ulonglong value) { return HA_ERR_WRONG_COMMAND; } - virtual int backup(THD* thd, HA_CHECK_OPT* check_opt) - { return HA_ADMIN_NOT_IMPLEMENTED; } - /** - Restore assumes .frm file must exist, and that generate_table() has been - called; It will just copy the data file and run repair. - */ - virtual int restore(THD* thd, HA_CHECK_OPT* check_opt) - { return HA_ADMIN_NOT_IMPLEMENTED; } virtual int optimize(THD* thd, HA_CHECK_OPT* check_opt) { return HA_ADMIN_NOT_IMPLEMENTED; } virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt) @@ -1956,7 +2052,7 @@ extern const char *ha_row_type[]; extern MYSQL_PLUGIN_IMPORT const char *tx_isolation_names[]; extern MYSQL_PLUGIN_IMPORT const char *binlog_format_names[]; extern TYPELIB tx_isolation_typelib; -extern TYPELIB myisam_stats_method_typelib; +extern const char *myisam_stats_method_names[]; extern ulong total_ha, total_ha_2pc; /* Wrapper functions */ @@ -2030,7 +2126,6 @@ extern "C" int ha_init_key_cache(const char *name, KEY_CACHE *key_cache); int ha_resize_key_cache(KEY_CACHE *key_cache); int ha_change_key_cache_param(KEY_CACHE *key_cache); int ha_change_key_cache(KEY_CACHE *old_key_cache, KEY_CACHE *new_key_cache); -int ha_end_key_cache(KEY_CACHE *key_cache); /* report to InnoDB that control passes to the client */ int ha_release_temporary_latches(THD *thd); diff --git a/sql/hash_filo.h b/sql/hash_filo.h index 5d17b880b4d..805e1262020 100644 --- a/sql/hash_filo.h +++ b/sql/hash_filo.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003, 2005 MySQL AB +/* Copyright (C) 2000-2003, 2005 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -45,7 +45,7 @@ class hash_filo hash_filo_element *first_link,*last_link; public: - pthread_mutex_t lock; + mysql_mutex_t lock; HASH cache; hash_filo(uint size_arg, uint key_offset_arg , uint key_length_arg, @@ -64,7 +64,7 @@ public: { if (cache.array.buffer) /* Avoid problems with thread library */ (void) my_hash_free(&cache); - pthread_mutex_destroy(&lock); + mysql_mutex_destroy(&lock); } } void clear(bool locked=0) @@ -72,15 +72,15 @@ public: if (!init) { init=1; - (void) pthread_mutex_init(&lock,MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_hash_filo_lock, &lock, MY_MUTEX_INIT_FAST); } if (!locked) - (void) pthread_mutex_lock(&lock); + mysql_mutex_lock(&lock); (void) my_hash_free(&cache); (void) my_hash_init(&cache,hash_charset,size,key_offset, key_length, get_key, free_element,0); if (!locked) - (void) pthread_mutex_unlock(&lock); + mysql_mutex_unlock(&lock); first_link=last_link=0; } diff --git a/sql/hostname.cc b/sql/hostname.cc index 45b10d16ce2..5517d85527c 100644 --- a/sql/hostname.cc +++ b/sql/hostname.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright (C) 2000-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,10 +18,10 @@ @file @brief - Get hostname for an IP. + Get hostname for an IP address. - Hostnames are checked with reverse name lookup and - checked that they doesn't resemble an ip. + Hostnames are checked with reverse name lookup and checked that they + doesn't resemble an IP address. */ #include "mysql_priv.h" @@ -34,24 +34,54 @@ extern "C" { // Because of SCO 3.2V4.2 #ifdef HAVE_SYS_UN_H #include <sys/un.h> #endif -#include <netdb.h> #include <sys/utsname.h> #endif // __WIN__ #ifdef __cplusplus } #endif +/* + HOST_ENTRY_KEY_SIZE -- size of IP address string in the hash cache. +*/ + +#define HOST_ENTRY_KEY_SIZE INET6_ADDRSTRLEN + +/** + An entry in the hostname hash table cache. + + Host name cache does two things: + - caches host names to save DNS look ups; + - counts connect errors from IP. -class host_entry :public hash_filo_element + Host name can be NULL (that means DNS look up failed), but connect errors + still are counted. +*/ + +class Host_entry :public hash_filo_element { public: - char ip[sizeof(((struct in_addr *) 0)->s_addr)]; - uint errors; - char *hostname; + /** + Client IP address. This is the key used with the hash table. + + The client IP address is always expressed in IPv6, even when the + network IPv6 stack is not present. + + This IP address is never used to connect to a socket. + */ + char ip_key[HOST_ENTRY_KEY_SIZE]; + + /** + Number of errors during handshake phase from the IP address. + */ + uint connect_errors; + + /** + One of the host names for the IP address. May be NULL. + */ + const char *hostname; }; static hash_filo *hostname_cache; -static pthread_mutex_t LOCK_hostname; void hostname_cache_refresh() { @@ -60,219 +90,468 @@ void hostname_cache_refresh() bool hostname_cache_init() { - host_entry tmp; - uint offset= (uint) ((char*) (&tmp.ip) - (char*) &tmp); - if (!(hostname_cache=new hash_filo(HOST_CACHE_SIZE, offset, - sizeof(struct in_addr),NULL, - (my_hash_free_key) free, - &my_charset_bin))) + Host_entry tmp; + uint key_offset= (uint) ((char*) (&tmp.ip_key) - (char*) &tmp); + + if (!(hostname_cache= new hash_filo(HOST_CACHE_SIZE, + key_offset, HOST_ENTRY_KEY_SIZE, + NULL, (my_hash_free_key) free, + &my_charset_bin))) return 1; + hostname_cache->clear(); - (void) pthread_mutex_init(&LOCK_hostname,MY_MUTEX_INIT_SLOW); + return 0; } void hostname_cache_free() { - if (hostname_cache) - { - (void) pthread_mutex_destroy(&LOCK_hostname); - delete hostname_cache; - hostname_cache= 0; - } + delete hostname_cache; + hostname_cache= NULL; } +static void prepare_hostname_cache_key(const char *ip_string, + char *ip_key) +{ + int ip_string_length= strlen(ip_string); + DBUG_ASSERT(ip_string_length < HOST_ENTRY_KEY_SIZE); + + memset(ip_key, 0, HOST_ENTRY_KEY_SIZE); + memcpy_fixed(ip_key, ip_string, ip_string_length); +} -static void add_hostname(struct in_addr *in,const char *name) +static inline Host_entry *hostname_cache_search(const char *ip_key) { - if (!(specialflag & SPECIAL_NO_HOST_CACHE)) + return (Host_entry *) hostname_cache->search((uchar *) ip_key, 0); +} + +static bool add_hostname_impl(const char *ip_key, const char *hostname) +{ + if (hostname_cache_search(ip_key)) + return FALSE; + + size_t hostname_size= hostname ? strlen(hostname) + 1 : 0; + + Host_entry *entry= (Host_entry *) malloc(sizeof (Host_entry) + hostname_size); + + if (!entry) + return TRUE; + + char *hostname_copy; + + memcpy_fixed(&entry->ip_key, ip_key, HOST_ENTRY_KEY_SIZE); + + if (hostname_size) { - VOID(pthread_mutex_lock(&hostname_cache->lock)); - host_entry *entry; - if (!(entry=(host_entry*) hostname_cache->search((uchar*) &in->s_addr,0))) - { - uint length=name ? (uint) strlen(name) : 0; + hostname_copy= (char *) (entry + 1); + memcpy(hostname_copy, hostname, hostname_size); - if ((entry=(host_entry*) malloc(sizeof(host_entry)+length+1))) - { - char *new_name; - memcpy_fixed(&entry->ip, &in->s_addr, sizeof(in->s_addr)); - if (length) - memcpy(new_name= (char *) (entry+1), name, length+1); - else - new_name=0; - entry->hostname=new_name; - entry->errors=0; - (void) hostname_cache->add(entry); - } - } - VOID(pthread_mutex_unlock(&hostname_cache->lock)); + DBUG_PRINT("info", ("Adding '%s' -> '%s' to the hostname cache...'", + (const char *) ip_key, + (const char *) hostname_copy)); + } + else + { + hostname_copy= NULL; + + DBUG_PRINT("info", ("Adding '%s' -> NULL to the hostname cache...'", + (const char *) ip_key)); } + + entry->hostname= hostname_copy; + entry->connect_errors= 0; + + return hostname_cache->add(entry); +} + +static bool add_hostname(const char *ip_key, const char *hostname) +{ + if (specialflag & SPECIAL_NO_HOST_CACHE) + return FALSE; + + mysql_mutex_lock(&hostname_cache->lock); + + bool err_status= add_hostname_impl(ip_key, hostname); + + mysql_mutex_unlock(&hostname_cache->lock); + + return err_status; } +void inc_host_errors(const char *ip_string) +{ + if (!ip_string) + return; + + char ip_key[HOST_ENTRY_KEY_SIZE]; + prepare_hostname_cache_key(ip_string, ip_key); + + mysql_mutex_lock(&hostname_cache->lock); + + Host_entry *entry= hostname_cache_search(ip_key); + + if (entry) + entry->connect_errors++; + + mysql_mutex_unlock(&hostname_cache->lock); +} -inline void add_wrong_ip(struct in_addr *in) + +void reset_host_errors(const char *ip_string) { - add_hostname(in,NullS); + if (!ip_string) + return; + + char ip_key[HOST_ENTRY_KEY_SIZE]; + prepare_hostname_cache_key(ip_string, ip_key); + + mysql_mutex_lock(&hostname_cache->lock); + + Host_entry *entry= hostname_cache_search(ip_key); + + if (entry) + entry->connect_errors= 0; + + mysql_mutex_unlock(&hostname_cache->lock); } -void inc_host_errors(struct in_addr *in) + +static inline bool is_ip_loopback(const struct sockaddr *ip) { - VOID(pthread_mutex_lock(&hostname_cache->lock)); - host_entry *entry; - if ((entry=(host_entry*) hostname_cache->search((uchar*) &in->s_addr,0))) - entry->errors++; - VOID(pthread_mutex_unlock(&hostname_cache->lock)); + switch (ip->sa_family) { + case AF_INET: + { + /* Check for IPv4 127.0.0.1. */ + struct in_addr *ip4= &((struct sockaddr_in *) ip)->sin_addr; + return ntohl(ip4->s_addr) == INADDR_LOOPBACK; + } + +#ifdef HAVE_IPV6 + case AF_INET6: + { + /* Check for IPv6 ::1. */ + struct in6_addr *ip6= &((struct sockaddr_in6 *) ip)->sin6_addr; + return IN6_IS_ADDR_LOOPBACK(ip6); + } +#endif /* HAVE_IPV6 */ + + default: + return FALSE; + } } -void reset_host_errors(struct in_addr *in) +static inline bool is_hostname_valid(const char *hostname) { - VOID(pthread_mutex_lock(&hostname_cache->lock)); - host_entry *entry; - if ((entry=(host_entry*) hostname_cache->search((uchar*) &in->s_addr,0))) - entry->errors=0; - VOID(pthread_mutex_unlock(&hostname_cache->lock)); + /* + A hostname is invalid if it starts with a number followed by a dot + (IPv4 address). + */ + + if (!my_isdigit(&my_charset_latin1, hostname[0])) + return TRUE; + + const char *p= hostname + 1; + + while (my_isdigit(&my_charset_latin1, *p)) + ++p; + + return *p != '.'; } -/* Deal with systems that don't defined INADDR_LOOPBACK */ -#ifndef INADDR_LOOPBACK -#define INADDR_LOOPBACK 0x7f000001UL -#endif +/** + Resolve IP-address to host name. -char * ip_to_hostname(struct in_addr *in, uint *errors) + This function does the following things: + - resolves IP-address; + - employs Forward Confirmed Reverse DNS technique to validate IP-address; + - returns host name if IP-address is validated; + - set value to out-variable connect_errors -- this variable represents the + number of connection errors from the specified IP-address. + + NOTE: connect_errors are counted (are supported) only for the clients + where IP-address can be resolved and FCrDNS check is passed. + + @param [in] ip_storage IP address (sockaddr). Must be set. + @param [in] ip_string IP address (string). Must be set. + @param [out] hostname + @param [out] connect_errors + + @return Error status + @retval FALSE Success + @retval TRUE Error + + The function does not set/report MySQL server error in case of failure. + It's caller's responsibility to handle failures of this function + properly. +*/ + +bool ip_to_hostname(struct sockaddr_storage *ip_storage, + const char *ip_string, + char **hostname, uint *connect_errors) { - uint i; - host_entry *entry; + const struct sockaddr *ip= (const sockaddr *) ip_storage; + int err_code; + bool err_status; + DBUG_ENTER("ip_to_hostname"); - *errors=0; + DBUG_PRINT("info", ("IP address: '%s'; family: %d.", + (const char *) ip_string, + (int) ip->sa_family)); + + /* Check if we have loopback address (127.0.0.1 or ::1). */ + + if (is_ip_loopback(ip)) + { + DBUG_PRINT("info", ("Loopback address detected.")); - /* We always treat the loopback address as "localhost". */ - if (in->s_addr == htonl(INADDR_LOOPBACK)) // is expanded inline by gcc - DBUG_RETURN((char *)my_localhost); + *connect_errors= 0; /* Do not count connect errors from localhost. */ + *hostname= (char *) my_localhost; + + DBUG_RETURN(FALSE); + } + + /* Prepare host name cache key. */ + + char ip_key[HOST_ENTRY_KEY_SIZE]; + prepare_hostname_cache_key(ip_string, ip_key); + + /* Check first if we have host name in the cache. */ - /* Check first if we have name in cache */ if (!(specialflag & SPECIAL_NO_HOST_CACHE)) { - VOID(pthread_mutex_lock(&hostname_cache->lock)); - if ((entry=(host_entry*) hostname_cache->search((uchar*) &in->s_addr,0))) + mysql_mutex_lock(&hostname_cache->lock); + + Host_entry *entry= hostname_cache_search(ip_key); + + if (entry) { - char *name; - if (!entry->hostname) - name=0; // Don't allow connection - else - name=my_strdup(entry->hostname,MYF(0)); - *errors= entry->errors; - VOID(pthread_mutex_unlock(&hostname_cache->lock)); - DBUG_RETURN(name); + *connect_errors= entry->connect_errors; + *hostname= NULL; + + if (entry->hostname) + *hostname= my_strdup(entry->hostname, MYF(0)); + + DBUG_PRINT("info",("IP (%s) has been found in the cache. " + "Hostname: '%s'; connect_errors: %d", + (const char *) ip_key, + (const char *) (*hostname? *hostname : "null"), + (int) *connect_errors)); + + mysql_mutex_unlock(&hostname_cache->lock); + + DBUG_RETURN(FALSE); } - VOID(pthread_mutex_unlock(&hostname_cache->lock)); - } - struct hostent *hp, *check; - char *name; - LINT_INIT(check); -#if defined(HAVE_GETHOSTBYADDR_R) && defined(HAVE_SOLARIS_STYLE_GETHOST) - char buff[GETHOSTBYADDR_BUFF_SIZE],buff2[GETHOSTBYNAME_BUFF_SIZE]; - int tmp_errno; - struct hostent tmp_hostent, tmp_hostent2; -#ifdef HAVE_purify - bzero(buff,sizeof(buff)); // Bug in purify -#endif - if (!(hp=gethostbyaddr_r((char*) in,sizeof(*in), - AF_INET, - &tmp_hostent,buff,sizeof(buff),&tmp_errno))) - { - DBUG_PRINT("error",("gethostbyaddr_r returned %d",tmp_errno)); - return 0; + mysql_mutex_unlock(&hostname_cache->lock); } - if (!(check=my_gethostbyname_r(hp->h_name,&tmp_hostent2,buff2,sizeof(buff2), - &tmp_errno))) + + /* + Resolve host name. Return an error if a host name can not be resolved + (instead of returning the numeric form of the host name). + */ + + char hostname_buffer[NI_MAXHOST]; + + DBUG_PRINT("info", ("Resolving '%s'...", (const char *) ip_key)); + + err_code= vio_getnameinfo(ip, hostname_buffer, NI_MAXHOST, NULL, 0, + NI_NAMEREQD); + + if (err_code == EAI_NONAME) { - DBUG_PRINT("error",("gethostbyname_r returned %d",tmp_errno)); /* - Don't cache responses when the DSN server is down, as otherwise - transient DNS failure may leave any number of clients (those - that attempted to connect during the outage) unable to connect - indefinitely. + There is no reverse address mapping for the IP address. A host name + can not be resolved. */ - if (tmp_errno == HOST_NOT_FOUND || tmp_errno == NO_DATA) - add_wrong_ip(in); - my_gethostbyname_r_free(); - DBUG_RETURN(0); - } - if (!hp->h_name[0]) - { - DBUG_PRINT("error",("Got an empty hostname")); - add_wrong_ip(in); - my_gethostbyname_r_free(); - DBUG_RETURN(0); // Don't allow empty hostnames - } - if (!(name=my_strdup(hp->h_name,MYF(0)))) - { - my_gethostbyname_r_free(); - DBUG_RETURN(0); // out of memory + + DBUG_PRINT("error", ("IP address '%s' could not be resolved: " + "no reverse address mapping.", + (const char *) ip_key)); + + sql_print_warning("IP address '%s' could not be resolved: " + "no reverse address mapping.", + (const char *) ip_key); + + err_status= add_hostname(ip_key, NULL); + + *hostname= NULL; + *connect_errors= 0; /* New IP added to the cache. */ + + DBUG_RETURN(err_status); } - my_gethostbyname_r_free(); -#else - VOID(pthread_mutex_lock(&LOCK_hostname)); - if (!(hp=gethostbyaddr((char*) in,sizeof(*in), AF_INET))) + else if (err_code) { - VOID(pthread_mutex_unlock(&LOCK_hostname)); - DBUG_PRINT("error",("gethostbyaddr returned %d",errno)); + DBUG_PRINT("error", ("IP address '%s' could not be resolved: " + "getnameinfo() returned %d.", + (const char *) ip_key, + (int) err_code)); - if (errno == HOST_NOT_FOUND || errno == NO_DATA) - goto add_wrong_ip_and_return; - /* Failure, don't cache responce */ - DBUG_RETURN(0); + sql_print_warning("IP address '%s' could not be resolved: " + "getnameinfo() returned error (code: %d).", + (const char *) ip_key, + (int) err_code); + + DBUG_RETURN(TRUE); } - if (!hp->h_name[0]) // Don't allow empty hostnames + + DBUG_PRINT("info", ("IP '%s' resolved to '%s'.", + (const char *) ip_key, + (const char *) hostname_buffer)); + + /* + Validate hostname: the server does not accept host names, which + resemble IP addresses. + + The thing is that theoretically, a host name can be in a form of IPv4 + address (123.example.org, or 1.2 or even 1.2.3.4). We have to deny such + host names because ACL-systems is not designed to work with them. + + For example, it is possible to specify a host name mask (like + 192.168.1.%) for an ACL rule. Then, if IPv4-like hostnames are allowed, + there is a security hole: instead of allowing access for + 192.168.1.0/255 network (which was assumed by the user), the access + will be allowed for host names like 192.168.1.example.org. + */ + + if (!is_hostname_valid(hostname_buffer)) { - VOID(pthread_mutex_unlock(&LOCK_hostname)); - DBUG_PRINT("error",("Got an empty hostname")); - goto add_wrong_ip_and_return; + DBUG_PRINT("error", ("IP address '%s' has been resolved " + "to the host name '%s', which resembles " + "IPv4-address itself.", + (const char *) ip_key, + (const char *) hostname_buffer)); + + sql_print_warning("IP address '%s' has been resolved " + "to the host name '%s', which resembles " + "IPv4-address itself.", + (const char *) ip_key, + (const char *) hostname_buffer); + + err_status= add_hostname(ip_key, NULL); + + *hostname= NULL; + *connect_errors= 0; /* New IP added to the cache. */ + + DBUG_RETURN(err_status); } - if (!(name=my_strdup(hp->h_name,MYF(0)))) + + /* Get IP-addresses for the resolved host name (FCrDNS technique). */ + + struct addrinfo hints; + struct addrinfo *addr_info_list; + + memset(&hints, 0, sizeof (struct addrinfo)); + hints.ai_flags= AI_PASSIVE; + hints.ai_socktype= SOCK_STREAM; + hints.ai_family= AF_UNSPEC; + + DBUG_PRINT("info", ("Getting IP addresses for hostname '%s'...", + (const char *) hostname_buffer)); + + err_code= getaddrinfo(hostname_buffer, NULL, &hints, &addr_info_list); + + if (err_code == EAI_NONAME) { - VOID(pthread_mutex_unlock(&LOCK_hostname)); - DBUG_RETURN(0); // out of memory + /* + Don't cache responses when the DNS server is down, as otherwise + transient DNS failure may leave any number of clients (those + that attempted to connect during the outage) unable to connect + indefinitely. + */ + + err_status= add_hostname(ip_key, NULL); + + *hostname= NULL; + *connect_errors= 0; /* New IP added to the cache. */ + + DBUG_RETURN(err_status); } - check=gethostbyname(name); - VOID(pthread_mutex_unlock(&LOCK_hostname)); - if (!check) + else if (err_code) { - DBUG_PRINT("error",("gethostbyname returned %d",errno)); - my_free(name,MYF(0)); - DBUG_RETURN(0); + DBUG_PRINT("error", ("getaddrinfo() failed with error code %d.", err_code)); + DBUG_RETURN(TRUE); } -#endif - /* Don't accept hostnames that starts with digits because they may be - false ip:s */ - if (my_isdigit(&my_charset_latin1,name[0])) + /* Check that getaddrinfo() returned the used IP (FCrDNS technique). */ + + DBUG_PRINT("info", ("The following IP addresses found for '%s':", + (const char *) hostname_buffer)); + + for (struct addrinfo *addr_info= addr_info_list; + addr_info; addr_info= addr_info->ai_next) { - char *pos; - for (pos= name+1 ; my_isdigit(&my_charset_latin1,*pos); pos++) ; - if (*pos == '.') + char ip_buffer[HOST_ENTRY_KEY_SIZE]; + { - DBUG_PRINT("error",("mysqld doesn't accept hostnames that starts with a number followed by a '.'")); - my_free(name,MYF(0)); - goto add_wrong_ip_and_return; + err_status= + vio_get_normalized_ip_string(addr_info->ai_addr, addr_info->ai_addrlen, + ip_buffer, sizeof (ip_buffer)); + DBUG_ASSERT(!err_status); + } + + DBUG_PRINT("info", (" - '%s'", (const char *) ip_buffer)); + + if (strcmp(ip_key, ip_buffer) == 0) + { + /* Copy host name string to be stored in the cache. */ + + *hostname= my_strdup(hostname_buffer, MYF(0)); + + if (!*hostname) + { + DBUG_PRINT("error", ("Out of memory.")); + + freeaddrinfo(addr_info_list); + DBUG_RETURN(TRUE); + } + + break; } } - /* Check that 'gethostbyname' returned the used ip */ - for (i=0; check->h_addr_list[i]; i++) + /* Log resolved IP-addresses if no match was found. */ + + if (!*hostname) { - if (*(uint32*)(check->h_addr_list)[i] == in->s_addr) + sql_print_information("Hostname '%s' does not resolve to '%s'.", + (const char *) hostname_buffer, + (const char *) ip_key); + sql_print_information("Hostname '%s' has the following IP addresses:", + (const char *) hostname_buffer); + + for (struct addrinfo *addr_info= addr_info_list; + addr_info; addr_info= addr_info->ai_next) { - add_hostname(in,name); - DBUG_RETURN(name); + char ip_buffer[HOST_ENTRY_KEY_SIZE]; + + err_status= + vio_get_normalized_ip_string(addr_info->ai_addr, addr_info->ai_addrlen, + ip_buffer, sizeof (ip_buffer)); + DBUG_ASSERT(!err_status); + + sql_print_information(" - %s\n", (const char *) ip_buffer); } } - DBUG_PRINT("error",("Couldn't verify hostname with gethostbyname")); - my_free(name,MYF(0)); -add_wrong_ip_and_return: - add_wrong_ip(in); - DBUG_RETURN(0); + /* Free the result of getaddrinfo(). */ + + freeaddrinfo(addr_info_list); + + /* Add an entry for the IP to the cache. */ + + if (*hostname) + { + err_status= add_hostname(ip_key, *hostname); + *connect_errors= 0; + } + else + { + DBUG_PRINT("error",("Couldn't verify hostname with getaddrinfo().")); + + err_status= add_hostname(ip_key, NULL); + *hostname= NULL; + *connect_errors= 0; + } + + DBUG_RETURN(err_status); } diff --git a/sql/init.cc b/sql/init.cc index afda36b6b9d..cada907b013 100644 --- a/sql/init.cc +++ b/sql/init.cc @@ -40,7 +40,7 @@ void unireg_init(ulong options) my_abort_hook=unireg_abort; /* Abort with close of databases */ #endif - VOID(strmov(reg_ext,".frm")); + (void) strmov(reg_ext,".frm"); reg_ext_length= 4; specialflag=SPECIAL_SAME_DB_NAME | options; /* Set options from argv */ DBUG_VOID_RETURN; diff --git a/sql/item.cc b/sql/item.cc index b52619ceee0..e785f0addde 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -975,7 +975,7 @@ int Item::save_in_field_no_warnings(Field *field, bool no_conversions) THD *thd= table->in_use; enum_check_fields tmp= thd->count_cuted_fields; my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set); - ulong sql_mode= thd->variables.sql_mode; + ulonglong sql_mode= thd->variables.sql_mode; thd->variables.sql_mode&= ~(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE); thd->count_cuted_fields= CHECK_FIELD_IGNORE; res= save_in_field(field, no_conversions); @@ -1196,7 +1196,7 @@ void Item_case_expr::print(String *str, enum_query_type) { if (str->reserve(MAX_INT_WIDTH + sizeof("case_expr@"))) return; /* purecov: inspected */ - VOID(str->append(STRING_WITH_LEN("case_expr@"))); + (void) str->append(STRING_WITH_LEN("case_expr@")); str->qs_append(m_case_expr_id); } @@ -5025,7 +5025,7 @@ Field *Item::make_string_field(TABLE *table) DBUG_ASSERT(collation.collation); if (max_length/collation.collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB) field= new Field_blob(max_length, maybe_null, name, - collation.collation); + collation.collation, TRUE); /* Item_type_holder holds the exact type, do not change it */ else if (max_length > 0 && (type() != Item::TYPE_HOLDER || field_type() != MYSQL_TYPE_STRING)) @@ -5259,9 +5259,7 @@ int Item_null::save_safe_in_field(Field *field) int Item::save_in_field(Field *field, bool no_conversions) { int error; - if (result_type() == STRING_RESULT || - (result_type() == REAL_RESULT && - field->result_type() == STRING_RESULT)) + if (result_type() == STRING_RESULT) { String *result; CHARSET_INFO *cs= collation.collation; @@ -5280,6 +5278,15 @@ int Item::save_in_field(Field *field, bool no_conversions) error=field->store(result->ptr(),result->length(),cs); str_value.set_quick(0, 0, cs); } + else if (result_type() == REAL_RESULT && + field->result_type() == STRING_RESULT) + { + double nr= val_real(); + if (null_value) + return set_field_to_null_with_conversions(field, no_conversions); + field->set_notnull(); + error= field->store(nr); + } else if (result_type() == REAL_RESULT) { double nr= val_real(); @@ -5764,6 +5771,67 @@ bool Item::send(Protocol *protocol, String *buffer) } +/** + Check if an item is a constant one and can be cached. + + @param arg [out] TRUE <=> Cache this item. + + @return TRUE Go deeper in item tree. + @return FALSE Don't go deeper in item tree. +*/ + +bool Item::cache_const_expr_analyzer(uchar **arg) +{ + bool *cache_flag= (bool*)*arg; + if (!*cache_flag) + { + Item *item= real_item(); + /* + Cache constant items unless it's a basic constant, constant field or + a subselect (they use their own cache). + */ + if (const_item() && + !(item->basic_const_item() || item->type() == Item::FIELD_ITEM || + item->type() == SUBSELECT_ITEM || + /* + Do not cache GET_USER_VAR() function as its const_item() may + return TRUE for the current thread but it still may change + during the execution. + */ + (item->type() == Item::FUNC_ITEM && + ((Item_func*)item)->functype() == Item_func::GUSERVAR_FUNC))) + *cache_flag= TRUE; + return TRUE; + } + return FALSE; +} + + +/** + Cache item if needed. + + @param arg TRUE <=> Cache this item. + + @return cache if cache needed. + @return this otherwise. +*/ + +Item* Item::cache_const_expr_transformer(uchar *arg) +{ + if (*(bool*)arg) + { + *((bool*)arg)= FALSE; + Item_cache *cache= Item_cache::get_cache(this); + if (!cache) + return NULL; + cache->setup(this); + cache->store(this); + return cache; + } + return this; +} + + bool Item_field::send(Protocol *protocol, String *buffer) { return protocol->store(result_field); @@ -7125,6 +7193,10 @@ Item_cache* Item_cache::get_cache(const Item *item, const Item_result type) case DECIMAL_RESULT: return new Item_cache_decimal(); case STRING_RESULT: + if (item->field_type() == MYSQL_TYPE_DATE || + item->field_type() == MYSQL_TYPE_DATETIME || + item->field_type() == MYSQL_TYPE_TIME) + return new Item_cache_datetime(item->field_type()); return new Item_cache_str(item); case ROW_RESULT: return new Item_cache_row(); @@ -7210,6 +7282,79 @@ longlong Item_cache_int::val_int() return value; } +bool Item_cache_datetime::cache_value_int() +{ + if (!example) + return FALSE; + + value_cached= TRUE; + /* Assume here that the underlying item will do correct conversion.*/ + int_value= example->val_int_result(); + null_value= example->null_value; + unsigned_flag= example->unsigned_flag; + return TRUE; +} + + +bool Item_cache_datetime::cache_value() +{ + if (!example) + return FALSE; + str_value_cached= TRUE; + /* Assume here that the underlying item will do correct conversion.*/ + String *res= example->str_result(&str_value); + if (res && res != &str_value) + str_value.copy(*res); + null_value= example->null_value; + unsigned_flag= example->unsigned_flag; + return TRUE; +} + + +void Item_cache_datetime::store(Item *item, longlong val_arg) +{ + /* An explicit values is given, save it. */ + value_cached= TRUE; + int_value= val_arg; + null_value= item->null_value; + unsigned_flag= item->unsigned_flag; +} + + +String *Item_cache_datetime::val_str(String *str) +{ + DBUG_ASSERT(fixed == 1); + if (!str_value_cached && !cache_value()) + return NULL; + return &str_value; +} + + +my_decimal *Item_cache_datetime::val_decimal(my_decimal *decimal_val) +{ + DBUG_ASSERT(fixed == 1); + if (!value_cached && !cache_value_int()) + return NULL; + int2my_decimal(E_DEC_FATAL_ERROR, int_value, unsigned_flag, decimal_val); + return decimal_val; +} + +double Item_cache_datetime::val_real() +{ + DBUG_ASSERT(fixed == 1); + if (!value_cached && !cache_value_int()) + return 0.0; + return (double) int_value; +} + +longlong Item_cache_datetime::val_int() +{ + DBUG_ASSERT(fixed == 1); + if (!value_cached && !cache_value_int()) + return 0; + return int_value; +} + bool Item_cache_real::cache_value() { if (!example) diff --git a/sql/item.h b/sql/item.h index 0304fc1420b..b7e6cc6c204 100644 --- a/sql/item.h +++ b/sql/item.h @@ -919,6 +919,9 @@ public: virtual bool reset_query_id_processor(uchar *query_id_arg) { return 0; } virtual bool is_expensive_processor(uchar *arg) { return 0; } virtual bool register_field_in_read_map(uchar *arg) { return 0; } + + virtual bool cache_const_expr_analyzer(uchar **arg); + virtual Item* cache_const_expr_transformer(uchar *arg); /* Check if a partition function is allowed SYNOPSIS @@ -2351,6 +2354,7 @@ public: if (ref && result_type() == ROW_RESULT) (*ref)->bring_value(); } + bool basic_const_item() { return (*ref)->basic_const_item(); } }; @@ -3036,6 +3040,8 @@ public: } virtual void store(Item *item); virtual bool cache_value()= 0; + bool basic_const_item() const + { return test(example && example->basic_const_item());} }; @@ -3186,6 +3192,38 @@ public: }; +class Item_cache_datetime: public Item_cache +{ +protected: + String str_value; + ulonglong int_value; + bool str_value_cached; +public: + Item_cache_datetime(enum_field_types field_type_arg): + Item_cache(field_type_arg), int_value(0), str_value_cached(0) + { + cmp_context= STRING_RESULT; + } + + void store(Item *item, longlong val_arg); + double val_real(); + longlong val_int(); + String* val_str(String *str); + my_decimal *val_decimal(my_decimal *); + enum Item_result result_type() const { return STRING_RESULT; } + bool result_as_longlong() { return TRUE; } + /* + In order to avoid INT <-> STRING conversion of a DATETIME value + two cache_value functions are introduced. One (cache_value) caches STRING + value, another (cache_value_int) - INT value. Thus this cache item + completely relies on the ability of the underlying item to do the + correct conversion. + */ + bool cache_value_int(); + bool cache_value(); +}; + + /* Item_type_holder used to store type. name, length of Item for UNIONS & derived tables. @@ -3233,5 +3271,4 @@ extern Cached_item *new_Cached_item(THD *thd, Item *item); extern Item_result item_cmp_type(Item_result a,Item_result b); extern void resolve_const_item(THD *thd, Item **ref, Item *cmp_item); extern int stored_field_cmp_to_item(THD *thd, Field *field, Item *item); - #endif /* ITEM_INCLUDED */ diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 1d33e369af0..1da383ce3e9 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -404,7 +404,7 @@ static bool convert_constant_item(THD *thd, Item_field *field_item, if (!(*item)->with_subselect && (*item)->const_item()) { TABLE *table= field->table; - ulong orig_sql_mode= thd->variables.sql_mode; + ulonglong orig_sql_mode= thd->variables.sql_mode; enum_check_fields orig_count_cuted_fields= thd->count_cuted_fields; my_bitmap_map *old_maps[2]; ulonglong UNINIT_VAR(orig_field_val); /* original field value if valid */ @@ -867,7 +867,8 @@ get_time_value(THD *thd, Item ***item_arg, Item **cache_arg, else { *is_null= item->get_time(<ime); - value= !*is_null ? (longlong) TIME_to_ulonglong_datetime(<ime) : 0; + value= !*is_null ? (longlong) TIME_to_ulonglong_datetime(<ime) * + (ltime.neg ? -1 : 1) : 0; } /* Do not cache GET_USER_VAR() function as its const_item() may return TRUE @@ -4352,7 +4353,7 @@ void Item_cond::neg_arguments(THD *thd) if (!(new_item= new Item_func_not(item))) return; // Fatal OEM error } - VOID(li.replace(new_item)); + (void) li.replace(new_item); } } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index f498873a7ad..ef4eef3276c 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1747,5 +1747,4 @@ Item *and_expressions(Item *a, Item *b, Item **org_item); bool get_mysql_time_from_str(THD *thd, String *str, timestamp_type warn_type, const char *warn_name, MYSQL_TIME *l_time); - #endif /* ITEM_CMPFUNC_INCLUDED */ diff --git a/sql/item_create.cc b/sql/item_create.cc index cdd87af4c37..a393c886483 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -2387,10 +2387,11 @@ Create_udf_func::create(THD *thd, udf_func *udf, List<Item> *item_list) Item *func= NULL; int arg_count= 0; + DBUG_ENTER("Create_udf_func::create"); if (item_list != NULL) arg_count= item_list->elements; - thd->lex->set_stmt_unsafe(); + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_UDF); DBUG_ASSERT( (udf->type == UDFTYPE_FUNCTION) || (udf->type == UDFTYPE_AGGREGATE)); @@ -2474,7 +2475,7 @@ Create_udf_func::create(THD *thd, udf_func *udf, List<Item> *item_list) } } thd->lex->safe_to_cache_query= 0; - return func; + DBUG_RETURN(func); } #endif @@ -3400,9 +3401,10 @@ Create_func_found_rows Create_func_found_rows::s_singleton; Item* Create_func_found_rows::create(THD *thd) { - thd->lex->set_stmt_unsafe(); + DBUG_ENTER("Create_func_found_rows::create"); + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); thd->lex->safe_to_cache_query= 0; - return new (thd->mem_root) Item_func_found_rows(); + DBUG_RETURN(new (thd->mem_root) Item_func_found_rows()); } @@ -3561,7 +3563,7 @@ Create_func_get_lock Create_func_get_lock::s_singleton; Item* Create_func_get_lock::create(THD *thd, Item *arg1, Item *arg2) { - thd->lex->set_stmt_unsafe(); + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); return new (thd->mem_root) Item_func_get_lock(arg1, arg2); } @@ -3673,7 +3675,7 @@ Create_func_is_free_lock Create_func_is_free_lock::s_singleton; Item* Create_func_is_free_lock::create(THD *thd, Item *arg1) { - thd->lex->set_stmt_unsafe(); + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); return new (thd->mem_root) Item_func_is_free_lock(arg1); } @@ -3684,7 +3686,7 @@ Create_func_is_used_lock Create_func_is_used_lock::s_singleton; Item* Create_func_is_used_lock::create(THD *thd, Item *arg1) { - thd->lex->set_stmt_unsafe(); + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); return new (thd->mem_root) Item_func_is_used_lock(arg1); } @@ -3831,9 +3833,10 @@ Create_func_load_file Create_func_load_file::s_singleton; Item* Create_func_load_file::create(THD *thd, Item *arg1) { - thd->lex->set_stmt_unsafe(); + DBUG_ENTER("Create_func_load_file::create"); + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); - return new (thd->mem_root) Item_load_file(arg1); + DBUG_RETURN(new (thd->mem_root) Item_load_file(arg1)); } @@ -4001,7 +4004,7 @@ Create_func_master_pos_wait::create_native(THD *thd, LEX_STRING name, Item *func= NULL; int arg_count= 0; - thd->lex->set_stmt_unsafe(); + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); if (item_list != NULL) arg_count= item_list->elements; @@ -4223,7 +4226,7 @@ Create_func_rand::create_native(THD *thd, LEX_STRING name, between master and slave, because the order is undefined. Hence, the statement is unsafe to log in statement format. */ - thd->lex->set_stmt_unsafe(); + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); switch (arg_count) { case 0: @@ -4255,7 +4258,7 @@ Create_func_release_lock Create_func_release_lock::s_singleton; Item* Create_func_release_lock::create(THD *thd, Item *arg1) { - thd->lex->set_stmt_unsafe(); + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); return new (thd->mem_root) Item_func_release_lock(arg1); } @@ -4313,9 +4316,10 @@ Create_func_row_count Create_func_row_count::s_singleton; Item* Create_func_row_count::create(THD *thd) { - thd->lex->set_stmt_unsafe(); + DBUG_ENTER("Create_func_row_count::create"); + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); thd->lex->safe_to_cache_query= 0; - return new (thd->mem_root) Item_func_row_count(); + DBUG_RETURN(new (thd->mem_root) Item_func_row_count()); } @@ -4378,7 +4382,7 @@ Create_func_sleep Create_func_sleep::s_singleton; Item* Create_func_sleep::create(THD *thd, Item *arg1) { - thd->lex->set_stmt_unsafe(); + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); return new (thd->mem_root) Item_func_sleep(arg1); } @@ -4632,9 +4636,10 @@ Create_func_uuid Create_func_uuid::s_singleton; Item* Create_func_uuid::create(THD *thd) { - thd->lex->set_stmt_unsafe(); + DBUG_ENTER("Create_func_uuid::create"); + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); thd->lex->safe_to_cache_query= 0; - return new (thd->mem_root) Item_func_uuid(); + DBUG_RETURN(new (thd->mem_root) Item_func_uuid()); } @@ -4643,9 +4648,10 @@ Create_func_uuid_short Create_func_uuid_short::s_singleton; Item* Create_func_uuid_short::create(THD *thd) { - thd->lex->set_stmt_unsafe(); + DBUG_ENTER("Create_func_uuid_short::create"); + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); thd->lex->safe_to_cache_query= 0; - return new (thd->mem_root) Item_func_uuid_short(); + DBUG_RETURN(new (thd->mem_root) Item_func_uuid_short()); } @@ -4654,7 +4660,7 @@ Create_func_version Create_func_version::s_singleton; Item* Create_func_version::create(THD *thd) { - thd->lex->set_stmt_unsafe(); + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); return new (thd->mem_root) Item_static_string_func("version()", server_version, (uint) strlen(server_version), diff --git a/sql/item_func.cc b/sql/item_func.cc index 198e77b225a..75f8b2045b5 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -37,6 +37,7 @@ #include "sp_head.h" #include "sp_rcontext.h" #include "sp.h" +#include "set_var.h" #ifdef NO_EMBEDDED_ACCESS_CHECKS #define sp_restore_security_context(A,B) while (0) {} @@ -1347,6 +1348,38 @@ void Item_func_div::fix_length_and_dec() longlong Item_func_int_div::val_int() { DBUG_ASSERT(fixed == 1); + + /* + Perform division using DECIMAL math if either of the operands has a + non-integer type + */ + if (args[0]->result_type() != INT_RESULT || + args[1]->result_type() != INT_RESULT) + { + my_decimal value0, value1, tmp; + my_decimal *val0, *val1; + longlong res; + int err; + + val0= args[0]->val_decimal(&value0); + val1= args[1]->val_decimal(&value1); + if ((null_value= (args[0]->null_value || args[1]->null_value))) + return 0; + + if ((err= my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, &tmp, + val0, val1, 0)) > 3) + { + if (err == E_DEC_DIV_ZERO) + signal_divide_by_null(); + return 0; + } + + if (my_decimal2int(E_DEC_FATAL_ERROR, &tmp, unsigned_flag, &res) & + E_DEC_OVERFLOW) + my_error(ER_WARN_DATA_OUT_OF_RANGE, MYF(0), name, 1); + return res; + } + longlong value=args[0]->val_int(); longlong val2=args[1]->val_int(); if ((null_value= (args[0]->null_value || args[1]->null_value))) @@ -2920,7 +2953,7 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func, String *res= arguments[i]->val_str(&buffers[i]); if (arguments[i]->null_value) continue; - f_args.args[i]= (char*) res->c_ptr(); + f_args.args[i]= (char*) res->c_ptr_safe(); f_args.lengths[i]= res->length(); break; } @@ -3058,7 +3091,7 @@ String *udf_handler::val_str(String *str,String *save_str) if (res == str->ptr()) { str->length(res_length); - DBUG_PRINT("exit", ("str: %s", str->ptr())); + DBUG_PRINT("exit", ("str: %*.s", (int) str->length(), str->ptr())); DBUG_RETURN(str); } save_str->set(res, res_length, str->charset()); @@ -3250,7 +3283,7 @@ bool udf_handler::get_arguments() { return 0; } ** User level locks */ -pthread_mutex_t LOCK_user_locks; +mysql_mutex_t LOCK_user_locks; static HASH hash_user_locks; class User_level_lock @@ -3261,7 +3294,7 @@ class User_level_lock public: int count; bool locked; - pthread_cond_t cond; + mysql_cond_t cond; my_thread_id thread_id; void set_thread(THD *thd) { thread_id= thd->thread_id; } @@ -3269,7 +3302,7 @@ public: :key_length(length),count(1),locked(1), thread_id(id) { key= (uchar*) my_memdup(key_arg,length,MYF(0)); - pthread_cond_init(&cond,NULL); + mysql_cond_init(key_user_level_lock_cond, &cond, NULL); if (key) { if (my_hash_insert(&hash_user_locks,(uchar*) this)) @@ -3286,7 +3319,7 @@ public: my_hash_delete(&hash_user_locks,(uchar*) this); my_free(key, MYF(0)); } - pthread_cond_destroy(&cond); + mysql_cond_destroy(&cond); } inline bool initialized() { return key != 0; } friend void item_user_lock_release(User_level_lock *ull); @@ -3301,12 +3334,36 @@ uchar *ull_get_key(const User_level_lock *ull, size_t *length, return ull->key; } +#ifdef HAVE_PSI_INTERFACE +static PSI_mutex_key key_LOCK_user_locks; + +static PSI_mutex_info all_user_mutexes[]= +{ + { &key_LOCK_user_locks, "LOCK_user_locks", PSI_FLAG_GLOBAL} +}; + +static void init_user_lock_psi_keys(void) +{ + const char* category= "sql"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_user_mutexes); + PSI_server->register_mutex(category, all_user_mutexes, count); +} +#endif static bool item_user_lock_inited= 0; void item_user_lock_init(void) { - pthread_mutex_init(&LOCK_user_locks,MY_MUTEX_INIT_SLOW); +#ifdef HAVE_PSI_INTERFACE + init_user_lock_psi_keys(); +#endif + + mysql_mutex_init(key_LOCK_user_locks, &LOCK_user_locks, MY_MUTEX_INIT_SLOW); my_hash_init(&hash_user_locks,system_charset_info, 16,0,0,(my_hash_get_key) ull_get_key,NULL,0); item_user_lock_inited= 1; @@ -3318,7 +3375,7 @@ void item_user_lock_free(void) { item_user_lock_inited= 0; my_hash_free(&hash_user_locks); - pthread_mutex_destroy(&LOCK_user_locks); + mysql_mutex_destroy(&LOCK_user_locks); } } @@ -3327,7 +3384,7 @@ void item_user_lock_release(User_level_lock *ull) ull->locked=0; ull->thread_id= 0; if (--ull->count) - pthread_cond_signal(&ull->cond); + mysql_cond_signal(&ull->cond); else delete ull; } @@ -3370,7 +3427,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout) struct timespec abstime; size_t lock_name_len; lock_name_len= strlen(lock_name); - pthread_mutex_lock(&LOCK_user_locks); + mysql_mutex_lock(&LOCK_user_locks); if (thd->ull) { @@ -3388,7 +3445,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout) (uchar*) lock_name, lock_name_len)))) { - pthread_mutex_unlock(&LOCK_user_locks); + mysql_mutex_unlock(&LOCK_user_locks); return; } ull->count++; @@ -3404,7 +3461,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout) set_timespec(abstime,lock_timeout); while (ull->locked && !thd->killed) { - int error= pthread_cond_timedwait(&ull->cond, &LOCK_user_locks, &abstime); + int error= mysql_cond_timedwait(&ull->cond, &LOCK_user_locks, &abstime); if (error == ETIMEDOUT || error == ETIME) break; } @@ -3420,23 +3477,65 @@ void debug_sync_point(const char* lock_name, uint lock_timeout) ull->set_thread(thd); thd->ull=ull; } - pthread_mutex_unlock(&LOCK_user_locks); - pthread_mutex_lock(&thd->mysys_var->mutex); + mysql_mutex_unlock(&LOCK_user_locks); + mysql_mutex_lock(&thd->mysys_var->mutex); thd_proc_info(thd, 0); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; - pthread_mutex_unlock(&thd->mysys_var->mutex); - pthread_mutex_lock(&LOCK_user_locks); + mysql_mutex_unlock(&thd->mysys_var->mutex); + mysql_mutex_lock(&LOCK_user_locks); if (thd->ull) { item_user_lock_release(thd->ull); thd->ull=0; } - pthread_mutex_unlock(&LOCK_user_locks); + mysql_mutex_unlock(&LOCK_user_locks); } #endif + +/** + Wait for a given condition to be signaled within the specified timeout. + + @param cond the condition variable to wait on + @param lock the associated mutex + @param abstime the amount of time in seconds to wait + + @retval return value from mysql_cond_timedwait +*/ + +#define INTERRUPT_INTERVAL (5 * ULL(1000000000)) + +static int interruptible_wait(THD *thd, mysql_cond_t *cond, + mysql_mutex_t *lock, double time) +{ + int error; + struct timespec abstime; + ulonglong slice, timeout= (ulonglong) (time * 1000000000.0); + + do + { + /* Wait for a fixed interval. */ + if (timeout > INTERRUPT_INTERVAL) + slice= INTERRUPT_INTERVAL; + else + slice= timeout; + + timeout-= slice; + set_timespec_nsec(abstime, slice); + error= mysql_cond_timedwait(cond, lock, &abstime); + if (error == ETIMEDOUT || error == ETIME) + { + /* Return error if timed out or connection is broken. */ + if (!timeout || !thd->is_connected()) + break; + } + } while (error && timeout); + + return error; +} + /** Get a user level lock. If the thread has an old lock this is first released. @@ -3452,8 +3551,7 @@ longlong Item_func_get_lock::val_int() { DBUG_ASSERT(fixed == 1); String *res=args[0]->val_str(&value); - longlong timeout=args[1]->val_int(); - struct timespec abstime; + double timeout= args[1]->val_real(); THD *thd=current_thd; User_level_lock *ull; int error; @@ -3469,11 +3567,11 @@ longlong Item_func_get_lock::val_int() if (thd->slave_thread) DBUG_RETURN(1); - pthread_mutex_lock(&LOCK_user_locks); + mysql_mutex_lock(&LOCK_user_locks); if (!res || !res->length()) { - pthread_mutex_unlock(&LOCK_user_locks); + mysql_mutex_unlock(&LOCK_user_locks); null_value=1; DBUG_RETURN(0); } @@ -3496,13 +3594,13 @@ longlong Item_func_get_lock::val_int() if (!ull || !ull->initialized()) { delete ull; - pthread_mutex_unlock(&LOCK_user_locks); + mysql_mutex_unlock(&LOCK_user_locks); null_value=1; // Probably out of memory DBUG_RETURN(0); } ull->set_thread(thd); thd->ull=ull; - pthread_mutex_unlock(&LOCK_user_locks); + mysql_mutex_unlock(&LOCK_user_locks); DBUG_PRINT("info", ("made new lock")); DBUG_RETURN(1); // Got new lock } @@ -3517,12 +3615,11 @@ longlong Item_func_get_lock::val_int() thd->mysys_var->current_mutex= &LOCK_user_locks; thd->mysys_var->current_cond= &ull->cond; - set_timespec(abstime,timeout); error= 0; while (ull->locked && !thd->killed) { DBUG_PRINT("info", ("waiting on lock")); - error= pthread_cond_timedwait(&ull->cond,&LOCK_user_locks,&abstime); + error= interruptible_wait(thd, &ull->cond, &LOCK_user_locks, timeout); if (error == ETIMEDOUT || error == ETIME) { DBUG_PRINT("info", ("lock wait timeout")); @@ -3553,13 +3650,13 @@ longlong Item_func_get_lock::val_int() error=0; DBUG_PRINT("info", ("got the lock")); } - pthread_mutex_unlock(&LOCK_user_locks); + mysql_mutex_unlock(&LOCK_user_locks); - pthread_mutex_lock(&thd->mysys_var->mutex); + mysql_mutex_lock(&thd->mysys_var->mutex); thd_proc_info(thd, 0); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; - pthread_mutex_unlock(&thd->mysys_var->mutex); + mysql_mutex_unlock(&thd->mysys_var->mutex); DBUG_RETURN(!error ? 1 : 0); } @@ -3590,7 +3687,7 @@ longlong Item_func_release_lock::val_int() null_value=0; result=0; - pthread_mutex_lock(&LOCK_user_locks); + mysql_mutex_lock(&LOCK_user_locks); if (!(ull= ((User_level_lock*) my_hash_search(&hash_user_locks, (const uchar*) res->ptr(), (size_t) res->length())))) @@ -3611,7 +3708,7 @@ longlong Item_func_release_lock::val_int() thd->ull=0; } } - pthread_mutex_unlock(&LOCK_user_locks); + mysql_mutex_unlock(&LOCK_user_locks); DBUG_RETURN(result); } @@ -3717,29 +3814,27 @@ void Item_func_benchmark::print(String *str, enum_query_type query_type) longlong Item_func_sleep::val_int() { THD *thd= current_thd; - struct timespec abstime; - pthread_cond_t cond; + mysql_cond_t cond; + double timeout; int error; DBUG_ASSERT(fixed == 1); - double time= args[0]->val_real(); + timeout= args[0]->val_real(); /* - On 64-bit OSX pthread_cond_timedwait() waits forever + On 64-bit OSX mysql_cond_timedwait() waits forever if passed abstime time has already been exceeded by the system time. When given a very short timeout (< 10 mcs) just return immediately. We assume that the lines between this test and the call - to pthread_cond_timedwait() will be executed in less than 0.00001 sec. + to mysql_cond_timedwait() will be executed in less than 0.00001 sec. */ - if (time < 0.00001) + if (timeout < 0.00001) return 0; - - set_timespec_nsec(abstime, (ulonglong)(time * ULL(1000000000))); - pthread_cond_init(&cond, NULL); - pthread_mutex_lock(&LOCK_user_locks); + mysql_cond_init(key_item_func_sleep_cond, &cond, NULL); + mysql_mutex_lock(&LOCK_user_locks); thd_proc_info(thd, "User sleep"); thd->mysys_var->current_mutex= &LOCK_user_locks; @@ -3748,19 +3843,19 @@ longlong Item_func_sleep::val_int() error= 0; while (!thd->killed) { - error= pthread_cond_timedwait(&cond, &LOCK_user_locks, &abstime); + error= interruptible_wait(thd, &cond, &LOCK_user_locks, timeout); if (error == ETIMEDOUT || error == ETIME) break; error= 0; } thd_proc_info(thd, 0); - pthread_mutex_unlock(&LOCK_user_locks); - pthread_mutex_lock(&thd->mysys_var->mutex); + mysql_mutex_unlock(&LOCK_user_locks); + mysql_mutex_lock(&thd->mysys_var->mutex); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; - pthread_mutex_unlock(&thd->mysys_var->mutex); + mysql_mutex_unlock(&thd->mysys_var->mutex); - pthread_cond_destroy(&cond); + mysql_cond_destroy(&cond); return test(!error); // Return 1 killed } @@ -3780,7 +3875,7 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name, uint size=ALIGN_SIZE(sizeof(user_var_entry))+name.length+1+extra_size; if (!my_hash_inited(hash)) return 0; - if (!(entry = (user_var_entry*) my_malloc(size,MYF(MY_WME)))) + if (!(entry = (user_var_entry*) my_malloc(size,MYF(MY_WME | ME_FATALERROR)))) return 0; entry->name.str=(char*) entry+ ALIGN_SIZE(sizeof(user_var_entry))+ extra_size; @@ -3918,6 +4013,8 @@ bool Item_func_set_user_var::register_field_in_read_map(uchar *arg) @param dv derivation for new value @param unsigned_arg indiates if a value of type INT_RESULT is unsigned + @note Sets error and fatal error if allocation fails. + @retval false success @retval @@ -3961,7 +4058,8 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length, if (entry->value == pos) entry->value=0; entry->value= (char*) my_realloc(entry->value, length, - MYF(MY_ALLOW_ZERO_PTR | MY_WME)); + MYF(MY_ALLOW_ZERO_PTR | MY_WME | + ME_FATALERROR)); if (!entry->value) return 1; } @@ -3998,7 +4096,6 @@ Item_func_set_user_var::update_hash(void *ptr, uint length, if (::update_hash(entry, (null_value= args[0]->null_value), ptr, length, res_type, cs, dv, unsigned_arg)) { - current_thd->fatal_error(); // Probably end of memory null_value= 1; return 1; } @@ -4731,11 +4828,6 @@ void Item_func_get_user_var::fix_length_and_dec() m_cached_result_type= STRING_RESULT; max_length= MAX_BLOB_WIDTH; } - - if (error) - thd->fatal_error(); - - return; } @@ -4806,18 +4898,16 @@ bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref) void Item_user_var_as_out_param::set_null_value(CHARSET_INFO* cs) { - if (::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs, - DERIVATION_IMPLICIT, 0 /* unsigned_arg */)) - current_thd->fatal_error(); // Probably end of memory + ::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs, + DERIVATION_IMPLICIT, 0 /* unsigned_arg */); } void Item_user_var_as_out_param::set_value(const char *str, uint length, CHARSET_INFO* cs) { - if (::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs, - DERIVATION_IMPLICIT, 0 /* unsigned_arg */)) - current_thd->fatal_error(); // Probably end of memory + ::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs, + DERIVATION_IMPLICIT, 0 /* unsigned_arg */); } @@ -4895,7 +4985,7 @@ void Item_func_get_system_var::fix_length_and_dec() if (var_type != OPT_DEFAULT) { my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), - var->name, var_type == OPT_GLOBAL ? "SESSION" : "GLOBAL"); + var->name.str, var_type == OPT_GLOBAL ? "SESSION" : "GLOBAL"); return; } /* As there was no local variable, return the global value */ @@ -4912,22 +5002,38 @@ void Item_func_get_system_var::fix_length_and_dec() decimals=0; break; case SHOW_LONGLONG: - unsigned_flag= FALSE; + unsigned_flag= TRUE; max_length= MY_INT64_NUM_DECIMAL_DIGITS; decimals=0; break; case SHOW_CHAR: case SHOW_CHAR_PTR: - pthread_mutex_lock(&LOCK_global_system_variables); - cptr= var->show_type() == SHOW_CHAR_PTR ? - *(char**) var->value_ptr(current_thd, var_type, &component) : - (char*) var->value_ptr(current_thd, var_type, &component); + mysql_mutex_lock(&LOCK_global_system_variables); + cptr= var->show_type() == SHOW_CHAR ? + (char*) var->value_ptr(current_thd, var_type, &component) : + *(char**) var->value_ptr(current_thd, var_type, &component); if (cptr) - max_length= strlen(cptr) * system_charset_info->mbmaxlen; - pthread_mutex_unlock(&LOCK_global_system_variables); + max_length= system_charset_info->cset->numchars(system_charset_info, + cptr, + cptr + strlen(cptr)); + mysql_mutex_unlock(&LOCK_global_system_variables); collation.set(system_charset_info, DERIVATION_SYSCONST); + max_length*= system_charset_info->mbmaxlen; decimals=NOT_FIXED_DEC; break; + case SHOW_LEX_STRING: + { + mysql_mutex_lock(&LOCK_global_system_variables); + LEX_STRING *ls= ((LEX_STRING*)var->value_ptr(current_thd, var_type, &component)); + max_length= system_charset_info->cset->numchars(system_charset_info, + ls->str, + ls->str + ls->length); + mysql_mutex_unlock(&LOCK_global_system_variables); + collation.set(system_charset_info, DERIVATION_SYSCONST); + max_length*= system_charset_info->mbmaxlen; + decimals=NOT_FIXED_DEC; + } + break; case SHOW_BOOL: case SHOW_MY_BOOL: unsigned_flag= FALSE; @@ -4940,7 +5046,7 @@ void Item_func_get_system_var::fix_length_and_dec() max_length= DBL_DIG + 6; break; default: - my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name); + my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str); break; } } @@ -4965,11 +5071,12 @@ enum Item_result Item_func_get_system_var::result_type() const return INT_RESULT; case SHOW_CHAR: case SHOW_CHAR_PTR: + case SHOW_LEX_STRING: return STRING_RESULT; case SHOW_DOUBLE: return REAL_RESULT; default: - my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name); + my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str); return STRING_RESULT; // keep the compiler happy } } @@ -4988,11 +5095,12 @@ enum_field_types Item_func_get_system_var::field_type() const return MYSQL_TYPE_LONGLONG; case SHOW_CHAR: case SHOW_CHAR_PTR: + case SHOW_LEX_STRING: return MYSQL_TYPE_VARCHAR; case SHOW_DOUBLE: return MYSQL_TYPE_DOUBLE; default: - my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name); + my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str); return MYSQL_TYPE_VARCHAR; // keep the compiler happy } } @@ -5005,9 +5113,9 @@ enum_field_types Item_func_get_system_var::field_type() const #define get_sys_var_safe(type) \ do { \ type value; \ - pthread_mutex_lock(&LOCK_global_system_variables); \ + mysql_mutex_lock(&LOCK_global_system_variables); \ value= *(type*) var->value_ptr(thd, var_type, &component); \ - pthread_mutex_unlock(&LOCK_global_system_variables); \ + mysql_mutex_unlock(&LOCK_global_system_variables); \ cache_present |= GET_SYS_VAR_CACHE_LONG; \ used_query_id= thd->query_id; \ cached_llval= null_value ? 0 : (longlong) value; \ @@ -5053,7 +5161,7 @@ longlong Item_func_get_system_var::val_int() { case SHOW_INT: get_sys_var_safe (uint); case SHOW_LONG: get_sys_var_safe (ulong); - case SHOW_LONGLONG: get_sys_var_safe (longlong); + case SHOW_LONGLONG: get_sys_var_safe (ulonglong); case SHOW_HA_ROWS: get_sys_var_safe (ha_rows); case SHOW_BOOL: get_sys_var_safe (bool); case SHOW_MY_BOOL: get_sys_var_safe (my_bool); @@ -5068,6 +5176,7 @@ longlong Item_func_get_system_var::val_int() } case SHOW_CHAR: case SHOW_CHAR_PTR: + case SHOW_LEX_STRING: { String *str_val= val_str(NULL); @@ -5087,7 +5196,7 @@ longlong Item_func_get_system_var::val_int() } default: - my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name); + my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str); return 0; // keep the compiler happy } } @@ -5127,14 +5236,18 @@ String* Item_func_get_system_var::val_str(String* str) { case SHOW_CHAR: case SHOW_CHAR_PTR: + case SHOW_LEX_STRING: { - pthread_mutex_lock(&LOCK_global_system_variables); - char *cptr= var->show_type() == SHOW_CHAR_PTR ? - *(char**) var->value_ptr(thd, var_type, &component) : - (char*) var->value_ptr(thd, var_type, &component); + mysql_mutex_lock(&LOCK_global_system_variables); + char *cptr= var->show_type() == SHOW_CHAR ? + (char*) var->value_ptr(thd, var_type, &component) : + *(char**) var->value_ptr(thd, var_type, &component); if (cptr) { - if (str->copy(cptr, strlen(cptr), collation.collation)) + size_t len= var->show_type() == SHOW_LEX_STRING ? + ((LEX_STRING*)(var->value_ptr(thd, var_type, &component)))->length : + strlen(cptr); + if (str->copy(cptr, len, collation.collation)) { null_value= TRUE; str= NULL; @@ -5145,7 +5258,7 @@ String* Item_func_get_system_var::val_str(String* str) null_value= TRUE; str= NULL; } - pthread_mutex_unlock(&LOCK_global_system_variables); + mysql_mutex_unlock(&LOCK_global_system_variables); break; } @@ -5162,7 +5275,7 @@ String* Item_func_get_system_var::val_str(String* str) break; default: - my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name); + my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str); str= NULL; break; } @@ -5210,9 +5323,9 @@ double Item_func_get_system_var::val_real() switch (var->show_type()) { case SHOW_DOUBLE: - pthread_mutex_lock(&LOCK_global_system_variables); + mysql_mutex_lock(&LOCK_global_system_variables); cached_dval= *(double*) var->value_ptr(thd, var_type, &component); - pthread_mutex_unlock(&LOCK_global_system_variables); + mysql_mutex_unlock(&LOCK_global_system_variables); used_query_id= thd->query_id; cached_null_value= null_value; if (null_value) @@ -5220,12 +5333,11 @@ double Item_func_get_system_var::val_real() cache_present|= GET_SYS_VAR_CACHE_DOUBLE; return cached_dval; case SHOW_CHAR: + case SHOW_LEX_STRING: case SHOW_CHAR_PTR: { - char *cptr; - - pthread_mutex_lock(&LOCK_global_system_variables); - cptr= var->show_type() == SHOW_CHAR ? + mysql_mutex_lock(&LOCK_global_system_variables); + char *cptr= var->show_type() == SHOW_CHAR ? (char*) var->value_ptr(thd, var_type, &component) : *(char**) var->value_ptr(thd, var_type, &component); if (cptr) @@ -5236,7 +5348,7 @@ double Item_func_get_system_var::val_real() null_value= TRUE; cached_dval= 0; } - pthread_mutex_unlock(&LOCK_global_system_variables); + mysql_mutex_unlock(&LOCK_global_system_variables); used_query_id= thd->query_id; cached_null_value= null_value; cache_present|= GET_SYS_VAR_CACHE_DOUBLE; @@ -5254,7 +5366,7 @@ double Item_func_get_system_var::val_real() cached_null_value= null_value; return cached_dval; default: - my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name); + my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str); return 0; } } @@ -5693,10 +5805,10 @@ longlong Item_func_is_free_lock::val_int() return 0; } - pthread_mutex_lock(&LOCK_user_locks); + mysql_mutex_lock(&LOCK_user_locks); ull= (User_level_lock *) my_hash_search(&hash_user_locks, (uchar*) res->ptr(), (size_t) res->length()); - pthread_mutex_unlock(&LOCK_user_locks); + mysql_mutex_unlock(&LOCK_user_locks); if (!ull || !ull->locked) return 1; return 0; @@ -5712,10 +5824,10 @@ longlong Item_func_is_used_lock::val_int() if (!res || !res->length()) return 0; - pthread_mutex_lock(&LOCK_user_locks); + mysql_mutex_lock(&LOCK_user_locks); ull= (User_level_lock *) my_hash_search(&hash_user_locks, (uchar*) res->ptr(), (size_t) res->length()); - pthread_mutex_unlock(&LOCK_user_locks); + mysql_mutex_unlock(&LOCK_user_locks); if (!ull || !ull->locked) return 0; @@ -6169,8 +6281,8 @@ void uuid_short_init() longlong Item_func_uuid_short::val_int() { ulonglong val; - pthread_mutex_lock(&LOCK_uuid_generator); + mysql_mutex_lock(&LOCK_uuid_generator); val= uuid_value++; - pthread_mutex_unlock(&LOCK_uuid_generator); + mysql_mutex_unlock(&LOCK_uuid_generator); return (longlong) val; } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 990f2ef951e..c33e0f4c6fb 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright (C) 2000-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -466,18 +466,18 @@ String *Item_func_des_encrypt::val_str(String *str) if (arg_count == 1) { /* Protect against someone doing FLUSH DES_KEY_FILE */ - VOID(pthread_mutex_lock(&LOCK_des_key_file)); + mysql_mutex_lock(&LOCK_des_key_file); keyschedule= des_keyschedule[key_number=des_default_key]; - VOID(pthread_mutex_unlock(&LOCK_des_key_file)); + mysql_mutex_unlock(&LOCK_des_key_file); } else if (args[1]->result_type() == INT_RESULT) { key_number= (uint) args[1]->val_int(); if (key_number > 9) goto error; - VOID(pthread_mutex_lock(&LOCK_des_key_file)); + mysql_mutex_lock(&LOCK_des_key_file); keyschedule= des_keyschedule[key_number]; - VOID(pthread_mutex_unlock(&LOCK_des_key_file)); + mysql_mutex_unlock(&LOCK_des_key_file); } else { @@ -567,9 +567,9 @@ String *Item_func_des_decrypt::val_str(String *str) key_number > 9) goto error; - VOID(pthread_mutex_lock(&LOCK_des_key_file)); + mysql_mutex_lock(&LOCK_des_key_file); keyschedule= des_keyschedule[key_number]; - VOID(pthread_mutex_unlock(&LOCK_des_key_file)); + mysql_mutex_unlock(&LOCK_des_key_file); } else { @@ -1703,17 +1703,17 @@ String *Item_func_encrypt::val_str(String *str) return 0; salt_ptr= salt_str->c_ptr_safe(); } - pthread_mutex_lock(&LOCK_crypt); + mysql_mutex_lock(&LOCK_crypt); char *tmp= crypt(res->c_ptr_safe(),salt_ptr); if (!tmp) { - pthread_mutex_unlock(&LOCK_crypt); + mysql_mutex_unlock(&LOCK_crypt); null_value= 1; return 0; } str->set(tmp, (uint) strlen(tmp), &my_charset_bin); str->copy(); - pthread_mutex_unlock(&LOCK_crypt); + mysql_mutex_unlock(&LOCK_crypt); return str; #else null_value=1; @@ -2999,7 +2999,7 @@ String *Item_load_file::val_str(String *str) strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv))) goto err; - if (!my_stat(path, &stat_info, MYF(0))) + if (!mysql_file_stat(key_file_loadfile, path, &stat_info, MYF(0))) goto err; if (!(stat_info.st_mode & S_IROTH)) @@ -3017,15 +3017,17 @@ String *Item_load_file::val_str(String *str) } if (tmp_value.alloc(stat_info.st_size)) goto err; - if ((file = my_open(file_name->ptr(), O_RDONLY, MYF(0))) < 0) + if ((file= mysql_file_open(key_file_loadfile, + file_name->ptr(), O_RDONLY, MYF(0))) < 0) goto err; - if (my_read(file, (uchar*) tmp_value.ptr(), stat_info.st_size, MYF(MY_NABP))) + if (mysql_file_read(file, (uchar*) tmp_value.ptr(), stat_info.st_size, + MYF(MY_NABP))) { - my_close(file, MYF(0)); + mysql_file_close(file, MYF(0)); goto err; } tmp_value.length(stat_info.st_size); - my_close(file, MYF(0)); + mysql_file_close(file, MYF(0)); null_value = 0; DBUG_RETURN(&tmp_value); @@ -3469,7 +3471,7 @@ String *Item_func_uuid::val_str(String *str) char *s; THD *thd= current_thd; - pthread_mutex_lock(&LOCK_uuid_generator); + mysql_mutex_lock(&LOCK_uuid_generator); if (! uuid_time) /* first UUID() call. initializing data */ { ulong tmp=sql_rnd_with_mutex(); @@ -3559,7 +3561,7 @@ String *Item_func_uuid::val_str(String *str) } uuid_time=tv; - pthread_mutex_unlock(&LOCK_uuid_generator); + mysql_mutex_unlock(&LOCK_uuid_generator); uint32 time_low= (uint32) (tv & 0xFFFFFFFF); uint16 time_mid= (uint16) ((tv >> 32) & 0xFFFF); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index a6499b9584c..267a4b38450 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1741,8 +1741,6 @@ subselect_union_engine::subselect_union_engine(st_select_lex_unit *u, :subselect_engine(item_arg, result_arg) { unit= u; - if (!result_arg) //out of memory - current_thd->fatal_error(); unit->item= item_arg; } @@ -1754,10 +1752,7 @@ int subselect_single_select_engine::prepare() join= new JOIN(thd, select_lex->item_list, select_lex->options | SELECT_NO_UNLOCK, result); if (!join || !result) - { - thd->fatal_error(); //out of memory - return 1; - } + return 1; /* Fatal error is set already. */ prepared= 1; SELECT_LEX *save_select= thd->lex->current_select; thd->lex->current_select= select_lex; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 82b68a87dfd..a61c5d59d67 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -29,6 +29,18 @@ #include "sql_select.h" /** + Calculate the affordable RAM limit for structures like TREE or Unique + used in Item_sum_* +*/ + +ulonglong Item_sum::ram_limitation(THD *thd) +{ + return min(thd->variables.tmp_table_size, + thd->variables.max_heap_table_size); +} + + +/** Prepare an aggregate function item for checking context conditions. The function initializes the members of the Item_sum object created @@ -566,7 +578,14 @@ int Item_sum::set_aggregator(Aggregator::Aggregator_type aggregator) { if (aggr) { + /* + Dependent subselects may be executed multiple times, making + set_aggregator to be called multiple times. The aggregator type + will be the same, but it needs to be reset so that it is + reevaluated with the new dependent data. + */ DBUG_ASSERT(aggregator == aggr->Aggrtype()); + aggr->clear(); return FALSE; } switch (aggregator) @@ -766,8 +785,8 @@ bool Aggregator_distinct::setup(THD *thd) } if (!(table= create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1, 0, - (select_lex->options | thd->options), - HA_POS_ERROR, (char*)""))) + (select_lex->options | thd->variables.option_bits), + HA_POS_ERROR, ""))) return TRUE; table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows table->no_rows=1; @@ -832,7 +851,7 @@ bool Aggregator_distinct::setup(THD *thd) } DBUG_ASSERT(tree == 0); tree= new Unique(compare_key, cmp_arg, tree_key_length, - thd->variables.max_heap_table_size); + item_sum->ram_limitation(thd)); /* The only time tree_key_length could be 0 is if someone does count(distinct) on a char(0) field - stupid thing to do, @@ -901,7 +920,7 @@ bool Aggregator_distinct::setup(THD *thd) are converted to binary representation as well. */ tree= new Unique(simple_raw_key_cmp, &tree_key_length, tree_key_length, - thd->variables.max_heap_table_size); + item_sum->ram_limitation(thd)); DBUG_RETURN(tree == 0); } @@ -1195,7 +1214,8 @@ void Item_sum_hybrid::setup(Item *item, Item *value_arg) { value= Item_cache::get_cache(item); value->setup(item); - value->store(value_arg); + if (value_arg) + value->store(value_arg); cmp= new Arg_comparator(); cmp->set_cmp_func(this, args, (Item**)&value, FALSE); collation.set(item->collation); @@ -3311,7 +3331,7 @@ bool Item_func_group_concat::setup(THD *thd) */ if (!(table= create_tmp_table(thd, tmp_table_param, all_fields, (ORDER*) 0, 0, TRUE, - (select_lex->options | thd->options), + (select_lex->options | thd->variables.option_bits), HA_POS_ERROR, (char*) ""))) DBUG_RETURN(TRUE); table->file->extra(HA_EXTRA_NO_ROWS); @@ -3342,7 +3362,7 @@ bool Item_func_group_concat::setup(THD *thd) unique_filter= new Unique(group_concat_key_cmp_with_distinct, (void*)this, tree_key_length, - thd->variables.max_heap_table_size); + ram_limitation(thd)); DBUG_RETURN(FALSE); } diff --git a/sql/item_sum.h b/sql/item_sum.h index 88be83137cb..26f0a08096e 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -364,6 +364,7 @@ protected: Item **orig_args, *tmp_orig_args[2]; table_map used_tables_cache; bool forced_const; + static ulonglong ram_limitation(THD *thd); public: diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 1702868aeb8..392bc936f17 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -865,6 +865,8 @@ static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs, { const char *end=str+length; uint i; + long msec_length= 0; + while (str != end && !my_isdigit(cs,*str)) str++; @@ -874,12 +876,7 @@ static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs, const char *start= str; for (value=0; str != end && my_isdigit(cs,*str) ; str++) value= value*LL(10) + (longlong) (*str - '0'); - if (transform_msec && i == count - 1) // microseconds always last - { - int msec_length= 6 - (int)(str - start); - if (msec_length > 0) - value*= (long)log_10_int[msec_length]; - } + msec_length= 6 - (str - start); values[i]= value; while (str != end && !my_isdigit(cs,*str)) str++; @@ -893,6 +890,10 @@ static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs, break; } } + + if (transform_msec && msec_length > 0) + values[count - 1] *= (long) log_10_int[msec_length]; + return (str != end); } @@ -1854,7 +1855,7 @@ longlong Item_func_sec_to_time::val_int() sec_to_time(arg_val, args[0]->unsigned_flag, <ime); return (ltime.neg ? -1 : 1) * - ((ltime.hour)*10000 + ltime.minute*100 + ltime.second); + (longlong) ((ltime.hour)*10000 + ltime.minute*100 + ltime.second); } @@ -2666,7 +2667,8 @@ longlong Item_time_typecast::val_int() null_value= 1; return 0; } - return ltime.hour * 10000L + ltime.minute * 100 + ltime.second; + return (ltime.neg ? -1 : 1) * + (longlong) ((ltime.hour)*10000 + ltime.minute*100 + ltime.second); } String *Item_time_typecast::val_str(String *str) diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index f6c316c15c6..860bd983184 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -96,7 +96,7 @@ public: { int *input_version= (int*)int_arg; /* This function was introduced in 5.5 */ - int output_version= (*input_version, 50500); + int output_version= max(*input_version, 50500); *input_version= output_version; return 0; } diff --git a/sql/keycaches.cc b/sql/keycaches.cc new file mode 100644 index 00000000000..d68e2bccd96 --- /dev/null +++ b/sql/keycaches.cc @@ -0,0 +1,163 @@ +/* Copyright (C) 2002-2006 MySQL AB, 2009 Sun Microsystems, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "keycaches.h" + +/**************************************************************************** + Named list handling +****************************************************************************/ + +NAMED_ILIST key_caches; + +/** + ilink (intrusive list element) with a name +*/ +class NAMED_ILINK :public ilink +{ +public: + const char *name; + uint name_length; + uchar* data; + + NAMED_ILINK(I_List<NAMED_ILINK> *links, const char *name_arg, + uint name_length_arg, uchar* data_arg) + :name_length(name_length_arg), data(data_arg) + { + name= my_strndup(name_arg, name_length, MYF(MY_WME)); + links->push_back(this); + } + inline bool cmp(const char *name_cmp, uint length) + { + return length == name_length && !memcmp(name, name_cmp, length); + } + ~NAMED_ILINK() + { + my_free((uchar*) name, MYF(0)); + } +}; + +uchar* find_named(I_List<NAMED_ILINK> *list, const char *name, uint length, + NAMED_ILINK **found) +{ + I_List_iterator<NAMED_ILINK> it(*list); + NAMED_ILINK *element; + while ((element= it++)) + { + if (element->cmp(name, length)) + { + if (found) + *found= element; + return element->data; + } + } + return 0; +} + + +void NAMED_ILIST::delete_elements(void (*free_element)(const char *name, uchar*)) +{ + NAMED_ILINK *element; + DBUG_ENTER("NAMED_ILIST::delete_elements"); + while ((element= get())) + { + (*free_element)(element->name, element->data); + delete element; + } + DBUG_VOID_RETURN; +} + + +/* Key cache functions */ + +LEX_STRING default_key_cache_base= {C_STRING_WITH_LEN("default")}; + +KEY_CACHE zero_key_cache; ///< @@nonexistent_cache.param->value_ptr() points here + +KEY_CACHE *get_key_cache(LEX_STRING *cache_name) +{ + if (!cache_name || ! cache_name->length) + cache_name= &default_key_cache_base; + return ((KEY_CACHE*) find_named(&key_caches, + cache_name->str, cache_name->length, 0)); +} + +KEY_CACHE *create_key_cache(const char *name, uint length) +{ + KEY_CACHE *key_cache; + DBUG_ENTER("create_key_cache"); + DBUG_PRINT("enter",("name: %.*s", length, name)); + + if ((key_cache= (KEY_CACHE*) my_malloc(sizeof(KEY_CACHE), + MYF(MY_ZEROFILL | MY_WME)))) + { + if (!new NAMED_ILINK(&key_caches, name, length, (uchar*) key_cache)) + { + my_free((char*) key_cache, MYF(0)); + key_cache= 0; + } + else + { + /* + Set default values for a key cache + The values in dflt_key_cache_var is set by my_getopt() at startup + + We don't set 'buff_size' as this is used to enable the key cache + */ + key_cache->param_block_size= dflt_key_cache_var.param_block_size; + key_cache->param_division_limit= dflt_key_cache_var.param_division_limit; + key_cache->param_age_threshold= dflt_key_cache_var.param_age_threshold; + } + } + DBUG_RETURN(key_cache); +} + + +KEY_CACHE *get_or_create_key_cache(const char *name, uint length) +{ + LEX_STRING key_cache_name; + KEY_CACHE *key_cache; + + key_cache_name.str= (char *) name; + key_cache_name.length= length; + if (!(key_cache= get_key_cache(&key_cache_name))) + key_cache= create_key_cache(name, length); + return key_cache; +} + + +void free_key_cache(const char *name, KEY_CACHE *key_cache) +{ + end_key_cache(key_cache, 1); // Can never fail + my_free((char*) key_cache, MYF(0)); +} + + +bool process_key_caches(process_key_cache_t func) +{ + I_List_iterator<NAMED_ILINK> it(key_caches); + NAMED_ILINK *element; + + while ((element= it++)) + { + KEY_CACHE *key_cache= (KEY_CACHE *) element->data; + func(element->name, key_cache); + } + return 0; +} + +#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION +template class I_List_iterator<NAMED_ILINK>; +#endif + diff --git a/sql/keycaches.h b/sql/keycaches.h new file mode 100644 index 00000000000..542a4d14c3d --- /dev/null +++ b/sql/keycaches.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2002-2006 MySQL AB, 2009 Sun Microsystems, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "sql_list.h" +#include <keycache.h> + +extern "C" +{ + typedef int (*process_key_cache_t) (const char *, KEY_CACHE *); +} + +class NAMED_ILINK; + +class NAMED_ILIST: public I_List<NAMED_ILINK> +{ + public: + void delete_elements(void (*free_element)(const char*, uchar*)); +}; + +extern LEX_STRING default_key_cache_base; +extern KEY_CACHE zero_key_cache; +extern NAMED_ILIST key_caches; + +KEY_CACHE *create_key_cache(const char *name, uint length); +KEY_CACHE *get_key_cache(LEX_STRING *cache_name); +KEY_CACHE *get_or_create_key_cache(const char *name, uint length); +void free_key_cache(const char *name, KEY_CACHE *key_cache); +bool process_key_caches(process_key_cache_t func); + diff --git a/sql/lex.h b/sql/lex.h index cd0c042159f..7961339c4f3 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -196,6 +196,7 @@ static SYMBOL symbols[] = { { "ENGINE", SYM(ENGINE_SYM)}, { "ENGINES", SYM(ENGINES_SYM)}, { "ENUM", SYM(ENUM)}, + { "ERROR", SYM(ERROR_SYM)}, { "ERRORS", SYM(ERRORS)}, { "ESCAPE", SYM(ESCAPE_SYM)}, { "ESCAPED", SYM(ESCAPED)}, @@ -230,6 +231,7 @@ static SYMBOL symbols[] = { { "FULL", SYM(FULL)}, { "FULLTEXT", SYM(FULLTEXT_SYM)}, { "FUNCTION", SYM(FUNCTION_SYM)}, + { "GENERAL", SYM(GENERAL)}, { "GEOMETRY", SYM(GEOMETRY_SYM)}, { "GEOMETRYCOLLECTION",SYM(GEOMETRYCOLLECTION)}, { "GET_FORMAT", SYM(GET_FORMAT)}, @@ -259,8 +261,6 @@ static SYMBOL symbols[] = { { "INFILE", SYM(INFILE)}, { "INITIAL_SIZE", SYM(INITIAL_SIZE_SYM)}, { "INNER", SYM(INNER_SYM)}, - { "INNOBASE", SYM(INNOBASE_SYM)}, - { "INNODB", SYM(INNOBASE_SYM)}, { "INOUT", SYM(INOUT_SYM)}, { "INSENSITIVE", SYM(INSENSITIVE_SYM)}, { "INSERT", SYM(INSERT)}, @@ -440,6 +440,7 @@ static SYMBOL symbols[] = { { "REDUNDANT", SYM(REDUNDANT_SYM)}, { "REFERENCES", SYM(REFERENCES)}, { "REGEXP", SYM(REGEXP)}, + { "RELAY", SYM(RELAY)}, { "RELAYLOG", SYM(RELAYLOG_SYM)}, { "RELAY_LOG_FILE", SYM(RELAY_LOG_FILE_SYM)}, { "RELAY_LOG_POS", SYM(RELAY_LOG_POS_SYM)}, @@ -495,6 +496,7 @@ static SYMBOL symbols[] = { { "SIGNED", SYM(SIGNED_SYM)}, { "SIMPLE", SYM(SIMPLE_SYM)}, { "SLAVE", SYM(SLAVE)}, + { "SLOW", SYM(SLOW)}, { "SNAPSHOT", SYM(SNAPSHOT_SYM)}, { "SMALLINT", SYM(SMALLINT)}, { "SOCKET", SYM(SOCKET_SYM)}, diff --git a/sql/lock.cc b/sql/lock.cc index c0cda1dbf03..6106e20678a 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -90,7 +90,6 @@ extern HASH open_cache; static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table,uint count, uint flags, TABLE **write_locked); -static void reset_lock_data(MYSQL_LOCK *sql_lock); static int lock_external(THD *thd, TABLE **table,uint count); static int unlock_external(THD *thd, TABLE **table,uint count); static void print_lock_error(int error, const char *); @@ -194,6 +193,60 @@ int mysql_lock_tables_check(THD *thd, TABLE **tables, uint count, uint flags) DBUG_RETURN(0); } + +/** + Reset lock type in lock data and free. + + @param mysql_lock Lock structures to reset. + + @note After a locking error we want to quit the locking of the table(s). + The test case in the bug report for Bug #18544 has the following + cases: 1. Locking error in lock_external() due to InnoDB timeout. + 2. Locking error in get_lock_data() due to missing write permission. + 3. Locking error in wait_if_global_read_lock() due to lock conflict. + + @note In all these cases we have already set the lock type into the lock + data of the open table(s). If the table(s) are in the open table + cache, they could be reused with the non-zero lock type set. This + could lead to ignoring a different lock type with the next lock. + + @note Clear the lock type of all lock data. This ensures that the next + lock request will set its lock type properly. +*/ + + +static void reset_lock_data(MYSQL_LOCK *sql_lock) +{ + THR_LOCK_DATA **ldata, **ldata_end; + DBUG_ENTER("reset_lock_data"); + + /* Clear the lock type of all lock data to avoid reusage. */ + for (ldata= sql_lock->locks, ldata_end= ldata + sql_lock->lock_count; + ldata < ldata_end; + ldata++) + { + /* Reset lock type. */ + (*ldata)->type= TL_UNLOCK; + } + DBUG_VOID_RETURN; +} + + +/** + Reset lock type in lock data and free. + + @param mysql_lock Lock structures to reset. + +*/ + +static void reset_lock_data_and_free(MYSQL_LOCK **mysql_lock) +{ + reset_lock_data(*mysql_lock); + my_free(*mysql_lock, MYF(0)); + *mysql_lock= 0; +} + + MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, uint flags, bool *need_reopen) { @@ -224,16 +277,13 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, if (wait_if_global_read_lock(thd, 1, 1)) { /* Clear the lock type of all lock data to avoid reusage. */ - reset_lock_data(sql_lock); - my_free((uchar*) sql_lock,MYF(0)); - sql_lock=0; + reset_lock_data_and_free(&sql_lock); break; } if (thd->version != refresh_version) { /* Clear the lock type of all lock data to avoid reusage. */ - reset_lock_data(sql_lock); - my_free((uchar*) sql_lock,MYF(0)); + reset_lock_data_and_free(&sql_lock); goto retry; } } @@ -248,9 +298,7 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, Someone has issued SET GLOBAL READ_ONLY=1 and we want a write lock. We do not wait for READ_ONLY=0, and fail. */ - reset_lock_data(sql_lock); - my_free((uchar*) sql_lock, MYF(0)); - sql_lock=0; + reset_lock_data_and_free(&sql_lock); my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); break; } @@ -261,14 +309,11 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, sql_lock->table_count)) { /* Clear the lock type of all lock data to avoid reusage. */ - reset_lock_data(sql_lock); - my_free((uchar*) sql_lock,MYF(0)); - sql_lock=0; + reset_lock_data_and_free(&sql_lock); break; } - thd_proc_info(thd, "Table lock"); DBUG_PRINT("info", ("thd->proc_info %s", thd->proc_info)); - thd->locked=1; + thd_proc_info(thd, "Locked"); /* Copy the lock data array. thr_multi_lock() reorders its contens. */ memcpy(sql_lock->locks + sql_lock->lock_count, sql_lock->locks, sql_lock->lock_count * sizeof(*sql_lock->locks)); @@ -280,23 +325,16 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, if (rc > 1) /* a timeout or a deadlock */ { if (sql_lock->table_count) - VOID(unlock_external(thd, sql_lock->table, sql_lock->table_count)); + (void) unlock_external(thd, sql_lock->table, sql_lock->table_count); + reset_lock_data_and_free(&sql_lock); my_error(rc, MYF(0)); - my_free((uchar*) sql_lock,MYF(0)); - sql_lock= 0; break; } else if (rc == 1) /* aborted */ { - /* - reset_lock_data is required here. If thr_multi_lock fails it - resets lock type for tables, which were locked before (and - including) one that caused error. Lock type for other tables - preserved. - */ - reset_lock_data(sql_lock); thd->some_tables_deleted=1; // Try again sql_lock->lock_count= 0; // Locks are already freed + // Fall through: unlock, reset lock data, free and retry } else if (!thd->some_tables_deleted || (flags & MYSQL_LOCK_IGNORE_FLUSH)) { @@ -304,23 +342,30 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, Thread was killed or lock aborted. Let upper level close all used tables and retry or give error. */ - thd->locked=0; break; } else if (!thd->open_tables) { // Only using temporary tables, no need to unlock thd->some_tables_deleted=0; - thd->locked=0; break; } thd_proc_info(thd, 0); - /* some table was altered or deleted. reopen tables marked deleted */ - mysql_unlock_tables(thd,sql_lock); - thd->locked=0; + /* going to retry, unlock all tables */ + if (sql_lock->lock_count) + thr_multi_unlock(sql_lock->locks, sql_lock->lock_count); + + if (sql_lock->table_count) + (void) unlock_external(thd, sql_lock->table, sql_lock->table_count); + + /* + If thr_multi_lock fails it resets lock type for tables, which + were locked before (and including) one that caused error. Lock + type for other tables preserved. + */ + reset_lock_data_and_free(&sql_lock); retry: - sql_lock=0; if (flags & MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN) { *need_reopen= TRUE; @@ -388,7 +433,7 @@ void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock) if (sql_lock->lock_count) thr_multi_unlock(sql_lock->locks,sql_lock->lock_count); if (sql_lock->table_count) - VOID(unlock_external(thd,sql_lock->table,sql_lock->table_count)); + (void) unlock_external(thd,sql_lock->table,sql_lock->table_count); my_free((uchar*) sql_lock,MYF(0)); DBUG_VOID_RETURN; } @@ -452,7 +497,7 @@ void mysql_unlock_read_tables(THD *thd, MYSQL_LOCK *sql_lock) /* Unlock all read locked tables */ if (i != found) { - VOID(unlock_external(thd,table,i-found)); + (void) unlock_external(thd,table,i-found); sql_lock->table_count=found; } /* Fix the lock positions in TABLE */ @@ -863,8 +908,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, my_error(ER_OPEN_AS_READONLY,MYF(0),table->alias); /* Clear the lock type of the lock data that are stored already. */ sql_lock->lock_count= (uint) (locks - sql_lock->locks); - reset_lock_data(sql_lock); - my_free((uchar*) sql_lock,MYF(0)); + reset_lock_data_and_free(&sql_lock); DBUG_RETURN(0); } } @@ -905,42 +949,6 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, } -/** - Reset lock type in lock data. - - After a locking error we want to quit the locking of the table(s). - The test case in the bug report for Bug #18544 has the following - cases: - -# Locking error in lock_external() due to InnoDB timeout. - -# Locking error in get_lock_data() due to missing write permission. - -# Locking error in wait_if_global_read_lock() due to lock conflict. - - In all these cases we have already set the lock type into the lock - data of the open table(s). If the table(s) are in the open table - cache, they could be reused with the non-zero lock type set. This - could lead to ignoring a different lock type with the next lock. - - Clear the lock type of all lock data. This ensures that the next - lock request will set its lock type properly. - - @param sql_lock The MySQL lock. -*/ - -static void reset_lock_data(MYSQL_LOCK *sql_lock) -{ - THR_LOCK_DATA **ldata; - THR_LOCK_DATA **ldata_end; - - for (ldata= sql_lock->locks, ldata_end= ldata + sql_lock->lock_count; - ldata < ldata_end; - ldata++) - { - /* Reset lock type. */ - (*ldata)->type= TL_UNLOCK; - } -} - - /***************************************************************************** Lock table based on the name. This is used when we need total access to a closed, not open table @@ -970,7 +978,7 @@ int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list) if (wait_if_global_read_lock(thd, 0, 1)) DBUG_RETURN(1); - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); if ((lock_retcode = lock_table_name(thd, table_list, TRUE)) < 0) goto end; if (lock_retcode && wait_for_locked_table_names(thd, table_list)) @@ -981,7 +989,7 @@ int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list) error=0; end: - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); start_waiting_global_read_lock(thd); DBUG_RETURN(error); } @@ -1020,6 +1028,7 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list, bool check_in_use) char key[MAX_DBKEY_LENGTH]; char *db= table_list->db; uint key_length; + bool found_locked_table= FALSE; HASH_SEARCH_STATE state; DBUG_ENTER("lock_table_name"); DBUG_PRINT("enter",("db: %s name: %s", db, table_list->table_name)); @@ -1035,6 +1044,13 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list, bool check_in_use) table = (TABLE*) my_hash_next(&open_cache,(uchar*) key, key_length, &state)) { + if (table->reginfo.lock_type < TL_WRITE) + { + if (table->in_use == thd) + found_locked_table= TRUE; + continue; + } + if (table->in_use == thd) { DBUG_PRINT("info", ("Table is in use")); @@ -1045,6 +1061,17 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list, bool check_in_use) } } + if (thd->locked_tables && thd->locked_tables->table_count && + ! find_temporary_table(thd, table_list->db, table_list->table_name)) + { + if (found_locked_table) + my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), table_list->alias); + else + my_error(ER_TABLE_NOT_LOCKED, MYF(0), table_list->alias); + + DBUG_RETURN(-1); + } + if (!(table= table_cache_insert_placeholder(thd, key, key_length))) DBUG_RETURN(-1); @@ -1091,7 +1118,7 @@ bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list) bool result=0; DBUG_ENTER("wait_for_locked_table_names"); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); while (locked_named_table(thd,table_list)) { @@ -1101,7 +1128,7 @@ bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list) break; } wait_for_condition(thd, &LOCK_open, &COND_refresh); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); } DBUG_RETURN(result); } @@ -1409,7 +1436,7 @@ bool lock_global_read_lock(THD *thd) if (!thd->global_read_lock) { const char *old_message; - (void) pthread_mutex_lock(&LOCK_global_read_lock); + mysql_mutex_lock(&LOCK_global_read_lock); old_message=thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock, "Waiting to get readlock"); DBUG_PRINT("info", @@ -1418,7 +1445,7 @@ bool lock_global_read_lock(THD *thd) waiting_for_read_lock++; while (protect_against_global_read_lock && !thd->killed) - pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock); + mysql_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock); waiting_for_read_lock--; if (thd->killed) { @@ -1449,16 +1476,16 @@ void unlock_global_read_lock(THD *thd) ("global_read_lock: %u global_read_lock_blocks_commit: %u", global_read_lock, global_read_lock_blocks_commit)); - pthread_mutex_lock(&LOCK_global_read_lock); + mysql_mutex_lock(&LOCK_global_read_lock); tmp= --global_read_lock; if (thd->global_read_lock == MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT) --global_read_lock_blocks_commit; - pthread_mutex_unlock(&LOCK_global_read_lock); + mysql_mutex_unlock(&LOCK_global_read_lock); /* Send the signal outside the mutex to avoid a context switch */ if (!tmp) { DBUG_PRINT("signal", ("Broadcasting COND_global_read_lock")); - pthread_cond_broadcast(&COND_global_read_lock); + mysql_cond_broadcast(&COND_global_read_lock); } thd->global_read_lock= 0; @@ -1481,9 +1508,9 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh, threads could not close their tables. This would make a pretty deadlock. */ - safe_mutex_assert_not_owner(&LOCK_open); + mysql_mutex_assert_not_owner(&LOCK_open); - (void) pthread_mutex_lock(&LOCK_global_read_lock); + mysql_mutex_lock(&LOCK_global_read_lock); if ((need_exit_cond= must_wait)) { if (thd->global_read_lock) // This thread had the read locks @@ -1491,7 +1518,7 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh, if (is_not_commit) my_message(ER_CANT_UPDATE_WITH_READLOCK, ER(ER_CANT_UPDATE_WITH_READLOCK), MYF(0)); - (void) pthread_mutex_unlock(&LOCK_global_read_lock); + mysql_mutex_unlock(&LOCK_global_read_lock); /* We allow FLUSHer to COMMIT; we assume FLUSHer knows what it does. This allowance is needed to not break existing versions of innobackup @@ -1505,7 +1532,7 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh, (!abort_on_refresh || thd->version == refresh_version)) { DBUG_PRINT("signal", ("Waiting for COND_global_read_lock")); - (void) pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock); + mysql_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock); DBUG_PRINT("signal", ("Got COND_global_read_lock")); } if (thd->killed) @@ -1520,7 +1547,7 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh, if (unlikely(need_exit_cond)) thd->exit_cond(old_message); // this unlocks LOCK_global_read_lock else - pthread_mutex_unlock(&LOCK_global_read_lock); + mysql_mutex_unlock(&LOCK_global_read_lock); DBUG_RETURN(result); } @@ -1531,13 +1558,13 @@ void start_waiting_global_read_lock(THD *thd) DBUG_ENTER("start_waiting_global_read_lock"); if (unlikely(thd->global_read_lock)) DBUG_VOID_RETURN; - (void) pthread_mutex_lock(&LOCK_global_read_lock); + mysql_mutex_lock(&LOCK_global_read_lock); DBUG_ASSERT(protect_against_global_read_lock); tmp= (!--protect_against_global_read_lock && (waiting_for_read_lock || global_read_lock_blocks_commit)); - (void) pthread_mutex_unlock(&LOCK_global_read_lock); + mysql_mutex_unlock(&LOCK_global_read_lock); if (tmp) - pthread_cond_broadcast(&COND_global_read_lock); + mysql_cond_broadcast(&COND_global_read_lock); DBUG_VOID_RETURN; } @@ -1553,7 +1580,7 @@ bool make_global_read_lock_block_commit(THD *thd) */ if (thd->global_read_lock != GOT_GLOBAL_READ_LOCK) DBUG_RETURN(0); - pthread_mutex_lock(&LOCK_global_read_lock); + mysql_mutex_lock(&LOCK_global_read_lock); /* increment this BEFORE waiting on cond (otherwise race cond) */ global_read_lock_blocks_commit++; /* For testing we set up some blocking, to see if we can be killed */ @@ -1562,7 +1589,7 @@ bool make_global_read_lock_block_commit(THD *thd) old_message= thd->enter_cond(&COND_global_read_lock, &LOCK_global_read_lock, "Waiting for all running commits to finish"); while (protect_against_global_read_lock && !thd->killed) - pthread_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock); + mysql_cond_wait(&COND_global_read_lock, &LOCK_global_read_lock); DBUG_EXECUTE_IF("make_global_read_lock_block_commit_loop", protect_against_global_read_lock--;); if ((error= test(thd->killed))) @@ -1580,7 +1607,7 @@ bool make_global_read_lock_block_commit(THD *thd) Due to a bug in a threading library it could happen that a signal did not reach its target. A condition for this was that the same condition variable was used with different mutexes in - pthread_cond_wait(). Some time ago we changed LOCK_open to + mysql_cond_wait(). Some time ago we changed LOCK_open to LOCK_global_read_lock in global read lock handling. So COND_refresh was used with LOCK_open and LOCK_global_read_lock. @@ -1595,8 +1622,8 @@ bool make_global_read_lock_block_commit(THD *thd) void broadcast_refresh(void) { - VOID(pthread_cond_broadcast(&COND_refresh)); - VOID(pthread_cond_broadcast(&COND_global_read_lock)); + mysql_cond_broadcast(&COND_refresh); + mysql_cond_broadcast(&COND_global_read_lock); } /** diff --git a/sql/log.cc b/sql/log.cc index 491a9a0ac43..5a583e9e134 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,6 +28,7 @@ #include "sql_repl.h" #include "rpl_filter.h" #include "rpl_rli.h" +#include "sql_audit.h" #include <my_dir.h> #include <stdarg.h> @@ -42,7 +43,6 @@ /* max size of the log message */ #define MAX_LOG_BUFFER_SIZE 1024 -#define MAX_USER_HOST_SIZE 512 #define MAX_TIME_SIZE 32 #define MY_OFF_T_UNDEF (~(my_off_t)0UL) @@ -53,7 +53,7 @@ LOGGER logger; MYSQL_BIN_LOG mysql_bin_log(&sync_binlog_period); static bool test_if_number(const char *str, - long *res, bool allow_wildcards); + ulong *res, bool allow_wildcards); static int binlog_init(void *p); static int binlog_close_connection(handlerton *hton, THD *thd); static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv); @@ -63,6 +63,35 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all); static int binlog_prepare(handlerton *hton, THD *thd, bool all); /** + purge logs, master and slave sides both, related error code + convertor. + Called from @c purge_error_message(), @c MYSQL_BIN_LOG::reset_logs() + + @param res an internal to purging routines error code + + @return the user level error code ER_* +*/ +uint purge_log_get_error_code(int res) +{ + uint errcode= 0; + + switch (res) { + case 0: break; + case LOG_INFO_EOF: errcode= ER_UNKNOWN_TARGET_BINLOG; break; + case LOG_INFO_IO: errcode= ER_IO_ERR_LOG_INDEX_READ; break; + case LOG_INFO_INVALID:errcode= ER_BINLOG_PURGE_PROHIBITED; break; + case LOG_INFO_SEEK: errcode= ER_FSEEK_FAIL; break; + case LOG_INFO_MEM: errcode= ER_OUT_OF_RESOURCES; break; + case LOG_INFO_FATAL: errcode= ER_BINLOG_PURGE_FATAL_ERR; break; + case LOG_INFO_IN_USE: errcode= ER_LOG_IN_USE; break; + case LOG_INFO_EMFILE: errcode= ER_BINLOG_PURGE_EMFILE; break; + default: errcode= ER_LOG_PURGE_UNKNOWN_ERR; break; + } + + return errcode; +} + +/** Silence all errors and warnings reported when performing a write to a log table. Errors and warnings are not reported to the client or SQL exception @@ -109,18 +138,22 @@ sql_print_message_func sql_print_message_handlers[3] = sql_print_error }; - /** - Create the name of the default general log file - + Create the name of the log specified. + + This method forms a new path + file name for the + log specified in @c name. + @param[IN] buff Location for building new string. - @param[IN] log_ext The extension for the file (e.g .log) - @returns Pointer to a new string containing the name + @param[IN] name Name of the log file. + @param[IN] log_ext The extension for the log (e.g. .log). + + @returns Pointer to new string containing the name. */ -char *make_default_log_name(char *buff,const char* log_ext) +char *make_log_name(char *buff, const char *name, const char* log_ext) { - strmake(buff, default_logfile_name, FN_REFLEN-5); - return fn_format(buff, buff, mysql_data_home, log_ext, + strmake(buff, name, FN_REFLEN-5); + return fn_format(buff, buff, mysql_real_data_home, log_ext, MYF(MY_UNPACK_FILENAME|MY_REPLACE_EXT)); } @@ -135,24 +168,24 @@ char *make_default_log_name(char *buff,const char* log_ext) class Mutex_sentry { public: - Mutex_sentry(pthread_mutex_t *mutex) + Mutex_sentry(mysql_mutex_t *mutex) : m_mutex(mutex) { if (m_mutex) - pthread_mutex_lock(mutex); + mysql_mutex_lock(mutex); } ~Mutex_sentry() { if (m_mutex) - pthread_mutex_unlock(m_mutex); + mysql_mutex_unlock(m_mutex); #ifndef DBUG_OFF m_mutex= 0; #endif } private: - pthread_mutex_t *m_mutex; + mysql_mutex_t *m_mutex; // It's not allowed to copy this object in any way Mutex_sentry(Mutex_sentry const&); @@ -160,115 +193,155 @@ private: }; /* - Helper class to store binary log transaction data. + Helper classes to store non-transactional and transactional data + before copying it to the binary log. */ -class binlog_trx_data { +class binlog_cache_data +{ public: - binlog_trx_data() - : at_least_one_stmt_committed(0), incident(FALSE), m_pending(0), - before_stmt_pos(MY_OFF_T_UNDEF) + binlog_cache_data(): m_pending(0), before_stmt_pos(MY_OFF_T_UNDEF), + incident(FALSE) { - trans_log.end_of_file= max_binlog_cache_size; + cache_log.end_of_file= max_binlog_cache_size; } - ~binlog_trx_data() + ~binlog_cache_data() { - DBUG_ASSERT(pending() == NULL); - close_cached_file(&trans_log); + DBUG_ASSERT(empty()); + close_cached_file(&cache_log); } - my_off_t position() const { - return my_b_tell(&trans_log); + bool empty() const + { + return pending() == NULL && my_b_tell(&cache_log) == 0; } - bool empty() const + Rows_log_event *pending() const { - return pending() == NULL && my_b_tell(&trans_log) == 0; + return m_pending; } - /* - Truncate the transaction cache to a certain position. This - includes deleting the pending event. - */ - void truncate(my_off_t pos) + void set_pending(Rows_log_event *const pending) { - DBUG_PRINT("info", ("truncating to position %lu", (ulong) pos)); - DBUG_PRINT("info", ("before_stmt_pos=%lu", (ulong) pos)); - if (pending()) - { - delete pending(); - } - set_pending(0); - reinit_io_cache(&trans_log, WRITE_CACHE, pos, 0, 0); - trans_log.end_of_file= max_binlog_cache_size; - if (pos < before_stmt_pos) - before_stmt_pos= MY_OFF_T_UNDEF; + m_pending= pending; + } - /* - The only valid positions that can be truncated to are at the - beginning of a statement. We are relying on this fact to be able - to set the at_least_one_stmt_committed flag correctly. In other word, if - we are truncating to the beginning of the transaction cache, - there will be no statements in the cache, otherwhise, we will - have at least one statement in the transaction cache. - */ - at_least_one_stmt_committed= (pos > 0); + void set_incident(void) + { + incident= TRUE; + } + + bool has_incident(void) + { + return(incident); } - /* - Reset the entire contents of the transaction cache, emptying it - completely. - */ - void reset() { - if (!empty()) - truncate(0); - before_stmt_pos= MY_OFF_T_UNDEF; + void reset() + { + truncate(0); incident= FALSE; - trans_log.end_of_file= max_binlog_cache_size; + before_stmt_pos= MY_OFF_T_UNDEF; + cache_log.end_of_file= max_binlog_cache_size; DBUG_ASSERT(empty()); } - Rows_log_event *pending() const + my_off_t get_byte_position() const { - return m_pending; + return my_b_tell(&cache_log); } - void set_pending(Rows_log_event *const pending) + my_off_t get_prev_position() { - m_pending= pending; + return(before_stmt_pos); } - IO_CACHE trans_log; // The transaction cache - - void set_incident(void) + void set_prev_position(my_off_t pos) { - incident= TRUE; + before_stmt_pos= pos; } - bool has_incident(void) + void restore_prev_position() { - return(incident); + truncate(before_stmt_pos); } - /** - Boolean that is true if there is at least one statement in the - transaction cache. + void restore_savepoint(my_off_t pos) + { + truncate(pos); + if (pos < before_stmt_pos) + before_stmt_pos= MY_OFF_T_UNDEF; + } + + /* + Cache to store data before copying it to the binary log. */ - bool at_least_one_stmt_committed; - bool incident; + IO_CACHE cache_log; private: /* - Pending binrows event. This event is the event where the rows are - currently written. + Pending binrows event. This event is the event where the rows are currently + written. */ Rows_log_event *m_pending; -public: /* Binlog position before the start of the current statement. */ my_off_t before_stmt_pos; + + /* + This indicates that some events did not get into the cache and most likely + it is corrupted. + */ + bool incident; + + /* + It truncates the cache to a certain position. This includes deleting the + pending event. + */ + void truncate(my_off_t pos) + { + DBUG_PRINT("info", ("truncating to position %lu", (ulong) pos)); + if (pending()) + { + delete pending(); + set_pending(0); + } + reinit_io_cache(&cache_log, WRITE_CACHE, pos, 0, 0); + cache_log.end_of_file= max_binlog_cache_size; + } + + binlog_cache_data& operator=(const binlog_cache_data& info); + binlog_cache_data(const binlog_cache_data& info); +}; + +class binlog_cache_mngr { +public: + binlog_cache_mngr() {} + + void reset_cache(binlog_cache_data* cache_data) + { + cache_data->reset(); + } + + binlog_cache_data* get_binlog_cache_data(bool is_transactional) + { + return (is_transactional ? &trx_cache : &stmt_cache); + } + + IO_CACHE* get_binlog_cache_log(bool is_transactional) + { + return (is_transactional ? &trx_cache.cache_log : &stmt_cache.cache_log); + } + + binlog_cache_data stmt_cache; + + binlog_cache_data trx_cache; + +private: + + binlog_cache_mngr& operator=(const binlog_cache_mngr& info); + binlog_cache_mngr(const binlog_cache_mngr& info); }; handlerton *binlog_hton; @@ -391,8 +464,8 @@ bool Log_to_csv_event_handler:: */ save_time_zone_used= thd->time_zone_used; - save_thd_options= thd->options; - thd->options&= ~OPTION_BIN_LOG; + save_thd_options= thd->variables.option_bits; + thd->variables.option_bits&= ~OPTION_BIN_LOG; bzero(& table_list, sizeof(TABLE_LIST)); table_list.alias= table_list.table_name= GENERAL_LOG_NAME.str; @@ -404,7 +477,7 @@ bool Log_to_csv_event_handler:: table_list.db_length= MYSQL_SCHEMA_NAME.length; /* - 1) open_performance_schema_table generates an error of the + 1) open_log_table generates an error of the table can not be opened or is corrupted. 2) "INSERT INTO general_log" can generate warning sometimes. @@ -417,8 +490,7 @@ bool Log_to_csv_event_handler:: thd->push_internal_handler(& error_handler); need_pop= TRUE; - if (!(table= open_performance_schema_table(thd, & table_list, - & open_tables_backup))) + if (!(table= open_log_table(thd, &table_list, &open_tables_backup))) goto err; need_close= TRUE; @@ -498,9 +570,9 @@ err: if (need_pop) thd->pop_internal_handler(); if (need_close) - close_performance_schema_table(thd, & open_tables_backup); + close_log_table(thd, &open_tables_backup); - thd->options= save_thd_options; + thd->variables.option_bits= save_thd_options; thd->time_zone_used= save_time_zone_used; return result; } @@ -568,8 +640,7 @@ bool Log_to_csv_event_handler:: table_list.db= MYSQL_SCHEMA_NAME.str; table_list.db_length= MYSQL_SCHEMA_NAME.length; - if (!(table= open_performance_schema_table(thd, & table_list, - & open_tables_backup))) + if (!(table= open_log_table(thd, &table_list, &open_tables_backup))) goto err; need_close= TRUE; @@ -694,7 +765,7 @@ err: table->file->ha_release_auto_increment(); } if (need_close) - close_performance_schema_table(thd, & open_tables_backup); + close_log_table(thd, &open_tables_backup); thd->time_zone_used= save_time_zone_used; DBUG_RETURN(result); } @@ -728,12 +799,11 @@ int Log_to_csv_event_handler:: table_list.db= MYSQL_SCHEMA_NAME.str; table_list.db_length= MYSQL_SCHEMA_NAME.length; - table= open_performance_schema_table(thd, & table_list, - & open_tables_backup); + table= open_log_table(thd, &table_list, &open_tables_backup); if (table) { result= 0; - close_performance_schema_table(thd, & open_tables_backup); + close_log_table(thd, &open_tables_backup); } else result= 1; @@ -809,10 +879,10 @@ bool Log_to_file_event_handler::init() if (!is_initialized) { if (opt_slow_log) - mysql_slow_log.open_slow_log(sys_var_slow_log_path.value); + mysql_slow_log.open_slow_log(opt_slow_logname); if (opt_log) - mysql_log.open_query_log(sys_var_general_log_path.value); + mysql_log.open_query_log(opt_logname); is_initialized= TRUE; } @@ -869,7 +939,7 @@ bool LOGGER::error_log_print(enum loglevel level, const char *format, void LOGGER::cleanup_base() { DBUG_ASSERT(inited == 1); - rwlock_destroy(&LOCK_logger); + mysql_rwlock_destroy(&LOCK_logger); if (table_log_handler) { table_log_handler->cleanup(); @@ -914,7 +984,7 @@ void LOGGER::init_base() init_error_log(LOG_FILE); file_log_handler->init_pthread_objects(); - my_rwlock_init(&LOCK_logger, NULL); + mysql_rwlock_init(key_rwlock_LOCK_logger, &LOCK_logger); } @@ -948,6 +1018,54 @@ bool LOGGER::flush_logs(THD *thd) } +/** + Close and reopen the slow log (with locks). + + @returns FALSE. +*/ +bool LOGGER::flush_slow_log() +{ + /* + Now we lock logger, as nobody should be able to use logging routines while + log tables are closed + */ + logger.lock_exclusive(); + + /* Reopen slow log file */ + if (opt_slow_log) + file_log_handler->get_mysql_slow_log()->reopen_file(); + + /* End of log flush */ + logger.unlock(); + + return 0; +} + + +/** + Close and reopen the general log (with locks). + + @returns FALSE. +*/ +bool LOGGER::flush_general_log() +{ + /* + Now we lock logger, as nobody should be able to use logging routines while + log tables are closed + */ + logger.lock_exclusive(); + + /* Reopen general log file */ + if (opt_log) + file_log_handler->get_mysql_log()->reopen_file(); + + /* End of log flush */ + logger.unlock(); + + return 0; +} + + /* Log slow query with all enabled log event handlers @@ -1039,7 +1157,6 @@ bool LOGGER::general_log_write(THD *thd, enum enum_server_command command, bool error= FALSE; Log_event_handler **current_handler= general_log_handler_list; char user_host_buff[MAX_USER_HOST_SIZE + 1]; - Security_context *sctx= thd->security_ctx; uint user_host_len= 0; time_t current_time; @@ -1051,14 +1168,16 @@ bool LOGGER::general_log_write(THD *thd, enum enum_server_command command, unlock(); return 0; } - user_host_len= strxnmov(user_host_buff, MAX_USER_HOST_SIZE, - sctx->priv_user ? sctx->priv_user : "", "[", - sctx->user ? sctx->user : "", "] @ ", - sctx->host ? sctx->host : "", " [", - sctx->ip ? sctx->ip : "", "]", NullS) - - user_host_buff; + user_host_len= make_user_name(thd, user_host_buff); current_time= my_time(0); + + mysql_audit_general_log(thd, current_time, + user_host_buff, user_host_len, + command_name[(uint) command].str, + command_name[(uint) command].length, + query, query_length); + while (*current_handler) error|= (*current_handler++)-> log_general(thd, current_time, user_host_buff, @@ -1173,7 +1292,7 @@ bool LOGGER::activate_log_handler(THD* thd, uint log_type) { file_log= file_log_handler->get_mysql_slow_log(); - file_log->open_slow_log(sys_var_slow_log_path.value); + file_log->open_slow_log(opt_slow_logname); if (table_log_handler->activate_log(thd, QUERY_LOG_SLOW)) { /* Error printed by open table in activate_log() */ @@ -1192,7 +1311,7 @@ bool LOGGER::activate_log_handler(THD* thd, uint log_type) { file_log= file_log_handler->get_mysql_log(); - file_log->open_query_log(sys_var_general_log_path.value); + file_log->open_query_log(opt_logname); if (table_log_handler->activate_log(thd, QUERY_LOG_GENERAL)) { /* Error printed by open table in activate_log() */ @@ -1276,26 +1395,6 @@ int LOGGER::set_handlers(uint error_log_printer, return 0; } -/** - This function checks if a transactional talbe was updated by the - current statement. - - @param thd The client thread that executed the current statement. - @return - @c true if a transactional table was updated, @false otherwise. -*/ -static bool stmt_has_updated_trans_table(THD *thd) -{ - Ha_trx_info *ha_info; - - for (ha_info= thd->transaction.stmt.ha_list; ha_info && ha_info->is_started(); ha_info= ha_info->next()) - { - if (ha_info->is_trx_read_write() && ha_info->ht() != binlog_hton) - return (TRUE); - } - return (FALSE); -} - /* Save position of binary log transaction cache. @@ -1318,10 +1417,10 @@ binlog_trans_log_savepos(THD *thd, my_off_t *pos) DBUG_ASSERT(pos != NULL); if (thd_get_ha_data(thd, binlog_hton) == NULL) thd->binlog_setup_trx_data(); - binlog_trx_data *const trx_data= - (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton); + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); DBUG_ASSERT(mysql_bin_log.is_open()); - *pos= trx_data->position(); + *pos= cache_mngr->trx_cache.get_byte_position(); DBUG_PRINT("return", ("*pos: %lu", (ulong) *pos)); DBUG_VOID_RETURN; } @@ -1352,9 +1451,9 @@ binlog_trans_log_truncate(THD *thd, my_off_t pos) /* Only true if binlog_trans_log_savepos() wasn't called before */ DBUG_ASSERT(pos != ~(my_off_t) 0); - binlog_trx_data *const trx_data= - (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton); - trx_data->truncate(pos); + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + cache_mngr->trx_cache.restore_savepoint(pos); DBUG_VOID_RETURN; } @@ -1383,115 +1482,127 @@ int binlog_init(void *p) static int binlog_close_connection(handlerton *hton, THD *thd) { - binlog_trx_data *const trx_data= - (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton); - DBUG_ASSERT(trx_data->empty()); + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + DBUG_ASSERT(cache_mngr->trx_cache.empty() && cache_mngr->stmt_cache.empty()); thd_set_ha_data(thd, binlog_hton, NULL); - trx_data->~binlog_trx_data(); - my_free((uchar*)trx_data, MYF(0)); + cache_mngr->~binlog_cache_mngr(); + my_free((uchar*)cache_mngr, MYF(0)); return 0; } -/* - End a transaction. +/** + This function flushes a transactional cache upon commit/rollback. - SYNOPSIS - binlog_end_trans() + @param thd The thread whose transaction should be flushed + @param cache_mngr Pointer to the cache data to be flushed + @param end_ev The end event either commit/rollback. + + @return + nonzero if an error pops up when flushing the transactional cache. +*/ +static int +binlog_flush_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr, + Log_event *end_ev) +{ + DBUG_ENTER("binlog_flush_trx_cache"); + int error=0; + IO_CACHE *cache_log= &cache_mngr->trx_cache.cache_log; - thd The thread whose transaction should be ended - trx_data Pointer to the transaction data to use - end_ev The end event to use, or NULL - all True if the entire transaction should be ended, false if - only the statement transaction should be ended. + /* + This function handles transactional changes and as such + this flag equals to true. + */ + bool const is_transactional= TRUE; - DESCRIPTION + if (thd->binlog_flush_pending_rows_event(TRUE, is_transactional)) + DBUG_RETURN(1); + /* + Doing a commit or a rollback including non-transactional tables, + i.e., ending a transaction where we might write the transaction + cache to the binary log. + + We can always end the statement when ending a transaction since + transactions are not allowed inside stored functions. If they + were, we would have to ensure that we're not ending a statement + inside a stored function. + */ + error= mysql_bin_log.write(thd, &cache_mngr->trx_cache.cache_log, end_ev, + cache_mngr->trx_cache.has_incident()); + cache_mngr->reset_cache(&cache_mngr->trx_cache); - End the currently open transaction. The transaction can be either - a real transaction (if 'all' is true) or a statement transaction - (if 'all' is false). + /* + We need to step the table map version after writing the + transaction cache to disk. + */ + mysql_bin_log.update_table_map_version(); + statistic_increment(binlog_cache_use, &LOCK_status); + if (cache_log->disk_writes != 0) + { + statistic_increment(binlog_cache_disk_use, &LOCK_status); + cache_log->disk_writes= 0; + } - If 'end_ev' is NULL, the transaction is a rollback of only - transactional tables, so the transaction cache will be truncated - to either just before the last opened statement transaction (if - 'all' is false), or reset completely (if 'all' is true). - */ + DBUG_ASSERT(cache_mngr->trx_cache.empty()); + DBUG_RETURN(error); +} + +/** + This function truncates the transactional cache upon committing or rolling + back either a transaction or a statement. + + @param thd The thread whose transaction should be flushed + @param cache_mngr Pointer to the cache data to be flushed + @param all @c true means truncate the transaction, otherwise the + statement must be truncated. + + @return + nonzero if an error pops up when truncating the transactional cache. +*/ static int -binlog_end_trans(THD *thd, binlog_trx_data *trx_data, - Log_event *end_ev, bool all) +binlog_truncate_trx_cache(THD *thd, binlog_cache_mngr *cache_mngr, bool all) { - DBUG_ENTER("binlog_end_trans"); + DBUG_ENTER("binlog_truncate_trx_cache"); int error=0; - IO_CACHE *trans_log= &trx_data->trans_log; - DBUG_PRINT("enter", ("transaction: %s end_ev: 0x%lx", - all ? "all" : "stmt", (long) end_ev)); - DBUG_PRINT("info", ("thd->options={ %s%s}", - FLAGSTR(thd->options, OPTION_NOT_AUTOCOMMIT), - FLAGSTR(thd->options, OPTION_BEGIN))); + /* + This function handles transactional changes and as such this flag + equals to true. + */ + bool const is_transactional= TRUE; + DBUG_PRINT("info", ("thd->options={ %s%s}, transaction: %s", + FLAGSTR(thd->variables.option_bits, OPTION_NOT_AUTOCOMMIT), + FLAGSTR(thd->variables.option_bits, OPTION_BEGIN), + all ? "all" : "stmt")); /* - NULL denotes ROLLBACK with nothing to replicate: i.e., rollback of - only transactional tables. If the transaction contain changes to - any non-transactiona tables, we need write the transaction and log - a ROLLBACK last. + If rolling back an entire transaction or a single statement not + inside a transaction, we reset the transaction cache. */ - if (end_ev != NULL) + thd->binlog_remove_pending_rows_event(TRUE, is_transactional); + if (all || !thd->in_multi_stmt_transaction()) { - if (thd->binlog_flush_pending_rows_event(TRUE)) - DBUG_RETURN(1); - /* - Doing a commit or a rollback including non-transactional tables, - i.e., ending a transaction where we might write the transaction - cache to the binary log. - - We can always end the statement when ending a transaction since - transactions are not allowed inside stored functions. If they - were, we would have to ensure that we're not ending a statement - inside a stored function. - */ - error= mysql_bin_log.write(thd, &trx_data->trans_log, end_ev, - trx_data->has_incident()); - trx_data->reset(); + if (cache_mngr->trx_cache.has_incident()) + error= mysql_bin_log.write_incident(thd, TRUE); - /* - We need to step the table map version after writing the - transaction cache to disk. - */ - mysql_bin_log.update_table_map_version(); - statistic_increment(binlog_cache_use, &LOCK_status); - if (trans_log->disk_writes != 0) - { - statistic_increment(binlog_cache_disk_use, &LOCK_status); - trans_log->disk_writes= 0; - } + cache_mngr->reset_cache(&cache_mngr->trx_cache); + + thd->clear_binlog_table_maps(); } + /* + If rolling back a statement in a transaction, we truncate the + transaction cache to remove the statement. + */ else - { - /* - If rolling back an entire transaction or a single statement not - inside a transaction, we reset the transaction cache. - - If rolling back a statement in a transaction, we truncate the - transaction cache to remove the statement. - */ - thd->binlog_remove_pending_rows_event(TRUE); - if (all || !(thd->options & (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT))) - { - if (trx_data->has_incident()) - error= mysql_bin_log.write_incident(thd, TRUE); - trx_data->reset(); - } - else // ...statement - trx_data->truncate(trx_data->before_stmt_pos); + cache_mngr->trx_cache.restore_prev_position(); - /* - We need to step the table map version on a rollback to ensure - that a new table map event is generated instead of the one that - was written to the thrown-away transaction cache. - */ - mysql_bin_log.update_table_map_version(); - } + /* + We need to step the table map version on a rollback to ensure that a new + table map event is generated instead of the one that was written to the + thrown-away transaction cache. + */ + mysql_bin_log.update_table_map_version(); - DBUG_ASSERT(thd->binlog_get_pending_rows_event() == NULL); + DBUG_ASSERT(thd->binlog_get_pending_rows_event(is_transactional) == NULL); DBUG_RETURN(error); } @@ -1507,10 +1618,56 @@ static int binlog_prepare(handlerton *hton, THD *thd, bool all) } /** + This function flushes the non-transactional to the binary log upon + committing or rolling back a statement. + + @param thd The thread whose transaction should be flushed + @param cache_mngr Pointer to the cache data to be flushed + + @return + nonzero if an error pops up when flushing the non-transactional cache. +*/ +static int +binlog_flush_stmt_cache(THD *thd, binlog_cache_mngr *cache_mngr) +{ + int error= 0; + DBUG_ENTER("binlog_flush_stmt_cache"); + /* + If we are flushing the statement cache, it means that the changes get + through otherwise the cache is empty and this routine should not be called. + */ + DBUG_ASSERT(cache_mngr->stmt_cache.has_incident() == FALSE); + /* + This function handles non-transactional changes and as such this flag equals + to false. + */ + bool const is_transactional= FALSE; + IO_CACHE *cache_log= &cache_mngr->stmt_cache.cache_log; + thd->binlog_flush_pending_rows_event(TRUE, is_transactional); + Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE, TRUE, 0); + if ((error= mysql_bin_log.write(thd, cache_log, &qev, + cache_mngr->stmt_cache.has_incident()))) + DBUG_RETURN(error); + cache_mngr->reset_cache(&cache_mngr->stmt_cache); + + /* + We need to step the table map version after writing the + transaction cache to disk. + */ + mysql_bin_log.update_table_map_version(); + statistic_increment(binlog_cache_use, &LOCK_status); + if (cache_log->disk_writes != 0) + { + statistic_increment(binlog_cache_disk_use, &LOCK_status); + cache_log->disk_writes= 0; + } + DBUG_RETURN(error); +} + +/** This function is called once after each statement. - It has the responsibility to flush the transaction cache to the - binlog file on commits. + It has the responsibility to flush the caches to the binary log on commits. @param hton The binlog handlerton. @param thd The client thread that executes the transaction. @@ -1523,57 +1680,53 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all) { int error= 0; DBUG_ENTER("binlog_commit"); - binlog_trx_data *const trx_data= - (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton); + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + bool const in_transaction= thd->in_multi_stmt_transaction(); + + DBUG_PRINT("debug", + ("all: %d, in_transaction: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s", + all, + YESNO(in_transaction), + YESNO(thd->transaction.all.modified_non_trans_table), + YESNO(thd->transaction.stmt.modified_non_trans_table))); - if (trx_data->empty()) + if (!cache_mngr->stmt_cache.empty()) { - // we're here because trans_log was flushed in MYSQL_BIN_LOG::log_xid() - trx_data->reset(); + binlog_flush_stmt_cache(thd, cache_mngr); + } + + if (cache_mngr->trx_cache.empty()) + { + /* + we're here because cache_log was flushed in MYSQL_BIN_LOG::log_xid() + */ + cache_mngr->reset_cache(&cache_mngr->trx_cache); DBUG_RETURN(0); } /* We commit the transaction if: - - We are not in a transaction and committing a statement, or - - - We are in a transaction and a full transaction is committed - - Otherwise, we accumulate the statement + - We are in a transaction and a full transaction is committed. + Otherwise, we accumulate the changes. */ - ulonglong const in_transaction= - thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN); - DBUG_PRINT("debug", - ("all: %d, empty: %s, in_transaction: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s", - all, - YESNO(trx_data->empty()), - YESNO(in_transaction), - YESNO(thd->transaction.all.modified_non_trans_table), - YESNO(thd->transaction.stmt.modified_non_trans_table))); - if (!in_transaction || all || - (!all && !trx_data->at_least_one_stmt_committed && - !stmt_has_updated_trans_table(thd) && - thd->transaction.stmt.modified_non_trans_table)) + if (!in_transaction || all) { - Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, TRUE, 0); - error= binlog_end_trans(thd, trx_data, &qev, all); + Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE, TRUE, 0); + error= binlog_flush_trx_cache(thd, cache_mngr, &qev); } - trx_data->at_least_one_stmt_committed = my_b_tell(&trx_data->trans_log) > 0; - + /* + This is part of the stmt rollback. + */ if (!all) - trx_data->before_stmt_pos = MY_OFF_T_UNDEF; // part of the stmt commit + cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF); DBUG_RETURN(error); } /** - This function is called when a transaction involving a transactional - table is rolled back. - - It has the responsibility to flush the transaction cache to the - binlog file. However, if the transaction does not involve - non-transactional tables, nothing needs to be logged. + This function is called when a transaction or a statement is rolled back. @param hton The binlog handlerton. @param thd The client thread that executes the transaction. @@ -1586,18 +1739,37 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) { DBUG_ENTER("binlog_rollback"); int error=0; - binlog_trx_data *const trx_data= - (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton); - - if (trx_data->empty()) { - trx_data->reset(); - DBUG_RETURN(0); - } + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); DBUG_PRINT("debug", ("all: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s", YESNO(all), YESNO(thd->transaction.all.modified_non_trans_table), YESNO(thd->transaction.stmt.modified_non_trans_table))); + + /* + If an incident event is set we do not flush the content of the statement + cache because it may be corrupted. + */ + if (cache_mngr->stmt_cache.has_incident()) + { + error= mysql_bin_log.write_incident(thd, TRUE); + cache_mngr->reset_cache(&cache_mngr->stmt_cache); + } + else if (!cache_mngr->stmt_cache.empty()) + { + binlog_flush_stmt_cache(thd, cache_mngr); + } + + if (cache_mngr->trx_cache.empty()) + { + /* + we're here because cache_log was flushed in MYSQL_BIN_LOG::log_xid() + */ + cache_mngr->reset_cache(&cache_mngr->trx_cache); + DBUG_RETURN(0); + } + if (mysql_bin_log.check_write_error(thd)) { /* @@ -1608,52 +1780,46 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) */ DBUG_ASSERT(!all); /* - We reach this point if either only transactional tables were modified or - the effect of a statement that did not get into the binlog needs to be - rolled back. In the latter case, if a statement changed non-transactional - tables or had the OPTION_KEEP_LOG associated, we write an incident event - to the binlog in order to stop slaves and notify users that some changes - on the master did not get into the binlog and slaves will be inconsistent. - On the other hand, if a statement is transactional, we just safely roll it - back. + We reach this point if the effect of a statement did not properly get into + a cache and need to be rolled back. */ - if ((thd->transaction.stmt.modified_non_trans_table || - (thd->options & OPTION_KEEP_LOG)) && - mysql_bin_log.check_write_error(thd)) - trx_data->set_incident(); - error= binlog_end_trans(thd, trx_data, 0, all); + error= binlog_truncate_trx_cache(thd, cache_mngr, all); } else - { - /* - We flush the cache with a rollback, wrapped in a beging/rollback if: - . aborting a transaction that modified a non-transactional table; + { + /* + We flush the cache wrapped in a beging/rollback if: + . aborting a transcation that modified a non-transactional table or; . aborting a statement that modified both transactional and - non-transactional tables but which is not in the boundaries of any - transaction or there was no early change; + non-transctional tables but which is not in the boundaries of any + transaction; . the OPTION_KEEP_LOG is activate. */ - if ((all && thd->transaction.all.modified_non_trans_table) || - (!all && thd->transaction.stmt.modified_non_trans_table && - !(thd->options & (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT))) || + if (thd->variables.binlog_format == BINLOG_FORMAT_STMT && + ((all && thd->transaction.all.modified_non_trans_table) || (!all && thd->transaction.stmt.modified_non_trans_table && - !trx_data->at_least_one_stmt_committed && - thd->current_stmt_binlog_row_based) || - ((thd->options & OPTION_KEEP_LOG))) + !thd->in_multi_stmt_transaction()) || + (thd->variables.option_bits & OPTION_KEEP_LOG))) { - Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, TRUE, 0); - error= binlog_end_trans(thd, trx_data, &qev, all); + Query_log_event qev(thd, STRING_WITH_LEN("ROLLBACK"), TRUE, FALSE, TRUE, 0); + error= binlog_flush_trx_cache(thd, cache_mngr, &qev); } /* Otherwise, we simply truncate the cache as there is no change on non-transactional tables as follows. */ - else if ((all && !thd->transaction.all.modified_non_trans_table) || - (!all && !thd->transaction.stmt.modified_non_trans_table)) - error= binlog_end_trans(thd, trx_data, 0, all); + else if (all || (!all && + (!thd->transaction.stmt.modified_non_trans_table || + !thd->in_multi_stmt_transaction() || + thd->variables.binlog_format != BINLOG_FORMAT_STMT))) + error= binlog_truncate_trx_cache(thd, cache_mngr, all); } + + /* + This is part of the stmt rollback. + */ if (!all) - trx_data->before_stmt_pos = MY_OFF_T_UNDEF; // part of the stmt rollback + cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF); DBUG_RETURN(error); } @@ -1729,7 +1895,8 @@ static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv) int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); int const error= thd->binlog_query(THD::STMT_QUERY_TYPE, - thd->query(), thd->query_length(), TRUE, FALSE, errcode); + thd->query(), thd->query_length(), TRUE, FALSE, FALSE, + errcode); DBUG_RETURN(error); } @@ -1742,13 +1909,14 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv) non-transactional table. Otherwise, truncate the binlog cache starting from the SAVEPOINT command. */ - if (unlikely(thd->transaction.all.modified_non_trans_table || - (thd->options & OPTION_KEEP_LOG))) + if (unlikely(thd->transaction.all.modified_non_trans_table || + (thd->variables.option_bits & OPTION_KEEP_LOG))) { int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); int error= thd->binlog_query(THD::STMT_QUERY_TYPE, - thd->query(), thd->query_length(), TRUE, FALSE, errcode); + thd->query(), thd->query_length(), TRUE, FALSE, FALSE, + errcode); DBUG_RETURN(error); } binlog_trans_log_truncate(thd, *(my_off_t*)sv); @@ -1782,8 +1950,9 @@ File open_binlog(IO_CACHE *log, const char *log_file_name, const char **errmsg) File file; DBUG_ENTER("open_binlog"); - if ((file = my_open(log_file_name, O_RDONLY | O_BINARY | O_SHARE, - MYF(MY_WME))) < 0) + if ((file= mysql_file_open(key_file_binlog, + log_file_name, O_RDONLY | O_BINARY | O_SHARE, + MYF(MY_WME))) < 0) { sql_print_error("Failed to open log (file '%s', errno %d)", log_file_name, my_errno); @@ -1805,7 +1974,7 @@ File open_binlog(IO_CACHE *log, const char *log_file_name, const char **errmsg) err: if (file >= 0) { - my_close(file,MYF(0)); + mysql_file_close(file, MYF(0)); end_io_cache(log); } DBUG_RETURN(-1); @@ -1852,22 +2021,27 @@ static void setup_windows_event_source() /** Find a unique filename for 'filename.#'. - Set '#' to a number as low as possible. + Set '#' to the number next to the maximum found in the most + recent log file extension. + + This function will return nonzero if: (i) the generated name + exceeds FN_REFLEN; (ii) if the number of extensions is exhausted; + or (iii) some other error happened while examining the filesystem. @return - nonzero if not possible to get unique filename + nonzero if not possible to get unique filename. */ static int find_uniq_filename(char *name) { - long number; uint i; - char buff[FN_REFLEN]; + char buff[FN_REFLEN], ext_buf[FN_REFLEN]; struct st_my_dir *dir_info; reg1 struct fileinfo *file_info; - ulong max_found=0; + ulong max_found= 0, next= 0, number= 0; size_t buf_length, length; char *start, *end; + int error= 0; DBUG_ENTER("find_uniq_filename"); length= dirname_part(buff, name, &buf_length); @@ -1875,15 +2049,15 @@ static int find_uniq_filename(char *name) end= strend(start); *end='.'; - length= (size_t) (end-start+1); + length= (size_t) (end - start + 1); - if (!(dir_info = my_dir(buff,MYF(MY_DONT_SORT)))) + if (!(dir_info= my_dir(buff,MYF(MY_DONT_SORT)))) { // This shouldn't happen strmov(end,".1"); // use name+1 - DBUG_RETURN(0); + DBUG_RETURN(1); } file_info= dir_info->dir_entry; - for (i=dir_info->number_off_files ; i-- ; file_info++) + for (i= dir_info->number_off_files ; i-- ; file_info++) { if (bcmp((uchar*) file_info->name, (uchar*) start, length) == 0 && test_if_number(file_info->name+length, &number,0)) @@ -1893,9 +2067,44 @@ static int find_uniq_filename(char *name) } my_dirend(dir_info); + /* check if reached the maximum possible extension number */ + if ((max_found == MAX_LOG_UNIQUE_FN_EXT)) + { + sql_print_error("Log filename extension number exhausted: %06lu. \ +Please fix this by archiving old logs and \ +updating the index files.", max_found); + error= 1; + goto end; + } + + next= max_found + 1; + sprintf(ext_buf, "%06lu", next); *end++='.'; - sprintf(end,"%06ld",max_found+1); - DBUG_RETURN(0); + + /* + Check if the generated extension size + the file name exceeds the + buffer size used. If one did not check this, then the filename might be + truncated, resulting in error. + */ + if (((strlen(ext_buf) + (end - name)) >= FN_REFLEN)) + { + sql_print_error("Log filename too large: %s%s (%zu). \ +Please fix this by archiving old logs and updating the \ +index files.", name, ext_buf, (strlen(ext_buf) + (end - name))); + error= 1; + goto end; + } + + sprintf(end, "%06lu", next); + + /* print warning if reaching the end of available extensions. */ + if ((next > (MAX_LOG_UNIQUE_FN_EXT - LOG_WARN_UNIQUE_FN_EXT_LEFT))) + sql_print_warning("Next log extension: %lu. \ +Remaining log filename extensions: %lu. \ +Please consider archiving some logs.", next, (MAX_LOG_UNIQUE_FN_EXT - next)); + +end: + DBUG_RETURN(error); } @@ -1975,10 +2184,11 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg, db[0]= 0; - if ((file= my_open(log_file_name, open_flags, - MYF(MY_WME | ME_WAITTANG))) < 0 || + if ((file= mysql_file_open(key_file_MYSQL_LOG, + log_file_name, open_flags, + MYF(MY_WME | ME_WAITTANG))) < 0 || init_io_cache(&log_file, file, IO_SIZE, io_cache_type, - my_tell(file, MYF(MY_WME)), 0, + mysql_file_tell(file, MYF(MY_WME)), 0, MYF(MY_WME | MY_NABP | ((log_type == LOG_BIN) ? MY_WAIT_IF_FULL : 0)))) goto err; @@ -2016,7 +2226,7 @@ Turning logging off for the whole duration of the MySQL server process. \ To turn it on again: fix the cause, \ shutdown the MySQL server and restart it.", name, errno); if (file >= 0) - my_close(file, MYF(0)); + mysql_file_close(file, MYF(0)); end_io_cache(&log_file); safeFree(name); log_state= LOG_CLOSED; @@ -2040,7 +2250,7 @@ void MYSQL_LOG::init_pthread_objects() { DBUG_ASSERT(inited == 0); inited= 1; - (void) pthread_mutex_init(&LOCK_log, MY_MUTEX_INIT_SLOW); + mysql_mutex_init(key_LOG_LOCK_log, &LOCK_log, MY_MUTEX_INIT_SLOW); } /* @@ -2065,13 +2275,13 @@ void MYSQL_LOG::close(uint exiting) { end_io_cache(&log_file); - if (my_sync(log_file.file, MYF(MY_WME)) && ! write_error) + if (mysql_file_sync(log_file.file, MYF(MY_WME)) && ! write_error) { write_error= 1; sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); } - if (my_close(log_file.file, MYF(MY_WME)) && ! write_error) + if (mysql_file_close(log_file.file, MYF(MY_WME)) && ! write_error) { write_error= 1; sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); @@ -2091,7 +2301,7 @@ void MYSQL_LOG::cleanup() if (inited) { inited= 0; - (void) pthread_mutex_destroy(&LOCK_log); + mysql_mutex_destroy(&LOCK_log); close(0); } DBUG_VOID_RETURN; @@ -2107,6 +2317,13 @@ int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name) { if (find_uniq_filename(new_name)) { + /* + This should be treated as error once propagation of error further + up in the stack gets proper handling. + */ + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_NO_UNIQUE_LOGFILE, ER(ER_NO_UNIQUE_LOGFILE), + log_name); sql_print_error(ER(ER_NO_UNIQUE_LOGFILE), log_name); return 1; } @@ -2139,7 +2356,7 @@ void MYSQL_QUERY_LOG::reopen_file() DBUG_VOID_RETURN; } - pthread_mutex_lock(&LOCK_log); + mysql_mutex_lock(&LOCK_log); save_name= name; name= 0; // Don't free name @@ -2152,7 +2369,7 @@ void MYSQL_QUERY_LOG::reopen_file() open(save_name, log_type, 0, io_cache_type); my_free(save_name, MYF(0)); - pthread_mutex_unlock(&LOCK_log); + mysql_mutex_unlock(&LOCK_log); DBUG_VOID_RETURN; } @@ -2194,7 +2411,7 @@ bool MYSQL_QUERY_LOG::write(time_t event_time, const char *user_host, struct tm start; uint time_buff_len= 0; - (void) pthread_mutex_lock(&LOCK_log); + mysql_mutex_lock(&LOCK_log); /* Test if someone closed between the is_open test and lock */ if (is_open()) @@ -2243,7 +2460,7 @@ bool MYSQL_QUERY_LOG::write(time_t event_time, const char *user_host, goto err; } - (void) pthread_mutex_unlock(&LOCK_log); + mysql_mutex_unlock(&LOCK_log); return FALSE; err: @@ -2252,7 +2469,7 @@ err: write_error= 1; sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); } - (void) pthread_mutex_unlock(&LOCK_log); + mysql_mutex_unlock(&LOCK_log); return TRUE; } @@ -2295,11 +2512,11 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, bool error= 0; DBUG_ENTER("MYSQL_QUERY_LOG::write"); - (void) pthread_mutex_lock(&LOCK_log); + mysql_mutex_lock(&LOCK_log); if (!is_open()) { - (void) pthread_mutex_unlock(&LOCK_log); + mysql_mutex_unlock(&LOCK_log); DBUG_RETURN(0); } @@ -2408,7 +2625,7 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, } } } - (void) pthread_mutex_unlock(&LOCK_log); + mysql_mutex_unlock(&LOCK_log); DBUG_RETURN(error); } @@ -2470,9 +2687,9 @@ void MYSQL_BIN_LOG::cleanup() close(LOG_CLOSE_INDEX|LOG_CLOSE_STOP_EVENT); delete description_event_for_queue; delete description_event_for_exec; - (void) pthread_mutex_destroy(&LOCK_log); - (void) pthread_mutex_destroy(&LOCK_index); - (void) pthread_cond_destroy(&update_cond); + mysql_mutex_destroy(&LOCK_log); + mysql_mutex_destroy(&LOCK_index); + mysql_cond_destroy(&update_cond); } DBUG_VOID_RETURN; } @@ -2493,9 +2710,9 @@ void MYSQL_BIN_LOG::init_pthread_objects() { DBUG_ASSERT(inited == 0); inited= 1; - (void) pthread_mutex_init(&LOCK_log, MY_MUTEX_INIT_SLOW); - (void) pthread_mutex_init(&LOCK_index, MY_MUTEX_INIT_SLOW); - (void) pthread_cond_init(&update_cond, 0); + mysql_mutex_init(key_LOG_LOCK_log, &LOCK_log, MY_MUTEX_INIT_SLOW); + mysql_mutex_init(key_BINLOG_LOCK_index, &LOCK_index, MY_MUTEX_INIT_SLOW); + mysql_cond_init(key_BINLOG_update_cond, &update_cond, 0); } @@ -2518,23 +2735,25 @@ bool MYSQL_BIN_LOG::open_index_file(const char *index_file_name_arg, } fn_format(index_file_name, index_file_name_arg, mysql_data_home, ".index", opt); - if ((index_file_nr= my_open(index_file_name, - O_RDWR | O_CREAT | O_BINARY , - MYF(MY_WME))) < 0 || - my_sync(index_file_nr, MYF(MY_WME)) || + if ((index_file_nr= mysql_file_open(key_file_binlog_index, + index_file_name, + O_RDWR | O_CREAT | O_BINARY, + MYF(MY_WME))) < 0 || + mysql_file_sync(index_file_nr, MYF(MY_WME)) || init_io_cache(&index_file, index_file_nr, IO_SIZE, WRITE_CACHE, - my_seek(index_file_nr,0L,MY_SEEK_END,MYF(0)), - 0, MYF(MY_WME | MY_WAIT_IF_FULL)) || + mysql_file_seek(index_file_nr, 0L, MY_SEEK_END, MYF(0)), + 0, MYF(MY_WME | MY_WAIT_IF_FULL)) || DBUG_EVALUATE_IF("fault_injection_openning_index", 1, 0)) { /* TODO: all operations creating/deleting the index file or a log, should call my_sync_dir() or my_sync_dir_by_file() to be durable. - TODO: file creation should be done with my_create() not my_open(). + TODO: file creation should be done with mysql_file_create() + not mysql_file_open(). */ if (index_file_nr >= 0) - my_close(index_file_nr,MYF(0)); + mysql_file_close(index_file_nr, MYF(0)); return TRUE; } @@ -2698,7 +2917,7 @@ bool MYSQL_BIN_LOG::open(const char *log_name, bytes_written+= description_event_for_queue->data_written; } if (flush_io_cache(&log_file) || - my_sync(log_file.file, MYF(MY_WME))) + mysql_file_sync(log_file.file, MYF(MY_WME))) goto err; if (write_file_name_to_index_file) @@ -2719,7 +2938,7 @@ bool MYSQL_BIN_LOG::open(const char *log_name, strlen(log_file_name)) || my_b_write(&index_file, (uchar*) "\n", 1) || flush_io_cache(&index_file) || - my_sync(index_file.file, MYF(MY_WME))) + mysql_file_sync(index_file.file, MYF(MY_WME))) goto err; #ifdef HAVE_REPLICATION @@ -2746,7 +2965,7 @@ Turning logging off for the whole duration of the MySQL server process. \ To turn it on again: fix the cause, \ shutdown the MySQL server and restart it.", name, errno); if (file >= 0) - my_close(file,MYF(0)); + mysql_file_close(file, MYF(0)); end_io_cache(&log_file); end_io_cache(&index_file); safeFree(name); @@ -2757,9 +2976,9 @@ shutdown the MySQL server and restart it.", name, errno); int MYSQL_BIN_LOG::get_current_log(LOG_INFO* linfo) { - pthread_mutex_lock(&LOCK_log); + mysql_mutex_lock(&LOCK_log); int ret = raw_get_current_log(linfo); - pthread_mutex_unlock(&LOCK_log); + mysql_mutex_unlock(&LOCK_log); return ret; } @@ -2799,19 +3018,20 @@ static bool copy_up_file_and_fill(IO_CACHE *index_file, my_off_t offset) for (;; offset+= bytes_read) { - (void) my_seek(file, offset, MY_SEEK_SET, MYF(0)); - if ((bytes_read= (int) my_read(file, io_buf, sizeof(io_buf), MYF(MY_WME))) + mysql_file_seek(file, offset, MY_SEEK_SET, MYF(0)); + if ((bytes_read= (int) mysql_file_read(file, io_buf, sizeof(io_buf), + MYF(MY_WME))) < 0) goto err; if (!bytes_read) break; // end of file - (void) my_seek(file, offset-init_offset, MY_SEEK_SET, MYF(0)); - if (my_write(file, io_buf, bytes_read, MYF(MY_WME | MY_NABP))) + mysql_file_seek(file, offset-init_offset, MY_SEEK_SET, MYF(0)); + if (mysql_file_write(file, io_buf, bytes_read, MYF(MY_WME | MY_NABP))) goto err; } /* The following will either truncate the file or fill the end with \n' */ - if (my_chsize(file, offset - init_offset, '\n', MYF(MY_WME)) || - my_sync(file, MYF(MY_WME))) + if (mysql_file_chsize(file, offset - init_offset, '\n', MYF(MY_WME)) || + mysql_file_sync(file, MYF(MY_WME))) goto err; /* Reset data in old index cache */ @@ -2860,8 +3080,8 @@ int MYSQL_BIN_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name, move from under our feet */ if (need_lock) - pthread_mutex_lock(&LOCK_index); - safe_mutex_assert_owner(&LOCK_index); + mysql_mutex_lock(&LOCK_index); + mysql_mutex_assert_owner(&LOCK_index); /* As the file is flushed, we can't get an error here */ (void) reinit_io_cache(&index_file, READ_CACHE, (my_off_t) 0, 0, 0); @@ -2870,8 +3090,10 @@ int MYSQL_BIN_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name, { uint length; my_off_t offset= my_b_tell(&index_file); - /* If we get 0 or 1 characters, this is the end of the file */ + DBUG_EXECUTE_IF("simulate_find_log_pos_error", + error= LOG_INFO_EOF; break;); + /* If we get 0 or 1 characters, this is the end of the file */ if ((length= my_b_gets(&index_file, fname, FN_REFLEN)) <= 1) { /* Did not find the given entry; Return not found or error */ @@ -2893,7 +3115,7 @@ int MYSQL_BIN_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name, } if (need_lock) - pthread_mutex_unlock(&LOCK_index); + mysql_mutex_unlock(&LOCK_index); DBUG_RETURN(error); } @@ -2929,8 +3151,8 @@ int MYSQL_BIN_LOG::find_next_log(LOG_INFO* linfo, bool need_lock) char *fname= linfo->log_file_name; if (need_lock) - pthread_mutex_lock(&LOCK_index); - safe_mutex_assert_owner(&LOCK_index); + mysql_mutex_lock(&LOCK_index); + mysql_mutex_assert_owner(&LOCK_index); /* As the file is flushed, we can't get an error here */ (void) reinit_io_cache(&index_file, READ_CACHE, linfo->index_file_offset, 0, @@ -2947,7 +3169,7 @@ int MYSQL_BIN_LOG::find_next_log(LOG_INFO* linfo, bool need_lock) err: if (need_lock) - pthread_mutex_unlock(&LOCK_index); + mysql_mutex_unlock(&LOCK_index); return error; } @@ -2973,6 +3195,7 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd) { LOG_INFO linfo; bool error=0; + int err; const char* save_name; DBUG_ENTER("reset_logs"); @@ -2981,8 +3204,8 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd) We need to get both locks to be sure that no one is trying to write to the index log file. */ - pthread_mutex_lock(&LOCK_log); - pthread_mutex_lock(&LOCK_index); + mysql_mutex_lock(&LOCK_log); + mysql_mutex_lock(&LOCK_index); /* The following mutex is needed to ensure that no threads call @@ -2990,7 +3213,7 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd) thread. If the transaction involved MyISAM tables, it should go into binlog even on rollback. */ - VOID(pthread_mutex_lock(&LOCK_thread_count)); + mysql_mutex_lock(&LOCK_thread_count); /* Save variables so that we can reopen the log */ save_name=name; @@ -3006,9 +3229,13 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd) We need to invert the steps and use the purge_index_file methods in order to make the operation safe. */ - if (find_log_pos(&linfo, NullS, 0)) + + if ((err= find_log_pos(&linfo, NullS, 0)) != 0) { - error=1; + uint errcode= purge_log_get_error_code(err); + sql_print_error("Failed to locate old binlog or relay log files"); + my_message(errcode, ER(errcode), MYF(0)); + error= 1; goto err; } @@ -3077,9 +3304,11 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd) my_free((uchar*) save_name, MYF(0)); err: - VOID(pthread_mutex_unlock(&LOCK_thread_count)); - pthread_mutex_unlock(&LOCK_index); - pthread_mutex_unlock(&LOCK_log); + if (error == 1) + name= const_cast<char*>(save_name); + mysql_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_index); + mysql_mutex_unlock(&LOCK_log); DBUG_RETURN(error); } @@ -3133,7 +3362,7 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included) DBUG_ASSERT(rli->slave_running == 1); DBUG_ASSERT(!strcmp(rli->linfo.log_file_name,rli->event_relay_log_name)); - pthread_mutex_lock(&LOCK_index); + mysql_mutex_lock(&LOCK_index); to_purge_if_included= my_strdup(rli->group_relay_log_name, MYF(0)); /* @@ -3177,19 +3406,19 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included) DBUG_EXECUTE_IF("crash_before_purge_logs", abort();); - pthread_mutex_lock(&rli->log_space_lock); + mysql_mutex_lock(&rli->log_space_lock); rli->relay_log.purge_logs(to_purge_if_included, included, 0, 0, &rli->log_space_total); // Tell the I/O thread to take the relay_log_space_limit into account rli->ignore_log_space_limit= 0; - pthread_mutex_unlock(&rli->log_space_lock); + mysql_mutex_unlock(&rli->log_space_lock); /* Ok to broadcast after the critical region as there is no risk of the mutex being destroyed by this thread later - this helps save context switches */ - pthread_cond_broadcast(&rli->log_space_cond); + mysql_cond_broadcast(&rli->log_space_cond); /* * Need to update the log pos because purge logs has been called @@ -3211,7 +3440,7 @@ int MYSQL_BIN_LOG::purge_first_log(Relay_log_info* rli, bool included) err: my_free(to_purge_if_included, MYF(0)); - pthread_mutex_unlock(&LOCK_index); + mysql_mutex_unlock(&LOCK_index); DBUG_RETURN(error); } @@ -3251,7 +3480,7 @@ int MYSQL_BIN_LOG::update_log_index(LOG_INFO* log_info, bool need_update_threads LOG_INFO_EOF to_log not found LOG_INFO_EMFILE too many files opened LOG_INFO_FATAL if any other than ENOENT error from - my_stat() or my_delete() + mysql_file_stat() or mysql_file_delete() */ int MYSQL_BIN_LOG::purge_logs(const char *to_log, @@ -3268,7 +3497,7 @@ int MYSQL_BIN_LOG::purge_logs(const char *to_log, DBUG_PRINT("info",("to_log= %s",to_log)); if (need_mutex) - pthread_mutex_lock(&LOCK_index); + mysql_mutex_lock(&LOCK_index); if ((error=find_log_pos(&log_info, to_log, 0 /*no mutex*/))) { sql_print_error("MYSQL_BIN_LOG::purge_logs was called with file %s not " @@ -3331,7 +3560,7 @@ err: DBUG_EXECUTE_IF("crash_purge_non_critical_after_update_index", abort();); if (need_mutex) - pthread_mutex_unlock(&LOCK_index); + mysql_mutex_unlock(&LOCK_index); DBUG_RETURN(error); } @@ -3470,7 +3699,7 @@ int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space, /* Get rid of the trailing '\n' */ log_info.log_file_name[length-1]= 0; - if (!my_stat(log_info.log_file_name, &s, MYF(0))) + if (!mysql_file_stat(key_file_binlog, log_info.log_file_name, &s, MYF(0))) { if (my_errno == ENOENT) { @@ -3484,7 +3713,7 @@ int MYSQL_BIN_LOG::purge_index_entry(THD *thd, ulonglong *decrease_log_space, ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE), log_info.log_file_name); } - sql_print_information("Failed to execute my_stat on file '%s'", + sql_print_information("Failed to execute mysql_file_stat on file '%s'", log_info.log_file_name); my_errno= 0; } @@ -3622,7 +3851,7 @@ err: @retval LOG_INFO_PURGE_NO_ROTATE Binary file that can't be rotated LOG_INFO_FATAL if any other than ENOENT error from - my_stat() or my_delete() + mysql_file_stat() or mysql_file_delete() */ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time) @@ -3635,7 +3864,7 @@ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time) DBUG_ENTER("purge_logs_before_date"); - pthread_mutex_lock(&LOCK_index); + mysql_mutex_lock(&LOCK_index); to_log[0]= 0; if ((error=find_log_pos(&log_info, NullS, 0 /*no mutex*/))) @@ -3645,7 +3874,8 @@ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time) !is_active(log_info.log_file_name) && !log_in_use(log_info.log_file_name)) { - if (!my_stat(log_info.log_file_name, &stat_area, MYF(0))) + if (!mysql_file_stat(key_file_binlog, + log_info.log_file_name, &stat_area, MYF(0))) { if (my_errno == ENOENT) { @@ -3694,7 +3924,7 @@ int MYSQL_BIN_LOG::purge_logs_before_date(time_t purge_time) error= (to_log[0] ? purge_logs(to_log, 1, 0, 1, (ulonglong *) 0) : 0); err: - pthread_mutex_unlock(&LOCK_index); + mysql_mutex_unlock(&LOCK_index); DBUG_RETURN(error); } #endif /* HAVE_REPLICATION */ @@ -3770,11 +4000,11 @@ void MYSQL_BIN_LOG::new_file_impl(bool need_lock) } if (need_lock) - pthread_mutex_lock(&LOCK_log); - pthread_mutex_lock(&LOCK_index); + mysql_mutex_lock(&LOCK_log); + mysql_mutex_lock(&LOCK_index); - safe_mutex_assert_owner(&LOCK_log); - safe_mutex_assert_owner(&LOCK_index); + mysql_mutex_assert_owner(&LOCK_log); + mysql_mutex_assert_owner(&LOCK_index); /* if binlog is used as tc log, be sure all xids are "unlogged", @@ -3788,12 +4018,12 @@ void MYSQL_BIN_LOG::new_file_impl(bool need_lock) if (prepared_xids) { tc_log_page_waits++; - pthread_mutex_lock(&LOCK_prep_xids); + mysql_mutex_lock(&LOCK_prep_xids); while (prepared_xids) { DBUG_PRINT("info", ("prepared_xids=%lu", prepared_xids)); - pthread_cond_wait(&COND_prep_xids, &LOCK_prep_xids); + mysql_cond_wait(&COND_prep_xids, &LOCK_prep_xids); } - pthread_mutex_unlock(&LOCK_prep_xids); + mysql_mutex_unlock(&LOCK_prep_xids); } /* Reuse old name if not binlog and not update log */ @@ -3853,8 +4083,8 @@ void MYSQL_BIN_LOG::new_file_impl(bool need_lock) end: if (need_lock) - pthread_mutex_unlock(&LOCK_log); - pthread_mutex_unlock(&LOCK_index); + mysql_mutex_unlock(&LOCK_log); + mysql_mutex_unlock(&LOCK_index); DBUG_VOID_RETURN; } @@ -3863,7 +4093,7 @@ end: bool MYSQL_BIN_LOG::append(Log_event* ev) { bool error = 0; - pthread_mutex_lock(&LOCK_log); + mysql_mutex_lock(&LOCK_log); DBUG_ENTER("MYSQL_BIN_LOG::append"); DBUG_ASSERT(log_file.type == SEQ_READ_APPEND); @@ -3884,7 +4114,7 @@ bool MYSQL_BIN_LOG::append(Log_event* ev) new_file_without_locking(); err: - pthread_mutex_unlock(&LOCK_log); + mysql_mutex_unlock(&LOCK_log); signal_update(); // Safe as we don't call close DBUG_RETURN(error); } @@ -3899,7 +4129,7 @@ bool MYSQL_BIN_LOG::appendv(const char* buf, uint len,...) DBUG_ASSERT(log_file.type == SEQ_READ_APPEND); - safe_mutex_assert_owner(&LOCK_log); + mysql_mutex_assert_owner(&LOCK_log); do { if (my_b_append(&log_file,(uchar*) buf,len)) @@ -3926,14 +4156,14 @@ bool MYSQL_BIN_LOG::flush_and_sync(bool *synced) int err=0, fd=log_file.file; if (synced) *synced= 0; - safe_mutex_assert_owner(&LOCK_log); + mysql_mutex_assert_owner(&LOCK_log); if (flush_io_cache(&log_file)) return 1; uint sync_period= get_sync_period(); if (sync_period && ++sync_counter >= sync_period) { sync_counter= 0; - err=my_sync(fd, MYF(MY_WME)); + err= mysql_file_sync(fd, MYF(MY_WME)); if (synced) *synced= 1; } @@ -3961,6 +4191,66 @@ bool MYSQL_BIN_LOG::is_query_in_union(THD *thd, query_id_t query_id_param) query_id_param >= thd->binlog_evt_union.first_query_id); } +/** + This function checks if a transactional talbe was updated by the + current transaction. + + @param thd The client thread that executed the current statement. + @return + @c true if a transactional table was updated, @c false otherwise. +*/ +bool +trans_has_updated_trans_table(const THD* thd) +{ + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + + return (cache_mngr ? my_b_tell (&cache_mngr->trx_cache.cache_log) : 0); +} + +/** + This function checks if a transactional talbe was updated by the + current statement. + + @param thd The client thread that executed the current statement. + @return + @c true if a transactional table was updated, @c false otherwise. +*/ +bool +stmt_has_updated_trans_table(const THD *thd) +{ + Ha_trx_info *ha_info; + + for (ha_info= thd->transaction.stmt.ha_list; ha_info; ha_info= ha_info->next()) + { + if (ha_info->is_trx_read_write() && ha_info->ht() != binlog_hton) + return (TRUE); + } + return (FALSE); +} + +/** + This function checks if either a trx-cache or a non-trx-cache should + be used. If @c bin_log_direct_non_trans_update is active, the cache + to be used depends on the flag @c is_transactional. + + Otherswise, we use the trx-cache if either the @c is_transactional + is true or the trx-cache is not empty. + + @param thd The client thread. + @param is_transactional The changes are related to a trx-table. + @return + @c true if a trx-cache should be used, @c false otherwise. +*/ +bool use_trans_cache(const THD* thd, bool is_transactional) +{ + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + + return + (thd->variables.binlog_direct_non_trans_update ? is_transactional : + (cache_mngr->trx_cache.empty() && !is_transactional ? FALSE : TRUE)); +} /* These functions are placed in this file since they need access to @@ -3970,23 +4260,25 @@ bool MYSQL_BIN_LOG::is_query_in_union(THD *thd, query_id_t query_id_param) int THD::binlog_setup_trx_data() { DBUG_ENTER("THD::binlog_setup_trx_data"); - binlog_trx_data *trx_data= - (binlog_trx_data*) thd_get_ha_data(this, binlog_hton); + binlog_cache_mngr *cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton); - if (trx_data) + if (cache_mngr) DBUG_RETURN(0); // Already set up - trx_data= (binlog_trx_data*) my_malloc(sizeof(binlog_trx_data), MYF(MY_ZEROFILL)); - if (!trx_data || - open_cached_file(&trx_data->trans_log, mysql_tmpdir, + cache_mngr= (binlog_cache_mngr*) my_malloc(sizeof(binlog_cache_mngr), MYF(MY_ZEROFILL)); + if (!cache_mngr || + open_cached_file(&cache_mngr->stmt_cache.cache_log, mysql_tmpdir, + LOG_PREFIX, binlog_cache_size, MYF(MY_WME)) || + open_cached_file(&cache_mngr->trx_cache.cache_log, mysql_tmpdir, LOG_PREFIX, binlog_cache_size, MYF(MY_WME))) { - my_free((uchar*)trx_data, MYF(MY_ALLOW_ZERO_PTR)); + my_free((uchar*)cache_mngr, MYF(MY_ALLOW_ZERO_PTR)); DBUG_RETURN(1); // Didn't manage to set it up } - thd_set_ha_data(this, binlog_hton, trx_data); + thd_set_ha_data(this, binlog_hton, cache_mngr); - trx_data= new (thd_get_ha_data(this, binlog_hton)) binlog_trx_data; + cache_mngr= new (thd_get_ha_data(this, binlog_hton)) binlog_cache_mngr; DBUG_RETURN(0); } @@ -4004,11 +4296,10 @@ int THD::binlog_setup_trx_data() - Start a transaction if not in autocommit mode or if a BEGIN statement has been seen. - - Start a statement transaction to allow us to truncate the binary - log. + - Start a statement transaction to allow us to truncate the cache. - Save the currrent binlog position so that we can roll back the - statement by truncating the transaction log. + statement by truncating the cache. We only update the saved position if the old one was undefined, the reason is that there are some cases (e.g., for CREATE-SELECT) @@ -4022,18 +4313,18 @@ int THD::binlog_setup_trx_data() void THD::binlog_start_trans_and_stmt() { - binlog_trx_data *trx_data= (binlog_trx_data*) thd_get_ha_data(this, binlog_hton); + binlog_cache_mngr *cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton); DBUG_ENTER("binlog_start_trans_and_stmt"); - DBUG_PRINT("enter", ("trx_data: 0x%lx trx_data->before_stmt_pos: %lu", - (long) trx_data, - (trx_data ? (ulong) trx_data->before_stmt_pos : + DBUG_PRINT("enter", ("cache_mngr: %p cache_mngr->trx_cache.get_prev_position(): %lu", + cache_mngr, + (cache_mngr ? (ulong) cache_mngr->trx_cache.get_prev_position() : (ulong) 0))); - if (trx_data == NULL || - trx_data->before_stmt_pos == MY_OFF_T_UNDEF) + if (cache_mngr == NULL || + cache_mngr->trx_cache.get_prev_position() == MY_OFF_T_UNDEF) { this->binlog_set_stmt_begin(); - if (options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) + if (variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) trans_register_ha(this, TRUE, binlog_hton); trans_register_ha(this, FALSE, binlog_hton); /* @@ -4051,27 +4342,35 @@ THD::binlog_start_trans_and_stmt() } void THD::binlog_set_stmt_begin() { - binlog_trx_data *trx_data= - (binlog_trx_data*) thd_get_ha_data(this, binlog_hton); + binlog_cache_mngr *cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton); /* - The call to binlog_trans_log_savepos() might create the trx_data + The call to binlog_trans_log_savepos() might create the cache_mngr structure, if it didn't exist before, so we save the position into an auto variable and then write it into the transaction - data for the binary log (i.e., trx_data). + data for the binary log (i.e., cache_mngr). */ my_off_t pos= 0; binlog_trans_log_savepos(this, &pos); - trx_data= (binlog_trx_data*) thd_get_ha_data(this, binlog_hton); - trx_data->before_stmt_pos= pos; + cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton); + cache_mngr->trx_cache.set_prev_position(pos); } -/* - Write a table map to the binary log. - */ - -int THD::binlog_write_table_map(TABLE *table, bool is_trans) +/** + This function writes a table map to the binary log. + Note that in order to keep the signature uniform with related methods, + we use a redundant parameter to indicate whether a transactional table + was changed or not. + + @param table a pointer to the table. + @param is_transactional @c true indicates a transactional table, + otherwise @c false a non-transactional. + @return + nonzero if an error pops up when writing the table map event. +*/ +int THD::binlog_write_table_map(TABLE *table, bool is_transactional) { int error; DBUG_ENTER("THD::binlog_write_table_map"); @@ -4080,19 +4379,21 @@ int THD::binlog_write_table_map(TABLE *table, bool is_trans) table->s->table_map_id)); /* Pre-conditions */ - DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open()); + DBUG_ASSERT(is_current_stmt_binlog_format_row() && mysql_bin_log.is_open()); DBUG_ASSERT(table->s->table_map_id != ULONG_MAX); - Table_map_log_event::flag_set const - flags= Table_map_log_event::TM_NO_FLAGS; - Table_map_log_event - the_event(this, table, table->s->table_map_id, is_trans, flags); + the_event(this, table, table->s->table_map_id, is_transactional); - if (is_trans && binlog_table_maps == 0) + if (binlog_table_maps == 0) binlog_start_trans_and_stmt(); - if ((error= mysql_bin_log.write(&the_event))) + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton); + + IO_CACHE *file= + cache_mngr->get_binlog_cache_log(use_trans_cache(this, is_transactional)); + if ((error= the_event.write(file))) DBUG_RETURN(error); binlog_table_maps++; @@ -4100,144 +4401,163 @@ int THD::binlog_write_table_map(TABLE *table, bool is_trans) DBUG_RETURN(0); } +/** + This function retrieves a pending row event from a cache which is + specified through the parameter @c is_transactional. Respectively, when it + is @c true, the pending event is returned from the transactional cache. + Otherwise from the non-transactional cache. + + @param is_transactional @c true indicates a transactional cache, + otherwise @c false a non-transactional. + @return + The row event if any. +*/ Rows_log_event* -THD::binlog_get_pending_rows_event() const +THD::binlog_get_pending_rows_event(bool is_transactional) const { - binlog_trx_data *const trx_data= - (binlog_trx_data*) thd_get_ha_data(this, binlog_hton); + Rows_log_event* rows= NULL; + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton); + /* - This is less than ideal, but here's the story: If there is no - trx_data, prepare_pending_rows_event() has never been called - (since the trx_data is set up there). In that case, we just return - NULL. + This is less than ideal, but here's the story: If there is no cache_mngr, + prepare_pending_rows_event() has never been called (since the cache_mngr + is set up there). In that case, we just return NULL. */ - return trx_data ? trx_data->pending() : NULL; + if (cache_mngr) + { + binlog_cache_data *cache_data= + cache_mngr->get_binlog_cache_data(use_trans_cache(this, is_transactional)); + + rows= cache_data->pending(); + } + return (rows); } +/** + This function stores a pending row event into a cache which is specified + through the parameter @c is_transactional. Respectively, when it is @c + true, the pending event is stored into the transactional cache. Otherwise + into the non-transactional cache. + + @param evt a pointer to the row event. + @param is_transactional @c true indicates a transactional cache, + otherwise @c false a non-transactional. +*/ void -THD::binlog_set_pending_rows_event(Rows_log_event* ev) +THD::binlog_set_pending_rows_event(Rows_log_event* ev, bool is_transactional) { if (thd_get_ha_data(this, binlog_hton) == NULL) binlog_setup_trx_data(); - binlog_trx_data *const trx_data= - (binlog_trx_data*) thd_get_ha_data(this, binlog_hton); + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(this, binlog_hton); + + DBUG_ASSERT(cache_mngr); - DBUG_ASSERT(trx_data); - trx_data->set_pending(ev); + binlog_cache_data *cache_data= + cache_mngr->get_binlog_cache_data(use_trans_cache(this, is_transactional)); + + cache_data->set_pending(ev); } /** - Remove the pending rows event, discarding any outstanding rows. - - If there is no pending rows event available, this is effectively a + This function removes the pending rows event, discarding any outstanding + rows. If there is no pending rows event available, this is effectively a no-op. - */ + + @param thd a pointer to the user thread. + @param is_transactional @c true indicates a transactional cache, + otherwise @c false a non-transactional. +*/ int -MYSQL_BIN_LOG::remove_pending_rows_event(THD *thd) +MYSQL_BIN_LOG::remove_pending_rows_event(THD *thd, bool is_transactional) { DBUG_ENTER("MYSQL_BIN_LOG::remove_pending_rows_event"); - binlog_trx_data *const trx_data= - (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton); + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + + DBUG_ASSERT(cache_mngr); - DBUG_ASSERT(trx_data); + binlog_cache_data *cache_data= + cache_mngr->get_binlog_cache_data(use_trans_cache(thd, is_transactional)); - if (Rows_log_event* pending= trx_data->pending()) + if (Rows_log_event* pending= cache_data->pending()) { delete pending; - trx_data->set_pending(NULL); + cache_data->set_pending(NULL); } DBUG_RETURN(0); } /* - Moves the last bunch of rows from the pending Rows event to the binlog - (either cached binlog if transaction, or disk binlog). Sets a new pending - event. + Moves the last bunch of rows from the pending Rows event to a cache (either + transactional cache if is_transaction is @c true, or the non-transactional + cache otherwise. Sets a new pending event. + + @param thd a pointer to the user thread. + @param evt a pointer to the row event. + @param is_transactional @c true indicates a transactional cache, + otherwise @c false a non-transactional. */ int MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd, - Rows_log_event* event) + Rows_log_event* event, + bool is_transactional) { DBUG_ENTER("MYSQL_BIN_LOG::flush_and_set_pending_rows_event(event)"); DBUG_ASSERT(mysql_bin_log.is_open()); DBUG_PRINT("enter", ("event: 0x%lx", (long) event)); int error= 0; + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); - binlog_trx_data *const trx_data= - (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton); + DBUG_ASSERT(cache_mngr); - DBUG_ASSERT(trx_data); + binlog_cache_data *cache_data= + cache_mngr->get_binlog_cache_data(use_trans_cache(thd, is_transactional)); - DBUG_PRINT("info", ("trx_data->pending(): 0x%lx", (long) trx_data->pending())); + DBUG_PRINT("info", ("cache_mngr->pending(): 0x%lx", (long) cache_data->pending())); - if (Rows_log_event* pending= trx_data->pending()) + if (Rows_log_event* pending= cache_data->pending()) { - IO_CACHE *file= &log_file; - - /* - Decide if we should write to the log file directly or to the - transaction log. - */ - if (pending->get_cache_stmt() || my_b_tell(&trx_data->trans_log)) - file= &trx_data->trans_log; + IO_CACHE *file= &cache_data->cache_log; /* - If we are writing to the log file directly, we could avoid - locking the log. This does not work since we need to step the - m_table_map_version below, and that change has to be protected - by the LOCK_log mutex. - */ - pthread_mutex_lock(&LOCK_log); - - /* - Write pending event to log file or transaction cache + Write pending event to the cache. */ if (pending->write(file)) { - pthread_mutex_unlock(&LOCK_log); set_write_error(thd); + if (check_write_error(thd) && cache_data && + thd->transaction.stmt.modified_non_trans_table) + cache_data->set_incident(); DBUG_RETURN(1); } /* We step the table map version if we are writing an event - representing the end of a statement. We do this regardless of - wheather we write to the transaction cache or to directly to the - file. - - In an ideal world, we could avoid stepping the table map version - if we were writing to a transaction cache, since we could then - reuse the table map that was written earlier in the transaction - cache. This does not work since STMT_END_F implies closing all - table mappings on the slave side. + representing the end of a statement. + In an ideal world, we could avoid stepping the table map version, + since we could then reuse the table map that was written earlier + in the cache. This does not work since STMT_END_F implies closing + all table mappings on the slave side. + TODO: Find a solution so that table maps does not have to be written several times within a transaction. - */ + */ if (pending->get_flags(Rows_log_event::STMT_END_F)) ++m_table_map_version; delete pending; - - if (file == &log_file) - { - error= flush_and_sync(0); - if (!error) - { - signal_update(); - rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED); - } - } - - pthread_mutex_unlock(&LOCK_log); } - thd->binlog_set_pending_rows_event(event); + thd->binlog_set_pending_rows_event(event, is_transactional); DBUG_RETURN(error); } @@ -4251,6 +4571,7 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info) THD *thd= event_info->thd; bool error= 1; DBUG_ENTER("MYSQL_BIN_LOG::write(Log_event *)"); + binlog_cache_data *cache_data= 0; if (thd->binlog_evt_union.do_union) { @@ -4259,27 +4580,22 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info) We will log the function call to the binary log on function exit */ thd->binlog_evt_union.unioned_events= TRUE; - thd->binlog_evt_union.unioned_events_trans |= event_info->cache_stmt; + thd->binlog_evt_union.unioned_events_trans |= + event_info->use_trans_cache(); DBUG_RETURN(0); } /* - Flush the pending rows event to the transaction cache or to the - log file. Since this function potentially aquire the LOCK_log - mutex, we do this before aquiring the LOCK_log mutex in this - function. - We only end the statement if we are in a top-level statement. If we are inside a stored function, we do not end the statement since this will close all tables on the slave. */ bool const end_stmt= thd->prelocked_mode && thd->lex->requires_prelocking(); - if (thd->binlog_flush_pending_rows_event(end_stmt)) + if (thd->binlog_flush_pending_rows_event(end_stmt, + event_info->use_trans_cache())) DBUG_RETURN(error); - pthread_mutex_lock(&LOCK_log); - /* In most cases this is only called if 'is_open()' is true; in fact this is mostly called if is_open() *was* true a few instructions before, but it @@ -4287,7 +4603,6 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info) */ if (likely(is_open())) { - IO_CACHE *file= &log_file; #ifdef HAVE_REPLICATION /* In the future we need to add to the following if tests like @@ -4295,78 +4610,45 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info) binlog_[wild_]{do|ignore}_table?" (WL#1049)" */ const char *local_db= event_info->get_db(); - if ((thd && !(thd->options & OPTION_BIN_LOG)) || - (!binlog_filter->db_ok(local_db))) - { - VOID(pthread_mutex_unlock(&LOCK_log)); + if ((thd && !(thd->variables.option_bits & OPTION_BIN_LOG)) || + !binlog_filter->db_ok(local_db)) DBUG_RETURN(0); - } #endif /* HAVE_REPLICATION */ -#if defined(USING_TRANSACTIONS) - /* - Should we write to the binlog cache or to the binlog on disk? - - Write to the binlog cache if: - 1 - a transactional engine/table is updated (stmt_has_updated_trans_table == TRUE); - 2 - or the event asks for it (cache_stmt == TRUE); - 3 - or the cache is already not empty (meaning we're in a transaction; - note that the present event could be about a non-transactional table, but - still we need to write to the binlog cache in that case to handle updates - to mixed trans/non-trans table types). - - Write to the binlog on disk if only a non-transactional engine is - updated and: - 1 - the binlog cache is empty or; - 2 - --binlog-direct-non-transactional-updates is set and we are about to - use the statement format. When using the row format (cache_stmt == TRUE). - */ - if (opt_using_transactions && thd) + IO_CACHE *file= NULL; + + if (event_info->use_direct_logging()) + { + file= &log_file; + mysql_mutex_lock(&LOCK_log); + } + else { if (thd->binlog_setup_trx_data()) goto err; - binlog_trx_data *const trx_data= - (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton); - IO_CACHE *trans_log= &trx_data->trans_log; - my_off_t trans_log_pos= my_b_tell(trans_log); - if (event_info->get_cache_stmt() || stmt_has_updated_trans_table(thd) || - (!thd->variables.binlog_direct_non_trans_update && - trans_log_pos != 0)) - { - DBUG_PRINT("info", ("Using trans_log: cache: %d, trans_log_pos: %lu", - event_info->get_cache_stmt(), - (ulong) trans_log_pos)); - thd->binlog_start_trans_and_stmt(); - file= trans_log; - } - /* - TODO as Mats suggested, for all the cases above where we write to - trans_log, it sounds unnecessary to lock LOCK_log. We should rather - test first if we want to write to trans_log, and if not, lock - LOCK_log. - */ + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + + bool is_trans_cache= use_trans_cache(thd, event_info->use_trans_cache()); + file= cache_mngr->get_binlog_cache_log(is_trans_cache); + cache_data= cache_mngr->get_binlog_cache_data(is_trans_cache); + + thd->binlog_start_trans_and_stmt(); } -#endif /* USING_TRANSACTIONS */ DBUG_PRINT("info",("event type: %d",event_info->get_type_code())); /* - No check for auto events flag here - this write method should - never be called if auto-events are enabled - */ + No check for auto events flag here - this write method should + never be called if auto-events are enabled. - /* - 1. Write first log events which describe the 'run environment' - of the SQL command - */ - - /* - If row-based binlogging, Insert_id, Rand and other kind of "setting - context" events are not needed. + Write first log events which describe the 'run environment' + of the SQL command. If row-based binlogging, Insert_id, Rand + and other kind of "setting context" events are not needed. */ if (thd) { - if (!thd->current_stmt_binlog_row_based) + if (!thd->is_current_stmt_binlog_format_row()) { if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt) { @@ -4412,39 +4694,48 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info) } /* - Write the SQL command - */ - - if (event_info->write(file) || + Write the event. + */ + if (event_info->write(file) || DBUG_EVALUATE_IF("injecting_fault_writing", 1, 0)) goto err; - if (file == &log_file) // we are writing to the real log (disk) + error= 0; + +err: + if (event_info->use_direct_logging()) { - bool synced= 0; - if (flush_and_sync(&synced)) - goto err; + if (!error) + { + bool synced; + if ((error= flush_and_sync(&synced))) + goto unlock; - if (RUN_HOOK(binlog_storage, after_flush, - (thd, log_file_name, file->pos_in_file, synced))) { - sql_print_error("Failed to run 'after_flush' hooks"); - goto err; + if ((error= RUN_HOOK(binlog_storage, after_flush, + (thd, log_file_name, file->pos_in_file, synced)))) + { + sql_print_error("Failed to run 'after_flush' hooks"); + goto unlock; + } + signal_update(); + rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED); } - - signal_update(); - rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED); +unlock: + mysql_mutex_unlock(&LOCK_log); } - error=0; -err: if (error) + { set_write_error(thd); + if (check_write_error(thd) && cache_data && + thd->transaction.stmt.modified_non_trans_table) + cache_data->set_incident(); + } } if (event_info->flags & LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F) ++m_table_map_version; - pthread_mutex_unlock(&LOCK_log); DBUG_RETURN(error); } @@ -4474,7 +4765,7 @@ bool LOGGER::log_command(THD *thd, enum enum_server_command command) */ if (*general_log_handler_list && (what_to_log & (1L << (uint) command))) { - if ((thd->options & OPTION_LOG_OFF) + if ((thd->variables.option_bits & OPTION_LOG_OFF) #ifndef NO_EMBEDDED_ACCESS_CHECKS && (sctx->master_access & SUPER_ACL) #endif @@ -4524,7 +4815,7 @@ void MYSQL_BIN_LOG::rotate_and_purge(uint flags) bool check_purge= false; #endif if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED)) - pthread_mutex_lock(&LOCK_log); + mysql_mutex_lock(&LOCK_log); if ((flags & RP_FORCE_ROTATE) || (my_b_tell(&log_file) >= (my_off_t) max_size)) { @@ -4534,7 +4825,7 @@ void MYSQL_BIN_LOG::rotate_and_purge(uint flags) #endif } if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED)) - pthread_mutex_unlock(&LOCK_log); + mysql_mutex_unlock(&LOCK_log); #ifdef HAVE_REPLICATION /* @@ -4553,9 +4844,9 @@ void MYSQL_BIN_LOG::rotate_and_purge(uint flags) uint MYSQL_BIN_LOG::next_file_id() { uint res; - pthread_mutex_lock(&LOCK_log); + mysql_mutex_lock(&LOCK_log); res = file_id++; - pthread_mutex_unlock(&LOCK_log); + mysql_mutex_unlock(&LOCK_log); return res; } @@ -4567,7 +4858,7 @@ uint MYSQL_BIN_LOG::next_file_id() write_cache() cache Cache to write to the binary log lock_log True if the LOCK_log mutex should be aquired, false otherwise - sync_log True if the log should be flushed and sync:ed + sync_log True if the log should be flushed and synced DESCRIPTION Write the contents of the cache to the binary log. The cache will @@ -4603,7 +4894,6 @@ int MYSQL_BIN_LOG::write_cache(IO_CACHE *cache, bool lock_log, bool sync_log) do { - /* if we only got a partial header in the last iteration, get the other half now and process a full header. @@ -4739,7 +5029,7 @@ bool MYSQL_BIN_LOG::write_incident(THD *thd, bool lock) Incident incident= INCIDENT_LOST_EVENTS; Incident_log_event ev(thd, incident, write_error_msg); if (lock) - pthread_mutex_lock(&LOCK_log); + mysql_mutex_lock(&LOCK_log); error= ev.write(&log_file); if (lock) { @@ -4748,7 +5038,7 @@ bool MYSQL_BIN_LOG::write_incident(THD *thd, bool lock) signal_update(); rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED); } - pthread_mutex_unlock(&LOCK_log); + mysql_mutex_unlock(&LOCK_log); } DBUG_RETURN(error); } @@ -4781,10 +5071,7 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event, bool incident) { DBUG_ENTER("MYSQL_BIN_LOG::write(THD *, IO_CACHE *, Log_event *)"); - VOID(pthread_mutex_lock(&LOCK_log)); - - /* NULL would represent nothing to replicate after ROLLBACK */ - DBUG_ASSERT(commit_event != NULL); + mysql_mutex_lock(&LOCK_log); DBUG_ASSERT(is_open()); if (likely(is_open())) // Should always be true @@ -4800,19 +5087,9 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event, transaction is either a BEGIN..COMMIT block or a single statement in autocommit mode. */ - Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, TRUE, 0); - - /* - Now this Query_log_event has artificial log_pos 0. It must be - adjusted to reflect the real position in the log. Not doing it - would confuse the slave: it would prevent this one from - knowing where he is in the master's binlog, which would result - in wrong positions being shown to the user, MASTER_POS_WAIT - undue waiting etc. - */ + Query_log_event qinfo(thd, STRING_WITH_LEN("BEGIN"), TRUE, FALSE, TRUE, 0); if (qinfo.write(&log_file)) goto err; - DBUG_EXECUTE_IF("crash_before_writing_xid", { if ((write_error= write_cache(cache, false, true))) @@ -4863,14 +5140,14 @@ bool MYSQL_BIN_LOG::write(THD *thd, IO_CACHE *cache, Log_event *commit_event, */ if (commit_event && commit_event->get_type_code() == XID_EVENT) { - pthread_mutex_lock(&LOCK_prep_xids); + mysql_mutex_lock(&LOCK_prep_xids); prepared_xids++; - pthread_mutex_unlock(&LOCK_prep_xids); + mysql_mutex_unlock(&LOCK_prep_xids); } else rotate_and_purge(RP_LOCK_LOG_IS_ALREADY_LOCKED); } - VOID(pthread_mutex_unlock(&LOCK_log)); + mysql_mutex_unlock(&LOCK_log); DBUG_RETURN(0); @@ -4880,7 +5157,7 @@ err: write_error= 1; sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); } - VOID(pthread_mutex_unlock(&LOCK_log)); + mysql_mutex_unlock(&LOCK_log); DBUG_RETURN(1); } @@ -4902,10 +5179,10 @@ void MYSQL_BIN_LOG::wait_for_update_relay_log(THD* thd) DBUG_ENTER("wait_for_update_relay_log"); old_msg= thd->enter_cond(&update_cond, &LOCK_log, - "Slave has read all relay log; " + "Slave has read all relay log; " "waiting for the slave I/O " "thread to update it" ); - pthread_cond_wait(&update_cond, &LOCK_log); + mysql_cond_wait(&update_cond, &LOCK_log); thd->exit_cond(old_msg); DBUG_VOID_RETURN; } @@ -4936,10 +5213,10 @@ int MYSQL_BIN_LOG::wait_for_update_bin_log(THD* thd, "Master has sent all binlog to slave; " "waiting for binlog to be updated"); if (!timeout) - pthread_cond_wait(&update_cond, &LOCK_log); + mysql_cond_wait(&update_cond, &LOCK_log); else - ret= pthread_cond_timedwait(&update_cond, &LOCK_log, - const_cast<struct timespec *>(timeout)); + ret= mysql_cond_timedwait(&update_cond, &LOCK_log, + const_cast<struct timespec *>(timeout)); DBUG_RETURN(ret); } @@ -4979,16 +5256,16 @@ void MYSQL_BIN_LOG::close(uint exiting) if (log_file.type == WRITE_CACHE && log_type == LOG_BIN) { my_off_t offset= BIN_LOG_HEADER_SIZE + FLAGS_OFFSET; - my_off_t org_position= my_tell(log_file.file, MYF(0)); + my_off_t org_position= mysql_file_tell(log_file.file, MYF(0)); uchar flags= 0; // clearing LOG_EVENT_BINLOG_IN_USE_F - my_pwrite(log_file.file, &flags, 1, offset, MYF(0)); + mysql_file_pwrite(log_file.file, &flags, 1, offset, MYF(0)); /* Restore position so that anything we have in the IO_cache is written to the correct position. - We need the seek here, as my_pwrite() is not guaranteed to keep the + We need the seek here, as mysql_file_pwrite() is not guaranteed to keep the original position on system that doesn't support pwrite(). */ - my_seek(log_file.file, org_position, MY_SEEK_SET, MYF(0)); + mysql_file_seek(log_file.file, org_position, MY_SEEK_SET, MYF(0)); } /* this will cleanup IO_CACHE, sync and close the file */ @@ -5003,7 +5280,7 @@ void MYSQL_BIN_LOG::close(uint exiting) if ((exiting & LOG_CLOSE_INDEX) && my_b_inited(&index_file)) { end_io_cache(&index_file); - if (my_close(index_file.file, MYF(0)) < 0 && ! write_error) + if (mysql_file_close(index_file.file, MYF(0)) < 0 && ! write_error) { write_error= 1; sql_print_error(ER(ER_ERROR_ON_WRITE), index_file_name, errno); @@ -5025,10 +5302,10 @@ void MYSQL_BIN_LOG::set_max_size(ulong max_size_arg) it's like if the SET command was never run. */ DBUG_ENTER("MYSQL_BIN_LOG::set_max_size"); - pthread_mutex_lock(&LOCK_log); + mysql_mutex_lock(&LOCK_log); if (is_open()) max_size= max_size_arg; - pthread_mutex_unlock(&LOCK_log); + mysql_mutex_unlock(&LOCK_log); DBUG_VOID_RETURN; } @@ -5047,11 +5324,11 @@ void MYSQL_BIN_LOG::set_max_size(ulong max_size_arg) @retval 1 String is a number @retval - 0 Error + 0 String is not a number */ static bool test_if_number(register const char *str, - long *res, bool allow_wildcards) + ulong *res, bool allow_wildcards) { reg2 int flag; const char *start; @@ -5100,7 +5377,7 @@ bool flush_error_log() char err_renamed[FN_REFLEN], *end; end= strmake(err_renamed,log_error_file,FN_REFLEN-5); strmov(end, "-old"); - VOID(pthread_mutex_lock(&LOCK_error_log)); + mysql_mutex_lock(&LOCK_error_log); #ifdef __WIN__ char err_temp[FN_REFLEN+5]; /* @@ -5108,7 +5385,7 @@ bool flush_error_log() the current error file. */ strxmov(err_temp, err_renamed,"-tmp",NullS); - (void) my_delete(err_temp, MYF(0)); + my_delete(err_temp, MYF(0)); if (freopen(err_temp,"a+",stdout)) { int fd; @@ -5117,27 +5394,27 @@ bool flush_error_log() freopen(err_temp,"a+",stderr); setbuf(stderr, NULL); - (void) my_delete(err_renamed, MYF(0)); - my_rename(log_error_file,err_renamed,MYF(0)); + my_delete(err_renamed, MYF(0)); + my_rename(log_error_file, err_renamed, MYF(0)); if (freopen(log_error_file,"a+",stdout)) { freopen(log_error_file,"a+",stderr); setbuf(stderr, NULL); } - if ((fd = my_open(err_temp, O_RDONLY, MYF(0))) >= 0) + if ((fd= my_open(err_temp, O_RDONLY, MYF(0))) >= 0) { - while ((bytes= my_read(fd, buf, IO_SIZE, MYF(0))) && + while ((bytes= mysql_file_read(fd, buf, IO_SIZE, MYF(0))) && bytes != MY_FILE_ERROR) my_fwrite(stderr, buf, bytes, MYF(0)); - my_close(fd, MYF(0)); + mysql_file_close(fd, MYF(0)); } - (void) my_delete(err_temp, MYF(0)); + my_delete(err_temp, MYF(0)); } else result= 1; #else - my_rename(log_error_file,err_renamed,MYF(0)); + my_rename(log_error_file, err_renamed, MYF(0)); if (freopen(log_error_file,"a+",stdout)) { FILE *reopen; @@ -5147,7 +5424,7 @@ bool flush_error_log() else result= 1; #endif - VOID(pthread_mutex_unlock(&LOCK_error_log)); + mysql_mutex_unlock(&LOCK_error_log); } return result; } @@ -5156,7 +5433,7 @@ void MYSQL_BIN_LOG::signal_update() { DBUG_ENTER("MYSQL_BIN_LOG::signal_update"); signal_cnt++; - pthread_cond_broadcast(&update_cond); + mysql_cond_broadcast(&update_cond); DBUG_VOID_RETURN; } @@ -5222,7 +5499,7 @@ static void print_buffer_to_file(enum loglevel level, const char *buffer) DBUG_ENTER("print_buffer_to_file"); DBUG_PRINT("enter",("buffer: %s", buffer)); - VOID(pthread_mutex_lock(&LOCK_error_log)); + mysql_mutex_lock(&LOCK_error_log); skr= my_time(0); localtime_r(&skr, &tm_tmp); @@ -5241,7 +5518,7 @@ static void print_buffer_to_file(enum loglevel level, const char *buffer) fflush(stderr); - VOID(pthread_mutex_unlock(&LOCK_error_log)); + mysql_mutex_unlock(&LOCK_error_log); DBUG_VOID_RETURN; } @@ -5365,17 +5642,18 @@ int TC_LOG_MMAP::open(const char *opt_name) DBUG_ASSERT(TC_LOG_PAGE_SIZE % tc_log_page_size == 0); fn_format(logname,opt_name,mysql_data_home,"",MY_UNPACK_FILENAME); - if ((fd= my_open(logname, O_RDWR, MYF(0))) < 0) + if ((fd= mysql_file_open(key_file_tclog, logname, O_RDWR, MYF(0))) < 0) { if (my_errno != ENOENT) goto err; if (using_heuristic_recover()) return 1; - if ((fd= my_create(logname, CREATE_MODE, O_RDWR, MYF(MY_WME))) < 0) + if ((fd= mysql_file_create(key_file_tclog, logname, CREATE_MODE, + O_RDWR, MYF(MY_WME))) < 0) goto err; inited=1; file_length= opt_tc_log_size; - if (my_chsize(fd, file_length, 0, MYF(MY_WME))) + if (mysql_file_chsize(fd, file_length, 0, MYF(MY_WME))) goto err; } else @@ -5389,7 +5667,7 @@ int TC_LOG_MMAP::open(const char *opt_name) "--tc-heuristic-recover is used"); goto err; } - file_length= my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE)); + file_length= mysql_file_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE)); if (file_length == MY_FILEPOS_ERROR || file_length % tc_log_page_size) goto err; } @@ -5413,8 +5691,8 @@ int TC_LOG_MMAP::open(const char *opt_name) pg->next=pg+1; pg->waiters=0; pg->state=POOL; - pthread_mutex_init(&pg->lock, MY_MUTEX_INIT_FAST); - pthread_cond_init (&pg->cond, 0); + mysql_mutex_init(key_PAGE_lock, &pg->lock, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_PAGE_cond, &pg->cond, 0); pg->start=(my_xid *)(data + i*tc_log_page_size); pg->end=(my_xid *)(pg->start + tc_log_page_size); pg->size=pg->free=tc_log_page_size/sizeof(my_xid); @@ -5433,11 +5711,11 @@ int TC_LOG_MMAP::open(const char *opt_name) my_msync(fd, data, tc_log_page_size, MS_SYNC); inited=5; - pthread_mutex_init(&LOCK_sync, MY_MUTEX_INIT_FAST); - pthread_mutex_init(&LOCK_active, MY_MUTEX_INIT_FAST); - pthread_mutex_init(&LOCK_pool, MY_MUTEX_INIT_FAST); - pthread_cond_init(&COND_active, 0); - pthread_cond_init(&COND_pool, 0); + mysql_mutex_init(key_LOCK_sync, &LOCK_sync, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_active, &LOCK_active, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_pool, &LOCK_pool, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_active, &COND_active, 0); + mysql_cond_init(key_COND_pool, &COND_pool, 0); inited=6; @@ -5471,7 +5749,7 @@ void TC_LOG_MMAP::get_active_from_pool() int best_free; if (syncing) - pthread_mutex_lock(&LOCK_pool); + mysql_mutex_lock(&LOCK_pool); do { @@ -5504,7 +5782,7 @@ void TC_LOG_MMAP::get_active_from_pool() pool_last=*best_p; if (syncing) - pthread_mutex_unlock(&LOCK_pool); + mysql_mutex_unlock(&LOCK_pool); } /** @@ -5519,7 +5797,7 @@ int TC_LOG_MMAP::overflow() let's check the behaviour of tc_log_page_waits first */ tc_log_page_waits++; - pthread_cond_wait(&COND_pool, &LOCK_pool); + mysql_cond_wait(&COND_pool, &LOCK_pool); return 1; // always return 1 } @@ -5556,7 +5834,7 @@ int TC_LOG_MMAP::log_xid(THD *thd, my_xid xid) PAGE *p; ulong cookie; - pthread_mutex_lock(&LOCK_active); + mysql_mutex_lock(&LOCK_active); /* if active page is full - just wait... @@ -5566,14 +5844,14 @@ int TC_LOG_MMAP::log_xid(THD *thd, my_xid xid) unlog() does not signal COND_active. */ while (unlikely(active && active->free == 0)) - pthread_cond_wait(&COND_active, &LOCK_active); + mysql_cond_wait(&COND_active, &LOCK_active); /* no active page ? take one from the pool */ if (active == 0) get_active_from_pool(); p=active; - pthread_mutex_lock(&p->lock); + mysql_mutex_lock(&p->lock); /* searching for an empty slot */ while (*p->ptr) @@ -5589,9 +5867,9 @@ int TC_LOG_MMAP::log_xid(THD *thd, my_xid xid) p->state= DIRTY; /* to sync or not to sync - this is the question */ - pthread_mutex_unlock(&LOCK_active); - pthread_mutex_lock(&LOCK_sync); - pthread_mutex_unlock(&p->lock); + mysql_mutex_unlock(&LOCK_active); + mysql_mutex_lock(&LOCK_sync); + mysql_mutex_unlock(&p->lock); if (syncing) { // somebody's syncing. let's wait @@ -5601,24 +5879,24 @@ int TC_LOG_MMAP::log_xid(THD *thd, my_xid xid) as p->state may be not DIRTY when we come here */ while (p->state == DIRTY && syncing) - pthread_cond_wait(&p->cond, &LOCK_sync); + mysql_cond_wait(&p->cond, &LOCK_sync); p->waiters--; err= p->state == ERROR; if (p->state != DIRTY) // page was synced { if (p->waiters == 0) - pthread_cond_signal(&COND_pool); // in case somebody's waiting - pthread_mutex_unlock(&LOCK_sync); + mysql_cond_signal(&COND_pool); // in case somebody's waiting + mysql_mutex_unlock(&LOCK_sync); goto done; // we're done } } // page was not synced! do it now DBUG_ASSERT(active == p && syncing == 0); - pthread_mutex_lock(&LOCK_active); + mysql_mutex_lock(&LOCK_active); syncing=p; // place is vacant - take it active=0; // page is not active anymore - pthread_cond_broadcast(&COND_active); // in case somebody's waiting - pthread_mutex_unlock(&LOCK_active); - pthread_mutex_unlock(&LOCK_sync); + mysql_cond_broadcast(&COND_active); // in case somebody's waiting + mysql_mutex_unlock(&LOCK_active); + mysql_mutex_unlock(&LOCK_sync); err= sync(); done: @@ -5638,20 +5916,20 @@ int TC_LOG_MMAP::sync() err= my_msync(fd, syncing->start, 1, MS_SYNC); /* page is synced. let's move it to the pool */ - pthread_mutex_lock(&LOCK_pool); + mysql_mutex_lock(&LOCK_pool); pool_last->next=syncing; pool_last=syncing; syncing->next=0; syncing->state= err ? ERROR : POOL; - pthread_cond_broadcast(&syncing->cond); // signal "sync done" - pthread_cond_signal(&COND_pool); // in case somebody's waiting - pthread_mutex_unlock(&LOCK_pool); + mysql_cond_broadcast(&syncing->cond); // signal "sync done" + mysql_cond_signal(&COND_pool); // in case somebody's waiting + mysql_mutex_unlock(&LOCK_pool); /* marking 'syncing' slot free */ - pthread_mutex_lock(&LOCK_sync); + mysql_mutex_lock(&LOCK_sync); syncing=0; - pthread_cond_signal(&active->cond); // wake up a new syncer - pthread_mutex_unlock(&LOCK_sync); + mysql_cond_signal(&active->cond); // wake up a new syncer + mysql_mutex_unlock(&LOCK_sync); return err; } @@ -5669,15 +5947,15 @@ void TC_LOG_MMAP::unlog(ulong cookie, my_xid xid) DBUG_ASSERT(x >= p->start && x < p->end); *x=0; - pthread_mutex_lock(&p->lock); + mysql_mutex_lock(&p->lock); p->free++; DBUG_ASSERT(p->free <= p->size); set_if_smaller(p->ptr, x); if (p->free == p->size) // the page is completely empty statistic_decrement(tc_log_cur_pages_used, &LOCK_status); if (p->waiters == 0) // the page is in pool and ready to rock - pthread_cond_signal(&COND_pool); // ping ... for overflow() - pthread_mutex_unlock(&p->lock); + mysql_cond_signal(&COND_pool); // ping ... for overflow() + mysql_mutex_unlock(&p->lock); } void TC_LOG_MMAP::close() @@ -5685,29 +5963,29 @@ void TC_LOG_MMAP::close() uint i; switch (inited) { case 6: - pthread_mutex_destroy(&LOCK_sync); - pthread_mutex_destroy(&LOCK_active); - pthread_mutex_destroy(&LOCK_pool); - pthread_cond_destroy(&COND_pool); + mysql_mutex_destroy(&LOCK_sync); + mysql_mutex_destroy(&LOCK_active); + mysql_mutex_destroy(&LOCK_pool); + mysql_cond_destroy(&COND_pool); case 5: - data[0]='A'; // garble the first (signature) byte, in case my_delete fails + data[0]='A'; // garble the first (signature) byte, in case mysql_file_delete fails case 4: for (i=0; i < npages; i++) { if (pages[i].ptr == 0) break; - pthread_mutex_destroy(&pages[i].lock); - pthread_cond_destroy(&pages[i].cond); + mysql_mutex_destroy(&pages[i].lock); + mysql_cond_destroy(&pages[i].cond); } case 3: my_free((uchar*)pages, MYF(0)); case 2: my_munmap((char*)data, (size_t)file_length); case 1: - my_close(fd, MYF(0)); + mysql_file_close(fd, MYF(0)); } if (inited>=5) // cannot do in the switch because of Windows - my_delete(logname, MYF(MY_WME)); + mysql_file_delete(key_file_tclog, logname, MYF(MY_WME)); inited=0; } @@ -5812,8 +6090,9 @@ int TC_LOG_BINLOG::open(const char *opt_name) DBUG_ASSERT(total_ha_2pc > 1); DBUG_ASSERT(opt_name && opt_name[0]); - pthread_mutex_init(&LOCK_prep_xids, MY_MUTEX_INIT_FAST); - pthread_cond_init (&COND_prep_xids, 0); + mysql_mutex_init(key_BINLOG_LOCK_prep_xids, + &LOCK_prep_xids, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_BINLOG_COND_prep_xids, &COND_prep_xids, 0); if (!my_b_inited(&index_file)) { @@ -5879,7 +6158,7 @@ int TC_LOG_BINLOG::open(const char *opt_name) delete ev; end_io_cache(&log); - my_close(file, MYF(MY_WME)); + mysql_file_close(file, MYF(MY_WME)); if (error) goto err; @@ -5893,8 +6172,8 @@ err: void TC_LOG_BINLOG::close() { DBUG_ASSERT(prepared_xids==0); - pthread_mutex_destroy(&LOCK_prep_xids); - pthread_cond_destroy (&COND_prep_xids); + mysql_mutex_destroy(&LOCK_prep_xids); + mysql_cond_destroy(&COND_prep_xids); } /** @@ -5910,24 +6189,25 @@ int TC_LOG_BINLOG::log_xid(THD *thd, my_xid xid) { DBUG_ENTER("TC_LOG_BINLOG::log"); Xid_log_event xle(thd, xid); - binlog_trx_data *trx_data= - (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton); + binlog_cache_mngr *cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); /* We always commit the entire transaction when writing an XID. Also note that the return value is inverted. */ - DBUG_RETURN(!binlog_end_trans(thd, trx_data, &xle, TRUE)); + DBUG_RETURN(!binlog_flush_stmt_cache(thd, cache_mngr) && + !binlog_flush_trx_cache(thd, cache_mngr, &xle)); } void TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid) { - pthread_mutex_lock(&LOCK_prep_xids); + mysql_mutex_lock(&LOCK_prep_xids); DBUG_ASSERT(prepared_xids > 0); if (--prepared_xids == 0) { DBUG_PRINT("info", ("prepared_xids=%lu", prepared_xids)); - pthread_cond_signal(&COND_prep_xids); + mysql_cond_signal(&COND_prep_xids); } - pthread_mutex_unlock(&LOCK_prep_xids); + mysql_mutex_unlock(&LOCK_prep_xids); rotate_and_purge(0); // as ::write() did not rotate } diff --git a/sql/log.h b/sql/log.h index 29a12f18a78..e9429067a34 100644 --- a/sql/log.h +++ b/sql/log.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 MySQL AB +/* Copyright (C) 2005 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,6 +20,10 @@ class Relay_log_info; class Format_description_log_event; +bool trans_has_updated_trans_table(const THD* thd); +bool stmt_has_updated_trans_table(const THD *thd); +bool use_trans_cache(const THD* thd, bool is_transactional); + /* Transaction Coordinator log - a base abstract class for two different implementations @@ -65,8 +69,8 @@ class TC_LOG_MMAP: public TC_LOG int size, free; // max and current number of free xid slots on the page int waiters; // number of waiters on condition PAGE_STATE state; // see above - pthread_mutex_t lock; // to access page data or control structure - pthread_cond_t cond; // to wait for a sync + mysql_mutex_t lock; // to access page data or control structure + mysql_cond_t cond; // to wait for a sync } PAGE; char logname[FN_REFLEN]; @@ -81,8 +85,8 @@ class TC_LOG_MMAP: public TC_LOG one has to use active->lock. Same for LOCK_pool and LOCK_sync */ - pthread_mutex_t LOCK_active, LOCK_pool, LOCK_sync; - pthread_cond_t COND_pool, COND_active; + mysql_mutex_t LOCK_active, LOCK_pool, LOCK_sync; + mysql_cond_t COND_pool, COND_active; public: TC_LOG_MMAP(): inited(0) {} @@ -121,23 +125,40 @@ extern TC_LOG_DUMMY tc_log_dummy; #define LOG_CLOSE_TO_BE_OPENED 2 #define LOG_CLOSE_STOP_EVENT 4 +/* + Maximum unique log filename extension. + Note: setting to 0x7FFFFFFF due to atol windows + overflow/truncate. + */ +#define MAX_LOG_UNIQUE_FN_EXT 0x7FFFFFFF + +/* + Number of warnings that will be printed to error log + before extension number is exhausted. +*/ +#define LOG_WARN_UNIQUE_FN_EXT_LEFT 1000 + class Relay_log_info; +#ifdef HAVE_PSI_INTERFACE +extern PSI_mutex_key key_LOG_INFO_lock; +#endif + typedef struct st_log_info { char log_file_name[FN_REFLEN]; my_off_t index_file_offset, index_file_start_offset; my_off_t pos; bool fatal; // if the purge happens to give us a negative offset - pthread_mutex_t lock; + mysql_mutex_t lock; st_log_info() : index_file_offset(0), index_file_start_offset(0), pos(0), fatal(0) { log_file_name[0] = '\0'; - pthread_mutex_init(&lock, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOG_INFO_lock, &lock, MY_MUTEX_INIT_FAST); } - ~st_log_info() { pthread_mutex_destroy(&lock);} + ~st_log_info() { mysql_mutex_destroy(&lock);} } LOG_INFO; /* @@ -185,7 +206,7 @@ public: int generate_new_name(char *new_name, const char *log_name); protected: /* LOCK_log is inited by init_pthread_objects() */ - pthread_mutex_t LOCK_log; + mysql_mutex_t LOCK_log; char *name; char log_file_name[FN_REFLEN]; char time_buff[20], db[NAME_LEN + 1]; @@ -231,10 +252,10 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG { private: /* LOCK_log and LOCK_index are inited by init_pthread_objects() */ - pthread_mutex_t LOCK_index; - pthread_mutex_t LOCK_prep_xids; - pthread_cond_t COND_prep_xids; - pthread_cond_t update_cond; + mysql_mutex_t LOCK_index; + mysql_mutex_t LOCK_prep_xids; + mysql_cond_t COND_prep_xids; + mysql_cond_t update_cond; ulonglong bytes_written; IO_CACHE index_file; char index_file_name[FN_REFLEN]; @@ -334,8 +355,9 @@ public: ulonglong table_map_version() const { return m_table_map_version; } void update_table_map_version() { ++m_table_map_version; } - int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event); - int remove_pending_rows_event(THD *thd); + int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event, + bool is_transactional); + int remove_pending_rows_event(THD *thd, bool is_transactional); #endif /* !defined(MYSQL_CLIENT) */ void reset_bytes_written() @@ -374,7 +396,7 @@ public: /* Use this to start writing a new log file */ void new_file(); - bool write(Log_event* event_info); // binary log write + bool write(Log_event* event_info); bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event, bool incident); bool write_incident(THD *thd, bool lock); @@ -439,11 +461,11 @@ public: inline char* get_index_fname() { return index_file_name;} inline char* get_log_fname() { return log_file_name; } inline char* get_name() { return name; } - inline pthread_mutex_t* get_log_lock() { return &LOCK_log; } + inline mysql_mutex_t* get_log_lock() { return &LOCK_log; } inline IO_CACHE* get_log_file() { return &log_file; } - inline void lock_index() { pthread_mutex_lock(&LOCK_index);} - inline void unlock_index() { pthread_mutex_unlock(&LOCK_index);} + inline void lock_index() { mysql_mutex_lock(&LOCK_index);} + inline void unlock_index() { mysql_mutex_unlock(&LOCK_index);} inline IO_CACHE *get_index_file() { return &index_file;} inline uint32 get_open_count() { return open_count; } }; @@ -538,7 +560,7 @@ public: /* Class which manages slow, general and error log event handlers */ class LOGGER { - rw_lock_t LOCK_logger; + mysql_rwlock_t LOCK_logger; /* flag to check whether logger mutex is initialized */ uint inited; @@ -558,9 +580,9 @@ public: LOGGER() : inited(0), table_log_handler(NULL), file_log_handler(NULL), is_log_tables_initialized(FALSE) {} - void lock_shared() { rw_rdlock(&LOCK_logger); } - void lock_exclusive() { rw_wrlock(&LOCK_logger); } - void unlock() { rw_unlock(&LOCK_logger); } + void lock_shared() { mysql_rwlock_rdlock(&LOCK_logger); } + void lock_exclusive() { mysql_rwlock_wrlock(&LOCK_logger); } + void unlock() { mysql_rwlock_unlock(&LOCK_logger); } bool is_log_table_enabled(uint log_table_type); bool log_command(THD *thd, enum enum_server_command command); @@ -573,6 +595,8 @@ public: void init_base(); void init_log_tables(); bool flush_logs(THD *thd); + bool flush_slow_log(); + bool flush_general_log(); /* Perform basic logger cleanup. this will leave e.g. error log open. */ void cleanup_base(); /* Free memory. Nothing could be logged after this function is called */ @@ -595,13 +619,13 @@ public: void init_general_log(uint general_log_printer); void deactivate_log_handler(THD* thd, uint log_type); bool activate_log_handler(THD* thd, uint log_type); - MYSQL_QUERY_LOG *get_slow_log_file_handler() + MYSQL_QUERY_LOG *get_slow_log_file_handler() const { if (file_log_handler) return file_log_handler->get_mysql_slow_log(); return NULL; } - MYSQL_QUERY_LOG *get_log_file_handler() + MYSQL_QUERY_LOG *get_log_file_handler() const { if (file_log_handler) return file_log_handler->get_mysql_log(); @@ -610,22 +634,14 @@ public: }; enum enum_binlog_format { - /* - statement-based except for cases where only row-based can work (UUID() - etc): - */ - BINLOG_FORMAT_MIXED= 0, - BINLOG_FORMAT_STMT= 1, // statement-based - BINLOG_FORMAT_ROW= 2, // row_based -/* - This value is last, after the end of binlog_format_typelib: it has no - corresponding cell in this typelib. We use this value to be able to know if - the user has explicitely specified a binlog format at startup or not. -*/ - BINLOG_FORMAT_UNSPEC= 3 + BINLOG_FORMAT_MIXED= 0, ///< statement if safe, otherwise row - autodetected + BINLOG_FORMAT_STMT= 1, ///< statement-based + BINLOG_FORMAT_ROW= 2, ///< row-based + BINLOG_FORMAT_UNSPEC=3 ///< thd_binlog_format() returns it when binlog is closed }; extern TYPELIB binlog_format_typelib; int query_error_code(THD *thd, bool not_killed); +uint purge_log_get_error_code(int res); #endif /* LOG_H */ diff --git a/sql/log_event.cc b/sql/log_event.cc index b6c84dd95f4..be167451cb3 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,7 +29,6 @@ #include "rpl_rli.h" #include "rpl_mi.h" #include "rpl_filter.h" -#include "rpl_utility.h" #include "rpl_record.h" #include <my_dir.h> @@ -37,6 +36,7 @@ #include <base64.h> #include <my_bitmap.h> +#include "rpl_utility.h" #define log_cs &my_charset_latin1 @@ -497,7 +497,7 @@ static void cleanup_load_tmpdir() if (is_prefix(file->name, prefbuf)) { fn_format(fname,file->name,slave_load_tmpdir,"",MY_UNPACK_FILENAME); - my_delete(fname, MYF(0)); + mysql_file_delete(key_file_misc, fname, MYF(0)); } } @@ -665,10 +665,11 @@ Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans) { server_id= thd->server_id; when= thd->start_time; - cache_stmt= using_trans; + cache_type= (using_trans || stmt_has_updated_trans_table(thd) + ? Log_event::EVENT_TRANSACTIONAL_CACHE : + Log_event::EVENT_STMT_CACHE); } - /** This minimal constructor is for when you are not even sure that there is a valid THD. For example in the server when we are shutting down or @@ -677,8 +678,8 @@ Log_event::Log_event(THD* thd_arg, uint16 flags_arg, bool using_trans) */ Log_event::Log_event() - :temp_buf(0), exec_time(0), flags(0), cache_stmt(0), - thd(0) + :temp_buf(0), exec_time(0), flags(0), + cache_type(Log_event::EVENT_INVALID_CACHE), thd(0) { server_id= ::server_id; /* @@ -697,7 +698,7 @@ Log_event::Log_event() Log_event::Log_event(const char* buf, const Format_description_log_event* description_event) - :temp_buf(0), cache_stmt(0) + :temp_buf(0), cache_type(Log_event::EVENT_INVALID_CACHE) { #ifndef MYSQL_CLIENT thd = 0; @@ -967,7 +968,7 @@ bool Log_event::write_header(IO_CACHE* file, ulong event_data_length) */ int Log_event::read_log_event(IO_CACHE* file, String* packet, - pthread_mutex_t* log_lock) + mysql_mutex_t* log_lock) { ulong data_len; int result=0; @@ -975,7 +976,7 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet, DBUG_ENTER("Log_event::read_log_event"); if (log_lock) - pthread_mutex_lock(log_lock); + mysql_mutex_lock(log_lock); if (my_b_read(file, (uchar*) buf, sizeof(buf))) { /* @@ -1033,14 +1034,14 @@ int Log_event::read_log_event(IO_CACHE* file, String* packet, end: if (log_lock) - pthread_mutex_unlock(log_lock); + mysql_mutex_unlock(log_lock); DBUG_RETURN(result); } #endif /* !MYSQL_CLIENT */ #ifndef MYSQL_CLIENT -#define UNLOCK_MUTEX if (log_lock) pthread_mutex_unlock(log_lock); -#define LOCK_MUTEX if (log_lock) pthread_mutex_lock(log_lock); +#define UNLOCK_MUTEX if (log_lock) mysql_mutex_unlock(log_lock); +#define LOCK_MUTEX if (log_lock) mysql_mutex_lock(log_lock); #else #define UNLOCK_MUTEX #define LOCK_MUTEX @@ -1052,7 +1053,7 @@ end: Allocates memory; The caller is responsible for clean-up. */ Log_event* Log_event::read_log_event(IO_CACHE* file, - pthread_mutex_t* log_lock, + mysql_mutex_t* log_lock, const Format_description_log_event *description_event) #else @@ -1200,15 +1201,11 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len, */ if (description_event->event_type_permutation) { -#ifndef DBUG_OFF - int new_event_type= - description_event->event_type_permutation[event_type]; - DBUG_PRINT("info", - ("converting event type %d to %d (%s)", - event_type, new_event_type, - get_type_str((Log_event_type)new_event_type))); -#endif - event_type= description_event->event_type_permutation[event_type]; + int new_event_type= description_event->event_type_permutation[event_type]; + DBUG_PRINT("info", ("converting event type %d to %d (%s)", + event_type, new_event_type, + get_type_str((Log_event_type)new_event_type))); + event_type= new_event_type; } switch(event_type) { @@ -1571,37 +1568,14 @@ log_event_print_value(IO_CACHE *file, const uchar *ptr, /* a long CHAR() field: see #37426 */ length= byte1 | (((byte0 & 0x30) ^ 0x30) << 4); type= byte0 | 0x30; - goto beg; - } - - switch (byte0) - { - case MYSQL_TYPE_SET: - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_STRING: - type= byte0; - length= byte1; - break; - - default: - - { - char tmp[5]; - my_snprintf(tmp, sizeof(tmp), "%04X", meta); - my_b_printf(file, - "!! Don't know how to handle column type=%d meta=%d (%s)", - type, meta, tmp); - return 0; - } } + else + length = meta & 0xFF; } else length= meta; } - -beg: - switch (type) { case MYSQL_TYPE_LONG: { @@ -1738,6 +1712,33 @@ beg: return 3; } + case MYSQL_TYPE_NEWDATE: + { + uint32 tmp= uint3korr(ptr); + int part; + char buf[10]; + char *pos= &buf[10]; + + /* Copied from field.cc */ + *pos--=0; // End NULL + part=(int) (tmp & 31); + *pos--= (char) ('0'+part%10); + *pos--= (char) ('0'+part/10); + *pos--= ':'; + part=(int) (tmp >> 5 & 15); + *pos--= (char) ('0'+part%10); + *pos--= (char) ('0'+part/10); + *pos--= ':'; + part=(int) (tmp >> 9); + *pos--= (char) ('0'+part%10); part/=10; + *pos--= (char) ('0'+part%10); part/=10; + *pos--= (char) ('0'+part%10); part/=10; + *pos= (char) ('0'+part); + my_b_printf(file , "'%s'", buf); + my_snprintf(typestr, typestr_length, "DATE"); + return 3; + } + case MYSQL_TYPE_DATE: { uint i32= uint3korr(ptr); @@ -1756,7 +1757,7 @@ beg: } case MYSQL_TYPE_ENUM: - switch (length) { + switch (meta & 0xFF) { case 1: my_b_printf(file, "%d", (int) *ptr); my_snprintf(typestr, typestr_length, "ENUM(1 byte)"); @@ -1769,15 +1770,15 @@ beg: return 2; } default: - my_b_printf(file, "!! Unknown ENUM packlen=%d", length); + my_b_printf(file, "!! Unknown ENUM packlen=%d", meta & 0xFF); return 0; } break; case MYSQL_TYPE_SET: - my_b_write_bit(file, ptr , length * 8); - my_snprintf(typestr, typestr_length, "SET(%d bytes)", length); - return length; + my_b_write_bit(file, ptr , (meta & 0xFF) * 8); + my_snprintf(typestr, typestr_length, "SET(%d bytes)", meta & 0xFF); + return meta & 0xFF; case MYSQL_TYPE_BLOB: switch (meta) { @@ -2369,7 +2370,7 @@ Query_log_event::Query_log_event() */ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length, bool using_trans, - bool suppress_use, int errcode) + bool direct, bool suppress_use, int errcode) :Log_event(thd_arg, (thd_arg->thread_specific_used ? LOG_EVENT_THREAD_SPECIFIC_F : @@ -2428,7 +2429,7 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, the autocommit flag as written by the master to the binlog. This behavior may change after WL#4162 has been implemented. */ - flags2= (uint32) (thd_arg->options & + flags2= (uint32) (thd_arg->variables.option_bits & (OPTIONS_WRITTEN_TO_BIN_LOG & ~OPTION_NOT_AUTOCOMMIT)); DBUG_ASSERT(thd_arg->variables.character_set_client->number < 256*256); DBUG_ASSERT(thd_arg->variables.collation_connection->number < 256*256); @@ -2449,6 +2450,95 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, } else time_zone_len= 0; + + /* + In what follows, we decide whether to write to the binary log or to use a + cache. + */ + LEX *lex= thd->lex; + bool implicit_commit= FALSE; + cache_type= Log_event::EVENT_INVALID_CACHE; + switch (lex->sql_command) + { + case SQLCOM_ALTER_DB: + case SQLCOM_CREATE_FUNCTION: + case SQLCOM_DROP_FUNCTION: + case SQLCOM_DROP_PROCEDURE: + case SQLCOM_INSTALL_PLUGIN: + case SQLCOM_UNINSTALL_PLUGIN: + case SQLCOM_ALTER_TABLESPACE: + implicit_commit= TRUE; + break; + case SQLCOM_DROP_TABLE: + implicit_commit= !(lex->drop_temporary && thd->in_multi_stmt_transaction()); + break; + case SQLCOM_ALTER_TABLE: + case SQLCOM_CREATE_TABLE: + implicit_commit= !((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) && + thd->in_multi_stmt_transaction()) && + !(lex->select_lex.item_list.elements && + thd->is_current_stmt_binlog_format_row()); + break; + case SQLCOM_SET_OPTION: + implicit_commit= (lex->autocommit ? TRUE : FALSE); + break; + /* + Replace what follows after CF_AUTO_COMMIT_TRANS is backported by: + + default: + implicit_commit= ((sql_command_flags[lex->sql_command] & + CF_AUTO_COMMIT_TRANS)); + break; + */ + case SQLCOM_CREATE_INDEX: + case SQLCOM_TRUNCATE: + case SQLCOM_CREATE_DB: + case SQLCOM_DROP_DB: + case SQLCOM_ALTER_DB_UPGRADE: + case SQLCOM_RENAME_TABLE: + case SQLCOM_DROP_INDEX: + case SQLCOM_CREATE_VIEW: + case SQLCOM_DROP_VIEW: + case SQLCOM_CREATE_TRIGGER: + case SQLCOM_DROP_TRIGGER: + case SQLCOM_CREATE_EVENT: + case SQLCOM_ALTER_EVENT: + case SQLCOM_DROP_EVENT: + case SQLCOM_REPAIR: + case SQLCOM_OPTIMIZE: + case SQLCOM_ANALYZE: + case SQLCOM_CREATE_USER: + case SQLCOM_DROP_USER: + case SQLCOM_RENAME_USER: + case SQLCOM_REVOKE_ALL: + case SQLCOM_REVOKE: + case SQLCOM_GRANT: + case SQLCOM_CREATE_PROCEDURE: + case SQLCOM_CREATE_SPFUNCTION: + case SQLCOM_ALTER_PROCEDURE: + case SQLCOM_ALTER_FUNCTION: + case SQLCOM_ASSIGN_TO_KEYCACHE: + case SQLCOM_PRELOAD_KEYS: + case SQLCOM_FLUSH: + case SQLCOM_CHECK: + implicit_commit= TRUE; + break; + default: + implicit_commit= FALSE; + break; + } + + if (implicit_commit || direct) + { + cache_type= Log_event::EVENT_NO_CACHE; + } + else + { + cache_type= (using_trans || stmt_has_updated_trans_table(thd) + ? Log_event::EVENT_TRANSACTIONAL_CACHE : + Log_event::EVENT_STMT_CACHE); + } + DBUG_ASSERT(cache_type != Log_event::EVENT_INVALID_CACHE); DBUG_PRINT("info",("Query_log_event has flags2: %lu sql_mode: %lu", (ulong) flags2, sql_mode)); } @@ -3086,10 +3176,7 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli, rpl_filter->db_ok(thd->db)) { thd->set_time((time_t)when); - thd->set_query((char*)query_arg, q_len_arg); - VOID(pthread_mutex_lock(&LOCK_thread_count)); - thd->query_id = next_query_id(); - VOID(pthread_mutex_unlock(&LOCK_thread_count)); + thd->set_query_and_id((char*)query_arg, q_len_arg, next_query_id()); thd->variables.pseudo_thread_id= thread_id; // for temp tables DBUG_PRINT("query",("%s", thd->query())); @@ -3098,13 +3185,13 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli, { if (flags2_inited) /* - all bits of thd->options which are 1 in OPTIONS_WRITTEN_TO_BIN_LOG + all bits of thd->variables.option_bits which are 1 in OPTIONS_WRITTEN_TO_BIN_LOG must take their value from flags2. */ - thd->options= flags2|(thd->options & ~OPTIONS_WRITTEN_TO_BIN_LOG); + thd->variables.option_bits= flags2|(thd->variables.option_bits & ~OPTIONS_WRITTEN_TO_BIN_LOG); /* else, we are in a 3.23/4.0 binlog; we previously received a - Rotate_log_event which reset thd->options and sql_mode etc, so + Rotate_log_event which reset thd->variables.option_bits and sql_mode etc, so nothing to do. */ /* @@ -3392,13 +3479,13 @@ Query_log_event::do_shall_skip(Relay_log_info *rli) { if (strcmp("BEGIN", query) == 0) { - thd->options|= OPTION_BEGIN; + thd->variables.option_bits|= OPTION_BEGIN; DBUG_RETURN(Log_event::continue_group(rli)); } if (strcmp("COMMIT", query) == 0 || strcmp("ROLLBACK", query) == 0) { - thd->options&= ~OPTION_BEGIN; + thd->variables.option_bits&= ~OPTION_BEGIN; DBUG_RETURN(Log_event::EVENT_SKIP_COUNT); } } @@ -3654,8 +3741,7 @@ Format_description_log_event(uint8 binlog_ver, const char* server_ver) #ifndef DBUG_OFF // Allows us to sanity-check that all events initialized their // events (see the end of this 'if' block). - memset(post_header_len, 255, - number_of_event_types*sizeof(uint8)); + memset(post_header_len, 255, number_of_event_types*sizeof(uint8)); #endif /* Note: all event types must explicitly fill in their lengths here. */ @@ -3937,7 +4023,6 @@ int Format_description_log_event::do_apply_event(Relay_log_info const *rli) int ret= 0; DBUG_ENTER("Format_description_log_event::do_apply_event"); -#ifdef USING_TRANSACTIONS /* As a transaction NEVER spans on 2 or more binlogs: if we have an active transaction at this point, the master died @@ -3959,7 +4044,7 @@ int Format_description_log_event::do_apply_event(Relay_log_info const *rli) "its binary log, thus rolled back too."); const_cast<Relay_log_info*>(rli)->cleanup_context(thd, 1); } -#endif + /* If this event comes from ourselves, there is no cleaning task to perform, we don't call Start_log_event_v3::do_apply_event() @@ -4628,9 +4713,7 @@ int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli, if (rpl_filter->db_ok(thd->db)) { thd->set_time((time_t)when); - VOID(pthread_mutex_lock(&LOCK_thread_count)); - thd->query_id = next_query_id(); - VOID(pthread_mutex_unlock(&LOCK_thread_count)); + thd->set_query_id(next_query_id()); thd->warning_info->opt_clear_warning_info(thd->query_id); TABLE_LIST tables; @@ -4985,7 +5068,7 @@ int Rotate_log_event::do_update_pos(Relay_log_info *rli) !is_relay_log_event() && !rli->is_in_group()) { - pthread_mutex_lock(&rli->data_lock); + mysql_mutex_lock(&rli->data_lock); DBUG_PRINT("info", ("old group_master_log_name: '%s' " "old group_master_log_pos: %lu", rli->group_master_log_name, @@ -4997,11 +5080,11 @@ int Rotate_log_event::do_update_pos(Relay_log_info *rli) "new group_master_log_pos: %lu", rli->group_master_log_name, (ulong) rli->group_master_log_pos)); - pthread_mutex_unlock(&rli->data_lock); + mysql_mutex_unlock(&rli->data_lock); flush_relay_log_info(rli); /* - Reset thd->options and sql_mode etc, because this could be the signal of + Reset thd->variables.option_bits and sql_mode etc, because this could be the signal of a master's downgrade from 5.0 to 4.0. However, no need to reset description_event_for_exec: indeed, if the next master is 5.0 (even 5.0.1) we will soon get a Format_desc; if the next @@ -5371,7 +5454,7 @@ Xid_log_event::do_shall_skip(Relay_log_info *rli) { DBUG_ENTER("Xid_log_event::do_shall_skip"); if (rli->slave_skip_counter > 0) { - thd->options&= ~OPTION_BEGIN; + thd->variables.option_bits&= ~OPTION_BEGIN; DBUG_RETURN(Log_event::EVENT_SKIP_COUNT); } DBUG_RETURN(Log_event::do_shall_skip(rli)); @@ -5403,11 +5486,11 @@ void User_var_log_event::pack_info(Protocol* protocol) case REAL_RESULT: double real_val; float8get(real_val, val); - if (!(buf= (char*) my_malloc(val_offset + FLOATING_POINT_BUFFER, + if (!(buf= (char*) my_malloc(val_offset + MY_GCVT_MAX_FIELD_WIDTH + 1, MYF(MY_WME)))) return; - event_len+= my_sprintf(buf + val_offset, - (buf + val_offset, "%.14g", real_val)); + event_len+= my_gcvt(real_val, MY_GCVT_ARG_DOUBLE, MY_GCVT_MAX_FIELD_WIDTH, + buf + val_offset, NULL); break; case INT_RESULT: if (!(buf= (char*) my_malloc(val_offset + 22, MYF(MY_WME)))) @@ -5818,8 +5901,8 @@ Slave_log_event::Slave_log_event(THD* thd_arg, Master_info* mi = rli->mi; // TODO: re-write this better without holding both locks at the same time - pthread_mutex_lock(&mi->data_lock); - pthread_mutex_lock(&rli->data_lock); + mysql_mutex_lock(&mi->data_lock); + mysql_mutex_lock(&rli->data_lock); master_host_len = strlen(mi->host); master_log_len = strlen(rli->group_master_log_name); // on OOM, just do not initialize the structure and print the error @@ -5837,8 +5920,8 @@ Slave_log_event::Slave_log_event(THD* thd_arg, } else sql_print_error("Out of memory while recording slave event"); - pthread_mutex_unlock(&rli->data_lock); - pthread_mutex_unlock(&mi->data_lock); + mysql_mutex_unlock(&rli->data_lock); + mysql_mutex_unlock(&mi->data_lock); DBUG_VOID_RETURN; } #endif /* !MYSQL_CLIENT */ @@ -5972,7 +6055,7 @@ int Stop_log_event::do_update_pos(Relay_log_info *rli) could give false triggers in MASTER_POS_WAIT() that we have reached the target position when in fact we have not. */ - if (thd->options & OPTION_BEGIN) + if (thd->variables.option_bits & OPTION_BEGIN) rli->inc_event_relay_log_pos(); else { @@ -6195,10 +6278,12 @@ int Create_file_log_event::do_apply_event(Relay_log_info const *rli) fname_buf= strmov(proc_info, "Making temp file "); ext= slave_load_file_stem(fname_buf, file_id, server_id, ".info"); thd_proc_info(thd, proc_info); - my_delete(fname_buf, MYF(0)); // old copy may exist already - if ((fd= my_create(fname_buf, CREATE_MODE, - O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW, - MYF(MY_WME))) < 0 || + /* old copy may exist already */ + mysql_file_delete(key_file_log_event_info, fname_buf, MYF(0)); + if ((fd= mysql_file_create(key_file_log_event_info, + fname_buf, CREATE_MODE, + O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW, + MYF(MY_WME))) < 0 || init_io_cache(&file, fd, IO_SIZE, WRITE_CACHE, (my_off_t)0, 0, MYF(MY_WME|MY_NABP))) { @@ -6220,20 +6305,22 @@ int Create_file_log_event::do_apply_event(Relay_log_info const *rli) goto err; } end_io_cache(&file); - my_close(fd, MYF(0)); + mysql_file_close(fd, MYF(0)); // fname_buf now already has .data, not .info, because we did our trick - my_delete(fname_buf, MYF(0)); // old copy may exist already - if ((fd= my_create(fname_buf, CREATE_MODE, - O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW, - MYF(MY_WME))) < 0) + /* old copy may exist already */ + mysql_file_delete(key_file_log_event_data, fname_buf, MYF(0)); + if ((fd= mysql_file_create(key_file_log_event_data, + fname_buf, CREATE_MODE, + O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW, + MYF(MY_WME))) < 0) { rli->report(ERROR_LEVEL, my_errno, "Error in Create_file event: could not open file '%s'", fname_buf); goto err; } - if (my_write(fd, (uchar*) block, block_len, MYF(MY_WME+MY_NABP))) + if (mysql_file_write(fd, (uchar*) block, block_len, MYF(MY_WME+MY_NABP))) { rli->report(ERROR_LEVEL, my_errno, "Error in Create_file event: write to '%s' failed", @@ -6246,7 +6333,7 @@ err: if (error) end_io_cache(&file); if (fd >= 0) - my_close(fd, MYF(0)); + mysql_file_close(fd, MYF(0)); thd_proc_info(thd, 0); return error != 0; } @@ -6378,10 +6465,12 @@ int Append_block_log_event::do_apply_event(Relay_log_info const *rli) */ lex_start(thd); mysql_reset_thd_for_next_command(thd); - my_delete(fname, MYF(0)); // old copy may exist already - if ((fd= my_create(fname, CREATE_MODE, - O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW, - MYF(MY_WME))) < 0) + /* old copy may exist already */ + mysql_file_delete(key_file_log_event_data, fname, MYF(0)); + if ((fd= mysql_file_create(key_file_log_event_data, + fname, CREATE_MODE, + O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW, + MYF(MY_WME))) < 0) { rli->report(ERROR_LEVEL, my_errno, "Error in %s event: could not create file '%s'", @@ -6389,8 +6478,10 @@ int Append_block_log_event::do_apply_event(Relay_log_info const *rli) goto err; } } - else if ((fd = my_open(fname, O_WRONLY | O_APPEND | O_BINARY | O_NOFOLLOW, - MYF(MY_WME))) < 0) + else if ((fd= mysql_file_open(key_file_log_event_data, + fname, + O_WRONLY | O_APPEND | O_BINARY | O_NOFOLLOW, + MYF(MY_WME))) < 0) { rli->report(ERROR_LEVEL, my_errno, "Error in %s event: could not open file '%s'", @@ -6398,10 +6489,14 @@ int Append_block_log_event::do_apply_event(Relay_log_info const *rli) goto err; } - DBUG_EXECUTE_IF("remove_slave_load_file_before_write", - my_close(fd,MYF(0)); fd= -1; my_delete(fname, MYF(0));); + DBUG_EXECUTE_IF("remove_slave_load_file_before_write", + { + mysql_file_close(fd, MYF(0)); + fd= -1; + mysql_file_delete(0, fname, MYF(0)); + }); - if (my_write(fd, (uchar*) block, block_len, MYF(MY_WME+MY_NABP))) + if (mysql_file_write(fd, (uchar*) block, block_len, MYF(MY_WME+MY_NABP))) { rli->report(ERROR_LEVEL, my_errno, "Error in %s event: write to '%s' failed", @@ -6412,7 +6507,7 @@ int Append_block_log_event::do_apply_event(Relay_log_info const *rli) err: if (fd >= 0) - my_close(fd, MYF(0)); + mysql_file_close(fd, MYF(0)); thd_proc_info(thd, 0); DBUG_RETURN(error); } @@ -6506,9 +6601,9 @@ int Delete_file_log_event::do_apply_event(Relay_log_info const *rli) { char fname[FN_REFLEN+10]; char *ext= slave_load_file_stem(fname, file_id, server_id, ".data"); - (void) my_delete(fname, MYF(MY_WME)); + mysql_file_delete(key_file_log_event_data, fname, MYF(MY_WME)); strmov(ext, ".info"); - (void) my_delete(fname, MYF(MY_WME)); + mysql_file_delete(key_file_log_event_info, fname, MYF(MY_WME)); return 0; } #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */ @@ -6609,8 +6704,9 @@ int Execute_load_log_event::do_apply_event(Relay_log_info const *rli) Load_log_event *lev= 0; ext= slave_load_file_stem(fname, file_id, server_id, ".info"); - if ((fd = my_open(fname, O_RDONLY | O_BINARY | O_NOFOLLOW, - MYF(MY_WME))) < 0 || + if ((fd= mysql_file_open(key_file_log_event_info, + fname, O_RDONLY | O_BINARY | O_NOFOLLOW, + MYF(MY_WME))) < 0 || init_io_cache(&file, fd, IO_SIZE, READ_CACHE, (my_off_t)0, 0, MYF(MY_WME|MY_NABP))) { @@ -6620,7 +6716,7 @@ int Execute_load_log_event::do_apply_event(Relay_log_info const *rli) goto err; } if (!(lev = (Load_log_event*)Log_event::read_log_event(&file, - (pthread_mutex_t*)0, + (mysql_mutex_t*)0, rli->relay_log.description_event_for_exec)) || lev->get_type_code() != NEW_LOAD_EVENT) { @@ -6660,24 +6756,24 @@ int Execute_load_log_event::do_apply_event(Relay_log_info const *rli) } /* We have an open file descriptor to the .info file; we need to close it - or Windows will refuse to delete the file in my_delete(). + or Windows will refuse to delete the file in mysql_file_delete(). */ if (fd >= 0) { - my_close(fd, MYF(0)); + mysql_file_close(fd, MYF(0)); end_io_cache(&file); fd= -1; } - (void) my_delete(fname, MYF(MY_WME)); + mysql_file_delete(key_file_log_event_info, fname, MYF(MY_WME)); memcpy(ext, ".data", 6); - (void) my_delete(fname, MYF(MY_WME)); + mysql_file_delete(key_file_log_event_data, fname, MYF(MY_WME)); error = 0; err: delete lev; if (fd >= 0) { - my_close(fd, MYF(0)); + mysql_file_close(fd, MYF(0)); end_io_cache(&file); } return error; @@ -6742,9 +6838,9 @@ Execute_load_query_log_event(THD *thd_arg, const char* query_arg, ulong query_length_arg, uint fn_pos_start_arg, uint fn_pos_end_arg, enum_load_dup_handling dup_handling_arg, - bool using_trans, bool suppress_use, + bool using_trans, bool direct, bool suppress_use, int errcode): - Query_log_event(thd_arg, query_arg, query_length_arg, using_trans, + Query_log_event(thd_arg, query_arg, query_length_arg, using_trans, direct, suppress_use, errcode), file_id(thd_arg->file_id), fn_pos_start(fn_pos_start_arg), fn_pos_end(fn_pos_end_arg), dup_handling(dup_handling_arg) @@ -6916,7 +7012,7 @@ Execute_load_query_log_event::do_apply_event(Relay_log_info const *rli) file so that we can re-execute this event at START SLAVE. */ if (!error) - (void) my_delete(fname, MYF(MY_WME)); + mysql_file_delete(key_file_log_event_data, fname, MYF(MY_WME)); my_free(buf, MYF(MY_ALLOW_ZERO_PTR)); return error; @@ -7039,9 +7135,9 @@ Rows_log_event::Rows_log_event(THD *thd_arg, TABLE *tbl_arg, ulong tid, DBUG_ASSERT((tbl_arg && tbl_arg->s && tid != ~0UL) || (!tbl_arg && !cols && tid == ~0UL)); - if (thd_arg->options & OPTION_NO_FOREIGN_KEY_CHECKS) + if (thd_arg->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS) set_flags(NO_FOREIGN_KEY_CHECKS_F); - if (thd_arg->options & OPTION_RELAXED_UNIQUE_CHECKS) + if (thd_arg->variables.option_bits & OPTION_RELAXED_UNIQUE_CHECKS) set_flags(RELAXED_UNIQUE_CHECKS_F); /* if bitmap_init fails, caught in is_valid() */ if (likely(!bitmap_init(&m_cols, @@ -7313,7 +7409,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) We also call the mysql_reset_thd_for_next_command(), since this is the logical start of the next "statement". Note that this - call might reset the value of current_stmt_binlog_row_based, so + call might reset the value of current_stmt_binlog_format, so we need to do any changes to that value after this function. */ lex_start(thd); @@ -7325,16 +7421,12 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) */ thd->transaction.stmt.modified_non_trans_table= FALSE; /* - Check if the slave is set to use SBR. If so, it should switch - to using RBR until the end of the "statement", i.e., next - STMT_END_F or next error. + This is a row injection, so we flag the "statement" as + such. Note that this code is called both when the slave does row + injections and when the BINLOG statement is used to do row + injections. */ - if (!thd->current_stmt_binlog_row_based && - mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG)) - { - thd->set_current_stmt_binlog_row_based(); - } - + thd->lex->set_stmt_row_injection(); /* There are a few flags that are replicated with each row event. @@ -7342,16 +7434,16 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) the event. */ if (get_flags(NO_FOREIGN_KEY_CHECKS_F)) - thd->options|= OPTION_NO_FOREIGN_KEY_CHECKS; + thd->variables.option_bits|= OPTION_NO_FOREIGN_KEY_CHECKS; else - thd->options&= ~OPTION_NO_FOREIGN_KEY_CHECKS; + thd->variables.option_bits&= ~OPTION_NO_FOREIGN_KEY_CHECKS; if (get_flags(RELAXED_UNIQUE_CHECKS_F)) - thd->options|= OPTION_RELAXED_UNIQUE_CHECKS; + thd->variables.option_bits|= OPTION_RELAXED_UNIQUE_CHECKS; else - thd->options&= ~OPTION_RELAXED_UNIQUE_CHECKS; + thd->variables.option_bits&= ~OPTION_RELAXED_UNIQUE_CHECKS; /* A small test to verify that objects have consistent types */ - DBUG_ASSERT(sizeof(thd->options) == sizeof(OPTION_RELAXED_UNIQUE_CHECKS)); + DBUG_ASSERT(sizeof(thd->variables.option_bits) == sizeof(OPTION_RELAXED_UNIQUE_CHECKS)); if (simple_open_n_lock_tables(thd, rli->tables_to_lock)) { @@ -7383,11 +7475,18 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) */ { + DBUG_PRINT("debug", ("Checking compability of tables to lock - tables_to_lock: %p", + rli->tables_to_lock)); RPL_TABLE_LIST *ptr= rli->tables_to_lock; for ( ; ptr ; ptr= static_cast<RPL_TABLE_LIST*>(ptr->next_global)) { - if (ptr->m_tabledef.compatible_with(rli, ptr->table)) + TABLE *conv_table; + if (!ptr->m_tabledef.compatible_with(thd, const_cast<Relay_log_info*>(rli), + ptr->table, &conv_table)) { + DBUG_PRINT("debug", ("Table: %s.%s is not compatible with master", + ptr->table->s->db.str, + ptr->table->s->table_name.str)); /* We should not honour --slave-skip-errors at this point as we are having severe errors which should not be skiped. @@ -7398,12 +7497,17 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) const_cast<Relay_log_info*>(rli)->clear_tables_to_lock(); DBUG_RETURN(ERR_BAD_TABLE_DEF); } + DBUG_PRINT("debug", ("Table: %s.%s is compatible with master" + " - conv_table: %p", + ptr->table->s->db.str, + ptr->table->s->table_name.str, conv_table)); + ptr->m_conv_table= conv_table; } } /* - ... and then we add all the tables to the table map and remove - them from tables to lock. + ... and then we add all the tables to the table map and but keep + them in the tables to lock list. We also invalidate the query cache for all the tables, since they will now be changed. @@ -7505,8 +7609,7 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) { int actual_error= convert_handler_error(error, thd, table); bool idempotent_error= (idempotent_error_code(error) && - ((bit_is_set(slave_exec_mode, - SLAVE_EXEC_MODE_IDEMPOTENT)) == 1)); + (slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT)); bool ignored_error= (idempotent_error == 0 ? ignored_error_code(actual_error) : 0); @@ -7571,10 +7674,10 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) error= 0; } - if (!cache_stmt) + if (!use_trans_cache()) { DBUG_PRINT("info", ("Marked that we need to keep log")); - thd->options|= OPTION_KEEP_LOG; + thd->variables.option_bits|= OPTION_KEEP_LOG; } } // if (table) @@ -7590,7 +7693,14 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) slave_rows_error_report(ERROR_LEVEL, error, rli, thd, table, get_type_str(), RPL_LOG_NAME, (ulong) log_pos); - thd->reset_current_stmt_binlog_row_based(); + /* + @todo We should probably not call + reset_current_stmt_binlog_format_row() from here. + + Note: this applies to log_event_old.cc too. + /Sven + */ + thd->reset_current_stmt_binlog_format_row(); const_cast<Relay_log_info*>(rli)->cleanup_context(thd, error); thd->is_slave_error= 1; DBUG_RETURN(error); @@ -7651,7 +7761,7 @@ static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD * thd) (assume the last master's transaction is ignored by the slave because of replicate-ignore rules). */ - error= thd->binlog_flush_pending_rows_event(true); + error= thd->binlog_flush_pending_rows_event(TRUE); /* If this event is not in a transaction, the call below will, if some @@ -7674,7 +7784,17 @@ static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD * thd) event flushed. */ - thd->reset_current_stmt_binlog_row_based(); + /* + @todo We should probably not call + reset_current_stmt_binlog_format_row() from here. + + Note: this applies to log_event_old.cc too + + Btw, the previous comment about transactional engines does not + seem related to anything that happens here. + /Sven + */ + thd->reset_current_stmt_binlog_format_row(); const_cast<Relay_log_info*>(rli)->cleanup_context(thd, 0); } @@ -7881,7 +8001,10 @@ int Table_map_log_event::save_field_metadata() DBUG_ENTER("Table_map_log_event::save_field_metadata"); int index= 0; for (unsigned int i= 0 ; i < m_table->s->fields ; i++) + { + DBUG_PRINT("debug", ("field_type: %d", m_coltype[i])); index+= m_table->s->field[i]->save_field_metadata(&m_field_metadata[index]); + } DBUG_RETURN(index); } #endif /* !defined(MYSQL_CLIENT) */ @@ -7893,8 +8016,8 @@ int Table_map_log_event::save_field_metadata() */ #if !defined(MYSQL_CLIENT) Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, - bool is_transactional, uint16 flags) - : Log_event(thd, 0, true), + bool is_transactional) + : Log_event(thd, 0, is_transactional), m_table(tbl), m_dbnam(tbl->s->db.str), m_dblen(m_dbnam ? tbl->s->db.length : 0), @@ -7903,7 +8026,7 @@ Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, m_colcnt(tbl->s->fields), m_memory(NULL), m_table_id(tid), - m_flags(flags), + m_flags(TM_BIT_LEN_EXACT_F), m_data_size(0), m_field_metadata(0), m_field_metadata_size(0), @@ -8119,9 +8242,7 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli) DBUG_ASSERT(rli->sql_thd == thd); /* Step the query id to mark what columns that are actually used. */ - pthread_mutex_lock(&LOCK_thread_count); - thd->query_id= next_query_id(); - pthread_mutex_unlock(&LOCK_thread_count); + thd->set_query_id(next_query_id()); if (!(memory= my_multi_malloc(MYF(MY_WME), &table_list, (uint) sizeof(RPL_TABLE_LIST), @@ -8161,8 +8282,10 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli) inside Relay_log_info::clear_tables_to_lock() by calling the table_def destructor explicitly. */ - new (&table_list->m_tabledef) table_def(m_coltype, m_colcnt, - m_field_metadata, m_field_metadata_size, m_null_bits); + new (&table_list->m_tabledef) + table_def(m_coltype, m_colcnt, + m_field_metadata, m_field_metadata_size, + m_null_bits, m_flags); table_list->m_tabledef_valid= TRUE; /* @@ -8320,8 +8443,8 @@ Write_rows_log_event::do_before_row_operations(const Slave_reporting_capability todo: to introduce a property for the event (handler?) which forces applying the event in the replace (idempotent) fashion. */ - if (bit_is_set(slave_exec_mode, SLAVE_EXEC_MODE_IDEMPOTENT) == 1 || - m_table->s->db_type()->db_type == DB_TYPE_NDBCLUSTER) + if ((slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT) || + (m_table->s->db_type()->db_type == DB_TYPE_NDBCLUSTER)) { /* We are using REPLACE semantics and not INSERT IGNORE semantics @@ -8399,7 +8522,7 @@ Write_rows_log_event::do_after_row_operations(const Slave_reporting_capability * int local_error= 0; m_table->next_number_field=0; m_table->auto_increment_field_not_null= FALSE; - if (bit_is_set(slave_exec_mode, SLAVE_EXEC_MODE_IDEMPOTENT) == 1 || + if ((slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT) || m_table->s->db_type()->db_type == DB_TYPE_NDBCLUSTER) { m_table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); @@ -8700,9 +8823,7 @@ int Write_rows_log_event::do_exec_row(const Relay_log_info *const rli) { DBUG_ASSERT(m_table != NULL); - int error= - write_row(rli, /* if 1 then overwrite */ - bit_is_set(slave_exec_mode, SLAVE_EXEC_MODE_IDEMPOTENT) == 1); + int error= write_row(rli, slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT); if (error && !thd->is_error()) { diff --git a/sql/log_event.h b/sql/log_event.h index 0dcc5ebc71f..5530444b0d4 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright (C) 2000-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -875,6 +875,31 @@ public: EVENT_SKIP_COUNT }; + enum enum_event_cache_type + { + EVENT_INVALID_CACHE, + /* + If possible the event should use a non-transactional cache before + being flushed to the binary log. This means that it must be flushed + right after its correspondent statement is completed. + */ + EVENT_STMT_CACHE, + /* + The event should use a transactional cache before being flushed to + the binary log. This means that it must be flushed upon commit or + rollback. + */ + EVENT_TRANSACTIONAL_CACHE, + /* + The event must be written directly to the binary log without going + through a cache. + */ + EVENT_NO_CACHE, + /** + If there is a need for different types, introduce them before this. + */ + EVENT_CACHE_COUNT + }; /* The following type definition is to be used whenever data is placed @@ -925,8 +950,12 @@ public: LOG_EVENT_SUPPRESS_USE_F for notes. */ uint16 flags; - - bool cache_stmt; + + /* + Defines the type of the cache, if any, where the event will be + stored before being flushed to disk. + */ + uint16 cache_type; /** A storage to cache the global system variable's value. @@ -938,7 +967,7 @@ public: THD* thd; Log_event(); - Log_event(THD* thd_arg, uint16 flags_arg, bool cache_stmt); + Log_event(THD* thd_arg, uint16 flags_arg, bool is_transactional); /* read_log_event() functions read an event from a binlog or relay log; used by SHOW BINLOG EVENTS, the binlog_dump thread on the @@ -951,11 +980,11 @@ public: constructor and pass description_event as an argument. */ static Log_event* read_log_event(IO_CACHE* file, - pthread_mutex_t* log_lock, + mysql_mutex_t* log_lock, const Format_description_log_event *description_event); static int read_log_event(IO_CACHE* file, String* packet, - pthread_mutex_t* log_lock); + mysql_mutex_t* log_lock); /* init_show_field_list() prepares the column names and types for the output of SHOW BINLOG EVENTS; it is used only by SHOW BINLOG @@ -1036,7 +1065,18 @@ public: void set_relay_log_event() { flags |= LOG_EVENT_RELAY_LOG_F; } bool is_artificial_event() const { return flags & LOG_EVENT_ARTIFICIAL_F; } bool is_relay_log_event() const { return flags & LOG_EVENT_RELAY_LOG_F; } - inline bool get_cache_stmt() const { return cache_stmt; } + inline bool use_trans_cache() const + { + return (cache_type == Log_event::EVENT_TRANSACTIONAL_CACHE); + } + inline void set_direct_logging() + { + cache_type = Log_event::EVENT_NO_CACHE; + } + inline bool use_direct_logging() + { + return (cache_type == Log_event::EVENT_NO_CACHE); + } Log_event(const char* buf, const Format_description_log_event *description_event); virtual ~Log_event() { free_temp_buf();} @@ -1660,7 +1700,7 @@ public: #ifndef MYSQL_CLIENT Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length, - bool using_trans, bool suppress_use, int error); + bool using_trans, bool direct, bool suppress_use, int error); const char* get_db() { return db; } #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol); @@ -2910,8 +2950,8 @@ public: ulong query_length, uint fn_pos_start_arg, uint fn_pos_end_arg, enum_load_dup_handling dup_handling_arg, - bool using_trans, bool suppress_use, - int errcode); + bool using_trans, bool direct, + bool suppress_use, int errcode); #ifdef HAVE_REPLICATION void pack_info(Protocol* protocol); #endif /* HAVE_REPLICATION */ @@ -3319,16 +3359,14 @@ public: /* Special constants representing sets of flags */ enum { - TM_NO_FLAGS = 0U + TM_NO_FLAGS = 0U, + TM_BIT_LEN_EXACT_F = (1U << 0) }; - void set_flags(flag_set flag) { m_flags |= flag; } - void clear_flags(flag_set flag) { m_flags &= ~flag; } flag_set get_flags(flag_set flag) const { return m_flags & flag; } #ifndef MYSQL_CLIENT - Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, - bool is_transactional, uint16 flags); + Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, bool is_transactional); #endif #ifdef HAVE_REPLICATION Table_map_log_event(const char *buf, uint event_len, @@ -3341,12 +3379,12 @@ public: table_def *create_table_def() { return new table_def(m_coltype, m_colcnt, m_field_metadata, - m_field_metadata_size, m_null_bits); + m_field_metadata_size, m_null_bits, m_flags); } +#endif ulong get_table_id() const { return m_table_id; } const char *get_table_name() const { return m_tblnam; } const char *get_db_name() const { return m_dbnam; } -#endif virtual Log_event_type get_type_code() { return TABLE_MAP_EVENT; } virtual bool is_valid() const { return m_memory != NULL; /* we check malloc */ } @@ -3898,6 +3936,7 @@ public: DBUG_PRINT("enter", ("m_incident: %d", m_incident)); m_message.str= NULL; /* Just as a precaution */ m_message.length= 0; + set_direct_logging(); DBUG_VOID_RETURN; } @@ -3907,6 +3946,7 @@ public: DBUG_ENTER("Incident_log_event::Incident_log_event"); DBUG_PRINT("enter", ("m_incident: %d", m_incident)); m_message= msg; + set_direct_logging(); DBUG_VOID_RETURN; } #endif diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index 72affd2bee9..8670631cfa0 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -59,22 +59,19 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info We also call the mysql_reset_thd_for_next_command(), since this is the logical start of the next "statement". Note that this - call might reset the value of current_stmt_binlog_row_based, so + call might reset the value of current_stmt_binlog_format, so we need to do any changes to that value after this function. */ lex_start(thd); mysql_reset_thd_for_next_command(thd); /* - Check if the slave is set to use SBR. If so, it should switch - to using RBR until the end of the "statement", i.e., next - STMT_END_F or next error. + This is a row injection, so we flag the "statement" as + such. Note that this code is called both when the slave does row + injections and when the BINLOG statement is used to do row + injections. */ - if (!thd->current_stmt_binlog_row_based && - mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG)) - { - thd->set_current_stmt_binlog_row_based(); - } + thd->lex->set_stmt_row_injection(); if (simple_open_n_lock_tables(thd, rli->tables_to_lock)) { @@ -107,14 +104,24 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info RPL_TABLE_LIST *ptr= rli->tables_to_lock; for ( ; ptr ; ptr= static_cast<RPL_TABLE_LIST*>(ptr->next_global)) { - if (ptr->m_tabledef.compatible_with(rli, ptr->table)) + TABLE *conv_table; + if (!ptr->m_tabledef.compatible_with(thd, const_cast<Relay_log_info*>(rli), + ptr->table, &conv_table)) { + DBUG_PRINT("debug", ("Table: %s.%s is not compatible with master", + ptr->table->s->db.str, + ptr->table->s->table_name.str)); mysql_unlock_tables(thd, thd->lock); thd->lock= 0; thd->is_slave_error= 1; const_cast<Relay_log_info*>(rli)->clear_tables_to_lock(); DBUG_RETURN(Old_rows_log_event::ERR_BAD_TABLE_DEF); } + DBUG_PRINT("debug", ("Table: %s.%s is compatible with master" + " - conv_table: %p", + ptr->table->s->db.str, + ptr->table->s->table_name.str, conv_table)); + ptr->m_conv_table= conv_table; } } @@ -166,16 +173,16 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info the event. */ if (ev->get_flags(Old_rows_log_event::NO_FOREIGN_KEY_CHECKS_F)) - thd->options|= OPTION_NO_FOREIGN_KEY_CHECKS; + thd->variables.option_bits|= OPTION_NO_FOREIGN_KEY_CHECKS; else - thd->options&= ~OPTION_NO_FOREIGN_KEY_CHECKS; + thd->variables.option_bits&= ~OPTION_NO_FOREIGN_KEY_CHECKS; if (ev->get_flags(Old_rows_log_event::RELAXED_UNIQUE_CHECKS_F)) - thd->options|= OPTION_RELAXED_UNIQUE_CHECKS; + thd->variables.option_bits|= OPTION_RELAXED_UNIQUE_CHECKS; else - thd->options&= ~OPTION_RELAXED_UNIQUE_CHECKS; + thd->variables.option_bits&= ~OPTION_RELAXED_UNIQUE_CHECKS; /* A small test to verify that objects have consistent types */ - DBUG_ASSERT(sizeof(thd->options) == sizeof(OPTION_RELAXED_UNIQUE_CHECKS)); + DBUG_ASSERT(sizeof(thd->variables.option_bits) == sizeof(OPTION_RELAXED_UNIQUE_CHECKS)); /* Now we are in a statement and will stay in a statement until we @@ -229,10 +236,10 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info DBUG_EXECUTE_IF("stop_slave_middle_group", const_cast<Relay_log_info*>(rli)->abort_slave= 1;); error= do_after_row_operations(table, error); - if (!ev->cache_stmt) + if (!ev->use_trans_cache()) { DBUG_PRINT("info", ("Marked that we need to keep log")); - thd->options|= OPTION_KEEP_LOG; + thd->variables.option_bits|= OPTION_KEEP_LOG; } } @@ -263,7 +270,7 @@ Old_rows_log_event::do_apply_event(Old_rows_log_event *ev, const Relay_log_info thread is certainly going to stop. rollback at the caller along with sbr. */ - thd->reset_current_stmt_binlog_row_based(); + thd->reset_current_stmt_binlog_format_row(); const_cast<Relay_log_info*>(rli)->cleanup_context(thd, error); thd->is_slave_error= 1; DBUG_RETURN(error); @@ -1220,9 +1227,9 @@ Old_rows_log_event::Old_rows_log_event(THD *thd_arg, TABLE *tbl_arg, ulong tid, DBUG_ASSERT((tbl_arg && tbl_arg->s && tid != ~0UL) || (!tbl_arg && !cols && tid == ~0UL)); - if (thd_arg->options & OPTION_NO_FOREIGN_KEY_CHECKS) + if (thd_arg->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS) set_flags(NO_FOREIGN_KEY_CHECKS_F); - if (thd_arg->options & OPTION_RELAXED_UNIQUE_CHECKS) + if (thd_arg->variables.option_bits & OPTION_RELAXED_UNIQUE_CHECKS) set_flags(RELAXED_UNIQUE_CHECKS_F); /* if bitmap_init fails, caught in is_valid() */ if (likely(!bitmap_init(&m_cols, @@ -1513,7 +1520,7 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli) NOTE: For this new scheme there should be no pending event: need to add code to assert that is the case. */ - error= thd->binlog_flush_pending_rows_event(false); + error= thd->binlog_flush_pending_rows_event(FALSE); if (error) { rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, @@ -1558,7 +1565,9 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli) RPL_TABLE_LIST *ptr= rli->tables_to_lock; for ( ; ptr ; ptr= static_cast<RPL_TABLE_LIST*>(ptr->next_global)) { - if (ptr->m_tabledef.compatible_with(rli, ptr->table)) + TABLE *conv_table; + if (ptr->m_tabledef.compatible_with(thd, const_cast<Relay_log_info*>(rli), + ptr->table, &conv_table)) { mysql_unlock_tables(thd, thd->lock); thd->lock= 0; @@ -1566,12 +1575,14 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli) const_cast<Relay_log_info*>(rli)->clear_tables_to_lock(); DBUG_RETURN(ERR_BAD_TABLE_DEF); } + ptr->m_conv_table= conv_table; } } /* - ... and then we add all the tables to the table map and remove - them from tables to lock. + ... and then we add all the tables to the table map but keep + them in the tables to lock list. + We also invalidate the query cache for all the tables, since they will now be changed. @@ -1619,16 +1630,16 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli) the event. */ if (get_flags(NO_FOREIGN_KEY_CHECKS_F)) - thd->options|= OPTION_NO_FOREIGN_KEY_CHECKS; + thd->variables.option_bits|= OPTION_NO_FOREIGN_KEY_CHECKS; else - thd->options&= ~OPTION_NO_FOREIGN_KEY_CHECKS; + thd->variables.option_bits&= ~OPTION_NO_FOREIGN_KEY_CHECKS; if (get_flags(RELAXED_UNIQUE_CHECKS_F)) - thd->options|= OPTION_RELAXED_UNIQUE_CHECKS; + thd->variables.option_bits|= OPTION_RELAXED_UNIQUE_CHECKS; else - thd->options&= ~OPTION_RELAXED_UNIQUE_CHECKS; + thd->variables.option_bits&= ~OPTION_RELAXED_UNIQUE_CHECKS; /* A small test to verify that objects have consistent types */ - DBUG_ASSERT(sizeof(thd->options) == sizeof(OPTION_RELAXED_UNIQUE_CHECKS)); + DBUG_ASSERT(sizeof(thd->variables.option_bits) == sizeof(OPTION_RELAXED_UNIQUE_CHECKS)); /* Now we are in a statement and will stay in a statement until we @@ -1727,10 +1738,10 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli) DBUG_EXECUTE_IF("stop_slave_middle_group", const_cast<Relay_log_info*>(rli)->abort_slave= 1;); error= do_after_row_operations(rli, error); - if (!cache_stmt) + if (!use_trans_cache()) { DBUG_PRINT("info", ("Marked that we need to keep log")); - thd->options|= OPTION_KEEP_LOG; + thd->variables.option_bits|= OPTION_KEEP_LOG; } } // if (table) @@ -1761,7 +1772,7 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli) thread is certainly going to stop. rollback at the caller along with sbr. */ - thd->reset_current_stmt_binlog_row_based(); + thd->reset_current_stmt_binlog_format_row(); const_cast<Relay_log_info*>(rli)->cleanup_context(thd, error); thd->is_slave_error= 1; DBUG_RETURN(error); @@ -1773,7 +1784,7 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli) last_event_start_time here instead. */ if (table && (table->s->primary_key == MAX_KEY) && - !cache_stmt && get_flags(STMT_END_F) == RLE_NO_FLAGS) + !use_trans_cache() && get_flags(STMT_END_F) == RLE_NO_FLAGS) { /* ------------ Temporary fix until WL#2975 is implemented --------- @@ -1811,7 +1822,7 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli) (assume the last master's transaction is ignored by the slave because of replicate-ignore rules). */ - int binlog_error= thd->binlog_flush_pending_rows_event(true); + int binlog_error= thd->binlog_flush_pending_rows_event(TRUE); /* If this event is not in a transaction, the call below will, if some @@ -1840,7 +1851,7 @@ int Old_rows_log_event::do_apply_event(Relay_log_info const *rli) event flushed. */ - thd->reset_current_stmt_binlog_row_based(); + thd->reset_current_stmt_binlog_format_row(); const_cast<Relay_log_info*>(rli)->cleanup_context(thd, 0); } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 5714db92af0..8daf8f5ecb3 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,7 +36,7 @@ #define SHOW_always_last SHOW_KEY_CACHE_LONG, \ SHOW_KEY_CACHE_LONGLONG, SHOW_LONG_STATUS, SHOW_DOUBLE_STATUS, \ SHOW_HAVE, SHOW_MY_BOOL, SHOW_HA_ROWS, SHOW_SYS, \ - SHOW_LONG_NOFLUSH, SHOW_LONGLONG_STATUS + SHOW_LONG_NOFLUSH, SHOW_LONGLONG_STATUS, SHOW_LEX_STRING #include <my_global.h> #include <mysql_version.h> @@ -53,6 +53,11 @@ #include "sql_array.h" #include "sql_plugin.h" #include "scheduler.h" +#include <my_atomic.h> +#include <mysql/psi/mysql_file.h> +#ifndef __WIN__ +#include <netdb.h> +#endif class Parser_state; @@ -85,11 +90,60 @@ typedef ulong nesting_map; /* Used for flags of nesting constructs */ typedef ulonglong nested_join_map; /* query_id */ -typedef ulonglong query_id_t; +typedef int64 query_id_t; extern query_id_t global_query_id; +extern int32 thread_running; +extern my_atomic_rwlock_t global_query_id_lock; +extern my_atomic_rwlock_t thread_running_lock; /* increment query_id and return it. */ -inline query_id_t next_query_id() { return global_query_id++; } +inline query_id_t next_query_id() +{ + query_id_t id; + my_atomic_rwlock_wrlock(&global_query_id_lock); + id= my_atomic_add64(&global_query_id, 1); + my_atomic_rwlock_wrunlock(&global_query_id_lock); + return (id+1); +} + +inline query_id_t get_query_id() +{ + query_id_t id; + my_atomic_rwlock_wrlock(&global_query_id_lock); + id= my_atomic_load64(&global_query_id); + my_atomic_rwlock_wrunlock(&global_query_id_lock); + return id; +} + +inline int32 +inc_thread_running() +{ + int32 num_thread_running; + my_atomic_rwlock_wrlock(&thread_running_lock); + num_thread_running= my_atomic_add32(&thread_running, 1); + my_atomic_rwlock_wrunlock(&thread_running_lock); + return (num_thread_running+1); +} + +inline int32 +dec_thread_running() +{ + int32 num_thread_running; + my_atomic_rwlock_wrlock(&thread_running_lock); + num_thread_running= my_atomic_add32(&thread_running, -1); + my_atomic_rwlock_wrunlock(&thread_running_lock); + return (num_thread_running-1); +} + +inline int32 +get_thread_running() +{ + int32 num_thread_running; + my_atomic_rwlock_wrlock(&thread_running_lock); + num_thread_running= my_atomic_load32(&thread_running); + my_atomic_rwlock_wrunlock(&thread_running_lock); + return num_thread_running; +} /* useful constants */ extern MYSQL_PLUGIN_IMPORT const key_map key_map_empty; @@ -121,20 +175,35 @@ char* query_table_status(THD *thd,const char *db,const char *table_name); #define PREV_BITS(type,A) ((type) (((type) 1 << (A)) -1)) #define all_bits_set(A,B) ((A) & (B) != (B)) -/* Version numbers for deprecation messages */ -#define VER_BETONY "5.5" -#define VER_CELOSIA "5.6" - -#define WARN_DEPRECATED(Thd,Ver,Old,New) \ - do { \ - DBUG_ASSERT(strncmp(Ver, MYSQL_SERVER_VERSION, sizeof(Ver)-1) > 0); \ - if (((uchar*)Thd) != NULL) \ - push_warning_printf(((THD *)Thd), MYSQL_ERROR::WARN_LEVEL_WARN, \ - ER_WARN_DEPRECATED_SYNTAX, ER(ER_WARN_DEPRECATED_SYNTAX_WITH_VER), \ - (Old), (Ver), (New)); \ - else \ - sql_print_warning("The syntax '%s' is deprecated and will be removed " \ - "in a future release. Please use %s instead.", (Old), (New)); \ +/* + Generates a warning that a feature is deprecated. After a specified + version asserts that the feature is removed. + + Using it as + + WARN_DEPRECATED(thd, 6,2, "BAD", "'GOOD'"); + + Will result in a warning + + "The syntax 'BAD' is deprecated and will be removed in MySQL 6.2. Please + use 'GOOD' instead" + + Note that in macro arguments BAD is not quoted, while 'GOOD' is. + Note that the version is TWO numbers, separated with a comma + (two macro arguments, that is) +*/ +#define WARN_DEPRECATED(Thd,VerHi,VerLo,Old,New) \ + do { \ + compile_time_assert(MYSQL_VERSION_ID < VerHi * 10000 + VerLo * 100); \ + if (((THD *) Thd) != NULL) \ + push_warning_printf(((THD *) Thd), MYSQL_ERROR::WARN_LEVEL_WARN, \ + ER_WARN_DEPRECATED_SYNTAX, \ + ER(ER_WARN_DEPRECATED_SYNTAX_WITH_VER), \ + (Old), #VerHi "." #VerLo, (New)); \ + else \ + sql_print_warning("The syntax '%s' is deprecated and will be removed " \ + "in MySQL %s. Please use %s instead.", \ + (Old), #VerHi "." #VerLo, (New)); \ } while(0) extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *system_charset_info; @@ -166,6 +235,7 @@ typedef struct my_locale_errmsgs extern char err_shared_dir[]; +/** @note Keep this a POD-type because we use offsetof() on it */ typedef struct my_locale_st { uint number; @@ -423,26 +493,10 @@ protected: #define FLUSH_TIME 0 /**< Don't flush tables */ #define MAX_CONNECT_ERRORS 10 ///< errors before disabling host -#ifdef __NETWARE__ -#define IF_NETWARE(A,B) A -#else -#define IF_NETWARE(A,B) B -#endif - #if defined(__WIN__) #undef FLUSH_TIME #define FLUSH_TIME 1800 /**< Flush every half hour */ - -#define INTERRUPT_PRIOR -2 -#define CONNECT_PRIOR -1 -#define WAIT_PRIOR 0 -#define QUERY_PRIOR 2 -#else -#define INTERRUPT_PRIOR 10 -#define CONNECT_PRIOR 9 -#define WAIT_PRIOR 8 -#define QUERY_PRIOR 6 -#endif /* __WIN92__ */ +#endif /* __WIN__ */ /* Bits from testflag */ #define TEST_PRINT_CACHED_TABLES 1 @@ -463,7 +517,7 @@ protected: This is included in the server and in the client. Options for select set by the yacc parser (stored in lex->options). - XXX: + NOTE log_event.h defines OPTIONS_WRITTEN_TO_BIN_LOG to specify what THD options list are written into binlog. These options can NOT change their values, or it will break replication between version. @@ -477,53 +531,52 @@ protected: TODO: separate three contexts above, move them to separate bitfields. */ -#define SELECT_DISTINCT (ULL(1) << 0) // SELECT, user -#define SELECT_STRAIGHT_JOIN (ULL(1) << 1) // SELECT, user -#define SELECT_DESCRIBE (ULL(1) << 2) // SELECT, user -#define SELECT_SMALL_RESULT (ULL(1) << 3) // SELECT, user -#define SELECT_BIG_RESULT (ULL(1) << 4) // SELECT, user -#define OPTION_FOUND_ROWS (ULL(1) << 5) // SELECT, user -#define OPTION_TO_QUERY_CACHE (ULL(1) << 6) // SELECT, user -#define SELECT_NO_JOIN_CACHE (ULL(1) << 7) // intern -#define OPTION_BIG_TABLES (ULL(1) << 8) // THD, user -#define OPTION_BIG_SELECTS (ULL(1) << 9) // THD, user -#define OPTION_LOG_OFF (ULL(1) << 10) // THD, user -#define OPTION_QUOTE_SHOW_CREATE (ULL(1) << 11) // THD, user, unused -#define TMP_TABLE_ALL_COLUMNS (ULL(1) << 12) // SELECT, intern -#define OPTION_WARNINGS (ULL(1) << 13) // THD, user -#define OPTION_AUTO_IS_NULL (ULL(1) << 14) // THD, user, binlog -#define OPTION_FOUND_COMMENT (ULL(1) << 15) // SELECT, intern, parser -#define OPTION_SAFE_UPDATES (ULL(1) << 16) // THD, user -#define OPTION_BUFFER_RESULT (ULL(1) << 17) // SELECT, user -#define OPTION_BIN_LOG (ULL(1) << 18) // THD, user -#define OPTION_NOT_AUTOCOMMIT (ULL(1) << 19) // THD, user -#define OPTION_BEGIN (ULL(1) << 20) // THD, intern -#define OPTION_TABLE_LOCK (ULL(1) << 21) // THD, intern -#define OPTION_QUICK (ULL(1) << 22) // SELECT (for DELETE) -#define OPTION_KEEP_LOG (ULL(1) << 23) // THD, user +#define SELECT_DISTINCT (1ULL << 0) // SELECT, user +#define SELECT_STRAIGHT_JOIN (1ULL << 1) // SELECT, user +#define SELECT_DESCRIBE (1ULL << 2) // SELECT, user +#define SELECT_SMALL_RESULT (1ULL << 3) // SELECT, user +#define SELECT_BIG_RESULT (1ULL << 4) // SELECT, user +#define OPTION_FOUND_ROWS (1ULL << 5) // SELECT, user +#define OPTION_TO_QUERY_CACHE (1ULL << 6) // SELECT, user +#define SELECT_NO_JOIN_CACHE (1ULL << 7) // intern +/** always the opposite of OPTION_NOT_AUTOCOMMIT except when in fix_autocommit() */ +#define OPTION_AUTOCOMMIT (1ULL << 8) // THD, user +#define OPTION_BIG_SELECTS (1ULL << 9) // THD, user +#define OPTION_LOG_OFF (1ULL << 10) // THD, user +#define OPTION_QUOTE_SHOW_CREATE (1ULL << 11) // THD, user, unused +#define TMP_TABLE_ALL_COLUMNS (1ULL << 12) // SELECT, intern +#define OPTION_WARNINGS (1ULL << 13) // THD, user +#define OPTION_AUTO_IS_NULL (1ULL << 14) // THD, user, binlog +#define OPTION_FOUND_COMMENT (1ULL << 15) // SELECT, intern, parser +#define OPTION_SAFE_UPDATES (1ULL << 16) // THD, user +#define OPTION_BUFFER_RESULT (1ULL << 17) // SELECT, user +#define OPTION_BIN_LOG (1ULL << 18) // THD, user +#define OPTION_NOT_AUTOCOMMIT (1ULL << 19) // THD, user +#define OPTION_BEGIN (1ULL << 20) // THD, intern +#define OPTION_TABLE_LOCK (1ULL << 21) // THD, intern +#define OPTION_QUICK (1ULL << 22) // SELECT (for DELETE) +#define OPTION_KEEP_LOG (1ULL << 23) // THD, user /* The following is used to detect a conflict with DISTINCT */ -#define SELECT_ALL (ULL(1) << 24) // SELECT, user, parser - +#define SELECT_ALL (1ULL << 24) // SELECT, user, parser /** The following can be set when importing tables in a 'wrong order' to suppress foreign key checks */ -#define OPTION_NO_FOREIGN_KEY_CHECKS (ULL(1) << 26) // THD, user, binlog +#define OPTION_NO_FOREIGN_KEY_CHECKS (1ULL << 26) // THD, user, binlog /** The following speeds up inserts to InnoDB tables by suppressing unique key checks in some cases */ -#define OPTION_RELAXED_UNIQUE_CHECKS (ULL(1) << 27) // THD, user, binlog -#define SELECT_NO_UNLOCK (ULL(1) << 28) // SELECT, intern -#define OPTION_SCHEMA_TABLE (ULL(1) << 29) // SELECT, intern +#define OPTION_RELAXED_UNIQUE_CHECKS (1ULL << 27) // THD, user, binlog +#define SELECT_NO_UNLOCK (1ULL << 28) // SELECT, intern +#define OPTION_SCHEMA_TABLE (1ULL << 29) // SELECT, intern /** Flag set if setup_tables already done */ -#define OPTION_SETUP_TABLES_DONE (ULL(1) << 30) // intern +#define OPTION_SETUP_TABLES_DONE (1ULL << 30) // intern /** If not set then the thread will ignore all warnings with level notes. */ -#define OPTION_SQL_NOTES (ULL(1) << 31) // THD, user +#define OPTION_SQL_NOTES (1ULL << 31) // THD, user /** Force the used temporary table to be a MyISAM table (because we will use fulltext functions when reading from it. */ -#define TMP_TABLE_FORCE_MYISAM (ULL(1) << 32) -#define OPTION_PROFILING (ULL(1) << 33) - +#define TMP_TABLE_FORCE_MYISAM (1ULL << 32) +#define OPTION_PROFILING (1ULL << 33) /** @@ -570,17 +623,19 @@ protected: #define MODE_PAD_CHAR_TO_FULL_LENGTH (ULL(1) << 31) /* @@optimizer_switch flags. These must be in sync with optimizer_switch_typelib */ -#define OPTIMIZER_SWITCH_INDEX_MERGE 1 -#define OPTIMIZER_SWITCH_INDEX_MERGE_UNION 2 -#define OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION 4 -#define OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT 8 -#define OPTIMIZER_SWITCH_LAST 16 +#define OPTIMIZER_SWITCH_INDEX_MERGE (1ULL << 0) +#define OPTIMIZER_SWITCH_INDEX_MERGE_UNION (1ULL << 1) +#define OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION (1ULL << 2) +#define OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT (1ULL << 3) +#define OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN (1ULL << 4) +#define OPTIMIZER_SWITCH_LAST (1ULL << 5) /* The following must be kept in sync with optimizer_switch_str in mysqld.cc */ #define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \ OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \ OPTIMIZER_SWITCH_INDEX_MERGE_SORT_UNION | \ - OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT) + OPTIMIZER_SWITCH_INDEX_MERGE_INTERSECT | \ + OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN) /* @@ -839,7 +894,10 @@ inline bool check_routine_access(THD *thd,ulong want_access,char *db, char *name, bool is_proc, bool no_errors) { return false; } inline bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table) -{ return false; } +{ + table->grant.privilege= want_access; + return false; +} inline bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list) { return false; } inline bool check_some_routine_access(THD *thd, const char *db, @@ -871,6 +929,8 @@ bool check_string_char_length(LEX_STRING *str, const char *err_msg, bool no_error); bool check_host_name(LEX_STRING *str); +CHARSET_INFO *merge_charset_and_collation(CHARSET_INFO *cs, CHARSET_INFO *cl); + bool parse_sql(THD *thd, Parser_state *parser_state, Object_creation_ctx *creation_ctx); @@ -980,13 +1040,15 @@ struct Query_cache_query_flags #endif /*HAVE_QUERY_CACHE*/ int write_bin_log(THD *thd, bool clear_error, - char const *query, ulong query_length); + char const *query, ulong query_length, + bool is_trans= FALSE); /* sql_connect.cc */ int check_user(THD *thd, enum enum_server_command command, const char *passwd, uint passwd_len, const char *db, bool check_count); pthread_handler_t handle_one_connection(void *arg); +void do_handle_one_connection(THD *thd_arg); bool init_new_connection_handler_thread(); void reset_mqh(LEX_USER *lu, bool get_them); bool check_mqh(THD *thd, uint check_command); @@ -1039,6 +1101,7 @@ void init_max_user_conn(void); void init_update_queries(void); void free_max_user_conn(void); pthread_handler_t handle_bootstrap(void *arg); +void do_handle_bootstrap(THD *thd); int mysql_execute_command(THD *thd); bool do_command(THD *thd); bool dispatch_command(enum enum_server_command command, THD *thd, @@ -1063,24 +1126,26 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, bool *write_to_binlog); #ifndef NO_EMBEDDED_ACCESS_CHECKS bool check_access(THD *thd, ulong access, const char *db, ulong *save_priv, - bool no_grant, bool no_errors, bool schema_db); -bool check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables, + GRANT_INTERNAL_INFO *grant_internal_info, + bool no_grant, bool no_errors); +bool check_table_access(THD *thd, ulong requirements, TABLE_LIST *tables, bool any_combination_of_privileges_will_do, uint number, bool no_errors); #else inline bool check_access(THD *thd, ulong access, const char *db, - ulong *save_priv, bool no_grant, bool no_errors, - bool schema_db) + ulong *save_priv, + GRANT_INTERNAL_INFO *grant_internal_info, + bool no_grant, bool no_errors) { if (save_priv) *save_priv= GLOBAL_ACLS; return false; } inline bool check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables, - bool no_errors, bool any_combination_of_privileges_will_do, - uint number) + uint number, + bool no_errors) { return false; } #endif /*NO_EMBEDDED_ACCESS_CHECKS*/ @@ -1255,12 +1320,16 @@ thr_lock_type read_lock_type_for_table(THD *thd, TABLE *table); void close_data_files_and_morph_locks(THD *thd, const char *db, const char *table_name); void close_handle_and_leave_table_as_lock(TABLE *table); +bool open_new_frm(THD *thd, TABLE_SHARE *share, const char *alias, + uint db_stat, uint prgflag, + uint ha_open_flags, TABLE *outparam, + TABLE_LIST *table_desc, MEM_ROOT *mem_root); bool wait_for_tables(THD *thd); bool table_is_used(TABLE *table, bool wait_for_name_lock); TABLE *drop_locked_tables(THD *thd,const char *db, const char *table_name); void abort_locked_tables(THD *thd,const char *db, const char *table_name); -void execute_init_command(THD *thd, sys_var_str *init_command_var, - rw_lock_t *var_mutex); +void execute_init_command(THD *thd, LEX_STRING *init_command, + mysql_rwlock_t *var_mutex); extern Field *not_found_field; extern Field *view_ref_found; @@ -1301,7 +1370,7 @@ struct st_des_keyschedule extern char *des_key_file; extern struct st_des_keyschedule des_keyschedule[10]; extern uint des_default_key; -extern pthread_mutex_t LOCK_des_key_file; +extern mysql_mutex_t LOCK_des_key_file; bool load_des_key_file(const char *file_name); #endif /* HAVE_OPENSSL */ @@ -1348,6 +1417,8 @@ void free_status_vars(); void reset_status_vars(); /* information schema */ extern LEX_STRING INFORMATION_SCHEMA_NAME; +/* performance schema */ +extern LEX_STRING PERFORMANCE_SCHEMA_DB_NAME; /* log tables */ extern LEX_STRING MYSQL_SCHEMA_NAME; extern LEX_STRING GENERAL_LOG_NAME; @@ -1369,19 +1440,21 @@ bool get_schema_tables_result(JOIN *join, enum enum_schema_table_state executed_place); enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table); -inline bool is_schema_db(const char *name, size_t len) +inline bool is_infoschema_db(const char *name, size_t len) { return (INFORMATION_SCHEMA_NAME.length == len && !my_strcasecmp(system_charset_info, - INFORMATION_SCHEMA_NAME.str, name)); + INFORMATION_SCHEMA_NAME.str, name)); } -inline bool is_schema_db(const char *name) +inline bool is_infoschema_db(const char *name) { return !my_strcasecmp(system_charset_info, INFORMATION_SCHEMA_NAME.str, name); } +void initialize_information_schema_acl(); + /* sql_handler.cc */ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen); bool mysql_ha_close(THD *thd, TABLE_LIST *tables); @@ -1497,8 +1570,8 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds); int setup_ftfuncs(SELECT_LEX* select); int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order); -void wait_for_condition(THD *thd, pthread_mutex_t *mutex, - pthread_cond_t *cond); +void wait_for_condition(THD *thd, mysql_mutex_t *mutex, + mysql_cond_t *cond); int open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags); /* open_and_lock_tables with optional derived handling */ int open_and_lock_tables_derived(THD *thd, TABLE_LIST *tables, bool derived); @@ -1517,7 +1590,6 @@ TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l, thr_lock_type lock_type); bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags); int lock_tables(THD *thd, TABLE_LIST *tables, uint counter, bool *need_reopen); -int decide_logging_format(THD *thd, TABLE_LIST *tables); TABLE *open_temporary_table(THD *thd, const char *path, const char *db, const char *table_name, bool link_in_list); bool rm_temporary_table(handlerton *base, char *path); @@ -1543,7 +1615,8 @@ bool rename_temporary_table(THD* thd, TABLE *table, const char *new_db, void remove_db_from_cache(const char *db); void flush_tables(); bool is_equal(const LEX_STRING *a, const LEX_STRING *b); -char *make_default_log_name(char *buff,const char* log_ext); +char *make_log_name(char *buff, const char *name, const char* log_ext); +extern char default_logfile_name[FN_REFLEN]; #ifdef WITH_PARTITION_STORAGE_ENGINE uint fast_alter_partition_table(THD *thd, TABLE *table, @@ -1683,7 +1756,7 @@ void release_ddl_log(); void execute_ddl_log_recovery(); bool execute_ddl_log_entry(THD *thd, uint first_entry); -extern pthread_mutex_t LOCK_gdl; +extern mysql_mutex_t LOCK_gdl; #define WFRM_WRITE_SHADOW 1 #define WFRM_INSTALL_SHADOW 2 @@ -1700,9 +1773,8 @@ bool open_system_tables_for_read(THD *thd, TABLE_LIST *table_list, void close_system_tables(THD *thd, Open_tables_state *backup); TABLE *open_system_table_for_update(THD *thd, TABLE_LIST *one_table); -TABLE *open_performance_schema_table(THD *thd, TABLE_LIST *one_table, - Open_tables_state *backup); -void close_performance_schema_table(THD *thd, Open_tables_state *backup); +TABLE *open_log_table(THD *thd, TABLE_LIST *one_table, Open_tables_state *backup); +void close_log_table(THD *thd, Open_tables_state *backup); bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, bool wait_for_refresh, bool wait_for_placeholders); @@ -1809,10 +1881,6 @@ extern enum_field_types agg_field_type(Item **items, uint nitems); /* strfunc.cc */ ulonglong find_set(TYPELIB *lib, const char *x, uint length, CHARSET_INFO *cs, char **err_pos, uint *err_len, bool *set_warning); -ulonglong find_set_from_flags(TYPELIB *lib, uint default_name, - ulonglong cur_set, ulonglong default_set, - const char *str, uint length, CHARSET_INFO *cs, - char **err_pos, uint *err_len, bool *set_warning); uint find_type(const TYPELIB *lib, const char *find, uint length, bool part_match); uint find_type2(const TYPELIB *lib, const char *find, uint length, @@ -1822,6 +1890,10 @@ uint check_word(TYPELIB *lib, const char *val, const char *end, const char **end_of_word); int find_string_in_array(LEX_STRING * const haystack, LEX_STRING * const needle, CHARSET_INFO * const cs); +char *set_to_string(THD *thd, LEX_STRING *result, ulonglong set, + const char *lib[]); +char *flagset_to_string(THD *thd, LEX_STRING *result, ulonglong set, + const char *lib[]); bool is_keyword(const char *name, uint len); @@ -1846,7 +1918,9 @@ extern int creating_table; // How many mysql_create_table() are running extern time_t server_start_time, flush_status_time; #endif /* MYSQL_SERVER */ #if defined MYSQL_SERVER || defined INNODB_COMPATIBILITY_HOOKS -extern uint mysql_data_home_len; +extern uint mysql_data_home_len, mysql_real_data_home_len; +extern const char *mysql_real_data_home_ptr; +extern uint thread_handling; extern MYSQL_PLUGIN_IMPORT char *mysql_data_home; extern char server_version[SERVER_VERSION_LENGTH]; @@ -1856,18 +1930,18 @@ extern char mysql_unpacked_real_data_home[]; extern CHARSET_INFO *character_set_filesystem; #endif /* MYSQL_SERVER || INNODB_COMPATIBILITY_HOOKS */ #ifdef MYSQL_SERVER -extern char *opt_mysql_tmpdir, mysql_charsets_dir[], - def_ft_boolean_syntax[sizeof(ft_boolean_syntax)]; +extern char *opt_mysql_tmpdir, mysql_charsets_dir[]; extern int mysql_unpacked_real_data_home_len; #define mysql_tmpdir (my_tmpdir(&mysql_tmpdir_list)) extern MYSQL_PLUGIN_IMPORT MY_TMPDIR mysql_tmpdir_list; extern const LEX_STRING command_name[]; +extern LEX_STRING opt_init_connect, opt_init_slave; + extern const char *first_keyword, *delayed_user, *binary_keyword; extern MYSQL_PLUGIN_IMPORT const char *my_localhost; extern MYSQL_PLUGIN_IMPORT const char **errmesg; /* Error messages */ -extern const char *myisam_recover_options_str; extern const char *in_left_expr_name, *in_additional_cond, *in_having_cond; extern const char * const TRG_EXT; extern const char * const TRN_EXT; @@ -1878,16 +1952,18 @@ extern Lt_creator lt_creator; extern Ge_creator ge_creator; extern Le_creator le_creator; extern char lc_messages_dir[FN_REFLEN]; +extern char *lc_messages_dir_ptr, *log_error_file_ptr; #endif /* MYSQL_SERVER */ #if defined MYSQL_SERVER || defined INNODB_COMPATIBILITY_HOOKS extern MYSQL_PLUGIN_IMPORT char reg_ext[FN_EXTLEN]; extern MYSQL_PLUGIN_IMPORT uint reg_ext_length; #endif /* MYSQL_SERVER || INNODB_COMPATIBILITY_HOOKS */ #ifdef MYSQL_SERVER +extern char *mysql_home_ptr, *pidfile_name_ptr; extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN]; extern char pidfile_name[FN_REFLEN], system_time_zone[30], *opt_init_file; -extern char default_logfile_name[FN_REFLEN]; extern char log_error_file[FN_REFLEN], *opt_tc_log_file; +extern const double log_10[309]; extern ulonglong log_10_int[20]; extern ulonglong keybuff_size; extern ulonglong thd_startup_options; @@ -1905,7 +1981,6 @@ extern ulong table_cache_size, table_def_size; extern MYSQL_PLUGIN_IMPORT ulong max_connections; extern ulong max_connect_errors, connect_timeout; extern ulong slave_net_timeout, slave_trans_retries; -extern uint max_user_connections; extern ulong what_to_log,flush_time; extern ulong query_buff_size; extern ulong max_prepared_stmt_count, prepared_stmt_count; @@ -1947,30 +2022,33 @@ extern MYSQL_PLUGIN_IMPORT bool mysqld_embedded; extern bool opt_large_files, server_id_supplied; extern bool opt_update_log, opt_bin_log, opt_error_log; extern my_bool opt_log, opt_slow_log; -extern ulong log_output_options; +extern ulonglong log_output_options; extern my_bool opt_log_queries_not_using_indexes; extern bool opt_disable_networking, opt_skip_show_db; extern bool opt_ignore_builtin_innodb; extern my_bool opt_character_set_client_handshake; extern bool volatile abort_loop, shutdown_in_progress; extern bool in_bootstrap; -extern uint volatile thread_count, thread_running, global_read_lock; +extern uint volatile thread_count, global_read_lock; extern uint connection_count; extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types; extern my_bool opt_safe_show_db, opt_local_infile, opt_myisam_use_mmap; extern my_bool opt_slave_compressed_protocol, use_temp_pool; -extern ulong slave_exec_mode_options; +extern uint slave_exec_mode_options; +extern ulonglong slave_type_conversions_options; extern my_bool opt_readonly, lower_case_file_system; extern my_bool opt_enable_named_pipe, opt_sync_frm, opt_allow_suspicious_udfs; extern my_bool opt_secure_auth; extern char* opt_secure_file_priv; extern my_bool opt_log_slow_admin_statements, opt_log_slow_slave_statements; -extern my_bool sp_automatic_privileges, opt_noacl; +extern my_bool sp_automatic_privileges, opt_noacl, disable_slaves; extern my_bool opt_old_style_user_limits, trust_function_creators; extern uint opt_crash_binlog_innodb; extern char *shared_memory_base_name, *mysqld_unix_port; extern my_bool opt_enable_shared_memory; extern char *default_tz_name; +extern Time_zone *default_tz; +extern char *default_storage_engine; #endif /* MYSQL_SERVER */ #if defined MYSQL_SERVER || defined INNODB_COMPATIBILITY_HOOKS extern my_bool opt_large_pages; @@ -1979,35 +2057,36 @@ extern uint opt_large_page_size; #ifdef MYSQL_SERVER extern char *opt_logname, *opt_slow_logname; extern const char *log_output_str; +extern my_bool old_mode; extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log; extern LOGGER logger; extern TABLE_LIST general_log, slow_log; -extern FILE *bootstrap_file; +extern MYSQL_FILE *bootstrap_file; extern int bootstrap_error; extern FILE *stderror_file; extern pthread_key(MEM_ROOT**,THR_MALLOC); -extern pthread_mutex_t LOCK_mysql_create_db, LOCK_open, LOCK_lock_db, - LOCK_mapped_file,LOCK_user_locks, LOCK_status, +extern mysql_mutex_t LOCK_mysql_create_db, LOCK_open, LOCK_lock_db, + LOCK_mapped_file, LOCK_user_locks, LOCK_status, LOCK_error_log, LOCK_delayed_insert, LOCK_uuid_generator, LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone, LOCK_slave_list, LOCK_active_mi, LOCK_manager, LOCK_global_read_lock, LOCK_global_system_variables, LOCK_user_conn, LOCK_prepared_stmt_count, LOCK_error_messages, LOCK_connection_count; -extern MYSQL_PLUGIN_IMPORT pthread_mutex_t LOCK_thread_count; +extern MYSQL_PLUGIN_IMPORT mysql_mutex_t LOCK_thread_count; #ifdef HAVE_OPENSSL -extern pthread_mutex_t LOCK_des_key_file; +extern mysql_mutex_t LOCK_des_key_file; #endif -extern pthread_mutex_t LOCK_server_started; -extern pthread_cond_t COND_server_started; +extern mysql_mutex_t LOCK_server_started; +extern mysql_cond_t COND_server_started; extern int mysqld_server_started; -extern rw_lock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave; -extern rw_lock_t LOCK_system_variables_hash; -extern pthread_cond_t COND_refresh, COND_thread_count, COND_manager; -extern pthread_cond_t COND_global_read_lock; +extern mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave; +extern mysql_rwlock_t LOCK_system_variables_hash; +extern mysql_cond_t COND_thread_count; +extern mysql_cond_t COND_refresh, COND_manager; +extern mysql_cond_t COND_global_read_lock; extern pthread_attr_t connection_attrib; extern I_List<THD> threads; -extern I_List<NAMED_LIST> key_caches; extern MY_BITMAP temp_pool; extern String my_empty_string; extern const String my_null_string; @@ -2021,22 +2100,24 @@ extern struct system_variables max_system_variables; extern struct system_status_var global_status_var; extern struct rand_struct sql_rand; -extern const char *opt_date_time_formats[]; +extern DATE_TIME_FORMAT global_date_format, global_datetime_format, global_time_format; extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[]; extern String null_string; extern HASH open_cache, lock_db_cache; extern TABLE *unused_tables; extern const char* any_db; -extern struct my_option my_long_options[]; extern const LEX_STRING view_type; extern scheduler_functions thread_scheduler; extern TYPELIB thread_handling_typelib; extern uint8 uc_update_queries[SQLCOM_END+1]; extern uint sql_command_flags[]; extern TYPELIB log_output_typelib; +extern const char *log_output_names[]; /* optional things, have_* variables */ +extern SHOW_COMP_OPTION have_csv, have_innodb; +extern SHOW_COMP_OPTION have_ndbcluster, have_partitioning; extern SHOW_COMP_OPTION have_profiling; extern handlerton *partition_hton; @@ -2057,6 +2138,9 @@ extern const char *load_default_groups[]; extern pthread_t signal_thread; #endif +extern char *opt_ssl_ca, *opt_ssl_capath, *opt_ssl_cert, *opt_ssl_cipher, + *opt_ssl_key; + #ifdef HAVE_OPENSSL extern struct st_VioSSLFd * ssl_acceptor_fd; #endif /* HAVE_OPENSSL */ @@ -2167,6 +2251,20 @@ bool calc_time_diff(MYSQL_TIME *l_time1, MYSQL_TIME *l_time2, int l_sign, extern LEX_STRING interval_type_to_name[]; + +bool parse_date_time_format(timestamp_type format_type, + const char *format, uint format_length, + DATE_TIME_FORMAT *date_time_format); +/* convenience wrapper */ +inline bool parse_date_time_format(timestamp_type format_type, + DATE_TIME_FORMAT *date_time_format) +{ + return parse_date_time_format(format_type, + date_time_format->format.str, + date_time_format->format.length, + date_time_format); +} + extern DATE_TIME_FORMAT *date_time_format_make(timestamp_type format_type, const char *format_str, uint format_length); @@ -2259,10 +2357,11 @@ uint build_table_shadow_filename(char *buff, size_t bufflen, #define FRM_ONLY (1 << 3) /* from hostname.cc */ -struct in_addr; -char * ip_to_hostname(struct in_addr *in,uint *errors); -void inc_host_errors(struct in_addr *in); -void reset_host_errors(struct in_addr *in); +bool ip_to_hostname(struct sockaddr_storage *ip_storage, + const char *ip_string, + char **hostname, uint *connect_errors); +void inc_host_errors(const char *ip_string); +void reset_host_errors(const char *ip_string); bool hostname_cache_init(); void hostname_cache_free(); void hostname_cache_refresh(void); @@ -2345,9 +2444,9 @@ inline const char *table_case_name(HA_CREATE_INFO *info, const char *name) inline ulong sql_rnd_with_mutex() { - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); ulong tmp=(ulong) (my_rnd(&sql_rand) * 0xffffffff); /* make all bits random */ - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); return tmp; } @@ -2433,6 +2532,11 @@ inline void kill_delayed_threads(void) {} #define check_stack_overrun(A, B, C) 0 #endif +/* This must match the path length limit in the ER_NOT_RW_DIR error msg. */ +#define ER_NOT_RW_DIR_PATHSIZE 200 +bool is_usable_directory(THD *thd, const char *varname, + const char *path, const char *prefix); + /* Used by handlers to store things in schema tables */ #define IS_FILES_FILE_ID 0 #define IS_FILES_FILE_NAME 1 @@ -2472,6 +2576,17 @@ inline void kill_delayed_threads(void) {} #define IS_FILES_CHECKSUM 35 #define IS_FILES_STATUS 36 #define IS_FILES_EXTRA 37 + +#define IS_TABLESPACES_TABLESPACE_NAME 0 +#define IS_TABLESPACES_ENGINE 1 +#define IS_TABLESPACES_TABLESPACE_TYPE 2 +#define IS_TABLESPACES_LOGFILE_GROUP_NAME 3 +#define IS_TABLESPACES_EXTENT_SIZE 4 +#define IS_TABLESPACES_AUTOEXTEND_SIZE 5 +#define IS_TABLESPACES_MAXIMUM_SIZE 6 +#define IS_TABLESPACES_NODEGROUP_ID 7 +#define IS_TABLESPACES_TABLESPACE_COMMENT 8 + void init_fill_schema_files_row(TABLE* table); bool schema_table_store_record(THD *thd, TABLE *table); @@ -2497,9 +2612,129 @@ bool load_collation(MEM_ROOT *mem_root, CHARSET_INFO *dflt_cl, CHARSET_INFO **cl); +#define LONG_TIMEOUT ((ulong) 3600L*24L*365L) + +/** + only options that need special treatment in get_one_option() deserve + to be listed below +*/ +enum options_mysqld +{ + OPT_to_set_the_start_number=256, + OPT_BIND_ADDRESS, + OPT_BINLOG_DO_DB, + OPT_BINLOG_FORMAT, + OPT_BINLOG_IGNORE_DB, + OPT_BIN_LOG, + OPT_BOOTSTRAP, + OPT_CONSOLE, + OPT_DEBUG_SYNC_TIMEOUT, + OPT_DELAY_KEY_WRITE_ALL, + OPT_ISAM_LOG, + OPT_KEY_BUFFER_SIZE, + OPT_KEY_CACHE_AGE_THRESHOLD, + OPT_KEY_CACHE_BLOCK_SIZE, + OPT_KEY_CACHE_DIVISION_LIMIT, + OPT_LOWER_CASE_TABLE_NAMES, + OPT_ONE_THREAD, + OPT_POOL_OF_THREADS, + OPT_REPLICATE_DO_DB, + OPT_REPLICATE_DO_TABLE, + OPT_REPLICATE_IGNORE_DB, + OPT_REPLICATE_IGNORE_TABLE, + OPT_REPLICATE_REWRITE_DB, + OPT_REPLICATE_WILD_DO_TABLE, + OPT_REPLICATE_WILD_IGNORE_TABLE, + OPT_SAFE, + OPT_SERVER_ID, + OPT_SKIP_HOST_CACHE, + OPT_SKIP_LOCK, + OPT_SKIP_NEW, + OPT_SKIP_PRIOR, + OPT_SKIP_RESOLVE, + OPT_SKIP_STACK_TRACE, + OPT_SKIP_SYMLINKS, + OPT_SLOW_QUERY_LOG, + OPT_SSL_CA, + OPT_SSL_CAPATH, + OPT_SSL_CERT, + OPT_SSL_CIPHER, + OPT_SSL_KEY, + OPT_UPDATE_LOG, + OPT_WANT_CORE, + OPT_ENGINE_CONDITION_PUSHDOWN +}; + #endif /* MYSQL_SERVER */ extern "C" int test_if_data_home_dir(const char *dir); #endif /* MYSQL_CLIENT */ +#ifdef MYSQL_SERVER +#ifdef HAVE_PSI_INTERFACE +#ifdef HAVE_MMAP +extern PSI_mutex_key key_PAGE_lock, key_LOCK_sync, key_LOCK_active, + key_LOCK_pool; +#endif /* HAVE_MMAP */ + +#ifdef HAVE_OPENSSL +extern PSI_mutex_key key_LOCK_des_key_file; +#endif + +extern PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_prep_xids, + key_delayed_insert_mutex, key_hash_filo_lock, key_LOCK_active_mi, + key_LOCK_connection_count, key_LOCK_crypt, key_LOCK_delayed_create, + key_LOCK_delayed_insert, key_LOCK_delayed_status, key_LOCK_error_log, + key_LOCK_gdl, key_LOCK_global_read_lock, key_LOCK_global_system_variables, + key_LOCK_lock_db, key_LOCK_logger, key_LOCK_manager, key_LOCK_mapped_file, + key_LOCK_mysql_create_db, key_LOCK_open, key_LOCK_prepared_stmt_count, + key_LOCK_rpl_status, key_LOCK_server_started, key_LOCK_status, + key_LOCK_table_share, key_LOCK_thd_data, + key_LOCK_user_conn, key_LOCK_uuid_generator, key_LOG_LOCK_log, + key_master_info_data_lock, key_master_info_run_lock, + key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock, + key_relay_log_info_log_space_lock, key_relay_log_info_run_lock, + key_structure_guard_mutex, key_TABLE_SHARE_mutex, key_LOCK_error_messages, + key_LOCK_thread_count; + +extern PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger, + key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave, + key_rwlock_LOCK_system_variables_hash, key_rwlock_query_cache_query_lock; + +#ifdef HAVE_MMAP +extern PSI_cond_key key_PAGE_cond, key_COND_active, key_COND_pool; +#endif /* HAVE_MMAP */ + +extern PSI_cond_key key_BINLOG_COND_prep_xids, key_BINLOG_update_cond, + key_COND_cache_status_changed, key_COND_global_read_lock, key_COND_manager, + key_COND_refresh, key_COND_rpl_status, key_COND_server_started, + key_delayed_insert_cond, key_delayed_insert_cond_client, + key_item_func_sleep_cond, key_master_info_data_cond, + key_master_info_start_cond, key_master_info_stop_cond, + key_relay_log_info_data_cond, key_relay_log_info_log_space_cond, + key_relay_log_info_start_cond, key_relay_log_info_stop_cond, + key_TABLE_SHARE_cond, key_user_level_lock_cond, + key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache; + +extern PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert, + key_thread_handle_manager, key_thread_kill_server, key_thread_main, + key_thread_one_connection, key_thread_signal_hand; + +#ifdef HAVE_MMAP +extern PSI_file_key key_file_map; +#endif /* HAVE_MMAP */ + +extern PSI_file_key key_file_binlog, key_file_binlog_index, key_file_casetest, + key_file_dbopt, key_file_des_key_file, key_file_ERRMSG, key_select_to_file, + key_file_fileparser, key_file_frm, key_file_global_ddl_log, key_file_load, + key_file_loadfile, key_file_log_event_data, key_file_log_event_info, + key_file_master_info, key_file_misc, key_file_MYSQL_LOG, key_file_partition, + key_file_pid, key_file_relay_log_info, key_file_send_file, key_file_tclog, + key_file_trg, key_file_trn, key_file_init; + +void init_server_psi_keys(); +#endif /* HAVE_PSI_INTERFACE */ +#endif /* MYSQL_SERVER */ + + #endif /* MYSQL_PRIV_H */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 90b6f3fe357..983f1750a38 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,10 +26,17 @@ #include "mysqld_suffix.h" #include "mysys_err.h" #include "events.h" +#include "sql_audit.h" #include "probes_mysql.h" #include "debug_sync.h" +#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE +#include "../storage/perfschema/pfs_server.h" +#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */ + +#include "keycaches.h" #include "../storage/myisam/ha_myisam.h" +#include "set_var.h" #include "rpl_injector.h" @@ -39,19 +46,6 @@ #include <sys/prctl.h> #endif -#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE -#if defined(NOT_ENOUGH_TESTED) \ - && defined(NDB_SHM_TRANSPORTER) && MYSQL_VERSION_ID >= 50000 -#define OPT_NDB_SHM_DEFAULT 1 -#else -#define OPT_NDB_SHM_DEFAULT 0 -#endif -#endif - -#ifndef DEFAULT_SKIP_THREAD_PRIORITY -#define DEFAULT_SKIP_THREAD_PRIORITY 0 -#endif - #include <thr_alarm.h> #include <ft_global.h> #include <errmsg.h> @@ -60,18 +54,6 @@ #define mysqld_charset &my_charset_latin1 -#ifdef HAVE_purify -#define IF_PURIFY(A,B) (A) -#else -#define IF_PURIFY(A,B) (B) -#endif - -#if SIZEOF_CHARP == 4 -#define MAX_MEM_TABLE_SIZE ~(ulong) 0 -#else -#define MAX_MEM_TABLE_SIZE ~(ulonglong) 0 -#endif - /* stack traces are only supported on linux intel */ #if defined(__linux__) && defined(__i386__) && defined(USE_PSTACK) #define HAVE_STACK_TRACE_ON_SEGV @@ -110,7 +92,6 @@ extern "C" { // Because of SCO 3.2V4.2 #ifdef HAVE_SYS_UN_H # include <sys/un.h> #endif -#include <netdb.h> #ifdef HAVE_SELECT_H # include <select.h> #endif @@ -180,7 +161,7 @@ static void registerwithneb(); static void getvolumename(); static void getvolumeID(BYTE *volumeName); #endif /* __NETWARE__ */ - + #ifdef _AIX41 int initgroups(const char *,unsigned int); @@ -196,6 +177,18 @@ typedef fp_except fp_except_t; /* for IRIX to use set_fpc_csr() */ #include <sys/fpu.h> #endif +#if defined(__i386__) && !defined(HAVE_FPU_CONTROL_H) +# define fpu_control_t unsigned int +# define _FPU_EXTENDED 0x300 +# define _FPU_DOUBLE 0x200 +# ifdef __GNUC__ +# define _FPU_GETCW(cw) __asm__ __volatile__("fnstcw %0" : "=m" (*&cw)) +# define _FPU_SETCW(cw) __asm__ __volatile__("fldcw %0" : : "m" (*&cw)) +# else +# define _FPU_GETCW(cw) (cw= 0) +# define _FPU_SETCW(cw) +# endif +#endif inline void setup_fpu() { @@ -217,7 +210,26 @@ inline void setup_fpu() /* Set FPU rounding mode to "round-to-nearest" */ fesetround(FE_TONEAREST); #endif /* HAVE_FESETROUND */ - + + /* + x86 (32-bit) requires FPU precision to be explicitly set to 64 bit + (double precision) for portable results of floating point operations. + However, there is no need to do so if compiler is using SSE2 for floating + point, double values will be stored and processed in 64 bits anyway. + */ +#if defined(__i386__) && !defined(__SSE2_MATH__) +#if defined(_WIN32) +#if !defined(_WIN64) + _control87(_PC_53, MCW_PC); +#endif /* !_WIN64 */ +#else /* !_WIN32 */ + fpu_control_t cw; + _FPU_GETCW(cw); + cw= (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE; + _FPU_SETCW(cw); +#endif /* _WIN32 && */ +#endif /* __i386__ */ + #if defined(__sgi) && defined(HAVE_SYS_FPU_H) /* Enable denormalized DOUBLE values support for IRIX */ union fpc_csr n; @@ -252,85 +264,6 @@ extern "C" sig_handler handle_segfault(int sig); /* Constants */ const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"}; -/* - WARNING: When adding new SQL modes don't forget to update the - tables definitions that stores it's value. - (ie: mysql.event, mysql.proc) -*/ -static const char *sql_mode_names[]= -{ - "REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE", - "?", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION", - "NO_DIR_IN_CREATE", - "POSTGRESQL", "ORACLE", "MSSQL", "DB2", "MAXDB", "NO_KEY_OPTIONS", - "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI", - "NO_AUTO_VALUE_ON_ZERO", "NO_BACKSLASH_ESCAPES", "STRICT_TRANS_TABLES", - "STRICT_ALL_TABLES", - "NO_ZERO_IN_DATE", "NO_ZERO_DATE", "ALLOW_INVALID_DATES", - "ERROR_FOR_DIVISION_BY_ZERO", - "TRADITIONAL", "NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE", - "NO_ENGINE_SUBSTITUTION", - "PAD_CHAR_TO_FULL_LENGTH", - NullS -}; - -static const unsigned int sql_mode_names_len[]= -{ - /*REAL_AS_FLOAT*/ 13, - /*PIPES_AS_CONCAT*/ 15, - /*ANSI_QUOTES*/ 11, - /*IGNORE_SPACE*/ 12, - /*?*/ 1, - /*ONLY_FULL_GROUP_BY*/ 18, - /*NO_UNSIGNED_SUBTRACTION*/ 23, - /*NO_DIR_IN_CREATE*/ 16, - /*POSTGRESQL*/ 10, - /*ORACLE*/ 6, - /*MSSQL*/ 5, - /*DB2*/ 3, - /*MAXDB*/ 5, - /*NO_KEY_OPTIONS*/ 14, - /*NO_TABLE_OPTIONS*/ 16, - /*NO_FIELD_OPTIONS*/ 16, - /*MYSQL323*/ 8, - /*MYSQL40*/ 7, - /*ANSI*/ 4, - /*NO_AUTO_VALUE_ON_ZERO*/ 21, - /*NO_BACKSLASH_ESCAPES*/ 20, - /*STRICT_TRANS_TABLES*/ 19, - /*STRICT_ALL_TABLES*/ 17, - /*NO_ZERO_IN_DATE*/ 15, - /*NO_ZERO_DATE*/ 12, - /*ALLOW_INVALID_DATES*/ 19, - /*ERROR_FOR_DIVISION_BY_ZERO*/ 26, - /*TRADITIONAL*/ 11, - /*NO_AUTO_CREATE_USER*/ 19, - /*HIGH_NOT_PRECEDENCE*/ 19, - /*NO_ENGINE_SUBSTITUTION*/ 22, - /*PAD_CHAR_TO_FULL_LENGTH*/ 23 -}; - -TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"", - sql_mode_names, - (unsigned int *)sql_mode_names_len }; - -static const char *optimizer_switch_names[]= -{ - "index_merge","index_merge_union","index_merge_sort_union", - "index_merge_intersection", "default", NullS -}; -/* Corresponding defines are named OPTIMIZER_SWITCH_XXX */ -static const unsigned int optimizer_switch_names_len[]= -{ - sizeof("index_merge") - 1, - sizeof("index_merge_union") - 1, - sizeof("index_merge_sort_union") - 1, - sizeof("index_merge_intersection") - 1, - sizeof("default") - 1 -}; -TYPELIB optimizer_switch_typelib= { array_elements(optimizer_switch_names)-1,"", - optimizer_switch_names, - (unsigned int *)optimizer_switch_names_len }; static const char *tc_heuristic_recover_names[]= { @@ -342,26 +275,8 @@ static TYPELIB tc_heuristic_recover_typelib= tc_heuristic_recover_names, NULL }; -static const char *thread_handling_names[]= -{ "one-thread-per-connection", "no-threads", -#if HAVE_POOL_OF_THREADS == 1 - "pool-of-threads", -#endif - NullS}; - -TYPELIB thread_handling_typelib= -{ - array_elements(thread_handling_names) - 1, "", - thread_handling_names, NULL -}; - const char *first_keyword= "first", *binary_keyword= "BINARY"; const char *my_localhost= "localhost", *delayed_user= "DELAYED"; -#if SIZEOF_OFF_T > 4 && defined(BIG_TABLES) -#define GET_HA_ROWS GET_ULL -#else -#define GET_HA_ROWS GET_ULONG -#endif bool opt_large_files= sizeof(my_off_t) > 4; @@ -385,6 +300,29 @@ TYPELIB log_output_typelib= {array_elements(log_output_names)-1,"", /* static variables */ +#ifdef HAVE_PSI_INTERFACE +#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY) +static PSI_thread_key key_thread_handle_con_namedpipes; +static PSI_cond_key key_COND_handler_count; +#endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */ + +#if defined(HAVE_SMEM) && !defined(EMBEDDED_LIBRARY) +static PSI_thread_key key_thread_handle_con_sharedmem; +#endif /* HAVE_SMEM && !EMBEDDED_LIBRARY */ + +#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY) +static PSI_thread_key key_thread_handle_con_sockets; +#endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */ + +#ifdef __WIN__ +static PSI_thread_key key_thread_handle_shutdown; +#endif /* __WIN__ */ + +#if defined (HAVE_OPENSSL) && !defined(HAVE_YASSL) +static PSI_rwlock_key key_rwlock_openssl; +#endif +#endif /* HAVE_PSI_INTERFACE */ + /* the default log output is log tables */ static bool lower_case_table_names_used= 0; static bool volatile select_thread_in_use, signal_thread_in_use; @@ -392,35 +330,30 @@ static bool volatile ready_to_exit; static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0; static my_bool opt_short_log_format= 0; static uint kill_cached_threads, wake_thread; -static ulong killed_threads, thread_created; +static ulong killed_threads; static ulong max_used_connections; -static ulong my_bind_addr; /**< the address we bind to */ static volatile ulong cached_thread_count= 0; -static const char *sql_mode_str= "OFF"; -/* Text representation for OPTIMIZER_SWITCH_DEFAULT */ -static const char *optimizer_switch_str="index_merge=on,index_merge_union=on," - "index_merge_sort_union=on," - "index_merge_intersection=on"; -static char *mysqld_user, *mysqld_chroot, *log_error_file_ptr; -static char *opt_init_slave, *lc_messages_dir_ptr, *opt_init_connect; +static char *mysqld_user, *mysqld_chroot; static char *default_character_set_name; static char *character_set_filesystem_name; static char *lc_messages; static char *lc_time_names_name; static char *my_bind_addr_str; -static char *default_collation_name; -static char *default_storage_engine_str; +static char *default_collation_name; +char *default_storage_engine; static char compiled_default_collation_name[]= MYSQL_DEFAULT_COLLATION_NAME; static I_List<THD> thread_cache; -static double long_query_time; +static bool binlog_format_used= false; + +LEX_STRING opt_init_connect, opt_init_slave; -static pthread_cond_t COND_thread_cache, COND_flush_thread_cache; +static mysql_cond_t COND_thread_cache, COND_flush_thread_cache; /* Global variables */ bool opt_update_log, opt_bin_log, opt_ignore_builtin_innodb= 0; my_bool opt_log, opt_slow_log; -ulong log_output_options; +ulonglong log_output_options; my_bool opt_log_queries_not_using_indexes= 0; bool opt_error_log= IF_WIN(1,0); bool opt_disable_networking=0, opt_skip_show_db=0; @@ -462,7 +395,13 @@ my_bool opt_local_infile, opt_slave_compressed_protocol; my_bool opt_safe_user_create = 0, opt_no_mix_types = 0; my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0; my_bool opt_log_slave_updates= 0; -bool slave_warning_issued = false; +char *opt_slave_skip_errors; + +/** + compatibility option: + - index usage hints (USE INDEX without a FOR clause) behave as in 5.0 +*/ +my_bool old_mode; /* Legacy global handlerton. These will be removed (please do not add more). @@ -471,38 +410,18 @@ handlerton *heap_hton; handlerton *myisam_hton; handlerton *partition_hton; -#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE -const char *opt_ndbcluster_connectstring= 0; -const char *opt_ndb_connectstring= 0; -char opt_ndb_constrbuf[1024]= {0}; -unsigned opt_ndb_constrbuf_len= 0; -my_bool opt_ndb_shm, opt_ndb_optimized_node_selection; -ulong opt_ndb_cache_check_time; -const char *opt_ndb_mgmd; -ulong opt_ndb_nodeid; -ulong ndb_extra_logging; -#ifdef HAVE_NDB_BINLOG -ulong ndb_report_thresh_binlog_epoch_slip; -ulong ndb_report_thresh_binlog_mem_usage; -#endif - -extern const char *ndb_distribution_names[]; -extern TYPELIB ndb_distribution_typelib; -extern const char *opt_ndb_distribution; -extern enum ndb_distribution opt_ndb_distribution_id; -#endif -my_bool opt_readonly, use_temp_pool, relay_log_purge; +my_bool opt_readonly= 0, use_temp_pool, relay_log_purge; my_bool relay_log_recovery; my_bool opt_sync_frm, opt_allow_suspicious_udfs; my_bool opt_secure_auth= 0; -char* opt_secure_file_priv= 0; +char* opt_secure_file_priv; my_bool opt_log_slow_admin_statements= 0; my_bool opt_log_slow_slave_statements= 0; my_bool lower_case_file_system= 0; my_bool opt_large_pages= 0; my_bool opt_super_large_pages= 0; my_bool opt_myisam_use_mmap= 0; -uint opt_large_page_size= 0; +uint opt_large_page_size= 0; #if defined(ENABLED_DEBUG_SYNC) uint opt_debug_sync_timeout= 0; #endif /* defined(ENABLED_DEBUG_SYNC) */ @@ -521,32 +440,34 @@ const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS}; TYPELIB binlog_format_typelib= { array_elements(binlog_format_names) - 1, "", binlog_format_names, NULL }; -ulong opt_binlog_format_id= (ulong) BINLOG_FORMAT_UNSPEC; -const char *opt_binlog_format= binlog_format_names[opt_binlog_format_id]; #ifdef HAVE_INITGROUPS static bool calling_initgroups= FALSE; /**< Used in SIGSEGV handler. */ #endif uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options; uint mysqld_port_timeout; -uint delay_key_write_options, protocol_version; +uint delay_key_write_options; +uint protocol_version; uint lower_case_table_names; uint tc_heuristic_recover= 0; -uint volatile thread_count, thread_running; -ulonglong thd_startup_options; +uint volatile thread_count; +int32 thread_running; +ulong thread_created; ulong back_log, connect_timeout, concurrency, server_id; ulong table_cache_size, table_def_size; ulong what_to_log; ulong query_buff_size, slow_launch_time, slave_open_temp_tables; ulong open_files_limit, max_binlog_size, max_relay_log_size; ulong slave_net_timeout, slave_trans_retries; -ulong slave_exec_mode_options; -const char *slave_exec_mode_str= "STRICT"; +uint slave_exec_mode_options; +ulonglong slave_type_conversions_options; ulong thread_cache_size=0, thread_pool_size= 0; ulong binlog_cache_size=0; ulonglong max_binlog_cache_size=0; ulong query_cache_size=0; ulong refresh_version; /* Increments on each reload */ query_id_t global_query_id; +my_atomic_rwlock_t global_query_id_lock; +my_atomic_rwlock_t thread_running_lock; ulong aborted_threads, aborted_connects; ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size; ulong delayed_insert_threads, delayed_insert_writes, delayed_rows_in_use; @@ -554,7 +475,6 @@ ulong delayed_insert_errors,flush_time; ulong specialflag=0; ulong binlog_cache_use= 0, binlog_cache_disk_use= 0; ulong max_connections, max_connect_errors; -uint max_user_connections= 0; /** Limit of the total number of prepared statements in the server. Is necessary to protect the server against out-of-memory attacks. @@ -577,7 +497,40 @@ uint sync_binlog_period= 0, sync_relaylog_period= 0, sync_relayloginfo_period= 0, sync_masterinfo_period= 0; ulong expire_logs_days = 0; ulong rpl_recovery_rank=0; -const char *log_output_str= "FILE"; + +const double log_10[] = { + 1e000, 1e001, 1e002, 1e003, 1e004, 1e005, 1e006, 1e007, 1e008, 1e009, + 1e010, 1e011, 1e012, 1e013, 1e014, 1e015, 1e016, 1e017, 1e018, 1e019, + 1e020, 1e021, 1e022, 1e023, 1e024, 1e025, 1e026, 1e027, 1e028, 1e029, + 1e030, 1e031, 1e032, 1e033, 1e034, 1e035, 1e036, 1e037, 1e038, 1e039, + 1e040, 1e041, 1e042, 1e043, 1e044, 1e045, 1e046, 1e047, 1e048, 1e049, + 1e050, 1e051, 1e052, 1e053, 1e054, 1e055, 1e056, 1e057, 1e058, 1e059, + 1e060, 1e061, 1e062, 1e063, 1e064, 1e065, 1e066, 1e067, 1e068, 1e069, + 1e070, 1e071, 1e072, 1e073, 1e074, 1e075, 1e076, 1e077, 1e078, 1e079, + 1e080, 1e081, 1e082, 1e083, 1e084, 1e085, 1e086, 1e087, 1e088, 1e089, + 1e090, 1e091, 1e092, 1e093, 1e094, 1e095, 1e096, 1e097, 1e098, 1e099, + 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109, + 1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119, + 1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129, + 1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139, + 1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149, + 1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159, + 1e160, 1e161, 1e162, 1e163, 1e164, 1e165, 1e166, 1e167, 1e168, 1e169, + 1e170, 1e171, 1e172, 1e173, 1e174, 1e175, 1e176, 1e177, 1e178, 1e179, + 1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186, 1e187, 1e188, 1e189, + 1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, 1e197, 1e198, 1e199, + 1e200, 1e201, 1e202, 1e203, 1e204, 1e205, 1e206, 1e207, 1e208, 1e209, + 1e210, 1e211, 1e212, 1e213, 1e214, 1e215, 1e216, 1e217, 1e218, 1e219, + 1e220, 1e221, 1e222, 1e223, 1e224, 1e225, 1e226, 1e227, 1e228, 1e229, + 1e230, 1e231, 1e232, 1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239, + 1e240, 1e241, 1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249, + 1e250, 1e251, 1e252, 1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259, + 1e260, 1e261, 1e262, 1e263, 1e264, 1e265, 1e266, 1e267, 1e268, 1e269, + 1e270, 1e271, 1e272, 1e273, 1e274, 1e275, 1e276, 1e277, 1e278, 1e279, + 1e280, 1e281, 1e282, 1e283, 1e284, 1e285, 1e286, 1e287, 1e288, 1e289, + 1e290, 1e291, 1e292, 1e293, 1e294, 1e295, 1e296, 1e297, 1e298, 1e299, + 1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307, 1e308 +}; time_t server_start_time, flush_status_time; @@ -588,25 +541,26 @@ char log_error_file[FN_REFLEN], glob_hostname[FN_REFLEN]; char mysql_real_data_home[FN_REFLEN], lc_messages_dir[FN_REFLEN], reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN], - *opt_init_file, *opt_tc_log_file, - def_ft_boolean_syntax[sizeof(ft_boolean_syntax)]; + *opt_init_file, *opt_tc_log_file; +char *lc_messages_dir_ptr, *log_error_file_ptr; char err_shared_dir[FN_REFLEN]; char mysql_unpacked_real_data_home[FN_REFLEN]; int mysql_unpacked_real_data_home_len; +uint mysql_real_data_home_len, mysql_data_home_len= 1; uint reg_ext_length; const key_map key_map_empty(0); key_map key_map_full(0); // Will be initialized later -const char *opt_date_time_formats[3]; +DATE_TIME_FORMAT global_date_format, global_datetime_format, global_time_format; +Time_zone *default_tz; -uint mysql_data_home_len; -char mysql_data_home_buff[2], *mysql_data_home=mysql_real_data_home; +char *mysql_data_home= const_cast<char*>("."); +const char *mysql_real_data_home_ptr= mysql_real_data_home; char server_version[SERVER_VERSION_LENGTH]; char *mysqld_unix_port, *opt_mysql_tmpdir; -const char *myisam_recover_options_str="OFF"; -const char *myisam_stats_method_str="nulls_unequal"; +uint thread_handling; -/** name of reference on left espression in rewritten IN subquery */ +/** name of reference on left expression in rewritten IN subquery */ const char *in_left_expr_name= "<left expr>"; /** name of additional condition */ const char *in_additional_cond= "<IN COND>"; @@ -621,12 +575,11 @@ Lt_creator lt_creator; Ge_creator ge_creator; Le_creator le_creator; -FILE *bootstrap_file; +MYSQL_FILE *bootstrap_file; int bootstrap_error; FILE *stderror_file=0; I_List<THD> threads; -I_List<NAMED_LIST> key_caches; Rpl_filter* rpl_filter; Rpl_filter* binlog_filter; @@ -654,14 +607,15 @@ SHOW_COMP_OPTION have_profiling; pthread_key(MEM_ROOT**,THR_MALLOC); pthread_key(THD*, THR_THD); -pthread_mutex_t LOCK_mysql_create_db, LOCK_open, LOCK_thread_count, - LOCK_mapped_file, LOCK_status, LOCK_global_read_lock, - LOCK_error_log, LOCK_uuid_generator, - LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create, - LOCK_crypt, - LOCK_global_system_variables, - LOCK_user_conn, LOCK_slave_list, LOCK_active_mi, - LOCK_connection_count, LOCK_error_messages; +mysql_mutex_t LOCK_thread_count; +mysql_mutex_t LOCK_mysql_create_db, LOCK_open, + LOCK_mapped_file, LOCK_status, LOCK_global_read_lock, + LOCK_error_log, LOCK_uuid_generator, + LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create, + LOCK_crypt, + LOCK_global_system_variables, + LOCK_user_conn, LOCK_slave_list, LOCK_active_mi, + LOCK_connection_count, LOCK_error_messages; /** The below lock protects access to two global server variables: max_prepared_stmt_count and prepared_stmt_count. These variables @@ -669,32 +623,29 @@ pthread_mutex_t LOCK_mysql_create_db, LOCK_open, LOCK_thread_count, in the server, respectively. As PREPARE/DEALLOCATE rate in a loaded server may be fairly high, we need a dedicated lock. */ -pthread_mutex_t LOCK_prepared_stmt_count; +mysql_mutex_t LOCK_prepared_stmt_count; #ifdef HAVE_OPENSSL -pthread_mutex_t LOCK_des_key_file; +mysql_mutex_t LOCK_des_key_file; #endif -rw_lock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave; -rw_lock_t LOCK_system_variables_hash; -pthread_cond_t COND_refresh, COND_thread_count, COND_global_read_lock; +mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave; +mysql_rwlock_t LOCK_system_variables_hash; +mysql_cond_t COND_thread_count; +mysql_cond_t COND_refresh, COND_global_read_lock; pthread_t signal_thread; pthread_attr_t connection_attrib; -pthread_mutex_t LOCK_server_started; -pthread_cond_t COND_server_started; +mysql_mutex_t LOCK_server_started; +mysql_cond_t COND_server_started; int mysqld_server_started= 0; File_parser_dummy_hook file_parser_dummy_hook; /* replication parameters, if master_host is not NULL, we are a slave */ -uint master_port= MYSQL_PORT, master_connect_retry = 60; uint report_port= MYSQL_PORT; ulong master_retry_count=0; -char *master_user, *master_password, *master_host, *master_info_file; +char *master_info_file; char *relay_log_info_file, *report_user, *report_password, *report_host; char *opt_relay_logname = 0, *opt_relaylog_index_name=0; -my_bool master_ssl; -char *master_ssl_key, *master_ssl_cert; -char *master_ssl_ca, *master_ssl_capath, *master_ssl_cipher; char *opt_logname, *opt_slow_logname; /* Static variables */ @@ -705,17 +656,179 @@ static my_bool opt_do_pstack; #endif /* HAVE_STACK_TRACE_ON_SEGV */ static my_bool opt_bootstrap, opt_myisam_log; static int cleanup_done; -static ulong opt_specialflag, opt_myisam_block_size; +static ulong opt_specialflag; static char *opt_update_logname, *opt_binlog_index_name; -static char *opt_tc_heuristic_recover; -static char *mysql_home_ptr, *pidfile_name_ptr; +char *mysql_home_ptr, *pidfile_name_ptr; +/** Initial command line arguments (count), after load_defaults().*/ static int defaults_argc; +/** + Initial command line arguments (arguments), after load_defaults(). + This memory is allocated by @c load_defaults() and should be freed + using @c free_defaults(). + Do not modify defaults_argc / defaults_argv, + use remaining_argc / remaining_argv instead to parse the command + line arguments in multiple steps. +*/ static char **defaults_argv; +/** Remaining command line arguments (count), filtered by handle_options().*/ +static int remaining_argc; +/** Remaining command line arguments (arguments), filtered by handle_options().*/ +static char **remaining_argv; static char *opt_bin_logname; int orig_argc; char **orig_argv; +/* + Since buffered_option_error_reporter is only used currently + for parsing performance schema options, this code is not needed + when the performance schema is not compiled in. +*/ +#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE +/** + A log message for the error log, buffered in memory. + Log messages are temporarily buffered when generated before the error log + is initialized, and then printed once the error log is ready. +*/ +class Buffered_log : public Sql_alloc +{ +public: + Buffered_log(enum loglevel level, const char *message); + + ~Buffered_log() + {} + + void print(void); + +private: + /** Log message level. */ + enum loglevel m_level; + /** Log message text. */ + String m_message; +}; + +/** + Constructor. + @param level the message log level + @param message the message text +*/ +Buffered_log::Buffered_log(enum loglevel level, const char *message) + : m_level(level), m_message() +{ + m_message.copy(message, strlen(message), &my_charset_latin1); +} + +/** + Print a buffered log to the real log file. +*/ +void Buffered_log::print() +{ + /* + Since messages are buffered, they can be printed out + of order with other entries in the log. + Add "Buffered xxx" to the message text to prevent confusion. + */ + switch(m_level) + { + case ERROR_LEVEL: + sql_print_error("Buffered error: %s\n", m_message.c_ptr_safe()); + break; + case WARNING_LEVEL: + sql_print_warning("Buffered warning: %s\n", m_message.c_ptr_safe()); + break; + case INFORMATION_LEVEL: + sql_print_information("Buffered information: %s\n", m_message.c_ptr_safe()); + break; + } +} + +/** + Collection of all the buffered log messages. +*/ +class Buffered_logs +{ +public: + Buffered_logs() + {} + + ~Buffered_logs() + {} + + void init(); + void cleanup(); + + void buffer(enum loglevel m_level, const char *msg); + void print(); +private: + /** + Memory root to use to store buffered logs. + This memory root lifespan is between init and cleanup. + Once the buffered logs are printed, they are not needed anymore, + and all the memory used is reclaimed. + */ + MEM_ROOT m_root; + /** List of buffered log messages. */ + List<Buffered_log> m_list; +}; + +void Buffered_logs::init() +{ + init_alloc_root(&m_root, 1024, 0); +} + +void Buffered_logs::cleanup() +{ + m_list.delete_elements(); + free_root(&m_root, MYF(0)); +} + +/** + Add a log message to the buffer. +*/ +void Buffered_logs::buffer(enum loglevel level, const char *msg) +{ + /* + Do not let Sql_alloc::operator new(size_t) allocate memory, + there is no memory root associated with the main() thread. + Give explicitly the proper memory root to use to + Sql_alloc::operator new(size_t, MEM_ROOT *) instead. + */ + Buffered_log *log= new (&m_root) Buffered_log(level, msg); + if (log) + m_list.push_back(log, &m_root); +} + +/** + Print buffered log messages. +*/ +void Buffered_logs::print() +{ + Buffered_log *log; + List_iterator_fast<Buffered_log> it(m_list); + while ((log= it++)) + log->print(); +} + +/** Logs reported before a logger is available. */ +static Buffered_logs buffered_logs; + +/** + Error reporter that buffer log messages. + @param level log message level + @param format log message format string +*/ +void buffered_option_error_reporter(enum loglevel level, const char *format, ...) +{ + va_list args; + char buffer[1024]; + + va_start(args, format); + my_vsnprintf(buffer, sizeof(buffer), format, args); + va_end(args); + buffered_logs.buffer(level, buffer); +} +#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */ + static my_socket unix_sock,ip_sock; struct rand_struct sql_rand; ///< used by sql_class.cc:THD::THD() @@ -731,7 +844,7 @@ static uint thr_kill_signal; #undef getpid #include <process.h> -static pthread_cond_t COND_handler_count; +static mysql_cond_t COND_handler_count; static uint handler_count; static bool start_mode=0, use_opt_args; static int opt_argc; @@ -769,7 +882,6 @@ int allow_severity = LOG_INFO; int deny_severity = LOG_WARNING; #endif #ifdef HAVE_QUERY_CACHE -static ulong query_cache_limit= 0; ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE; Query_cache query_cache; #endif @@ -781,14 +893,16 @@ HANDLE smem_event_connect_request= 0; scheduler_functions thread_scheduler; -#define SSL_VARS_NOT_STATIC -#include "sslopt-vars.h" +my_bool opt_use_ssl = 0; +char *opt_ssl_ca= NULL, *opt_ssl_capath= NULL, *opt_ssl_cert= NULL, + *opt_ssl_cipher= NULL, *opt_ssl_key= NULL; + #ifdef HAVE_OPENSSL #include <openssl/crypto.h> #ifndef HAVE_YASSL typedef struct CRYPTO_dynlock_value { - rw_lock_t lock; + mysql_rwlock_t lock; } openssl_lock_t; static openssl_lock_t *openssl_stdlocks; @@ -812,7 +926,9 @@ uint connection_count= 0; pthread_handler_t signal_hand(void *arg); static int mysql_init_variables(void); -static int get_options(int *argc,char **argv); +extern "C" void option_error_reporter(enum loglevel level, const char *format, ...); +static int get_options(int *argc_ptr, char ***argv_ptr); +static bool add_terminator(DYNAMIC_ARRAY *options); extern "C" my_bool mysqld_get_one_option(int, const struct my_option *, char *); static void set_server_version(void); static int init_thread_environment(); @@ -823,7 +939,7 @@ void handle_connections_sockets(); pthread_handler_t handle_connections_sockets_thread(void *arg); #endif pthread_handler_t kill_server_thread(void *arg); -static void bootstrap(FILE *file); +static void bootstrap(MYSQL_FILE *file); static bool read_init_file(char *file_name); #ifdef _WIN32 pthread_handler_t handle_connections_namedpipes(void *arg); @@ -832,9 +948,6 @@ pthread_handler_t handle_connections_namedpipes(void *arg); pthread_handler_t handle_connections_shared_memory(void *arg); #endif pthread_handler_t handle_slave(void *arg); -static ulong find_bit_type(const char *x, TYPELIB *bit_lib); -static ulong find_bit_type_or_exit(const char *x, TYPELIB *bit_lib, - const char *option, int *error); static void clean_up(bool print_message); static int test_if_case_insensitive(const char *dir_name); @@ -845,6 +958,7 @@ static void close_server_sock(); static void clean_up_mutexes(void); static void wait_for_signal_thread_to_end(void); static void create_pid_file(); +static void mysqld_exit(int exit_code) __attribute__((noreturn)); static void end_ssl(); #endif @@ -869,7 +983,7 @@ static void close_connections(void) #if !defined(__WIN__) && !defined(__NETWARE__) DBUG_PRINT("quit", ("waiting for select thread: 0x%lx", (ulong) select_thread)); - (void) pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); while (select_thread_in_use) { @@ -885,18 +999,18 @@ static void close_connections(void) set_timespec(abstime, 2); for (uint tmp=0 ; tmp < 10 && select_thread_in_use; tmp++) { - error=pthread_cond_timedwait(&COND_thread_count,&LOCK_thread_count, - &abstime); + error= mysql_cond_timedwait(&COND_thread_count, &LOCK_thread_count, + &abstime); if (error != EINTR) break; } #ifdef EXTRA_DEBUG if (error != 0 && !count++) - sql_print_error("Got error %d from pthread_cond_timedwait",error); + sql_print_error("Got error %d from mysql_cond_timedwait", error); #endif close_server_sock(); } - (void) pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); #endif /* __WIN__ */ @@ -953,7 +1067,7 @@ static void close_connections(void) */ THD *tmp; - (void) pthread_mutex_lock(&LOCK_thread_count); // For unlink from list + mysql_mutex_lock(&LOCK_thread_count); // For unlink from list I_List_iterator<THD> it(threads); while ((tmp=it++)) @@ -969,17 +1083,17 @@ static void close_connections(void) if (tmp->mysys_var) { tmp->mysys_var->abort=1; - pthread_mutex_lock(&tmp->mysys_var->mutex); + mysql_mutex_lock(&tmp->mysys_var->mutex); if (tmp->mysys_var->current_cond) { - pthread_mutex_lock(tmp->mysys_var->current_mutex); - pthread_cond_broadcast(tmp->mysys_var->current_cond); - pthread_mutex_unlock(tmp->mysys_var->current_mutex); + mysql_mutex_lock(tmp->mysys_var->current_mutex); + mysql_cond_broadcast(tmp->mysys_var->current_cond); + mysql_mutex_unlock(tmp->mysys_var->current_mutex); } - pthread_mutex_unlock(&tmp->mysys_var->mutex); + mysql_mutex_unlock(&tmp->mysys_var->mutex); } } - (void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list + mysql_mutex_unlock(&LOCK_thread_count); // For unlink from list Events::deinit(); end_slave(); @@ -996,11 +1110,11 @@ static void close_connections(void) for (;;) { DBUG_PRINT("quit",("Locking LOCK_thread_count")); - (void) pthread_mutex_lock(&LOCK_thread_count); // For unlink from list + mysql_mutex_lock(&LOCK_thread_count); // For unlink from list if (!(tmp=threads.get())) { DBUG_PRINT("quit",("Unlocking LOCK_thread_count")); - (void) pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); break; } #ifndef __bsdi__ // Bug in BSDI kernel @@ -1015,17 +1129,17 @@ static void close_connections(void) } #endif DBUG_PRINT("quit",("Unlocking LOCK_thread_count")); - (void) pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); } /* All threads has now been aborted */ DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count)); - (void) pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); while (thread_count) { - (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count); + mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); DBUG_PRINT("quit",("One thread died (count=%u)",thread_count)); } - (void) pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); close_active_mi(); DBUG_PRINT("quit",("close_connections thread")); @@ -1043,14 +1157,14 @@ static void close_server_sock() { ip_sock=INVALID_SOCKET; DBUG_PRINT("info",("calling shutdown on TCP/IP socket")); - VOID(shutdown(tmp_sock, SHUT_RDWR)); + (void) shutdown(tmp_sock, SHUT_RDWR); #if defined(__NETWARE__) /* The following code is disabled for normal systems as it causes MySQL to hang on AIX 4.3 during shutdown */ DBUG_PRINT("info",("calling closesocket on TCP/IP socket")); - VOID(closesocket(tmp_sock)); + (void) closesocket(tmp_sock); #endif } tmp_sock=unix_sock; @@ -1058,16 +1172,16 @@ static void close_server_sock() { unix_sock=INVALID_SOCKET; DBUG_PRINT("info",("calling shutdown on unix socket")); - VOID(shutdown(tmp_sock, SHUT_RDWR)); + (void) shutdown(tmp_sock, SHUT_RDWR); #if defined(__NETWARE__) /* The following code is disabled for normal systems as it may cause MySQL to hang on AIX 4.3 during shutdown */ DBUG_PRINT("info",("calling closesocket on unix/IP socket")); - VOID(closesocket(tmp_sock)); + (void) closesocket(tmp_sock); #endif - VOID(unlink(mysqld_unix_port)); + (void) unlink(mysqld_unix_port); } DBUG_VOID_RETURN; #endif @@ -1115,8 +1229,9 @@ void kill_mysql(void) { pthread_t tmp; abort_loop=1; - if (pthread_create(&tmp,&connection_attrib, kill_server_thread, - (void*) 0)) + if (mysql_thread_create(0, /* Not instrumented */ + &tmp, &connection_attrib, kill_server_thread, + (void*) 0)) sql_print_error("Can't create thread to kill server"); } #endif @@ -1233,6 +1348,18 @@ extern "C" sig_handler print_signal_warning(int sig) #ifndef EMBEDDED_LIBRARY +static void init_error_log_mutex() +{ + mysql_mutex_init(key_LOCK_error_log, &LOCK_error_log, MY_MUTEX_INIT_FAST); +} + + +static void clean_up_error_log_mutex() +{ + mysql_mutex_destroy(&LOCK_error_log); +} + + /** cleanup all memory and end program nicely. @@ -1254,6 +1381,7 @@ void unireg_end(void) #endif } + extern "C" void unireg_abort(int exit_code) { DBUG_ENTER("unireg_abort"); @@ -1264,14 +1392,25 @@ extern "C" void unireg_abort(int exit_code) sql_print_error("Aborting\n"); clean_up(!opt_help && (exit_code || !opt_bootstrap)); /* purecov: inspected */ DBUG_PRINT("quit",("done with cleanup in unireg_abort")); + mysqld_exit(exit_code); +} + +static void mysqld_exit(int exit_code) +{ + /* + Important note: we wait for the signal thread to end, + but if a kill -15 signal was sent, the signal thread did + spawn the kill_server_thread thread, which is running concurrently. + */ wait_for_signal_thread_to_end(); + mysql_audit_finalize(); clean_up_mutexes(); + clean_up_error_log_mutex(); my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); exit(exit_code); /* purecov: inspected */ } -#endif /*EMBEDDED_LIBRARY*/ - +#endif /* !EMBEDDED_LIBRARY */ void clean_up(bool print_message) { @@ -1311,7 +1450,6 @@ void clean_up(bool print_message) item_user_lock_free(); lex_free(); /* Free some memory */ item_create_cleanup(); - set_var_free(); if (!opt_noacl) { #ifdef HAVE_DLOPEN @@ -1324,30 +1462,15 @@ void clean_up(bool print_message) tc_log->close(); delegates_destroy(); xid_cache_free(); - delete_elements(&key_caches, (void (*)(const char*, uchar*)) free_key_cache); + key_caches.delete_elements((void (*)(const char*, uchar*)) free_key_cache); multi_keycache_free(); free_status_vars(); end_thr_alarm(1); /* Free allocated memory */ my_free_open_file_info(); - my_free((char*) global_system_variables.date_format, - MYF(MY_ALLOW_ZERO_PTR)); - my_free((char*) global_system_variables.time_format, - MYF(MY_ALLOW_ZERO_PTR)); - my_free((char*) global_system_variables.datetime_format, - MYF(MY_ALLOW_ZERO_PTR)); if (defaults_argv) free_defaults(defaults_argv); - my_free(sys_init_connect.value, MYF(MY_ALLOW_ZERO_PTR)); - my_free(sys_init_slave.value, MYF(MY_ALLOW_ZERO_PTR)); - my_free(sys_var_general_log_path.value, MYF(MY_ALLOW_ZERO_PTR)); - my_free(sys_var_slow_log_path.value, MYF(MY_ALLOW_ZERO_PTR)); free_tmpdir(&mysql_tmpdir_list); -#ifdef HAVE_REPLICATION - my_free(slave_load_tmpdir,MYF(MY_ALLOW_ZERO_PTR)); -#endif x_free(opt_bin_logname); - x_free(opt_relay_logname); - x_free(opt_secure_file_priv); bitmap_free(&temp_pool); free_max_user_conn(); #ifdef HAVE_REPLICATION @@ -1369,9 +1492,9 @@ void clean_up(bool print_message) #if !defined(EMBEDDED_LIBRARY) if (!opt_bootstrap) - (void) my_delete(pidfile_name,MYF(0)); // This may not always exist + mysql_file_delete(key_file_pid, pidfile_name, MYF(0)); // This may not always exist #endif - if (print_message && /*errmesg &&*/ server_start_time) + if (print_message && my_default_lc_messages && server_start_time) sql_print_information(ER_DEFAULT(ER_SHUTDOWN_COMPLETE),my_progname); cleanup_errmsgs(); thread_scheduler.end(); @@ -1379,12 +1502,15 @@ void clean_up(bool print_message) DBUG_PRINT("quit", ("Error messages freed")); /* Tell main we are ready */ logger.cleanup_end(); - (void) pthread_mutex_lock(&LOCK_thread_count); + my_atomic_rwlock_destroy(&global_query_id_lock); + my_atomic_rwlock_destroy(&thread_running_lock); + mysql_mutex_lock(&LOCK_thread_count); DBUG_PRINT("quit", ("got thread count lock")); ready_to_exit=1; /* do the broadcast inside the lock to ensure that my_end() is not called */ - (void) pthread_cond_broadcast(&COND_thread_count); - (void) pthread_mutex_unlock(&LOCK_thread_count); + mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); + sys_var_end(); /* The following lines may never be executed as the main thread may have @@ -1420,51 +1546,49 @@ static void wait_for_signal_thread_to_end() static void clean_up_mutexes() { - (void) pthread_mutex_destroy(&LOCK_mysql_create_db); - (void) pthread_mutex_destroy(&LOCK_lock_db); - (void) rwlock_destroy(&LOCK_grant); - (void) pthread_mutex_destroy(&LOCK_open); - (void) pthread_mutex_destroy(&LOCK_thread_count); - (void) pthread_mutex_destroy(&LOCK_mapped_file); - (void) pthread_mutex_destroy(&LOCK_status); - (void) pthread_mutex_destroy(&LOCK_error_log); - (void) pthread_mutex_destroy(&LOCK_delayed_insert); - (void) pthread_mutex_destroy(&LOCK_delayed_status); - (void) pthread_mutex_destroy(&LOCK_delayed_create); - (void) pthread_mutex_destroy(&LOCK_manager); - (void) pthread_mutex_destroy(&LOCK_crypt); - (void) pthread_mutex_destroy(&LOCK_user_conn); - (void) pthread_mutex_destroy(&LOCK_connection_count); + mysql_mutex_destroy(&LOCK_mysql_create_db); + mysql_mutex_destroy(&LOCK_lock_db); + mysql_rwlock_destroy(&LOCK_grant); + mysql_mutex_destroy(&LOCK_open); + mysql_mutex_destroy(&LOCK_thread_count); + mysql_mutex_destroy(&LOCK_mapped_file); + mysql_mutex_destroy(&LOCK_status); + mysql_mutex_destroy(&LOCK_delayed_insert); + mysql_mutex_destroy(&LOCK_delayed_status); + mysql_mutex_destroy(&LOCK_delayed_create); + mysql_mutex_destroy(&LOCK_manager); + mysql_mutex_destroy(&LOCK_crypt); + mysql_mutex_destroy(&LOCK_user_conn); + mysql_mutex_destroy(&LOCK_connection_count); Events::destroy_mutexes(); #ifdef HAVE_OPENSSL - (void) pthread_mutex_destroy(&LOCK_des_key_file); + mysql_mutex_destroy(&LOCK_des_key_file); #ifndef HAVE_YASSL for (int i= 0; i < CRYPTO_num_locks(); ++i) - (void) rwlock_destroy(&openssl_stdlocks[i].lock); + mysql_rwlock_destroy(&openssl_stdlocks[i].lock); OPENSSL_free(openssl_stdlocks); #endif #endif #ifdef HAVE_REPLICATION - (void) pthread_mutex_destroy(&LOCK_rpl_status); - (void) pthread_cond_destroy(&COND_rpl_status); -#endif - (void) pthread_mutex_destroy(&LOCK_active_mi); - (void) rwlock_destroy(&LOCK_sys_init_connect); - (void) rwlock_destroy(&LOCK_sys_init_slave); - (void) pthread_mutex_destroy(&LOCK_global_system_variables); - (void) rwlock_destroy(&LOCK_system_variables_hash); - (void) pthread_mutex_destroy(&LOCK_global_read_lock); - (void) pthread_mutex_destroy(&LOCK_uuid_generator); - (void) pthread_mutex_destroy(&LOCK_prepared_stmt_count); - (void) pthread_mutex_destroy(&LOCK_error_messages); - (void) pthread_cond_destroy(&COND_thread_count); - (void) pthread_cond_destroy(&COND_refresh); - (void) pthread_cond_destroy(&COND_global_read_lock); - (void) pthread_cond_destroy(&COND_thread_cache); - (void) pthread_cond_destroy(&COND_flush_thread_cache); - (void) pthread_cond_destroy(&COND_manager); + mysql_mutex_destroy(&LOCK_rpl_status); + mysql_cond_destroy(&COND_rpl_status); +#endif + mysql_mutex_destroy(&LOCK_active_mi); + mysql_rwlock_destroy(&LOCK_sys_init_connect); + mysql_rwlock_destroy(&LOCK_sys_init_slave); + mysql_mutex_destroy(&LOCK_global_system_variables); + mysql_rwlock_destroy(&LOCK_system_variables_hash); + mysql_mutex_destroy(&LOCK_global_read_lock); + mysql_mutex_destroy(&LOCK_uuid_generator); + mysql_mutex_destroy(&LOCK_prepared_stmt_count); + mysql_mutex_destroy(&LOCK_error_messages); + mysql_cond_destroy(&COND_thread_count); + mysql_cond_destroy(&COND_refresh); + mysql_cond_destroy(&COND_global_read_lock); + mysql_cond_destroy(&COND_thread_cache); + mysql_cond_destroy(&COND_flush_thread_cache); + mysql_cond_destroy(&COND_manager); } - #endif /*EMBEDDED_LIBRARY*/ @@ -1638,17 +1762,18 @@ static void set_root(const char *path) #endif } + static void network_init(void) { - struct sockaddr_in IPaddr; #ifdef HAVE_SYS_UN_H struct sockaddr_un UNIXaddr; #endif - int arg=1; + int arg; int ret; uint waited; uint this_wait; uint retry; + char port_buf[NI_MAXSERV]; DBUG_ENTER("network_init"); LINT_INIT(ret); @@ -1659,26 +1784,65 @@ static void network_init(void) if (mysqld_port != 0 && !opt_disable_networking && !opt_bootstrap) { + struct addrinfo *ai, *a; + struct addrinfo hints; + int error; DBUG_PRINT("general",("IP Socket is %d",mysqld_port)); - ip_sock = socket(AF_INET, SOCK_STREAM, 0); + + bzero(&hints, sizeof (hints)); + hints.ai_flags= AI_PASSIVE; + hints.ai_socktype= SOCK_STREAM; + hints.ai_family= AF_UNSPEC; + + my_snprintf(port_buf, NI_MAXSERV, "%d", mysqld_port); + error= getaddrinfo(my_bind_addr_str, port_buf, &hints, &ai); + if (error != 0) + { + DBUG_PRINT("error",("Got error: %d from getaddrinfo()", error)); + sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR)); /* purecov: tested */ + unireg_abort(1); /* purecov: tested */ + } + + for (a= ai; a != NULL; a= a->ai_next) + { + ip_sock= socket(a->ai_family, a->ai_socktype, a->ai_protocol); + if (ip_sock != INVALID_SOCKET) + break; + } + if (ip_sock == INVALID_SOCKET) { DBUG_PRINT("error",("Got error: %d from socket()",socket_errno)); - sql_perror(ER(ER_IPSOCK_ERROR)); /* purecov: tested */ + sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR)); /* purecov: tested */ unireg_abort(1); /* purecov: tested */ } - bzero((char*) &IPaddr, sizeof(IPaddr)); - IPaddr.sin_family = AF_INET; - IPaddr.sin_addr.s_addr = my_bind_addr; - IPaddr.sin_port = (unsigned short) htons((unsigned short) mysqld_port); #ifndef __WIN__ /* We should not use SO_REUSEADDR on windows as this would enable a user to open two mysqld servers with the same TCP/IP port. */ + arg= 1; (void) setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,sizeof(arg)); #endif /* __WIN__ */ + +#ifdef IPV6_V6ONLY + /* + For interoperability with older clients, IPv6 socket should + listen on both IPv6 and IPv4 wildcard addresses. + Turn off IPV6_V6ONLY option. + + NOTE: this will work starting from Windows Vista only. + On Windows XP dual stack is not available, so it will not + listen on the corresponding IPv4-address. + */ + if (a->ai_family == AF_INET6) + { + arg= 0; + (void) setsockopt(ip_sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg, + sizeof(arg)); + } +#endif /* Sometimes the port is not released fast enough when stopping and restarting the server. This happens quite often with the test suite @@ -1689,8 +1853,7 @@ static void network_init(void) */ for (waited= 0, retry= 1; ; retry++, waited+= this_wait) { - if (((ret= bind(ip_sock, my_reinterpret_cast(struct sockaddr *) (&IPaddr), - sizeof(IPaddr))) >= 0) || + if (((ret= bind(ip_sock, a->ai_addr, a->ai_addrlen)) >= 0 ) || (socket_errno != SOCKET_EADDRINUSE) || (waited >= mysqld_port_timeout)) break; @@ -1698,6 +1861,7 @@ static void network_init(void) this_wait= retry * retry / 3 + 1; sleep(this_wait); } + freeaddrinfo(ai); if (ret < 0) { DBUG_PRINT("error",("Got error: %d from bind",socket_errno)); @@ -1719,7 +1883,6 @@ static void network_init(void) if (Service.IsNT() && mysqld_unix_port[0] && !opt_bootstrap && opt_enable_named_pipe) { - strxnmov(pipe_name, sizeof(pipe_name)-1, "\\\\.\\pipe\\", mysqld_unix_port, NullS); bzero((char*) &saPipeSecurity, sizeof(saPipeSecurity)); @@ -1785,6 +1948,7 @@ static void network_init(void) UNIXaddr.sun_family = AF_UNIX; strmov(UNIXaddr.sun_path, mysqld_unix_port); (void) unlink(mysqld_unix_port); + arg= 1; (void) setsockopt(unix_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg, sizeof(arg)); umask(0); @@ -1831,7 +1995,7 @@ void close_connection(THD *thd, uint errcode, bool lock) "(not connected)", errcode ? ER_DEFAULT(errcode) : "")); if (lock) - (void) pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thd->killed= THD::KILL_CONNECTION; if ((vio= thd->net.vio) != 0) { @@ -1841,7 +2005,7 @@ void close_connection(THD *thd, uint errcode, bool lock) vio_close(vio); /* vio is freed in delete thd */ } if (lock) - (void) pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); MYSQL_CONNECTION_DONE((int) errcode, thd->thread_id); if (MYSQL_CONNECTION_DONE_ENABLED()) { @@ -1884,11 +2048,11 @@ void unlink_thd(THD *thd) DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd)); thd->cleanup(); - pthread_mutex_lock(&LOCK_connection_count); + mysql_mutex_lock(&LOCK_connection_count); --connection_count; - pthread_mutex_unlock(&LOCK_connection_count); + mysql_mutex_unlock(&LOCK_connection_count); - (void) pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thread_count--; delete thd; DBUG_VOID_RETURN; @@ -1913,7 +2077,7 @@ void unlink_thd(THD *thd) static bool cache_thread() { - safe_mutex_assert_owner(&LOCK_thread_count); + mysql_mutex_assert_owner(&LOCK_thread_count); if (cached_thread_count < thread_cache_size && ! abort_loop && !kill_cached_threads) { @@ -1921,10 +2085,10 @@ static bool cache_thread() DBUG_PRINT("info", ("Adding thread to cache")); cached_thread_count++; while (!abort_loop && ! wake_thread && ! kill_cached_threads) - (void) pthread_cond_wait(&COND_thread_cache, &LOCK_thread_count); + mysql_cond_wait(&COND_thread_cache, &LOCK_thread_count); cached_thread_count--; if (kill_cached_threads) - pthread_cond_signal(&COND_flush_thread_cache); + mysql_cond_signal(&COND_flush_thread_cache); if (wake_thread) { THD *thd; @@ -1972,7 +2136,7 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache) unlink_thd(thd); if (put_in_cache) put_in_cache= cache_thread(); - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); if (put_in_cache) DBUG_RETURN(0); // Thread is reused @@ -1980,7 +2144,7 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache) DBUG_PRINT("signal", ("Broadcasting COND_thread_count")); DBUG_LEAVE; // Must match DBUG_ENTER() my_thread_end(); - (void) pthread_cond_broadcast(&COND_thread_count); + mysql_cond_broadcast(&COND_thread_count); pthread_exit(0); return 0; // Avoid compiler warnings @@ -1989,15 +2153,15 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache) void flush_thread_cache() { - (void) pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); kill_cached_threads++; while (cached_thread_count) { - pthread_cond_broadcast(&COND_thread_cache); - pthread_cond_wait(&COND_flush_thread_cache,&LOCK_thread_count); + mysql_cond_broadcast(&COND_thread_cache); + mysql_cond_wait(&COND_flush_thread_cache, &LOCK_thread_count); } kill_cached_threads--; - (void) pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); } @@ -2470,7 +2634,8 @@ and this may fail.\n\n"); fprintf(stderr, "read_buffer_size=%ld\n", (long) global_system_variables.read_buff_size); fprintf(stderr, "max_used_connections=%lu\n", max_used_connections); fprintf(stderr, "max_threads=%u\n", thread_scheduler.max_threads); - fprintf(stderr, "threads_connected=%u\n", thread_count); + fprintf(stderr, "thread_count=%u\n", thread_count); + fprintf(stderr, "connection_count=%u\n", connection_count); fprintf(stderr, "It is possible that mysqld could use up to \n\ key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = %lu K\n\ bytes of memory\n", ((ulong) dflt_key_cache->key_cache_mem_size + @@ -2679,8 +2844,6 @@ static void start_signal_handler(void) #if !defined(HAVE_DEC_3_2_THREADS) pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_SYSTEM); (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); - if (!(opt_specialflag & SPECIAL_NO_PRIOR)) - my_pthread_attr_setprio(&thr_attr,INTERRUPT_PRIOR); #if defined(__ia64__) || defined(__ia64) /* Peculiar things with ia64 platforms - it seems we only have half the @@ -2692,15 +2855,16 @@ static void start_signal_handler(void) #endif #endif - (void) pthread_mutex_lock(&LOCK_thread_count); - if ((error=pthread_create(&signal_thread,&thr_attr,signal_hand,0))) + mysql_mutex_lock(&LOCK_thread_count); + if ((error= mysql_thread_create(key_thread_signal_hand, + &signal_thread, &thr_attr, signal_hand, 0))) { sql_print_error("Can't create interrupt-thread (error %d, errno: %d)", error,errno); exit(1); } - (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count); - pthread_mutex_unlock(&LOCK_thread_count); + mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); (void) pthread_attr_destroy(&thr_attr); DBUG_VOID_RETURN; @@ -2758,11 +2922,11 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) This works by waiting for start_signal_handler to free mutex, after which we signal it that we are ready. At this pointer there is no other threads running, so there - should not be any other pthread_cond_signal() calls. + should not be any other mysql_cond_signal() calls. */ - (void) pthread_mutex_lock(&LOCK_thread_count); - (void) pthread_mutex_unlock(&LOCK_thread_count); - (void) pthread_cond_broadcast(&COND_thread_count); + mysql_mutex_lock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); + mysql_cond_broadcast(&COND_thread_count); (void) pthread_sigmask(SIG_BLOCK,&set,NULL); for (;;) @@ -2800,10 +2964,9 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) abort_loop=1; // mark abort for threads #ifdef USE_ONE_SIGNAL_HAND pthread_t tmp; - if (!(opt_specialflag & SPECIAL_NO_PRIOR)) - my_pthread_attr_setprio(&connection_attrib,INTERRUPT_PRIOR); - if (pthread_create(&tmp,&connection_attrib, kill_server_thread, - (void*) &sig)) + if (mysql_thread_create(0, /* Not instrumented */ + &tmp, &connection_attrib, kill_server_thread, + (void*) &sig)) sql_print_error("Can't create thread to kill server"); #else kill_server((void*) sig); // MIT THREAD has a alarm thread @@ -2888,6 +3051,8 @@ void my_message_sql(uint error, const char *str, myf MyFlags) error= ER_UNKNOWN_ERROR; } + mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_ERROR, error, str); + if (thd) { if (MyFlags & ME_FATALERROR) @@ -2955,10 +3120,6 @@ sizeof(load_default_groups)/sizeof(load_default_groups[0]); @param format_type What kind of format should be supported @param var_ptr Pointer to variable that should be updated - @note - The default value is taken from either opt_date_time_formats[] or - the ISO format (ANSI SQL) - @retval 0 ok @retval @@ -2966,27 +3127,21 @@ sizeof(load_default_groups)/sizeof(load_default_groups[0]); */ static bool init_global_datetime_format(timestamp_type format_type, - DATE_TIME_FORMAT **var_ptr) + DATE_TIME_FORMAT *format) { - /* Get command line option */ - const char *str= opt_date_time_formats[format_type]; + /* + Get command line option + format->format.str is already set by my_getopt + */ + format->format.length= strlen(format->format.str); - if (!str) // No specified format - { - str= get_date_time_format_str(&known_date_time_formats[ISO_FORMAT], - format_type); - /* - Set the "command line" option to point to the generated string so - that we can set global formats back to default - */ - opt_date_time_formats[format_type]= str; - } - if (!(*var_ptr= date_time_format_make(format_type, str, strlen(str)))) + if (parse_date_time_format(format_type, format)) { - fprintf(stderr, "Wrong date/time format specifier: %s\n", str); - return 1; + fprintf(stderr, "Wrong date/time format specifier: %s\n", + format->format.str); + return true; } - return 0; + return false; } SHOW_VAR com_status_vars[]= { @@ -3001,7 +3156,6 @@ SHOW_VAR com_status_vars[]= { {"alter_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_TABLE]), SHOW_LONG_STATUS}, {"alter_tablespace", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_TABLESPACE]), SHOW_LONG_STATUS}, {"analyze", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ANALYZE]), SHOW_LONG_STATUS}, - {"backup_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BACKUP_TABLE]), SHOW_LONG_STATUS}, {"begin", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BEGIN]), SHOW_LONG_STATUS}, {"binlog", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BINLOG_BASE64_EVENT]), SHOW_LONG_STATUS}, {"call_procedure", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CALL]), SHOW_LONG_STATUS}, @@ -3048,8 +3202,6 @@ SHOW_VAR com_status_vars[]= { {"install_plugin", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSTALL_PLUGIN]), SHOW_LONG_STATUS}, {"kill", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_KILL]), SHOW_LONG_STATUS}, {"load", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD]), SHOW_LONG_STATUS}, - {"load_master_data", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD_MASTER_DATA]), SHOW_LONG_STATUS}, - {"load_master_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD_MASTER_TABLE]), SHOW_LONG_STATUS}, {"lock_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOCK_TABLES]), SHOW_LONG_STATUS}, {"optimize", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_OPTIMIZE]), SHOW_LONG_STATUS}, {"preload_keys", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PRELOAD_KEYS]), SHOW_LONG_STATUS}, @@ -3064,7 +3216,6 @@ SHOW_VAR com_status_vars[]= { {"replace_select", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE_SELECT]), SHOW_LONG_STATUS}, {"reset", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESET]), SHOW_LONG_STATUS}, {"resignal", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESIGNAL]), SHOW_LONG_STATUS}, - {"restore_table", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESTORE_TABLE]), SHOW_LONG_STATUS}, {"revoke", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE]), SHOW_LONG_STATUS}, {"revoke_all", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE_ALL]), SHOW_LONG_STATUS}, {"rollback", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ROLLBACK]), SHOW_LONG_STATUS}, @@ -3143,10 +3294,21 @@ SHOW_VAR com_status_vars[]= { {NullS, NullS, SHOW_LONG} }; -static int init_common_variables(const char *conf_file_name, int argc, - char **argv, const char **groups) +/** + Create the name of the default general log file + + @param[IN] buff Location for building new string. + @param[IN] log_ext The extension for the file (e.g .log) + @returns Pointer to a new string containing the name +*/ +static inline char *make_default_log_name(char *buff,const char* log_ext) { - char buff[FN_REFLEN], *s; + return make_log_name(buff, default_logfile_name, log_ext); +} + +static int init_common_variables() +{ + char buff[FN_REFLEN]; umask(((~my_umask) & 0666)); my_decimal_set_zero(&decimal_zero); // set decimal_zero constant; tzset(); // Set tzname @@ -3205,6 +3367,16 @@ static int init_common_variables(const char *conf_file_name, int argc, strmov(fn_ext(pidfile_name),".pid"); // Add proper extension /* + The default-storage-engine entry in my_long_options should have a + non-null default value. It was earlier intialized as + (longlong)"MyISAM" in my_long_options but this triggered a + compiler error in the Sun Studio 12 compiler. As a work-around we + set the def_value member to 0 in my_long_options and initialize it + to the correct value here. + */ + default_storage_engine= const_cast<char *>("MyISAM"); + + /* Add server status variables to the dynamic list of status variables that is shown by SHOW STATUS. Later, in plugin_init, and mysql_install_plugin @@ -3239,12 +3411,7 @@ static int init_common_variables(const char *conf_file_name, int argc, SQLCOM_END + 8); #endif - orig_argc=argc; - orig_argv=argv; - load_defaults(conf_file_name, groups, &argc, &argv); - defaults_argv=argv; - defaults_argc=argc; - if (get_options(&defaults_argc, defaults_argv)) + if (get_options(&remaining_argc, &remaining_argv)) return 1; set_server_version(); @@ -3387,12 +3554,6 @@ static int init_common_variables(const char *conf_file_name, int argc, if (item_create_init()) return 1; item_init(); - if (set_var_init()) - return 1; -#ifdef HAVE_REPLICATION - if (init_replication_sys_vars()) - return 1; -#endif mysys_uses_curses=0; #ifdef USE_REGEX my_regex_init(&my_charset_latin1); @@ -3447,8 +3608,7 @@ static int init_common_variables(const char *conf_file_name, int argc, global_system_variables.collation_database= default_charset_info; global_system_variables.collation_connection= default_charset_info; global_system_variables.character_set_results= default_charset_info; - global_system_variables.character_set_client= default_charset_info; - + global_system_variables.character_set_client= default_charset_info; if (!(character_set_filesystem= get_charset_by_csname(character_set_filesystem_name, MY_CS_PRIMARY, MYF(MY_WME)))) @@ -3462,20 +3622,6 @@ static int init_common_variables(const char *conf_file_name, int argc, return 1; } global_system_variables.lc_time_names= my_default_lc_time_names; - - sys_init_connect.value_length= 0; - if ((sys_init_connect.value= opt_init_connect)) - sys_init_connect.value_length= strlen(opt_init_connect); - else - sys_init_connect.value=my_strdup("",MYF(0)); - sys_init_connect.is_os_charset= TRUE; - - sys_init_slave.value_length= 0; - if ((sys_init_slave.value= opt_init_slave)) - sys_init_slave.value_length= strlen(opt_init_slave); - else - sys_init_slave.value=my_strdup("",MYF(0)); - sys_init_slave.is_os_charset= TRUE; /* check log options and issue warnings if needed */ if (opt_log && opt_logname && !(log_output_options & LOG_FILE) && @@ -3490,13 +3636,17 @@ static int init_common_variables(const char *conf_file_name, int argc, "--log-slow-queries option, log tables are used. " "To enable logging to files use the --log-output=file option."); - s= opt_logname ? opt_logname : make_default_log_name(buff, ".log"); - sys_var_general_log_path.value= my_strdup(s, MYF(0)); - sys_var_general_log_path.value_length= strlen(s); +#define FIX_LOG_VAR(VAR, ALT) \ + if (!VAR || !*VAR) \ + { \ + x_free(VAR); /* it could be an allocated empty string "" */ \ + VAR= my_strdup(ALT, MYF(0)); \ + } - s= opt_slow_logname ? opt_slow_logname : make_default_log_name(buff, "-slow.log"); - sys_var_slow_log_path.value= my_strdup(s, MYF(0)); - sys_var_slow_log_path.value_length= strlen(s); + FIX_LOG_VAR(opt_logname, + make_default_log_name(buff, ".log")); + FIX_LOG_VAR(opt_slow_logname, + make_default_log_name(buff, "-slow.log")); #if defined(ENABLED_DEBUG_SYNC) /* Initialize the debug sync facility. See debug_sync.cc. */ @@ -3568,34 +3718,46 @@ You should consider changing lower_case_table_names to 1 or 2", static int init_thread_environment() { - (void) pthread_mutex_init(&LOCK_mysql_create_db,MY_MUTEX_INIT_SLOW); - (void) pthread_mutex_init(&LOCK_lock_db,MY_MUTEX_INIT_SLOW); - (void) pthread_mutex_init(&LOCK_open, MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_mapped_file,MY_MUTEX_INIT_SLOW); - (void) pthread_mutex_init(&LOCK_status,MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_error_log,MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_delayed_insert,MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_delayed_status,MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_delayed_create,MY_MUTEX_INIT_SLOW); - (void) pthread_mutex_init(&LOCK_manager,MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST); - (void) my_rwlock_init(&LOCK_system_variables_hash, NULL); - (void) pthread_mutex_init(&LOCK_global_read_lock, MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_prepared_stmt_count, MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_error_messages, MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_uuid_generator, MY_MUTEX_INIT_FAST); - (void) pthread_mutex_init(&LOCK_connection_count, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_mysql_create_db, + &LOCK_mysql_create_db, MY_MUTEX_INIT_SLOW); + mysql_mutex_init(key_LOCK_lock_db, &LOCK_lock_db, MY_MUTEX_INIT_SLOW); + mysql_mutex_init(key_LOCK_open, &LOCK_open, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_thread_count, &LOCK_thread_count, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_mapped_file, &LOCK_mapped_file, MY_MUTEX_INIT_SLOW); + mysql_mutex_init(key_LOCK_status, &LOCK_status, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_delayed_insert, + &LOCK_delayed_insert, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_delayed_status, + &LOCK_delayed_status, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_delayed_create, + &LOCK_delayed_create, MY_MUTEX_INIT_SLOW); + mysql_mutex_init(key_LOCK_manager, + &LOCK_manager, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_crypt, &LOCK_crypt, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_user_conn, &LOCK_user_conn, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_active_mi, &LOCK_active_mi, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_global_system_variables, + &LOCK_global_system_variables, MY_MUTEX_INIT_FAST); + mysql_rwlock_init(key_rwlock_LOCK_system_variables_hash, + &LOCK_system_variables_hash); + mysql_mutex_init(key_LOCK_global_read_lock, + &LOCK_global_read_lock, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_prepared_stmt_count, + &LOCK_prepared_stmt_count, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_error_messages, + &LOCK_error_messages, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_uuid_generator, + &LOCK_uuid_generator, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_connection_count, + &LOCK_connection_count, MY_MUTEX_INIT_FAST); #ifdef HAVE_OPENSSL - (void) pthread_mutex_init(&LOCK_des_key_file,MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_des_key_file, + &LOCK_des_key_file, MY_MUTEX_INIT_FAST); #ifndef HAVE_YASSL openssl_stdlocks= (openssl_lock_t*) OPENSSL_malloc(CRYPTO_num_locks() * sizeof(openssl_lock_t)); for (int i= 0; i < CRYPTO_num_locks(); ++i) - (void) my_rwlock_init(&openssl_stdlocks[i].lock, NULL); + mysql_rwlock_init(key_rwlock_openssl, &openssl_stdlocks[i].lock); CRYPTO_set_dynlock_create_callback(openssl_dynlock_create); CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy); CRYPTO_set_dynlock_lock_callback(openssl_lock); @@ -3603,21 +3765,22 @@ static int init_thread_environment() CRYPTO_set_id_callback(openssl_id_function); #endif #endif - (void) my_rwlock_init(&LOCK_sys_init_connect, NULL); - (void) my_rwlock_init(&LOCK_sys_init_slave, NULL); - (void) my_rwlock_init(&LOCK_grant, NULL); - (void) pthread_cond_init(&COND_thread_count,NULL); - (void) pthread_cond_init(&COND_refresh,NULL); - (void) pthread_cond_init(&COND_global_read_lock,NULL); - (void) pthread_cond_init(&COND_thread_cache,NULL); - (void) pthread_cond_init(&COND_flush_thread_cache,NULL); - (void) pthread_cond_init(&COND_manager,NULL); + mysql_rwlock_init(key_rwlock_LOCK_sys_init_connect, &LOCK_sys_init_connect); + mysql_rwlock_init(key_rwlock_LOCK_sys_init_slave, &LOCK_sys_init_slave); + mysql_rwlock_init(key_rwlock_LOCK_grant, &LOCK_grant); + mysql_cond_init(key_COND_thread_count, &COND_thread_count, NULL); + mysql_cond_init(key_COND_refresh, &COND_refresh, NULL); + mysql_cond_init(key_COND_global_read_lock, &COND_global_read_lock, NULL); + mysql_cond_init(key_COND_thread_cache, &COND_thread_cache, NULL); + mysql_cond_init(key_COND_flush_thread_cache, &COND_flush_thread_cache, NULL); + mysql_cond_init(key_COND_manager, &COND_manager, NULL); #ifdef HAVE_REPLICATION - (void) pthread_mutex_init(&LOCK_rpl_status, MY_MUTEX_INIT_FAST); - (void) pthread_cond_init(&COND_rpl_status, NULL); + mysql_mutex_init(key_LOCK_rpl_status, &LOCK_rpl_status, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_rpl_status, &COND_rpl_status, NULL); #endif - (void) pthread_mutex_init(&LOCK_server_started, MY_MUTEX_INIT_FAST); - (void) pthread_cond_init(&COND_server_started,NULL); + mysql_mutex_init(key_LOCK_server_started, + &LOCK_server_started, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_server_started, &COND_server_started, NULL); sp_cache_init(); #ifdef HAVE_EVENT_SCHEDULER Events::init_mutexes(); @@ -3627,8 +3790,6 @@ static int init_thread_environment() (void) pthread_attr_setdetachstate(&connection_attrib, PTHREAD_CREATE_DETACHED); pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM); - if (!(opt_specialflag & SPECIAL_NO_PRIOR)) - my_pthread_attr_setprio(&connection_attrib,WAIT_PRIOR); if (pthread_key_create(&THR_THD,NULL) || pthread_key_create(&THR_MALLOC,NULL)) @@ -3650,7 +3811,7 @@ static unsigned long openssl_id_function() static openssl_lock_t *openssl_dynlock_create(const char *file, int line) { openssl_lock_t *lock= new openssl_lock_t; - my_rwlock_init(&lock->lock, NULL); + mysql_rwlock_init(key_rwlock_openssl, &lock->lock); return lock; } @@ -3658,7 +3819,7 @@ static openssl_lock_t *openssl_dynlock_create(const char *file, int line) static void openssl_dynlock_destroy(openssl_lock_t *lock, const char *file, int line) { - rwlock_destroy(&lock->lock); + mysql_rwlock_destroy(&lock->lock); delete lock; } @@ -3684,16 +3845,16 @@ static void openssl_lock(int mode, openssl_lock_t *lock, const char *file, switch (mode) { case CRYPTO_LOCK|CRYPTO_READ: what = "read lock"; - err = rw_rdlock(&lock->lock); + err= mysql_rwlock_rdlock(&lock->lock); break; case CRYPTO_LOCK|CRYPTO_WRITE: what = "write lock"; - err = rw_wrlock(&lock->lock); + err= mysql_rwlock_wrlock(&lock->lock); break; case CRYPTO_UNLOCK|CRYPTO_READ: case CRYPTO_UNLOCK|CRYPTO_WRITE: what = "unlock"; - err = rw_unlock(&lock->lock); + err= mysql_rwlock_unlock(&lock->lock); break; default: /* Unknown locking mode. */ @@ -3757,7 +3918,7 @@ static void end_ssl() static int init_server_components() { - FILE* reopen; + FILE *reopen; DBUG_ENTER("init_server_components"); /* We need to call each of these following functions to ensure that @@ -3766,7 +3927,6 @@ static int init_server_components() if (table_cache_init() | table_def_init() | hostname_cache_init()) unireg_abort(1); - query_cache_result_size_limit(query_cache_limit); query_cache_set_min_res_unit(query_cache_min_res_unit); query_cache_init(); query_cache_resize(query_cache_size); @@ -3793,7 +3953,7 @@ static int init_server_components() fn_format(log_error_file, log_error_file_ptr, mysql_data_home, ".err", MY_UNPACK_FILENAME | MY_SAFE_PATH); if (!log_error_file[0]) - opt_error_log= 1; // Too long file name + opt_error_log= 0; // Too long file name else { #ifndef EMBEDDED_LIBRARY @@ -3806,6 +3966,18 @@ static int init_server_components() } } +#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE + /* + Parsing the performance schema command line option may have reported + warnings/information messages. + Now that the logger is finally available, and redirected + to the proper file when the --log--error option is used, + print the buffered messages to the log. + */ + buffered_logs.print(); + buffered_logs.cleanup(); +#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */ + if (xid_cache_init()) { sql_print_error("Out of memory"); @@ -3880,27 +4052,9 @@ with --log-bin instead."); sql_print_warning("You need to use --log-bin to make " "--log-slave-updates work."); } - if (!opt_bin_log) - { - if (opt_binlog_format_id != BINLOG_FORMAT_UNSPEC) - { - sql_print_warning("You need to use --log-bin to make " - "--binlog-format work."); - - global_system_variables.binlog_format= opt_binlog_format_id; - } - else - { - global_system_variables.binlog_format= BINLOG_FORMAT_STMT; - } - } - else - if (opt_binlog_format_id == BINLOG_FORMAT_UNSPEC) - global_system_variables.binlog_format= BINLOG_FORMAT_STMT; - else - { - DBUG_ASSERT(global_system_variables.binlog_format != BINLOG_FORMAT_UNSPEC); - } + if (!opt_bin_log && binlog_format_used) + sql_print_warning("You need to use --log-bin to make " + "--binlog-format work."); /* Check that we have not let the format to unspecified at this point */ DBUG_ASSERT((uint)global_system_variables.binlog_format <= @@ -3982,25 +4136,26 @@ a file name for --log-bin-index option", opt_binlog_index_name); if (ha_init_errors()) DBUG_RETURN(1); - { - if (plugin_init(&defaults_argc, defaults_argv, - (opt_noacl ? PLUGIN_INIT_SKIP_PLUGIN_TABLE : 0) | - (opt_help ? PLUGIN_INIT_SKIP_INITIALIZATION : 0))) - { - sql_print_error("Failed to initialize plugins."); - unireg_abort(1); - } - plugins_are_initialized= TRUE; /* Don't separate from init function */ + if (plugin_init(&remaining_argc, remaining_argv, + (opt_noacl ? PLUGIN_INIT_SKIP_PLUGIN_TABLE : 0) | + (opt_help ? PLUGIN_INIT_SKIP_INITIALIZATION : 0))) + { + sql_print_error("Failed to initialize plugins."); + unireg_abort(1); } + plugins_are_initialized= TRUE; /* Don't separate from init function */ - if (opt_help) - unireg_abort(0); + have_csv= plugin_status(STRING_WITH_LEN("csv"), + MYSQL_STORAGE_ENGINE_PLUGIN); + have_ndbcluster= plugin_status(STRING_WITH_LEN("ndbcluster"), + MYSQL_STORAGE_ENGINE_PLUGIN); + have_partitioning= plugin_status(STRING_WITH_LEN("partition"), + MYSQL_STORAGE_ENGINE_PLUGIN); /* we do want to exit if there are any other unknown options */ - if (defaults_argc > 1) + if (remaining_argc > 1) { int ho_error; - char **tmp_argv= defaults_argv; struct my_option no_opts[]= { {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} @@ -4008,25 +4163,29 @@ a file name for --log-bin-index option", opt_binlog_index_name); /* We need to eat any 'loose' arguments first before we conclude that there are unprocessed options. - But we need to preserve defaults_argv pointer intact for - free_defaults() to work. Thus we use a copy here. */ my_getopt_skip_unknown= 0; - if ((ho_error= handle_options(&defaults_argc, &tmp_argv, no_opts, + if ((ho_error= handle_options(&remaining_argc, &remaining_argv, no_opts, mysqld_get_one_option))) unireg_abort(ho_error); + /* Add back the program name handle_options removes */ + remaining_argc++; + remaining_argv--; my_getopt_skip_unknown= TRUE; - if (defaults_argc) + if (remaining_argc > 1) { fprintf(stderr, "%s: Too many arguments (first extra is '%s').\n" "Use --verbose --help to get a list of available options\n", - my_progname, *tmp_argv); + my_progname, remaining_argv[1]); unireg_abort(1); } } + if (opt_help) + unireg_abort(0); + /* if the errmsg.sys is not loaded, terminate to maintain behaviour */ if (!DEFAULT_ERRMSGS[0][0]) unireg_abort(1); @@ -4078,42 +4237,37 @@ a file name for --log-bin-index option", opt_binlog_index_name); #endif /* - Check that the default storage engine is actually available. + Set the default storage engine */ - if (default_storage_engine_str) + LEX_STRING name= { default_storage_engine, strlen(default_storage_engine) }; + plugin_ref plugin; + handlerton *hton; + if ((plugin= ha_resolve_by_name(0, &name))) + hton= plugin_data(plugin, handlerton*); + else { - LEX_STRING name= { default_storage_engine_str, - strlen(default_storage_engine_str) }; - plugin_ref plugin; - handlerton *hton; - - if ((plugin= ha_resolve_by_name(0, &name))) - hton= plugin_data(plugin, handlerton*); - else + sql_print_error("Unknown/unsupported storage engine: %s", + default_storage_engine); + unireg_abort(1); + } + if (!ha_storage_engine_is_enabled(hton)) + { + if (!opt_bootstrap) { - sql_print_error("Unknown/unsupported table type: %s", - default_storage_engine_str); + sql_print_error("Default storage engine (%s) is not available", + default_storage_engine); unireg_abort(1); } - if (!ha_storage_engine_is_enabled(hton)) - { - if (!opt_bootstrap) - { - sql_print_error("Default storage engine (%s) is not available", - default_storage_engine_str); - unireg_abort(1); - } - DBUG_ASSERT(global_system_variables.table_plugin); - } - else - { - /* - Need to unlock as global_system_variables.table_plugin - was acquired during plugin_init() - */ - plugin_unlock(0, global_system_variables.table_plugin); - global_system_variables.table_plugin= plugin; - } + DBUG_ASSERT(global_system_variables.table_plugin); + } + else + { + /* + Need to unlock as global_system_variables.table_plugin + was acquired during plugin_init() + */ + plugin_unlock(0, global_system_variables.table_plugin); + global_system_variables.table_plugin= plugin; } tc_log= (total_ha_2pc > 1 ? (opt_bin_log ? @@ -4188,7 +4342,8 @@ static void create_shutdown_thread() #ifdef __WIN__ hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name); pthread_t hThread; - if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0)) + if (mysql_thread_create(key_thread_handle_shutdown, + &hThread, &connection_attrib, handle_shutdown, 0)) sql_print_warning("Can't create thread to handle shutdown requests"); // On "Stop Service" we have to do regular shutdown @@ -4212,14 +4367,15 @@ static void handle_connections_methods() unireg_abort(1); // Will not return } - pthread_mutex_lock(&LOCK_thread_count); - (void) pthread_cond_init(&COND_handler_count,NULL); + mysql_mutex_lock(&LOCK_thread_count); + mysql_cond_init(key_COND_handler_count, &COND_handler_count, NULL); handler_count=0; if (hPipe != INVALID_HANDLE_VALUE) { handler_count++; - if (pthread_create(&hThread,&connection_attrib, - handle_connections_namedpipes, 0)) + if (mysql_thread_create(key_thread_handle_con_namedpipes, + &hThread, &connection_attrib, + handle_connections_namedpipes, 0)) { sql_print_warning("Can't create thread to handle named pipes"); handler_count--; @@ -4228,8 +4384,9 @@ static void handle_connections_methods() if (have_tcpip && !opt_disable_networking) { handler_count++; - if (pthread_create(&hThread,&connection_attrib, - handle_connections_sockets_thread, 0)) + if (mysql_thread_create(key_thread_handle_con_sockets, + &hThread, &connection_attrib, + handle_connections_sockets_thread, 0)) { sql_print_warning("Can't create thread to handle TCP/IP"); handler_count--; @@ -4239,8 +4396,9 @@ static void handle_connections_methods() if (opt_enable_shared_memory) { handler_count++; - if (pthread_create(&hThread,&connection_attrib, - handle_connections_shared_memory, 0)) + if (mysql_thread_create(key_thread_handle_con_sharedmem, + &hThread, &connection_attrib, + handle_connections_shared_memory, 0)) { sql_print_warning("Can't create thread to handle shared memory"); handler_count--; @@ -4249,17 +4407,17 @@ static void handle_connections_methods() #endif while (handler_count > 0) - pthread_cond_wait(&COND_handler_count,&LOCK_thread_count); - pthread_mutex_unlock(&LOCK_thread_count); + mysql_cond_wait(&COND_handler_count, &LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); DBUG_VOID_RETURN; } void decrement_handler_count() { - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); handler_count--; - pthread_cond_signal(&COND_handler_count); - pthread_mutex_unlock(&LOCK_thread_count); + mysql_cond_signal(&COND_handler_count); + mysql_mutex_unlock(&LOCK_thread_count); my_thread_end(); } #else @@ -4305,15 +4463,134 @@ static void test_lc_time_sz() } #endif//DBUG_OFF - #ifdef __WIN__ int win_main(int argc, char **argv) #else int main(int argc, char **argv) #endif { - MY_INIT(argv[0]); // init my_sys library & pthreads - /* nothing should come before this line ^^^ */ + /* + Perform basic thread library and malloc initialization, + to be able to read defaults files and parse options. + */ + my_progname= argv[0]; + if (my_basic_init()) + { + fprintf(stderr, "my_basic_init() failed."); + return 1; + } + + orig_argc= argc; + orig_argv= argv; + if (load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv)) + return 1; + defaults_argc= argc; + defaults_argv= argv; + remaining_argc= argc; + remaining_argv= argv; + + /* Must be initialized early for comparison of options name */ + system_charset_info= &my_charset_utf8_general_ci; + + sys_var_init(); + +#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE + /* + The performance schema needs to be initialized as early as possible, + before to-be-instrumented objects of the server are initialized. + */ + int ho_error; + DYNAMIC_ARRAY all_early_options; + + my_getopt_register_get_addr(NULL); + /* Skip unknown options so that they may be processed later */ + my_getopt_skip_unknown= TRUE; + + /* prepare all_early_options array */ + my_init_dynamic_array(&all_early_options, sizeof(my_option), 100, 25); + sys_var_add_options(&all_early_options, sys_var::PARSE_EARLY); + add_terminator(&all_early_options); + + /* + Logs generated while parsing the command line + options are buffered and printed later. + */ + buffered_logs.init(); + my_getopt_error_reporter= buffered_option_error_reporter; + + ho_error= handle_options(&remaining_argc, &remaining_argv, + (my_option*)(all_early_options.buffer), NULL); + delete_dynamic(&all_early_options); + if (ho_error == 0) + { + /* Add back the program name handle_options removes */ + remaining_argc++; + remaining_argv--; + if (pfs_param.m_enabled) + { + PSI_hook= initialize_performance_schema(&pfs_param); + if (PSI_hook == NULL) + { + pfs_param.m_enabled= false; + buffered_logs.buffer(WARNING_LEVEL, + "Performance schema disabled (reason: init failed)."); + } + else + { + buffered_logs.buffer(INFORMATION_LEVEL, + "Performance schema enabled."); + } + } + else + { + buffered_logs.buffer(INFORMATION_LEVEL, + "Performance schema disabled (reason: start parameters)."); + } + } +#else + /* + Other provider of the instrumentation interface should + initialize PSI_hook here: + - HAVE_PSI_INTERFACE is for the instrumentation interface + - WITH_PERFSCHEMA_STORAGE_ENGINE is for one implementation + of the interface, + but there could be alternate implementations, which is why + these two defines are kept separate. + */ +#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */ + +#ifdef HAVE_PSI_INTERFACE + /* + Obtain the current performance schema instrumentation interface, + if available. + */ + if (PSI_hook) + PSI_server= (PSI*) PSI_hook->get_interface(PSI_CURRENT_VERSION); + + if (PSI_server) + { + /* + Now that we have parsed the command line arguments, and have initialized + the performance schema itself, the next step is to register all the + server instruments. + */ + init_server_psi_keys(); + /* Instrument the main thread */ + PSI_thread *psi= PSI_server->new_thread(key_thread_main, NULL, 0); + if (psi) + PSI_server->set_thread(psi); + + /* + Now that some instrumentation is in place, + recreate objects which were initialised early, + so that they are instrumented as well. + */ + my_thread_basic_global_reinit(); + } +#endif /* HAVE_PSI_INTERFACE */ + + my_init(); // init my_sys library & pthreads + init_error_log_mutex(); /* Set signal used to kill MySQL */ #if defined(SIGUSR2) @@ -4322,12 +4599,37 @@ int main(int argc, char **argv) thr_kill_signal= SIGINT; #endif + /* Initialize audit interface globals. Audit plugins are inited later. */ + mysql_audit_initialize(); + /* Perform basic logger initialization logger. Should be called after MY_INIT, as it initializes mutexes. Log tables are inited later. */ logger.init_base(); +#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE + if (ho_error) + { + /* + Parsing command line option failed, + Since we don't have a workable remaining_argc/remaining_argv + to continue the server initialization, this is as far as this + code can go. + This is the best effort to log meaningful messages: + - messages will be printed to stderr, which is not redirected yet, + - messages will be printed in the NT event log, for windows. + */ + buffered_logs.print(); + buffered_logs.cleanup(); + /* + Not enough initializations for unireg_abort() + Using exit() for windows. + */ + exit (ho_error); + } +#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */ + #ifdef _CUSTOMSTARTUPCONFIG_ if (_cust_check_startup()) { @@ -4347,18 +4649,16 @@ int main(int argc, char **argv) { /* errors are not read yet, so we use english text here */ my_message(ER_WSAS_FAILED, "WSAStartup Failed", MYF(0)); - unireg_abort(1); + /* Not enough initializations for unireg_abort() */ + return 1; } } #endif /* __WIN__ */ - if (init_common_variables(MYSQL_CONFIG_NAME, - argc, argv, load_default_groups)) + if (init_common_variables()) unireg_abort(1); // Will do exit init_signals(); - if (!(opt_specialflag & SPECIAL_NO_PRIOR)) - my_pthread_setprio(pthread_self(),CONNECT_PRIOR); #if defined(__ia64__) || defined(__ia64) /* Peculiar things with ia64 platforms - it seems we only have half the @@ -4415,10 +4715,6 @@ int main(int argc, char **argv) check_data_home(mysql_real_data_home); if (my_setwd(mysql_real_data_home,MYF(MY_WME)) && !opt_help) unireg_abort(1); /* purecov: inspected */ - mysql_data_home= mysql_data_home_buff; - mysql_data_home[0]=FN_CURLIB; // all paths are relative from here - mysql_data_home[1]=0; - mysql_data_home_len= 2; if ((user_info= check_user(mysqld_user))) { @@ -4432,21 +4728,12 @@ int main(int argc, char **argv) if (opt_bin_log && !server_id) { - server_id= !master_host ? 1 : 2; + server_id= 1; #ifdef EXTRA_DEBUG - switch (server_id) { - case 1: - sql_print_warning("\ -You have enabled the binary log, but you haven't set server-id to \ -a non-zero value: we force server id to 1; updates will be logged to the \ -binary log, but connections from slaves will not be accepted."); - break; - case 2: - sql_print_warning("\ -You should set server-id to a non-0 value if master_host is set; \ -we force server id to 2, but this MySQL server will not act as a slave."); - break; - } + sql_print_warning("You have enabled the binary log, but you haven't set " + "server-id to a non-zero value: we force server id to 1; " + "updates will be logged to the binary log, but " + "connections from slaves will not be accepted."); #endif } @@ -4489,12 +4776,13 @@ we force server id to 2, but this MySQL server will not act as a slave."); #endif /* __NETWARE__ */ if (!opt_bootstrap) - (void) my_delete(pidfile_name,MYF(MY_WME)); // Not needed anymore + mysql_file_delete(key_file_pid, pidfile_name, MYF(MY_WME)); // Not needed anymore if (unix_sock != INVALID_SOCKET) unlink(mysqld_unix_port); exit(1); } + if (!opt_noacl) (void) grant_init(); @@ -4522,6 +4810,13 @@ we force server id to 2, but this MySQL server will not act as a slave."); unireg_abort(1); } +#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE + initialize_performance_schema_acl(opt_bootstrap); + check_performance_schema(); +#endif + + initialize_information_schema_acl(); + execute_ddl_log_recovery(); if (Events::init(opt_noacl || opt_bootstrap)) @@ -4530,10 +4825,10 @@ we force server id to 2, but this MySQL server will not act as a slave."); if (opt_bootstrap) { select_thread_in_use= 0; // Allow 'kill' to work - bootstrap(stdin); + bootstrap(mysql_stdin); unireg_abort(bootstrap_error ? 1 : 0); } - if (opt_init_file) + if (opt_init_file && *opt_init_file) { if (read_init_file(opt_init_file)) unireg_abort(1); @@ -4553,10 +4848,10 @@ we force server id to 2, but this MySQL server will not act as a slave."); /* Signal threads waiting for server to be started */ - pthread_mutex_lock(&LOCK_server_started); + mysql_mutex_lock(&LOCK_server_started); mysqld_server_started= 1; - pthread_cond_signal(&COND_server_started); - pthread_mutex_unlock(&LOCK_server_started); + mysql_cond_signal(&COND_server_started); + mysql_mutex_unlock(&LOCK_server_started); #if defined(_WIN32) || defined(HAVE_SMEM) handle_connections_methods(); @@ -4572,21 +4867,21 @@ we force server id to 2, but this MySQL server will not act as a slave."); #ifdef EXTRA_DEBUG2 sql_print_error("Before Lock_thread_count"); #endif - (void) pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); DBUG_PRINT("quit", ("Got thread_count mutex")); select_thread_in_use=0; // For close_connections - (void) pthread_mutex_unlock(&LOCK_thread_count); - (void) pthread_cond_broadcast(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); + mysql_cond_broadcast(&COND_thread_count); #ifdef EXTRA_DEBUG2 sql_print_error("After lock_thread_count"); #endif #endif /* __WIN__ */ /* Wait until cleanup is done */ - (void) pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); while (!ready_to_exit) - pthread_cond_wait(&COND_thread_count,&LOCK_thread_count); - (void) pthread_mutex_unlock(&LOCK_thread_count); + mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); #if defined(__WIN__) && !defined(EMBEDDED_LIBRARY) if (Service.IsNT() && start_mode) @@ -4599,15 +4894,22 @@ we force server id to 2, but this MySQL server will not act as a slave."); } #endif clean_up(1); - wait_for_signal_thread_to_end(); - clean_up_mutexes(); - my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); - - exit(0); - return(0); /* purecov: deadcode */ +#ifdef HAVE_PSI_INTERFACE + /* + Disable the instrumentation, to avoid recording events + during the shutdown. + */ + if (PSI_server) + { + PSI_server->delete_current_thread(); + PSI_server= NULL; + } + shutdown_performance_schema(); +#endif + mysqld_exit(0); } -#endif /* EMBEDDED_LIBRARY */ +#endif /* !EMBEDDED_LIBRARY */ /**************************************************************************** @@ -4818,7 +5120,7 @@ int main(int argc, char **argv) create MySQL privilege tables without having to start a full MySQL server. */ -static void bootstrap(FILE *file) +static void bootstrap(MYSQL_FILE *file) { DBUG_ENTER("bootstrap"); @@ -4833,24 +5135,25 @@ static void bootstrap(FILE *file) bootstrap_file=file; #ifndef EMBEDDED_LIBRARY // TODO: Enable this - if (pthread_create(&thd->real_id,&connection_attrib,handle_bootstrap, - (void*) thd)) + if (mysql_thread_create(key_thread_bootstrap, + &thd->real_id, &connection_attrib, handle_bootstrap, + (void*) thd)) { sql_print_warning("Can't create thread to handle bootstrap"); bootstrap_error=-1; DBUG_VOID_RETURN; } /* Wait for thread to die */ - (void) pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); while (in_bootstrap) { - (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count); + mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); DBUG_PRINT("quit",("One thread died (count=%u)",thread_count)); } - (void) pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); #else thd->mysql= 0; - handle_bootstrap((void *)thd); + do_handle_bootstrap(thd); #endif DBUG_VOID_RETURN; @@ -4859,13 +5162,14 @@ static void bootstrap(FILE *file) static bool read_init_file(char *file_name) { - FILE *file; + MYSQL_FILE *file; DBUG_ENTER("read_init_file"); DBUG_PRINT("enter",("name: %s",file_name)); - if (!(file=my_fopen(file_name,O_RDONLY,MYF(MY_WME)))) + if (!(file= mysql_file_fopen(key_file_init, file_name, + O_RDONLY, MYF(MY_WME)))) DBUG_RETURN(TRUE); bootstrap(file); - (void) my_fclose(file,MYF(MY_WME)); + mysql_file_fclose(file, MYF(MY_WME)); DBUG_RETURN(FALSE); } @@ -4881,15 +5185,15 @@ static bool read_init_file(char *file_name) When we enter this function, LOCK_thread_count is hold! */ - + void handle_connection_in_main_thread(THD *thd) { - safe_mutex_assert_owner(&LOCK_thread_count); + mysql_mutex_assert_owner(&LOCK_thread_count); thread_cache_size=0; // Safety threads.append(thd); - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); thd->start_utime= my_micro_time(); - handle_one_connection(thd); + do_handle_one_connection(thd); } @@ -4904,7 +5208,7 @@ void create_thread_to_handle_connection(THD *thd) /* Get thread from cache */ thread_cache.append(thd); wake_thread++; - pthread_cond_signal(&COND_thread_cache); + mysql_cond_signal(&COND_thread_cache); } else { @@ -4915,9 +5219,10 @@ void create_thread_to_handle_connection(THD *thd) threads.append(thd); DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id)); thd->prior_thr_create_utime= thd->start_utime= my_micro_time(); - if ((error=pthread_create(&thd->real_id,&connection_attrib, - handle_one_connection, - (void*) thd))) + if ((error= mysql_thread_create(key_thread_one_connection, + &thd->real_id, &connection_attrib, + handle_one_connection, + (void*) thd))) { /* purecov: begin inspected */ DBUG_PRINT("error", @@ -4925,26 +5230,26 @@ void create_thread_to_handle_connection(THD *thd) error)); thread_count--; thd->killed= THD::KILL_CONNECTION; // Safety - (void) pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); - pthread_mutex_lock(&LOCK_connection_count); + mysql_mutex_lock(&LOCK_connection_count); --connection_count; - pthread_mutex_unlock(&LOCK_connection_count); + mysql_mutex_unlock(&LOCK_connection_count); statistic_increment(aborted_connects,&LOCK_status); /* Can't use my_error() since store_globals has not been called. */ my_snprintf(error_message_buff, sizeof(error_message_buff), ER(ER_CANT_CREATE_THREAD), error); net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff, NULL); - (void) pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); close_connection(thd,0,0); delete thd; - (void) pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); return; /* purecov: end */ } } - (void) pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); DBUG_PRINT("info",("Thread created")); } @@ -4964,7 +5269,6 @@ void create_thread_to_handle_connection(THD *thd) static void create_new_thread(THD *thd) { - NET *net=&thd->net; DBUG_ENTER("create_new_thread"); /* @@ -4972,11 +5276,11 @@ static void create_new_thread(THD *thd) only (max_connections + 1) connections. */ - pthread_mutex_lock(&LOCK_connection_count); + mysql_mutex_lock(&LOCK_connection_count); if (connection_count >= max_connections + 1 || abort_loop) { - pthread_mutex_unlock(&LOCK_connection_count); + mysql_mutex_unlock(&LOCK_connection_count); DBUG_PRINT("error",("Too many connections")); close_connection(thd, ER_CON_COUNT_ERROR, 1); @@ -4989,11 +5293,11 @@ static void create_new_thread(THD *thd) if (connection_count > max_used_connections) max_used_connections= connection_count; - pthread_mutex_unlock(&LOCK_connection_count); + mysql_mutex_unlock(&LOCK_connection_count); /* Start a new thread to handle connection. */ - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); /* The initialization of thread_id is done in create_embedded_thd() for @@ -5034,6 +5338,7 @@ inline void kill_broken_server() /* Handle new connections and spawn new process to handle them */ #ifndef EMBEDDED_LIBRARY + void handle_connections_sockets() { my_socket sock,new_sock; @@ -5041,15 +5346,13 @@ void handle_connections_sockets() uint max_used_connection= (uint) (max(ip_sock,unix_sock)+1); fd_set readFDs,clientFDs; THD *thd; - struct sockaddr_in cAddr; + struct sockaddr_storage cAddr; int ip_flags=0,socket_flags=0,flags; st_vio *vio_tmp; DBUG_ENTER("handle_connections_sockets"); LINT_INIT(new_sock); - (void) my_pthread_getprio(pthread_self()); // For debugging - FD_ZERO(&clientFDs); if (ip_sock != INVALID_SOCKET) { @@ -5117,9 +5420,9 @@ void handle_connections_sockets() #endif /* NO_FCNTL_NONBLOCK */ for (uint retry=0; retry < MAX_ACCEPT_RETRY; retry++) { - size_socket length=sizeof(struct sockaddr_in); - new_sock = accept(sock, my_reinterpret_cast(struct sockaddr *) (&cAddr), - &length); + size_socket length= sizeof(struct sockaddr_storage); + new_sock= accept(sock, (struct sockaddr *)(&cAddr), + &length); #ifdef __NETWARE__ // TODO: temporary fix, waiting for TCP/IP fix - DEFECT000303149 if ((new_sock == INVALID_SOCKET) && (socket_errno == EINVAL)) @@ -5190,9 +5493,10 @@ void handle_connections_sockets() { size_socket dummyLen; - struct sockaddr dummy; - dummyLen = sizeof(struct sockaddr); - if (getsockname(new_sock,&dummy, &dummyLen) < 0) + struct sockaddr_storage dummy; + dummyLen = sizeof(dummy); + if ( getsockname(new_sock,(struct sockaddr *)&dummy, + (SOCKET_SIZE_TYPE *)&dummyLen) < 0 ) { sql_perror("Error on new connection socket"); (void) shutdown(new_sock, SHUT_RDWR); @@ -5208,7 +5512,7 @@ void handle_connections_sockets() if (!(thd= new THD)) { (void) shutdown(new_sock, SHUT_RDWR); - VOID(closesocket(new_sock)); + (void) closesocket(new_sock); continue; } if (!(vio_tmp=vio_new(new_sock, @@ -5544,7 +5848,7 @@ errorconn: NullS); sql_perror(buff); } - if (handle_client_file_map) + if (handle_client_file_map) CloseHandle(handle_client_file_map); if (handle_client_map) UnmapViewOfFile(handle_client_map); @@ -5590,204 +5894,26 @@ error: Handle start options ******************************************************************************/ -enum options_mysqld -{ - OPT_ISAM_LOG=256, OPT_SKIP_NEW, - OPT_SKIP_GRANT, OPT_SKIP_LOCK, - OPT_ENABLE_LOCK, OPT_USE_LOCKING, - OPT_SOCKET, OPT_UPDATE_LOG, - OPT_BIN_LOG, OPT_SKIP_RESOLVE, - OPT_SKIP_NETWORKING, OPT_BIN_LOG_INDEX, - OPT_BIND_ADDRESS, OPT_PID_FILE, - OPT_SKIP_PRIOR, OPT_BIG_TABLES, - OPT_STANDALONE, OPT_ONE_THREAD, - OPT_CONSOLE, OPT_LOW_PRIORITY_UPDATES, - OPT_SKIP_HOST_CACHE, OPT_SHORT_LOG_FORMAT, - OPT_FLUSH, OPT_SAFE, - OPT_BOOTSTRAP, OPT_SKIP_SHOW_DB, - OPT_STORAGE_ENGINE, OPT_INIT_FILE, - OPT_DELAY_KEY_WRITE_ALL, OPT_SLOW_QUERY_LOG, - OPT_DELAY_KEY_WRITE, OPT_CHARSETS_DIR, - OPT_MASTER_HOST, OPT_MASTER_USER, - OPT_MASTER_PASSWORD, OPT_MASTER_PORT, - OPT_MASTER_INFO_FILE, OPT_MASTER_CONNECT_RETRY, - OPT_MASTER_RETRY_COUNT, OPT_LOG_TC, OPT_LOG_TC_SIZE, - OPT_MASTER_SSL, OPT_MASTER_SSL_KEY, - OPT_MASTER_SSL_CERT, OPT_MASTER_SSL_CAPATH, - OPT_MASTER_SSL_CIPHER, OPT_MASTER_SSL_CA, - OPT_SQL_BIN_UPDATE_SAME, OPT_REPLICATE_DO_DB, - OPT_REPLICATE_IGNORE_DB, OPT_LOG_SLAVE_UPDATES, - OPT_BINLOG_DO_DB, OPT_BINLOG_IGNORE_DB, - OPT_BINLOG_FORMAT, -#ifndef DBUG_OFF - OPT_BINLOG_SHOW_XID, -#endif - OPT_BINLOG_ROWS_EVENT_MAX_SIZE, - OPT_WANT_CORE, OPT_CONCURRENT_INSERT, - OPT_MEMLOCK, OPT_MYISAM_RECOVER, - OPT_REPLICATE_REWRITE_DB, OPT_SERVER_ID, - OPT_SKIP_SLAVE_START, OPT_SAFE_SHOW_DB, - OPT_SAFEMALLOC_MEM_LIMIT, OPT_REPLICATE_DO_TABLE, - OPT_REPLICATE_IGNORE_TABLE, OPT_REPLICATE_WILD_DO_TABLE, - OPT_REPLICATE_WILD_IGNORE_TABLE, OPT_REPLICATE_SAME_SERVER_ID, - OPT_DISCONNECT_SLAVE_EVENT_COUNT, OPT_TC_HEURISTIC_RECOVER, - OPT_ABORT_SLAVE_EVENT_COUNT, - OPT_LOG_BIN_TRUST_FUNCTION_CREATORS, - OPT_LOG_BIN_TRUST_FUNCTION_CREATORS_OLD, - OPT_ENGINE_CONDITION_PUSHDOWN, OPT_NDB_CONNECTSTRING, - OPT_NDB_USE_EXACT_COUNT, OPT_NDB_USE_TRANSACTIONS, - OPT_NDB_FORCE_SEND, OPT_NDB_AUTOINCREMENT_PREFETCH_SZ, - OPT_NDB_SHM, OPT_NDB_OPTIMIZED_NODE_SELECTION, OPT_NDB_CACHE_CHECK_TIME, - OPT_NDB_MGMD, OPT_NDB_NODEID, - OPT_NDB_DISTRIBUTION, - OPT_NDB_INDEX_STAT_ENABLE, - OPT_NDB_EXTRA_LOGGING, - OPT_NDB_REPORT_THRESH_BINLOG_EPOCH_SLIP, - OPT_NDB_REPORT_THRESH_BINLOG_MEM_USAGE, - OPT_NDB_USE_COPYING_ALTER_TABLE, - OPT_SKIP_SAFEMALLOC, - OPT_TEMP_POOL, OPT_TX_ISOLATION, OPT_COMPLETION_TYPE, - OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS, - OPT_MAX_BINLOG_DUMP_EVENTS, OPT_SPORADIC_BINLOG_DUMP_FAIL, - OPT_SAFE_USER_CREATE, OPT_SQL_MODE, - OPT_HAVE_NAMED_PIPE, - OPT_DO_PSTACK, OPT_EVENT_SCHEDULER, OPT_REPORT_HOST, - OPT_REPORT_USER, OPT_REPORT_PASSWORD, OPT_REPORT_PORT, - OPT_SHOW_SLAVE_AUTH_INFO, - OPT_SLAVE_LOAD_TMPDIR, OPT_NO_MIX_TYPE, - OPT_RPL_RECOVERY_RANK,OPT_INIT_RPL_ROLE, - OPT_RELAY_LOG, OPT_RELAY_LOG_INDEX, OPT_RELAY_LOG_INFO_FILE, - OPT_SLAVE_SKIP_ERRORS, OPT_DES_KEY_FILE, OPT_LOCAL_INFILE, - OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, - OPT_SSL_CAPATH, OPT_SSL_CIPHER, - OPT_BACK_LOG, OPT_BINLOG_CACHE_SIZE, - OPT_CONNECT_TIMEOUT, OPT_DELAYED_INSERT_TIMEOUT, - OPT_DELAYED_INSERT_LIMIT, OPT_DELAYED_QUEUE_SIZE, - OPT_FLUSH_TIME, OPT_FT_MIN_WORD_LEN, OPT_FT_BOOLEAN_SYNTAX, - OPT_FT_MAX_WORD_LEN, OPT_FT_QUERY_EXPANSION_LIMIT, OPT_FT_STOPWORD_FILE, - OPT_INTERACTIVE_TIMEOUT, OPT_JOIN_BUFF_SIZE, - OPT_KEY_BUFFER_SIZE, OPT_KEY_CACHE_BLOCK_SIZE, - OPT_KEY_CACHE_DIVISION_LIMIT, OPT_KEY_CACHE_AGE_THRESHOLD, - OPT_LONG_QUERY_TIME, - OPT_LOWER_CASE_TABLE_NAMES, OPT_MAX_ALLOWED_PACKET, - OPT_MAX_BINLOG_CACHE_SIZE, OPT_MAX_BINLOG_SIZE, - OPT_MAX_CONNECTIONS, OPT_MAX_CONNECT_ERRORS, - OPT_MAX_DELAYED_THREADS, OPT_MAX_HEP_TABLE_SIZE, - OPT_MAX_JOIN_SIZE, OPT_MAX_PREPARED_STMT_COUNT, - OPT_MAX_RELAY_LOG_SIZE, OPT_MAX_SORT_LENGTH, - OPT_MAX_SEEKS_FOR_KEY, OPT_MAX_TMP_TABLES, OPT_MAX_USER_CONNECTIONS, - OPT_MAX_LENGTH_FOR_SORT_DATA, - OPT_MAX_WRITE_LOCK_COUNT, OPT_BULK_INSERT_BUFFER_SIZE, - OPT_MAX_ERROR_COUNT, OPT_MULTI_RANGE_COUNT, OPT_MYISAM_DATA_POINTER_SIZE, - OPT_MYISAM_BLOCK_SIZE, OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE, - OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_SORT_BUFFER_SIZE, - OPT_MYISAM_USE_MMAP, OPT_MYISAM_REPAIR_THREADS, - OPT_MYISAM_MMAP_SIZE, - OPT_MYISAM_STATS_METHOD, - OPT_NET_BUFFER_LENGTH, OPT_NET_RETRY_COUNT, - OPT_NET_READ_TIMEOUT, OPT_NET_WRITE_TIMEOUT, - OPT_OPEN_FILES_LIMIT, - OPT_PRELOAD_BUFFER_SIZE, - OPT_QUERY_CACHE_LIMIT, OPT_QUERY_CACHE_MIN_RES_UNIT, OPT_QUERY_CACHE_SIZE, - OPT_QUERY_CACHE_TYPE, OPT_QUERY_CACHE_WLOCK_INVALIDATE, OPT_RECORD_BUFFER, - OPT_RECORD_RND_BUFFER, OPT_DIV_PRECINCREMENT, OPT_RELAY_LOG_SPACE_LIMIT, - OPT_RELAY_LOG_PURGE, - OPT_RELAY_LOG_RECOVERY, - OPT_SLAVE_NET_TIMEOUT, OPT_SLAVE_COMPRESSED_PROTOCOL, OPT_SLOW_LAUNCH_TIME, - OPT_SLAVE_TRANS_RETRIES, OPT_READONLY, OPT_DEBUGGING, - OPT_SORT_BUFFER, OPT_TABLE_OPEN_CACHE, OPT_TABLE_DEF_CACHE, - OPT_THREAD_CONCURRENCY, OPT_THREAD_CACHE_SIZE, - OPT_TMP_TABLE_SIZE, OPT_THREAD_STACK, - OPT_WAIT_TIMEOUT, - OPT_ERROR_LOG_FILE, - OPT_DEFAULT_WEEK_FORMAT, - OPT_RANGE_ALLOC_BLOCK_SIZE, OPT_ALLOW_SUSPICIOUS_UDFS, - OPT_QUERY_ALLOC_BLOCK_SIZE, OPT_QUERY_PREALLOC_SIZE, - OPT_TRANS_ALLOC_BLOCK_SIZE, OPT_TRANS_PREALLOC_SIZE, - OPT_SYNC_FRM, OPT_SYNC_BINLOG, - OPT_SYNC_REPLICATION, - OPT_SYNC_REPLICATION_SLAVE_ID, - OPT_SYNC_REPLICATION_TIMEOUT, - OPT_ENABLE_SHARED_MEMORY, - OPT_SHARED_MEMORY_BASE_NAME, - OPT_OLD_PASSWORDS, - OPT_OLD_ALTER_TABLE, - OPT_EXPIRE_LOGS_DAYS, - OPT_GROUP_CONCAT_MAX_LEN, - OPT_DEFAULT_COLLATION, - OPT_DEFAULT_COLLATION_OLD, - OPT_CHARACTER_SET_CLIENT_HANDSHAKE, - OPT_CHARACTER_SET_FILESYSTEM, - OPT_LC_ERROR_MESSAGES, - OPT_LC_TIME_NAMES, - OPT_INIT_CONNECT, - OPT_INIT_SLAVE, - OPT_SECURE_AUTH, - OPT_DATE_FORMAT, - OPT_TIME_FORMAT, - OPT_DATETIME_FORMAT, - OPT_LOG_QUERIES_NOT_USING_INDEXES, - OPT_DEFAULT_TIME_ZONE, - OPT_SYSDATE_IS_NOW, - OPT_OPTIMIZER_SEARCH_DEPTH, - OPT_OPTIMIZER_PRUNE_LEVEL, - OPT_OPTIMIZER_SWITCH, - OPT_UPDATABLE_VIEWS_WITH_LIMIT, - OPT_SP_AUTOMATIC_PRIVILEGES, - OPT_MAX_SP_RECURSION_DEPTH, - OPT_AUTO_INCREMENT, OPT_AUTO_INCREMENT_OFFSET, - OPT_ENABLE_LARGE_PAGES, - OPT_ENABLE_SUPER_LARGE_PAGES, - OPT_TIMED_MUTEXES, - OPT_OLD_STYLE_USER_LIMITS, - OPT_LOG_SLOW_ADMIN_STATEMENTS, - OPT_TABLE_LOCK_WAIT_TIMEOUT, - OPT_PLUGIN_LOAD, - OPT_PLUGIN_DIR, - OPT_SYMBOLIC_LINKS, - OPT_WARNINGS, - OPT_RECORD_BUFFER_OLD, - OPT_LOG_OUTPUT, - OPT_PORT_OPEN_TIMEOUT, - OPT_PROFILING, - OPT_KEEP_FILES_ON_CREATE, - OPT_GENERAL_LOG, - OPT_SLOW_LOG, - OPT_THREAD_HANDLING, - OPT_INNODB_ROLLBACK_ON_TIMEOUT, - OPT_SECURE_FILE_PRIV, - OPT_MIN_EXAMINED_ROW_LIMIT, - OPT_LOG_SLOW_SLAVE_STATEMENTS, -#if defined(ENABLED_DEBUG_SYNC) - OPT_DEBUG_SYNC_TIMEOUT, -#endif /* defined(ENABLED_DEBUG_SYNC) */ - OPT_OLD_MODE, - OPT_SLAVE_EXEC_MODE, - OPT_GENERAL_LOG_FILE, - OPT_SLOW_QUERY_LOG_FILE, - OPT_IGNORE_BUILTIN_INNODB, - OPT_SYNC_RELAY_LOG, - OPT_SYNC_RELAY_LOG_INFO, - OPT_SYNC_MASTER_INFO, - OPT_BINLOG_DIRECT_NON_TRANS_UPDATE, - OPT_DEFAULT_CHARACTER_SET_OLD -}; - +DYNAMIC_ARRAY all_options; -#define LONG_TIMEOUT ((ulong) 3600L*24L*365L) +/** + System variables are automatically command-line options (few + exceptions are documented in sys_var.h), so don't need + to be listed here. +*/ -struct my_option my_long_options[] = +struct my_option my_long_options[]= { {"help", '?', "Display this help and exit.", (uchar**) &opt_help, (uchar**) &opt_help, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_REPLICATION - {"abort-slave-event-count", OPT_ABORT_SLAVE_EVENT_COUNT, + {"abort-slave-event-count", 0, "Option used by mysql-test for debugging and testing of replication.", (uchar**) &abort_slave_event_count, (uchar**) &abort_slave_event_count, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_REPLICATION */ - {"allow-suspicious-udfs", OPT_ALLOW_SUSPICIOUS_UDFS, + {"allow-suspicious-udfs", 0, "Allows use of UDFs consisting of only one symbol xxx() " "without corresponding xxx_init() or xxx_deinit(). That also means " "that one can load any function from any library, for example exit() " @@ -5796,51 +5922,16 @@ struct my_option my_long_options[] = 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax. This mode will also set transaction isolation level 'serializable'.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"auto-increment-increment", OPT_AUTO_INCREMENT, - "Auto-increment columns are incremented by this", - (uchar**) &global_system_variables.auto_increment_increment, - (uchar**) &max_system_variables.auto_increment_increment, 0, GET_ULONG, - OPT_ARG, 1, 1, 65535, 0, 1, 0 }, - {"auto-increment-offset", OPT_AUTO_INCREMENT_OFFSET, - "Offset added to Auto-increment columns. Used when auto-increment-increment != 1", - (uchar**) &global_system_variables.auto_increment_offset, - (uchar**) &max_system_variables.auto_increment_offset, 0, GET_ULONG, OPT_ARG, - 1, 1, 65535, 0, 1, 0 }, - {"automatic-sp-privileges", OPT_SP_AUTOMATIC_PRIVILEGES, - "Creating and dropping stored procedures alters ACLs. Disable with --skip-automatic-sp-privileges.", - (uchar**) &sp_automatic_privileges, (uchar**) &sp_automatic_privileges, - 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, - {"basedir", 'b', - "Path to installation directory. All paths are usually resolved relative to this.", - (uchar**) &mysql_home_ptr, (uchar**) &mysql_home_ptr, 0, GET_STR, REQUIRED_ARG, - 0, 0, 0, 0, 0, 0}, - {"big-tables", OPT_BIG_TABLES, - "Allow big result sets by saving all temporary sets on file (Solves most 'table full' errors).", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"bind-address", OPT_BIND_ADDRESS, "IP address to bind to.", (uchar**) &my_bind_addr_str, (uchar**) &my_bind_addr_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"binlog_format", OPT_BINLOG_FORMAT, - "Does not have any effect without '--log-bin'. " - "Tell the master the form of binary logging to use: either 'row' for " - "row-based binary logging, or 'statement' for statement-based binary " - "logging, or 'mixed'. 'mixed' is statement-based binary logging except " - "for those statements where only row-based is correct: those which " - "involve user-defined functions (i.e. UDFs) or the UUID() function; for " - "those, row-based binary logging is automatically used. " -#ifdef HAVE_NDB_BINLOG - "If ndbcluster is enabled and binlog_format is `mixed', the format switches" - " to 'row' and back implicitly per each query accessing a NDB table." -#endif - ,(uchar**) &opt_binlog_format, (uchar**) &opt_binlog_format, - 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"binlog-do-db", OPT_BINLOG_DO_DB, "Tells the master it should log updates for the specified database, and exclude all others not explicitly mentioned.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB, "Tells the master that updates to the given database should not be logged tothe binary log.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"binlog-row-event-max-size", OPT_BINLOG_ROWS_EVENT_MAX_SIZE, + {"binlog-row-event-max-size", 0, "The maximum size of a row-based binary log event in bytes. Rows will be " "grouped into events smaller than this size if possible. " "The value has to be a multiple of 256.", @@ -5855,12 +5946,12 @@ struct my_option my_long_options[] = {"bootstrap", OPT_BOOTSTRAP, "Used by mysql installation scripts.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"character-set-client-handshake", OPT_CHARACTER_SET_CLIENT_HANDSHAKE, + {"character-set-client-handshake", 0, "Don't ignore client side character set value sent during handshake.", (uchar**) &opt_character_set_client_handshake, (uchar**) &opt_character_set_client_handshake, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, - {"character-set-filesystem", OPT_CHARACTER_SET_FILESYSTEM, + {"character-set-filesystem", 0, "Set the filesystem character set.", (uchar**) &character_set_filesystem_name, (uchar**) &character_set_filesystem_name, @@ -5868,230 +5959,117 @@ struct my_option my_long_options[] = {"character-set-server", 'C', "Set the default character set.", (uchar**) &default_character_set_name, (uchar**) &default_character_set_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, - {"character-sets-dir", OPT_CHARSETS_DIR, - "Directory where character sets are.", (uchar**) &charsets_dir, - (uchar**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"chroot", 'r', "Chroot mysqld daemon during startup.", (uchar**) &mysqld_chroot, (uchar**) &mysqld_chroot, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"collation-server", OPT_DEFAULT_COLLATION, "Set the default collation.", + {"collation-server", 0, "Set the default collation.", (uchar**) &default_collation_name, (uchar**) &default_collation_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, - {"completion-type", OPT_COMPLETION_TYPE, "Default completion type.", - (uchar**) &global_system_variables.completion_type, - (uchar**) &max_system_variables.completion_type, 0, GET_ULONG, - REQUIRED_ARG, 0, 0, 2, 0, 1, 0}, - {"concurrent-insert", OPT_CONCURRENT_INSERT, - "Use concurrent insert with MyISAM. Disable with --concurrent-insert=0", - (uchar**) &myisam_concurrent_insert, (uchar**) &myisam_concurrent_insert, - 0, GET_ULONG, OPT_ARG, 1, 0, 2, 0, 0, 0}, {"console", OPT_CONSOLE, "Write error output on screen; Don't remove the console window on windows.", (uchar**) &opt_console, (uchar**) &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"core-file", OPT_WANT_CORE, "Write core on errors.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"datadir", 'h', "Path to the database root.", (uchar**) &mysql_data_home, - (uchar**) &mysql_data_home, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#ifndef DBUG_OFF - {"debug", '#', "Debug log.", (uchar**) &default_dbug_option, - (uchar**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, -#endif - {"default-character-set", OPT_DEFAULT_CHARACTER_SET_OLD, - "Set the default character set (deprecated option, use --character-set-server instead).", + {"default-character-set", 'C', "Set the default character set (deprecated option, use --character-set-server instead).", (uchar**) &default_character_set_name, (uchar**) &default_character_set_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, - {"default-collation", OPT_DEFAULT_COLLATION_OLD, "Set the default collation (deprecated option, use --collation-server instead).", + {"default-collation", 0, "Set the default collation (deprecated option, use --collation-server instead).", (uchar**) &default_collation_name, (uchar**) &default_collation_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, - {"default-storage-engine", OPT_STORAGE_ENGINE, - "Set the default storage engine (table type) for tables.", - (uchar**)&default_storage_engine_str, (uchar**)&default_storage_engine_str, - 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"default-time-zone", OPT_DEFAULT_TIME_ZONE, "Set the default time zone.", + /* default-storage-engine should have "MyISAM" as def_value. Instead + of initializing it here it is done in init_common_variables() due + to a compiler bug in Sun Studio compiler. */ + {"default-storage-engine", 0, "The default storage engine for new tables", + (uchar**) &default_storage_engine, 0, 0, GET_STR, REQUIRED_ARG, + 0, 0, 0, 0, 0, 0 }, + {"default-time-zone", 0, "Set the default time zone.", (uchar**) &default_tz_name, (uchar**) &default_tz_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, - {"delay-key-write", OPT_DELAY_KEY_WRITE, "Type of DELAY_KEY_WRITE.", - 0,0,0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"delay-key-write-for-all-tables", OPT_DELAY_KEY_WRITE_ALL, "Don't flush key buffers between writes for any MyISAM table (Deprecated option, use --delay-key-write=all instead).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_OPENSSL - {"des-key-file", OPT_DES_KEY_FILE, + {"des-key-file", 0, "Load keys for des_encrypt() and des_encrypt from given file.", (uchar**) &des_key_file, (uchar**) &des_key_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_OPENSSL */ #ifdef HAVE_REPLICATION - {"disconnect-slave-event-count", OPT_DISCONNECT_SLAVE_EVENT_COUNT, + {"disconnect-slave-event-count", 0, "Option used by mysql-test for debugging and testing of replication.", (uchar**) &disconnect_slave_event_count, (uchar**) &disconnect_slave_event_count, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_REPLICATION */ - {"enable-locking", OPT_ENABLE_LOCK, + {"enable-locking", 0, "Deprecated option, use --external-locking instead.", (uchar**) &opt_external_locking, (uchar**) &opt_external_locking, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef _WIN32 - {"enable-named-pipe", OPT_HAVE_NAMED_PIPE, "Enable the named pipe (NT).", - (uchar**) &opt_enable_named_pipe, (uchar**) &opt_enable_named_pipe, 0, GET_BOOL, - NO_ARG, 0, 0, 0, 0, 0, 0}, -#endif #ifdef HAVE_STACK_TRACE_ON_SEGV - {"enable-pstack", OPT_DO_PSTACK, "Print a symbolic stack trace on failure.", + {"enable-pstack", 0, "Print a symbolic stack trace on failure.", (uchar**) &opt_do_pstack, (uchar**) &opt_do_pstack, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_STACK_TRACE_ON_SEGV */ - {"engine-condition-pushdown", - OPT_ENGINE_CONDITION_PUSHDOWN, - "Push supported query conditions to the storage engine.", - (uchar**) &global_system_variables.engine_condition_pushdown, - (uchar**) &global_system_variables.engine_condition_pushdown, - 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, /* See how it's handled in get_one_option() */ - {"event-scheduler", OPT_EVENT_SCHEDULER, "Enable/disable the event scheduler.", - NULL, NULL, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"exit-info", 'T', "Used for debugging; Use at your own risk!", 0, 0, 0, GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"external-locking", OPT_USE_LOCKING, "Use system (external) locking (disabled by default). With this option enabled you can run myisamchk to test (not repair) tables while the MySQL server is running. Disable with --skip-external-locking.", + {"external-locking", 0, "Use system (external) locking (disabled by default). With this option enabled you can run myisamchk to test (not repair) tables while the MySQL server is running. Disable with --skip-external-locking.", (uchar**) &opt_external_locking, (uchar**) &opt_external_locking, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"flush", OPT_FLUSH, "Flush tables to disk between SQL commands.", 0, 0, 0, - GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, /* We must always support the next option to make scripts like mysqltest easier to do */ - {"gdb", OPT_DEBUGGING, + {"gdb", 0, "Set up signals usable for debugging", (uchar**) &opt_debugging, (uchar**) &opt_debugging, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"general_log", OPT_GENERAL_LOG, - "Enable|disable general log", (uchar**) &opt_log, - (uchar**) &opt_log, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_LARGE_PAGE_OPTION - {"large-pages", OPT_ENABLE_LARGE_PAGES, "Enable support for large pages. \ -Disable with --skip-large-pages.", - (uchar**) &opt_large_pages, (uchar**) &opt_large_pages, 0, GET_BOOL, - NO_ARG, 0, 0, 1, 0, 1, 0}, - {"super-large-pages", OPT_ENABLE_SUPER_LARGE_PAGES, - "Enable support for super large pages. \ -Disable with --skip-super-large-pages.", + {"super-large-pages", 0, "Enable support for super large pages.", (uchar**) &opt_super_large_pages, (uchar**) &opt_super_large_pages, 0, - GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0}, + GET_BOOL, OPT_ARG, 0, 0, 1, 0, 1, 0}, #endif - {"ignore-builtin-innodb", OPT_IGNORE_BUILTIN_INNODB , - "Disable initialization of builtin InnoDB plugin", - 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"init-connect", OPT_INIT_CONNECT, "Command(s) that are executed for each new connection", - (uchar**) &opt_init_connect, (uchar**) &opt_init_connect, 0, GET_STR_ALLOC, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#ifndef DISABLE_GRANT_OPTIONS - {"init-file", OPT_INIT_FILE, "Read SQL commands from this file at startup.", - (uchar**) &opt_init_file, (uchar**) &opt_init_file, 0, GET_STR, REQUIRED_ARG, - 0, 0, 0, 0, 0, 0}, -#endif - {"init-rpl-role", OPT_INIT_RPL_ROLE, "Set the replication role.", 0, 0, 0, - GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"init-slave", OPT_INIT_SLAVE, "Command(s) that are executed by a slave server \ -each time the SQL thread starts.", - (uchar**) &opt_init_slave, (uchar**) &opt_init_slave, 0, GET_STR_ALLOC, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"language", 'L', "Client error messages in given language. May be given as a full path. " "Deprecated. Use --lc-messages-dir instead.", (uchar**) &lc_messages_dir_ptr, (uchar**) &lc_messages_dir_ptr, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"lc-messages-dir", 'L', - "Directory where error messages are.", (uchar**) &lc_messages_dir_ptr, - (uchar**) &lc_messages_dir_ptr, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"lc-messages", OPT_LC_ERROR_MESSAGES, + {"lc-messages", 0, "Set the language used for the error messages.", (uchar**) &lc_messages, (uchar**) &lc_messages, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, - {"lc-time-names", OPT_LC_TIME_NAMES, + {"lc-time-names", 0, "Set the language used for the month names and the days of the week.", (uchar**) &lc_time_names_name, (uchar**) &lc_time_names_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, - {"local-infile", OPT_LOCAL_INFILE, - "Enable/disable LOAD DATA LOCAL INFILE (takes values 1|0).", - (uchar**) &opt_local_infile, - (uchar**) &opt_local_infile, 0, GET_BOOL, OPT_ARG, - 1, 0, 0, 0, 0, 0}, {"log", 'l', "Log connections and queries to file (deprecated option, use " - "--general_log/--general_log_file instead).", (uchar**) &opt_logname, - (uchar**) &opt_logname, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"general_log_file", OPT_GENERAL_LOG_FILE, - "Log connections and queries to given file.", (uchar**) &opt_logname, - (uchar**) &opt_logname, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "--general-log/--general-log-file instead).", (uchar**) &opt_logname, + (uchar**) &opt_logname, 0, GET_STR_ALLOC, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"log-bin", OPT_BIN_LOG, "Log update queries in binary format. Optional (but strongly recommended " "to avoid replication problems if server's hostname changes) argument " "should be the chosen location for the binary log files.", (uchar**) &opt_bin_logname, (uchar**) &opt_bin_logname, 0, GET_STR_ALLOC, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"log-bin-index", OPT_BIN_LOG_INDEX, + {"log-bin-index", 0, "File that holds the names for last binary log files.", (uchar**) &opt_binlog_index_name, (uchar**) &opt_binlog_index_name, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#ifndef TO_BE_REMOVED_IN_5_1_OR_6_0 - /* - In 5.0.6 we introduced the below option, then in 5.0.16 we renamed it to - log-bin-trust-function-creators but kept also the old name for - compatibility; the behaviour was also changed to apply only to functions - (and triggers). In a future release this old name could be removed. - */ - {"log-bin-trust-routine-creators", OPT_LOG_BIN_TRUST_FUNCTION_CREATORS_OLD, - "(deprecated) Use log-bin-trust-function-creators.", - (uchar**) &trust_function_creators, (uchar**) &trust_function_creators, 0, - GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, -#endif - /* - This option starts with "log-bin" to emphasize that it is specific of - binary logging. - */ - {"log-bin-trust-function-creators", OPT_LOG_BIN_TRUST_FUNCTION_CREATORS, - "If equal to 0 (the default), then when --log-bin is used, creation of " - "a stored function (or trigger) is allowed only to users having the SUPER privilege " - "and only if this stored function (trigger) may not break binary logging." - "Note that if ALL connections to this server ALWAYS use row-based binary " - "logging, the security issues do not exist and the binary logging cannot " - "break, so you can safely set this to 1." - ,(uchar**) &trust_function_creators, (uchar**) &trust_function_creators, 0, - GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"log-error", OPT_ERROR_LOG_FILE, "Error log file.", - (uchar**) &log_error_file_ptr, (uchar**) &log_error_file_ptr, 0, GET_STR, - OPT_ARG, 0, 0, 0, 0, 0, 0}, {"log-isam", OPT_ISAM_LOG, "Log all MyISAM changes to file.", (uchar**) &myisam_log_filename, (uchar**) &myisam_log_filename, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"log-long-format", '0', "Log some extra information to update log. Please note that this option is deprecated; see --log-short-format option.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef WITH_CSV_STORAGE_ENGINE - {"log-output", OPT_LOG_OUTPUT, - "Syntax: log-output[=value[,value...]], where \"value\" could be TABLE, " - "FILE or NONE.", - (uchar**) &log_output_str, (uchar**) &log_output_str, 0, - GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, -#endif - {"log-queries-not-using-indexes", OPT_LOG_QUERIES_NOT_USING_INDEXES, - "Log queries that are executed without benefit of any index to the slow log if it is open.", - (uchar**) &opt_log_queries_not_using_indexes, (uchar**) &opt_log_queries_not_using_indexes, - 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"log-short-format", OPT_SHORT_LOG_FORMAT, + {"log-short-format", 0, "Don't log extra information to update and slow-query logs.", (uchar**) &opt_short_log_format, (uchar**) &opt_short_log_format, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"log-slave-updates", OPT_LOG_SLAVE_UPDATES, - "Tells the slave to log the updates from the slave thread to the binary log. You will need to turn it on if you plan to daisy-chain the slaves.", - (uchar**) &opt_log_slave_updates, (uchar**) &opt_log_slave_updates, 0, GET_BOOL, - NO_ARG, 0, 0, 0, 0, 0, 0}, - {"log-slow-admin-statements", OPT_LOG_SLOW_ADMIN_STATEMENTS, + {"log-slow-admin-statements", 0, "Log slow OPTIMIZE, ANALYZE, ALTER and other administrative statements to the slow log if it is open.", (uchar**) &opt_log_slow_admin_statements, (uchar**) &opt_log_slow_admin_statements, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"log-slow-slave-statements", OPT_LOG_SLOW_SLAVE_STATEMENTS, + {"log-slow-slave-statements", 0, "Log slow statements executed by slave thread to the slow log if it is open.", (uchar**) &opt_log_slow_slave_statements, (uchar**) &opt_log_slow_slave_statements, @@ -6101,19 +6079,15 @@ each time the SQL thread starts.", "mysql.slow_log or hostname-slow.log if --log-output=file is used. " "Must be enabled to activate other slow log options. " "Deprecated option, use --slow-query-log/--slow-query-log-file instead.", - (uchar**) &opt_slow_logname, (uchar**) &opt_slow_logname, 0, GET_STR, OPT_ARG, + (uchar**) &opt_slow_logname, (uchar**) &opt_slow_logname, 0, GET_STR_ALLOC, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"slow-query-log-file", OPT_SLOW_QUERY_LOG_FILE, - "Log slow queries to given log file. Defaults logging to hostname-slow.log. Must be enabled to activate other slow log options.", - (uchar**) &opt_slow_logname, (uchar**) &opt_slow_logname, 0, GET_STR, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"log-tc", OPT_LOG_TC, + {"log-tc", 0, "Path to transaction coordinator log (used for transactions that affect " "more than one storage engine, when binary log is disabled)", (uchar**) &opt_tc_log_file, (uchar**) &opt_tc_log_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_MMAP - {"log-tc-size", OPT_LOG_TC_SIZE, "Size of transaction coordinator log.", + {"log-tc-size", 0, "Size of transaction coordinator log.", (uchar**) &opt_tc_log_size, (uchar**) &opt_tc_log_size, 0, GET_ULONG, REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, ULONG_MAX, 0, TC_LOG_PAGE_SIZE, 0}, @@ -6123,244 +6097,37 @@ each time the SQL thread starts.", log and this option justs turns on --log-bin instead.", (uchar**) &opt_update_logname, (uchar**) &opt_update_logname, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"log-warnings", 'W', "Log some not critical warnings to the log file.", - (uchar**) &global_system_variables.log_warnings, - (uchar**) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, 0, - 0, 0, 0}, - {"low-priority-updates", OPT_LOW_PRIORITY_UPDATES, - "INSERT/DELETE/UPDATE has lower priority than selects.", - (uchar**) &global_system_variables.low_priority_updates, - (uchar**) &max_system_variables.low_priority_updates, - 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"master-connect-retry", OPT_MASTER_CONNECT_RETRY, - "The number of seconds the slave thread will sleep before retrying to connect to the master in case the master goes down or the connection is lost.", - (uchar**) &master_connect_retry, (uchar**) &master_connect_retry, 0, GET_UINT, - REQUIRED_ARG, 60, 0, 0, 0, 0, 0}, - {"master-host", OPT_MASTER_HOST, - "Master hostname or IP address for replication. If not set, the slave thread will not be started. Note that the setting of master-host will be ignored if there exists a valid master.info file.", - (uchar**) &master_host, (uchar**) &master_host, 0, GET_STR, REQUIRED_ARG, 0, 0, - 0, 0, 0, 0}, - {"master-info-file", OPT_MASTER_INFO_FILE, + {"master-info-file", 0, "The location and name of the file that remembers the master and where the I/O replication \ thread is in the master's binlogs.", (uchar**) &master_info_file, (uchar**) &master_info_file, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"master-password", OPT_MASTER_PASSWORD, - "The password the slave thread will authenticate with when connecting to the master. If not set, an empty password is assumed.The value in master.info will take precedence if it can be read.", - (uchar**)&master_password, (uchar**)&master_password, 0, - GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"master-port", OPT_MASTER_PORT, - "The port the master is listening on. If not set, the compiled setting of MYSQL_PORT is assumed. If you have not tinkered with configure options, this should be 3306. The value in master.info will take precedence if it can be read.", - (uchar**) &master_port, (uchar**) &master_port, 0, GET_UINT, REQUIRED_ARG, - MYSQL_PORT, 0, 0, 0, 0, 0}, - {"master-retry-count", OPT_MASTER_RETRY_COUNT, + {"master-retry-count", 0, "The number of tries the slave will make to connect to the master before giving up.", (uchar**) &master_retry_count, (uchar**) &master_retry_count, 0, GET_ULONG, REQUIRED_ARG, 3600*24, 0, 0, 0, 0, 0}, - {"master-ssl", OPT_MASTER_SSL, - "Enable the slave to connect to the master using SSL.", - (uchar**) &master_ssl, (uchar**) &master_ssl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, - 0, 0}, - {"master-ssl-ca", OPT_MASTER_SSL_CA, - "Master SSL CA file. Only applies if you have enabled master-ssl.", - (uchar**) &master_ssl_ca, (uchar**) &master_ssl_ca, 0, GET_STR, OPT_ARG, - 0, 0, 0, 0, 0, 0}, - {"master-ssl-capath", OPT_MASTER_SSL_CAPATH, - "Master SSL CA path. Only applies if you have enabled master-ssl.", - (uchar**) &master_ssl_capath, (uchar**) &master_ssl_capath, 0, GET_STR, OPT_ARG, - 0, 0, 0, 0, 0, 0}, - {"master-ssl-cert", OPT_MASTER_SSL_CERT, - "Master SSL certificate file name. Only applies if you have enabled \ -master-ssl", - (uchar**) &master_ssl_cert, (uchar**) &master_ssl_cert, 0, GET_STR, OPT_ARG, - 0, 0, 0, 0, 0, 0}, - {"master-ssl-cipher", OPT_MASTER_SSL_CIPHER, - "Master SSL cipher. Only applies if you have enabled master-ssl.", - (uchar**) &master_ssl_cipher, (uchar**) &master_ssl_capath, 0, GET_STR, OPT_ARG, - 0, 0, 0, 0, 0, 0}, - {"master-ssl-key", OPT_MASTER_SSL_KEY, - "Master SSL keyfile name. Only applies if you have enabled master-ssl.", - (uchar**) &master_ssl_key, (uchar**) &master_ssl_key, 0, GET_STR, OPT_ARG, - 0, 0, 0, 0, 0, 0}, - {"master-user", OPT_MASTER_USER, - "The username the slave thread will use for authentication when connecting to the master. The user must have FILE privilege. If the master user is not set, user test is assumed. The value in master.info will take precedence if it can be read.", - (uchar**) &master_user, (uchar**) &master_user, 0, GET_STR, REQUIRED_ARG, 0, 0, - 0, 0, 0, 0}, #ifdef HAVE_REPLICATION - {"max-binlog-dump-events", OPT_MAX_BINLOG_DUMP_EVENTS, + {"init-rpl-role", 0, "Set the replication role.", + (uchar**)&rpl_status, (uchar**)&rpl_status, &rpl_role_typelib, + GET_ENUM, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"max-binlog-dump-events", 0, "Option used by mysql-test for debugging and testing of replication.", (uchar**) &max_binlog_dump_events, (uchar**) &max_binlog_dump_events, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_REPLICATION */ - {"memlock", OPT_MEMLOCK, "Lock mysqld in memory.", (uchar**) &locked_in_memory, + {"memlock", 0, "Lock mysqld in memory.", (uchar**) &locked_in_memory, (uchar**) &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"myisam-recover", OPT_MYISAM_RECOVER, - "Syntax: myisam-recover[=option[,option...]], where option can be DEFAULT, BACKUP, FORCE or QUICK.", - (uchar**) &myisam_recover_options_str, (uchar**) &myisam_recover_options_str, 0, - GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE - {"ndb-connectstring", OPT_NDB_CONNECTSTRING, - "Connect string for ndbcluster.", - (uchar**) &opt_ndb_connectstring, - (uchar**) &opt_ndb_connectstring, - 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"ndb-mgmd-host", OPT_NDB_MGMD, - "Set host and port for ndb_mgmd. Syntax: hostname[:port]", - (uchar**) &opt_ndb_mgmd, - (uchar**) &opt_ndb_mgmd, - 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"ndb-nodeid", OPT_NDB_NODEID, - "Nodeid for this mysqlserver in the cluster.", - (uchar**) &opt_ndb_nodeid, - (uchar**) &opt_ndb_nodeid, - 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"ndb-autoincrement-prefetch-sz", OPT_NDB_AUTOINCREMENT_PREFETCH_SZ, - "Specify number of autoincrement values that are prefetched.", - (uchar**) &global_system_variables.ndb_autoincrement_prefetch_sz, - (uchar**) &max_system_variables.ndb_autoincrement_prefetch_sz, - 0, GET_ULONG, REQUIRED_ARG, 1, 1, 256, 0, 0, 0}, - {"ndb-force-send", OPT_NDB_FORCE_SEND, - "Force send of buffers to ndb immediately without waiting for " - "other threads.", - (uchar**) &global_system_variables.ndb_force_send, - (uchar**) &global_system_variables.ndb_force_send, - 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, - {"ndb_force_send", OPT_NDB_FORCE_SEND, - "same as --ndb-force-send.", - (uchar**) &global_system_variables.ndb_force_send, - (uchar**) &global_system_variables.ndb_force_send, - 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, - {"ndb-extra-logging", OPT_NDB_EXTRA_LOGGING, - "Turn on more logging in the error log.", - (uchar**) &ndb_extra_logging, - (uchar**) &ndb_extra_logging, - 0, GET_INT, OPT_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef HAVE_NDB_BINLOG - {"ndb-report-thresh-binlog-epoch-slip", OPT_NDB_REPORT_THRESH_BINLOG_EPOCH_SLIP, - "Threshold on number of epochs to be behind before reporting binlog status. " - "E.g. 3 means that if the difference between what epoch has been received " - "from the storage nodes and what has been applied to the binlog is 3 or more, " - "a status message will be sent to the cluster log.", - (uchar**) &ndb_report_thresh_binlog_epoch_slip, - (uchar**) &ndb_report_thresh_binlog_epoch_slip, - 0, GET_ULONG, REQUIRED_ARG, 3, 0, 256, 0, 0, 0}, - {"ndb-report-thresh-binlog-mem-usage", OPT_NDB_REPORT_THRESH_BINLOG_MEM_USAGE, - "Threshold on percentage of free memory before reporting binlog status. E.g. " - "10 means that if amount of available memory for receiving binlog data from " - "the storage nodes goes below 10%, " - "a status message will be sent to the cluster log.", - (uchar**) &ndb_report_thresh_binlog_mem_usage, - (uchar**) &ndb_report_thresh_binlog_mem_usage, - 0, GET_ULONG, REQUIRED_ARG, 10, 0, 100, 0, 0, 0}, -#endif - {"ndb-use-exact-count", OPT_NDB_USE_EXACT_COUNT, - "Use exact records count during query planning and for fast " - "select count(*), disable for faster queries.", - (uchar**) &global_system_variables.ndb_use_exact_count, - (uchar**) &global_system_variables.ndb_use_exact_count, - 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, - {"ndb_use_exact_count", OPT_NDB_USE_EXACT_COUNT, - "same as --ndb-use-exact-count.", - (uchar**) &global_system_variables.ndb_use_exact_count, - (uchar**) &global_system_variables.ndb_use_exact_count, - 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, - {"ndb-use-transactions", OPT_NDB_USE_TRANSACTIONS, - "Use transactions for large inserts, if enabled then large " - "inserts will be split into several smaller transactions", - (uchar**) &global_system_variables.ndb_use_transactions, - (uchar**) &global_system_variables.ndb_use_transactions, - 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, - {"ndb_use_transactions", OPT_NDB_USE_TRANSACTIONS, - "same as --ndb-use-transactions.", - (uchar**) &global_system_variables.ndb_use_transactions, - (uchar**) &global_system_variables.ndb_use_transactions, - 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, - {"ndb-shm", OPT_NDB_SHM, - "Use shared memory connections when available.", - (uchar**) &opt_ndb_shm, - (uchar**) &opt_ndb_shm, - 0, GET_BOOL, OPT_ARG, OPT_NDB_SHM_DEFAULT, 0, 0, 0, 0, 0}, - {"ndb-optimized-node-selection", OPT_NDB_OPTIMIZED_NODE_SELECTION, - "Select nodes for transactions in a more optimal way.", - (uchar**) &opt_ndb_optimized_node_selection, - (uchar**) &opt_ndb_optimized_node_selection, - 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, - { "ndb-cache-check-time", OPT_NDB_CACHE_CHECK_TIME, - "A dedicated thread is created to, at the given millisecons interval, invalidate the query cache if another MySQL server in the cluster has changed the data in the database.", - (uchar**) &opt_ndb_cache_check_time, (uchar**) &opt_ndb_cache_check_time, 0, GET_ULONG, REQUIRED_ARG, - 0, 0, LONG_TIMEOUT, 0, 1, 0}, - {"ndb-index-stat-enable", OPT_NDB_INDEX_STAT_ENABLE, - "Use ndb index statistics in query optimization.", - (uchar**) &global_system_variables.ndb_index_stat_enable, - (uchar**) &max_system_variables.ndb_index_stat_enable, - 0, GET_BOOL, OPT_ARG, 0, 0, 1, 0, 0, 0}, -#endif - {"ndb-use-copying-alter-table", - OPT_NDB_USE_COPYING_ALTER_TABLE, - "Force ndbcluster to always copy tables at alter table (should only be used if on-line alter table fails).", - (uchar**) &global_system_variables.ndb_use_copying_alter_table, - (uchar**) &global_system_variables.ndb_use_copying_alter_table, - 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"new", 'n', "Use very new possible 'unsafe' functions.", - (uchar**) &global_system_variables.new_mode, - (uchar**) &max_system_variables.new_mode, - 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef NOT_YET - {"no-mix-table-types", OPT_NO_MIX_TYPE, "Don't allow commands with uses two different table types.", - (uchar**) &opt_no_mix_types, (uchar**) &opt_no_mix_types, 0, GET_BOOL, NO_ARG, - 0, 0, 0, 0, 0, 0}, -#endif - {"old-alter-table", OPT_OLD_ALTER_TABLE, - "Use old, non-optimized alter table.", - (uchar**) &global_system_variables.old_alter_table, - (uchar**) &max_system_variables.old_alter_table, 0, GET_BOOL, NO_ARG, - 0, 0, 0, 0, 0, 0}, - {"old-passwords", OPT_OLD_PASSWORDS, "Use old password encryption method (needed for 4.0 and older clients).", - (uchar**) &global_system_variables.old_passwords, - (uchar**) &max_system_variables.old_passwords, 0, GET_BOOL, NO_ARG, - 0, 0, 0, 0, 0, 0}, {"one-thread", OPT_ONE_THREAD, "(deprecated): Only use one thread (for debugging under Linux). Use thread-handling=no-threads instead", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"old-style-user-limits", OPT_OLD_STYLE_USER_LIMITS, + {"old-style-user-limits", 0, "Enable old-style user limits (before 5.0.3 user resources were counted per each user+host vs. per account)", (uchar**) &opt_old_style_user_limits, (uchar**) &opt_old_style_user_limits, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"pid-file", OPT_PID_FILE, "Pid file used by safe_mysqld.", - (uchar**) &pidfile_name_ptr, (uchar**) &pidfile_name_ptr, 0, GET_STR, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"port", 'P', "Port number to use for connection or 0 for default to, in " - "order of preference, my.cnf, $MYSQL_TCP_PORT, " -#if MYSQL_PORT_DEFAULT == 0 - "/etc/services, " -#endif - "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").", - (uchar**) &mysqld_port, - (uchar**) &mysqld_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"port-open-timeout", OPT_PORT_OPEN_TIMEOUT, + {"port-open-timeout", 0, "Maximum time in seconds to wait for the port to become free. " "(Default: no wait)", (uchar**) &mysqld_port_timeout, (uchar**) &mysqld_port_timeout, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#if defined(ENABLED_PROFILING) - {"profiling_history_size", OPT_PROFILING, "Limit of query profiling memory", - (uchar**) &global_system_variables.profiling_history_size, - (uchar**) &max_system_variables.profiling_history_size, - 0, GET_ULONG, REQUIRED_ARG, 15, 0, 100, 0, 0, 0}, -#endif - {"relay-log", OPT_RELAY_LOG, - "The location and name to use for relay logs.", - (uchar**) &opt_relay_logname, (uchar**) &opt_relay_logname, 0, - GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"relay-log-index", OPT_RELAY_LOG_INDEX, - "The location and name to use for the file that keeps a list of the last \ -relay logs.", - (uchar**) &opt_relaylog_index_name, (uchar**) &opt_relaylog_index_name, 0, - GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"relay-log-info-file", OPT_RELAY_LOG_INFO_FILE, - "The location and name of the file that remembers where the SQL replication \ -thread is in the relay logs.", - (uchar**) &relay_log_info_file, (uchar**) &relay_log_info_file, 0, GET_STR, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"replicate-do-db", OPT_REPLICATE_DO_DB, "Tells the slave thread to restrict replication to the specified database. To specify more than one database, use the directive multiple times, once for each database. Note that this will only work if you do not use cross-database queries such as UPDATE some_db.some_table SET foo='bar' while having selected a different or no database. If you need cross database updates to work, make sure you have 3.23.28 or later, and use replicate-wild-do-table=db_name.%.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -6377,7 +6144,7 @@ thread is in the relay logs.", "Updates to a database with a different name than the original. Example: replicate-rewrite-db=master_db_name->slave_db_name.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_REPLICATION - {"replicate-same-server-id", OPT_REPLICATE_SAME_SERVER_ID, + {"replicate-same-server-id", 0, "In replication, if set to 1, do not skip events having our server id. \ Default value is 0 (to break infinite loops in circular replication). \ Can't be set to 1 if --log-slave-updates is used.", @@ -6391,67 +6158,34 @@ Can't be set to 1 if --log-slave-updates is used.", {"replicate-wild-ignore-table", OPT_REPLICATE_WILD_IGNORE_TABLE, "Tells the slave thread to not replicate to the tables that match the given wildcard pattern. To specify more than one table to ignore, use the directive multiple times, once for each table. This will work for cross-database updates. Example: replicate-wild-ignore-table=foo%.bar% will not do updates to tables in databases that start with foo and whose table names start with bar.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - // In replication, we may need to tell the other servers how to connect - {"report-host", OPT_REPORT_HOST, - "Hostname or IP of the slave to be reported to to the master during slave registration. Will appear in the output of SHOW SLAVE HOSTS. Leave unset if you do not want the slave to register itself with the master. Note that it is not sufficient for the master to simply read the IP of the slave off the socket once the slave connects. Due to NAT and other routing issues, that IP may not be valid for connecting to the slave from the master or other hosts.", - (uchar**) &report_host, (uchar**) &report_host, 0, GET_STR, REQUIRED_ARG, 0, 0, - 0, 0, 0, 0}, - {"report-password", OPT_REPORT_PASSWORD, "Undocumented.", - (uchar**) &report_password, (uchar**) &report_password, 0, GET_STR, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"report-port", OPT_REPORT_PORT, - "Port for connecting to slave reported to the master during slave registration. Set it only if the slave is listening on a non-default port or if you have a special tunnel from the master or other clients to the slave. If not sure, leave this option unset.", - (uchar**) &report_port, (uchar**) &report_port, 0, GET_UINT, REQUIRED_ARG, - MYSQL_PORT, 0, 0, 0, 0, 0}, - {"report-user", OPT_REPORT_USER, "Undocumented.", (uchar**) &report_user, - (uchar**) &report_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"rpl-recovery-rank", OPT_RPL_RECOVERY_RANK, "Undocumented.", - (uchar**) &rpl_recovery_rank, (uchar**) &rpl_recovery_rank, 0, GET_ULONG, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"safe-mode", OPT_SAFE, "Skip some optimize stages (for testing).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifndef TO_BE_DELETED - {"safe-show-database", OPT_SAFE_SHOW_DB, + {"safe-show-database", 0, "Deprecated option; use GRANT SHOW DATABASES instead...", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif - {"safe-user-create", OPT_SAFE_USER_CREATE, + {"safe-user-create", 0, "Don't allow new user creation by the user who has no write privileges to the mysql.user table.", (uchar**) &opt_safe_user_create, (uchar**) &opt_safe_user_create, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"safemalloc-mem-limit", OPT_SAFEMALLOC_MEM_LIMIT, - "Simulate memory shortage when compiled with the --with-debug=full option.", - 0, 0, 0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"secure-auth", OPT_SECURE_AUTH, "Disallow authentication for accounts that have old (pre-4.1) passwords.", - (uchar**) &opt_secure_auth, (uchar**) &opt_secure_auth, 0, GET_BOOL, NO_ARG, - my_bool(0), 0, 0, 0, 0, 0}, - {"secure-file-priv", OPT_SECURE_FILE_PRIV, - "Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files within specified directory", - (uchar**) &opt_secure_file_priv, (uchar**) &opt_secure_file_priv, 0, - GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"server-id", OPT_SERVER_ID, - "Uniquely identifies the server instance in the community of replication partners.", - (uchar**) &server_id, (uchar**) &server_id, 0, GET_ULONG, REQUIRED_ARG, 0, 0, UINT_MAX32, - 0, 0, 0}, +#if !defined(DBUG_OFF) && defined(SAFEMALLOC) + {"safemalloc", 0, "Enable the memory allocation checking.", + (uchar**) &sf_malloc_quick, (uchar**) &sf_malloc_quick, 0, + GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, + {"safemalloc-mem-limit", 0, "Simulate memory shortage.", + (uchar**)&sf_malloc_mem_limit, (uchar**)&sf_malloc_mem_limit, 0, GET_UINT, + REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#endif {"set-variable", 'O', "Change the value of a variable. Please note that this option is deprecated;you can set variables directly with --variable-name=value.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#ifdef HAVE_SMEM - {"shared-memory", OPT_ENABLE_SHARED_MEMORY, - "Enable the shared memory.",(uchar**) &opt_enable_shared_memory, (uchar**) &opt_enable_shared_memory, - 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, -#endif -#ifdef HAVE_SMEM - {"shared-memory-base-name",OPT_SHARED_MEMORY_BASE_NAME, - "Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name, - 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#endif - {"show-slave-auth-info", OPT_SHOW_SLAVE_AUTH_INFO, + {"show-slave-auth-info", 0, "Show user and password in SHOW SLAVE HOSTS on this master", (uchar**) &opt_show_slave_auth_info, (uchar**) &opt_show_slave_auth_info, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifndef DISABLE_GRANT_OPTIONS - {"skip-grant-tables", OPT_SKIP_GRANT, + {"skip-grant-tables", 0, "Start without grant tables. This gives all users FULL ACCESS to all tables!", (uchar**) &opt_noacl, (uchar**) &opt_noacl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -6464,22 +6198,9 @@ Can't be set to 1 if --log-slave-updates is used.", {"skip-name-resolve", OPT_SKIP_RESOLVE, "Don't resolve hostnames. All hostnames are IP's or 'localhost'.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"skip-networking", OPT_SKIP_NETWORKING, - "Don't allow connection with TCP/IP.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, - 0, 0, 0}, {"skip-new", OPT_SKIP_NEW, "Don't use new, possible wrong routines.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, -#ifndef DBUG_OFF -#ifdef SAFEMALLOC - {"skip-safemalloc", OPT_SKIP_SAFEMALLOC, - "Don't use the memory allocation checking.", 0, 0, 0, GET_NO_ARG, NO_ARG, - 0, 0, 0, 0, 0, 0}, -#endif -#endif - {"skip-show-database", OPT_SKIP_SHOW_DB, - "Don't allow 'SHOW DATABASE' commands.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, - 0, 0, 0, 0}, - {"skip-slave-start", OPT_SKIP_SLAVE_START, + {"skip-slave-start", 0, "If set, slave is not autostarted.", (uchar**) &opt_skip_slave_start, (uchar**) &opt_skip_slave_start, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"skip-stack-trace", OPT_SKIP_STACK_TRACE, @@ -6488,47 +6209,28 @@ Can't be set to 1 if --log-slave-updates is used.", {"skip-symlink", OPT_SKIP_SYMLINKS, "Don't allow symlinking of tables. Deprecated option. Use --skip-symbolic-links instead.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"skip-thread-priority", OPT_SKIP_PRIOR, - "Don't give threads different priorities. Deprecated option.", 0, 0, 0, GET_NO_ARG, NO_ARG, - DEFAULT_SKIP_THREAD_PRIORITY, 0, 0, 0, 0, 0}, -#ifdef HAVE_REPLICATION - {"slave-load-tmpdir", OPT_SLAVE_LOAD_TMPDIR, - "The location where the slave should put its temporary files when \ -replicating a LOAD DATA INFILE command.", - (uchar**) &slave_load_tmpdir, (uchar**) &slave_load_tmpdir, 0, GET_STR_ALLOC, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"slave-skip-errors", OPT_SLAVE_SKIP_ERRORS, - "Tells the slave thread to continue replication when a query event returns an error from the provided list.", - 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"slave-exec-mode", OPT_SLAVE_EXEC_MODE, - "Modes for how replication events should be executed. Legal values are STRICT (default) and IDEMPOTENT. In IDEMPOTENT mode, replication will not stop for operations that are idempotent. In STRICT mode, replication will stop on any unexpected difference between the master and the slave.", - (uchar**) &slave_exec_mode_str, (uchar**) &slave_exec_mode_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, -#endif - {"slow-query-log", OPT_SLOW_LOG, - "Enable|disable slow query log", (uchar**) &opt_slow_log, - (uchar**) &opt_slow_log, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"socket", OPT_SOCKET, "Socket file to use for connection.", - (uchar**) &mysqld_unix_port, (uchar**) &mysqld_unix_port, 0, GET_STR, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + "Don't give threads different priorities. This option is deprecated " + "because it has no effect; the implied behavior is already the default.", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #ifdef HAVE_REPLICATION - {"sporadic-binlog-dump-fail", OPT_SPORADIC_BINLOG_DUMP_FAIL, + {"sporadic-binlog-dump-fail", 0, "Option used by mysql-test for debugging and testing of replication.", (uchar**) &opt_sporadic_binlog_dump_fail, (uchar**) &opt_sporadic_binlog_dump_fail, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif /* HAVE_REPLICATION */ - {"sql-bin-update-same", OPT_SQL_BIN_UPDATE_SAME, - "The update log is deprecated since version 5.0, is replaced by the binary \ -log and this option does nothing anymore.", + {"sql-bin-update-same", 0, + "The update log is deprecated since version 5.0, is replaced by the " + "binary log and this option does nothing anymore.", 0, 0, 0, GET_DISABLED, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"sql-mode", OPT_SQL_MODE, - "Syntax: sql-mode=option[,option[,option...]] where option can be one of: REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, ONLY_FULL_GROUP_BY, NO_UNSIGNED_SUBTRACTION.", - (uchar**) &sql_mode_str, (uchar**) &sql_mode_str, 0, GET_STR, REQUIRED_ARG, 0, - 0, 0, 0, 0, 0}, #ifdef HAVE_OPENSSL -#include "sslopt-longopts.h" + {"ssl", 0, + "Enable SSL for connection (automatically enabled with other flags).", + (uchar **) &opt_use_ssl, (uchar **) &opt_use_ssl, 0, GET_BOOL, OPT_ARG, 0, 0, 0, + 0, 0, 0}, #endif #ifdef __WIN__ - {"standalone", OPT_STANDALONE, + {"standalone", 0, "Dummy option to start as a standalone program (NT).", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif @@ -6540,14 +6242,14 @@ log and this option does nothing anymore.", option if compiled with valgrind support. */ IF_PURIFY(0,1), 0, 0, 0, 0, 0}, - {"sysdate-is-now", OPT_SYSDATE_IS_NOW, + {"sysdate-is-now", 0, "Non-default option to alias SYSDATE() to NOW() to make it safe-replicable. Since 5.0, SYSDATE() returns a `dynamic' value different for different invocations, even within the same statement.", (uchar**) &global_system_variables.sysdate_is_now, 0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0}, - {"tc-heuristic-recover", OPT_TC_HEURISTIC_RECOVER, + {"tc-heuristic-recover", 0, "Decision to use in heuristic recover process. Possible values are COMMIT or ROLLBACK.", - (uchar**) &opt_tc_heuristic_recover, (uchar**) &opt_tc_heuristic_recover, - 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + (uchar**) &tc_heuristic_recover, (uchar**) &tc_heuristic_recover, + &tc_heuristic_recover_typelib, GET_ENUM, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #if defined(ENABLED_DEBUG_SYNC) {"debug-sync-timeout", OPT_DEBUG_SYNC_TIMEOUT, "Enable the debug sync facility " @@ -6556,7 +6258,7 @@ log and this option does nothing anymore.", (uchar**) &opt_debug_sync_timeout, 0, 0, GET_UINT, OPT_ARG, 0, 0, UINT_MAX, 0, 0, 0}, #endif /* defined(ENABLED_DEBUG_SYNC) */ - {"temp-pool", OPT_TEMP_POOL, + {"temp-pool", 0, #if (ENABLE_TEMP_POOL) "Using this option will cause most temporary files created to use a small set of names, rather than a unique name for each new file.", #else @@ -6564,25 +6266,12 @@ log and this option does nothing anymore.", #endif (uchar**) &use_temp_pool, (uchar**) &use_temp_pool, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0}, - - {"timed_mutexes", OPT_TIMED_MUTEXES, - "Specify whether to time mutexes (only InnoDB mutexes are currently supported)", - (uchar**) &timed_mutexes, (uchar**) &timed_mutexes, 0, GET_BOOL, NO_ARG, 0, - 0, 0, 0, 0, 0}, - {"tmpdir", 't', - "Path for temporary files. Several paths may be specified, separated by a " -#if defined(__WIN__) || defined(__NETWARE__) - "semicolon (;)" -#else - "colon (:)" -#endif - ", in this case they are used in a round-robin fashion.", - (uchar**) &opt_mysql_tmpdir, - (uchar**) &opt_mysql_tmpdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"transaction-isolation", OPT_TX_ISOLATION, - "Default transaction isolation level.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, - 0, 0, 0, 0, 0}, - {"use-symbolic-links", OPT_SYMBOLIC_LINKS, "Enable symbolic link support. Deprecated option; use --symbolic-links instead.", + {"transaction-isolation", 0, + "Default transaction isolation level.", + (uchar**)&global_system_variables.tx_isolation, + (uchar**)&global_system_variables.tx_isolation, &tx_isolation_typelib, + GET_ENUM, REQUIRED_ARG, ISO_REPEATABLE_READ, 0, 0, 0, 0, 0}, + {"use-symbolic-links", 's', "Enable symbolic link support. Deprecated option; use --symbolic-links instead.", (uchar**) &my_use_symdir, (uchar**) &my_use_symdir, 0, GET_BOOL, NO_ARG, IF_PURIFY(0,1), 0, 0, 0, 0, 0}, {"user", 'u', "Run mysqld daemon as user.", 0, 0, 0, GET_STR, REQUIRED_ARG, @@ -6592,565 +6281,23 @@ log and this option does nothing anymore.", 0, 0}, {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"warnings", OPT_WARNINGS, "Deprecated; use --log-warnings instead.", + {"warnings", 'W', "Deprecated; use --log-warnings instead.", (uchar**) &global_system_variables.log_warnings, (uchar**) &max_system_variables.log_warnings, 0, GET_ULONG, OPT_ARG, 1, 0, ULONG_MAX, 0, 0, 0}, - { "back_log", OPT_BACK_LOG, - "The number of outstanding connection requests MySQL can have. This comes into play when the main MySQL thread gets very many connection requests in a very short time.", - (uchar**) &back_log, (uchar**) &back_log, 0, GET_ULONG, - REQUIRED_ARG, 50, 1, 65535, 0, 1, 0 }, - {"binlog_cache_size", OPT_BINLOG_CACHE_SIZE, - "The size of the cache to hold the SQL statements for the binary log during a transaction. If you often use big, multi-statement transactions you can increase this to get more performance.", - (uchar**) &binlog_cache_size, (uchar**) &binlog_cache_size, 0, GET_ULONG, - REQUIRED_ARG, 32*1024L, IO_SIZE, ULONG_MAX, 0, IO_SIZE, 0}, - {"bulk_insert_buffer_size", OPT_BULK_INSERT_BUFFER_SIZE, - "Size of tree cache used in bulk insert optimisation. Note that this is a limit per thread!", - (uchar**) &global_system_variables.bulk_insert_buff_size, - (uchar**) &max_system_variables.bulk_insert_buff_size, - 0, GET_ULONG, REQUIRED_ARG, 8192*1024, 0, ULONG_MAX, 0, 1, 0}, - {"connect_timeout", OPT_CONNECT_TIMEOUT, - "The number of seconds the mysqld server is waiting for a connect packet before responding with 'Bad handshake'.", - (uchar**) &connect_timeout, (uchar**) &connect_timeout, - 0, GET_ULONG, REQUIRED_ARG, CONNECT_TIMEOUT, 2, LONG_TIMEOUT, 0, 1, 0 }, - { "date_format", OPT_DATE_FORMAT, - "The DATE format (For future).", - (uchar**) &opt_date_time_formats[MYSQL_TIMESTAMP_DATE], - (uchar**) &opt_date_time_formats[MYSQL_TIMESTAMP_DATE], - 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - { "datetime_format", OPT_DATETIME_FORMAT, - "The DATETIME/TIMESTAMP format (for future).", - (uchar**) &opt_date_time_formats[MYSQL_TIMESTAMP_DATETIME], - (uchar**) &opt_date_time_formats[MYSQL_TIMESTAMP_DATETIME], - 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - { "default_week_format", OPT_DEFAULT_WEEK_FORMAT, - "The default week format used by WEEK() functions.", - (uchar**) &global_system_variables.default_week_format, - (uchar**) &max_system_variables.default_week_format, - 0, GET_ULONG, REQUIRED_ARG, 0, 0, 7L, 0, 1, 0}, - {"delayed_insert_limit", OPT_DELAYED_INSERT_LIMIT, - "After inserting delayed_insert_limit rows, the INSERT DELAYED handler will check if there are any SELECT statements pending. If so, it allows these to execute before continuing.", - (uchar**) &delayed_insert_limit, (uchar**) &delayed_insert_limit, 0, GET_ULONG, - REQUIRED_ARG, DELAYED_LIMIT, 1, ULONG_MAX, 0, 1, 0}, - {"delayed_insert_timeout", OPT_DELAYED_INSERT_TIMEOUT, - "How long a INSERT DELAYED thread should wait for INSERT statements before terminating.", - (uchar**) &delayed_insert_timeout, (uchar**) &delayed_insert_timeout, 0, - GET_ULONG, REQUIRED_ARG, DELAYED_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, - { "delayed_queue_size", OPT_DELAYED_QUEUE_SIZE, - "What size queue (in rows) should be allocated for handling INSERT DELAYED. If the queue becomes full, any client that does INSERT DELAYED will wait until there is room in the queue again.", - (uchar**) &delayed_queue_size, (uchar**) &delayed_queue_size, 0, GET_ULONG, - REQUIRED_ARG, DELAYED_QUEUE_SIZE, 1, ULONG_MAX, 0, 1, 0}, - {"div_precision_increment", OPT_DIV_PRECINCREMENT, - "Precision of the result of '/' operator will be increased on that value.", - (uchar**) &global_system_variables.div_precincrement, - (uchar**) &max_system_variables.div_precincrement, 0, GET_ULONG, - REQUIRED_ARG, 4, 0, DECIMAL_MAX_SCALE, 0, 0, 0}, - {"expire_logs_days", OPT_EXPIRE_LOGS_DAYS, - "If non-zero, binary logs will be purged after expire_logs_days " - "days; possible purges happen at startup and at binary log rotation.", - (uchar**) &expire_logs_days, - (uchar**) &expire_logs_days, 0, GET_ULONG, - REQUIRED_ARG, 0, 0, 99, 0, 1, 0}, - { "flush_time", OPT_FLUSH_TIME, - "A dedicated thread is created to flush all tables at the given interval.", - (uchar**) &flush_time, (uchar**) &flush_time, 0, GET_ULONG, REQUIRED_ARG, - FLUSH_TIME, 0, LONG_TIMEOUT, 0, 1, 0}, - { "ft_boolean_syntax", OPT_FT_BOOLEAN_SYNTAX, - "List of operators for MATCH ... AGAINST ( ... IN BOOLEAN MODE)", - 0, 0, 0, GET_STR, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - { "ft_max_word_len", OPT_FT_MAX_WORD_LEN, - "The maximum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable.", - (uchar**) &ft_max_word_len, (uchar**) &ft_max_word_len, 0, GET_ULONG, - REQUIRED_ARG, HA_FT_MAXCHARLEN, 10, HA_FT_MAXCHARLEN, 0, 1, 0}, - { "ft_min_word_len", OPT_FT_MIN_WORD_LEN, - "The minimum length of the word to be included in a FULLTEXT index. Note: FULLTEXT indexes must be rebuilt after changing this variable.", - (uchar**) &ft_min_word_len, (uchar**) &ft_min_word_len, 0, GET_ULONG, - REQUIRED_ARG, 4, 1, HA_FT_MAXCHARLEN, 0, 1, 0}, - { "ft_query_expansion_limit", OPT_FT_QUERY_EXPANSION_LIMIT, - "Number of best matches to use for query expansion", - (uchar**) &ft_query_expansion_limit, (uchar**) &ft_query_expansion_limit, 0, GET_ULONG, - REQUIRED_ARG, 20, 0, 1000, 0, 1, 0}, - { "ft_stopword_file", OPT_FT_STOPWORD_FILE, - "Use stopwords from this file instead of built-in list.", - (uchar**) &ft_stopword_file, (uchar**) &ft_stopword_file, 0, GET_STR, - REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - { "group_concat_max_len", OPT_GROUP_CONCAT_MAX_LEN, - "The maximum length of the result of function group_concat.", - (uchar**) &global_system_variables.group_concat_max_len, - (uchar**) &max_system_variables.group_concat_max_len, 0, GET_ULONG, - REQUIRED_ARG, 1024, 4, ULONG_MAX, 0, 1, 0}, - {"interactive_timeout", OPT_INTERACTIVE_TIMEOUT, - "The number of seconds the server waits for activity on an interactive connection before closing it.", - (uchar**) &global_system_variables.net_interactive_timeout, - (uchar**) &max_system_variables.net_interactive_timeout, 0, - GET_ULONG, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, - {"join_buffer_size", OPT_JOIN_BUFF_SIZE, - "The size of the buffer that is used for full joins.", - (uchar**) &global_system_variables.join_buff_size, - (uchar**) &max_system_variables.join_buff_size, 0, GET_ULONG, - REQUIRED_ARG, 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ULONG_MAX, - MALLOC_OVERHEAD, IO_SIZE, 0}, - {"keep_files_on_create", OPT_KEEP_FILES_ON_CREATE, - "Don't overwrite stale .MYD and .MYI even if no directory is specified.", - (uchar**) &global_system_variables.keep_files_on_create, - (uchar**) &max_system_variables.keep_files_on_create, - 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"key_buffer_size", OPT_KEY_BUFFER_SIZE, - "The size of the buffer used for index blocks for MyISAM tables. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common.", - (uchar**) &dflt_key_cache_var.param_buff_size, - (uchar**) 0, - 0, (GET_ULL | GET_ASK_ADDR), - REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, SIZE_T_MAX, MALLOC_OVERHEAD, - IO_SIZE, 0}, - {"key_cache_age_threshold", OPT_KEY_CACHE_AGE_THRESHOLD, - "This characterizes the number of hits a hot block has to be untouched until it is considered aged enough to be downgraded to a warm block. This specifies the percentage ratio of that number of hits to the total number of blocks in key cache", - (uchar**) &dflt_key_cache_var.param_age_threshold, - (uchar**) 0, - 0, (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG, - 300, 100, ULONG_MAX, 0, 100, 0}, - {"key_cache_block_size", OPT_KEY_CACHE_BLOCK_SIZE, - "The default size of key cache blocks", - (uchar**) &dflt_key_cache_var.param_block_size, - (uchar**) 0, - 0, (GET_ULONG | GET_ASK_ADDR), REQUIRED_ARG, - KEY_CACHE_BLOCK_SIZE, 512, 1024 * 16, 0, 512, 0}, - {"key_cache_division_limit", OPT_KEY_CACHE_DIVISION_LIMIT, - "The minimum percentage of warm blocks in key cache", - (uchar**) &dflt_key_cache_var.param_division_limit, - (uchar**) 0, - 0, (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100, - 1, 100, 0, 1, 0}, - {"long_query_time", OPT_LONG_QUERY_TIME, - "Log all queries that have taken more than long_query_time seconds to execute to file. " - "The argument will be treated as a decimal value with microsecond precission.", - (uchar**) &long_query_time, (uchar**) &long_query_time, 0, GET_DOUBLE, - REQUIRED_ARG, 10, 0, LONG_TIMEOUT, 0, 0, 0}, - {"lower_case_table_names", OPT_LOWER_CASE_TABLE_NAMES, - "If set to 1 table names are stored in lowercase on disk and table names will be case-insensitive. Should be set to 2 if you are using a case insensitive file system", - (uchar**) &lower_case_table_names, - (uchar**) &lower_case_table_names, 0, GET_UINT, OPT_ARG, -#ifdef FN_NO_CASE_SENCE - 1 -#else - 0 -#endif - , 0, 2, 0, 1, 0}, - {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, - "Max packetlength to send/receive from to server.", - (uchar**) &global_system_variables.max_allowed_packet, - (uchar**) &max_system_variables.max_allowed_packet, 0, GET_ULONG, - REQUIRED_ARG, 1024*1024L, 1024, 1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0}, - {"max_binlog_cache_size", OPT_MAX_BINLOG_CACHE_SIZE, - "Can be used to restrict the total size used to cache a multi-transaction query.", - (uchar**) &max_binlog_cache_size, (uchar**) &max_binlog_cache_size, 0, - GET_ULL, REQUIRED_ARG, ULONG_MAX, IO_SIZE, ULONGLONG_MAX, 0, IO_SIZE, 0}, - {"max_binlog_size", OPT_MAX_BINLOG_SIZE, - "Binary log will be rotated automatically when the size exceeds this \ -value. Will also apply to relay logs if max_relay_log_size is 0. \ -The minimum value for this variable is 4096.", - (uchar**) &max_binlog_size, (uchar**) &max_binlog_size, 0, GET_ULONG, - REQUIRED_ARG, 1024*1024L*1024L, IO_SIZE, 1024*1024L*1024L, 0, IO_SIZE, 0}, - {"max_connect_errors", OPT_MAX_CONNECT_ERRORS, - "If there is more than this number of interrupted connections from a host this host will be blocked from further connections.", - (uchar**) &max_connect_errors, (uchar**) &max_connect_errors, 0, GET_ULONG, - REQUIRED_ARG, MAX_CONNECT_ERRORS, 1, ULONG_MAX, 0, 1, 0}, - // Default max_connections of 151 is larger than Apache's default max - // children, to avoid "too many connections" error in a common setup - {"max_connections", OPT_MAX_CONNECTIONS, - "The number of simultaneous clients allowed.", (uchar**) &max_connections, - (uchar**) &max_connections, 0, GET_ULONG, REQUIRED_ARG, 151, 1, 100000, 0, 1, - 0}, - {"max_delayed_threads", OPT_MAX_DELAYED_THREADS, - "Don't start more than this number of threads to handle INSERT DELAYED statements. If set to zero, which means INSERT DELAYED is not used.", - (uchar**) &global_system_variables.max_insert_delayed_threads, - (uchar**) &max_system_variables.max_insert_delayed_threads, - 0, GET_ULONG, REQUIRED_ARG, 20, 0, 16384, 0, 1, 0}, - {"max_error_count", OPT_MAX_ERROR_COUNT, - "Max number of errors/warnings to store for a statement.", - (uchar**) &global_system_variables.max_error_count, - (uchar**) &max_system_variables.max_error_count, - 0, GET_ULONG, REQUIRED_ARG, DEFAULT_ERROR_COUNT, 0, 65535, 0, 1, 0}, - {"max_heap_table_size", OPT_MAX_HEP_TABLE_SIZE, - "Don't allow creation of heap tables bigger than this.", - (uchar**) &global_system_variables.max_heap_table_size, - (uchar**) &max_system_variables.max_heap_table_size, 0, GET_ULL, - REQUIRED_ARG, 16*1024*1024L, 16384, MAX_MEM_TABLE_SIZE, - MALLOC_OVERHEAD, 1024, 0}, - {"max_join_size", OPT_MAX_JOIN_SIZE, - "Joins that are probably going to read more than max_join_size records return an error.", - (uchar**) &global_system_variables.max_join_size, - (uchar**) &max_system_variables.max_join_size, 0, GET_HA_ROWS, REQUIRED_ARG, - HA_POS_ERROR, 1, HA_POS_ERROR, 0, 1, 0}, - {"max_length_for_sort_data", OPT_MAX_LENGTH_FOR_SORT_DATA, - "Max number of bytes in sorted records.", - (uchar**) &global_system_variables.max_length_for_sort_data, - (uchar**) &max_system_variables.max_length_for_sort_data, 0, GET_ULONG, - REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0}, - {"max_prepared_stmt_count", OPT_MAX_PREPARED_STMT_COUNT, - "Maximum number of prepared statements in the server.", - (uchar**) &max_prepared_stmt_count, (uchar**) &max_prepared_stmt_count, - 0, GET_ULONG, REQUIRED_ARG, 16382, 0, 1*1024*1024, 0, 1, 0}, - {"max_relay_log_size", OPT_MAX_RELAY_LOG_SIZE, - "If non-zero: relay log will be rotated automatically when the size exceeds this value; if zero (the default): when the size exceeds max_binlog_size. 0 excepted, the minimum value for this variable is 4096.", - (uchar**) &max_relay_log_size, (uchar**) &max_relay_log_size, 0, GET_ULONG, - REQUIRED_ARG, 0L, 0L, 1024*1024L*1024L, 0, IO_SIZE, 0}, - { "max_seeks_for_key", OPT_MAX_SEEKS_FOR_KEY, - "Limit assumed max number of seeks when looking up rows based on a key", - (uchar**) &global_system_variables.max_seeks_for_key, - (uchar**) &max_system_variables.max_seeks_for_key, 0, GET_ULONG, - REQUIRED_ARG, ULONG_MAX, 1, ULONG_MAX, 0, 1, 0 }, - {"max_sort_length", OPT_MAX_SORT_LENGTH, - "The number of bytes to use when sorting BLOB or TEXT values (only the first max_sort_length bytes of each value are used; the rest are ignored).", - (uchar**) &global_system_variables.max_sort_length, - (uchar**) &max_system_variables.max_sort_length, 0, GET_ULONG, - REQUIRED_ARG, 1024, 4, 8192*1024L, 0, 1, 0}, - {"max_sp_recursion_depth", OPT_MAX_SP_RECURSION_DEPTH, - "Maximum stored procedure recursion depth. (discussed with docs).", - (uchar**) &global_system_variables.max_sp_recursion_depth, - (uchar**) &max_system_variables.max_sp_recursion_depth, 0, GET_ULONG, - OPT_ARG, 0, 0, 255, 0, 1, 0 }, - {"max_tmp_tables", OPT_MAX_TMP_TABLES, - "Maximum number of temporary tables a client can keep open at a time.", - (uchar**) &global_system_variables.max_tmp_tables, - (uchar**) &max_system_variables.max_tmp_tables, 0, GET_ULONG, - REQUIRED_ARG, 32, 1, ULONG_MAX, 0, 1, 0}, - {"max_user_connections", OPT_MAX_USER_CONNECTIONS, - "The maximum number of active connections for a single user (0 = no limit).", - (uchar**) &max_user_connections, (uchar**) &max_user_connections, 0, GET_UINT, - REQUIRED_ARG, 0, 0, UINT_MAX, 0, 1, 0}, - {"max_write_lock_count", OPT_MAX_WRITE_LOCK_COUNT, - "After this many write locks, allow some read locks to run in between.", - (uchar**) &max_write_lock_count, (uchar**) &max_write_lock_count, 0, GET_ULONG, - REQUIRED_ARG, ULONG_MAX, 1, ULONG_MAX, 0, 1, 0}, - {"min_examined_row_limit", OPT_MIN_EXAMINED_ROW_LIMIT, - "Don't write queries to slow log that examine fewer than min_examined_row_limit rows.", - (uchar**) &global_system_variables.min_examined_row_limit, - (uchar**) &max_system_variables.min_examined_row_limit, 0, GET_ULONG, - REQUIRED_ARG, 0, 0, ULONG_MAX, 0, 1L, 0}, - {"multi_range_count", OPT_MULTI_RANGE_COUNT, - "Number of key ranges to request at once.", - (uchar**) &global_system_variables.multi_range_count, - (uchar**) &max_system_variables.multi_range_count, 0, - GET_ULONG, REQUIRED_ARG, 256, 1, ULONG_MAX, 0, 1, 0}, - {"myisam_block_size", OPT_MYISAM_BLOCK_SIZE, - "Block size to be used for MyISAM index pages.", - (uchar**) &opt_myisam_block_size, - (uchar**) &opt_myisam_block_size, 0, GET_ULONG, REQUIRED_ARG, - MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, MI_MAX_KEY_BLOCK_LENGTH, - 0, MI_MIN_KEY_BLOCK_LENGTH, 0}, - {"myisam_data_pointer_size", OPT_MYISAM_DATA_POINTER_SIZE, - "Default pointer size to be used for MyISAM tables.", - (uchar**) &myisam_data_pointer_size, - (uchar**) &myisam_data_pointer_size, 0, GET_ULONG, REQUIRED_ARG, - 6, 2, 7, 0, 1, 0}, - {"myisam_max_extra_sort_file_size", OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE, - "This is a deprecated option that does nothing anymore. It will be removed in MySQL " - VER_CELOSIA, - (uchar**) &global_system_variables.myisam_max_extra_sort_file_size, - (uchar**) &max_system_variables.myisam_max_extra_sort_file_size, - 0, GET_ULL, REQUIRED_ARG, (ulonglong) MI_MAX_TEMP_LENGTH, - 0, (ulonglong) MAX_FILE_SIZE, 0, 1, 0}, - {"myisam_max_sort_file_size", OPT_MYISAM_MAX_SORT_FILE_SIZE, - "Don't use the fast sort index method to created index if the temporary file would get bigger than this.", - (uchar**) &global_system_variables.myisam_max_sort_file_size, - (uchar**) &max_system_variables.myisam_max_sort_file_size, 0, - GET_ULL, REQUIRED_ARG, (longlong) LONG_MAX, 0, (ulonglong) MAX_FILE_SIZE, - 0, 1024*1024, 0}, - {"myisam_mmap_size", OPT_MYISAM_MMAP_SIZE, - "Can be used to restrict the total memory used for memory mmaping of myisam files", - (uchar**) &myisam_mmap_size, (uchar**) &myisam_mmap_size, 0, - GET_ULL, REQUIRED_ARG, SIZE_T_MAX, MEMMAP_EXTRA_MARGIN, SIZE_T_MAX, 0, 1, 0}, - {"myisam_repair_threads", OPT_MYISAM_REPAIR_THREADS, - "Number of threads to use when repairing MyISAM tables. The value of 1 disables parallel repair.", - (uchar**) &global_system_variables.myisam_repair_threads, - (uchar**) &max_system_variables.myisam_repair_threads, 0, - GET_ULONG, REQUIRED_ARG, 1, 1, ULONG_MAX, 0, 1, 0}, - {"myisam_sort_buffer_size", OPT_MYISAM_SORT_BUFFER_SIZE, - "The buffer that is allocated when sorting the index when doing a REPAIR or when creating indexes with CREATE INDEX or ALTER TABLE.", - (uchar**) &global_system_variables.myisam_sort_buff_size, - (uchar**) &max_system_variables.myisam_sort_buff_size, 0, - GET_ULONG, REQUIRED_ARG, 8192*1024, 4, ~0L, 0, 1, 0}, - {"myisam_use_mmap", OPT_MYISAM_USE_MMAP, - "Use memory mapping for reading and writing MyISAM tables", - (uchar**) &opt_myisam_use_mmap, - (uchar**) &opt_myisam_use_mmap, 0, GET_BOOL, NO_ARG, 0, - 0, 0, 0, 0, 0}, - {"myisam_stats_method", OPT_MYISAM_STATS_METHOD, - "Specifies how MyISAM index statistics collection code should threat NULLs. " - "Possible values of name are \"nulls_unequal\" (default behavior for 4.1/5.0), " - "\"nulls_equal\" (emulate 4.0 behavior), and \"nulls_ignored\".", - (uchar**) &myisam_stats_method_str, (uchar**) &myisam_stats_method_str, 0, - GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"net_buffer_length", OPT_NET_BUFFER_LENGTH, - "Buffer length for TCP/IP and socket communication.", - (uchar**) &global_system_variables.net_buffer_length, - (uchar**) &max_system_variables.net_buffer_length, 0, GET_ULONG, - REQUIRED_ARG, 16384, 1024, 1024*1024L, 0, 1024, 0}, - {"net_read_timeout", OPT_NET_READ_TIMEOUT, - "Number of seconds to wait for more data from a connection before aborting the read.", - (uchar**) &global_system_variables.net_read_timeout, - (uchar**) &max_system_variables.net_read_timeout, 0, GET_ULONG, - REQUIRED_ARG, NET_READ_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, - {"net_retry_count", OPT_NET_RETRY_COUNT, - "If a read on a communication port is interrupted, retry this many times before giving up.", - (uchar**) &global_system_variables.net_retry_count, - (uchar**) &max_system_variables.net_retry_count,0, - GET_ULONG, REQUIRED_ARG, MYSQLD_NET_RETRY_COUNT, 1, ULONG_MAX, 0, 1, 0}, - {"net_write_timeout", OPT_NET_WRITE_TIMEOUT, - "Number of seconds to wait for a block to be written to a connection before aborting the write.", - (uchar**) &global_system_variables.net_write_timeout, - (uchar**) &max_system_variables.net_write_timeout, 0, GET_ULONG, - REQUIRED_ARG, NET_WRITE_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, - { "old", OPT_OLD_MODE, "Use compatible behavior.", - (uchar**) &global_system_variables.old_mode, - (uchar**) &max_system_variables.old_mode, 0, GET_BOOL, NO_ARG, - 0, 0, 0, 0, 0, 0}, - {"open_files_limit", OPT_OPEN_FILES_LIMIT, - "If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of files.", - (uchar**) &open_files_limit, (uchar**) &open_files_limit, 0, GET_ULONG, - REQUIRED_ARG, 0, 0, OS_FILE_LIMIT, 0, 1, 0}, - {"optimizer_prune_level", OPT_OPTIMIZER_PRUNE_LEVEL, - "Controls the heuristic(s) applied during query optimization to prune less-promising partial plans from the optimizer search space. Meaning: 0 - do not apply any heuristic, thus perform exhaustive search; 1 - prune plans based on number of retrieved rows.", - (uchar**) &global_system_variables.optimizer_prune_level, - (uchar**) &max_system_variables.optimizer_prune_level, - 0, GET_ULONG, OPT_ARG, 1, 0, 1, 0, 1, 0}, - {"optimizer_search_depth", OPT_OPTIMIZER_SEARCH_DEPTH, - "Maximum depth of search performed by the query optimizer. Values larger than the number of relations in a query result in better query plans, but take longer to compile a query. Smaller values than the number of tables in a relation result in faster optimization, but may produce very bad query plans. If set to 0, the system will automatically pick a reasonable value; if set to MAX_TABLES+2, the optimizer will switch to the original find_best (used for testing/comparison).", - (uchar**) &global_system_variables.optimizer_search_depth, - (uchar**) &max_system_variables.optimizer_search_depth, - 0, GET_ULONG, OPT_ARG, MAX_TABLES+1, 0, MAX_TABLES+2, 0, 1, 0}, - {"optimizer_switch", OPT_OPTIMIZER_SWITCH, - "optimizer_switch=option=val[,option=val...], where option={index_merge, " - "index_merge_union, index_merge_sort_union, index_merge_intersection} and " - "val={on, off, default}.", - (uchar**) &optimizer_switch_str, (uchar**) &optimizer_switch_str, 0, GET_STR, REQUIRED_ARG, - /*OPTIMIZER_SWITCH_DEFAULT*/0, - 0, 0, 0, 0, 0}, - {"plugin_dir", OPT_PLUGIN_DIR, - "Directory for plugins.", - (uchar**) &opt_plugin_dir_ptr, (uchar**) &opt_plugin_dir_ptr, 0, - GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"plugin-load", OPT_PLUGIN_LOAD, + {"plugin-load", 0, "Optional semicolon-separated list of plugins to load, where each plugin is " "identified as name=library, where name is the plugin name and library " "is the plugin library in plugin_dir.", (uchar**) &opt_plugin_load, (uchar**) &opt_plugin_load, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"preload_buffer_size", OPT_PRELOAD_BUFFER_SIZE, - "The size of the buffer that is allocated when preloading indexes", - (uchar**) &global_system_variables.preload_buff_size, - (uchar**) &max_system_variables.preload_buff_size, 0, GET_ULONG, - REQUIRED_ARG, 32*1024L, 1024, 1024*1024*1024L, 0, 1, 0}, - {"query_alloc_block_size", OPT_QUERY_ALLOC_BLOCK_SIZE, - "Allocation block size for query parsing and execution", - (uchar**) &global_system_variables.query_alloc_block_size, - (uchar**) &max_system_variables.query_alloc_block_size, 0, GET_ULONG, - REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ULONG_MAX, 0, 1024, 0}, -#ifdef HAVE_QUERY_CACHE - {"query_cache_limit", OPT_QUERY_CACHE_LIMIT, - "Don't cache results that are bigger than this.", - (uchar**) &query_cache_limit, (uchar**) &query_cache_limit, 0, GET_ULONG, - REQUIRED_ARG, 1024*1024L, 0, ULONG_MAX, 0, 1, 0}, - {"query_cache_min_res_unit", OPT_QUERY_CACHE_MIN_RES_UNIT, - "minimal size of unit in wich space for results is allocated (last unit will be trimed after writing all result data.", - (uchar**) &query_cache_min_res_unit, (uchar**) &query_cache_min_res_unit, - 0, GET_ULONG, REQUIRED_ARG, QUERY_CACHE_MIN_RESULT_DATA_SIZE, - 0, ULONG_MAX, 0, 1, 0}, -#endif /*HAVE_QUERY_CACHE*/ - {"query_cache_size", OPT_QUERY_CACHE_SIZE, - "The memory allocated to store results from old queries.", - (uchar**) &query_cache_size, (uchar**) &query_cache_size, 0, GET_ULONG, - REQUIRED_ARG, 0, 0, (longlong) ULONG_MAX, 0, 1024, 0}, -#ifdef HAVE_QUERY_CACHE - {"query_cache_type", OPT_QUERY_CACHE_TYPE, - "0 = OFF = Don't cache or retrieve results. 1 = ON = Cache all results except SELECT SQL_NO_CACHE ... queries. 2 = DEMAND = Cache only SELECT SQL_CACHE ... queries.", - (uchar**) &global_system_variables.query_cache_type, - (uchar**) &max_system_variables.query_cache_type, - 0, GET_ULONG, REQUIRED_ARG, 1, 0, 2, 0, 1, 0}, - {"query_cache_wlock_invalidate", OPT_QUERY_CACHE_WLOCK_INVALIDATE, - "Invalidate queries in query cache on LOCK for write", - (uchar**) &global_system_variables.query_cache_wlock_invalidate, - (uchar**) &max_system_variables.query_cache_wlock_invalidate, - 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0}, -#endif /*HAVE_QUERY_CACHE*/ - {"query_prealloc_size", OPT_QUERY_PREALLOC_SIZE, - "Persistent buffer for query parsing and execution", - (uchar**) &global_system_variables.query_prealloc_size, - (uchar**) &max_system_variables.query_prealloc_size, 0, GET_ULONG, - REQUIRED_ARG, QUERY_ALLOC_PREALLOC_SIZE, QUERY_ALLOC_PREALLOC_SIZE, - ULONG_MAX, 0, 1024, 0}, - {"range_alloc_block_size", OPT_RANGE_ALLOC_BLOCK_SIZE, - "Allocation block size for storing ranges during optimization", - (uchar**) &global_system_variables.range_alloc_block_size, - (uchar**) &max_system_variables.range_alloc_block_size, 0, GET_ULONG, - REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, RANGE_ALLOC_BLOCK_SIZE, ULONG_MAX, - 0, 1024, 0}, - {"read_buffer_size", OPT_RECORD_BUFFER, - "Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value.", - (uchar**) &global_system_variables.read_buff_size, - (uchar**) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG, - 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, INT_MAX32, MALLOC_OVERHEAD, IO_SIZE, - 0}, - {"read_only", OPT_READONLY, - "Make all non-temporary tables read-only, with the exception for replication (slave) threads and users with the SUPER privilege", - (uchar**) &opt_readonly, - (uchar**) &opt_readonly, - 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0}, - {"read_rnd_buffer_size", OPT_RECORD_RND_BUFFER, - "When reading rows in sorted order after a sort, the rows are read through this buffer to avoid a disk seeks. If not set, then it's set to the value of record_buffer.", - (uchar**) &global_system_variables.read_rnd_buff_size, - (uchar**) &max_system_variables.read_rnd_buff_size, 0, - GET_ULONG, REQUIRED_ARG, 256*1024L, IO_SIZE*2+MALLOC_OVERHEAD, - INT_MAX32, MALLOC_OVERHEAD, IO_SIZE, 0}, - {"record_buffer", OPT_RECORD_BUFFER_OLD, - "Alias for read_buffer_size. This variable is deprecated and will be removed in a future release.", + {"record_buffer", 0, "Deprecated; use --read-buffer-size instead.", (uchar**) &global_system_variables.read_buff_size, (uchar**) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG, - 128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, INT_MAX32, MALLOC_OVERHEAD, IO_SIZE, 0}, -#ifdef HAVE_REPLICATION - {"relay_log_purge", OPT_RELAY_LOG_PURGE, - "0 = do not purge relay logs. 1 = purge them as soon as they are no more needed.", - (uchar**) &relay_log_purge, - (uchar**) &relay_log_purge, 0, GET_BOOL, NO_ARG, - 1, 0, 1, 0, 1, 0}, - {"relay_log_recovery", OPT_RELAY_LOG_RECOVERY, - "Enables automatic relay log recovery right after the database startup, " - "which means that the IO Thread starts re-fetching from the master " - "right after the last transaction processed.", - (uchar**) &relay_log_recovery, - (uchar**) &relay_log_recovery, 0, GET_BOOL, NO_ARG, - 0, 0, 1, 0, 1, 0}, - {"relay_log_space_limit", OPT_RELAY_LOG_SPACE_LIMIT, - "Maximum space to use for all relay logs.", - (uchar**) &relay_log_space_limit, - (uchar**) &relay_log_space_limit, 0, GET_ULL, REQUIRED_ARG, 0L, 0L, - (longlong) ULONG_MAX, 0, 1, 0}, - {"slave_compressed_protocol", OPT_SLAVE_COMPRESSED_PROTOCOL, - "Use compression on master/slave protocol.", - (uchar**) &opt_slave_compressed_protocol, - (uchar**) &opt_slave_compressed_protocol, - 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0}, - {"slave_net_timeout", OPT_SLAVE_NET_TIMEOUT, - "Number of seconds to wait for more data from a master/slave connection before aborting the read.", - (uchar**) &slave_net_timeout, (uchar**) &slave_net_timeout, 0, - GET_ULONG, REQUIRED_ARG, SLAVE_NET_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, - {"slave_transaction_retries", OPT_SLAVE_TRANS_RETRIES, - "Number of times the slave SQL thread will retry a transaction in case " - "it failed with a deadlock or elapsed lock wait timeout, " - "before giving up and stopping.", - (uchar**) &slave_trans_retries, (uchar**) &slave_trans_retries, 0, - GET_ULONG, REQUIRED_ARG, 10L, 0L, (longlong) ULONG_MAX, 0, 1, 0}, -#endif /* HAVE_REPLICATION */ - {"slow_launch_time", OPT_SLOW_LAUNCH_TIME, - "If creating the thread takes longer than this value (in seconds), the Slow_launch_threads counter will be incremented.", - (uchar**) &slow_launch_time, (uchar**) &slow_launch_time, 0, GET_ULONG, - REQUIRED_ARG, 2L, 0L, LONG_TIMEOUT, 0, 1, 0}, - {"sort_buffer_size", OPT_SORT_BUFFER, - "Each thread that needs to do a sort allocates a buffer of this size.", - (uchar**) &global_system_variables.sortbuff_size, - (uchar**) &max_system_variables.sortbuff_size, 0, GET_ULONG, REQUIRED_ARG, - MAX_SORT_MEMORY, MIN_SORT_MEMORY+MALLOC_OVERHEAD*2, ~0L, MALLOC_OVERHEAD, - 1, 0}, - {"sync-binlog", OPT_SYNC_BINLOG, - "Synchronously flush binary log to disk after every #th event. " - "Use 0 (default) to disable synchronous flushing.", - (uchar**) &sync_binlog_period, (uchar**) &sync_binlog_period, 0, GET_UINT, - REQUIRED_ARG, 0, 0, (longlong) UINT_MAX, 0, 1, 0}, - {"sync-relay-log", OPT_SYNC_RELAY_LOG, - "Synchronously flush relay log to disk after every #th event. " - "Use 0 (default) to disable synchronous flushing.", - (uchar**) &sync_relaylog_period, (uchar**) &sync_relaylog_period, 0, GET_UINT, - REQUIRED_ARG, 0, 0, (longlong) UINT_MAX, 0, 1, 0}, - {"sync-relay-log-info", OPT_SYNC_RELAY_LOG_INFO, - "Synchronously flush relay log info to disk after #th transaction. " - "Use 0 (default) to disable synchronous flushing.", - (uchar**) &sync_relayloginfo_period, (uchar**) &sync_relayloginfo_period, 0, GET_UINT, - REQUIRED_ARG, 0, 0, (longlong) UINT_MAX, 0, 1, 0}, - {"sync-master-info", OPT_SYNC_MASTER_INFO, - "Synchronously flush master info to disk after every #th event. " - "Use 0 (default) to disable synchronous flushing.", - (uchar**) &sync_masterinfo_period, (uchar**) &sync_masterinfo_period, 0, GET_UINT, - REQUIRED_ARG, 0, 0, (longlong) UINT_MAX, 0, 1, 0}, - {"sync-frm", OPT_SYNC_FRM, "Sync .frm to disk on create. Enabled by default.", - (uchar**) &opt_sync_frm, (uchar**) &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0, - 0, 0, 0, 0}, - {"table_cache", OPT_TABLE_OPEN_CACHE, - "Deprecated; use --table_open_cache instead.", - (uchar**) &table_cache_size, (uchar**) &table_cache_size, 0, GET_ULONG, - REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0}, - {"table_definition_cache", OPT_TABLE_DEF_CACHE, - "The number of cached table definitions.", - (uchar**) &table_def_size, (uchar**) &table_def_size, - 0, GET_ULONG, REQUIRED_ARG, TABLE_DEF_CACHE_DEFAULT, TABLE_DEF_CACHE_MIN, - 512*1024L, 0, 1, 0}, - {"table_open_cache", OPT_TABLE_OPEN_CACHE, - "The number of cached open tables.", + 128*1024L, IO_SIZE*2, INT_MAX32, 0, IO_SIZE, 0}, + {"table_cache", 0, "Deprecated; use --table-open-cache instead.", (uchar**) &table_cache_size, (uchar**) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0}, - {"table_lock_wait_timeout", OPT_TABLE_LOCK_WAIT_TIMEOUT, - "Timeout in seconds to wait for a table level lock before returning an " - "error. Used only if the connection has active cursors.", - (uchar**) &table_lock_wait_timeout, (uchar**) &table_lock_wait_timeout, - 0, GET_ULONG, REQUIRED_ARG, 50, 1, 1024 * 1024 * 1024, 0, 1, 0}, - {"thread_cache_size", OPT_THREAD_CACHE_SIZE, - "How many threads we should keep in a cache for reuse.", - (uchar**) &thread_cache_size, (uchar**) &thread_cache_size, 0, GET_ULONG, - REQUIRED_ARG, 0, 0, 16384, 0, 1, 0}, - {"thread_concurrency", OPT_THREAD_CONCURRENCY, - "Permits the application to give the threads system a hint for the desired number of threads that should be run at the same time.", - (uchar**) &concurrency, (uchar**) &concurrency, 0, GET_ULONG, REQUIRED_ARG, - DEFAULT_CONCURRENCY, 1, 512, 0, 1, 0}, -#if HAVE_POOL_OF_THREADS == 1 - {"thread_pool_size", OPT_THREAD_CACHE_SIZE, - "How many threads we should create to handle query requests in case of 'thread_handling=pool-of-threads'", - (uchar**) &thread_pool_size, (uchar**) &thread_pool_size, 0, GET_ULONG, - REQUIRED_ARG, 20, 1, 16384, 0, 1, 0}, -#endif - {"thread_stack", OPT_THREAD_STACK, - "The stack size for each thread.", (uchar**) &my_thread_stack_size, - (uchar**) &my_thread_stack_size, 0, GET_ULONG, REQUIRED_ARG,DEFAULT_THREAD_STACK, - 1024L*128L, ULONG_MAX, 0, 1024, 0}, - { "time_format", OPT_TIME_FORMAT, - "The TIME format (for future).", - (uchar**) &opt_date_time_formats[MYSQL_TIMESTAMP_TIME], - (uchar**) &opt_date_time_formats[MYSQL_TIMESTAMP_TIME], - 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"tmp_table_size", OPT_TMP_TABLE_SIZE, - "If an internal in-memory temporary table exceeds this size, MySQL will" - " automatically convert it to an on-disk MyISAM table.", - (uchar**) &global_system_variables.tmp_table_size, - (uchar**) &max_system_variables.tmp_table_size, 0, GET_ULL, - REQUIRED_ARG, 16*1024*1024L, 1024, MAX_MEM_TABLE_SIZE, 0, 1, 0}, - {"transaction_alloc_block_size", OPT_TRANS_ALLOC_BLOCK_SIZE, - "Allocation block size for transactions to be stored in binary log", - (uchar**) &global_system_variables.trans_alloc_block_size, - (uchar**) &max_system_variables.trans_alloc_block_size, 0, GET_ULONG, - REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ULONG_MAX, 0, 1024, 0}, - {"transaction_prealloc_size", OPT_TRANS_PREALLOC_SIZE, - "Persistent buffer for transactions to be stored in binary log", - (uchar**) &global_system_variables.trans_prealloc_size, - (uchar**) &max_system_variables.trans_prealloc_size, 0, GET_ULONG, - REQUIRED_ARG, TRANS_ALLOC_PREALLOC_SIZE, 1024, ULONG_MAX, 0, 1024, 0}, - {"thread_handling", OPT_THREAD_HANDLING, - "Define threads usage for handling queries: " - "one-thread-per-connection or no-threads", 0, 0, - 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"updatable_views_with_limit", OPT_UPDATABLE_VIEWS_WITH_LIMIT, - "1 = YES = Don't issue an error message (warning only) if a VIEW without presence of a key of the underlying table is used in queries with a LIMIT clause for updating. 0 = NO = Prohibit update of a VIEW, which does not contain a key of the underlying table and the query uses a LIMIT clause (usually get from GUI tools).", - (uchar**) &global_system_variables.updatable_views_with_limit, - (uchar**) &max_system_variables.updatable_views_with_limit, - 0, GET_ULONG, REQUIRED_ARG, 1, 0, 1, 0, 1, 0}, - {"wait_timeout", OPT_WAIT_TIMEOUT, - "The number of seconds the server waits for activity on a connection before closing it.", - (uchar**) &global_system_variables.net_wait_timeout, - (uchar**) &max_system_variables.net_wait_timeout, 0, GET_ULONG, - REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT), - 0, 1, 0}, - {"binlog-direct-non-transactional-updates", OPT_BINLOG_DIRECT_NON_TRANS_UPDATE, - "Causes updates to non-transactional engines using statement format to be written directly to binary log. Before using this option make sure that there are no dependencies between transactional and non-transactional tables such as in the statement INSERT INTO t_myisam SELECT * FROM t_innodb; otherwise, slaves may diverge from the master.", - (uchar**) &global_system_variables.binlog_direct_non_trans_update, (uchar**) &max_system_variables.binlog_direct_non_trans_update, 0, GET_BOOL, NO_ARG, 0, - 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} }; @@ -7199,12 +6346,12 @@ static int show_rpl_status(THD *thd, SHOW_VAR *var, char *buff) static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff) { var->type= SHOW_MY_BOOL; - pthread_mutex_lock(&LOCK_active_mi); + mysql_mutex_lock(&LOCK_active_mi); var->value= buff; *((my_bool *)buff)= (my_bool) (active_mi && active_mi->slave_running == MYSQL_SLAVE_RUN_CONNECT && active_mi->rli.slave_running); - pthread_mutex_unlock(&LOCK_active_mi); + mysql_mutex_unlock(&LOCK_active_mi); return 0; } @@ -7214,41 +6361,41 @@ static int show_slave_retried_trans(THD *thd, SHOW_VAR *var, char *buff) TODO: with multimaster, have one such counter per line in SHOW SLAVE STATUS, and have the sum over all lines here. */ - pthread_mutex_lock(&LOCK_active_mi); + mysql_mutex_lock(&LOCK_active_mi); if (active_mi) { var->type= SHOW_LONG; var->value= buff; - pthread_mutex_lock(&active_mi->rli.data_lock); + mysql_mutex_lock(&active_mi->rli.data_lock); *((long *)buff)= (long)active_mi->rli.retried_trans; - pthread_mutex_unlock(&active_mi->rli.data_lock); + mysql_mutex_unlock(&active_mi->rli.data_lock); } else var->type= SHOW_UNDEF; - pthread_mutex_unlock(&LOCK_active_mi); + mysql_mutex_unlock(&LOCK_active_mi); return 0; } static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff) { - pthread_mutex_lock(&LOCK_active_mi); + mysql_mutex_lock(&LOCK_active_mi); if (active_mi) { var->type= SHOW_LONGLONG; var->value= buff; - pthread_mutex_lock(&active_mi->rli.data_lock); + mysql_mutex_lock(&active_mi->rli.data_lock); *((longlong *)buff)= active_mi->received_heartbeats; - pthread_mutex_unlock(&active_mi->rli.data_lock); + mysql_mutex_unlock(&active_mi->rli.data_lock); } else var->type= SHOW_UNDEF; - pthread_mutex_unlock(&LOCK_active_mi); + mysql_mutex_unlock(&LOCK_active_mi); return 0; } static int show_heartbeat_period(THD *thd, SHOW_VAR *var, char *buff) { - pthread_mutex_lock(&LOCK_active_mi); + mysql_mutex_lock(&LOCK_active_mi); if (active_mi) { var->type= SHOW_CHAR; @@ -7257,7 +6404,7 @@ static int show_heartbeat_period(THD *thd, SHOW_VAR *var, char *buff) } else var->type= SHOW_UNDEF; - pthread_mutex_unlock(&LOCK_active_mi); + mysql_mutex_unlock(&LOCK_active_mi); return 0; } @@ -7276,9 +6423,9 @@ static int show_prepared_stmt_count(THD *thd, SHOW_VAR *var, char *buff) { var->type= SHOW_LONG; var->value= buff; - pthread_mutex_lock(&LOCK_prepared_stmt_count); + mysql_mutex_lock(&LOCK_prepared_stmt_count); *((long *)buff)= (long)prepared_stmt_count; - pthread_mutex_unlock(&LOCK_prepared_stmt_count); + mysql_mutex_unlock(&LOCK_prepared_stmt_count); return 0; } @@ -7669,7 +6816,7 @@ SHOW_VAR status_vars[]= { {"Tc_log_page_waits", (char*) &tc_log_page_waits, SHOW_LONG}, #endif {"Threads_cached", (char*) &cached_thread_count, SHOW_LONG_NOFLUSH}, - {"Threads_connected", (char*) &thread_count, SHOW_INT}, + {"Threads_connected", (char*) &connection_count, SHOW_INT}, {"Threads_created", (char*) &thread_created, SHOW_LONG_NOFLUSH}, {"Threads_running", (char*) &thread_running, SHOW_INT}, {"Uptime", (char*) &show_starttime, SHOW_FUNC}, @@ -7679,6 +6826,12 @@ SHOW_VAR status_vars[]= { {NullS, NullS, SHOW_LONG} }; +bool add_terminator(DYNAMIC_ARRAY *options) +{ + my_option empty_element= {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}; + return insert_dynamic(options, (uchar *)&empty_element); +} + #ifndef EMBEDDED_LIBRARY static void print_version(void) { @@ -7688,8 +6841,53 @@ static void print_version(void) server_version,SYSTEM_TYPE,MACHINE_TYPE, MYSQL_COMPILATION_COMMENT); } +/** Compares two options' names, treats - and _ the same */ +static int option_cmp(my_option *a, my_option *b) +{ + const char *sa= a->name; + const char *sb= b->name; + for (; *sa || *sb; sa++, sb++) + { + if (*sa < *sb) + { + if (*sa == '-' && *sb == '_') + continue; + else + return -1; + } + if (*sa > *sb) + { + if (*sa == '_' && *sb == '-') + continue; + else + return 1; + } + } + DBUG_ASSERT(a->name == b->name); + return 0; +} + +static void print_help() +{ + MEM_ROOT mem_root; + init_alloc_root(&mem_root, 4096, 4096); + + pop_dynamic(&all_options); + sys_var_add_options(&all_options, sys_var::PARSE_EARLY); + add_plugin_options(&all_options, &mem_root); + sort_dynamic(&all_options, (qsort_cmp) option_cmp); + add_terminator(&all_options); + + my_print_help((my_option*) all_options.buffer); + my_print_variables((my_option*) all_options.buffer); + + free_root(&mem_root, MYF(0)); + delete_dynamic(&all_options); +} + static void usage(void) { + DBUG_ENTER("usage"); if (!(default_charset_info= get_charset_by_csname(default_character_set_name, MY_CS_PRIMARY, MYF(MY_WME)))) @@ -7699,7 +6897,7 @@ static void usage(void) print_version(); puts("\ Copyright (C) 2000-2008 MySQL AB, by Monty and others\n\ -Copyright (C) 2008 Sun Microsystems, Inc.\n\ +Copyright (C) 2008,2009 Sun Microsystems, Inc.\n\ This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\ and you are welcome to modify and redistribute it under the GPL license\n\n\ Starts the MySQL database server\n"); @@ -7727,7 +6925,7 @@ Starts the MySQL database server\n"); set_ports(); /* Print out all the options including plugin supplied options */ - my_print_help_inc_plugins(my_long_options, sizeof(my_long_options)/sizeof(my_option)); + print_help(); if (! plugins_are_initialized) { @@ -7740,15 +6938,12 @@ because execution stopped before plugins were initialized."); To see what values a running MySQL server is using, type\n\ 'mysqladmin variables' instead of 'mysqld --verbose --help'."); } + DBUG_VOID_RETURN; } #endif /*!EMBEDDED_LIBRARY*/ - /** - Initialize all MySQL global variables to default values. - - We don't need to set numeric variables refered to in my_long_options - as these are initialized by my_getopt. + Initialize MySQL global variables to default values. @note The reason to set a lot of global variables to zero is to allow one to @@ -7756,33 +6951,28 @@ To see what values a running MySQL server is using, type\n\ It's also needed on some exotic platforms where global variables are not set to 0 when a program starts. - We don't need to set numeric variables refered to in my_long_options + We don't need to set variables refered to in my_long_options as these are initialized by my_getopt. */ static int mysql_init_variables(void) { - int error; /* Things reset to zero */ opt_skip_slave_start= opt_reckless_slave = 0; mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0; myisam_test_invalid_symlink= test_if_data_home_dir; opt_log= opt_slow_log= 0; opt_update_log= 0; - log_output_options= find_bit_type(log_output_str, &log_output_typelib); opt_bin_log= 0; opt_disable_networking= opt_skip_show_db=0; opt_ignore_builtin_innodb= 0; opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname= 0; opt_tc_log_file= (char *)"tc.log"; // no hostname in tc_log file name ! opt_secure_auth= 0; - opt_secure_file_priv= 0; opt_bootstrap= opt_myisam_log= 0; mqh_used= 0; segfaulted= kill_in_progress= 0; cleanup_done= 0; - defaults_argc= 0; - defaults_argv= 0; server_id_supplied= 0; test_flags= select_errors= dropping_tables= ha_open_options=0; thread_count= thread_running= kill_cached_threads= wake_thread=0; @@ -7817,33 +7007,19 @@ static int mysql_init_variables(void) table_alias_charset= &my_charset_bin; character_set_filesystem= &my_charset_bin; - opt_date_time_formats[0]= opt_date_time_formats[1]= opt_date_time_formats[2]= 0; - - /* Things with default values that are not zero */ - delay_key_write_options= (uint) DELAY_KEY_WRITE_ON; - slave_exec_mode_options= 0; - slave_exec_mode_options= (uint) - find_bit_type_or_exit(slave_exec_mode_str, &slave_exec_mode_typelib, NULL, - &error); - if (error) - return 1; opt_specialflag= SPECIAL_ENGLISH; unix_sock= ip_sock= INVALID_SOCKET; mysql_home_ptr= mysql_home; pidfile_name_ptr= pidfile_name; log_error_file_ptr= log_error_file; lc_messages_dir_ptr= lc_messages_dir; - mysql_data_home= mysql_real_data_home; - thd_startup_options= (OPTION_AUTO_IS_NULL | OPTION_BIN_LOG | - OPTION_QUOTE_SHOW_CREATE | OPTION_SQL_NOTES); protocol_version= PROTOCOL_VERSION; what_to_log= ~ (1L << (uint) COM_TIME); refresh_version= 1L; /* Increments on each reload */ global_query_id= thread_id= 1L; + my_atomic_rwlock_init(&global_query_id_lock); + my_atomic_rwlock_init(&thread_running_lock); strmov(server_version, MYSQL_SERVER_VERSION); - myisam_recover_options_str= sql_mode_str= "OFF"; - myisam_stats_method_str= "nulls_unequal"; - my_bind_addr = htonl(INADDR_ANY); threads.empty(); thread_cache.empty(); key_caches.empty(); @@ -7857,19 +7033,12 @@ static int mysql_init_variables(void) multi_keycache_init(); /* Set directory paths */ - strmake(mysql_real_data_home, get_relative_path(MYSQL_DATADIR), - sizeof(mysql_real_data_home)-1); - mysql_data_home_buff[0]=FN_CURLIB; // all paths are relative from here - mysql_data_home_buff[1]=0; - mysql_data_home_len= 2; - + mysql_real_data_home_len= + strmake(mysql_real_data_home, get_relative_path(MYSQL_DATADIR), + sizeof(mysql_real_data_home)-1) - mysql_real_data_home; /* Replication parameters */ - master_user= (char*) "test"; - master_password= master_host= 0; master_info_file= (char*) "master.info", relay_log_info_file= (char*) "relay-log.info"; - master_ssl_key= master_ssl_cert= master_ssl_ca= - master_ssl_capath= master_ssl_cipher= 0; report_user= report_password = report_host= 0; /* TO BE DELETED */ opt_relay_logname= opt_relaylog_index_name= 0; @@ -7877,28 +7046,10 @@ static int mysql_init_variables(void) charsets_dir= 0; default_character_set_name= (char*) MYSQL_DEFAULT_CHARSET_NAME; default_collation_name= compiled_default_collation_name; - sys_charset_system.value= (char*) system_charset_info->csname; character_set_filesystem_name= (char*) "binary"; lc_messages= (char*) "en_US"; lc_time_names_name= (char*) "en_US"; - /* Set default values for some option variables */ - default_storage_engine_str= (char*) "MyISAM"; - global_system_variables.table_plugin= NULL; - global_system_variables.tx_isolation= ISO_REPEATABLE_READ; - global_system_variables.select_limit= (ulonglong) HA_POS_ERROR; - max_system_variables.select_limit= (ulonglong) HA_POS_ERROR; - global_system_variables.max_join_size= (ulonglong) HA_POS_ERROR; - max_system_variables.max_join_size= (ulonglong) HA_POS_ERROR; - global_system_variables.old_passwords= 0; - global_system_variables.old_alter_table= 0; - global_system_variables.binlog_format= BINLOG_FORMAT_UNSPEC; - /* - Default behavior for 4.1 and 5.0 is to treat NULL values as unequal - when collecting index statistics for MyISAM tables. - */ - global_system_variables.myisam_stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL; - global_system_variables.optimizer_switch= OPTIMIZER_SWITCH_DEFAULT; /* Variables that depends on compile options */ #ifndef DBUG_OFF default_dbug_option=IF_WIN("d:t:i:O,\\mysqld.trace", @@ -7910,12 +7061,7 @@ static int mysql_init_variables(void) #else have_profiling = SHOW_OPTION_NO; #endif - global_system_variables.ndb_index_stat_enable=FALSE; - max_system_variables.ndb_index_stat_enable=TRUE; - global_system_variables.ndb_index_stat_cache_entries=32; - max_system_variables.ndb_index_stat_cache_entries=~0L; - global_system_variables.ndb_index_stat_update_freq=20; - max_system_variables.ndb_index_stat_update_freq=~0L; + #ifdef HAVE_OPENSSL have_ssl=SHOW_OPTION_YES; #else @@ -7966,9 +7112,6 @@ static int mysql_init_variables(void) #ifdef HAVE_SMEM shared_memory_base_name= default_shared_memory_base_name; #endif -#if !defined(my_pthread_setprio) && !defined(HAVE_PTHREAD_SETSCHEDPARAM) - opt_specialflag |= SPECIAL_NO_PRIOR; -#endif #if defined(__WIN__) || defined(__NETWARE__) /* Allow Win32 and NetWare users to move MySQL anywhere */ @@ -7999,14 +7142,11 @@ static int mysql_init_variables(void) return 0; } - my_bool mysqld_get_one_option(int optid, const struct my_option *opt __attribute__((unused)), char *argument) { - int error; - switch(optid) { case '#': #ifndef DBUG_OFF @@ -8014,34 +7154,25 @@ mysqld_get_one_option(int optid, #endif opt_endinfo=1; /* unireg: memory allocation */ break; - case '0': - WARN_DEPRECATED(NULL, VER_CELOSIA, "--log-long-format", "--log-short-format"); - break; case 'a': - global_system_variables.sql_mode= fix_sql_mode(MODE_ANSI); + global_system_variables.sql_mode= MODE_ANSI; global_system_variables.tx_isolation= ISO_SERIALIZABLE; break; case 'b': strmake(mysql_home,argument,sizeof(mysql_home)-1); break; - case OPT_DEFAULT_CHARACTER_SET_OLD: // --default-character-set - WARN_DEPRECATED(NULL, VER_CELOSIA, - "--default-character-set", - "--character-set-server"); - /* Fall through */ case 'C': if (default_collation_name == compiled_default_collation_name) default_collation_name= 0; break; case 'l': - WARN_DEPRECATED(NULL, "7.0", "--log", "'--general-log'/'--general-log-file'"); + WARN_DEPRECATED(NULL, 7, 0, "--log", "'--general-log'/'--general-log-file'"); opt_log=1; break; case 'h': strmake(mysql_real_data_home,argument, sizeof(mysql_real_data_home)-1); /* Correct pointer set by my_getopt (for embedded library) */ - mysql_data_home= mysql_real_data_home; - mysql_data_home_len= strlen(mysql_data_home); + mysql_real_data_home_ptr= mysql_real_data_home; break; case 'u': if (!mysqld_user || !strcmp(mysqld_user, argument)) @@ -8051,25 +7182,10 @@ mysqld_get_one_option(int optid, break; case 'L': strmake(lc_messages_dir, argument, sizeof(lc_messages_dir)-1); + lc_messages_dir_ptr= lc_messages_dir; break; - case 'O': - WARN_DEPRECATED(NULL, VER_CELOSIA, "--set-variable", "--variable-name=value"); - break; -#ifdef HAVE_REPLICATION - case OPT_SLAVE_SKIP_ERRORS: - init_slave_skip_errors(argument); - break; - case OPT_SLAVE_EXEC_MODE: - slave_exec_mode_options= (uint) - find_bit_type_or_exit(argument, &slave_exec_mode_typelib, "", &error); - if (error) - return 1; - break; -#endif - case OPT_SAFEMALLOC_MEM_LIMIT: -#if !defined(DBUG_OFF) && defined(SAFEMALLOC) - sf_malloc_mem_limit = atoi(argument); -#endif + case OPT_BINLOG_FORMAT: + binlog_format_used= true; break; #include <sslopt-case.h> #ifndef EMBEDDED_LIBRARY @@ -8077,9 +7193,6 @@ mysqld_get_one_option(int optid, print_version(); exit(0); #endif /*EMBEDDED_LIBRARY*/ - case OPT_WARNINGS: - WARN_DEPRECATED(NULL, VER_CELOSIA, "--warnings", "--log-warnings"); - /* Note: fall-through to 'W' */ case 'W': if (!argument) global_system_variables.log_warnings++; @@ -8092,45 +7205,16 @@ mysqld_get_one_option(int optid, test_flags= argument ? (uint) atoi(argument) : 0; opt_endinfo=1; break; - case (int) OPT_DEFAULT_COLLATION_OLD: - WARN_DEPRECATED(NULL, VER_CELOSIA, "--default-collation", "--collation-server"); - break; - case (int) OPT_SAFE_SHOW_DB: - WARN_DEPRECATED(NULL, VER_CELOSIA, "--safe-show-database", "GRANT SHOW DATABASES"); - break; - case (int) OPT_LOG_BIN_TRUST_FUNCTION_CREATORS_OLD: - WARN_DEPRECATED(NULL, VER_CELOSIA, "--log-bin-trust-routine-creators", "--log-bin-trust-function-creators"); - break; - case (int) OPT_ENABLE_LOCK: - WARN_DEPRECATED(NULL, VER_CELOSIA, "--enable-locking", "--external-locking"); - break; - case (int) OPT_BIG_TABLES: - thd_startup_options|=OPTION_BIG_TABLES; - break; - case (int) OPT_IGNORE_BUILTIN_INNODB: - opt_ignore_builtin_innodb= 1; - break; case (int) OPT_ISAM_LOG: opt_myisam_log=1; break; case (int) OPT_UPDATE_LOG: - WARN_DEPRECATED(NULL, VER_CELOSIA, "--log-update", "--log-bin"); opt_update_log=1; break; case (int) OPT_BIN_LOG: opt_bin_log= test(argument != disabled_my_option); break; - case (int) OPT_ERROR_LOG_FILE: - opt_error_log= 1; - break; #ifdef HAVE_REPLICATION - case (int) OPT_INIT_RPL_ROLE: - { - int role; - role= find_type_or_exit(argument, &rpl_role_typelib, opt->name); - rpl_status = (role == 1) ? RPL_AUTH_MASTER : RPL_IDLE_SLAVE; - break; - } case (int)OPT_REPLICATE_IGNORE_DB: { rpl_filter->add_ignore_db(argument); @@ -8177,13 +7261,6 @@ mysqld_get_one_option(int optid, binlog_filter->add_ignore_db(argument); break; } - case OPT_BINLOG_FORMAT: - { - int id; - id= find_type_or_exit(argument, &binlog_format_typelib, opt->name); - global_system_variables.binlog_format= opt_binlog_format_id= id - 1; - break; - } case (int)OPT_BINLOG_DO_DB: { binlog_filter->add_do_db(argument); @@ -8227,42 +7304,14 @@ mysqld_get_one_option(int optid, } #endif /* HAVE_REPLICATION */ case (int) OPT_SLOW_QUERY_LOG: - WARN_DEPRECATED(NULL, "7.0", "--log-slow-queries", - "'--slow-query-log'/'--slow-query-log-file'"); + WARN_DEPRECATED(NULL, 7, 0, "--log-slow-queries", "'--slow-query-log'/'--slow-query-log-file'"); opt_slow_log= 1; break; -#ifdef WITH_CSV_STORAGE_ENGINE - case OPT_LOG_OUTPUT: - { - if (!argument || !argument[0]) - { - log_output_options= LOG_FILE; - log_output_str= log_output_typelib.type_names[1]; - } - else - { - log_output_str= argument; - log_output_options= - find_bit_type_or_exit(argument, &log_output_typelib, opt->name, &error); - if (error) - return 1; - } - break; - } -#endif - case OPT_EVENT_SCHEDULER: -#ifndef HAVE_EVENT_SCHEDULER - sql_perror("Event scheduler is not supported in embedded build."); -#else - if (Events::set_opt_event_scheduler(argument)) - return 1; -#endif - break; case (int) OPT_SKIP_NEW: opt_specialflag|= SPECIAL_NO_NEW_FUNC; - delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE; + delay_key_write_options= DELAY_KEY_WRITE_NONE; myisam_concurrent_insert=0; - myisam_recover_options= HA_RECOVER_NONE; + myisam_recover_options= HA_RECOVER_OFF; sp_automatic_privileges=0; my_use_symdir=0; ha_open_options&= ~(HA_OPEN_ABORT_IF_CRASHED | HA_OPEN_DELAY_KEY_WRITE); @@ -8272,47 +7321,25 @@ mysqld_get_one_option(int optid, break; case (int) OPT_SAFE: opt_specialflag|= SPECIAL_SAFE_MODE; - delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE; + delay_key_write_options= DELAY_KEY_WRITE_NONE; myisam_recover_options= HA_RECOVER_DEFAULT; ha_open_options&= ~(HA_OPEN_DELAY_KEY_WRITE); break; case (int) OPT_SKIP_PRIOR: opt_specialflag|= SPECIAL_NO_PRIOR; sql_print_warning("The --skip-thread-priority startup option is deprecated " - "and will be removed in MySQL 7.0. MySQL 6.0 and up do not " - "give threads different priorities."); + "and will be removed in MySQL 7.0. This option has no effect " + "as the implied behavior is already the default."); break; case (int) OPT_SKIP_LOCK: - WARN_DEPRECATED(NULL, VER_CELOSIA, "--skip-locking", "--skip-external-locking"); opt_external_locking=0; break; - case (int) OPT_SQL_BIN_UPDATE_SAME: - WARN_DEPRECATED(NULL, VER_CELOSIA, "--sql-bin-update-same", "the binary log"); - break; - case (int) OPT_RECORD_BUFFER_OLD: - WARN_DEPRECATED(NULL, VER_CELOSIA, "record_buffer", "read_buffer_size"); - break; - case (int) OPT_SYMBOLIC_LINKS: - WARN_DEPRECATED(NULL, VER_CELOSIA, "--use-symbolic-links", "--symbolic-links"); - break; case (int) OPT_SKIP_HOST_CACHE: opt_specialflag|= SPECIAL_NO_HOST_CACHE; break; case (int) OPT_SKIP_RESOLVE: opt_specialflag|=SPECIAL_NO_RESOLVE; break; - case (int) OPT_SKIP_NETWORKING: -#if defined(__NETWARE__) - sql_perror("Can't start server: skip-networking option is currently not supported on NetWare"); - return 1; -#endif - opt_disable_networking=1; - mysqld_port=0; - break; - case (int) OPT_SKIP_SHOW_DB: - opt_skip_show_db=1; - opt_specialflag|=SPECIAL_SKIP_SHOW_DB; - break; case (int) OPT_WANT_CORE: test_flags |= TEST_CORE_ON_SIGNAL; break; @@ -8320,75 +7347,34 @@ mysqld_get_one_option(int optid, test_flags|=TEST_NO_STACKTRACE; break; case (int) OPT_SKIP_SYMLINKS: - WARN_DEPRECATED(NULL, VER_CELOSIA, "--skip-symlink", "--skip-symbolic-links"); my_use_symdir=0; break; case (int) OPT_BIND_ADDRESS: - if ((my_bind_addr= (ulong) inet_addr(argument)) == INADDR_NONE) { - struct hostent *ent; - if (argument[0]) - ent=gethostbyname(argument); - else + struct addrinfo *res_lst, hints; + + bzero(&hints, sizeof(struct addrinfo)); + hints.ai_socktype= SOCK_STREAM; + hints.ai_protocol= IPPROTO_TCP; + + if (getaddrinfo(argument, NULL, &hints, &res_lst) != 0) { - char myhostname[255]; - if (gethostname(myhostname,sizeof(myhostname)) < 0) - { - sql_perror("Can't start server: cannot get my own hostname!"); - return 1; - } - ent=gethostbyname(myhostname); + sql_print_error("Can't start server: cannot resolve hostname!"); + return 1; } - if (!ent) + + if (res_lst->ai_next) { - sql_perror("Can't start server: cannot resolve hostname!"); + sql_print_error("Can't start server: bind-address refers to multiple interfaces!"); return 1; } - my_bind_addr = (ulong) ((in_addr*)ent->h_addr_list[0])->s_addr; - } - break; - case (int) OPT_PID_FILE: - strmake(pidfile_name, argument, sizeof(pidfile_name)-1); - break; -#ifdef __WIN__ - case (int) OPT_STANDALONE: /* Dummy option for NT */ - break; -#endif - /* - The following change issues a deprecation warning if the slave - configuration is specified either in the my.cnf file or on - the command-line. See BUG#21490. - */ - case OPT_MASTER_HOST: - case OPT_MASTER_USER: - case OPT_MASTER_PASSWORD: - case OPT_MASTER_PORT: - case OPT_MASTER_CONNECT_RETRY: - case OPT_MASTER_SSL: - case OPT_MASTER_SSL_KEY: - case OPT_MASTER_SSL_CERT: - case OPT_MASTER_SSL_CAPATH: - case OPT_MASTER_SSL_CIPHER: - case OPT_MASTER_SSL_CA: - if (!slave_warning_issued) //only show the warning once - { - slave_warning_issued = true; - WARN_DEPRECATED(NULL, "6.0", "for replication startup options", - "'CHANGE MASTER'"); + freeaddrinfo(res_lst); } break; case OPT_CONSOLE: if (opt_console) opt_error_log= 0; // Force logs to stdout break; - case (int) OPT_FLUSH: - myisam_flush=1; - flush_time=0; // No auto flush - break; - case OPT_LOW_PRIORITY_UPDATES: - thr_upgraded_concurrent_insert_lock= TL_WRITE_LOW_PRIORITY; - global_system_variables.low_priority_updates=1; - break; case OPT_BOOTSTRAP: opt_noacl=opt_bootstrap=1; break; @@ -8396,197 +7382,15 @@ mysqld_get_one_option(int optid, server_id_supplied = 1; break; case OPT_DELAY_KEY_WRITE_ALL: - WARN_DEPRECATED(NULL, VER_CELOSIA, - "--delay-key-write-for-all-tables", - "--delay-key-write=ALL"); if (argument != disabled_my_option) - argument= (char*) "ALL"; - /* Fall through */ - case OPT_DELAY_KEY_WRITE: - if (argument == disabled_my_option) - delay_key_write_options= (uint) DELAY_KEY_WRITE_NONE; - else if (! argument) - delay_key_write_options= (uint) DELAY_KEY_WRITE_ON; - else - { - int type; - type= find_type_or_exit(argument, &delay_key_write_typelib, opt->name); - delay_key_write_options= (uint) type-1; - } - break; - case OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE: - sql_print_warning("--myisam_max_extra_sort_file_size is deprecated and " - "does nothing in this version. It will be removed in " - "a future release."); - break; - case OPT_CHARSETS_DIR: - strmake(mysql_charsets_dir, argument, sizeof(mysql_charsets_dir)-1); - charsets_dir = mysql_charsets_dir; - break; - case OPT_TX_ISOLATION: - { - int type; - type= find_type_or_exit(argument, &tx_isolation_typelib, opt->name); - global_system_variables.tx_isolation= (type-1); - break; - } -#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE - case OPT_NDB_MGMD: - case OPT_NDB_NODEID: - { - int len= my_snprintf(opt_ndb_constrbuf+opt_ndb_constrbuf_len, - sizeof(opt_ndb_constrbuf)-opt_ndb_constrbuf_len, - "%s%s%s",opt_ndb_constrbuf_len > 0 ? ",":"", - optid == OPT_NDB_NODEID ? "nodeid=" : "", - argument); - opt_ndb_constrbuf_len+= len; - } - /* fall through to add the connectstring to the end - * and set opt_ndbcluster_connectstring - */ - case OPT_NDB_CONNECTSTRING: - if (opt_ndb_connectstring && opt_ndb_connectstring[0]) - my_snprintf(opt_ndb_constrbuf+opt_ndb_constrbuf_len, - sizeof(opt_ndb_constrbuf)-opt_ndb_constrbuf_len, - "%s%s", opt_ndb_constrbuf_len > 0 ? ",":"", - opt_ndb_connectstring); + delay_key_write_options= DELAY_KEY_WRITE_ALL; else - opt_ndb_constrbuf[opt_ndb_constrbuf_len]= 0; - opt_ndbcluster_connectstring= opt_ndb_constrbuf; - break; - case OPT_NDB_DISTRIBUTION: - int id; - id= find_type_or_exit(argument, &ndb_distribution_typelib, opt->name); - opt_ndb_distribution_id= (enum ndb_distribution)(id-1); + delay_key_write_options= DELAY_KEY_WRITE_NONE; break; - case OPT_NDB_EXTRA_LOGGING: - if (!argument) - ndb_extra_logging++; - else if (argument == disabled_my_option) - ndb_extra_logging= 0L; - else - ndb_extra_logging= atoi(argument); - break; -#endif - case OPT_MYISAM_RECOVER: - { - if (!argument) - { - myisam_recover_options= HA_RECOVER_DEFAULT; - myisam_recover_options_str= myisam_recover_typelib.type_names[0]; - } - else if (!argument[0]) - { - myisam_recover_options= HA_RECOVER_NONE; - myisam_recover_options_str= "OFF"; - } - else - { - myisam_recover_options_str=argument; - myisam_recover_options= - find_bit_type_or_exit(argument, &myisam_recover_typelib, opt->name, - &error); - if (error) - return 1; - } - ha_open_options|=HA_OPEN_ABORT_IF_CRASHED; - break; - } - case OPT_CONCURRENT_INSERT: - /* The following code is mainly here to emulate old behavior */ - if (!argument) /* --concurrent-insert */ - myisam_concurrent_insert= 1; - else if (argument == disabled_my_option) - myisam_concurrent_insert= 0; /* --skip-concurrent-insert */ - break; - case OPT_TC_HEURISTIC_RECOVER: - tc_heuristic_recover= find_type_or_exit(argument, - &tc_heuristic_recover_typelib, - opt->name); - break; - case OPT_MYISAM_STATS_METHOD: - { - ulong method_conv; - int method; - LINT_INIT(method_conv); - - myisam_stats_method_str= argument; - method= find_type_or_exit(argument, &myisam_stats_method_typelib, - opt->name); - switch (method-1) { - case 2: - method_conv= MI_STATS_METHOD_IGNORE_NULLS; - break; - case 1: - method_conv= MI_STATS_METHOD_NULLS_EQUAL; - break; - case 0: - default: - method_conv= MI_STATS_METHOD_NULLS_NOT_EQUAL; - break; - } - global_system_variables.myisam_stats_method= method_conv; - break; - } - case OPT_SQL_MODE: - { - sql_mode_str= argument; - global_system_variables.sql_mode= - find_bit_type_or_exit(argument, &sql_mode_typelib, opt->name, &error); - if (error) - return 1; - global_system_variables.sql_mode= fix_sql_mode(global_system_variables. - sql_mode); - break; - } - case OPT_OPTIMIZER_SWITCH: - { - bool not_used; - char *error= 0; - uint error_len= 0; - optimizer_switch_str= argument; - global_system_variables.optimizer_switch= - (ulong)find_set_from_flags(&optimizer_switch_typelib, - optimizer_switch_typelib.count, - global_system_variables.optimizer_switch, - global_system_variables.optimizer_switch, - argument, strlen(argument), NULL, - &error, &error_len, ¬_used); - if (error) - { - char buf[512]; - char *cbuf= buf; - cbuf += my_snprintf(buf, 512, "Error in parsing optimizer_switch setting near %*s\n", error_len, error); - sql_perror(buf); - return 1; - } - break; - } case OPT_ONE_THREAD: - global_system_variables.thread_handling= - SCHEDULER_ONE_THREAD_PER_CONNECTION; - break; - case OPT_THREAD_HANDLING: - { - global_system_variables.thread_handling= - find_type_or_exit(argument, &thread_handling_typelib, opt->name)-1; - break; - } - case OPT_FT_BOOLEAN_SYNTAX: - if (ft_boolean_check_syntax_string((uchar*) argument)) - { - sql_print_error("Invalid ft-boolean-syntax string: %s\n", argument); - return 1; - } - strmake(ft_boolean_syntax, argument, sizeof(ft_boolean_syntax)-1); - break; - case OPT_SKIP_SAFEMALLOC: -#ifdef SAFEMALLOC - sf_malloc_quick=1; -#endif + thread_handling= SCHEDULER_ONE_THREAD_PER_CONNECTION; break; case OPT_LOWER_CASE_TABLE_NAMES: - lower_case_table_names= argument ? atoi(argument) : 1; lower_case_table_names_used= 1; break; #if defined(ENABLED_DEBUG_SYNC) @@ -8605,6 +7409,18 @@ mysqld_get_one_option(int optid, } break; #endif /* defined(ENABLED_DEBUG_SYNC) */ + case OPT_ENGINE_CONDITION_PUSHDOWN: + /* + The last of --engine-condition-pushdown and --optimizer_switch on + command line wins (see get_options(). + */ + if (global_system_variables.engine_condition_pushdown) + global_system_variables.optimizer_switch|= + OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN; + else + global_system_variables.optimizer_switch&= + ~OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN; + break; } return 0; } @@ -8651,9 +7467,6 @@ mysql_getopt_value(const char *keyname, uint key_length, return option->value; } - -extern "C" void option_error_reporter(enum loglevel level, const char *format, ...); - void option_error_reporter(enum loglevel level, const char *format, ...) { va_list args; @@ -8670,32 +7483,108 @@ void option_error_reporter(enum loglevel level, const char *format, ...) /** + Get server options from the command line, + and perform related server initializations. + @param [in, out] argc_ptr command line options (count) + @param [in, out] argv_ptr command line options (values) + @return 0 on success + @todo - FIXME add EXIT_TOO_MANY_ARGUMENTS to "mysys_err.h" and return that code? */ -static int get_options(int *argc,char **argv) +static int get_options(int *argc_ptr, char ***argv_ptr) { int ho_error; my_getopt_register_get_addr(mysql_getopt_value); - strmake(def_ft_boolean_syntax, ft_boolean_syntax, - sizeof(ft_boolean_syntax)-1); my_getopt_error_reporter= option_error_reporter; + /* prepare all_options array */ + my_init_dynamic_array(&all_options, sizeof(my_option), + array_elements(my_long_options), + array_elements(my_long_options)/4); + for (my_option *opt= my_long_options; + opt < my_long_options + array_elements(my_long_options) - 1; + opt++) + insert_dynamic(&all_options, (uchar*) opt); + sys_var_add_options(&all_options, sys_var::PARSE_NORMAL); + add_terminator(&all_options); + /* Skip unknown options so that they may be processed later by plugins */ my_getopt_skip_unknown= TRUE; - if ((ho_error= handle_options(argc, &argv, my_long_options, + if ((ho_error= handle_options(argc_ptr, argv_ptr, (my_option*)(all_options.buffer), mysqld_get_one_option))) return ho_error; - (*argc)++; /* add back one for the progname handle_options removes */ - /* no need to do this for argv as we are discarding it. */ + + if (!opt_help) + delete_dynamic(&all_options); + + /* Add back the program name handle_options removes */ + (*argc_ptr)++; + (*argv_ptr)--; + + /* + Options have been parsed. Now some of them need additional special + handling, like custom value checking, checking of incompatibilites + between options, setting of multiple variables, etc. + Do them here. + */ if ((opt_log_slow_admin_statements || opt_log_queries_not_using_indexes || opt_log_slow_slave_statements) && !opt_slow_log) sql_print_warning("options --log-slow-admin-statements, --log-queries-not-using-indexes and --log-slow-slave-statements have no effect if --log_slow_queries is not set"); + if (log_error_file_ptr != disabled_my_option) + opt_error_log= 1; + else + log_error_file_ptr= const_cast<char*>(""); + + opt_init_connect.length=strlen(opt_init_connect.str); + opt_init_slave.length=strlen(opt_init_slave.str); + + if (global_system_variables.low_priority_updates) + thr_upgraded_concurrent_insert_lock= TL_WRITE_LOW_PRIORITY; + + if (ft_boolean_check_syntax_string((uchar*) ft_boolean_syntax)) + { + sql_print_error("Invalid ft-boolean-syntax string: %s\n", + ft_boolean_syntax); + return 1; + } + + if (opt_disable_networking) + { +#if defined(__NETWARE__) + sql_print_error("Can't start server: skip-networking option is currently not supported on NetWare"); + return 1; +#endif + mysqld_port= 0; + } + if (opt_skip_show_db) + opt_specialflag|= SPECIAL_SKIP_SHOW_DB; + + if (myisam_flush) + flush_time= 0; + +#ifdef HAVE_REPLICATION + if (opt_slave_skip_errors) + init_slave_skip_errors(opt_slave_skip_errors); +#endif + + if (global_system_variables.max_join_size == HA_POS_ERROR) + global_system_variables.option_bits|= OPTION_BIG_SELECTS; + else + global_system_variables.option_bits&= ~OPTION_BIG_SELECTS; + + if (global_system_variables.option_bits & OPTION_AUTOCOMMIT) + global_system_variables.option_bits&= ~OPTION_NOT_AUTOCOMMIT; + else + global_system_variables.option_bits|= OPTION_NOT_AUTOCOMMIT; + + global_system_variables.sql_mode= + expand_sql_mode(global_system_variables.sql_mode); #if defined(HAVE_BROKEN_REALPATH) my_use_symdir=0; my_disable_symlinks=1; @@ -8714,15 +7603,13 @@ static int get_options(int *argc,char **argv) test_flags&= ~TEST_CORE_ON_SIGNAL; } /* Set global MyISAM variables from delay_key_write_options */ - fix_delay_key_write((THD*) 0, OPT_GLOBAL); - /* Set global slave_exec_mode from its option */ - fix_slave_exec_mode(OPT_GLOBAL); + fix_delay_key_write(0, 0, OPT_GLOBAL); #ifndef EMBEDDED_LIBRARY if (mysqld_chroot) set_root(mysqld_chroot); #else - global_system_variables.thread_handling = SCHEDULER_NO_THREADS; + thread_handling = SCHEDULER_NO_THREADS; max_allowed_packet= global_system_variables.max_allowed_packet; net_buffer_length= global_system_variables.net_buffer_length; #endif @@ -8735,38 +7622,36 @@ static int get_options(int *argc,char **argv) */ my_disable_locking= myisam_single_user= test(opt_external_locking == 0); my_default_record_cache_size=global_system_variables.read_buff_size; - myisam_max_temp_length= - (my_off_t) global_system_variables.myisam_max_sort_file_size; - - /* Set global variables based on startup options */ - myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size); - /* long_query_time is in microseconds */ - global_system_variables.long_query_time= max_system_variables.long_query_time= - (longlong) (long_query_time * 1000000.0); + global_system_variables.long_query_time= (ulonglong) + (global_system_variables.long_query_time_double * 1e6); if (opt_short_log_format) opt_specialflag|= SPECIAL_SHORT_LOG_FORMAT; if (init_global_datetime_format(MYSQL_TIMESTAMP_DATE, - &global_system_variables.date_format) || + &global_date_format) || init_global_datetime_format(MYSQL_TIMESTAMP_TIME, - &global_system_variables.time_format) || + &global_time_format) || init_global_datetime_format(MYSQL_TIMESTAMP_DATETIME, - &global_system_variables.datetime_format)) + &global_datetime_format)) return 1; #ifdef EMBEDDED_LIBRARY one_thread_scheduler(&thread_scheduler); #else - if (global_system_variables.thread_handling <= - SCHEDULER_ONE_THREAD_PER_CONNECTION) + if (thread_handling <= SCHEDULER_ONE_THREAD_PER_CONNECTION) one_thread_per_connection_scheduler(&thread_scheduler); - else if (global_system_variables.thread_handling == SCHEDULER_NO_THREADS) + else if (thread_handling == SCHEDULER_NO_THREADS) one_thread_scheduler(&thread_scheduler); else pool_of_threads_scheduler(&thread_scheduler); /* purecov: tested */ #endif + + global_system_variables.engine_condition_pushdown= + test(global_system_variables.optimizer_switch & + OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN); + return 0; } @@ -8848,7 +7733,7 @@ static int fix_paths(void) convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS); (void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir (void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home); - (void) my_load_path(pidfile_name,pidfile_name,mysql_real_data_home); + (void) my_load_path(pidfile_name, pidfile_name_ptr, mysql_real_data_home); (void) my_load_path(opt_plugin_dir, opt_plugin_dir_ptr ? opt_plugin_dir_ptr : get_relative_path(PLUGINDIR), mysql_home); opt_plugin_dir_ptr= opt_plugin_dir; @@ -8868,23 +7753,22 @@ static int fix_paths(void) (void) my_load_path(lc_messages_dir, lc_messages_dir, buff); /* If --character-sets-dir isn't given, use shared library dir */ - if (charsets_dir != mysql_charsets_dir) - { + if (charsets_dir) + strmake(mysql_charsets_dir, charsets_dir, sizeof(mysql_charsets_dir)-1); + else strxnmov(mysql_charsets_dir, sizeof(mysql_charsets_dir)-1, buff, CHARSET_DIR, NullS); - } (void) my_load_path(mysql_charsets_dir, mysql_charsets_dir, buff); convert_dirname(mysql_charsets_dir, mysql_charsets_dir, NullS); charsets_dir=mysql_charsets_dir; if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir)) return 1; + if (!opt_mysql_tmpdir) + opt_mysql_tmpdir= mysql_tmpdir; #ifdef HAVE_REPLICATION if (!slave_load_tmpdir) - { - if (!(slave_load_tmpdir = (char*) my_strdup(mysql_tmpdir, MYF(MY_FAE)))) - return 1; - } + slave_load_tmpdir= mysql_tmpdir; #endif /* HAVE_REPLICATION */ /* Convert the secure-file-priv option to system format, allowing @@ -8893,106 +7777,12 @@ static int fix_paths(void) if (opt_secure_file_priv) { convert_dirname(buff, opt_secure_file_priv, NullS); - my_free(opt_secure_file_priv, MYF(0)); + x_free(opt_secure_file_priv); opt_secure_file_priv= my_strdup(buff, MYF(MY_FAE)); } return 0; } - -static ulong find_bit_type_or_exit(const char *x, TYPELIB *bit_lib, - const char *option, int *error) -{ - ulong result; - const char **ptr; - - *error= 0; - if ((result= find_bit_type(x, bit_lib)) == ~(ulong) 0) - { - char *buff= (char *) my_alloca(2048); - char *cbuf; - ptr= bit_lib->type_names; - cbuf= buff + ((!*x) ? - my_snprintf(buff, 2048, "No option given to %s\n", option) : - my_snprintf(buff, 2048, "Wrong option to %s. Option(s) given: %s\n", - option, x)); - cbuf+= my_snprintf(cbuf, 2048 - (cbuf-buff), "Alternatives are: '%s'", *ptr); - while (*++ptr) - cbuf+= my_snprintf(cbuf, 2048 - (cbuf-buff), ",'%s'", *ptr); - my_snprintf(cbuf, 2048 - (cbuf-buff), "\n"); - sql_perror(buff); - *error= 1; - my_afree(buff); - return 0; - } - - return result; -} - - -/** - @return - a bitfield from a string of substrings separated by ',' - or - ~(ulong) 0 on error. -*/ - -static ulong find_bit_type(const char *x, TYPELIB *bit_lib) -{ - bool found_end; - int found_count; - const char *end,*i,*j; - const char **array, *pos; - ulong found,found_int,bit; - DBUG_ENTER("find_bit_type"); - DBUG_PRINT("enter",("x: '%s'",x)); - - found=0; - found_end= 0; - pos=(char *) x; - while (*pos == ' ') pos++; - found_end= *pos == 0; - while (!found_end) - { - if (!*(end=strcend(pos,','))) /* Let end point at fieldend */ - { - while (end > pos && end[-1] == ' ') - end--; /* Skip end-space */ - found_end=1; - } - found_int=0; found_count=0; - for (array=bit_lib->type_names, bit=1 ; (i= *array++) ; bit<<=1) - { - j=pos; - while (j != end) - { - if (my_toupper(mysqld_charset,*i++) != - my_toupper(mysqld_charset,*j++)) - goto skip; - } - found_int=bit; - if (! *i) - { - found_count=1; - break; - } - else if (j != pos) // Half field found - { - found_count++; // Could be one of two values - } -skip: ; - } - if (found_count != 1) - DBUG_RETURN(~(ulong) 0); // No unique value - found|=found_int; - pos=end+1; - } - - DBUG_PRINT("exit",("bit-field: %ld",(ulong) found)); - DBUG_RETURN(found); -} /* find_bit_type */ - - /** Check if file system used for databases is case insensitive. @@ -9018,16 +7808,17 @@ static int test_if_case_insensitive(const char *dir_name) MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR); fn_format(buff2, glob_hostname, dir_name, ".LOWER-TEST", MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR); - (void) my_delete(buff2, MYF(0)); - if ((file= my_create(buff, 0666, O_RDWR, MYF(0))) < 0) + mysql_file_delete(key_file_casetest, buff2, MYF(0)); + if ((file= mysql_file_create(key_file_casetest, + buff, 0666, O_RDWR, MYF(0))) < 0) { sql_print_warning("Can't create test file %s", buff); DBUG_RETURN(-1); } - my_close(file, MYF(0)); - if (my_stat(buff2, &stat_info, MYF(0))) + mysql_file_close(file, MYF(0)); + if (mysql_file_stat(key_file_casetest, buff2, &stat_info, MYF(0))) result= 1; // Can access file - (void) my_delete(buff, MYF(MY_WME)); + mysql_file_delete(key_file_casetest, buff, MYF(MY_WME)); DBUG_PRINT("exit", ("result: %d", result)); DBUG_RETURN(result); } @@ -9041,18 +7832,19 @@ static int test_if_case_insensitive(const char *dir_name) static void create_pid_file() { File file; - if ((file = my_create(pidfile_name,0664, - O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0) + if ((file= mysql_file_create(key_file_pid, pidfile_name, 0664, + O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0) { char buff[21], *end; end= int10_to_str((long) getpid(), buff, 10); *end++= '\n'; - if (!my_write(file, (uchar*) buff, (uint) (end-buff), MYF(MY_WME | MY_NABP))) + if (!mysql_file_write(file, (uchar*) buff, (uint) (end-buff), + MYF(MY_WME | MY_NABP))) { - (void) my_close(file, MYF(0)); + mysql_file_close(file, MYF(0)); return; } - (void) my_close(file, MYF(0)); + mysql_file_close(file, MYF(0)); } sql_perror("Can't start server: can't create PID file"); exit(1); @@ -9062,7 +7854,7 @@ static void create_pid_file() /** Clear most status variables. */ void refresh_status(THD *thd) { - pthread_mutex_lock(&LOCK_status); + mysql_mutex_lock(&LOCK_status); /* Add thread's status variabes to global status */ add_to_status(&global_status_var, &thd->status_var); @@ -9076,7 +7868,7 @@ void refresh_status(THD *thd) /* Reset the counters of all key caches (default and named). */ process_key_caches(reset_key_cache_counters); flush_status_time= time((time_t*) 0); - pthread_mutex_unlock(&LOCK_status); + mysql_mutex_unlock(&LOCK_status); /* Set max_used_connections to the number of currently open @@ -9084,9 +7876,9 @@ void refresh_status(THD *thd) deadlocks. Status reset becomes not atomic, but status data is not exact anyway. */ - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); max_used_connections= thread_count-delayed_insert_threads; - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); } @@ -9095,11 +7887,6 @@ void refresh_status(THD *thd) This section should go away soon *****************************************************************************/ -#ifndef WITH_NDBCLUSTER_STORAGE_ENGINE -ulong ndb_cache_check_time; -ulong ndb_extra_logging; -#endif - /***************************************************************************** Instantiate templates *****************************************************************************/ @@ -9110,7 +7897,258 @@ template class I_List<THD>; template class I_List_iterator<THD>; template class I_List<i_string>; template class I_List<i_string_pair>; -template class I_List<NAMED_LIST>; template class I_List<Statement>; template class I_List_iterator<Statement>; #endif + +#ifdef HAVE_PSI_INTERFACE +#ifdef HAVE_MMAP +PSI_mutex_key key_PAGE_lock, key_LOCK_sync, key_LOCK_active, key_LOCK_pool; +#endif /* HAVE_MMAP */ + +#ifdef HAVE_OPENSSL +PSI_mutex_key key_LOCK_des_key_file; +#endif /* HAVE_OPENSSL */ + +PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_prep_xids, + key_delayed_insert_mutex, key_hash_filo_lock, key_LOCK_active_mi, + key_LOCK_connection_count, key_LOCK_crypt, key_LOCK_delayed_create, + key_LOCK_delayed_insert, key_LOCK_delayed_status, key_LOCK_error_log, + key_LOCK_gdl, key_LOCK_global_read_lock, key_LOCK_global_system_variables, + key_LOCK_lock_db, key_LOCK_manager, key_LOCK_mapped_file, + key_LOCK_mysql_create_db, key_LOCK_open, key_LOCK_prepared_stmt_count, + key_LOCK_rpl_status, key_LOCK_server_started, key_LOCK_status, + key_LOCK_system_variables_hash, key_LOCK_table_share, key_LOCK_thd_data, + key_LOCK_user_conn, key_LOCK_uuid_generator, key_LOG_LOCK_log, + key_master_info_data_lock, key_master_info_run_lock, + key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock, + key_relay_log_info_log_space_lock, key_relay_log_info_run_lock, + key_structure_guard_mutex, key_TABLE_SHARE_mutex, key_LOCK_error_messages, + key_LOG_INFO_lock, key_LOCK_thread_count; + +static PSI_mutex_info all_server_mutexes[]= +{ +#ifdef HAVE_MMAP + { &key_PAGE_lock, "PAGE::lock", 0}, + { &key_LOCK_sync, "TC_LOG_MMAP::LOCK_sync", 0}, + { &key_LOCK_active, "TC_LOG_MMAP::LOCK_active", 0}, + { &key_LOCK_pool, "TC_LOG_MMAP::LOCK_pool", 0}, +#endif /* HAVE_MMAP */ + +#ifdef HAVE_OPENSSL + { &key_LOCK_des_key_file, "LOCK_des_key_file", PSI_FLAG_GLOBAL}, +#endif /* HAVE_OPENSSL */ + + { &key_BINLOG_LOCK_index, "MYSQL_BIN_LOG::LOCK_index", 0}, + { &key_BINLOG_LOCK_prep_xids, "MYSQL_BIN_LOG::LOCK_prep_xids", 0}, + { &key_delayed_insert_mutex, "Delayed_insert::mutex", 0}, + { &key_hash_filo_lock, "hash_filo::lock", 0}, + { &key_LOCK_active_mi, "LOCK_active_mi", PSI_FLAG_GLOBAL}, + { &key_LOCK_connection_count, "LOCK_connection_count", PSI_FLAG_GLOBAL}, + { &key_LOCK_crypt, "LOCK_crypt", PSI_FLAG_GLOBAL}, + { &key_LOCK_delayed_create, "LOCK_delayed_create", PSI_FLAG_GLOBAL}, + { &key_LOCK_delayed_insert, "LOCK_delayed_insert", PSI_FLAG_GLOBAL}, + { &key_LOCK_delayed_status, "LOCK_delayed_status", PSI_FLAG_GLOBAL}, + { &key_LOCK_error_log, "LOCK_error_log", PSI_FLAG_GLOBAL}, + { &key_LOCK_gdl, "LOCK_gdl", PSI_FLAG_GLOBAL}, + { &key_LOCK_global_read_lock, "LOCK_global_read_lock", PSI_FLAG_GLOBAL}, + { &key_LOCK_global_system_variables, "LOCK_global_system_variables", PSI_FLAG_GLOBAL}, + { &key_LOCK_lock_db, "LOCK_lock_db", PSI_FLAG_GLOBAL}, + { &key_LOCK_manager, "LOCK_manager", PSI_FLAG_GLOBAL}, + { &key_LOCK_mapped_file, "LOCK_mapped_file", PSI_FLAG_GLOBAL}, + { &key_LOCK_mysql_create_db, "LOCK_mysql_create_db", PSI_FLAG_GLOBAL}, + { &key_LOCK_open, "LOCK_open", PSI_FLAG_GLOBAL}, + { &key_LOCK_prepared_stmt_count, "LOCK_prepared_stmt_count", PSI_FLAG_GLOBAL}, + { &key_LOCK_rpl_status, "LOCK_rpl_status", PSI_FLAG_GLOBAL}, + { &key_LOCK_server_started, "LOCK_server_started", PSI_FLAG_GLOBAL}, + { &key_LOCK_status, "LOCK_status", PSI_FLAG_GLOBAL}, + { &key_LOCK_system_variables_hash, "LOCK_system_variables_hash", PSI_FLAG_GLOBAL}, + { &key_LOCK_table_share, "LOCK_table_share", PSI_FLAG_GLOBAL}, + { &key_LOCK_thd_data, "THD::LOCK_thd_data", 0}, + { &key_LOCK_user_conn, "LOCK_user_conn", PSI_FLAG_GLOBAL}, + { &key_LOCK_uuid_generator, "LOCK_uuid_generator", PSI_FLAG_GLOBAL}, + { &key_LOG_LOCK_log, "LOG::LOCK_log", 0}, + { &key_master_info_data_lock, "Master_info::data_lock", 0}, + { &key_master_info_run_lock, "Master_info::run_lock", 0}, + { &key_mutex_slave_reporting_capability_err_lock, "Slave_reporting_capability::err_lock", 0}, + { &key_relay_log_info_data_lock, "Relay_log_info::data_lock", 0}, + { &key_relay_log_info_log_space_lock, "Relay_log_info::log_space_lock", 0}, + { &key_relay_log_info_run_lock, "Relay_log_info::run_lock", 0}, + { &key_structure_guard_mutex, "Query_cache::structure_guard_mutex", 0}, + { &key_TABLE_SHARE_mutex, "TABLE_SHARE::mutex", 0}, + { &key_LOCK_error_messages, "LOCK_error_messages", PSI_FLAG_GLOBAL}, + { &key_LOG_INFO_lock, "LOG_INFO::lock", 0}, + { &key_LOCK_thread_count, "LOCK_thread_count", PSI_FLAG_GLOBAL} +}; + +PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger, + key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave, + key_rwlock_LOCK_system_variables_hash, key_rwlock_query_cache_query_lock; + +static PSI_rwlock_info all_server_rwlocks[]= +{ +#if defined (HAVE_OPENSSL) && !defined(HAVE_YASSL) + { &key_rwlock_openssl, "CRYPTO_dynlock_value::lock", 0}, +#endif + { &key_rwlock_LOCK_grant, "LOCK_grant", PSI_FLAG_GLOBAL}, + { &key_rwlock_LOCK_logger, "LOGGER::LOCK_logger", 0}, + { &key_rwlock_LOCK_sys_init_connect, "LOCK_sys_init_connect", PSI_FLAG_GLOBAL}, + { &key_rwlock_LOCK_sys_init_slave, "LOCK_sys_init_slave", PSI_FLAG_GLOBAL}, + { &key_rwlock_LOCK_system_variables_hash, "LOCK_system_variables_hash", PSI_FLAG_GLOBAL}, + { &key_rwlock_query_cache_query_lock, "Query_cache_query::lock", 0} +}; + +#ifdef HAVE_MMAP +PSI_cond_key key_PAGE_cond, key_COND_active, key_COND_pool; +#endif /* HAVE_MMAP */ + +PSI_cond_key key_BINLOG_COND_prep_xids, key_BINLOG_update_cond, + key_COND_cache_status_changed, key_COND_global_read_lock, key_COND_manager, + key_COND_refresh, key_COND_rpl_status, key_COND_server_started, + key_delayed_insert_cond, key_delayed_insert_cond_client, + key_item_func_sleep_cond, key_master_info_data_cond, + key_master_info_start_cond, key_master_info_stop_cond, + key_relay_log_info_data_cond, key_relay_log_info_log_space_cond, + key_relay_log_info_start_cond, key_relay_log_info_stop_cond, + key_TABLE_SHARE_cond, key_user_level_lock_cond, + key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache; + +static PSI_cond_info all_server_conds[]= +{ +#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY) + { &key_COND_handler_count, "COND_handler_count", PSI_FLAG_GLOBAL}, +#endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */ +#ifdef HAVE_MMAP + { &key_PAGE_cond, "PAGE::cond", 0}, + { &key_COND_active, "TC_LOG_MMAP::COND_active", 0}, + { &key_COND_pool, "TC_LOG_MMAP::COND_pool", 0}, +#endif /* HAVE_MMAP */ + { &key_BINLOG_COND_prep_xids, "MYSQL_BIN_LOG::COND_prep_xids", 0}, + { &key_BINLOG_update_cond, "MYSQL_BIN_LOG::update_cond", 0}, + { &key_COND_cache_status_changed, "Query_cache::COND_cache_status_changed", 0}, + { &key_COND_global_read_lock, "COND_global_read_lock", PSI_FLAG_GLOBAL}, + { &key_COND_manager, "COND_manager", PSI_FLAG_GLOBAL}, + { &key_COND_refresh, "COND_refresh", PSI_FLAG_GLOBAL}, + { &key_COND_rpl_status, "COND_rpl_status", PSI_FLAG_GLOBAL}, + { &key_COND_server_started, "COND_server_started", PSI_FLAG_GLOBAL}, + { &key_delayed_insert_cond, "Delayed_insert::cond", 0}, + { &key_delayed_insert_cond_client, "Delayed_insert::cond_client", 0}, + { &key_item_func_sleep_cond, "Item_func_sleep::cond", 0}, + { &key_master_info_data_cond, "Master_info::data_cond", 0}, + { &key_master_info_start_cond, "Master_info::start_cond", 0}, + { &key_master_info_stop_cond, "Master_info::stop_cond", 0}, + { &key_relay_log_info_data_cond, "Relay_log_info::data_cond", 0}, + { &key_relay_log_info_log_space_cond, "Relay_log_info::log_space_cond", 0}, + { &key_relay_log_info_start_cond, "Relay_log_info::start_cond", 0}, + { &key_relay_log_info_stop_cond, "Relay_log_info::stop_cond", 0}, + { &key_TABLE_SHARE_cond, "TABLE_SHARE::cond", 0}, + { &key_user_level_lock_cond, "User_level_lock::cond", 0}, + { &key_COND_thread_count, "COND_thread_count", PSI_FLAG_GLOBAL}, + { &key_COND_thread_cache, "COND_thread_cache", PSI_FLAG_GLOBAL}, + { &key_COND_flush_thread_cache, "COND_flush_thread_cache", PSI_FLAG_GLOBAL} +}; + +PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert, + key_thread_handle_manager, key_thread_main, + key_thread_one_connection, key_thread_signal_hand; + +static PSI_thread_info all_server_threads[]= +{ +#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY) + { &key_thread_handle_con_namedpipes, "con_named_pipes", PSI_FLAG_GLOBAL}, +#endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */ + +#if defined(HAVE_SMEM) && !defined(EMBEDDED_LIBRARY) + { &key_thread_handle_con_sharedmem, "con_shared_mem", PSI_FLAG_GLOBAL}, +#endif /* HAVE_SMEM && !EMBEDDED_LIBRARY */ + +#if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY) + { &key_thread_handle_con_sockets, "con_sockets", PSI_FLAG_GLOBAL}, +#endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */ + +#ifdef __WIN__ + { &key_thread_handle_shutdown, "shutdown", PSI_FLAG_GLOBAL}, +#endif /* __WIN__ */ + + { &key_thread_bootstrap, "bootstrap", PSI_FLAG_GLOBAL}, + { &key_thread_delayed_insert, "delayed_insert", 0}, + { &key_thread_handle_manager, "manager", PSI_FLAG_GLOBAL}, + { &key_thread_main, "main", PSI_FLAG_GLOBAL}, + { &key_thread_one_connection, "one_connection", 0}, + { &key_thread_signal_hand, "signal_handler", PSI_FLAG_GLOBAL} +}; + +#ifdef HAVE_MMAP +PSI_file_key key_file_map; +#endif /* HAVE_MMAP */ + +PSI_file_key key_file_binlog, key_file_binlog_index, key_file_casetest, + key_file_dbopt, key_file_des_key_file, key_file_ERRMSG, key_select_to_file, + key_file_fileparser, key_file_frm, key_file_global_ddl_log, key_file_load, + key_file_loadfile, key_file_log_event_data, key_file_log_event_info, + key_file_master_info, key_file_misc, key_file_MYSQL_LOG, key_file_partition, + key_file_pid, key_file_relay_log_info, key_file_send_file, key_file_tclog, + key_file_trg, key_file_trn, key_file_init; + +static PSI_file_info all_server_files[]= +{ +#ifdef HAVE_MMAP + { &key_file_map, "map", 0}, +#endif /* HAVE_MMAP */ + { &key_file_binlog, "binlog", 0}, + { &key_file_binlog_index, "binlog_index", 0}, + { &key_file_casetest, "casetest", 0}, + { &key_file_dbopt, "dbopt", 0}, + { &key_file_des_key_file, "des_key_file", 0}, + { &key_file_ERRMSG, "ERRMSG", 0}, + { &key_select_to_file, "select_to_file", 0}, + { &key_file_fileparser, "file_parser", 0}, + { &key_file_frm, "FRM", 0}, + { &key_file_global_ddl_log, "global_ddl_log", 0}, + { &key_file_load, "load", 0}, + { &key_file_loadfile, "LOAD_FILE", 0}, + { &key_file_log_event_data, "log_event_data", 0}, + { &key_file_log_event_info, "log_event_info", 0}, + { &key_file_master_info, "master_info", 0}, + { &key_file_misc, "misc", 0}, + { &key_file_MYSQL_LOG, "MYSQL_LOG", 0}, + { &key_file_partition, "partition", 0}, + { &key_file_pid, "pid", 0}, + { &key_file_relay_log_info, "relay_log_info", 0}, + { &key_file_send_file, "send_file", 0}, + { &key_file_tclog, "tclog", 0}, + { &key_file_trg, "trigger_name", 0}, + { &key_file_trn, "trigger", 0}, + { &key_file_init, "init", 0} +}; + +/** + Initialise all the performance schema instrumentation points + used by the server. +*/ +void init_server_psi_keys(void) +{ + const char* category= "sql"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_server_mutexes); + PSI_server->register_mutex(category, all_server_mutexes, count); + + count= array_elements(all_server_rwlocks); + PSI_server->register_rwlock(category, all_server_rwlocks, count); + + count= array_elements(all_server_conds); + PSI_server->register_cond(category, all_server_conds, count); + + count= array_elements(all_server_threads); + PSI_server->register_thread(category, all_server_threads, count); + + count= array_elements(all_server_files); + PSI_server->register_file(category, all_server_files, count); +} + +#endif /* HAVE_PSI_INTERFACE */ + diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 5cf3597c638..d54ff1d2779 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -71,8 +71,10 @@ #if defined(__WIN__) || !defined(MYSQL_SERVER) /* The following is because alarms doesn't work on windows. */ +#ifndef NO_ALARM #define NO_ALARM #endif +#endif #ifndef NO_ALARM #include "my_pthread.h" diff --git a/sql/opt_range.cc b/sql/opt_range.cc index ac5b1f575de..741815585e2 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -5834,7 +5834,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, SEL_ARG *tree= 0; MEM_ROOT *alloc= param->mem_root; uchar *str; - ulong orig_sql_mode; + ulonglong orig_sql_mode; int err; DBUG_ENTER("get_mm_leaf"); @@ -7574,7 +7574,6 @@ void SEL_ARG::test_use_count(SEL_ARG *root) #endif - /* Calculate estimate of number records that will be retrieved by a range scan on given index using given SEL_ARG intervals tree. @@ -7811,8 +7810,8 @@ check_quick_keys(PARAM *param, uint idx, SEL_ARG *key_tree, param->range_count++; if (!tmp_min_flag && ! tmp_max_flag && (uint) key_tree->part+1 == param->table->key_info[keynr].key_parts && - (param->table->key_info[keynr].flags & (HA_NOSAME | HA_END_SPACE_KEY)) == - HA_NOSAME && min_key_length == max_key_length && + param->table->key_info[keynr].flags & HA_NOSAME && + min_key_length == max_key_length && !memcmp(param->min_key, param->max_key, min_key_length) && !param->first_null_comp) { @@ -8105,8 +8104,7 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key, { KEY *table_key=quick->head->key_info+quick->index; flag=EQ_RANGE; - if ((table_key->flags & (HA_NOSAME | HA_END_SPACE_KEY)) == HA_NOSAME && - key->part == table_key->key_parts-1) + if ((table_key->flags & HA_NOSAME) && key->part == table_key->key_parts-1) { if (!(table_key->flags & HA_NULL_PART_KEY) || !null_part_in_key(key, @@ -8155,8 +8153,7 @@ bool QUICK_RANGE_SELECT::unique_key_range() if ((tmp->flag & (EQ_RANGE | NULL_RANGE)) == EQ_RANGE) { KEY *key=head->key_info+index; - return ((key->flags & (HA_NOSAME | HA_END_SPACE_KEY)) == HA_NOSAME && - key->key_length == tmp->min_length); + return (key->flags & HA_NOSAME) && key->key_length == tmp->min_length; } } return 0; @@ -8274,8 +8271,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, range->min_length= range->max_length= ref->key_length; range->min_keypart_map= range->max_keypart_map= make_prev_keypart_map(ref->key_parts); - range->flag= ((ref->key_length == key_info->key_length && - (key_info->flags & HA_END_SPACE_KEY) == 0) ? EQ_RANGE : 0); + range->flag= (ref->key_length == key_info->key_length ? EQ_RANGE : 0); if (!(quick->key_parts=key_part=(KEY_PART *) alloc_root(&quick->alloc,sizeof(KEY_PART)*ref->key_parts))) diff --git a/sql/opt_range.h b/sql/opt_range.h index 393ffcb2115..0bb2243080a 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -730,7 +730,7 @@ class SQL_SELECT :public Sql_alloc { class FT_SELECT: public QUICK_RANGE_SELECT { public: FT_SELECT(THD *thd, TABLE *table, uint key) : - QUICK_RANGE_SELECT (thd, table, key, 1) { VOID(init()); } + QUICK_RANGE_SELECT (thd, table, key, 1) { (void) init(); } ~FT_SELECT() { file->ft_end(); } int init() { return error=file->ft_init(); } int reset() { return 0; } diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index 13b10ac2e8f..d85e976e9c8 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -175,8 +175,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) error= tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); if(error) { - tl->table->file->print_error(error, MYF(0)); - tl->table->in_use->fatal_error(); + tl->table->file->print_error(error, MYF(ME_FATALERROR)); return error; } count*= tl->table->file->stats.records; @@ -427,8 +426,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) if (error == HA_ERR_KEY_NOT_FOUND || error == HA_ERR_END_OF_FILE) return HA_ERR_KEY_NOT_FOUND; // No rows matching WHERE /* HA_ERR_LOCK_DEADLOCK or some other error */ - table->file->print_error(error, MYF(0)); - table->in_use->fatal_error(); + table->file->print_error(error, MYF(ME_FATALERROR)); return(error); } removed_tables|= table->map; diff --git a/sql/parse_file.cc b/sql/parse_file.cc index 3d65fa1de31..d94ab3d940d 100644 --- a/sql/parse_file.cc +++ b/sql/parse_file.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2004 MySQL AB +/* Copyright (C) 2004 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -237,8 +237,9 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, // temporary file name path[path_end]='~'; path[path_end+1]= '\0'; - if ((handler= my_create(path, CREATE_MODE, O_RDWR | O_TRUNC, - MYF(MY_WME))) <= 0) + if ((handler= mysql_file_create(key_file_fileparser, + path, CREATE_MODE, O_RDWR | O_TRUNC, + MYF(MY_WME))) <= 0) { DBUG_RETURN(TRUE); } @@ -267,11 +268,11 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, goto err_w_file; if (opt_sync_frm) { - if (my_sync(handler, MYF(MY_WME))) + if (mysql_file_sync(handler, MYF(MY_WME))) goto err_w_file; } - if (my_close(handler, MYF(MY_WME))) + if (mysql_file_close(handler, MYF(MY_WME))) { DBUG_RETURN(TRUE); } @@ -283,7 +284,7 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, char path_to[FN_REFLEN]; memcpy(path_to, path, path_end+1); path[path_end]='~'; - if (my_rename(path, path_to, MYF(MY_WME))) + if (mysql_file_rename(key_file_fileparser, path, path_to, MYF(MY_WME))) { DBUG_RETURN(TRUE); } @@ -292,7 +293,7 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name, err_w_cache: end_io_cache(&file); err_w_file: - my_close(handler, MYF(MY_WME)); + mysql_file_close(handler, MYF(MY_WME)); DBUG_RETURN(TRUE); } @@ -321,7 +322,7 @@ my_bool rename_in_schema_file(THD *thd, build_table_filename(new_path, sizeof(new_path) - 1, new_db, new_name, reg_ext, 0); - if (my_rename(old_path, new_path, MYF(MY_WME))) + if (mysql_file_rename(key_file_frm, old_path, new_path, MYF(MY_WME))) return 1; /* check if arc_dir exists: disabled unused feature (see bug #17823). */ @@ -365,7 +366,8 @@ sql_parse_prepare(const LEX_STRING *file_name, MEM_ROOT *mem_root, File file; DBUG_ENTER("sql_parse_prepare"); - if (!my_stat(file_name->str, &stat_info, MYF(MY_WME))) + if (!mysql_file_stat(key_file_fileparser, + file_name->str, &stat_info, MYF(MY_WME))) { DBUG_RETURN(0); } @@ -386,20 +388,21 @@ sql_parse_prepare(const LEX_STRING *file_name, MEM_ROOT *mem_root, DBUG_RETURN(0); } - if ((file= my_open(file_name->str, O_RDONLY | O_SHARE, MYF(MY_WME))) < 0) + if ((file= mysql_file_open(key_file_fileparser, file_name->str, + O_RDONLY | O_SHARE, MYF(MY_WME))) < 0) { DBUG_RETURN(0); } - if ((len= my_read(file, (uchar *)parser->buff, - stat_info.st_size, MYF(MY_WME))) == + if ((len= mysql_file_read(file, (uchar *)parser->buff, + stat_info.st_size, MYF(MY_WME))) == MY_FILE_ERROR) { - my_close(file, MYF(MY_WME)); + mysql_file_close(file, MYF(MY_WME)); DBUG_RETURN(0); } - if (my_close(file, MYF(MY_WME))) + if (mysql_file_close(file, MYF(MY_WME))) { DBUG_RETURN(0); } diff --git a/sql/protocol.cc b/sql/protocol.cc index ca6aa3a6052..855a6842f1f 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -247,6 +247,7 @@ net_send_ok(THD *thd, if (!error) error= net_flush(net); + thd->stmt_da->can_overwrite_status= FALSE; DBUG_PRINT("info", ("OK sent, so no more error sending allowed")); @@ -406,6 +407,7 @@ bool net_send_error_packet(THD *thd, uint sql_errno, const char *err, buff[2]= '#'; pos= (uchar*) strmov((char*) buff+3, sqlstate); } + converted_err_len= convert_error_message((char*)converted_err, sizeof(converted_err), thd->variables.character_set_results, @@ -414,6 +416,7 @@ bool net_send_error_packet(THD *thd, uint sql_errno, const char *err, length= (uint) (strmake((char*) pos, (char*)converted_err, MYSQL_ERRMSG_SIZE - 1) - (char*) buff); err= (char*) buff; + DBUG_RETURN(net_write_command(net,(uchar) 255, (uchar*) "", 0, (uchar*) err, length)); } @@ -1009,8 +1012,8 @@ bool Protocol_text::store(const char *from, size_t length, { CHARSET_INFO *tocs= this->thd->variables.character_set_results; #ifndef DBUG_OFF - DBUG_PRINT("info", ("Protocol_text::store field %u (%u): %s", field_pos, - field_count, from)); + DBUG_PRINT("info", ("Protocol_text::store field %u (%u): %*.s", + field_pos, field_count, (int) length, from)); DBUG_ASSERT(field_pos < field_count); DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_DECIMAL || diff --git a/sql/records.cc b/sql/records.cc index 8fd63d104a4..c97ffa152dc 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -178,7 +178,7 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table, if (table->s->tmp_table == NON_TRANSACTIONAL_TMP_TABLE && !table->sort.addon_field) - VOID(table->file->extra(HA_EXTRA_MMAP)); + (void) table->file->extra(HA_EXTRA_MMAP); if (table->sort.addon_field) { @@ -266,11 +266,12 @@ void init_read_record(READ_RECORD *info,THD *thd, TABLE *table, !(table->s->db_options_in_use & HA_OPTION_PACK_RECORD) || (use_record_cache < 0 && !(table->file->ha_table_flags() & HA_NOT_DELETE_WITH_CACHE)))) - VOID(table->file->extra_opt(HA_EXTRA_CACHE, - thd->variables.read_buff_size)); + (void) table->file->extra_opt(HA_EXTRA_CACHE, + thd->variables.read_buff_size); } /* Condition pushdown to storage engine */ - if (thd->variables.engine_condition_pushdown && + if ((thd->variables.optimizer_switch & + OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN) && select && select->cond && (select->cond->used_tables() & table->map) && !table->file->pushed_cond) diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 275571c2158..29443eb6e65 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2006 MySQL AB & Sasha +/* Copyright (C) 2001-2006 MySQL AB & Sasha, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -39,8 +39,8 @@ RPL_STATUS rpl_status=RPL_NULL; -pthread_mutex_t LOCK_rpl_status; -pthread_cond_t COND_rpl_status; +mysql_mutex_t LOCK_rpl_status; +mysql_cond_t COND_rpl_status; HASH slave_list; const char *rpl_role_type[] = {"MASTER","SLAVE",NullS}; @@ -49,7 +49,7 @@ TYPELIB rpl_role_typelib = {array_elements(rpl_role_type)-1,"", const char* rpl_status_type[]= { - "AUTH_MASTER","ACTIVE_SLAVE","IDLE_SLAVE", "LOST_SOLDIER","TROOP_SOLDIER", + "AUTH_MASTER","IDLE_SLAVE","ACTIVE_SLAVE","LOST_SOLDIER","TROOP_SOLDIER", "RECOVERY_CAPTAIN","NULL",NullS }; TYPELIB rpl_status_typelib= {array_elements(rpl_status_type)-1,"", @@ -83,9 +83,9 @@ static int init_failsafe_rpl_thread(THD* thd) my_net_init(&thd->net, 0); thd->net.read_timeout = slave_net_timeout; thd->max_client_packet_length=thd->net.max_packet; - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); if (init_thr_lock() || thd->store_globals()) { @@ -98,9 +98,6 @@ static int init_failsafe_rpl_thread(THD* thd) } thd->mem_root->free= thd->mem_root->used= 0; - if (thd->variables.max_join_size == HA_POS_ERROR) - thd->options|= OPTION_BIG_SELECTS; - thd_proc_info(thd, "Thread initialized"); thd->version=refresh_version; thd->set_time(); @@ -110,11 +107,11 @@ static int init_failsafe_rpl_thread(THD* thd) void change_rpl_status(RPL_STATUS from_status, RPL_STATUS to_status) { - pthread_mutex_lock(&LOCK_rpl_status); + mysql_mutex_lock(&LOCK_rpl_status); if (rpl_status == from_status || rpl_status == RPL_ANY) rpl_status = to_status; - pthread_cond_signal(&COND_rpl_status); - pthread_mutex_unlock(&LOCK_rpl_status); + mysql_cond_signal(&COND_rpl_status); + mysql_mutex_unlock(&LOCK_rpl_status); } @@ -143,7 +140,7 @@ void unregister_slave(THD* thd, bool only_mine, bool need_mutex) if (thd->server_id) { if (need_mutex) - pthread_mutex_lock(&LOCK_slave_list); + mysql_mutex_lock(&LOCK_slave_list); SLAVE_INFO* old_si; if ((old_si = (SLAVE_INFO*)my_hash_search(&slave_list, @@ -152,7 +149,7 @@ void unregister_slave(THD* thd, bool only_mine, bool need_mutex) my_hash_delete(&slave_list, (uchar*)old_si); if (need_mutex) - pthread_mutex_unlock(&LOCK_slave_list); + mysql_mutex_unlock(&LOCK_slave_list); } } @@ -173,7 +170,7 @@ int register_slave(THD* thd, uchar* packet, uint packet_length) uchar *p= packet, *p_end= packet + packet_length; const char *errmsg= "Wrong parameters to function register_slave"; - if (check_access(thd, REPL_SLAVE_ACL, any_db,0,0,0,0)) + if (check_access(thd, REPL_SLAVE_ACL, any_db, NULL, NULL, 0, 0)) return 1; if (!(si = (SLAVE_INFO*)my_malloc(sizeof(SLAVE_INFO), MYF(MY_WME)))) goto err2; @@ -187,16 +184,22 @@ int register_slave(THD* thd, uchar* packet, uint packet_length) goto err; si->port= uint2korr(p); p += 2; - si->rpl_recovery_rank= uint4korr(p); + /* + We need to by pass the bytes used in the fake rpl_recovery_rank + variable. It was removed in patch for BUG#13963. But this would + make a server with that patch unable to connect to an old master. + See: BUG#49259 + */ + // si->rpl_recovery_rank= uint4korr(p); p += 4; if (!(si->master_id= uint4korr(p))) si->master_id= server_id; si->thd= thd; - pthread_mutex_lock(&LOCK_slave_list); + mysql_mutex_lock(&LOCK_slave_list); unregister_slave(thd,0,0); res= my_hash_insert(&slave_list, (uchar*) si); - pthread_mutex_unlock(&LOCK_slave_list); + mysql_mutex_unlock(&LOCK_slave_list); return res; err: @@ -219,12 +222,37 @@ extern "C" void slave_info_free(void *s) my_free(s, MYF(MY_WME)); } +#ifdef HAVE_PSI_INTERFACE +static PSI_mutex_key key_LOCK_slave_list; + +static PSI_mutex_info all_slave_list_mutexes[]= +{ + { &key_LOCK_slave_list, "LOCK_slave_list", PSI_FLAG_GLOBAL} +}; + +static void init_all_slave_list_mutexes(void) +{ + const char* category= "sql"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_slave_list_mutexes); + PSI_server->register_mutex(category, all_slave_list_mutexes, count); +} +#endif /* HAVE_PSI_INTERFACE */ + void init_slave_list() { +#ifdef HAVE_PSI_INTERFACE + init_all_slave_list_mutexes(); +#endif + my_hash_init(&slave_list, system_charset_info, SLAVE_LIST_CHUNK, 0, 0, (my_hash_get_key) slave_list_key, (my_hash_free_key) slave_info_free, 0); - pthread_mutex_init(&LOCK_slave_list, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_slave_list, &LOCK_slave_list, MY_MUTEX_INIT_FAST); } void end_slave_list() @@ -233,7 +261,7 @@ void end_slave_list() if (my_hash_inited(&slave_list)) { my_hash_free(&slave_list); - pthread_mutex_destroy(&LOCK_slave_list); + mysql_mutex_destroy(&LOCK_slave_list); } } @@ -245,7 +273,7 @@ static int find_target_pos(LEX_MASTER_INFO *mi, IO_CACHE *log, char *errmsg) for (;;) { Log_event* ev; - if (!(ev = Log_event::read_log_event(log, (pthread_mutex_t*) 0, 0))) + if (!(ev= Log_event::read_log_event(log, (mysql_mutex_t*) 0, 0))) { if (log->error > 0) strmov(errmsg, "Binary log truncated in the middle of event"); @@ -287,7 +315,7 @@ int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg) char last_log_name[FN_REFLEN]; IO_CACHE log; File file = -1, last_file = -1; - pthread_mutex_t *log_lock; + mysql_mutex_t *log_lock; const char* errmsg_p; Slave_log_event* sev = 0; my_off_t last_pos = 0; @@ -317,7 +345,7 @@ int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg) bzero((char*) &log,sizeof(log)); log_lock = mysql_bin_log.get_log_lock(); - pthread_mutex_lock(log_lock); + mysql_mutex_lock(log_lock); for (;;) { @@ -349,7 +377,7 @@ int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg) goto err; } end_io_cache(&log); - (void) my_close(file, MYF(MY_WME)); + mysql_file_close(file, MYF(MY_WME)); if (init_io_cache(&log, (file = last_file), IO_SIZE, READ_CACHE, 0, 0, MYF(MY_WME))) { @@ -365,7 +393,7 @@ int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg) switch (mysql_bin_log.find_next_log(&linfo, 1)) { case LOG_INFO_EOF: if (last_file >= 0) - (void)my_close(last_file, MYF(MY_WME)); + mysql_file_close(last_file, MYF(MY_WME)); last_file = -1; goto found_log; case 0: @@ -377,7 +405,7 @@ int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg) end_io_cache(&log); if (last_file >= 0) - (void) my_close(last_file, MYF(MY_WME)); + mysql_file_close(last_file, MYF(MY_WME)); last_file = file; } @@ -390,15 +418,15 @@ found_log: mi_inited: error = 0; err: - pthread_mutex_unlock(log_lock); + mysql_mutex_unlock(log_lock); end_io_cache(&log); - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thd->current_linfo = 0; - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); if (file >= 0) - (void) my_close(file, MYF(MY_WME)); + mysql_file_close(file, MYF(MY_WME)); if (last_file >= 0 && last_file != file) - (void) my_close(last_file, MYF(MY_WME)); + mysql_file_close(last_file, MYF(MY_WME)); DBUG_RETURN(error); } @@ -419,7 +447,7 @@ static Slave_log_event* find_slave_event(IO_CACHE* log, for (i = 0; i < 2; i++) { - if (!(ev = Log_event::read_log_event(log, (pthread_mutex_t*)0, 0))) + if (!(ev= Log_event::read_log_event(log, (mysql_mutex_t*)0, 0))) { my_snprintf(errmsg, SLAVE_ERRMSG_SIZE, "Error reading event in log '%s'", @@ -541,7 +569,7 @@ HOSTS"; goto err; } - pthread_mutex_lock(&LOCK_slave_list); + mysql_mutex_lock(&LOCK_slave_list); while ((row= mysql_fetch_row(res))) { @@ -556,14 +584,14 @@ HOSTS"; if (!(si = (SLAVE_INFO*)my_malloc(sizeof(SLAVE_INFO), MYF(MY_WME)))) { error= "the slave is out of memory"; - pthread_mutex_unlock(&LOCK_slave_list); + mysql_mutex_unlock(&LOCK_slave_list); goto err; } si->server_id = log_server_id; if (my_hash_insert(&slave_list, (uchar*)si)) { error= "the slave is out of memory"; - pthread_mutex_unlock(&LOCK_slave_list); + mysql_mutex_unlock(&LOCK_slave_list); goto err; } } @@ -577,7 +605,7 @@ HOSTS"; strmake(si->password, row[3], sizeof(si->password)-1); } } - pthread_mutex_unlock(&LOCK_slave_list); + mysql_mutex_unlock(&LOCK_slave_list); err: if (res) @@ -615,13 +643,13 @@ pthread_handler_t handle_failsafe_rpl(void *arg) sql_print_error("Could not initialize failsafe replication thread"); goto err; } - pthread_mutex_lock(&LOCK_rpl_status); + mysql_mutex_lock(&LOCK_rpl_status); msg= thd->enter_cond(&COND_rpl_status, &LOCK_rpl_status, "Waiting for request"); while (!thd->killed && !abort_loop) { bool break_req_chain = 0; - pthread_cond_wait(&COND_rpl_status, &LOCK_rpl_status); + mysql_cond_wait(&COND_rpl_status, &LOCK_rpl_status); thd_proc_info(thd, "Processing request"); while (!break_req_chain) { @@ -677,8 +705,6 @@ bool show_slave_hosts(THD* thd) field_list.push_back(new Item_empty_string("Password",20)); } field_list.push_back(new Item_return_int("Port", 7, MYSQL_TYPE_LONG)); - field_list.push_back(new Item_return_int("Rpl_recovery_rank", 7, - MYSQL_TYPE_LONG)); field_list.push_back(new Item_return_int("Master_id", 10, MYSQL_TYPE_LONG)); @@ -686,7 +712,7 @@ bool show_slave_hosts(THD* thd) Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); - pthread_mutex_lock(&LOCK_slave_list); + mysql_mutex_lock(&LOCK_slave_list); for (uint i = 0; i < slave_list.records; ++i) { @@ -700,342 +726,17 @@ bool show_slave_hosts(THD* thd) protocol->store(si->password, &my_charset_bin); } protocol->store((uint32) si->port); - protocol->store((uint32) si->rpl_recovery_rank); protocol->store((uint32) si->master_id); if (protocol->write()) { - pthread_mutex_unlock(&LOCK_slave_list); + mysql_mutex_unlock(&LOCK_slave_list); DBUG_RETURN(TRUE); } } - pthread_mutex_unlock(&LOCK_slave_list); + mysql_mutex_unlock(&LOCK_slave_list); my_eof(thd); DBUG_RETURN(FALSE); } - -int connect_to_master(THD *thd, MYSQL* mysql, Master_info* mi) -{ - DBUG_ENTER("connect_to_master"); - - if (!mi->host || !*mi->host) /* empty host */ - { - strmov(mysql->net.last_error, "Master is not configured"); - DBUG_RETURN(1); - } - mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *) &slave_net_timeout); - mysql_options(mysql, MYSQL_OPT_READ_TIMEOUT, (char *) &slave_net_timeout); - -#ifdef HAVE_OPENSSL - if (mi->ssl) - { - mysql_ssl_set(mysql, - mi->ssl_key[0]?mi->ssl_key:0, - mi->ssl_cert[0]?mi->ssl_cert:0, - mi->ssl_ca[0]?mi->ssl_ca:0, - mi->ssl_capath[0]?mi->ssl_capath:0, - mi->ssl_cipher[0]?mi->ssl_cipher:0); - mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, - &mi->ssl_verify_server_cert); - } -#endif - - mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset_info->csname); - mysql_options(mysql, MYSQL_SET_CHARSET_DIR, (char *) charsets_dir); - if (!mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0, - mi->port, 0, 0)) - DBUG_RETURN(1); - mysql->reconnect= 1; - DBUG_RETURN(0); -} - - -static inline void cleanup_mysql_results(MYSQL_RES* db_res, - MYSQL_RES** cur, MYSQL_RES** start) -{ - for (; cur >= start; --cur) - { - if (*cur) - mysql_free_result(*cur); - } - mysql_free_result(db_res); -} - - -static int fetch_db_tables(THD *thd, MYSQL *mysql, const char *db, - MYSQL_RES *table_res, Master_info *mi) -{ - MYSQL_ROW row; - for (row = mysql_fetch_row(table_res); row; - row = mysql_fetch_row(table_res)) - { - TABLE_LIST table; - const char* table_name= row[0]; - int error; - if (rpl_filter->is_on()) - { - bzero((char*) &table, sizeof(table)); //just for safe - table.db= (char*) db; - table.table_name= (char*) table_name; - table.updating= 1; - - if (!rpl_filter->tables_ok(thd->db, &table)) - continue; - } - /* download master's table and overwrite slave's table */ - if ((error= fetch_master_table(thd, db, table_name, mi, mysql, 1))) - return error; - } - return 0; -} - -/** - Load all MyISAM tables from master to this slave. - - REQUIREMENTS - - No active transaction (flush_relay_log_info would not work in this case). - - @todo - - add special option, not enabled - by default, to allow inclusion of mysql database into load - data from master -*/ - -bool load_master_data(THD* thd) -{ - MYSQL mysql; - MYSQL_RES* master_status_res = 0; - int error = 0; - const char* errmsg=0; - int restart_thread_mask; - HA_CREATE_INFO create_info; - - mysql_init(&mysql); - - /* - We do not want anyone messing with the slave at all for the entire - duration of the data load. - */ - pthread_mutex_lock(&LOCK_active_mi); - lock_slave_threads(active_mi); - init_thread_mask(&restart_thread_mask,active_mi,0 /*not inverse*/); - if (restart_thread_mask && - (error=terminate_slave_threads(active_mi,restart_thread_mask, - 1 /*skip lock*/))) - { - my_message(error, ER(error), MYF(0)); - unlock_slave_threads(active_mi); - pthread_mutex_unlock(&LOCK_active_mi); - return TRUE; - } - - if (connect_to_master(thd, &mysql, active_mi)) - { - my_error(error= ER_CONNECT_TO_MASTER, MYF(0), mysql_error(&mysql)); - goto err; - } - - // now that we are connected, get all database and tables in each - { - MYSQL_RES *db_res, **table_res, **table_res_end, **cur_table_res; - uint num_dbs; - - if (mysql_real_query(&mysql, STRING_WITH_LEN("SHOW DATABASES")) || - !(db_res = mysql_store_result(&mysql))) - { - my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql)); - goto err; - } - - if (!(num_dbs = (uint) mysql_num_rows(db_res))) - goto err; - /* - In theory, the master could have no databases at all - and run with skip-grant - */ - - if (!(table_res = (MYSQL_RES**)thd->alloc(num_dbs * sizeof(MYSQL_RES*)))) - { - my_message(error = ER_OUTOFMEMORY, ER(ER_OUTOFMEMORY), MYF(0)); - goto err; - } - - /* - This is a temporary solution until we have online backup - capabilities - to be replaced once online backup is working - we wait to issue FLUSH TABLES WITH READ LOCK for as long as we - can to minimize the lock time. - */ - if (mysql_real_query(&mysql, - STRING_WITH_LEN("FLUSH TABLES WITH READ LOCK")) || - mysql_real_query(&mysql, STRING_WITH_LEN("SHOW MASTER STATUS")) || - !(master_status_res = mysql_store_result(&mysql))) - { - my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql)); - goto err; - } - - /* - Go through every table in every database, and if the replication - rules allow replicating it, get it - */ - - table_res_end = table_res + num_dbs; - - for (cur_table_res = table_res; cur_table_res < table_res_end; - cur_table_res++) - { - // since we know how many rows we have, this can never be NULL - MYSQL_ROW row = mysql_fetch_row(db_res); - char* db = row[0]; - - /* - Do not replicate databases excluded by rules. We also test - replicate_wild_*_table rules (replicate_wild_ignore_table='db1.%' will - be considered as "ignore the 'db1' database as a whole, as it already - works for CREATE DATABASE and DROP DATABASE). - Also skip 'mysql' database - in most cases the user will - mess up and not exclude mysql database with the rules when - he actually means to - in this case, he is up for a surprise if - his priv tables get dropped and downloaded from master - TODO - add special option, not enabled - by default, to allow inclusion of mysql database into load - data from master - */ - - if (!rpl_filter->db_ok(db) || - !rpl_filter->db_ok_with_wild_table(db) || - !strcmp(db,"mysql") || - is_schema_db(db)) - { - *cur_table_res = 0; - continue; - } - - bzero((char*) &create_info, sizeof(create_info)); - create_info.options= HA_LEX_CREATE_IF_NOT_EXISTS; - - if (mysql_create_db(thd, db, &create_info, 1)) - { - cleanup_mysql_results(db_res, cur_table_res - 1, table_res); - goto err; - } - /* Clear the result of mysql_create_db(). */ - thd->stmt_da->reset_diagnostics_area(); - - if (mysql_select_db(&mysql, db) || - mysql_real_query(&mysql, STRING_WITH_LEN("SHOW TABLES")) || - !(*cur_table_res = mysql_store_result(&mysql))) - { - my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql)); - cleanup_mysql_results(db_res, cur_table_res - 1, table_res); - goto err; - } - - if ((error = fetch_db_tables(thd,&mysql,db,*cur_table_res,active_mi))) - { - // we do not report the error - fetch_db_tables handles it - cleanup_mysql_results(db_res, cur_table_res, table_res); - goto err; - } - } - - cleanup_mysql_results(db_res, cur_table_res - 1, table_res); - - // adjust replication coordinates from the master - if (master_status_res) - { - MYSQL_ROW row = mysql_fetch_row(master_status_res); - - /* - We need this check because the master may not be running with - log-bin, but it will still allow us to do all the steps - of LOAD DATA FROM MASTER - no reason to forbid it, really, - although it does not make much sense for the user to do it - */ - if (row && row[0] && row[1]) - { - /* - If the slave's master info is not inited, we init it, then we write - the new coordinates to it. Must call init_master_info() *before* - setting active_mi, because init_master_info() sets active_mi with - defaults. - */ - int error_2; - - if (init_master_info(active_mi, master_info_file, relay_log_info_file, - 0, (SLAVE_IO | SLAVE_SQL))) - my_message(ER_MASTER_INFO, ER(ER_MASTER_INFO), MYF(0)); - strmake(active_mi->master_log_name, row[0], - sizeof(active_mi->master_log_name) -1); - active_mi->master_log_pos= my_strtoll10(row[1], (char**) 0, &error_2); - /* at least in recent versions, the condition below should be false */ - if (active_mi->master_log_pos < BIN_LOG_HEADER_SIZE) - active_mi->master_log_pos = BIN_LOG_HEADER_SIZE; - /* - Relay log's IO_CACHE may not be inited (even if we are sure that some - host was specified; there could have been a problem when replication - started, which led to relay log's IO_CACHE to not be inited. - */ - if (flush_master_info(active_mi, FALSE, FALSE)) - sql_print_error("Failed to flush master info file"); - } - mysql_free_result(master_status_res); - } - - if (mysql_real_query(&mysql, STRING_WITH_LEN("UNLOCK TABLES"))) - { - my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql)); - goto err; - } - } - thd_proc_info(thd, "purging old relay logs"); - if (purge_relay_logs(&active_mi->rli,thd, - 0 /* not only reset, but also reinit */, - &errmsg)) - { - my_error(ER_RELAY_LOG_FAIL, MYF(0), errmsg); - unlock_slave_threads(active_mi); - pthread_mutex_unlock(&LOCK_active_mi); - return TRUE; - } - pthread_mutex_lock(&active_mi->rli.data_lock); - active_mi->rli.group_master_log_pos = active_mi->master_log_pos; - strmake(active_mi->rli.group_master_log_name,active_mi->master_log_name, - sizeof(active_mi->rli.group_master_log_name)-1); - /* - Cancel the previous START SLAVE UNTIL, as the fact to download - a new copy logically makes UNTIL irrelevant. - */ - active_mi->rli.clear_until_condition(); - - /* - No need to update rli.event* coordinates, they will be when the slave - threads start ; only rli.group* coordinates are necessary here. - */ - flush_relay_log_info(&active_mi->rli); - pthread_cond_broadcast(&active_mi->rli.data_cond); - pthread_mutex_unlock(&active_mi->rli.data_lock); - thd_proc_info(thd, "starting slave"); - if (restart_thread_mask) - { - error=start_slave_threads(0 /* mutex not needed */, - 1 /* wait for start */, - active_mi,master_info_file,relay_log_info_file, - restart_thread_mask); - } - -err: - unlock_slave_threads(active_mi); - pthread_mutex_unlock(&LOCK_active_mi); - thd_proc_info(thd, 0); - - mysql_close(&mysql); // safe to call since we always do mysql_init() - if (!error) - my_ok(thd); - - return error; -} - #endif /* HAVE_REPLICATION */ diff --git a/sql/repl_failsafe.h b/sql/repl_failsafe.h index bce2c727050..94b151aaee7 100644 --- a/sql/repl_failsafe.h +++ b/sql/repl_failsafe.h @@ -1,7 +1,7 @@ #ifndef REPL_FAILSAFE_INCLUDED #define REPL_FAILSAFE_INCLUDED -/* Copyright (C) 2001-2005 MySQL AB & Sasha +/* Copyright (C) 2001-2005 MySQL AB & Sasha, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,14 +22,14 @@ #include "my_sys.h" #include "slave.h" -typedef enum {RPL_AUTH_MASTER=0,RPL_ACTIVE_SLAVE,RPL_IDLE_SLAVE, +typedef enum {RPL_AUTH_MASTER=0,RPL_IDLE_SLAVE,RPL_ACTIVE_SLAVE, RPL_LOST_SOLDIER,RPL_TROOP_SOLDIER, RPL_RECOVERY_CAPTAIN,RPL_NULL /* inactive */, RPL_ANY /* wild card used by change_rpl_status */ } RPL_STATUS; extern RPL_STATUS rpl_status; -extern pthread_mutex_t LOCK_rpl_status; -extern pthread_cond_t COND_rpl_status; +extern mysql_mutex_t LOCK_rpl_status; +extern mysql_cond_t COND_rpl_status; extern TYPELIB rpl_role_typelib, rpl_status_typelib; extern const char* rpl_role_type[], *rpl_status_type[]; diff --git a/sql/replication.h b/sql/replication.h index eea77ef9f8e..5e9c09adf31 100644 --- a/sql/replication.h +++ b/sql/replication.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2008 MySQL AB +/* Copyright (C) 2008 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -470,8 +470,8 @@ MYSQL *rpl_connect_master(MYSQL *mysql); held before call this function @param msg The new process message for the thread */ -const char* thd_enter_cond(MYSQL_THD thd, pthread_cond_t *cond, - pthread_mutex_t *mutex, const char *msg); +const char* thd_enter_cond(MYSQL_THD thd, mysql_cond_t *cond, + mysql_mutex_t *mutex, const char *msg); /** Set thread leaving a condition diff --git a/sql/rpl_injector.cc b/sql/rpl_injector.cc index 43f4e7d849d..64f79092057 100644 --- a/sql/rpl_injector.cc +++ b/sql/rpl_injector.cc @@ -36,8 +36,6 @@ injector::transaction::transaction(MYSQL_BIN_LOG *log, THD *thd) m_start_pos.m_file_pos= log_info.pos; begin_trans(m_thd); - - thd->set_current_stmt_binlog_row_based(); } injector::transaction::~transaction() diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index 28b0af441f8..7dad340cfa6 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,6 +21,7 @@ #ifdef HAVE_REPLICATION +#define DEFAULT_CONNECT_RETRY 60 // Defined in slave.cc int init_intvar_from_file(int* var, IO_CACHE* f, int default_val); @@ -31,9 +32,10 @@ int init_dynarray_intvar_from_file(DYNAMIC_ARRAY* arr, IO_CACHE* f); Master_info::Master_info(bool is_slave_recovery) :Slave_reporting_capability("I/O"), - ssl(0), ssl_verify_server_cert(0), fd(-1), io_thd(0), inited(0), - rli(is_slave_recovery), abort_slave(0), slave_running(0), - slave_run_id(0), sync_counter(0), + ssl(0), ssl_verify_server_cert(0), fd(-1), io_thd(0), + rli(is_slave_recovery), port(MYSQL_PORT), + connect_retry(DEFAULT_CONNECT_RETRY), inited(0), abort_slave(0), + slave_running(0), slave_run_id(0), sync_counter(0), heartbeat_period(0), received_heartbeats(0), master_id(0) { host[0] = 0; user[0] = 0; password[0] = 0; @@ -42,21 +44,21 @@ Master_info::Master_info(bool is_slave_recovery) my_init_dynamic_array(&ignore_server_ids, sizeof(::server_id), 16, 16); bzero((char*) &file, sizeof(file)); - pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST); - pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST); - pthread_cond_init(&data_cond, NULL); - pthread_cond_init(&start_cond, NULL); - pthread_cond_init(&stop_cond, NULL); + mysql_mutex_init(key_master_info_run_lock, &run_lock, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_master_info_data_lock, &data_lock, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_master_info_data_cond, &data_cond, NULL); + mysql_cond_init(key_master_info_start_cond, &start_cond, NULL); + mysql_cond_init(key_master_info_stop_cond, &stop_cond, NULL); } Master_info::~Master_info() { delete_dynamic(&ignore_server_ids); - pthread_mutex_destroy(&run_lock); - pthread_mutex_destroy(&data_lock); - pthread_cond_destroy(&data_cond); - pthread_cond_destroy(&start_cond); - pthread_cond_destroy(&stop_cond); + mysql_mutex_destroy(&run_lock); + mysql_mutex_destroy(&data_lock); + mysql_cond_destroy(&data_cond); + mysql_cond_destroy(&start_cond); + mysql_cond_destroy(&stop_cond); } /** @@ -97,33 +99,13 @@ bool Master_info::shall_ignore_server_id(ulong s_id) != NULL; } -void init_master_info_with_options(Master_info* mi) +void init_master_log_pos(Master_info* mi) { - DBUG_ENTER("init_master_info_with_options"); + DBUG_ENTER("init_master_log_pos"); mi->master_log_name[0] = 0; mi->master_log_pos = BIN_LOG_HEADER_SIZE; // skip magic number - if (master_host) - strmake(mi->host, master_host, sizeof(mi->host) - 1); - if (master_user) - strmake(mi->user, master_user, sizeof(mi->user) - 1); - if (master_password) - strmake(mi->password, master_password, MAX_PASSWORD_LENGTH); - mi->port = master_port; - mi->connect_retry = master_connect_retry; - - mi->ssl= master_ssl; - if (master_ssl_ca) - strmake(mi->ssl_ca, master_ssl_ca, sizeof(mi->ssl_ca)-1); - if (master_ssl_capath) - strmake(mi->ssl_capath, master_ssl_capath, sizeof(mi->ssl_capath)-1); - if (master_ssl_cert) - strmake(mi->ssl_cert, master_ssl_cert, sizeof(mi->ssl_cert)-1); - if (master_ssl_cipher) - strmake(mi->ssl_cipher, master_ssl_cipher, sizeof(mi->ssl_cipher)-1); - if (master_ssl_key) - strmake(mi->ssl_key, master_ssl_key, sizeof(mi->ssl_key)-1); /* Intentionally init ssl_verify_server_cert to 0, no option available */ mi->ssl_verify_server_cert= 0; /* @@ -193,7 +175,7 @@ int init_master_info(Master_info* mi, const char* master_info_fname, keep other threads from reading bogus info */ - pthread_mutex_lock(&mi->data_lock); + mysql_mutex_lock(&mi->data_lock); fd = mi->fd; /* does master.info exist ? */ @@ -202,7 +184,7 @@ int init_master_info(Master_info* mi, const char* master_info_fname, { if (abort_if_no_master_info_file) { - pthread_mutex_unlock(&mi->data_lock); + mysql_mutex_unlock(&mi->data_lock); DBUG_RETURN(0); } /* @@ -210,8 +192,9 @@ int init_master_info(Master_info* mi, const char* master_info_fname, the old descriptor and re-create the old file */ if (fd >= 0) - my_close(fd, MYF(MY_WME)); - if ((fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0 ) + mysql_file_close(fd, MYF(MY_WME)); + if ((fd= mysql_file_open(key_file_master_info, + fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0 ) { sql_print_error("Failed to create a new master info file (\ file '%s', errno %d)", fname, my_errno); @@ -226,7 +209,7 @@ file '%s')", fname); } mi->fd = fd; - init_master_info_with_options(mi); + init_master_log_pos(mi); } else // file exists @@ -235,7 +218,8 @@ file '%s')", fname); reinit_io_cache(&mi->file, READ_CACHE, 0L,0,0); else { - if ((fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0 ) + if ((fd= mysql_file_open(key_file_master_info, + fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0 ) { sql_print_error("Failed to open the existing master info file (\ file '%s', errno %d)", fname, my_errno); @@ -299,36 +283,34 @@ file '%s')", fname); lines= 7; if (init_intvar_from_file(&master_log_pos, &mi->file, 4) || - init_strvar_from_file(mi->host, sizeof(mi->host), &mi->file, - master_host) || - init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file, - master_user) || + init_strvar_from_file(mi->host, sizeof(mi->host), &mi->file, 0) || + init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file, "test") || init_strvar_from_file(mi->password, SCRAMBLED_PASSWORD_CHAR_LENGTH+1, - &mi->file, master_password) || - init_intvar_from_file(&port, &mi->file, master_port) || + &mi->file, 0) || + init_intvar_from_file(&port, &mi->file, MYSQL_PORT) || init_intvar_from_file(&connect_retry, &mi->file, - master_connect_retry)) + DEFAULT_CONNECT_RETRY)) goto errwithmsg; /* If file has ssl part use it even if we have server without - SSL support. But these option will be ignored later when + SSL support. But these options will be ignored later when slave will try connect to master, so in this case warning is printed. */ if (lines >= LINES_IN_MASTER_INFO_WITH_SSL) { - if (init_intvar_from_file(&ssl, &mi->file, master_ssl) || + if (init_intvar_from_file(&ssl, &mi->file, 0) || init_strvar_from_file(mi->ssl_ca, sizeof(mi->ssl_ca), - &mi->file, master_ssl_ca) || + &mi->file, 0) || init_strvar_from_file(mi->ssl_capath, sizeof(mi->ssl_capath), - &mi->file, master_ssl_capath) || + &mi->file, 0) || init_strvar_from_file(mi->ssl_cert, sizeof(mi->ssl_cert), - &mi->file, master_ssl_cert) || + &mi->file, 0) || init_strvar_from_file(mi->ssl_cipher, sizeof(mi->ssl_cipher), - &mi->file, master_ssl_cipher) || + &mi->file, 0) || init_strvar_from_file(mi->ssl_key, sizeof(mi->ssl_key), - &mi->file, master_ssl_key)) + &mi->file, 0)) goto errwithmsg; /* @@ -360,8 +342,8 @@ file '%s')", fname); #ifndef HAVE_OPENSSL if (ssl) sql_print_warning("SSL information in the master info file " - "('%s') are ignored because this MySQL slave was compiled " - "without SSL support.", fname); + "('%s') are ignored because this MySQL slave was " + "compiled without SSL support.", fname); #endif /* HAVE_OPENSSL */ /* @@ -389,7 +371,7 @@ file '%s')", fname); reinit_io_cache(&mi->file, WRITE_CACHE, 0L, 0, 1); if ((error=test(flush_master_info(mi, TRUE, TRUE)))) sql_print_error("Failed to flush master info file"); - pthread_mutex_unlock(&mi->data_lock); + mysql_mutex_unlock(&mi->data_lock); DBUG_RETURN(error); errwithmsg: @@ -398,11 +380,11 @@ errwithmsg: err: if (fd >= 0) { - my_close(fd, MYF(0)); + mysql_file_close(fd, MYF(0)); end_io_cache(&mi->file); } mi->fd= -1; - pthread_mutex_unlock(&mi->data_lock); + mysql_mutex_unlock(&mi->data_lock); DBUG_RETURN(1); } @@ -438,17 +420,17 @@ int flush_master_info(Master_info* mi, */ if (flush_relay_log_cache) { - pthread_mutex_t *log_lock= mi->rli.relay_log.get_log_lock(); + mysql_mutex_t *log_lock= mi->rli.relay_log.get_log_lock(); IO_CACHE *log_file= mi->rli.relay_log.get_log_file(); if (need_lock_relay_log) - pthread_mutex_lock(log_lock); + mysql_mutex_lock(log_lock); - safe_mutex_assert_owner(log_lock); + mysql_mutex_assert_owner(log_lock); err= flush_io_cache(log_file); if (need_lock_relay_log) - pthread_mutex_unlock(log_lock); + mysql_mutex_unlock(log_lock); if (err) DBUG_RETURN(2); @@ -527,7 +509,7 @@ void end_master_info(Master_info* mi) if (mi->fd >= 0) { end_io_cache(&mi->file); - (void)my_close(mi->fd, MYF(MY_WME)); + mysql_file_close(mi->fd, MYF(MY_WME)); mi->fd = -1; } mi->inited = 0; diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h index 363c8d4e0b3..c4ca5714306 100644 --- a/sql/rpl_mi.h +++ b/sql/rpl_mi.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -77,8 +77,8 @@ class Master_info : public Slave_reporting_capability File fd; // we keep the file open, so we need to remember the file pointer IO_CACHE file; - pthread_mutex_t data_lock,run_lock; - pthread_cond_t data_cond,start_cond,stop_cond; + mysql_mutex_t data_lock, run_lock; + mysql_cond_t data_cond, start_cond, stop_cond; THD *io_thd; MYSQL* mysql; uint32 file_id; /* for 3.23 load data infile */ @@ -113,8 +113,7 @@ class Master_info : public Slave_reporting_capability DYNAMIC_ARRAY ignore_server_ids; ulong master_id; }; - -void init_master_info_with_options(Master_info* mi); +void init_master_log_pos(Master_info* mi); int init_master_info(Master_info* mi, const char* master_info_fname, const char* slave_info_fname, bool abort_if_no_master_info_file, diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index 3a46bbcd6ee..9e1413d726d 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -104,10 +104,10 @@ pack_row(TABLE *table, MY_BITMAP const* cols, #endif pack_ptr= field->pack(pack_ptr, field->ptr + offset, field->max_data_length(), TRUE); - DBUG_PRINT("debug", ("field: %s; pack_ptr: 0x%lx;" + DBUG_PRINT("debug", ("field: %s; real_type: %d, pack_ptr: 0x%lx;" " pack_ptr':0x%lx; bytes: %d", - field->field_name, (ulong) old_pack_ptr, - (ulong) pack_ptr, + field->field_name, field->real_type(), + (ulong) old_pack_ptr, (ulong) pack_ptr, (int) (pack_ptr - old_pack_ptr))); } @@ -150,13 +150,20 @@ pack_row(TABLE *table, MY_BITMAP const* cols, the various member functions of Field and subclasses expect to write. - The row is assumed to only consist of the fields for which the corresponding - bit in bitset @c cols is set; the other parts of the record are left alone. + The row is assumed to only consist of the fields for which the + corresponding bit in bitset @c cols is set; the other parts of the + record are left alone. At most @c colcnt columns are read: if the table is larger than that, the remaining fields are not filled in. - @param rli Relay log info + @note The relay log information can be NULL, which means that no + checking or comparison with the source table is done, simply + because it is not used. This feature is used by MySQL Backup to + unpack a row from from the backup image, but can be used for other + purposes as well. + + @param rli Relay log info, which can be NULL @param table Table to unpack into @param colcnt Number of columns to read from record @param row_data @@ -170,10 +177,8 @@ pack_row(TABLE *table, MY_BITMAP const* cols, @retval 0 No error - @retval ER_NO_DEFAULT_FOR_FIELD - Returned if one of the fields existing on the slave but not on the - master does not have a default value (and isn't nullable) - + @retval HA_ERR_GENERIC + A generic, internal, error caused the unpacking to fail. */ #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) int @@ -185,6 +190,7 @@ unpack_row(Relay_log_info const *rli, { DBUG_ENTER("unpack_row"); DBUG_ASSERT(row_data); + DBUG_ASSERT(table); size_t const master_null_byte_count= (bitmap_bits_set(cols) + 7) / 8; int error= 0; @@ -202,10 +208,37 @@ unpack_row(Relay_log_info const *rli, // The "current" null bits unsigned int null_bits= *null_ptr++; uint i= 0; - table_def *tabledef= ((Relay_log_info*)rli)->get_tabledef(table); + table_def *tabledef= NULL; + TABLE *conv_table= NULL; + bool table_found= rli && rli->get_table_data(table, &tabledef, &conv_table); + DBUG_PRINT("debug", ("Table data: table_found: %d, tabldef: %p, conv_table: %p", + table_found, tabledef, conv_table)); + DBUG_ASSERT(table_found); + + /* + If rli is NULL it means that there is no source table and that the + row shall just be unpacked without doing any checks. This feature + is used by MySQL Backup, but can be used for other purposes as + well. + */ + if (rli && !table_found) + DBUG_RETURN(HA_ERR_GENERIC); + for (field_ptr= begin_ptr ; field_ptr < end_ptr && *field_ptr ; ++field_ptr) { - Field *const f= *field_ptr; + /* + If there is a conversion table, we pick up the field pointer to + the conversion table. If the conversion table or the field + pointer is NULL, no conversions are necessary. + */ + Field *conv_field= + conv_table ? conv_table->field[field_ptr - begin_ptr] : NULL; + Field *const f= + conv_field ? conv_field : *field_ptr; + DBUG_PRINT("debug", ("Conversion %srequired for field '%s' (#%ld)", + conv_field ? "" : "not ", + (*field_ptr)->field_name, field_ptr - begin_ptr)); + DBUG_ASSERT(f != NULL); /* No need to bother about columns that does not exist: they have @@ -291,6 +324,39 @@ unpack_row(Relay_log_info const *rli, (int) (pack_ptr - old_pack_ptr))); } + /* + If conv_field is set, then we are doing a conversion. In this + case, we have unpacked the master data to the conversion + table, so we need to copy the value stored in the conversion + table into the final table and do the conversion at the same time. + */ + if (conv_field) + { + Copy_field copy; +#ifndef DBUG_OFF + char source_buf[MAX_FIELD_WIDTH]; + char value_buf[MAX_FIELD_WIDTH]; + String source_type(source_buf, sizeof(source_buf), system_charset_info); + String value_string(value_buf, sizeof(value_buf), system_charset_info); + conv_field->sql_type(source_type); + conv_field->val_str(&value_string); + DBUG_PRINT("debug", ("Copying field '%s' of type '%s' with value '%s'", + (*field_ptr)->field_name, + source_type.c_ptr_safe(), value_string.c_ptr_safe())); +#endif + copy.set(*field_ptr, f, TRUE); + (*copy.do_copy)(©); +#ifndef DBUG_OFF + char target_buf[MAX_FIELD_WIDTH]; + String target_type(target_buf, sizeof(target_buf), system_charset_info); + (*field_ptr)->sql_type(target_type); + (*field_ptr)->val_str(&value_string); + DBUG_PRINT("debug", ("Value of field '%s' of type '%s' is now '%s'", + (*field_ptr)->field_name, + target_type.c_ptr_safe(), value_string.c_ptr_safe())); +#endif + } + null_mask <<= 1; } i++; diff --git a/sql/rpl_reporting.cc b/sql/rpl_reporting.cc index a09140de3c4..ae9d100eeb4 100644 --- a/sql/rpl_reporting.cc +++ b/sql/rpl_reporting.cc @@ -1,7 +1,29 @@ +/* Copyright (C) 2008-2009 Sun Microsystems, Inc + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #include "mysql_priv.h" #include "rpl_reporting.h" +Slave_reporting_capability::Slave_reporting_capability(char const *thread_name) + : m_thread_name(thread_name) +{ + mysql_mutex_init(key_mutex_slave_reporting_capability_err_lock, + &err_lock, MY_MUTEX_INIT_FAST); +} + void Slave_reporting_capability::report(loglevel level, int err_code, const char *msg, ...) const @@ -13,7 +35,7 @@ Slave_reporting_capability::report(loglevel level, int err_code, va_list args; va_start(args, msg); - pthread_mutex_lock(&err_lock); + mysql_mutex_lock(&err_lock); switch (level) { case ERROR_LEVEL: @@ -39,7 +61,7 @@ Slave_reporting_capability::report(loglevel level, int err_code, my_vsnprintf(pbuff, pbuffsize, msg, args); - pthread_mutex_unlock(&err_lock); + mysql_mutex_unlock(&err_lock); va_end(args); /* If the msg string ends with '.', do not add a ',' it would be ugly */ @@ -51,5 +73,5 @@ Slave_reporting_capability::report(loglevel level, int err_code, Slave_reporting_capability::~Slave_reporting_capability() { - pthread_mutex_destroy(&err_lock); + mysql_mutex_destroy(&err_lock); } diff --git a/sql/rpl_reporting.h b/sql/rpl_reporting.h index ce33407e516..b8d9c049653 100644 --- a/sql/rpl_reporting.h +++ b/sql/rpl_reporting.h @@ -1,6 +1,21 @@ #ifndef RPL_REPORTING_H #define RPL_REPORTING_H +/* Copyright (C) 2008-2009 Sun Microsystems, Inc + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + /** Maximum size of an error message from a slave thread. */ @@ -17,17 +32,13 @@ class Slave_reporting_capability { public: /** lock used to synchronize m_last_error on 'SHOW SLAVE STATUS' **/ - mutable pthread_mutex_t err_lock; + mutable mysql_mutex_t err_lock; /** Constructor. @param thread_name Printable name of the slave thread that is reporting. */ - Slave_reporting_capability(char const *thread_name) - : m_thread_name(thread_name) - { - pthread_mutex_init(&err_lock, MY_MUTEX_INIT_FAST); - } + Slave_reporting_capability(char const *thread_name); /** Writes a message and, if it's an error message, to Last_Error @@ -47,9 +58,9 @@ public: STATUS</code>. */ void clear_error() { - pthread_mutex_lock(&err_lock); + mysql_mutex_lock(&err_lock); m_last_error.clear(); - pthread_mutex_unlock(&err_lock); + mysql_mutex_unlock(&err_lock); } /** diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index fa979fe9a21..1b3c25dfda2 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -54,13 +54,15 @@ Relay_log_info::Relay_log_info(bool is_slave_recovery) bzero((char*) &info_file, sizeof(info_file)); bzero((char*) &cache_buf, sizeof(cache_buf)); cached_charset_invalidate(); - pthread_mutex_init(&run_lock, MY_MUTEX_INIT_FAST); - pthread_mutex_init(&data_lock, MY_MUTEX_INIT_FAST); - pthread_mutex_init(&log_space_lock, MY_MUTEX_INIT_FAST); - pthread_cond_init(&data_cond, NULL); - pthread_cond_init(&start_cond, NULL); - pthread_cond_init(&stop_cond, NULL); - pthread_cond_init(&log_space_cond, NULL); + mysql_mutex_init(key_relay_log_info_run_lock, &run_lock, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_relay_log_info_data_lock, + &data_lock, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_relay_log_info_log_space_lock, + &log_space_lock, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_relay_log_info_data_cond, &data_cond, NULL); + mysql_cond_init(key_relay_log_info_start_cond, &start_cond, NULL); + mysql_cond_init(key_relay_log_info_stop_cond, &stop_cond, NULL); + mysql_cond_init(key_relay_log_info_log_space_cond, &log_space_cond, NULL); relay_log.init_pthread_objects(); DBUG_VOID_RETURN; } @@ -70,13 +72,13 @@ Relay_log_info::~Relay_log_info() { DBUG_ENTER("Relay_log_info::~Relay_log_info"); - pthread_mutex_destroy(&run_lock); - pthread_mutex_destroy(&data_lock); - pthread_mutex_destroy(&log_space_lock); - pthread_cond_destroy(&data_cond); - pthread_cond_destroy(&start_cond); - pthread_cond_destroy(&stop_cond); - pthread_cond_destroy(&log_space_cond); + mysql_mutex_destroy(&run_lock); + mysql_mutex_destroy(&data_lock); + mysql_mutex_destroy(&log_space_lock); + mysql_cond_destroy(&data_cond); + mysql_cond_destroy(&start_cond); + mysql_cond_destroy(&stop_cond); + mysql_cond_destroy(&log_space_cond); relay_log.cleanup(); DBUG_VOID_RETURN; } @@ -95,7 +97,7 @@ int init_relay_log_info(Relay_log_info* rli, if (rli->inited) // Set if this function called DBUG_RETURN(0); fn_format(fname, info_fname, mysql_data_home, "", 4+32); - pthread_mutex_lock(&rli->data_lock); + mysql_mutex_lock(&rli->data_lock); info_fd = rli->info_fd; rli->cur_log_fd = -1; rli->slave_skip_counter=0; @@ -110,7 +112,7 @@ int init_relay_log_info(Relay_log_info* rli, if (fn_format(pattern, PREFIX_SQL_LOAD, pattern, "", MY_SAFE_PATH | MY_RETURN_REAL_PATH) == NullS) { - pthread_mutex_unlock(&rli->data_lock); + mysql_mutex_unlock(&rli->data_lock); sql_print_error("Unable to use slave's temporary directory %s", slave_load_tmpdir); DBUG_RETURN(1); @@ -139,7 +141,7 @@ int init_relay_log_info(Relay_log_info* rli, if (opt_relay_logname && opt_relay_logname[strlen(opt_relay_logname) - 1] == FN_LIBCHAR) { - pthread_mutex_unlock(&rli->data_lock); + mysql_mutex_unlock(&rli->data_lock); sql_print_error("Path '%s' is a directory name, please specify \ a file name for --relay-log option", opt_relay_logname); DBUG_RETURN(1); @@ -151,7 +153,7 @@ a file name for --relay-log option", opt_relay_logname); opt_relaylog_index_name[strlen(opt_relaylog_index_name) - 1] == FN_LIBCHAR) { - pthread_mutex_unlock(&rli->data_lock); + mysql_mutex_unlock(&rli->data_lock); sql_print_error("Path '%s' is a directory name, please specify \ a file name for --relay-log-index option", opt_relaylog_index_name); DBUG_RETURN(1); @@ -188,7 +190,7 @@ a file name for --relay-log-index option", opt_relaylog_index_name); (max_relay_log_size ? max_relay_log_size : max_binlog_size), 1, TRUE)) { - pthread_mutex_unlock(&rli->data_lock); + mysql_mutex_unlock(&rli->data_lock); sql_print_error("Failed in open_log() called from init_relay_log_info()"); DBUG_RETURN(1); } @@ -203,8 +205,9 @@ a file name for --relay-log-index option", opt_relaylog_index_name); the old descriptor and re-create the old file */ if (info_fd >= 0) - my_close(info_fd, MYF(MY_WME)); - if ((info_fd = my_open(fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0) + mysql_file_close(info_fd, MYF(MY_WME)); + if ((info_fd= mysql_file_open(key_file_relay_log_info, + fname, O_CREAT|O_RDWR|O_BINARY, MYF(MY_WME))) < 0) { sql_print_error("Failed to create a new relay log info file (\ file '%s', errno %d)", fname, my_errno); @@ -238,7 +241,8 @@ file '%s', errno %d)", fname, my_errno); else { int error=0; - if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) + if ((info_fd= mysql_file_open(key_file_relay_log_info, + fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) { sql_print_error("\ Failed to open the existing relay log info file '%s' (errno %d)", @@ -255,10 +259,10 @@ Failed to open the existing relay log info file '%s' (errno %d)", if (error) { if (info_fd >= 0) - my_close(info_fd, MYF(0)); + mysql_file_close(info_fd, MYF(0)); rli->info_fd= -1; rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT); - pthread_mutex_unlock(&rli->data_lock); + mysql_mutex_unlock(&rli->data_lock); DBUG_RETURN(1); } } @@ -327,17 +331,17 @@ Failed to open the existing relay log info file '%s' (errno %d)", goto err; } rli->inited= 1; - pthread_mutex_unlock(&rli->data_lock); + mysql_mutex_unlock(&rli->data_lock); DBUG_RETURN(error); err: sql_print_error("%s", msg); end_io_cache(&rli->info_file); if (info_fd >= 0) - my_close(info_fd, MYF(0)); + mysql_file_close(info_fd, MYF(0)); rli->info_fd= -1; rli->relay_log.close(LOG_CLOSE_INDEX | LOG_CLOSE_STOP_EVENT); - pthread_mutex_unlock(&rli->data_lock); + mysql_mutex_unlock(&rli->data_lock); DBUG_RETURN(1); } @@ -346,7 +350,8 @@ static inline int add_relay_log(Relay_log_info* rli,LOG_INFO* linfo) { MY_STAT s; DBUG_ENTER("add_relay_log"); - if (!my_stat(linfo->log_file_name,&s,MYF(0))) + if (!mysql_file_stat(key_file_binlog, + linfo->log_file_name, &s, MYF(0))) { sql_print_error("log %s listed in the index, but failed to stat", linfo->log_file_name); @@ -446,10 +451,10 @@ int init_relay_log_pos(Relay_log_info* rli,const char* log, DBUG_PRINT("info", ("pos: %lu", (ulong) pos)); *errmsg=0; - pthread_mutex_t *log_lock=rli->relay_log.get_log_lock(); + mysql_mutex_t *log_lock= rli->relay_log.get_log_lock(); if (need_data_lock) - pthread_mutex_lock(&rli->data_lock); + mysql_mutex_lock(&rli->data_lock); /* Slave threads are not the only users of init_relay_log_pos(). CHANGE MASTER @@ -469,13 +474,13 @@ int init_relay_log_pos(Relay_log_info* rli,const char* log, rli->relay_log.description_event_for_exec= new Format_description_log_event(3); - pthread_mutex_lock(log_lock); + mysql_mutex_lock(log_lock); /* Close log file and free buffers if it's already open */ if (rli->cur_log_fd >= 0) { end_io_cache(&rli->cache_buf); - my_close(rli->cur_log_fd, MYF(MY_WME)); + mysql_file_close(rli->cur_log_fd, MYF(MY_WME)); rli->cur_log_fd = -1; } @@ -609,12 +614,12 @@ err: */ if (!relay_log_purge) rli->log_space_limit= 0; - pthread_cond_broadcast(&rli->data_cond); + mysql_cond_broadcast(&rli->data_cond); - pthread_mutex_unlock(log_lock); + mysql_mutex_unlock(log_lock); if (need_data_lock) - pthread_mutex_unlock(&rli->data_lock); + mysql_mutex_unlock(&rli->data_lock); if (!rli->relay_log.description_event_for_exec->is_valid() && !*errmsg) *errmsg= "Invalid Format_description log event; could be out of memory"; @@ -665,7 +670,7 @@ int Relay_log_info::wait_for_pos(THD* thd, String* log_name, log_name->c_ptr(), (ulong) log_pos, (ulong) timeout)); set_timespec(abstime,timeout); - pthread_mutex_lock(&data_lock); + mysql_mutex_lock(&data_lock); msg= thd->enter_cond(&data_cond, &data_lock, "Waiting for the slave SQL thread to " "advance position"); @@ -778,26 +783,26 @@ int Relay_log_info::wait_for_pos(THD* thd, String* log_name, DBUG_PRINT("info",("Waiting for master update")); /* - We are going to pthread_cond_(timed)wait(); if the SQL thread stops it + We are going to mysql_cond_(timed)wait(); if the SQL thread stops it will wake us up. */ if (timeout > 0) { /* - Note that pthread_cond_timedwait checks for the timeout + Note that mysql_cond_timedwait checks for the timeout before for the condition ; i.e. it returns ETIMEDOUT if the system time equals or exceeds the time specified by abstime before the condition variable is signaled or broadcast, _or_ if the absolute time specified by abstime has already passed at the time of the call. - For that reason, pthread_cond_timedwait will do the "timeoutting" job + For that reason, mysql_cond_timedwait will do the "timeoutting" job even if its condition is always immediately signaled (case of a loaded master). */ - error=pthread_cond_timedwait(&data_cond, &data_lock, &abstime); + error= mysql_cond_timedwait(&data_cond, &data_lock, &abstime); } else - pthread_cond_wait(&data_cond, &data_lock); + mysql_cond_wait(&data_cond, &data_lock); DBUG_PRINT("info",("Got signal of master update or timed out")); if (error == ETIMEDOUT || error == ETIME) { @@ -833,7 +838,7 @@ void Relay_log_info::inc_group_relay_log_pos(ulonglong log_pos, DBUG_ENTER("Relay_log_info::inc_group_relay_log_pos"); if (!skip_lock) - pthread_mutex_lock(&data_lock); + mysql_mutex_lock(&data_lock); inc_event_relay_log_pos(); group_relay_log_pos= event_relay_log_pos; strmake(group_relay_log_name,event_relay_log_name, @@ -877,9 +882,9 @@ void Relay_log_info::inc_group_relay_log_pos(ulonglong log_pos, { group_master_log_pos= log_pos; } - pthread_cond_broadcast(&data_cond); + mysql_cond_broadcast(&data_cond); if (!skip_lock) - pthread_mutex_unlock(&data_lock); + mysql_mutex_unlock(&data_lock); DBUG_VOID_RETURN; } @@ -948,7 +953,7 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset, DBUG_ASSERT(rli->mi->slave_running == 0); rli->slave_skip_counter=0; - pthread_mutex_lock(&rli->data_lock); + mysql_mutex_lock(&rli->data_lock); /* we close the relay log fd possibly left open by the slave SQL thread, @@ -959,7 +964,7 @@ int purge_relay_logs(Relay_log_info* rli, THD *thd, bool just_reset, if (rli->cur_log_fd >= 0) { end_io_cache(&rli->cache_buf); - my_close(rli->cur_log_fd, MYF(MY_WME)); + mysql_file_close(rli->cur_log_fd, MYF(MY_WME)); rli->cur_log_fd= -1; } @@ -991,7 +996,7 @@ err: char buf[22]; #endif DBUG_PRINT("info",("log_space_total: %s",llstr(rli->log_space_total,buf))); - pthread_mutex_unlock(&rli->data_lock); + mysql_mutex_unlock(&rli->data_lock); DBUG_RETURN(error); } @@ -1043,7 +1048,7 @@ bool Relay_log_info::is_until_satisfied(THD *thd, Log_event *ev) DBUG_RETURN(FALSE); log_name= group_master_log_name; log_pos= (!ev)? group_master_log_pos : - ((thd->options & OPTION_BEGIN || !ev->log_pos) ? + ((thd->variables.option_bits & OPTION_BEGIN || !ev->log_pos) ? group_master_log_pos : ev->log_pos - ev->data_written); } else @@ -1168,7 +1173,7 @@ void Relay_log_info::stmt_done(my_off_t event_master_log_pos, middle of the "transaction". START SLAVE will resume at BEGIN while the MyISAM table has already been updated. */ - if ((sql_thd->options & OPTION_BEGIN) && opt_using_transactions) + if ((sql_thd->variables.option_bits & OPTION_BEGIN) && opt_using_transactions) inc_event_relay_log_pos(); else { @@ -1221,8 +1226,8 @@ void Relay_log_info::cleanup_context(THD *thd, bool error) /* Cleanup for the flags that have been set at do_apply_event. */ - thd->options&= ~OPTION_NO_FOREIGN_KEY_CHECKS; - thd->options&= ~OPTION_RELAXED_UNIQUE_CHECKS; + thd->variables.option_bits&= ~OPTION_NO_FOREIGN_KEY_CHECKS; + thd->variables.option_bits&= ~OPTION_RELAXED_UNIQUE_CHECKS; DBUG_VOID_RETURN; } diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index 60b55533926..54b5c9c30b2 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 MySQL AB +/* Copyright (C) 2005 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,6 +22,7 @@ struct RPL_TABLE_LIST; class Master_info; +extern uint sql_slave_skip_counter; /**************************************************************************** @@ -122,17 +123,17 @@ public: TABLE *save_temporary_tables; /* - standard lock acquistion order to avoid deadlocks: + standard lock acquisition order to avoid deadlocks: run_lock, data_lock, relay_log.LOCK_log, relay_log.LOCK_index */ - pthread_mutex_t data_lock,run_lock; + mysql_mutex_t data_lock, run_lock; /* start_cond is broadcast when SQL thread is started stop_cond - when stopped data_cond - when data protected by data_lock changes */ - pthread_cond_t start_cond, stop_cond, data_cond; + mysql_cond_t start_cond, stop_cond, data_cond; /* parent Master_info structure */ Master_info *mi; @@ -214,15 +215,21 @@ public: volatile uint32 slave_skip_counter; volatile ulong abort_pos_wait; /* Incremented on change master */ volatile ulong slave_run_id; /* Incremented on slave start */ - pthread_mutex_t log_space_lock; - pthread_cond_t log_space_cond; + mysql_mutex_t log_space_lock; + mysql_cond_t log_space_cond; THD * sql_thd; #ifndef DBUG_OFF int events_till_abort; #endif - /* if not set, the value of other members of the structure are undefined */ - bool inited; + /* + inited changes its value within LOCK_active_mi-guarded critical + sections at times of start_slave_threads() (0->1) and end_slave() (1->0). + Readers may not acquire the mutex while they realize potential concurrency + issue. + If not set, the value of other members of the structure are undefined. + */ + volatile bool inited; volatile bool abort_slave; volatile uint slave_running; @@ -327,13 +334,21 @@ public: uint tables_to_lock_count; /* RBR: Count of tables to lock */ table_mapping m_table_map; /* RBR: Mapping table-id to table */ - inline table_def *get_tabledef(TABLE *tbl) + bool get_table_data(TABLE *table_arg, table_def **tabledef_var, TABLE **conv_table_var) const { - table_def *td= 0; - for (TABLE_LIST *ptr= tables_to_lock; ptr && !td; ptr= ptr->next_global) - if (ptr->table == tbl) - td= &((RPL_TABLE_LIST *)ptr)->m_tabledef; - return (td); + DBUG_ASSERT(tabledef_var && conv_table_var); + for (TABLE_LIST *ptr= tables_to_lock ; ptr != NULL ; ptr= ptr->next_global) + if (ptr->table == table_arg) + { + *tabledef_var= &static_cast<RPL_TABLE_LIST*>(ptr)->m_tabledef; + *conv_table_var= static_cast<RPL_TABLE_LIST*>(ptr)->m_conv_table; + DBUG_PRINT("debug", ("Fetching table data for table %s.%s:" + " tabledef: %p, conv_table: %p", + table_arg->s->db.str, table_arg->s->table_name.str, + *tabledef_var, *conv_table_var)); + return true; + } + return false; } /* @@ -420,7 +435,7 @@ public: @retval false Replication thread is currently not inside a group */ bool is_in_group() const { - return (sql_thd->options & OPTION_BEGIN) || + return (sql_thd->variables.option_bits & OPTION_BEGIN) || (m_flags & (1UL << IN_STMT)); } diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc index e34f8561051..feb35527b62 100644 --- a/sql/rpl_utility.cc +++ b/sql/rpl_utility.cc @@ -14,8 +14,176 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "rpl_utility.h" + +#ifndef MYSQL_CLIENT #include "rpl_rli.h" +/** + Function to compare two size_t integers for their relative + order. Used below. + */ +int compare(size_t a, size_t b) +{ + if (a < b) + return -1; + if (b < a) + return 1; + return 0; +} + + +/** + Max value for an unsigned integer of 'bits' bits. + + The somewhat contorted expression is to avoid overflow. + */ +uint32 uint_max(int bits) { + return (((1UL << (bits - 1)) - 1) << 1) | 1; +} + + +/** + Compute the maximum display length of a field. + + @param sql_type Type of the field + @param metadata The metadata from the master for the field. + @return Maximum length of the field in bytes. + */ +static uint32 +max_display_length_for_field(enum_field_types sql_type, unsigned int metadata) +{ + DBUG_PRINT("debug", ("sql_type: %d, metadata: 0x%x", sql_type, metadata)); + DBUG_ASSERT(metadata >> 16 == 0); + + switch (sql_type) { + case MYSQL_TYPE_NEWDECIMAL: + return metadata >> 8; + + case MYSQL_TYPE_FLOAT: + return 12; + + case MYSQL_TYPE_DOUBLE: + return 22; + + case MYSQL_TYPE_SET: + case MYSQL_TYPE_ENUM: + return metadata & 0x00ff; + + case MYSQL_TYPE_STRING: + { + uchar type= metadata >> 8; + if (type == MYSQL_TYPE_SET || type == MYSQL_TYPE_ENUM) + return metadata & 0xff; + else + /* This is taken from Field_string::unpack. */ + return (((metadata >> 4) & 0x300) ^ 0x300) + (metadata & 0x00ff); + } + + case MYSQL_TYPE_YEAR: + case MYSQL_TYPE_TINY: + return 4; + + case MYSQL_TYPE_SHORT: + return 6; + + case MYSQL_TYPE_INT24: + return 9; + + case MYSQL_TYPE_LONG: + return 11; + +#ifdef HAVE_LONG_LONG + case MYSQL_TYPE_LONGLONG: + return 20; + +#endif + case MYSQL_TYPE_NULL: + return 0; + + case MYSQL_TYPE_NEWDATE: + return 3; + + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_TIME: + return 3; + + case MYSQL_TYPE_TIMESTAMP: + return 4; + + case MYSQL_TYPE_DATETIME: + return 8; + + case MYSQL_TYPE_BIT: + /* + Decode the size of the bit field from the master. + */ + DBUG_ASSERT((metadata & 0xff) <= 7); + return 8 * (metadata >> 8U) + (metadata & 0x00ff); + + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_VARCHAR: + return metadata; + + /* + The actual length for these types does not really matter since + they are used to calc_pack_length, which ignores the given + length for these types. + + Since we want this to be accurate for other uses, we return the + maximum size in bytes of these BLOBs. + */ + + case MYSQL_TYPE_TINY_BLOB: + return uint_max(1 * 8); + + case MYSQL_TYPE_MEDIUM_BLOB: + return uint_max(3 * 8); + + case MYSQL_TYPE_BLOB: + /* + For the blob type, Field::real_type() lies and say that all + blobs are of type MYSQL_TYPE_BLOB. In that case, we have to look + at the length instead to decide what the max display size is. + */ + return uint_max(metadata * 8); + + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_GEOMETRY: + return uint_max(4 * 8); + + default: + return ~(uint32) 0; + } +} + + +/* + Compare the pack lengths of a source field (on the master) and a + target field (on the slave). + + @param field Target field. + @param type Source field type. + @param metadata Source field metadata. + + @retval -1 The length of the source field is smaller than the target field. + @retval 0 The length of the source and target fields are the same. + @retval 1 The length of the source field is greater than the target field. + */ +int compare_lengths(Field *field, enum_field_types source_type, uint16 metadata) +{ + DBUG_ENTER("compare_lengths"); + size_t const source_length= + max_display_length_for_field(source_type, metadata); + size_t const target_length= field->max_display_length(); + DBUG_PRINT("debug", ("source_length: %lu, source_type: %u," + " target_length: %lu, target_type: %u", + (unsigned long) source_length, source_type, + (unsigned long) target_length, field->real_type())); + int result= compare(source_length, target_length); + DBUG_PRINT("result", ("%d", result)); + DBUG_RETURN(result); +} + /********************************************************************* * table_def member definitions * *********************************************************************/ @@ -169,58 +337,718 @@ uint32 table_def::calc_field_size(uint col, uchar *master_data) const return length; } -/* + +/** + */ +void show_sql_type(enum_field_types type, uint16 metadata, String *str) +{ + DBUG_ENTER("show_sql_type"); + DBUG_PRINT("enter", ("type: %d, metadata: 0x%x", type, metadata)); + + switch (type) + { + case MYSQL_TYPE_TINY: + str->set_ascii(STRING_WITH_LEN("tinyint")); + break; + + case MYSQL_TYPE_SHORT: + str->set_ascii(STRING_WITH_LEN("smallint")); + break; + + case MYSQL_TYPE_LONG: + str->set_ascii(STRING_WITH_LEN("int")); + break; + + case MYSQL_TYPE_FLOAT: + str->set_ascii(STRING_WITH_LEN("float")); + break; + + case MYSQL_TYPE_DOUBLE: + str->set_ascii(STRING_WITH_LEN("double")); + break; + + case MYSQL_TYPE_NULL: + str->set_ascii(STRING_WITH_LEN("null")); + break; + + case MYSQL_TYPE_TIMESTAMP: + str->set_ascii(STRING_WITH_LEN("timestamp")); + break; + + case MYSQL_TYPE_LONGLONG: + str->set_ascii(STRING_WITH_LEN("bigint")); + break; + + case MYSQL_TYPE_INT24: + str->set_ascii(STRING_WITH_LEN("mediumint")); + break; + + case MYSQL_TYPE_NEWDATE: + case MYSQL_TYPE_DATE: + str->set_ascii(STRING_WITH_LEN("date")); + break; + + case MYSQL_TYPE_TIME: + str->set_ascii(STRING_WITH_LEN("time")); + break; + + case MYSQL_TYPE_DATETIME: + str->set_ascii(STRING_WITH_LEN("datetime")); + break; + + case MYSQL_TYPE_YEAR: + str->set_ascii(STRING_WITH_LEN("year")); + break; + + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_VARCHAR: + { + CHARSET_INFO *cs= str->charset(); + uint32 length= + cs->cset->snprintf(cs, (char*) str->ptr(), str->alloced_length(), + "varchar(%u)", metadata); + str->length(length); + } + break; + + case MYSQL_TYPE_BIT: + { + CHARSET_INFO *cs= str->charset(); + int bit_length= 8 * (metadata >> 8) + (metadata & 0xFF); + uint32 length= + cs->cset->snprintf(cs, (char*) str->ptr(), str->alloced_length(), + "bit(%d)", bit_length); + str->length(length); + } + break; + + case MYSQL_TYPE_DECIMAL: + { + CHARSET_INFO *cs= str->charset(); + uint32 length= + cs->cset->snprintf(cs, (char*) str->ptr(), str->alloced_length(), + "decimal(%d,?)", metadata); + str->length(length); + } + break; + + case MYSQL_TYPE_NEWDECIMAL: + { + CHARSET_INFO *cs= str->charset(); + uint32 length= + cs->cset->snprintf(cs, (char*) str->ptr(), str->alloced_length(), + "decimal(%d,%d)", metadata >> 8, metadata & 0xff); + str->length(length); + } + break; + + case MYSQL_TYPE_ENUM: + str->set_ascii(STRING_WITH_LEN("enum")); + break; + + case MYSQL_TYPE_SET: + str->set_ascii(STRING_WITH_LEN("set")); + break; + + case MYSQL_TYPE_BLOB: + /* + Field::real_type() lies regarding the actual type of a BLOB, so + it is necessary to check the pack length to figure out what kind + of blob it really is. + */ + switch (get_blob_type_from_length(metadata)) + { + case MYSQL_TYPE_TINY_BLOB: + str->set_ascii(STRING_WITH_LEN("tinyblob")); + break; + + case MYSQL_TYPE_MEDIUM_BLOB: + str->set_ascii(STRING_WITH_LEN("mediumblob")); + break; + + case MYSQL_TYPE_LONG_BLOB: + str->set_ascii(STRING_WITH_LEN("longblob")); + break; + + case MYSQL_TYPE_BLOB: + str->set_ascii(STRING_WITH_LEN("blob")); + break; + + default: + DBUG_ASSERT(0); + break; + } + break; + + case MYSQL_TYPE_STRING: + { + /* + This is taken from Field_string::unpack. + */ + CHARSET_INFO *cs= str->charset(); + uint bytes= (((metadata >> 4) & 0x300) ^ 0x300) + (metadata & 0x00ff); + uint32 length= + cs->cset->snprintf(cs, (char*) str->ptr(), str->alloced_length(), + "char(%d)", bytes / cs->mbmaxlen); + str->length(length); + } + break; + + case MYSQL_TYPE_GEOMETRY: + str->set_ascii(STRING_WITH_LEN("geometry")); + break; + + default: + str->set_ascii(STRING_WITH_LEN("<unknown type>")); + } + DBUG_VOID_RETURN; +} + + +/** + Check the order variable and print errors if the order is not + acceptable according to the current settings. + + @param order The computed order of the conversion needed. + @param rli The relay log info data structure: for error reporting. + */ +bool is_conversion_ok(int order, Relay_log_info *rli) +{ + DBUG_ENTER("is_conversion_ok"); + bool allow_non_lossy= + bit_is_set(slave_type_conversions_options, SLAVE_TYPE_CONVERSIONS_ALL_NON_LOSSY); + bool allow_lossy= + bit_is_set(slave_type_conversions_options, SLAVE_TYPE_CONVERSIONS_ALL_LOSSY); + + DBUG_PRINT("enter", ("order: %d, flags:%s%s", order, + allow_non_lossy ? " ALL_NON_LOSSY" : "", + allow_lossy ? " ALL_LOSSY" : "")); + if (order < 0 && !allow_non_lossy) + { + /* !!! Add error message saying that non-lossy conversions need to be allowed. */ + DBUG_RETURN(false); + } + + if (order > 0 && !allow_lossy) + { + /* !!! Add error message saying that lossy conversions need to be allowed. */ + DBUG_RETURN(false); + } + + DBUG_RETURN(true); +} + + +/** + Can a type potentially be converted to another type? + + This function check if the types are convertible and what + conversion is required. + + If conversion is not possible, and error is printed. + + If conversion is possible: + + - *order will be set to -1 if source type is smaller than target + type and a non-lossy conversion can be required. This includes + the case where the field types are different but types could + actually be converted in either direction. + + - *order will be set to 0 if no conversion is required. + + - *order will be set to 1 if the source type is strictly larger + than the target type and that conversion is potentially lossy. + + @param[in] field Target field + @param[in] type Source field type + @param[in] metadata Source field metadata + @param[in] rli Relay log info (for error reporting) + @param[in] mflags Flags from the table map event + @param[out] order Order between source field and target field + + @return @c true if conversion is possible according to the current + settings, @c false if conversion is not possible according to the + current setting. + */ +static bool +can_convert_field_to(Field *field, + enum_field_types source_type, uint16 metadata, + Relay_log_info *rli, uint16 mflags, + int *order_var) +{ + DBUG_ENTER("can_convert_field_to"); +#ifndef DBUG_OFF + char field_type_buf[MAX_FIELD_WIDTH]; + String field_type(field_type_buf, sizeof(field_type_buf), field->charset()); + field->sql_type(field_type); + DBUG_PRINT("enter", ("field_type: %s, target_type: %d, source_type: %d, source_metadata: 0x%x", + field_type.c_ptr_safe(), field->real_type(), source_type, metadata)); +#endif + /* + If the real type is the same, we need to check the metadata to + decide if conversions are allowed. + */ + if (field->real_type() == source_type) + { + if (metadata == 0) // Metadata can only be zero if no metadata was provided + { + /* + If there is no metadata, we either have an old event where no + metadata were supplied, or a type that does not require any + metadata. In either case, conversion can be done but no + conversion table is necessary. + */ + DBUG_PRINT("debug", ("Base types are identical, but there is no metadata")); + *order_var= 0; + DBUG_RETURN(true); + } + + DBUG_PRINT("debug", ("Base types are identical, doing field size comparison")); + if (field->compatible_field_size(metadata, rli, mflags, order_var)) + DBUG_RETURN(is_conversion_ok(*order_var, rli)); + else + DBUG_RETURN(false); + } + else if (!slave_type_conversions_options) + DBUG_RETURN(false); + + /* + Here, from and to will always be different. Since the types are + different, we cannot use the compatible_field_size() function, but + have to rely on hard-coded max-sizes for fields. + */ + + DBUG_PRINT("debug", ("Base types are different, checking conversion")); + switch (source_type) // Source type (on master) + { + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + switch (field->real_type()) + { + case MYSQL_TYPE_NEWDECIMAL: + /* + Then the other type is either FLOAT, DOUBLE, or old style + DECIMAL, so we require lossy conversion. + */ + *order_var= 1; + DBUG_RETURN(is_conversion_ok(*order_var, rli)); + + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + { + if (source_type == MYSQL_TYPE_NEWDECIMAL || + source_type == MYSQL_TYPE_DECIMAL) + *order_var = 1; // Always require lossy conversions + else + *order_var= compare_lengths(field, source_type, metadata); + DBUG_ASSERT(*order_var != 0); + DBUG_RETURN(is_conversion_ok(*order_var, rli)); + } + + default: + DBUG_RETURN(false); + } + break; + + /* + The length comparison check will do the correct job of comparing + the field lengths (in bytes) of two integer types. + */ + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_LONGLONG: + switch (field->real_type()) + { + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_INT24: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_LONGLONG: + *order_var= compare_lengths(field, source_type, metadata); + DBUG_ASSERT(*order_var != 0); + DBUG_RETURN(is_conversion_ok(*order_var, rli)); + + default: + DBUG_RETURN(false); + } + break; + + /* + Since source and target type is different, and it is not possible + to convert bit types to anything else, this will return false. + */ + case MYSQL_TYPE_BIT: + DBUG_RETURN(false); + + /* + If all conversions are disabled, it is not allowed to convert + between these types. Since the TEXT vs. BINARY is distinguished by + the charset, and the charset is not replicated, we cannot + currently distinguish between , e.g., TEXT and BLOB. + */ + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_VARCHAR: + switch (field->real_type()) + { + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_VARCHAR: + *order_var= compare_lengths(field, source_type, metadata); + /* + Here we know that the types are different, so if the order + gives that they do not require any conversion, we still need + to have non-lossy conversion enabled to allow conversion + between different (string) types of the same length. + */ + if (*order_var == 0) + *order_var= -1; + DBUG_RETURN(is_conversion_ok(*order_var, rli)); + + default: + DBUG_RETURN(false); + } + break; + + case MYSQL_TYPE_GEOMETRY: + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_TIME: + case MYSQL_TYPE_DATETIME: + case MYSQL_TYPE_YEAR: + case MYSQL_TYPE_NEWDATE: + case MYSQL_TYPE_NULL: + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_SET: + DBUG_RETURN(false); + } + DBUG_RETURN(false); // To keep GCC happy +} + + +/** Is the definition compatible with a table? + This function will compare the master table with an existing table + on the slave and see if they are compatible with respect to the + current settings of @c SLAVE_TYPE_CONVERSIONS. + + If the tables are compatible and conversions are required, @c + *tmp_table_var will be set to a virtual temporary table with field + pointers for the fields that require conversions. This allow simple + checking of whether a conversion are to be applied or not. + + If tables are compatible, but no conversions are necessary, @c + *tmp_table_var will be set to NULL. + + @param rli_arg[in] + Relay log info, for error reporting. + + @param table[in] + Table to compare with + + @param tmp_table_var[out] + Virtual temporary table for performing conversions, if necessary. + + @retval true Master table is compatible with slave table. + @retval false Master table is not compatible with slave table. */ -int -table_def::compatible_with(Relay_log_info const *rli_arg, TABLE *table) +bool +table_def::compatible_with(THD *thd, Relay_log_info *rli, + TABLE *table, TABLE **conv_table_var) const { /* We only check the initial columns for the tables. */ uint const cols_to_check= min(table->s->fields, size()); - int error= 0; - Relay_log_info const *rli= const_cast<Relay_log_info*>(rli_arg); - - TABLE_SHARE const *const tsh= table->s; + TABLE *tmp_table= NULL; for (uint col= 0 ; col < cols_to_check ; ++col) { Field *const field= table->field[col]; - if (field->type() != type(col)) - { - DBUG_ASSERT(col < size() && col < tsh->fields); - DBUG_ASSERT(tsh->db.str && tsh->table_name.str); - error= 1; - char buf[256]; - my_snprintf(buf, sizeof(buf), "Column %d type mismatch - " - "received type %d, %s.%s has type %d", - col, type(col), tsh->db.str, tsh->table_name.str, - field->type()); - rli->report(ERROR_LEVEL, ER_BINLOG_ROW_WRONG_TABLE_DEF, - ER(ER_BINLOG_ROW_WRONG_TABLE_DEF), buf); + int order; + if (can_convert_field_to(field, type(col), field_metadata(col), rli, m_flags, &order)) + { + DBUG_PRINT("debug", ("Checking column %d -" + " field '%s' can be converted - order: %d", + col, field->field_name, order)); + DBUG_ASSERT(order >= -1 && order <= 1); + + /* + If order is not 0, a conversion is required, so we need to set + up the conversion table. + */ + if (order != 0 && tmp_table == NULL) + { + /* + This will create the full table with all fields. This is + necessary to ge the correct field lengths for the record. + */ + tmp_table= create_conversion_table(thd, rli, table); + if (tmp_table == NULL) + return false; + /* + Clear all fields up to, but not including, this column. + */ + for (unsigned int i= 0; i < col; ++i) + tmp_table->field[i]= NULL; + } + + if (order == 0 && tmp_table != NULL) + tmp_table->field[col]= NULL; } - /* - Check the slave's field size against that of the master. - */ - if (!error && - !field->compatible_field_size(field_metadata(col), rli_arg)) + else + { + DBUG_PRINT("debug", ("Checking column %d -" + " field '%s' can not be converted", + col, field->field_name)); + DBUG_ASSERT(col < size() && col < table->s->fields); + DBUG_ASSERT(table->s->db.str && table->s->table_name.str); + const char *db_name= table->s->db.str; + const char *tbl_name= table->s->table_name.str; + char source_buf[MAX_FIELD_WIDTH]; + char target_buf[MAX_FIELD_WIDTH]; + String source_type(source_buf, sizeof(source_buf), field->charset()); + String target_type(target_buf, sizeof(target_buf), field->charset()); + show_sql_type(type(col), field_metadata(col), &source_type); + field->sql_type(target_type); + rli->report(ERROR_LEVEL, ER_SLAVE_CONVERSION_FAILED, + ER(ER_SLAVE_CONVERSION_FAILED), + col, db_name, tbl_name, + source_type.c_ptr_safe(), target_type.c_ptr_safe()); + return false; + } + } + +#ifndef DBUG_OFF + if (tmp_table) + { + for (unsigned int col= 0; col < tmp_table->s->fields; ++col) + if (tmp_table->field[col]) + { + char source_buf[MAX_FIELD_WIDTH]; + char target_buf[MAX_FIELD_WIDTH]; + String source_type(source_buf, sizeof(source_buf), table->field[col]->charset()); + String target_type(target_buf, sizeof(target_buf), table->field[col]->charset()); + tmp_table->field[col]->sql_type(source_type); + table->field[col]->sql_type(target_type); + DBUG_PRINT("debug", ("Field %s - conversion required." + " Source type: '%s', Target type: '%s'", + tmp_table->field[col]->field_name, + source_type.c_ptr_safe(), target_type.c_ptr_safe())); + } + } +#endif + + *conv_table_var= tmp_table; + return true; +} + +/** + Create a conversion table. + + If the function is unable to create the conversion table, an error + will be printed and NULL will be returned. + + @return Pointer to conversion table, or NULL if unable to create + conversion table. + */ + +TABLE *table_def::create_conversion_table(THD *thd, Relay_log_info *rli, TABLE *target_table) const +{ + DBUG_ENTER("table_def::create_conversion_table"); + + List<Create_field> field_list; + + for (uint col= 0 ; col < size() ; ++col) + { + Create_field *field_def= + (Create_field*) alloc_root(thd->mem_root, sizeof(Create_field)); + if (field_list.push_back(field_def)) + DBUG_RETURN(NULL); + + uint decimals= 0; + TYPELIB* interval= NULL; + uint pack_length= 0; + uint32 max_length= + max_display_length_for_field(type(col), field_metadata(col)); + + switch(type(col)) + { + int precision; + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_SET: + interval= static_cast<Field_enum*>(target_table->field[col])->typelib; + pack_length= field_metadata(col) & 0x00ff; + break; + + case MYSQL_TYPE_NEWDECIMAL: + /* + The display length of a DECIMAL type is not the same as the + length that should be supplied to make_field, so we correct + the length here. + */ + precision= field_metadata(col) >> 8; + decimals= field_metadata(col) & 0x00ff; + max_length= + my_decimal_precision_to_length(precision, decimals, FALSE); + break; + + case MYSQL_TYPE_DECIMAL: + precision= field_metadata(col); + decimals= static_cast<Field_num*>(target_table->field[col])->dec; + max_length= field_metadata(col); + break; + + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_GEOMETRY: + pack_length= field_metadata(col) & 0x00ff; + break; + + default: + break; + } + + DBUG_PRINT("debug", ("sql_type: %d, target_field: '%s', max_length: %d, decimals: %d," + " maybe_null: %d, unsigned_flag: %d, pack_length: %u", + type(col), target_table->field[col]->field_name, + max_length, decimals, TRUE, FALSE, pack_length)); + field_def->init_for_tmp_table(type(col), + max_length, + decimals, + TRUE, // maybe_null + FALSE, // unsigned_flag + pack_length); + field_def->charset= target_table->field[col]->charset(); + field_def->interval= interval; + } + + TABLE *conv_table= create_virtual_tmp_table(thd, field_list); + if (conv_table == NULL) + rli->report(ERROR_LEVEL, ER_SLAVE_CANT_CREATE_CONVERSION, + ER(ER_SLAVE_CANT_CREATE_CONVERSION), + target_table->s->db.str, + target_table->s->table_name.str); + DBUG_RETURN(conv_table); +} + +#endif /* MYSQL_CLIENT */ + +table_def::table_def(unsigned char *types, ulong size, + uchar *field_metadata, int metadata_size, + uchar *null_bitmap, uint16 flags) + : m_size(size), m_type(0), m_field_metadata_size(metadata_size), + m_field_metadata(0), m_null_bits(0), m_flags(flags), + m_memory(NULL) +{ + m_memory= (uchar *)my_multi_malloc(MYF(MY_WME), + &m_type, size, + &m_field_metadata, + size * sizeof(uint16), + &m_null_bits, (size + 7) / 8, + NULL); + + bzero(m_field_metadata, size * sizeof(uint16)); + + if (m_type) + memcpy(m_type, types, size); + else + m_size= 0; + /* + Extract the data from the table map into the field metadata array + iff there is field metadata. The variable metadata_size will be + 0 if we are replicating from an older version server since no field + metadata was written to the table map. This can also happen if + there were no fields in the master that needed extra metadata. + */ + if (m_size && metadata_size) + { + int index= 0; + for (unsigned int i= 0; i < m_size; i++) { - error= 1; - char buf[256]; - my_snprintf(buf, sizeof(buf), "Column %d size mismatch - " - "master has size %d, %s.%s on slave has size %d." - " Master's column size should be <= the slave's " - "column size.", col, - field->pack_length_from_metadata(m_field_metadata[col]), - tsh->db.str, tsh->table_name.str, - field->row_pack_length()); - rli->report(ERROR_LEVEL, ER_BINLOG_ROW_WRONG_TABLE_DEF, - ER(ER_BINLOG_ROW_WRONG_TABLE_DEF), buf); + switch (m_type[i]) { + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_DOUBLE: + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_GEOMETRY: + { + /* + These types store a single byte. + */ + m_field_metadata[i]= field_metadata[index]; + index++; + break; + } + case MYSQL_TYPE_SET: + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_STRING: + { + uint16 x= field_metadata[index++] << 8U; // real_type + x+= field_metadata[index++]; // pack or field length + m_field_metadata[i]= x; + break; + } + case MYSQL_TYPE_BIT: + { + uint16 x= field_metadata[index++]; + x = x + (field_metadata[index++] << 8U); + m_field_metadata[i]= x; + break; + } + case MYSQL_TYPE_VARCHAR: + { + /* + These types store two bytes. + */ + char *ptr= (char *)&field_metadata[index]; + m_field_metadata[i]= uint2korr(ptr); + index= index + 2; + break; + } + case MYSQL_TYPE_NEWDECIMAL: + { + uint16 x= field_metadata[index++] << 8U; // precision + x+= field_metadata[index++]; // decimals + m_field_metadata[i]= x; + break; + } + default: + m_field_metadata[i]= 0; + break; + } } } + if (m_size && null_bitmap) + memcpy(m_null_bits, null_bitmap, (m_size + 7) / 8); +} + - return error; +table_def::~table_def() +{ + my_free(m_memory, MYF(0)); +#ifndef DBUG_OFF + m_type= 0; + m_size= 0; +#endif } + diff --git a/sql/rpl_utility.h b/sql/rpl_utility.h index d011e9aade8..4b9bf3be93f 100644 --- a/sql/rpl_utility.h +++ b/sql/rpl_utility.h @@ -21,6 +21,7 @@ #endif #include "mysql_priv.h" +#include "mysql_com.h" class Relay_log_info; @@ -32,128 +33,24 @@ class Relay_log_info; - Extract and decode table definition data from the table map event - Check if table definition in table map is compatible with table definition on slave - - Currently, the only field type data available is an array of the - type operators that are present in the table map event. - - @todo Add type operands to this structure to allow detection of - difference between, e.g., BIT(5) and BIT(10). */ class table_def { public: /** - Convenience declaration of the type of the field type data in a - table map event. - */ - typedef unsigned char field_type; - - /** Constructor. - @param types Array of types + @param types Array of types, each stored as a byte @param size Number of elements in array 'types' @param field_metadata Array of extra information about fields @param metadata_size Size of the field_metadata array @param null_bitmap The bitmap of fields that can be null */ - table_def(field_type *types, ulong size, uchar *field_metadata, - int metadata_size, uchar *null_bitmap) - : m_size(size), m_type(0), m_field_metadata_size(metadata_size), - m_field_metadata(0), m_null_bits(0), m_memory(NULL) - { - m_memory= (uchar *)my_multi_malloc(MYF(MY_WME), - &m_type, size, - &m_field_metadata, - size * sizeof(uint16), - &m_null_bits, (size + 7) / 8, - NULL); - - bzero(m_field_metadata, size * sizeof(uint16)); - - if (m_type) - memcpy(m_type, types, size); - else - m_size= 0; - /* - Extract the data from the table map into the field metadata array - iff there is field metadata. The variable metadata_size will be - 0 if we are replicating from an older version server since no field - metadata was written to the table map. This can also happen if - there were no fields in the master that needed extra metadata. - */ - if (m_size && metadata_size) - { - int index= 0; - for (unsigned int i= 0; i < m_size; i++) - { - switch (m_type[i]) { - case MYSQL_TYPE_TINY_BLOB: - case MYSQL_TYPE_BLOB: - case MYSQL_TYPE_MEDIUM_BLOB: - case MYSQL_TYPE_LONG_BLOB: - case MYSQL_TYPE_DOUBLE: - case MYSQL_TYPE_FLOAT: - case MYSQL_TYPE_GEOMETRY: - { - /* - These types store a single byte. - */ - m_field_metadata[i]= field_metadata[index]; - index++; - break; - } - case MYSQL_TYPE_SET: - case MYSQL_TYPE_ENUM: - case MYSQL_TYPE_STRING: - { - uint16 x= field_metadata[index++] << 8U; // real_type - x+= field_metadata[index++]; // pack or field length - m_field_metadata[i]= x; - break; - } - case MYSQL_TYPE_BIT: - { - uint16 x= field_metadata[index++]; - x = x + (field_metadata[index++] << 8U); - m_field_metadata[i]= x; - break; - } - case MYSQL_TYPE_VARCHAR: - { - /* - These types store two bytes. - */ - char *ptr= (char *)&field_metadata[index]; - m_field_metadata[i]= uint2korr(ptr); - index= index + 2; - break; - } - case MYSQL_TYPE_NEWDECIMAL: - { - uint16 x= field_metadata[index++] << 8U; // precision - x+= field_metadata[index++]; // decimals - m_field_metadata[i]= x; - break; - } - default: - m_field_metadata[i]= 0; - break; - } - } - } - if (m_size && null_bitmap) - memcpy(m_null_bits, null_bitmap, (m_size + 7) / 8); - } + table_def(unsigned char *types, ulong size, uchar *field_metadata, + int metadata_size, uchar *null_bitmap, uint16 flags); - ~table_def() { - my_free(m_memory, MYF(0)); -#ifndef DBUG_OFF - m_type= 0; - m_size= 0; -#endif - } + ~table_def(); /** Return the number of fields there is type data for. @@ -172,10 +69,40 @@ public: <code>index</code>. Currently, only the type identifier is returned. */ - field_type type(ulong index) const + enum_field_types type(ulong index) const { DBUG_ASSERT(index < m_size); - return m_type[index]; + /* + If the source type is MYSQL_TYPE_STRING, it can in reality be + either MYSQL_TYPE_STRING, MYSQL_TYPE_ENUM, or MYSQL_TYPE_SET, so + we might need to modify the type to get the real type. + */ + enum_field_types source_type= static_cast<enum_field_types>(m_type[index]); + uint16 source_metadata= m_field_metadata[index]; + switch (source_type) + { + case MYSQL_TYPE_STRING: + { + int real_type= source_metadata >> 8; + if (real_type == MYSQL_TYPE_ENUM || real_type == MYSQL_TYPE_SET) + source_type= static_cast<enum_field_types>(real_type); + break; + } + + /* + This type has not been used since before row-based replication, + so we can safely assume that it really is MYSQL_TYPE_NEWDATE. + */ + case MYSQL_TYPE_DATE: + source_type= MYSQL_TYPE_NEWDATE; + break; + + default: + /* Do nothing */ + break; + } + + return source_type; } @@ -227,26 +154,62 @@ public: with it. A table definition is compatible with a table if: - - the columns types of the table definition is a (not - necessarily proper) prefix of the column type of the table, or - - the other way around + - The columns types of the table definition is a (not + necessarily proper) prefix of the column type of the table. + + - The other way around. + - Each column on the master that also exists on the slave can be + converted according to the current settings of @c + SLAVE_TYPE_CONVERSIONS. + + @param thd @param rli Pointer to relay log info @param table Pointer to table to compare with. + @param[out] tmp_table_var Pointer to temporary table for holding + conversion table. + @retval 1 if the table definition is not compatible with @c table @retval 0 if the table definition is compatible with @c table */ #ifndef MYSQL_CLIENT - int compatible_with(Relay_log_info const *rli, TABLE *table) const; + bool compatible_with(THD *thd, Relay_log_info *rli, TABLE *table, + TABLE **conv_table_var) const; + + /** + Create a virtual in-memory temporary table structure. + + The table structure has records and field array so that a row can + be unpacked into the record for further processing. + + In the virtual table, each field that requires conversion will + have a non-NULL value, while fields that do not require + conversion will have a NULL value. + + Some information that is missing in the events, such as the + character set for string types, are taken from the table that the + field is going to be pushed into, so the target table that the data + eventually need to be pushed into need to be supplied. + + @param thd Thread to allocate memory from. + @param rli Relay log info structure, for error reporting. + @param target_table Target table for fields. + + @return A pointer to a temporary table with memory allocated in the + thread's memroot, NULL if the table could not be created + */ + TABLE *create_conversion_table(THD *thd, Relay_log_info *rli, TABLE *target_table) const; #endif + private: ulong m_size; // Number of elements in the types array - field_type *m_type; // Array of type descriptors + unsigned char *m_type; // Array of type descriptors uint m_field_metadata_size; uint16 *m_field_metadata; uchar *m_null_bits; + uint16 m_flags; // Table flags uchar *m_memory; }; @@ -261,6 +224,7 @@ struct RPL_TABLE_LIST { bool m_tabledef_valid; table_def m_tabledef; + TABLE *m_conv_table; }; diff --git a/sql/scheduler.cc b/sql/scheduler.cc index b05bdf4756f..b308b84eb19 100644 --- a/sql/scheduler.cc +++ b/sql/scheduler.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2007 MySQL AB +/* Copyright (C) 2007 MySQL AB, 2008-2010 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -54,7 +54,7 @@ scheduler_functions::scheduler_functions() static bool no_threads_end(THD *thd, bool put_in_cache) { unlink_thd(thd); - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); return 1; // Abort handle_one_connection } diff --git a/sql/set_var.cc b/sql/set_var.cc index 0c189704bca..73989b9c96f 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2010 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,2143 +13,341 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/** - @file - - @brief - Handling of MySQL SQL variables - - @details - To add a new variable, one has to do the following: - - - Use one of the 'sys_var... classes from set_var.h or write a specific - one for the variable type. - - Define it in the 'variable definition list' in this file. - - If the variable is thread specific, add it to 'system_variables' struct. - If not, add it to mysqld.cc and an declaration in 'mysql_priv.h' - - If the variable should be changed from the command line, add a definition - of it in the my_option structure list in mysqld.cc - - Don't forget to initialize new fields in global_system_variables and - max_system_variables! - - @todo - Add full support for the variable character_set (for 4.1) - - @todo - When updating myisam_delay_key_write, we should do a 'flush tables' - of all MyISAM tables to ensure that they are reopen with the - new attribute. - - @note - Be careful with var->save_result: sys_var::check() only updates - ulonglong_value; so other members of the union are garbage then; to use - them you must first assign a value to them (in specific ::check() for - example). -*/ - #ifdef USE_PRAGMA_IMPLEMENTATION -#pragma implementation // gcc: Class implementation -#endif - -#include "mysql_priv.h" -#include <mysql.h> -#include "slave.h" -#include "rpl_mi.h" -#include <my_getopt.h> -#include <thr_alarm.h> -#include <myisam.h> -#include <my_dir.h> - -#include "events.h" - -/* WITH_NDBCLUSTER_STORAGE_ENGINE */ -#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE -extern ulong ndb_cache_check_time; -extern char opt_ndb_constrbuf[]; -extern ulong ndb_extra_logging; +#pragma implementation #endif -#ifdef HAVE_NDB_BINLOG -extern ulong ndb_report_thresh_binlog_epoch_slip; -extern ulong ndb_report_thresh_binlog_mem_usage; -#endif - -extern CHARSET_INFO *character_set_filesystem; +/* variable declarations are in sys_vars.cc now !!! */ +#include "mysql_priv.h" +#include "sys_vars_shared.h" static HASH system_variable_hash; - -const char *bool_type_names[]= { "OFF", "ON", NullS }; -TYPELIB bool_typelib= -{ - array_elements(bool_type_names)-1, "", bool_type_names, NULL -}; - -const char *delay_key_write_type_names[]= { "OFF", "ON", "ALL", NullS }; -TYPELIB delay_key_write_typelib= -{ - array_elements(delay_key_write_type_names)-1, "", - delay_key_write_type_names, NULL -}; - -const char *slave_exec_mode_names[]= -{ "STRICT", "IDEMPOTENT", NullS }; -static const unsigned int slave_exec_mode_names_len[]= -{ sizeof("STRICT") - 1, sizeof("IDEMPOTENT") - 1, 0 }; -TYPELIB slave_exec_mode_typelib= -{ - array_elements(slave_exec_mode_names)-1, "", - slave_exec_mode_names, (unsigned int *) slave_exec_mode_names_len -}; - -static int sys_check_ftb_syntax(THD *thd, set_var *var); -static bool sys_update_ftb_syntax(THD *thd, set_var * var); -static void sys_default_ftb_syntax(THD *thd, enum_var_type type); -static bool sys_update_init_connect(THD*, set_var*); -static void sys_default_init_connect(THD*, enum_var_type type); -static bool sys_update_init_slave(THD*, set_var*); -static void sys_default_init_slave(THD*, enum_var_type type); -static bool set_option_bit(THD *thd, set_var *var); -static bool set_option_log_bin_bit(THD *thd, set_var *var); -static bool set_option_autocommit(THD *thd, set_var *var); -static int check_log_update(THD *thd, set_var *var); -static bool set_log_update(THD *thd, set_var *var); -static int check_pseudo_thread_id(THD *thd, set_var *var); -void fix_binlog_format_after_update(THD *thd, enum_var_type type); -static void fix_low_priority_updates(THD *thd, enum_var_type type); -static int check_tx_isolation(THD *thd, set_var *var); -static void fix_tx_isolation(THD *thd, enum_var_type type); -static int check_completion_type(THD *thd, set_var *var); -static void fix_completion_type(THD *thd, enum_var_type type); -static void fix_net_read_timeout(THD *thd, enum_var_type type); -static void fix_net_write_timeout(THD *thd, enum_var_type type); -static void fix_net_retry_count(THD *thd, enum_var_type type); -static void fix_max_join_size(THD *thd, enum_var_type type); -#ifdef HAVE_QUERY_CACHE -static void fix_query_cache_size(THD *thd, enum_var_type type); -static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type); -#endif -static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type); -static void fix_max_binlog_size(THD *thd, enum_var_type type); -static void fix_max_relay_log_size(THD *thd, enum_var_type type); -static void fix_max_connections(THD *thd, enum_var_type type); -static int check_max_delayed_threads(THD *thd, set_var *var); -static void fix_thd_mem_root(THD *thd, enum_var_type type); -static void fix_trans_mem_root(THD *thd, enum_var_type type); -static void fix_server_id(THD *thd, enum_var_type type); -bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd, - const char *name, longlong val); -static KEY_CACHE *create_key_cache(const char *name, uint length); -void fix_sql_mode_var(THD *thd, enum_var_type type); -static uchar *get_error_count(THD *thd); -static uchar *get_warning_count(THD *thd); -static uchar *get_tmpdir(THD *thd); -static int sys_check_log_path(THD *thd, set_var *var); -static bool sys_update_general_log_path(THD *thd, set_var * var); -static void sys_default_general_log_path(THD *thd, enum_var_type type); -static bool sys_update_slow_log_path(THD *thd, set_var * var); -static void sys_default_slow_log_path(THD *thd, enum_var_type type); -static uchar *get_myisam_mmap_size(THD *thd); - -/* - Variable definition list - - These are variables that can be set from the command line, in - alphabetic order. - - The variables are linked into the list. A variable is added to - it in the constructor (see sys_var class for details). -*/ - -static sys_var_chain vars = { NULL, NULL }; - -static sys_var_thd_ulong -sys_auto_increment_increment(&vars, "auto_increment_increment", - &SV::auto_increment_increment, NULL, NULL, - sys_var::SESSION_VARIABLE_IN_BINLOG); -static sys_var_thd_ulong -sys_auto_increment_offset(&vars, "auto_increment_offset", - &SV::auto_increment_offset, NULL, NULL, - sys_var::SESSION_VARIABLE_IN_BINLOG); - -static sys_var_bool_ptr sys_automatic_sp_privileges(&vars, "automatic_sp_privileges", - &sp_automatic_privileges); - -static sys_var_const sys_back_log(&vars, "back_log", - OPT_GLOBAL, SHOW_LONG, - (uchar*) &back_log); -static sys_var_const_os_str sys_basedir(&vars, "basedir", mysql_home); -static sys_var_long_ptr sys_binlog_cache_size(&vars, "binlog_cache_size", - &binlog_cache_size); -static sys_var_thd_binlog_format sys_binlog_format(&vars, "binlog_format", - &SV::binlog_format); -static sys_var_thd_bool sys_binlog_direct_non_trans_update(&vars, "binlog_direct_non_transactional_updates", - &SV::binlog_direct_non_trans_update); -static sys_var_thd_ulong sys_bulk_insert_buff_size(&vars, "bulk_insert_buffer_size", - &SV::bulk_insert_buff_size); -static sys_var_const_os sys_character_sets_dir(&vars, - "character_sets_dir", - OPT_GLOBAL, SHOW_CHAR, - (uchar*) - mysql_charsets_dir); -static sys_var_character_set_sv -sys_character_set_server(&vars, "character_set_server", - &SV::collation_server, &default_charset_info, 0, - sys_var::SESSION_VARIABLE_IN_BINLOG); -sys_var_const_str sys_charset_system(&vars, "character_set_system", - (char *)my_charset_utf8_general_ci.name); -static sys_var_character_set_database -sys_character_set_database(&vars, "character_set_database", - sys_var::SESSION_VARIABLE_IN_BINLOG); -static sys_var_character_set_client -sys_character_set_client(&vars, "character_set_client", - &SV::character_set_client, - &default_charset_info, - sys_var::SESSION_VARIABLE_IN_BINLOG); -static sys_var_character_set_sv -sys_character_set_connection(&vars, "character_set_connection", - &SV::collation_connection, - &default_charset_info, 0, - sys_var::SESSION_VARIABLE_IN_BINLOG); -static sys_var_character_set_sv sys_character_set_results(&vars, "character_set_results", - &SV::character_set_results, - &default_charset_info, true); -static sys_var_character_set_sv sys_character_set_filesystem(&vars, "character_set_filesystem", - &SV::character_set_filesystem, - &character_set_filesystem); -static sys_var_thd_ulong sys_completion_type(&vars, "completion_type", - &SV::completion_type, - check_completion_type, - fix_completion_type); -static sys_var_collation_sv -sys_collation_connection(&vars, "collation_connection", - &SV::collation_connection, &default_charset_info, - sys_var::SESSION_VARIABLE_IN_BINLOG); -static sys_var_collation_sv -sys_collation_database(&vars, "collation_database", &SV::collation_database, - &default_charset_info, - sys_var::SESSION_VARIABLE_IN_BINLOG); -static sys_var_collation_sv -sys_collation_server(&vars, "collation_server", &SV::collation_server, - &default_charset_info, - sys_var::SESSION_VARIABLE_IN_BINLOG); -static sys_var_long_ptr sys_concurrent_insert(&vars, "concurrent_insert", - &myisam_concurrent_insert); -static sys_var_long_ptr sys_connect_timeout(&vars, "connect_timeout", - &connect_timeout); -static sys_var_const_os_str sys_datadir(&vars, "datadir", mysql_real_data_home); -#ifndef DBUG_OFF -static sys_var_thd_dbug sys_dbug(&vars, "debug"); -#endif -static sys_var_enum sys_delay_key_write(&vars, "delay_key_write", - &delay_key_write_options, - &delay_key_write_typelib, - fix_delay_key_write); -static sys_var_long_ptr sys_delayed_insert_limit(&vars, "delayed_insert_limit", - &delayed_insert_limit); -static sys_var_long_ptr sys_delayed_insert_timeout(&vars, "delayed_insert_timeout", - &delayed_insert_timeout); -static sys_var_long_ptr sys_delayed_queue_size(&vars, "delayed_queue_size", - &delayed_queue_size); - -#ifdef HAVE_EVENT_SCHEDULER -static sys_var_event_scheduler sys_event_scheduler(&vars, "event_scheduler"); -#endif - -static sys_var_long_ptr sys_expire_logs_days(&vars, "expire_logs_days", - &expire_logs_days); -static sys_var_bool_ptr sys_flush(&vars, "flush", &myisam_flush); -static sys_var_long_ptr sys_flush_time(&vars, "flush_time", &flush_time); -static sys_var_str sys_ft_boolean_syntax(&vars, "ft_boolean_syntax", - sys_check_ftb_syntax, - sys_update_ftb_syntax, - sys_default_ftb_syntax, - ft_boolean_syntax); -static sys_var_const sys_ft_max_word_len(&vars, "ft_max_word_len", - OPT_GLOBAL, SHOW_LONG, - (uchar*) &ft_max_word_len); -static sys_var_const sys_ft_min_word_len(&vars, "ft_min_word_len", - OPT_GLOBAL, SHOW_LONG, - (uchar*) &ft_min_word_len); -static sys_var_const sys_ft_query_expansion_limit(&vars, - "ft_query_expansion_limit", - OPT_GLOBAL, SHOW_LONG, - (uchar*) - &ft_query_expansion_limit); -static sys_var_const sys_ft_stopword_file(&vars, "ft_stopword_file", - OPT_GLOBAL, SHOW_CHAR_PTR, - (uchar*) &ft_stopword_file); - -static sys_var_const sys_ignore_builtin_innodb(&vars, "ignore_builtin_innodb", - OPT_GLOBAL, SHOW_BOOL, - (uchar*) &opt_ignore_builtin_innodb); - -sys_var_str sys_init_connect(&vars, "init_connect", 0, - sys_update_init_connect, - sys_default_init_connect,0); -static sys_var_const sys_init_file(&vars, "init_file", - OPT_GLOBAL, SHOW_CHAR_PTR, - (uchar*) &opt_init_file); -sys_var_str sys_init_slave(&vars, "init_slave", 0, - sys_update_init_slave, - sys_default_init_slave,0); -static sys_var_thd_ulong sys_interactive_timeout(&vars, "interactive_timeout", - &SV::net_interactive_timeout); -static sys_var_thd_ulong sys_join_buffer_size(&vars, "join_buffer_size", - &SV::join_buff_size); -static sys_var_key_buffer_size sys_key_buffer_size(&vars, "key_buffer_size"); -static sys_var_key_cache_long sys_key_cache_block_size(&vars, "key_cache_block_size", - offsetof(KEY_CACHE, - param_block_size)); -static sys_var_key_cache_long sys_key_cache_division_limit(&vars, "key_cache_division_limit", - offsetof(KEY_CACHE, - param_division_limit)); -static sys_var_key_cache_long sys_key_cache_age_threshold(&vars, "key_cache_age_threshold", - offsetof(KEY_CACHE, - param_age_threshold)); -static sys_var_const sys_large_files_support(&vars, "large_files_support", - OPT_GLOBAL, SHOW_BOOL, - (uchar*) &opt_large_files); -static sys_var_const sys_large_page_size(&vars, "large_page_size", - OPT_GLOBAL, SHOW_INT, - (uchar*) &opt_large_page_size); -static sys_var_const sys_large_pages(&vars, "large_pages", - OPT_GLOBAL, SHOW_MY_BOOL, - (uchar*) &opt_large_pages); -static sys_var_const sys_language(&vars, "lc_messages_dir", - OPT_GLOBAL, SHOW_CHAR, - (uchar*) lc_messages_dir); -static sys_var_bool_ptr sys_local_infile(&vars, "local_infile", - &opt_local_infile); -#ifdef HAVE_MLOCKALL -static sys_var_const sys_locked_in_memory(&vars, "locked_in_memory", - OPT_GLOBAL, SHOW_MY_BOOL, - (uchar*) &locked_in_memory); -#endif -static sys_var_const sys_log_bin(&vars, "log_bin", - OPT_GLOBAL, SHOW_BOOL, - (uchar*) &opt_bin_log); -static sys_var_trust_routine_creators -sys_trust_routine_creators(&vars, "log_bin_trust_routine_creators", - &trust_function_creators); -static sys_var_bool_ptr -sys_trust_function_creators(&vars, "log_bin_trust_function_creators", - &trust_function_creators); -static sys_var_const sys_log_error(&vars, "log_error", - OPT_GLOBAL, SHOW_CHAR, - (uchar*) log_error_file); -static sys_var_bool_ptr - sys_log_queries_not_using_indexes(&vars, "log_queries_not_using_indexes", - &opt_log_queries_not_using_indexes); -static sys_var_thd_ulong sys_log_warnings(&vars, "log_warnings", &SV::log_warnings); -static sys_var_microseconds sys_var_long_query_time(&vars, "long_query_time", - &SV::long_query_time); -static sys_var_thd_bool sys_low_priority_updates(&vars, "low_priority_updates", - &SV::low_priority_updates, - fix_low_priority_updates); -#ifndef TO_BE_DELETED /* Alias for the low_priority_updates */ -static sys_var_thd_bool sys_sql_low_priority_updates(&vars, "sql_low_priority_updates", - &SV::low_priority_updates, - fix_low_priority_updates); -#endif -static sys_var_const sys_lower_case_file_system(&vars, - "lower_case_file_system", - OPT_GLOBAL, SHOW_MY_BOOL, - (uchar*) - &lower_case_file_system); -static sys_var_const sys_lower_case_table_names(&vars, - "lower_case_table_names", - OPT_GLOBAL, SHOW_INT, - (uchar*) - &lower_case_table_names); -static sys_var_thd_ulong_session_readonly sys_max_allowed_packet(&vars, "max_allowed_packet", - &SV::max_allowed_packet); -static sys_var_ulonglong_ptr sys_max_binlog_cache_size(&vars, "max_binlog_cache_size", - &max_binlog_cache_size); -static sys_var_long_ptr sys_max_binlog_size(&vars, "max_binlog_size", - &max_binlog_size, - fix_max_binlog_size); -static sys_var_long_ptr sys_max_connections(&vars, "max_connections", - &max_connections, - fix_max_connections); -static sys_var_long_ptr sys_max_connect_errors(&vars, "max_connect_errors", - &max_connect_errors); -static sys_var_thd_ulong sys_max_insert_delayed_threads(&vars, "max_insert_delayed_threads", - &SV::max_insert_delayed_threads, - check_max_delayed_threads, - fix_max_connections); -static sys_var_thd_ulong sys_max_delayed_threads(&vars, "max_delayed_threads", - &SV::max_insert_delayed_threads, - check_max_delayed_threads, - fix_max_connections); -static sys_var_thd_ulong sys_max_error_count(&vars, "max_error_count", - &SV::max_error_count); -static sys_var_thd_ulonglong sys_max_heap_table_size(&vars, "max_heap_table_size", - &SV::max_heap_table_size); -static sys_var_thd_ulong sys_pseudo_thread_id(&vars, "pseudo_thread_id", - &SV::pseudo_thread_id, - check_pseudo_thread_id, 0, - sys_var::SESSION_VARIABLE_IN_BINLOG); -static sys_var_thd_ha_rows sys_max_join_size(&vars, "max_join_size", - &SV::max_join_size, - fix_max_join_size); -static sys_var_thd_ulong sys_max_seeks_for_key(&vars, "max_seeks_for_key", - &SV::max_seeks_for_key); -static sys_var_thd_ulong sys_max_length_for_sort_data(&vars, "max_length_for_sort_data", - &SV::max_length_for_sort_data); -#ifndef TO_BE_DELETED /* Alias for max_join_size */ -static sys_var_thd_ha_rows sys_sql_max_join_size(&vars, "sql_max_join_size", - &SV::max_join_size, - fix_max_join_size); -#endif -static sys_var_long_ptr_global -sys_max_prepared_stmt_count(&vars, "max_prepared_stmt_count", - &max_prepared_stmt_count, - &LOCK_prepared_stmt_count); -static sys_var_long_ptr sys_max_relay_log_size(&vars, "max_relay_log_size", - &max_relay_log_size, - fix_max_relay_log_size); -static sys_var_thd_ulong sys_max_sort_length(&vars, "max_sort_length", - &SV::max_sort_length); -static sys_var_thd_ulong sys_max_sp_recursion_depth(&vars, "max_sp_recursion_depth", - &SV::max_sp_recursion_depth); -static sys_var_max_user_conn sys_max_user_connections(&vars, "max_user_connections"); -static sys_var_thd_ulong sys_max_tmp_tables(&vars, "max_tmp_tables", - &SV::max_tmp_tables); -static sys_var_long_ptr sys_max_write_lock_count(&vars, "max_write_lock_count", - &max_write_lock_count); -static sys_var_thd_ulong sys_min_examined_row_limit(&vars, "min_examined_row_limit", - &SV::min_examined_row_limit); -static sys_var_thd_ulong sys_multi_range_count(&vars, "multi_range_count", - &SV::multi_range_count); -static sys_var_long_ptr sys_myisam_data_pointer_size(&vars, "myisam_data_pointer_size", - &myisam_data_pointer_size); -static sys_var_thd_ulonglong sys_myisam_max_sort_file_size(&vars, "myisam_max_sort_file_size", &SV::myisam_max_sort_file_size, fix_myisam_max_sort_file_size, 1); -static sys_var_const sys_myisam_recover_options(&vars, "myisam_recover_options", - OPT_GLOBAL, SHOW_CHAR_PTR, - (uchar*) - &myisam_recover_options_str); -static sys_var_thd_ulong sys_myisam_repair_threads(&vars, "myisam_repair_threads", &SV::myisam_repair_threads); -static sys_var_thd_ulong sys_myisam_sort_buffer_size(&vars, "myisam_sort_buffer_size", &SV::myisam_sort_buff_size); -static sys_var_bool_ptr sys_myisam_use_mmap(&vars, "myisam_use_mmap", - &opt_myisam_use_mmap); - -static sys_var_thd_enum sys_myisam_stats_method(&vars, "myisam_stats_method", - &SV::myisam_stats_method, - &myisam_stats_method_typelib, - NULL); - -#ifdef _WIN32 -/* purecov: begin inspected */ -static sys_var_const sys_named_pipe(&vars, "named_pipe", - OPT_GLOBAL, SHOW_MY_BOOL, - (uchar*) &opt_enable_named_pipe); -/* purecov: end */ -#endif -static sys_var_thd_ulong_session_readonly sys_net_buffer_length(&vars, "net_buffer_length", - &SV::net_buffer_length); -static sys_var_thd_ulong sys_net_read_timeout(&vars, "net_read_timeout", - &SV::net_read_timeout, - 0, fix_net_read_timeout); -static sys_var_thd_ulong sys_net_write_timeout(&vars, "net_write_timeout", - &SV::net_write_timeout, - 0, fix_net_write_timeout); -static sys_var_thd_ulong sys_net_retry_count(&vars, "net_retry_count", - &SV::net_retry_count, - 0, fix_net_retry_count); -static sys_var_thd_bool sys_new_mode(&vars, "new", &SV::new_mode); -static sys_var_bool_ptr_readonly sys_old_mode(&vars, "old", - &global_system_variables.old_mode); -/* these two cannot be static */ -sys_var_thd_bool sys_old_alter_table(&vars, "old_alter_table", - &SV::old_alter_table); -sys_var_thd_bool sys_old_passwords(&vars, "old_passwords", &SV::old_passwords); -static sys_var_const sys_open_files_limit(&vars, "open_files_limit", - OPT_GLOBAL, SHOW_LONG, - (uchar*) - &open_files_limit); -static sys_var_thd_ulong sys_optimizer_prune_level(&vars, "optimizer_prune_level", - &SV::optimizer_prune_level); -static sys_var_thd_ulong sys_optimizer_search_depth(&vars, "optimizer_search_depth", - &SV::optimizer_search_depth); -static sys_var_thd_optimizer_switch sys_optimizer_switch(&vars, "optimizer_switch", - &SV::optimizer_switch); -static sys_var_const sys_pid_file(&vars, "pid_file", - OPT_GLOBAL, SHOW_CHAR, - (uchar*) pidfile_name); -static sys_var_const_os sys_plugin_dir(&vars, "plugin_dir", - OPT_GLOBAL, SHOW_CHAR, - (uchar*) opt_plugin_dir); -static sys_var_const sys_port(&vars, "port", - OPT_GLOBAL, SHOW_INT, - (uchar*) &mysqld_port); -static sys_var_thd_ulong sys_preload_buff_size(&vars, "preload_buffer_size", - &SV::preload_buff_size); -static sys_var_const sys_protocol_version(&vars, "protocol_version", - OPT_GLOBAL, SHOW_INT, - (uchar*) - &protocol_version); -static sys_var_thd_ulong sys_read_buff_size(&vars, "read_buffer_size", - &SV::read_buff_size); -static sys_var_opt_readonly sys_readonly(&vars, "read_only", &opt_readonly); -static sys_var_thd_ulong sys_read_rnd_buff_size(&vars, "read_rnd_buffer_size", - &SV::read_rnd_buff_size); -static sys_var_thd_ulong sys_div_precincrement(&vars, "div_precision_increment", - &SV::div_precincrement); -static sys_var_long_ptr sys_rpl_recovery_rank(&vars, "rpl_recovery_rank", - &rpl_recovery_rank); - -static sys_var_thd_ulong sys_range_alloc_block_size(&vars, "range_alloc_block_size", - &SV::range_alloc_block_size); -static sys_var_thd_ulong sys_query_alloc_block_size(&vars, "query_alloc_block_size", - &SV::query_alloc_block_size, - 0, fix_thd_mem_root); -static sys_var_thd_ulong sys_query_prealloc_size(&vars, "query_prealloc_size", - &SV::query_prealloc_size, - 0, fix_thd_mem_root); -#ifdef HAVE_SMEM -/* purecov: begin tested */ -static sys_var_const sys_shared_memory(&vars, "shared_memory", - OPT_GLOBAL, SHOW_MY_BOOL, - (uchar*) - &opt_enable_shared_memory); -static sys_var_const sys_shared_memory_base_name(&vars, - "shared_memory_base_name", - OPT_GLOBAL, SHOW_CHAR_PTR, - (uchar*) - &shared_memory_base_name); -/* purecov: end */ -#endif -static sys_var_const sys_skip_external_locking(&vars, - "skip_external_locking", - OPT_GLOBAL, SHOW_MY_BOOL, - (uchar*) - &my_disable_locking); -static sys_var_const sys_skip_networking(&vars, "skip_networking", - OPT_GLOBAL, SHOW_BOOL, - (uchar*) &opt_disable_networking); -static sys_var_const sys_skip_show_database(&vars, "skip_show_database", - OPT_GLOBAL, SHOW_BOOL, - (uchar*) &opt_skip_show_db); - -static sys_var_const sys_socket(&vars, "socket", - OPT_GLOBAL, SHOW_CHAR_PTR, - (uchar*) &mysqld_unix_port); - -#ifdef HAVE_THR_SETCONCURRENCY -/* purecov: begin tested */ -static sys_var_const sys_thread_concurrency(&vars, "thread_concurrency", - OPT_GLOBAL, SHOW_LONG, - (uchar*) &concurrency); -/* purecov: end */ -#endif -static sys_var_const sys_thread_stack(&vars, "thread_stack", - OPT_GLOBAL, SHOW_LONG, - (uchar*) &my_thread_stack_size); -static sys_var_readonly_os sys_tmpdir(&vars, "tmpdir", OPT_GLOBAL, SHOW_CHAR, get_tmpdir); -static sys_var_thd_ulong sys_trans_alloc_block_size(&vars, "transaction_alloc_block_size", - &SV::trans_alloc_block_size, - 0, fix_trans_mem_root); -static sys_var_thd_ulong sys_trans_prealloc_size(&vars, "transaction_prealloc_size", - &SV::trans_prealloc_size, - 0, fix_trans_mem_root); -sys_var_enum_const sys_thread_handling(&vars, "thread_handling", - &SV::thread_handling, - &thread_handling_typelib, - NULL); - -#ifdef HAVE_QUERY_CACHE -static sys_var_long_ptr sys_query_cache_size(&vars, "query_cache_size", - &query_cache_size, - fix_query_cache_size); -static sys_var_long_ptr sys_query_cache_limit(&vars, "query_cache_limit", - &query_cache.query_cache_limit); -static sys_var_long_ptr - sys_query_cache_min_res_unit(&vars, "query_cache_min_res_unit", - &query_cache_min_res_unit, - fix_query_cache_min_res_unit); -static int check_query_cache_type(THD *thd, set_var *var); -static sys_var_thd_enum sys_query_cache_type(&vars, "query_cache_type", - &SV::query_cache_type, - &query_cache_type_typelib, NULL, - check_query_cache_type); -static sys_var_thd_bool -sys_query_cache_wlock_invalidate(&vars, "query_cache_wlock_invalidate", - &SV::query_cache_wlock_invalidate); -#endif /* HAVE_QUERY_CACHE */ -static sys_var_bool_ptr sys_secure_auth(&vars, "secure_auth", &opt_secure_auth); -static sys_var_const_str_ptr sys_secure_file_priv(&vars, "secure_file_priv", - &opt_secure_file_priv); -static sys_var_long_ptr sys_server_id(&vars, "server_id", &server_id, fix_server_id); -static sys_var_bool_ptr sys_slave_compressed_protocol(&vars, "slave_compressed_protocol", - &opt_slave_compressed_protocol); -static sys_var_set_slave_mode slave_exec_mode(&vars, - "slave_exec_mode", - &slave_exec_mode_options, - &slave_exec_mode_typelib, - 0); -static sys_var_long_ptr sys_slow_launch_time(&vars, "slow_launch_time", - &slow_launch_time); -static sys_var_thd_ulong sys_sort_buffer(&vars, "sort_buffer_size", - &SV::sortbuff_size); -/* - sql_mode should *not* have binlog_mode=SESSION_VARIABLE_IN_BINLOG: - even though it is written to the binlog, the slave ignores the - MODE_NO_DIR_IN_CREATE variable, so slave's value differs from - master's (see log_event.cc: Query_log_event::do_apply_event()). -*/ -static sys_var_thd_sql_mode sys_sql_mode(&vars, "sql_mode", - &SV::sql_mode); -#ifdef HAVE_OPENSSL -extern char *opt_ssl_ca, *opt_ssl_capath, *opt_ssl_cert, *opt_ssl_cipher, - *opt_ssl_key; -static sys_var_const_os_str_ptr sys_ssl_ca(&vars, "ssl_ca", &opt_ssl_ca); -static sys_var_const_os_str_ptr sys_ssl_capath(&vars, "ssl_capath", &opt_ssl_capath); -static sys_var_const_os_str_ptr sys_ssl_cert(&vars, "ssl_cert", &opt_ssl_cert); -static sys_var_const_os_str_ptr sys_ssl_cipher(&vars, "ssl_cipher", &opt_ssl_cipher); -static sys_var_const_os_str_ptr sys_ssl_key(&vars, "ssl_key", &opt_ssl_key); -#else -static sys_var_const_os_str sys_ssl_ca(&vars, "ssl_ca", NULL); -static sys_var_const_os_str sys_ssl_capath(&vars, "ssl_capath", NULL); -static sys_var_const_os_str sys_ssl_cert(&vars, "ssl_cert", NULL); -static sys_var_const_os_str sys_ssl_cipher(&vars, "ssl_cipher", NULL); -static sys_var_const_os_str sys_ssl_key(&vars, "ssl_key", NULL); -#endif -static sys_var_thd_enum -sys_updatable_views_with_limit(&vars, "updatable_views_with_limit", - &SV::updatable_views_with_limit, - &updatable_views_with_limit_typelib); - -static sys_var_thd_table_type sys_table_type(&vars, "table_type", - &SV::table_plugin); -static sys_var_thd_storage_engine sys_storage_engine(&vars, "storage_engine", - &SV::table_plugin); -static sys_var_bool_ptr sys_sync_frm(&vars, "sync_frm", &opt_sync_frm); -static sys_var_const_str sys_system_time_zone(&vars, "system_time_zone", - system_time_zone); -static sys_var_long_ptr sys_table_def_size(&vars, "table_definition_cache", - &table_def_size); -static sys_var_long_ptr sys_table_cache_size(&vars, "table_open_cache", - &table_cache_size); -static sys_var_long_ptr sys_table_lock_wait_timeout(&vars, "table_lock_wait_timeout", - &table_lock_wait_timeout); - -#if defined(ENABLED_DEBUG_SYNC) -/* Debug Sync Facility. Implemented in debug_sync.cc. */ -static sys_var_debug_sync sys_debug_sync(&vars, "debug_sync"); -#endif /* defined(ENABLED_DEBUG_SYNC) */ - -static sys_var_long_ptr sys_thread_cache_size(&vars, "thread_cache_size", - &thread_cache_size); -#if HAVE_POOL_OF_THREADS == 1 -sys_var_long_ptr sys_thread_pool_size(&vars, "thread_pool_size", - &thread_pool_size); -#endif -static sys_var_thd_enum sys_tx_isolation(&vars, "tx_isolation", - &SV::tx_isolation, - &tx_isolation_typelib, - fix_tx_isolation, - check_tx_isolation); -static sys_var_thd_ulonglong sys_tmp_table_size(&vars, "tmp_table_size", - &SV::tmp_table_size); -static sys_var_bool_ptr sys_timed_mutexes(&vars, "timed_mutexes", - &timed_mutexes); -static sys_var_const_str sys_version(&vars, "version", server_version); -static sys_var_const_str sys_version_comment(&vars, "version_comment", - MYSQL_COMPILATION_COMMENT); -static sys_var_const_str sys_version_compile_machine(&vars, "version_compile_machine", - MACHINE_TYPE); -static sys_var_const_str sys_version_compile_os(&vars, "version_compile_os", - SYSTEM_TYPE); -static sys_var_thd_ulong sys_net_wait_timeout(&vars, "wait_timeout", - &SV::net_wait_timeout); - -/* Condition pushdown to storage engine */ -static sys_var_thd_bool -sys_engine_condition_pushdown(&vars, "engine_condition_pushdown", - &SV::engine_condition_pushdown); - -#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE -/* ndb thread specific variable settings */ -static sys_var_thd_ulong -sys_ndb_autoincrement_prefetch_sz(&vars, "ndb_autoincrement_prefetch_sz", - &SV::ndb_autoincrement_prefetch_sz); -static sys_var_thd_bool -sys_ndb_force_send(&vars, "ndb_force_send", &SV::ndb_force_send); -#ifdef HAVE_NDB_BINLOG -static sys_var_long_ptr -sys_ndb_report_thresh_binlog_epoch_slip(&vars, "ndb_report_thresh_binlog_epoch_slip", - &ndb_report_thresh_binlog_epoch_slip); -static sys_var_long_ptr -sys_ndb_report_thresh_binlog_mem_usage(&vars, "ndb_report_thresh_binlog_mem_usage", - &ndb_report_thresh_binlog_mem_usage); -#endif -static sys_var_thd_bool -sys_ndb_use_exact_count(&vars, "ndb_use_exact_count", &SV::ndb_use_exact_count); -static sys_var_thd_bool -sys_ndb_use_transactions(&vars, "ndb_use_transactions", &SV::ndb_use_transactions); -static sys_var_long_ptr -sys_ndb_cache_check_time(&vars, "ndb_cache_check_time", &ndb_cache_check_time); -static sys_var_const_str -sys_ndb_connectstring(&vars, "ndb_connectstring", opt_ndb_constrbuf); -static sys_var_thd_bool -sys_ndb_index_stat_enable(&vars, "ndb_index_stat_enable", - &SV::ndb_index_stat_enable); -static sys_var_thd_ulong -sys_ndb_index_stat_cache_entries(&vars, "ndb_index_stat_cache_entries", - &SV::ndb_index_stat_cache_entries); -static sys_var_thd_ulong -sys_ndb_index_stat_update_freq(&vars, "ndb_index_stat_update_freq", - &SV::ndb_index_stat_update_freq); -static sys_var_long_ptr -sys_ndb_extra_logging(&vars, "ndb_extra_logging", &ndb_extra_logging); -static sys_var_thd_bool -sys_ndb_use_copying_alter_table(&vars, "ndb_use_copying_alter_table", &SV::ndb_use_copying_alter_table); -#endif //WITH_NDBCLUSTER_STORAGE_ENGINE - -/* Time/date/datetime formats */ - -static sys_var_thd_date_time_format sys_time_format(&vars, "time_format", - &SV::time_format, - MYSQL_TIMESTAMP_TIME); -static sys_var_thd_date_time_format sys_date_format(&vars, "date_format", - &SV::date_format, - MYSQL_TIMESTAMP_DATE); -static sys_var_thd_date_time_format sys_datetime_format(&vars, "datetime_format", - &SV::datetime_format, - MYSQL_TIMESTAMP_DATETIME); - -/* Variables that are bits in THD */ - -sys_var_thd_bit sys_autocommit(&vars, "autocommit", 0, - set_option_autocommit, - OPTION_NOT_AUTOCOMMIT, - 1); -static sys_var_thd_bit sys_big_tables(&vars, "big_tables", 0, - set_option_bit, - OPTION_BIG_TABLES); -#ifndef TO_BE_DELETED /* Alias for big_tables */ -static sys_var_thd_bit sys_sql_big_tables(&vars, "sql_big_tables", 0, - set_option_bit, - OPTION_BIG_TABLES); -#endif -static sys_var_thd_bit sys_big_selects(&vars, "sql_big_selects", 0, - set_option_bit, - OPTION_BIG_SELECTS); -static sys_var_thd_bit sys_log_off(&vars, "sql_log_off", - check_log_update, - set_option_bit, - OPTION_LOG_OFF); -static sys_var_thd_bit sys_log_update(&vars, "sql_log_update", - check_log_update, - set_log_update, - OPTION_BIN_LOG); -static sys_var_thd_bit sys_log_binlog(&vars, "sql_log_bin", - check_log_update, - set_option_log_bin_bit, - OPTION_BIN_LOG); -static sys_var_thd_bit sys_sql_warnings(&vars, "sql_warnings", 0, - set_option_bit, - OPTION_WARNINGS); -static sys_var_thd_bit sys_sql_notes(&vars, "sql_notes", 0, - set_option_bit, - OPTION_SQL_NOTES); -static sys_var_thd_bit sys_auto_is_null(&vars, "sql_auto_is_null", 0, - set_option_bit, - OPTION_AUTO_IS_NULL, 0, - sys_var::SESSION_VARIABLE_IN_BINLOG); -static sys_var_thd_bit sys_safe_updates(&vars, "sql_safe_updates", 0, - set_option_bit, - OPTION_SAFE_UPDATES); -static sys_var_thd_bit sys_buffer_results(&vars, "sql_buffer_result", 0, - set_option_bit, - OPTION_BUFFER_RESULT); -static sys_var_thd_bit sys_quote_show_create(&vars, "sql_quote_show_create", 0, - set_option_bit, - OPTION_QUOTE_SHOW_CREATE); -static sys_var_thd_bit sys_foreign_key_checks(&vars, "foreign_key_checks", 0, - set_option_bit, - OPTION_NO_FOREIGN_KEY_CHECKS, - 1, sys_var::SESSION_VARIABLE_IN_BINLOG); -static sys_var_thd_bit sys_unique_checks(&vars, "unique_checks", 0, - set_option_bit, - OPTION_RELAXED_UNIQUE_CHECKS, - 1, - sys_var::SESSION_VARIABLE_IN_BINLOG); -#if defined(ENABLED_PROFILING) -static sys_var_thd_bit sys_profiling(&vars, "profiling", NULL, - set_option_bit, - ulonglong(OPTION_PROFILING)); -static sys_var_thd_ulong sys_profiling_history_size(&vars, "profiling_history_size", - &SV::profiling_history_size); -#endif - -/* Local state variables */ - -static sys_var_thd_ha_rows sys_select_limit(&vars, "sql_select_limit", - &SV::select_limit); -static sys_var_timestamp sys_timestamp(&vars, "timestamp", - sys_var::SESSION_VARIABLE_IN_BINLOG); -static sys_var_last_insert_id -sys_last_insert_id(&vars, "last_insert_id", - sys_var::SESSION_VARIABLE_IN_BINLOG); -/* - identity is an alias for last_insert_id(), so that we are compatible - with Sybase -*/ -static sys_var_last_insert_id -sys_identity(&vars, "identity", sys_var::SESSION_VARIABLE_IN_BINLOG); - -static sys_var_thd_lc_messages -sys_lc_messages(&vars, "lc_messages", sys_var::NOT_IN_BINLOG); - -static sys_var_thd_lc_time_names -sys_lc_time_names(&vars, "lc_time_names", sys_var::SESSION_VARIABLE_IN_BINLOG); - -/* - insert_id should *not* be marked as written to the binlog (i.e., it - should *not* have binlog_status==SESSION_VARIABLE_IN_BINLOG), - because we want any statement that refers to insert_id explicitly to - be unsafe. (By "explicitly", we mean using @@session.insert_id, - whereas insert_id is used "implicitly" when NULL value is inserted - into an auto_increment column). - - We want statements referring explicitly to @@session.insert_id to be - unsafe, because insert_id is modified internally by the slave sql - thread when NULL values are inserted in an AUTO_INCREMENT column. - This modification interfers with the value of the - @@session.insert_id variable if @@session.insert_id is referred - explicitly by an insert statement (as is seen by executing "SET - @@session.insert_id=0; CREATE TABLE t (a INT, b INT KEY - AUTO_INCREMENT); INSERT INTO t(a) VALUES (@@session.insert_id);" in - statement-based logging mode: t will be different on master and - slave). -*/ -static sys_var_insert_id sys_insert_id(&vars, "insert_id"); -static sys_var_readonly sys_error_count(&vars, "error_count", - OPT_SESSION, - SHOW_LONG, - get_error_count); -static sys_var_readonly sys_warning_count(&vars, "warning_count", - OPT_SESSION, - SHOW_LONG, - get_warning_count); - -static sys_var_rand_seed1 sys_rand_seed1(&vars, "rand_seed1", - sys_var::SESSION_VARIABLE_IN_BINLOG); -static sys_var_rand_seed2 sys_rand_seed2(&vars, "rand_seed2", - sys_var::SESSION_VARIABLE_IN_BINLOG); - -static sys_var_thd_ulong sys_default_week_format(&vars, "default_week_format", - &SV::default_week_format); - -sys_var_thd_ulong sys_group_concat_max_len(&vars, "group_concat_max_len", - &SV::group_concat_max_len); - -sys_var_thd_time_zone sys_time_zone(&vars, "time_zone", - sys_var::SESSION_VARIABLE_IN_BINLOG); - -/* Global read-only variable containing hostname */ -static sys_var_const_str sys_hostname(&vars, "hostname", glob_hostname); - -#ifndef EMBEDDED_LIBRARY -static sys_var_const_str_ptr sys_repl_report_host(&vars, "report_host", &report_host); -static sys_var_const_str_ptr sys_repl_report_user(&vars, "report_user", &report_user); -static sys_var_const_str_ptr sys_repl_report_password(&vars, "report_password", &report_password); - -static uchar *slave_get_report_port(THD *thd) -{ - thd->sys_var_tmp.long_value= report_port; - return (uchar*) &thd->sys_var_tmp.long_value; -} - -static sys_var_readonly sys_repl_report_port(&vars, "report_port", OPT_GLOBAL, SHOW_LONG, slave_get_report_port); - -#endif - -sys_var_thd_bool sys_keep_files_on_create(&vars, "keep_files_on_create", - &SV::keep_files_on_create); -/* Read only variables */ - -static sys_var_have_variable sys_have_compress(&vars, "have_compress", &have_compress); -static sys_var_have_variable sys_have_crypt(&vars, "have_crypt", &have_crypt); -static sys_var_have_plugin sys_have_csv(&vars, "have_csv", C_STRING_WITH_LEN("csv"), MYSQL_STORAGE_ENGINE_PLUGIN); -static sys_var_have_variable sys_have_dlopen(&vars, "have_dynamic_loading", &have_dlopen); -static sys_var_have_variable sys_have_geometry(&vars, "have_geometry", &have_geometry); -static sys_var_have_plugin sys_have_innodb(&vars, "have_innodb", C_STRING_WITH_LEN("innodb"), MYSQL_STORAGE_ENGINE_PLUGIN); -static sys_var_have_plugin sys_have_ndbcluster(&vars, "have_ndbcluster", C_STRING_WITH_LEN("ndbcluster"), MYSQL_STORAGE_ENGINE_PLUGIN); -static sys_var_have_variable sys_have_openssl(&vars, "have_openssl", &have_ssl); -static sys_var_have_variable sys_have_ssl(&vars, "have_ssl", &have_ssl); -static sys_var_have_plugin sys_have_partition_db(&vars, "have_partitioning", C_STRING_WITH_LEN("partition"), MYSQL_STORAGE_ENGINE_PLUGIN); -static sys_var_have_variable sys_have_profiling(&vars, "have_profiling", &have_profiling); -static sys_var_have_variable sys_have_query_cache(&vars, "have_query_cache", - &have_query_cache); -static sys_var_have_variable sys_have_rtree_keys(&vars, "have_rtree_keys", &have_rtree_keys); -static sys_var_have_variable sys_have_symlink(&vars, "have_symlink", &have_symlink); -/* Global read-only variable describing server license */ -static sys_var_const_str sys_license(&vars, "license", STRINGIFY_ARG(LICENSE)); -/* Global variables which enable|disable logging */ -static sys_var_log_state sys_var_general_log(&vars, "general_log", &opt_log, - QUERY_LOG_GENERAL); -/* Synonym of "general_log" for consistency with SHOW VARIABLES output */ -static sys_var_log_state sys_var_log(&vars, "log", &opt_log, - QUERY_LOG_GENERAL); -static sys_var_log_state sys_var_slow_query_log(&vars, "slow_query_log", &opt_slow_log, - QUERY_LOG_SLOW); -/* Synonym of "slow_query_log" for consistency with SHOW VARIABLES output */ -static sys_var_log_state sys_var_log_slow(&vars, "log_slow_queries", - &opt_slow_log, QUERY_LOG_SLOW); -sys_var_str sys_var_general_log_path(&vars, "general_log_file", sys_check_log_path, - sys_update_general_log_path, - sys_default_general_log_path, - opt_logname); -sys_var_str sys_var_slow_log_path(&vars, "slow_query_log_file", sys_check_log_path, - sys_update_slow_log_path, - sys_default_slow_log_path, - opt_slow_logname); -static sys_var_log_output sys_var_log_output_state(&vars, "log_output", &log_output_options, - &log_output_typelib, 0); -static sys_var_readonly sys_myisam_mmap_size(&vars, "myisam_mmap_size", - OPT_GLOBAL, - SHOW_LONGLONG, - get_myisam_mmap_size); - - -bool sys_var::check(THD *thd, set_var *var) -{ - var->save_result.ulonglong_value= var->value->val_int(); - return 0; -} - -bool sys_var_str::check(THD *thd, set_var *var) -{ - int res; - if (!check_func) - return 0; - - if ((res=(*check_func)(thd, var)) < 0) - { - ErrConvString err(&var->value->str_value); - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, err.ptr()); - } - return res; -} - -/* - Functions to check and update variables -*/ - - -/* - Update variables 'init_connect, init_slave'. - - In case of 'DEFAULT' value - (for example: 'set GLOBAL init_connect=DEFAULT') - 'var' parameter is NULL pointer. -*/ - -bool update_sys_var_str(sys_var_str *var_str, rw_lock_t *var_mutex, - set_var *var) -{ - char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0); - uint new_length= (var ? var->value->str_value.length() : 0); - if (!old_value) - old_value= (char*) ""; - if (!(res= my_strndup(old_value, new_length, MYF(0)))) - return 1; - /* - Replace the old value in such a way that the any thread using - the value will work. - */ - rw_wrlock(var_mutex); - old_value= var_str->value; - var_str->value= res; - var_str->value_length= new_length; - var_str->is_os_charset= FALSE; - rw_unlock(var_mutex); - my_free(old_value, MYF(MY_ALLOW_ZERO_PTR)); - return 0; -} - - -static bool sys_update_init_connect(THD *thd, set_var *var) -{ - return update_sys_var_str(&sys_init_connect, &LOCK_sys_init_connect, var); -} - - -static void sys_default_init_connect(THD* thd, enum_var_type type) -{ - update_sys_var_str(&sys_init_connect, &LOCK_sys_init_connect, 0); -} - - -static bool sys_update_init_slave(THD *thd, set_var *var) -{ - return update_sys_var_str(&sys_init_slave, &LOCK_sys_init_slave, var); -} - - -static void sys_default_init_slave(THD* thd, enum_var_type type) -{ - update_sys_var_str(&sys_init_slave, &LOCK_sys_init_slave, 0); -} - -static int sys_check_ftb_syntax(THD *thd, set_var *var) -{ - if (thd->security_ctx->master_access & SUPER_ACL) - return (ft_boolean_check_syntax_string((uchar*) - var->value->str_value.c_ptr()) ? - -1 : 0); - else - { - my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); - return 1; - } -} - -static bool sys_update_ftb_syntax(THD *thd, set_var * var) -{ - strmake(ft_boolean_syntax, var->value->str_value.c_ptr(), - sizeof(ft_boolean_syntax)-1); - -#ifdef HAVE_QUERY_CACHE - query_cache.flush(); -#endif /* HAVE_QUERY_CACHE */ - - return 0; -} - -static void sys_default_ftb_syntax(THD *thd, enum_var_type type) -{ - strmake(ft_boolean_syntax, def_ft_boolean_syntax, - sizeof(ft_boolean_syntax)-1); -} - +static PolyLock_mutex PLock_global_system_variables(&LOCK_global_system_variables); /** - If one sets the LOW_PRIORIY UPDATES flag, we also must change the - used lock type. + Return variable name and length for hashing of variables. */ -static void fix_low_priority_updates(THD *thd, enum_var_type type) +static uchar *get_sys_var_length(const sys_var *var, size_t *length, + my_bool first) { - if (type == OPT_GLOBAL) - thr_upgraded_concurrent_insert_lock= - (global_system_variables.low_priority_updates ? - TL_WRITE_LOW_PRIORITY : TL_WRITE); - else - thd->update_lock_default= (thd->variables.low_priority_updates ? - TL_WRITE_LOW_PRIORITY : TL_WRITE); + *length= var->name.length; + return (uchar*) var->name.str; } +sys_var_chain all_sys_vars = { NULL, NULL }; -static void -fix_myisam_max_sort_file_size(THD *thd, enum_var_type type) +int sys_var_init() { - myisam_max_temp_length= - (my_off_t) global_system_variables.myisam_max_sort_file_size; -} + DBUG_ENTER("sys_var_init"); -/** - Set the OPTION_BIG_SELECTS flag if max_join_size == HA_POS_ERROR. -*/ + /* Must be already initialized. */ + DBUG_ASSERT(system_charset_info != NULL); -static void fix_max_join_size(THD *thd, enum_var_type type) -{ - if (type != OPT_GLOBAL) - { - if (thd->variables.max_join_size == HA_POS_ERROR) - thd->options|= OPTION_BIG_SELECTS; - else - thd->options&= ~OPTION_BIG_SELECTS; - } -} + if (my_hash_init(&system_variable_hash, system_charset_info, 100, 0, + 0, (my_hash_get_key) get_sys_var_length, 0, HASH_UNIQUE)) + goto error; + if (mysql_add_sys_var_chain(all_sys_vars.first)) + goto error; -/** - Can't change the 'next' tx_isolation while we are already in - a transaction -*/ -static int check_tx_isolation(THD *thd, set_var *var) -{ - if (var->type == OPT_DEFAULT && (thd->server_status & SERVER_STATUS_IN_TRANS)) - { - my_error(ER_CANT_CHANGE_TX_ISOLATION, MYF(0)); - return 1; - } - return 0; + DBUG_RETURN(0); + +error: + fprintf(stderr, "failed to initialize System variables"); + DBUG_RETURN(1); } -/* - If one doesn't use the SESSION modifier, the isolation level - is only active for the next command. -*/ -static void fix_tx_isolation(THD *thd, enum_var_type type) +int sys_var_add_options(DYNAMIC_ARRAY *long_options, int parse_flags) { - if (type == OPT_SESSION) - thd->session_tx_isolation= ((enum_tx_isolation) - thd->variables.tx_isolation); -} + uint saved_elements= long_options->elements; -static void fix_completion_type(THD *thd __attribute__((unused)), - enum_var_type type __attribute__((unused))) {} + DBUG_ENTER("sys_var_add_options"); -static int check_completion_type(THD *thd, set_var *var) -{ - longlong val= var->value->val_int(); - if (val < 0 || val > 2) + for (sys_var *var=all_sys_vars.first; var; var= var->next) { - char buf[64]; - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name, llstr(val, buf)); - return 1; + if (var->register_option(long_options, parse_flags)) + goto error; } - return 0; -} - -/* - If we are changing the thread variable, we have to copy it to NET too -*/ + DBUG_RETURN(0); -#ifdef HAVE_REPLICATION -static void fix_net_read_timeout(THD *thd, enum_var_type type) -{ - if (type != OPT_GLOBAL) - my_net_set_read_timeout(&thd->net, thd->variables.net_read_timeout); +error: + fprintf(stderr, "failed to initialize System variables"); + long_options->elements= saved_elements; + DBUG_RETURN(1); } - -static void fix_net_write_timeout(THD *thd, enum_var_type type) +void sys_var_end() { - if (type != OPT_GLOBAL) - my_net_set_write_timeout(&thd->net, thd->variables.net_write_timeout); -} + DBUG_ENTER("sys_var_end"); -static void fix_net_retry_count(THD *thd, enum_var_type type) -{ - if (type != OPT_GLOBAL) - thd->net.retry_count=thd->variables.net_retry_count; -} -#else /* HAVE_REPLICATION */ -static void fix_net_read_timeout(THD *thd __attribute__((unused)), - enum_var_type type __attribute__((unused))) -{} -static void fix_net_write_timeout(THD *thd __attribute__((unused)), - enum_var_type type __attribute__((unused))) -{} -static void fix_net_retry_count(THD *thd __attribute__((unused)), - enum_var_type type __attribute__((unused))) -{} -#endif /* HAVE_REPLICATION */ - -#ifdef HAVE_QUERY_CACHE -static void fix_query_cache_size(THD *thd, enum_var_type type) -{ - ulong new_cache_size= query_cache.resize(query_cache_size); + my_hash_free(&system_variable_hash); - /* - Note: query_cache_size is a global variable reflecting the - requested cache size. See also query_cache_size_arg - */ + for (sys_var *var=all_sys_vars.first; var; var= var->next) + var->~sys_var(); - if (query_cache_size != new_cache_size) - push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_WARN_QC_RESIZE, ER(ER_WARN_QC_RESIZE), - query_cache_size, new_cache_size); - - query_cache_size= new_cache_size; + DBUG_VOID_RETURN; } - /** - Trigger before query_cache_type variable is updated. - @param thd Thread handler - @param var Pointer to the new variable status - - @return Status code - @retval 1 Failure - @retval 0 Success -*/ - -static int check_query_cache_type(THD *thd, set_var *var) -{ - /* - Don't allow changes of the query_cache_type if the query cache - is disabled. - */ - if (query_cache.is_disabled()) + sys_var constructor + + @param chain variables are linked into chain for mysql_add_sys_var_chain() + @param name_arg the name of the variable. @sa my_option::name + @param comment shown in mysqld --help, @sa my_option::comment + @param flags_arg or'ed flag_enum values + @param off offset of the global variable value from the + &global_system_variables. + @param getopt_id -1 for no command-line option, otherwise @sa my_option::id + @param getopt_arg_type @sa my_option::arg_type + @param show_val_type_arg what value_ptr() returns for sql_show.cc + @param def_val default value, @sa my_option::def_value + @param lock mutex or rw_lock that protects the global variable + *in addition* to LOCK_global_system_variables. + @param binlog_status_enum @sa binlog_status_enum + @param on_check_func a function to be called at the end of sys_var::check, + put your additional checks here + @param on_update_func a function to be called at the end of sys_var::update, + any post-update activity should happen here + @param deprecated_version if not 0 - when this variable will go away + @param substitute if not 0 - what one should use instead when this + deprecated variable + @param parse_flag either PARSE_EARLY or PARSE_NORMAL +*/ +sys_var::sys_var(sys_var_chain *chain, const char *name_arg, + const char *comment, int flags_arg, ptrdiff_t off, + int getopt_id, enum get_opt_arg_type getopt_arg_type, + SHOW_TYPE show_val_type_arg, longlong def_val, + PolyLock *lock, enum binlog_status_enum binlog_status_arg, + on_check_function on_check_func, + on_update_function on_update_func, + uint deprecated_version, const char *substitute, + int parse_flag) : + next(0), + binlog_status(binlog_status_arg), + flags(flags_arg), m_parse_flag(parse_flag), show_val_type(show_val_type_arg), + guard(lock), offset(off), on_check(on_check_func), on_update(on_update_func), + is_os_charset(FALSE) +{ + name.str= name_arg; + name.length= strlen(name_arg); + DBUG_ASSERT(name.length <= NAME_CHAR_LEN); + + bzero(&option, sizeof(option)); + option.name= name_arg; + option.id= getopt_id; + option.comment= comment; + option.arg_type= getopt_arg_type; + option.value= (uchar **)global_var_ptr(); + option.def_value= def_val; + + deprecated.version= deprecated_version; + deprecated.substitute= substitute; + DBUG_ASSERT((deprecated_version != 0) || (substitute == 0)); + DBUG_ASSERT(deprecated_version % 100 == 0); + DBUG_ASSERT(!deprecated_version || MYSQL_VERSION_ID < deprecated_version); + + if (chain->last) + chain->last->next= this; + else + chain->first= this; + chain->last= this; +} + +bool sys_var::update(THD *thd, set_var *var) +{ + enum_var_type type= var->type; + if (type == OPT_GLOBAL || scope() == GLOBAL) { - my_error(ER_QUERY_CACHE_DISABLED,MYF(0)); - return 1; + /* + Yes, both locks need to be taken before an update, just as + both are taken to get a value. If we'll take only 'guard' here, + then value_ptr() for strings won't be safe in SHOW VARIABLES anymore, + to make it safe we'll need value_ptr_unlock(). + */ + AutoWLock lock1(&PLock_global_system_variables); + AutoWLock lock2(guard); + return global_update(thd, var) || + (on_update && on_update(this, thd, OPT_GLOBAL)); } - - return 0; -} - - -static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type) -{ - query_cache_min_res_unit= - query_cache.set_min_res_unit(query_cache_min_res_unit); + else + return session_update(thd, var) || + (on_update && on_update(this, thd, OPT_SESSION)); } -#endif - -extern void fix_delay_key_write(THD *thd, enum_var_type type) +uchar *sys_var::session_value_ptr(THD *thd, LEX_STRING *base) { - switch ((enum_delay_key_write) delay_key_write_options) { - case DELAY_KEY_WRITE_NONE: - myisam_delay_key_write=0; - break; - case DELAY_KEY_WRITE_ON: - myisam_delay_key_write=1; - break; - case DELAY_KEY_WRITE_ALL: - myisam_delay_key_write=1; - ha_open_options|= HA_OPEN_DELAY_KEY_WRITE; - break; - } + return session_var_ptr(thd); } -bool sys_var_set::update(THD *thd, set_var *var) +uchar *sys_var::global_value_ptr(THD *thd, LEX_STRING *base) { - *value= var->save_result.ulong_value; - return 0; + return global_var_ptr(); } -uchar *sys_var_set::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) +bool sys_var::check(THD *thd, set_var *var) { - char buff[256]; - String tmp(buff, sizeof(buff), &my_charset_latin1); - ulong length; - ulong val= *value; - - tmp.length(0); - for (uint i= 0; val; val>>= 1, i++) + do_deprecated_warning(thd); + if ((var->value && do_check(thd, var)) + || (on_check && on_check(this, thd, var))) { - if (val & 1) + if (!thd->is_error()) { - tmp.append(enum_names->type_names[i], - enum_names->type_lengths[i]); - tmp.append(','); - } - } - - if ((length= tmp.length())) - length--; - return (uchar*) thd->strmake(tmp.ptr(), length); -} - -void sys_var_set_slave_mode::set_default(THD *thd, enum_var_type type) -{ - slave_exec_mode_options= 0; - bit_do_set(slave_exec_mode_options, SLAVE_EXEC_MODE_STRICT); -} - -bool sys_var_set_slave_mode::check(THD *thd, set_var *var) -{ - bool rc= sys_var_set::check(thd, var); - if (!rc && - bit_is_set(var->save_result.ulong_value, SLAVE_EXEC_MODE_STRICT) == 1 && - bit_is_set(var->save_result.ulong_value, SLAVE_EXEC_MODE_IDEMPOTENT) == 1) - { - rc= true; - my_error(ER_SLAVE_AMBIGOUS_EXEC_MODE, MYF(0), ""); - } - return rc; -} - -bool sys_var_set_slave_mode::update(THD *thd, set_var *var) -{ - bool rc; - pthread_mutex_lock(&LOCK_global_system_variables); - rc= sys_var_set::update(thd, var); - pthread_mutex_unlock(&LOCK_global_system_variables); - return rc; -} + char buff[STRING_BUFFER_USUAL_SIZE]; + String str(buff, sizeof(buff), system_charset_info), *res; -void fix_slave_exec_mode(enum_var_type type) -{ - DBUG_ENTER("fix_slave_exec_mode"); - compile_time_assert(sizeof(slave_exec_mode_options) * CHAR_BIT - > SLAVE_EXEC_MODE_LAST_BIT - 1); - if (bit_is_set(slave_exec_mode_options, SLAVE_EXEC_MODE_STRICT) == 1 && - bit_is_set(slave_exec_mode_options, SLAVE_EXEC_MODE_IDEMPOTENT) == 1) - { - sql_print_error("Ambiguous slave modes combination." - " STRICT will be used"); - bit_do_clear(slave_exec_mode_options, SLAVE_EXEC_MODE_IDEMPOTENT); + if (!var->value) + { + str.set(STRING_WITH_LEN("DEFAULT"), &my_charset_latin1); + res= &str; + } + else if (!(res=var->value->val_str(&str))) + { + str.set(STRING_WITH_LEN("NULL"), &my_charset_latin1); + res= &str; + } + ErrConvString err(res); + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr()); + } + return true; } - if (bit_is_set(slave_exec_mode_options, SLAVE_EXEC_MODE_IDEMPOTENT) == 0) - bit_do_set(slave_exec_mode_options, SLAVE_EXEC_MODE_STRICT); - DBUG_VOID_RETURN; -} - - -bool sys_var_thd_binlog_format::check(THD *thd, set_var *var) { - /* - All variables that affect writing to binary log (either format or - turning logging on and off) use the same checking. We call the - superclass ::check function to assign the variable correctly, and - then check the value. - */ - bool result= sys_var_thd_enum::check(thd, var); - if (!result) - result= check_log_update(thd, var); - return result; + return false; } - -bool sys_var_thd_binlog_format::is_readonly() const +uchar *sys_var::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { - /* - Under certain circumstances, the variable is read-only (unchangeable): - */ - THD *thd= current_thd; - /* - If RBR and open temporary tables, their CREATE TABLE may not be in the - binlog, so we can't toggle to SBR in this connection. - The test below will also prevent SET GLOBAL, well it was not easy to test - if global or not here. - And this test will also prevent switching from RBR to RBR (a no-op which - should not happen too often). - - If we don't have row-based replication compiled in, the variable - is always read-only. - */ - if ((thd->variables.binlog_format == BINLOG_FORMAT_ROW) && - thd->temporary_tables) + if (type == OPT_GLOBAL || scope() == GLOBAL) { - my_error(ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR, MYF(0)); - return 1; + mysql_mutex_assert_owner(&LOCK_global_system_variables); + AutoRLock lock(guard); + return global_value_ptr(thd, base); } - /* - if in a stored function/trigger, it's too late to change mode - */ - if (thd->in_sub_stmt) - { - my_error(ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT, MYF(0)); - return 1; - } - return sys_var_thd_enum::is_readonly(); + else + return session_value_ptr(thd, base); } - -void fix_binlog_format_after_update(THD *thd, enum_var_type type) +bool sys_var::set_default(THD *thd, enum_var_type type) { - thd->reset_current_stmt_binlog_row_based(); -} - + LEX_STRING empty={0,0}; + set_var var(type, 0, &empty, 0); -static void fix_max_binlog_size(THD *thd, enum_var_type type) -{ - DBUG_ENTER("fix_max_binlog_size"); - DBUG_PRINT("info",("max_binlog_size=%lu max_relay_log_size=%lu", - max_binlog_size, max_relay_log_size)); - mysql_bin_log.set_max_size(max_binlog_size); -#ifdef HAVE_REPLICATION - if (!max_relay_log_size) - active_mi->rli.relay_log.set_max_size(max_binlog_size); -#endif - DBUG_VOID_RETURN; -} + if (type == OPT_GLOBAL || scope() == GLOBAL) + global_save_default(thd, &var); + else + session_save_default(thd, &var); -static void fix_max_relay_log_size(THD *thd, enum_var_type type) -{ - DBUG_ENTER("fix_max_relay_log_size"); - DBUG_PRINT("info",("max_binlog_size=%lu max_relay_log_size=%lu", - max_binlog_size, max_relay_log_size)); -#ifdef HAVE_REPLICATION - active_mi->rli.relay_log.set_max_size(max_relay_log_size ? - max_relay_log_size: max_binlog_size); -#endif - DBUG_VOID_RETURN; + return check(thd, &var) || update(thd, &var); } - -static int check_max_delayed_threads(THD *thd, set_var *var) +void sys_var::do_deprecated_warning(THD *thd) { - longlong val= var->value->val_int(); - if (var->type != OPT_GLOBAL && val != 0 && - val != (longlong) global_system_variables.max_insert_delayed_threads) + if (deprecated.version) { - char buf[64]; - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name, llstr(val, buf)); - return 1; + char buf1[NAME_CHAR_LEN + 3], buf2[10]; + strxnmov(buf1, sizeof(buf1)-1, "@@", name.str, 0); + my_snprintf(buf2, sizeof(buf2), "%d.%d", deprecated.version/100/100, + deprecated.version/100%100); + uint errmsg= deprecated.substitute + ? ER_WARN_DEPRECATED_SYNTAX_WITH_VER + : ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT; + if (thd) + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARN_DEPRECATED_SYNTAX, ER(errmsg), + buf1, buf2, deprecated.substitute); + else + sql_print_warning(ER_DEFAULT(errmsg), buf1, buf2, deprecated.substitute); } - return 0; -} - -static void fix_max_connections(THD *thd, enum_var_type type) -{ -#ifndef EMBEDDED_LIBRARY - resize_thr_alarm(max_connections + - global_system_variables.max_insert_delayed_threads + 10); -#endif } - -static void fix_thd_mem_root(THD *thd, enum_var_type type) -{ - if (type != OPT_GLOBAL) - reset_root_defaults(thd->mem_root, - thd->variables.query_alloc_block_size, - thd->variables.query_prealloc_size); -} - - -static void fix_trans_mem_root(THD *thd, enum_var_type type) -{ -#ifdef USING_TRANSACTIONS - if (type != OPT_GLOBAL) - reset_root_defaults(&thd->transaction.mem_root, - thd->variables.trans_alloc_block_size, - thd->variables.trans_prealloc_size); -#endif -} - - -static void fix_server_id(THD *thd, enum_var_type type) -{ - server_id_supplied = 1; - thd->server_id= server_id; -} - - /** Throw warning (error in STRICT mode) if value for variable needed bounding. - Only call from check(), not update(), because an error in update() would be - bad mojo. Plug-in interface also uses this. + Plug-in interface also uses this. - @param thd thread handle - @param fixed did we have to correct the value? (throw warn/err if so) - @param unsignd is value's type unsigned? - @param name variable's name - @param val variable's value + @param thd thread handle + @param name variable's name + @param fixed did we have to correct the value? (throw warn/err if so) + @param is_unsigned is value's type unsigned? + @param v variable's value - @retval TRUE on error, FALSE otherwise (warning or OK) + @retval true on error, false otherwise (warning or ok) */ -bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd, - const char *name, longlong val) +bool throw_bounds_warning(THD *thd, const char *name, + bool fixed, bool is_unsigned, longlong v) { - if (fixed) + if (fixed || (!is_unsigned && v < 0)) { char buf[22]; - if (unsignd) - ullstr((ulonglong) val, buf); + if (is_unsigned) + ullstr((ulonglong) v, buf); else - llstr(val, buf); + llstr(v, buf); if (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) { my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buf); - return TRUE; + return true; } - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_TRUNCATED_WRONG_VALUE, ER(ER_TRUNCATED_WRONG_VALUE), name, buf); } - return FALSE; -} - - -/** - check an unsigned user-supplied value for a systemvariable against bounds. - - TODO: This is a wrapper function to call clipping from within an update() - function. Calling bounds from within update() is fair game in theory, - but we can only send warnings from in there, not errors, and besides, - it violates our model of separating check from update phase. - To avoid breaking out of the server with an ASSERT() in strict mode, - we pretend we're not in strict mode when we go through here. Bug#43233 - was opened to remind us to replace this kludge with The Right Thing, - which of course is to do the check in the actual check phase, and then - throw an error or warning accordingly. - - @param thd thread handle - @param num the value to limit - @param option_limits the bounds-record, or NULL if none - */ -static void bound_unsigned(THD *thd, ulonglong *num, - const struct my_option *option_limits) -{ - if (option_limits) - { - my_bool fixed = FALSE; - ulonglong unadjusted= *num; - - *num= getopt_ull_limit_value(unadjusted, option_limits, &fixed); - - if (fixed) - { - ulong ssm= thd->variables.sql_mode; - thd->variables.sql_mode&= ~MODE_STRICT_ALL_TABLES; - throw_bounds_warning(thd, fixed, TRUE, option_limits->name, unadjusted); - thd->variables.sql_mode= ssm; - } - } -} - - -/** - Get unsigned system-variable. - Negative value does not wrap around, but becomes zero. - Check user-supplied value for a systemvariable against bounds. - If we needed to adjust the value, throw a warning or error depending - on SQL-mode. - - @param thd thread handle - @param var the system-variable to get - @param user_max a limit given with --maximum-variable-name=... or 0 - @param var_type function will bound on systems where necessary. - - @retval TRUE on error, FALSE otherwise (warning or OK) - */ -static bool get_unsigned(THD *thd, set_var *var, ulonglong user_max, - ulong var_type) -{ - int warnings= 0; - ulonglong unadjusted; - const struct my_option *limits= var->var->option_limits; - struct my_option fallback; - - /* get_unsigned() */ - if (var->value->unsigned_flag) - var->save_result.ulonglong_value= (ulonglong) var->value->val_int(); - else - { - longlong v= var->value->val_int(); - var->save_result.ulonglong_value= (ulonglong) ((v < 0) ? 0 : v); - if (v < 0) - { - warnings++; - if (throw_bounds_warning(thd, TRUE, FALSE, var->var->name, v)) - return TRUE; /* warning was promoted to error, give up */ - } - } - - unadjusted= var->save_result.ulonglong_value; - - /* max, if any */ - - if ((user_max > 0) && (unadjusted > user_max)) - { - var->save_result.ulonglong_value= user_max; - - if ((warnings == 0) && throw_bounds_warning(thd, TRUE, TRUE, - var->var->name, - (longlong) unadjusted)) - return TRUE; - - warnings++; - } - - /* - if the sysvar doesn't have a proper bounds record but the check - function would like bounding to ULONG where its size differs from - that of ULONGLONG, we make up a bogus limits record here and let - the usual suspects handle the actual limiting. - */ - - if (!limits && var_type != GET_ULL) - { - bzero(&fallback, sizeof(fallback)); - fallback.var_type= var_type; - limits= &fallback; - } - - /* fix_unsigned() */ - if (limits) - { - my_bool fixed; - - var->save_result.ulonglong_value= getopt_ull_limit_value(var->save_result. - ulonglong_value, - limits, &fixed); - - if ((warnings == 0) && throw_bounds_warning(thd, fixed, TRUE, - var->var->name, - (longlong) unadjusted)) - return TRUE; - } - - return FALSE; -} - - -bool sys_var_uint_ptr::check(THD *thd, set_var *var) -{ - var->save_result.ulong_value= (ulong) var->value->val_uint(); - return 0; -} - -bool sys_var_uint_ptr::update(THD *thd, set_var *var) -{ - *value= (uint) var->save_result.ulong_value; - return 0; -} - -void sys_var_uint_ptr::set_default(THD *thd, enum_var_type type) -{ - *value= (uint) option_limits->def_value; -} - -sys_var_long_ptr:: -sys_var_long_ptr(sys_var_chain *chain, const char *name_arg, ulong *value_ptr_arg, - sys_after_update_func after_update_arg) - :sys_var_long_ptr_global(chain, name_arg, value_ptr_arg, - &LOCK_global_system_variables, after_update_arg) -{} - - -bool sys_var_long_ptr_global::check(THD *thd, set_var *var) -{ - return get_unsigned(thd, var, 0, GET_ULONG); -} - -bool sys_var_long_ptr_global::update(THD *thd, set_var *var) -{ - pthread_mutex_lock(guard); - *value= (ulong) var->save_result.ulonglong_value; - pthread_mutex_unlock(guard); - return 0; -} - - -void sys_var_long_ptr_global::set_default(THD *thd, enum_var_type type) -{ - my_bool not_used; - pthread_mutex_lock(guard); - *value= (ulong) getopt_ull_limit_value((ulong) option_limits->def_value, - option_limits, ¬_used); - pthread_mutex_unlock(guard); -} - - -bool sys_var_ulonglong_ptr::update(THD *thd, set_var *var) -{ - ulonglong tmp= var->save_result.ulonglong_value; - pthread_mutex_lock(&LOCK_global_system_variables); - bound_unsigned(thd, &tmp, option_limits); - *value= (ulonglong) tmp; - pthread_mutex_unlock(&LOCK_global_system_variables); - return 0; -} - - -void sys_var_ulonglong_ptr::set_default(THD *thd, enum_var_type type) -{ - my_bool not_used; - pthread_mutex_lock(&LOCK_global_system_variables); - *value= getopt_ull_limit_value((ulonglong) option_limits->def_value, - option_limits, ¬_used); - pthread_mutex_unlock(&LOCK_global_system_variables); -} - - -bool sys_var_bool_ptr::update(THD *thd, set_var *var) -{ - *value= (my_bool) var->save_result.ulong_value; - return 0; -} - - -void sys_var_bool_ptr::set_default(THD *thd, enum_var_type type) -{ - *value= (my_bool) option_limits->def_value; -} - - -bool sys_var_enum::update(THD *thd, set_var *var) -{ - *value= (uint) var->save_result.ulong_value; - return 0; -} - - -uchar *sys_var_enum::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) -{ - return (uchar*) enum_names->type_names[*value]; -} - - -uchar *sys_var_enum_const::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - return (uchar*) enum_names->type_names[global_system_variables.*offset]; -} - -bool sys_var_thd_ulong::check(THD *thd, set_var *var) -{ - if (get_unsigned(thd, var, max_system_variables.*offset, GET_ULONG)) - return TRUE; - DBUG_ASSERT(var->save_result.ulonglong_value <= ULONG_MAX); - return ((check_func && (*check_func)(thd, var))); -} - -bool sys_var_thd_ulong::update(THD *thd, set_var *var) -{ - if (var->type == OPT_GLOBAL) - global_system_variables.*offset= (ulong) var->save_result.ulonglong_value; - else - thd->variables.*offset= (ulong) var->save_result.ulonglong_value; - - return 0; -} - - -void sys_var_thd_ulong::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - { - my_bool not_used; - /* We will not come here if option_limits is not set */ - global_system_variables.*offset= - (ulong) getopt_ull_limit_value((ulong) option_limits->def_value, - option_limits, ¬_used); - } - else - thd->variables.*offset= global_system_variables.*offset; -} - - -uchar *sys_var_thd_ulong::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - if (type == OPT_GLOBAL) - return (uchar*) &(global_system_variables.*offset); - return (uchar*) &(thd->variables.*offset); -} - - -bool sys_var_thd_ha_rows::update(THD *thd, set_var *var) -{ - ulonglong tmp= var->save_result.ulonglong_value; - - /* Don't use bigger value than given with --maximum-variable-name=.. */ - if ((ha_rows) tmp > max_system_variables.*offset) - tmp= max_system_variables.*offset; - - bound_unsigned(thd, &tmp, option_limits); - - if (var->type == OPT_GLOBAL) - { - /* Lock is needed to make things safe on 32 bit systems */ - pthread_mutex_lock(&LOCK_global_system_variables); - global_system_variables.*offset= (ha_rows) tmp; - pthread_mutex_unlock(&LOCK_global_system_variables); - } - else - thd->variables.*offset= (ha_rows) tmp; - return 0; -} - - -void sys_var_thd_ha_rows::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - { - my_bool not_used; - /* We will not come here if option_limits is not set */ - pthread_mutex_lock(&LOCK_global_system_variables); - global_system_variables.*offset= - (ha_rows) getopt_ull_limit_value((ha_rows) option_limits->def_value, - option_limits, ¬_used); - pthread_mutex_unlock(&LOCK_global_system_variables); - } - else - thd->variables.*offset= global_system_variables.*offset; -} - - -uchar *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - if (type == OPT_GLOBAL) - return (uchar*) &(global_system_variables.*offset); - return (uchar*) &(thd->variables.*offset); -} - -bool sys_var_thd_ulonglong::check(THD *thd, set_var *var) -{ - return get_unsigned(thd, var, max_system_variables.*offset, GET_ULL); -} - -bool sys_var_thd_ulonglong::update(THD *thd, set_var *var) -{ - if (var->type == OPT_GLOBAL) - { - /* Lock is needed to make things safe on 32 bit systems */ - pthread_mutex_lock(&LOCK_global_system_variables); - global_system_variables.*offset= (ulonglong) - var->save_result.ulonglong_value; - pthread_mutex_unlock(&LOCK_global_system_variables); - } - else - thd->variables.*offset= (ulonglong) var->save_result.ulonglong_value; - return 0; -} - - -void sys_var_thd_ulonglong::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - { - my_bool not_used; - pthread_mutex_lock(&LOCK_global_system_variables); - global_system_variables.*offset= - getopt_ull_limit_value((ulonglong) option_limits->def_value, - option_limits, ¬_used); - pthread_mutex_unlock(&LOCK_global_system_variables); - } - else - thd->variables.*offset= global_system_variables.*offset; -} - - -uchar *sys_var_thd_ulonglong::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - if (type == OPT_GLOBAL) - return (uchar*) &(global_system_variables.*offset); - return (uchar*) &(thd->variables.*offset); -} - - -bool sys_var_thd_bool::update(THD *thd, set_var *var) -{ - if (var->type == OPT_GLOBAL) - global_system_variables.*offset= (my_bool) var->save_result.ulong_value; - else - thd->variables.*offset= (my_bool) var->save_result.ulong_value; - return 0; -} - - -void sys_var_thd_bool::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - global_system_variables.*offset= (my_bool) option_limits->def_value; - else - thd->variables.*offset= global_system_variables.*offset; -} - - -uchar *sys_var_thd_bool::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - if (type == OPT_GLOBAL) - return (uchar*) &(global_system_variables.*offset); - return (uchar*) &(thd->variables.*offset); -} - - -bool sys_var::check_enum(THD *thd, set_var *var, const TYPELIB *enum_names) -{ - char buff[STRING_BUFFER_USUAL_SIZE]; - const char *value; - String str(buff, sizeof(buff), system_charset_info), *res; - - if (var->value->result_type() == STRING_RESULT) - { - if (!(res=var->value->val_str(&str)) || - ((long) (var->save_result.ulong_value= - (ulong) find_type(enum_names, res->ptr(), - res->length(), FALSE) - 1)) < 0) - { - if (res) - { - ErrConvString err(res); - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, err.ptr()); - return 1; - } - value= "NULL"; - goto err; - } - } - else - { - ulonglong tmp=var->value->val_int(); - if (tmp >= enum_names->count) - { - llstr(tmp,buff); - value=buff; // Wrong value is here - goto err; - } - var->save_result.ulong_value= (ulong) tmp; // Save for update - } - return 0; - -err: - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, value); - return 1; + return false; } - -bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names) +bool throw_bounds_warning(THD *thd, const char *name, bool fixed, double v) { - bool not_used; - char buff[STRING_BUFFER_USUAL_SIZE], *error= 0; - uint error_len= 0; - String str(buff, sizeof(buff), system_charset_info), *res; - - if (var->value->result_type() == STRING_RESULT) - { - if (!(res= var->value->val_str(&str))) - { - strmov(buff, "NULL"); - goto err; - } - - if (!m_allow_empty_value && - res->length() == 0) - { - buff[0]= 0; - goto err; - } - - var->save_result.ulong_value= ((ulong) - find_set(enum_names, res->c_ptr(), - res->length(), - NULL, - &error, &error_len, - ¬_used)); - if (error_len) - { - ErrConvString err(error, error_len, res->charset()); - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, err.ptr()); - return 1; - } - } - else + if (fixed) { - ulonglong tmp= var->value->val_int(); + char buf[64]; - if (!m_allow_empty_value && - tmp == 0) - { - buff[0]= '0'; - buff[1]= 0; - goto err; - } + my_gcvt(v, MY_GCVT_ARG_DOUBLE, sizeof(buf) - 1, buf, NULL); - /* - For when the enum is made to contain 64 elements, as 1ULL<<64 is - undefined, we guard with a "count<64" test. - */ - if (unlikely((tmp >= ((ULL(1)) << enum_names->count)) && - (enum_names->count < 64))) + if (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES) { - llstr(tmp, buff); - goto err; + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buf); + return true; } - var->save_result.ulong_value= (ulong) tmp; // Save for update + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRUNCATED_WRONG_VALUE, + ER(ER_TRUNCATED_WRONG_VALUE), name, buf); } - return 0; - -err: - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buff); - return 1; + return false; } - CHARSET_INFO *sys_var::charset(THD *thd) { - return is_os_charset ? thd->variables.character_set_filesystem : + return is_os_charset ? thd->variables.character_set_filesystem : system_charset_info; } - -bool sys_var_thd_enum::update(THD *thd, set_var *var) -{ - if (var->type == OPT_GLOBAL) - global_system_variables.*offset= var->save_result.ulong_value; - else - thd->variables.*offset= var->save_result.ulong_value; - return 0; -} - - -void sys_var_thd_enum::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - global_system_variables.*offset= (ulong) option_limits->def_value; - else - thd->variables.*offset= global_system_variables.*offset; -} - - -uchar *sys_var_thd_enum::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - ulong tmp= ((type == OPT_GLOBAL) ? - global_system_variables.*offset : - thd->variables.*offset); - return (uchar*) enum_names->type_names[tmp]; -} - -bool sys_var_thd_bit::check(THD *thd, set_var *var) -{ - return (check_enum(thd, var, &bool_typelib) || - (check_func && (*check_func)(thd, var))); -} - -bool sys_var_thd_bit::update(THD *thd, set_var *var) -{ - int res= (*update_func)(thd, var); - return res; -} - - -uchar *sys_var_thd_bit::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - /* - If reverse is 0 (default) return 1 if bit is set. - If reverse is 1, return 0 if bit is set - */ - thd->sys_var_tmp.my_bool_value= ((thd->options & bit_flag) ? - !reverse : reverse); - return (uchar*) &thd->sys_var_tmp.my_bool_value; -} - - -/** Update a date_time format variable based on given value. */ - -void sys_var_thd_date_time_format::update2(THD *thd, enum_var_type type, - DATE_TIME_FORMAT *new_value) -{ - DATE_TIME_FORMAT *old; - DBUG_ENTER("sys_var_date_time_format::update2"); - DBUG_DUMP("positions", (uchar*) new_value->positions, - sizeof(new_value->positions)); - - if (type == OPT_GLOBAL) - { - pthread_mutex_lock(&LOCK_global_system_variables); - old= (global_system_variables.*offset); - (global_system_variables.*offset)= new_value; - pthread_mutex_unlock(&LOCK_global_system_variables); - } - else - { - old= (thd->variables.*offset); - (thd->variables.*offset)= new_value; - } - my_free((char*) old, MYF(MY_ALLOW_ZERO_PTR)); - DBUG_VOID_RETURN; -} - - -bool sys_var_thd_date_time_format::update(THD *thd, set_var *var) -{ - DATE_TIME_FORMAT *new_value; - /* We must make a copy of the last value to get it into normal memory */ - new_value= date_time_format_copy((THD*) 0, - var->save_result.date_time_format); - if (!new_value) - return 1; // Out of memory - update2(thd, var->type, new_value); // Can't fail - return 0; -} - - -bool sys_var_thd_date_time_format::check(THD *thd, set_var *var) -{ - char buff[STRING_BUFFER_USUAL_SIZE]; - String str(buff,sizeof(buff), system_charset_info), *res; - DATE_TIME_FORMAT *format; - - if (!(res=var->value->val_str(&str))) - res= &my_empty_string; - - if (!(format= date_time_format_make(date_time_type, - res->ptr(), res->length()))) - { - ErrConvString err(res); - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, err.ptr()); - return 1; - } - - /* - We must copy result to thread space to not get a memory leak if - update is aborted - */ - var->save_result.date_time_format= date_time_format_copy(thd, format); - my_free((char*) format, MYF(0)); - return var->save_result.date_time_format == 0; -} - - -void sys_var_thd_date_time_format::set_default(THD *thd, enum_var_type type) -{ - DATE_TIME_FORMAT *res= 0; - - if (type == OPT_GLOBAL) - { - const char *format; - if ((format= opt_date_time_formats[date_time_type])) - res= date_time_format_make(date_time_type, format, strlen(format)); - } - else - { - /* Make copy with malloc */ - res= date_time_format_copy((THD *) 0, global_system_variables.*offset); - } - - if (res) // Should always be true - update2(thd, type, res); -} - - -uchar *sys_var_thd_date_time_format::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - if (type == OPT_GLOBAL) - { - char *res; - /* - We do a copy here just to be sure things will work even if someone - is modifying the original string while the copy is accessed - (Can't happen now in SQL SHOW, but this is a good safety for the future) - */ - res= thd->strmake((global_system_variables.*offset)->format.str, - (global_system_variables.*offset)->format.length); - return (uchar*) res; - } - return (uchar*) (thd->variables.*offset)->format.str; -} - - typedef struct old_names_map_st { const char *old_name; const char *new_name; } my_old_conv; -static my_old_conv old_conv[]= -{ - { "cp1251_koi8" , "cp1251" }, - { "cp1250_latin2" , "cp1250" }, - { "kam_latin2" , "keybcs2" }, - { "mac_latin2" , "MacRoman" }, - { "macce_latin2" , "MacCE" }, - { "pc2_latin2" , "pclatin2" }, - { "vga_latin2" , "pclatin1" }, - { "koi8_cp1251" , "koi8r" }, - { "win1251ukr_koi8_ukr" , "win1251ukr" }, - { "koi8_ukr_win1251ukr" , "koi8u" }, - { NULL , NULL } +static my_old_conv old_conv[]= +{ + { "cp1251_koi8" , "cp1251" }, + { "cp1250_latin2" , "cp1250" }, + { "kam_latin2" , "keybcs2" }, + { "mac_latin2" , "MacRoman" }, + { "macce_latin2" , "MacCE" }, + { "pc2_latin2" , "pclatin2" }, + { "vga_latin2" , "pclatin1" }, + { "koi8_cp1251" , "koi8r" }, + { "win1251ukr_koi8_ukr" , "win1251ukr" }, + { "koi8_ukr_win1251ukr" , "koi8u" }, + { NULL , NULL } }; CHARSET_INFO *get_old_charset_by_name(const char *name) { my_old_conv *conv; - + for (conv= old_conv; conv->old_name; conv++) { if (!my_strcasecmp(&my_charset_latin1, name, conv->old_name)) @@ -2158,1169 +356,6 @@ CHARSET_INFO *get_old_charset_by_name(const char *name) return NULL; } - -bool sys_var_collation::check(THD *thd, set_var *var) -{ - CHARSET_INFO *tmp; - LINT_INIT(tmp); - - if (var->value->result_type() == STRING_RESULT) - { - char buff[STRING_BUFFER_USUAL_SIZE]; - String str(buff,sizeof(buff), system_charset_info), *res; - if (!(res=var->value->val_str(&str))) - { - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL"); - return 1; - } - if (!(tmp=get_charset_by_name(res->c_ptr(),MYF(0)))) - { - ErrConvString err(res); - my_error(ER_UNKNOWN_COLLATION, MYF(0), err.ptr()); - return 1; - } - } - else // INT_RESULT - { - if (!(tmp=get_charset((int) var->value->val_int(),MYF(0)))) - { - char buf[20]; - int10_to_str((int) var->value->val_int(), buf, -10); - my_error(ER_UNKNOWN_COLLATION, MYF(0), buf); - return 1; - } - } - var->save_result.charset= tmp; // Save for update - return 0; -} - - -bool sys_var_character_set::check(THD *thd, set_var *var) -{ - CHARSET_INFO *tmp; - LINT_INIT(tmp); - - if (var->value->result_type() == STRING_RESULT) - { - char buff[STRING_BUFFER_USUAL_SIZE]; - String str(buff,sizeof(buff), system_charset_info), *res; - if (!(res=var->value->val_str(&str))) - { - if (!nullable) - { - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL"); - return 1; - } - tmp= NULL; - } - else if (!(tmp=get_charset_by_csname(res->c_ptr(),MY_CS_PRIMARY,MYF(0))) && - !(tmp=get_old_charset_by_name(res->c_ptr()))) - { - ErrConvString err(res); - my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), err.ptr()); - return 1; - } - } - else // INT_RESULT - { - if (!(tmp=get_charset((int) var->value->val_int(),MYF(0)))) - { - char buf[20]; - int10_to_str((int) var->value->val_int(), buf, -10); - my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), buf); - return 1; - } - } - var->save_result.charset= tmp; // Save for update - return 0; -} - - -bool sys_var_character_set::update(THD *thd, set_var *var) -{ - ci_ptr(thd,var->type)[0]= var->save_result.charset; - thd->update_charset(); - return 0; -} - - -uchar *sys_var_character_set::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - CHARSET_INFO *cs= ci_ptr(thd,type)[0]; - return cs ? (uchar*) cs->csname : (uchar*) NULL; -} - - -void sys_var_character_set_sv::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - global_system_variables.*offset= *global_default; - else - { - thd->variables.*offset= global_system_variables.*offset; - thd->update_charset(); - } -} -CHARSET_INFO **sys_var_character_set_sv::ci_ptr(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - return &(global_system_variables.*offset); - else - return &(thd->variables.*offset); -} - - -bool sys_var_character_set_client::check(THD *thd, set_var *var) -{ - if (sys_var_character_set_sv::check(thd, var)) - return 1; - /* Currently, UCS-2 cannot be used as a client character set */ - if (var->save_result.charset->mbminlen > 1) - { - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, - var->save_result.charset->csname); - return 1; - } - return 0; -} - - -CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd, - enum_var_type type) -{ - if (type == OPT_GLOBAL) - return &global_system_variables.collation_database; - else - return &thd->variables.collation_database; -} - - -void sys_var_character_set_database::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - global_system_variables.collation_database= default_charset_info; - else - { - thd->variables.collation_database= thd->db_charset; - thd->update_charset(); - } -} - - -bool sys_var_collation_sv::update(THD *thd, set_var *var) -{ - if (var->type == OPT_GLOBAL) - global_system_variables.*offset= var->save_result.charset; - else - { - thd->variables.*offset= var->save_result.charset; - thd->update_charset(); - } - return 0; -} - - -void sys_var_collation_sv::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - global_system_variables.*offset= *global_default; - else - { - thd->variables.*offset= global_system_variables.*offset; - thd->update_charset(); - } -} - - -uchar *sys_var_collation_sv::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - CHARSET_INFO *cs= ((type == OPT_GLOBAL) ? - global_system_variables.*offset : thd->variables.*offset); - return cs ? (uchar*) cs->name : (uchar*) "NULL"; -} - - -LEX_STRING default_key_cache_base= {(char *) "default", 7 }; - -static KEY_CACHE zero_key_cache; - -KEY_CACHE *get_key_cache(LEX_STRING *cache_name) -{ - safe_mutex_assert_owner(&LOCK_global_system_variables); - if (!cache_name || ! cache_name->length) - cache_name= &default_key_cache_base; - return ((KEY_CACHE*) find_named(&key_caches, - cache_name->str, cache_name->length, 0)); -} - - -uchar *sys_var_key_cache_param::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - KEY_CACHE *key_cache= get_key_cache(base); - if (!key_cache) - key_cache= &zero_key_cache; - return (uchar*) key_cache + offset ; -} - - -bool sys_var_key_buffer_size::update(THD *thd, set_var *var) -{ - ulonglong tmp= var->save_result.ulonglong_value; - LEX_STRING *base_name= &var->base; - KEY_CACHE *key_cache; - bool error= 0; - - /* If no basename, assume it's for the key cache named 'default' */ - if (!base_name->length) - base_name= &default_key_cache_base; - - pthread_mutex_lock(&LOCK_global_system_variables); - key_cache= get_key_cache(base_name); - - if (!key_cache) - { - /* Key cache didn't exists */ - if (!tmp) // Tried to delete cache - goto end; // Ok, nothing to do - if (!(key_cache= create_key_cache(base_name->str, base_name->length))) - { - error= 1; - goto end; - } - } - - /* - Abort if some other thread is changing the key cache - TODO: This should be changed so that we wait until the previous - assignment is done and then do the new assign - */ - if (key_cache->in_init) - goto end; - - if (!tmp) // Zero size means delete - { - if (key_cache == dflt_key_cache) - { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_WARN_CANT_DROP_DEFAULT_KEYCACHE, - ER(ER_WARN_CANT_DROP_DEFAULT_KEYCACHE)); - goto end; // Ignore default key cache - } - - if (key_cache->key_cache_inited) // If initied - { - /* - Move tables using this key cache to the default key cache - and clear the old key cache. - */ - NAMED_LIST *list; - key_cache= (KEY_CACHE *) find_named(&key_caches, base_name->str, - base_name->length, &list); - key_cache->in_init= 1; - pthread_mutex_unlock(&LOCK_global_system_variables); - error= reassign_keycache_tables(thd, key_cache, dflt_key_cache); - pthread_mutex_lock(&LOCK_global_system_variables); - key_cache->in_init= 0; - } - /* - We don't delete the key cache as some running threads my still be - in the key cache code with a pointer to the deleted (empty) key cache - */ - goto end; - } - - bound_unsigned(thd, &tmp, option_limits); - key_cache->param_buff_size= (ulonglong) tmp; - - /* If key cache didn't exist initialize it, else resize it */ - key_cache->in_init= 1; - pthread_mutex_unlock(&LOCK_global_system_variables); - - if (!key_cache->key_cache_inited) - error= (bool) (ha_init_key_cache("", key_cache)); - else - error= (bool)(ha_resize_key_cache(key_cache)); - - pthread_mutex_lock(&LOCK_global_system_variables); - key_cache->in_init= 0; - -end: - pthread_mutex_unlock(&LOCK_global_system_variables); - return error; -} - - -/** - @todo - Abort if some other thread is changing the key cache. - This should be changed so that we wait until the previous - assignment is done and then do the new assign -*/ -bool sys_var_key_cache_long::update(THD *thd, set_var *var) -{ - ulonglong tmp= var->value->val_int(); - LEX_STRING *base_name= &var->base; - bool error= 0; - - if (!base_name->length) - base_name= &default_key_cache_base; - - pthread_mutex_lock(&LOCK_global_system_variables); - KEY_CACHE *key_cache= get_key_cache(base_name); - - if (!key_cache && !(key_cache= create_key_cache(base_name->str, - base_name->length))) - { - error= 1; - goto end; - } - - /* - Abort if some other thread is changing the key cache - TODO: This should be changed so that we wait until the previous - assignment is done and then do the new assign - */ - if (key_cache->in_init) - goto end; - - bound_unsigned(thd, &tmp, option_limits); - *((ulong*) (((char*) key_cache) + offset))= (ulong) tmp; - - /* - Don't create a new key cache if it didn't exist - (key_caches are created only when the user sets block_size) - */ - key_cache->in_init= 1; - - pthread_mutex_unlock(&LOCK_global_system_variables); - - error= (bool) (ha_resize_key_cache(key_cache)); - - pthread_mutex_lock(&LOCK_global_system_variables); - key_cache->in_init= 0; - -end: - pthread_mutex_unlock(&LOCK_global_system_variables); - return error; -} - - -bool sys_var_log_state::update(THD *thd, set_var *var) -{ - bool res; - - if (this == &sys_var_log) - WARN_DEPRECATED(thd, "7.0", "@@log", "'@@general_log'"); - else if (this == &sys_var_log_slow) - WARN_DEPRECATED(thd, "7.0", "@@log_slow_queries", "'@@slow_query_log'"); - - pthread_mutex_lock(&LOCK_global_system_variables); - if (!var->save_result.ulong_value) - { - logger.deactivate_log_handler(thd, log_type); - res= false; - } - else - res= logger.activate_log_handler(thd, log_type); - pthread_mutex_unlock(&LOCK_global_system_variables); - return res; -} - -void sys_var_log_state::set_default(THD *thd, enum_var_type type) -{ - if (this == &sys_var_log) - WARN_DEPRECATED(thd, "7.0", "@@log", "'@@general_log'"); - else if (this == &sys_var_log_slow) - WARN_DEPRECATED(thd, "7.0", "@@log_slow_queries", "'@@slow_query_log'"); - - pthread_mutex_lock(&LOCK_global_system_variables); - logger.deactivate_log_handler(thd, log_type); - pthread_mutex_unlock(&LOCK_global_system_variables); -} - - -static int sys_check_log_path(THD *thd, set_var *var) -{ - char path[FN_REFLEN], buff[FN_REFLEN]; - MY_STAT f_stat; - String str(buff, sizeof(buff), system_charset_info), *res; - const char *log_file_str; - size_t path_length; - - if (!(res= var->value->val_str(&str))) - goto err; - - log_file_str= res->c_ptr(); - bzero(&f_stat, sizeof(MY_STAT)); - - path_length= unpack_filename(path, log_file_str); - - if (!path_length) - { - /* File name is empty. */ - - goto err; - } - - if (my_stat(path, &f_stat, MYF(0))) - { - /* - A file system object exists. Check if argument is a file and we have - 'write' permission. - */ - - if (!MY_S_ISREG(f_stat.st_mode) || - !(f_stat.st_mode & MY_S_IWRITE)) - goto err; - - return 0; - } - - /* Get dirname of the file path. */ - (void) dirname_part(path, log_file_str, &path_length); - - /* Dirname is empty if file path is relative. */ - if (!path_length) - return 0; - - /* - Check if directory exists and we have permission to create file and - write to file. - */ - if (my_access(path, (F_OK|W_OK))) - goto err; - - return 0; - -err: - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name, - res ? log_file_str : "NULL"); - return 1; -} - - -bool update_sys_var_str_path(THD *thd, sys_var_str *var_str, - set_var *var, const char *log_ext, - bool log_state, uint log_type) -{ - MYSQL_QUERY_LOG *file_log; - char buff[FN_REFLEN]; - char *res= 0, *old_value= 0; - bool result= 0; - uint str_length= 0; - - if (var) - { - String str(buff, sizeof(buff), system_charset_info), *newval; - - newval= var->value->val_str(&str); - old_value= newval->c_ptr_safe(); - str_length= strlen(old_value); - } - - - - switch (log_type) { - case QUERY_LOG_SLOW: - file_log= logger.get_slow_log_file_handler(); - break; - case QUERY_LOG_GENERAL: - file_log= logger.get_log_file_handler(); - break; - default: - assert(0); // Impossible - } - - if (!old_value) - { - old_value= make_default_log_name(buff, log_ext); - str_length= strlen(old_value); - } - if (!(res= my_strndup(old_value, str_length, MYF(MY_FAE+MY_WME)))) - { - result= 1; - goto err; - } - - pthread_mutex_lock(&LOCK_global_system_variables); - logger.lock_exclusive(); - - if (file_log && log_state) - file_log->close(0); - old_value= var_str->value; - var_str->value= res; - var_str->value_length= str_length; - my_free(old_value, MYF(MY_ALLOW_ZERO_PTR)); - if (file_log && log_state) - { - switch (log_type) { - case QUERY_LOG_SLOW: - file_log->open_slow_log(sys_var_slow_log_path.value); - break; - case QUERY_LOG_GENERAL: - file_log->open_query_log(sys_var_general_log_path.value); - break; - default: - DBUG_ASSERT(0); - } - } - - logger.unlock(); - pthread_mutex_unlock(&LOCK_global_system_variables); - -err: - return result; -} - - -static bool sys_update_general_log_path(THD *thd, set_var * var) -{ - return update_sys_var_str_path(thd, &sys_var_general_log_path, - var, ".log", opt_log, QUERY_LOG_GENERAL); -} - - -static void sys_default_general_log_path(THD *thd, enum_var_type type) -{ - (void) update_sys_var_str_path(thd, &sys_var_general_log_path, - 0, ".log", opt_log, QUERY_LOG_GENERAL); -} - - -static bool sys_update_slow_log_path(THD *thd, set_var * var) -{ - return update_sys_var_str_path(thd, &sys_var_slow_log_path, - var, "-slow.log", opt_slow_log, - QUERY_LOG_SLOW); -} - - -static void sys_default_slow_log_path(THD *thd, enum_var_type type) -{ - (void) update_sys_var_str_path(thd, &sys_var_slow_log_path, - 0, "-slow.log", opt_slow_log, - QUERY_LOG_SLOW); -} - - -bool sys_var_log_output::update(THD *thd, set_var *var) -{ - pthread_mutex_lock(&LOCK_global_system_variables); - logger.lock_exclusive(); - logger.init_slow_log(var->save_result.ulong_value); - logger.init_general_log(var->save_result.ulong_value); - *value= var->save_result.ulong_value; - logger.unlock(); - pthread_mutex_unlock(&LOCK_global_system_variables); - return 0; -} - - -void sys_var_log_output::set_default(THD *thd, enum_var_type type) -{ - pthread_mutex_lock(&LOCK_global_system_variables); - logger.lock_exclusive(); - logger.init_slow_log(LOG_FILE); - logger.init_general_log(LOG_FILE); - *value= LOG_FILE; - logger.unlock(); - pthread_mutex_unlock(&LOCK_global_system_variables); -} - - -uchar *sys_var_log_output::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - char buff[256]; - String tmp(buff, sizeof(buff), &my_charset_latin1); - ulong length; - ulong val= *value; - - tmp.length(0); - for (uint i= 0; val; val>>= 1, i++) - { - if (val & 1) - { - tmp.append(log_output_typelib.type_names[i], - log_output_typelib.type_lengths[i]); - tmp.append(','); - } - } - - if ((length= tmp.length())) - length--; - return (uchar*) thd->strmake(tmp.ptr(), length); -} - - -/***************************************************************************** - Functions to handle SET NAMES and SET CHARACTER SET -*****************************************************************************/ - -int set_var_collation_client::check(THD *thd) -{ - /* Currently, UCS-2 cannot be used as a client character set */ - if (character_set_client->mbminlen > 1) - { - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "character_set_client", - character_set_client->csname); - return 1; - } - return 0; -} - -int set_var_collation_client::update(THD *thd) -{ - thd->variables.character_set_client= character_set_client; - thd->variables.character_set_results= character_set_results; - thd->variables.collation_connection= collation_connection; - thd->update_charset(); - thd->protocol_text.init(thd); - thd->protocol_binary.init(thd); - return 0; -} - -/****************************************************************************/ - -bool sys_var_timestamp::update(THD *thd, set_var *var) -{ - thd->set_time((time_t) var->save_result.ulonglong_value); - return 0; -} - - -void sys_var_timestamp::set_default(THD *thd, enum_var_type type) -{ - thd->user_time=0; -} - - -uchar *sys_var_timestamp::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - thd->sys_var_tmp.long_value= (long) thd->start_time; - return (uchar*) &thd->sys_var_tmp.long_value; -} - - -bool sys_var_last_insert_id::update(THD *thd, set_var *var) -{ - thd->first_successful_insert_id_in_prev_stmt= - var->save_result.ulonglong_value; - return 0; -} - - -uchar *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - /* - this tmp var makes it robust againt change of type of - read_first_successful_insert_id_in_prev_stmt(). - */ - thd->sys_var_tmp.ulonglong_value= - thd->read_first_successful_insert_id_in_prev_stmt(); - return (uchar*) &thd->sys_var_tmp.ulonglong_value; -} - - -bool sys_var_insert_id::update(THD *thd, set_var *var) -{ - thd->force_one_auto_inc_interval(var->save_result.ulonglong_value); - return 0; -} - - -uchar *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - thd->sys_var_tmp.ulonglong_value= - thd->auto_inc_intervals_forced.minimum(); - return (uchar*) &thd->sys_var_tmp.ulonglong_value; -} - - -bool sys_var_rand_seed1::update(THD *thd, set_var *var) -{ - thd->rand.seed1= (ulong) var->save_result.ulonglong_value; - return 0; -} - -bool sys_var_rand_seed2::update(THD *thd, set_var *var) -{ - thd->rand.seed2= (ulong) var->save_result.ulonglong_value; - return 0; -} - - -bool sys_var_thd_time_zone::check(THD *thd, set_var *var) -{ - char buff[MAX_TIME_ZONE_NAME_LENGTH]; - String str(buff, sizeof(buff), &my_charset_latin1); - String *res= var->value->val_str(&str); - - if (!(var->save_result.time_zone= my_tz_find(thd, res))) - { - my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), res ? res->c_ptr() : "NULL"); - return 1; - } - return 0; -} - - -bool sys_var_thd_time_zone::update(THD *thd, set_var *var) -{ - /* We are using Time_zone object found during check() phase. */ - if (var->type == OPT_GLOBAL) - { - pthread_mutex_lock(&LOCK_global_system_variables); - global_system_variables.time_zone= var->save_result.time_zone; - pthread_mutex_unlock(&LOCK_global_system_variables); - } - else - thd->variables.time_zone= var->save_result.time_zone; - return 0; -} - - -uchar *sys_var_thd_time_zone::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - /* - We can use ptr() instead of c_ptr() here because String contaning - time zone name is guaranteed to be zero ended. - */ - if (type == OPT_GLOBAL) - return (uchar *)(global_system_variables.time_zone->get_name()->ptr()); - else - { - /* - This is an ugly fix for replication: we don't replicate properly queries - invoking system variables' values to update tables; but - CONVERT_TZ(,,@@session.time_zone) is so popular that we make it - replicable (i.e. we tell the binlog code to store the session - timezone). If it's the global value which was used we can't replicate - (binlog code stores session value only). - */ - thd->time_zone_used= 1; - return (uchar *)(thd->variables.time_zone->get_name()->ptr()); - } -} - - -void sys_var_thd_time_zone::set_default(THD *thd, enum_var_type type) -{ - pthread_mutex_lock(&LOCK_global_system_variables); - if (type == OPT_GLOBAL) - { - if (default_tz_name) - { - String str(default_tz_name, &my_charset_latin1); - /* - We are guaranteed to find this time zone since its existence - is checked during start-up. - */ - global_system_variables.time_zone= my_tz_find(thd, &str); - } - else - global_system_variables.time_zone= my_tz_SYSTEM; - } - else - thd->variables.time_zone= global_system_variables.time_zone; - pthread_mutex_unlock(&LOCK_global_system_variables); -} - - -bool sys_var_max_user_conn::check(THD *thd, set_var *var) -{ - if (var->type == OPT_GLOBAL) - return sys_var_thd::check(thd, var); - else - { - /* - Per-session values of max_user_connections can't be set directly. - May be we should have a separate error message for this? - */ - my_error(ER_GLOBAL_VARIABLE, MYF(0), name); - return TRUE; - } -} - -bool sys_var_max_user_conn::update(THD *thd, set_var *var) -{ - DBUG_ASSERT(var->type == OPT_GLOBAL); - pthread_mutex_lock(&LOCK_global_system_variables); - max_user_connections= (uint)var->save_result.ulonglong_value; - pthread_mutex_unlock(&LOCK_global_system_variables); - return 0; -} - - -void sys_var_max_user_conn::set_default(THD *thd, enum_var_type type) -{ - DBUG_ASSERT(type == OPT_GLOBAL); - pthread_mutex_lock(&LOCK_global_system_variables); - max_user_connections= (ulong) option_limits->def_value; - pthread_mutex_unlock(&LOCK_global_system_variables); -} - - -uchar *sys_var_max_user_conn::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - if (type != OPT_GLOBAL && - thd->user_connect && thd->user_connect->user_resources.user_conn) - return (uchar*) &(thd->user_connect->user_resources.user_conn); - return (uchar*) &(max_user_connections); -} - - -bool sys_var_thd_ulong_session_readonly::check(THD *thd, set_var *var) -{ - if (var->type != OPT_GLOBAL) - { - my_error(ER_VARIABLE_IS_READONLY, MYF(0), "SESSION", name, "GLOBAL"); - return TRUE; - } - - return sys_var_thd_ulong::check(thd, var); -} - - -static MY_LOCALE *check_locale(THD *thd, const char *name, set_var *var) -{ - MY_LOCALE *locale_match; - - if (var->value->result_type() == INT_RESULT) - { - if (!(locale_match= my_locale_by_number((uint) var->value->val_int()))) - { - char buf[20]; - int10_to_str((int) var->value->val_int(), buf, -10); - my_printf_error(ER_UNKNOWN_LOCALE, ER(ER_UNKNOWN_LOCALE), MYF(0), buf); - return 0; - } - } - else // STRING_RESULT - { - char buff[6]; - String str(buff, sizeof(buff), system_charset_info), *res; - if (!(res=var->value->val_str(&str))) - { - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL"); - return 0; - } - const char *locale_str= res->c_ptr(); - if (!(locale_match= my_locale_by_name(locale_str))) - { - my_printf_error(ER_UNKNOWN_LOCALE, ER(ER_UNKNOWN_LOCALE), - MYF(0), locale_str); - return 0; - } - } - - return var->save_result.locale_value= locale_match; -} - - -bool sys_var_thd_lc::check(THD *thd, set_var *var) -{ - MY_LOCALE *locale_match; - - if (!(locale_match= check_locale(thd, name, var))) - return 1; - return 0; -} - - -bool sys_var_thd_lc_time_names::update(THD *thd, set_var *var) -{ - if (var->type == OPT_GLOBAL) - global_system_variables.lc_time_names= var->save_result.locale_value; - else - thd->variables.lc_time_names= var->save_result.locale_value; - return 0; -} - - -uchar *sys_var_thd_lc_time_names::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - return type == OPT_GLOBAL ? - (uchar *) global_system_variables.lc_time_names->name : - (uchar *) thd->variables.lc_time_names->name; -} - - -void sys_var_thd_lc_time_names::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - global_system_variables.lc_time_names= my_default_lc_time_names; - else - thd->variables.lc_time_names= global_system_variables.lc_time_names; -} - - -bool sys_var_thd_lc_messages::update(THD *thd, set_var *var) -{ - MY_LOCALE *locale= var->save_result.locale_value; - - if (!locale->errmsgs->errmsgs) - { - pthread_mutex_lock(&LOCK_error_messages); - if (!locale->errmsgs->errmsgs && - read_texts(ERRMSG_FILE, locale->errmsgs->language, - &locale->errmsgs->errmsgs, - ER_ERROR_LAST - ER_ERROR_FIRST + 1)) - { - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_UNKNOWN_ERROR, - "Can't process error message file for locale '%s'", - locale->name); - pthread_mutex_unlock(&LOCK_error_messages); - return 0; - } - pthread_mutex_unlock(&LOCK_error_messages); - } - - if (var->type == OPT_GLOBAL) - global_system_variables.lc_messages= locale; - else - thd->variables.lc_messages= locale; - - return 0; -} - - -uchar *sys_var_thd_lc_messages::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - return type == OPT_GLOBAL ? - (uchar *) global_system_variables.lc_messages->name : - (uchar *) thd->variables.lc_messages->name; -} - - -void sys_var_thd_lc_messages::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - global_system_variables.lc_messages= my_default_lc_messages; - else - thd->variables.lc_messages= global_system_variables.lc_messages; -} - - -/* - Handling of microseoncds given as seconds.part_seconds - - NOTES - The argument to long query time is in seconds in decimal - which is converted to ulonglong integer holding microseconds for storage. - This is used for handling long_query_time -*/ - -bool sys_var_microseconds::update(THD *thd, set_var *var) -{ - double num= var->value->val_real(); - longlong microseconds; - if (num > (double) option_limits->max_value) - num= (double) option_limits->max_value; - if (num < (double) option_limits->min_value) - num= (double) option_limits->min_value; - microseconds= (longlong) (num * 1000000.0 + 0.5); - if (var->type == OPT_GLOBAL) - { - pthread_mutex_lock(&LOCK_global_system_variables); - (global_system_variables.*offset)= microseconds; - pthread_mutex_unlock(&LOCK_global_system_variables); - } - else - thd->variables.*offset= microseconds; - return 0; -} - - -void sys_var_microseconds::set_default(THD *thd, enum_var_type type) -{ - longlong microseconds= (longlong) (option_limits->def_value * 1000000.0); - if (type == OPT_GLOBAL) - { - pthread_mutex_lock(&LOCK_global_system_variables); - global_system_variables.*offset= microseconds; - pthread_mutex_unlock(&LOCK_global_system_variables); - } - else - thd->variables.*offset= microseconds; -} - - -uchar *sys_var_microseconds::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - thd->tmp_double_value= (double) ((type == OPT_GLOBAL) ? - global_system_variables.*offset : - thd->variables.*offset) / 1000000.0; - return (uchar*) &thd->tmp_double_value; -} - - -/* - Functions to update thd->options bits -*/ - -static bool set_option_bit(THD *thd, set_var *var) -{ - sys_var_thd_bit *sys_var= ((sys_var_thd_bit*) var->var); - if ((var->save_result.ulong_value != 0) == sys_var->reverse) - thd->options&= ~sys_var->bit_flag; - else - thd->options|= sys_var->bit_flag; - return 0; -} - -/* - Functions to be only used to update thd->options OPTION_BIN_LOG bit -*/ -static bool set_option_log_bin_bit(THD *thd, set_var *var) -{ - set_option_bit(thd, var); - if (!thd->in_sub_stmt) - thd->sql_log_bin_toplevel= thd->options & OPTION_BIN_LOG; - return 0; -} - -static bool set_option_autocommit(THD *thd, set_var *var) -{ - /* The test is negative as the flag we use is NOT autocommit */ - - ulonglong org_options= thd->options; - - /* - If we are setting AUTOCOMMIT=1 and it was not already 1, then we - need to commit any outstanding transactions. - */ - if (var->save_result.ulong_value != 0 && - (thd->options & OPTION_NOT_AUTOCOMMIT) && - ha_commit(thd)) - return 1; - - if (var->save_result.ulong_value != 0) - thd->options&= ~((sys_var_thd_bit*) var->var)->bit_flag; - else - thd->options|= ((sys_var_thd_bit*) var->var)->bit_flag; - - if ((org_options ^ thd->options) & OPTION_NOT_AUTOCOMMIT) - { - if ((org_options & OPTION_NOT_AUTOCOMMIT)) - { - /* We changed to auto_commit mode */ - thd->options&= ~(ulonglong) (OPTION_BEGIN | OPTION_KEEP_LOG); - thd->transaction.all.modified_non_trans_table= FALSE; - thd->server_status|= SERVER_STATUS_AUTOCOMMIT; - } - else - { - thd->transaction.all.modified_non_trans_table= FALSE; - thd->server_status&= ~SERVER_STATUS_AUTOCOMMIT; - } - } - return 0; -} - -static int check_log_update(THD *thd, set_var *var) -{ -#ifndef NO_EMBEDDED_ACCESS_CHECKS - if (!(thd->security_ctx->master_access & SUPER_ACL)) - { - my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); - return 1; - } -#endif - return 0; -} - -static bool set_log_update(THD *thd, set_var *var) -{ - /* - The update log is not supported anymore since 5.0. - See sql/mysqld.cc/, comments in function init_server_components() for an - explaination of the different warnings we send below - */ - - if (opt_sql_bin_update) - { - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, - ER_UPDATE_LOG_DEPRECATED_TRANSLATED, - ER(ER_UPDATE_LOG_DEPRECATED_TRANSLATED)); - } - else - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, - ER_UPDATE_LOG_DEPRECATED_IGNORED, - ER(ER_UPDATE_LOG_DEPRECATED_IGNORED)); - set_option_bit(thd, var); - return 0; -} - - -static int check_pseudo_thread_id(THD *thd, set_var *var) -{ - var->save_result.ulonglong_value= var->value->val_int(); -#ifndef NO_EMBEDDED_ACCESS_CHECKS - if (thd->security_ctx->master_access & SUPER_ACL) - return 0; - else - { - my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); - return 1; - } -#else - return 0; -#endif -} - -static uchar *get_warning_count(THD *thd) -{ - thd->sys_var_tmp.long_value= thd->warning_info->warn_count(); - return (uchar*) &thd->sys_var_tmp.long_value; -} - -static uchar *get_error_count(THD *thd) -{ - thd->sys_var_tmp.long_value= thd->warning_info->error_count(); - return (uchar*) &thd->sys_var_tmp.long_value; -} - - -/** - Get the tmpdir that was specified or chosen by default. - - This is necessary because if the user does not specify a temporary - directory via the command line, one is chosen based on the environment - or system defaults. But we can't just always use mysql_tmpdir, because - that is actually a call to my_tmpdir() which cycles among possible - temporary directories. - - @param thd thread handle - - @retval - ptr pointer to NUL-terminated string -*/ -static uchar *get_tmpdir(THD *thd) -{ - if (opt_mysql_tmpdir) - return (uchar *)opt_mysql_tmpdir; - return (uchar*)mysql_tmpdir; -} - -static uchar *get_myisam_mmap_size(THD *thd) -{ - return (uchar *)&myisam_mmap_size; -} - - /**************************************************************************** Main handling of variables: - Initialisation @@ -3329,77 +364,31 @@ static uchar *get_myisam_mmap_size(THD *thd) ****************************************************************************/ /** - Find variable name in option my_getopt structure used for - command line args. + Add variables to the dynamic hash of system variables - @param opt option structure array to search in - @param name variable name + @param first Pointer to first system variable to add @retval - 0 Error - @retval - ptr pointer to option structure -*/ - -static struct my_option *find_option(struct my_option *opt, const char *name) -{ - uint length=strlen(name); - for (; opt->name; opt++) - { - if (!getopt_compare_strings(opt->name, name, length) && - !opt->name[length]) - { - /* - Only accept the option if one can set values through it. - If not, there is no default value or limits in the option. - */ - return (opt->value) ? opt : 0; - } - } - return 0; -} - - -/** - Return variable name and length for hashing of variables. -*/ - -static uchar *get_sys_var_length(const sys_var *var, size_t *length, - my_bool first) -{ - *length= var->name_length; - return (uchar*) var->name; -} - - -/* - Add variables to the dynamic hash of system variables - - SYNOPSIS - mysql_add_sys_var_chain() - first Pointer to first system variable to add - long_opt (optional)command line arguments may be tied for limit checks. - - RETURN VALUES 0 SUCCESS + @retval otherwise FAILURE */ -int mysql_add_sys_var_chain(sys_var *first, struct my_option *long_options) +int mysql_add_sys_var_chain(sys_var *first) { sys_var *var; - + /* A write lock should be held on LOCK_system_variables_hash */ - + for (var= first; var; var= var->next) { - var->name_length= strlen(var->name); /* this fails if there is a conflicting variable name. see HASH_UNIQUE */ if (my_hash_insert(&system_variable_hash, (uchar*) var)) + { + fprintf(stderr, "*** duplicate variable name '%s' ?\n", var->name.str); goto error; - if (long_options) - var->option_limits= find_option(long_options, var->name); + } } return 0; @@ -3408,53 +397,53 @@ error: my_hash_delete(&system_variable_hash, (uchar*) first); return 1; } - - + + /* Remove variables to the dynamic hash of system variables - + SYNOPSIS mysql_del_sys_var_chain() first Pointer to first system variable to remove - + RETURN VALUES 0 SUCCESS otherwise FAILURE */ - + int mysql_del_sys_var_chain(sys_var *first) { int result= 0; - + /* A write lock should be held on LOCK_system_variables_hash */ - + for (sys_var *var= first; var; var= var->next) result|= my_hash_delete(&system_variable_hash, (uchar*) var); return result; } - - + + static int show_cmp(SHOW_VAR *a, SHOW_VAR *b) { return strcmp(a->name, b->name); } - - -/* + + +/** Constructs an array of system variables for display to the user. - - SYNOPSIS - enumerate_sys_vars() - thd current thread - sorted If TRUE, the system variables should be sorted - - RETURN VALUES + + @param thd current thread + @param sorted If TRUE, the system variables should be sorted + @param type OPT_GLOBAL or OPT_SESSION for SHOW GLOBAL|SESSION VARIABLES + + @retval pointer Array of SHOW_VAR elements for display + @retval NULL FAILURE */ -SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted) +SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted, enum enum_var_type type) { int count= system_variable_hash.records, i; int size= sizeof(SHOW_VAR) * (count + 1); @@ -3467,7 +456,12 @@ SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted) for (i= 0; i < count; i++) { sys_var *var= (sys_var*) my_hash_element(&system_variable_hash, i); - show->name= var->name; + + // don't show session-only variables in SHOW GLOBAL VARIABLES + if (type == OPT_GLOBAL && var->check_type(type)) + continue; + + show->name= var->name.str; show->value= (char*) var; show->type= SHOW_SYS; show++; @@ -3475,79 +469,29 @@ SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted) /* sort into order */ if (sorted) - my_qsort(result, count, sizeof(SHOW_VAR), + my_qsort(result, show-result, sizeof(SHOW_VAR), (qsort_cmp) show_cmp); - + /* make last element empty */ bzero(show, sizeof(SHOW_VAR)); } return result; } - -/* - Initialize the system variables - - SYNOPSIS - set_var_init() - - RETURN VALUES - 0 SUCCESS - otherwise FAILURE -*/ - -int set_var_init() -{ - uint count= 0; - DBUG_ENTER("set_var_init"); - - for (sys_var *var=vars.first; var; var= var->next, count++) ; - - if (my_hash_init(&system_variable_hash, system_charset_info, count, 0, - 0, (my_hash_get_key) get_sys_var_length, 0, HASH_UNIQUE)) - goto error; - - vars.last->next= NULL; - if (mysql_add_sys_var_chain(vars.first, my_long_options)) - goto error; - - /* - Special cases - Needed because MySQL can't find the limits for a variable it it has - a different name than the command line option. - As these variables are deprecated, this code will disappear soon... - */ - sys_sql_max_join_size.option_limits= sys_max_join_size.option_limits; - - DBUG_RETURN(0); - -error: - fprintf(stderr, "failed to initialize system variables"); - DBUG_RETURN(1); -} - - -void set_var_free() -{ - my_hash_free(&system_variable_hash); -} - - /** Find a user set-table variable. - @param str Name of system variable to find + @param str Name of system variable to find @param length Length of variable. zero means that we should use strlen() on the variable - @param no_error Refuse to emit an error, even if one occurred. @retval - pointer pointer to variable definitions + pointer pointer to variable definitions @retval - 0 Unknown variable (error message is given) + 0 Unknown variable (error message is given) */ -sys_var *intern_find_sys_var(const char *str, uint length, bool no_error) +sys_var *intern_find_sys_var(const char *str, uint length) { sys_var *var; @@ -3556,10 +500,7 @@ sys_var *intern_find_sys_var(const char *str, uint length, bool no_error) A lock on LOCK_system_variable_hash should be held */ var= (sys_var*) my_hash_search(&system_variable_hash, - (uchar*) str, length ? length : strlen(str)); - if (!(var || no_error)) - my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str); - + (uchar*) str, length ? length : strlen(str)); return var; } @@ -3573,13 +514,13 @@ sys_var *intern_find_sys_var(const char *str, uint length, bool no_error) This should ensure that in all normal cases none all or variables are updated. - @param THD Thread id + @param THD Thread id @param var_list List of variables to update @retval - 0 ok + 0 ok @retval - 1 ERROR, message sent (normally no variables was updated) + 1 ERROR, message sent (normally no variables was updated) @retval -1 ERROR, message not sent */ @@ -3608,36 +549,6 @@ err: DBUG_RETURN(error); } - -/** - Say if all variables set by a SET support the ONE_SHOT keyword - (currently, only character set and collation do; later timezones - will). - - @param var_list List of variables to update - - @note - It has a "not_" because it makes faster tests (no need to "!") - - @retval - 0 all variables of the list support ONE_SHOT - @retval - 1 at least one does not support ONE_SHOT -*/ - -bool not_all_support_one_shot(List<set_var_base> *var_list) -{ - List_iterator_fast<set_var_base> it(*var_list); - set_var_base *var; - while ((var= it++)) - { - if (var->no_support_one_shot()) - return 1; - } - return 0; -} - - /***************************************************************************** Functions to handle SET mysql_internal_variable=const_expr *****************************************************************************/ @@ -3648,42 +559,35 @@ bool not_all_support_one_shot(List<set_var_base> *var_list) @param thd Thread handler @return status code - @retval -1 Failure - @retval 0 Success -*/ + @retval -1 Failure + @retval 0 Success + */ int set_var::check(THD *thd) { if (var->is_readonly()) { - my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), var->name, "read only"); + my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), var->name.str, "read only"); return -1; } if (var->check_type(type)) { int err= type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE; - my_error(err, MYF(0), var->name); + my_error(err, MYF(0), var->name.str); return -1; } if ((type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL))) return 1; /* value is a NULL pointer if we are using SET ... = DEFAULT */ if (!value) - { - if (var->check_default(type)) - { - my_error(ER_NO_DEFAULT, MYF(0), var->name); - return -1; - } return 0; - } if ((!value->fixed && value->fix_fields(thd, &value)) || value->check_cols(1)) return -1; if (var->check_update_type(value->result_type())) { - my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), var->name); + my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), var->name.str); return -1; } return var->check(thd, this) ? -1 : 0; @@ -3693,12 +597,12 @@ int set_var::check(THD *thd) /** Check variable, but without assigning value (used by PS). - @param thd thread handler + @param thd thread handler @retval - 0 ok + 0 ok @retval - 1 ERROR, message sent (normally no variables was updated) + 1 ERROR, message sent (normally no variables was updated) @retval -1 ERROR, message not sent */ @@ -3723,7 +627,7 @@ int set_var::light_check(THD *thd) Update variable @param thd thread handler - @returns 0|1 ok or ERROR + @returns 0|1 ok or ERROR @note ERROR can be only due to abnormal operations involving the server's execution evironment such as @@ -3733,13 +637,7 @@ int set_var::light_check(THD *thd) */ int set_var::update(THD *thd) { - if (!value) - var->set_default(thd, type); - else if (var->update(thd, this)) - return -1; // should never happen - if (var->after_update) - (*var->after_update)(thd, type); - return 0; + return value ? var->update(thd, this) : var->set_default(thd, type); } @@ -3754,19 +652,19 @@ int set_var_user::check(THD *thd) 0 can be passed as last argument (reference on item) */ return (user_var_item->fix_fields(thd, (Item**) 0) || - user_var_item->check(0)) ? -1 : 0; + user_var_item->check(0)) ? -1 : 0; } /** Check variable, but without assigning value (used by PS). - @param thd thread handler + @param thd thread handler @retval - 0 ok + 0 ok @retval - 1 ERROR, message sent (normally no variables was updated) + 1 ERROR, message sent (normally no variables was updated) @retval -1 ERROR, message not sent */ @@ -3832,620 +730,36 @@ int set_var_password::update(THD *thd) #ifndef NO_EMBEDDED_ACCESS_CHECKS /* Returns 1 as the function sends error to client */ return change_password(thd, user->host.str, user->user.str, password) ? - 1 : 0; + 1 : 0; #else return 0; #endif } -/**************************************************************************** - Functions to handle table_type -****************************************************************************/ - -/* Based upon sys_var::check_enum() */ - -bool sys_var_thd_storage_engine::check(THD *thd, set_var *var) -{ - char buff[STRING_BUFFER_USUAL_SIZE]; - const char *value; - String str(buff, sizeof(buff), &my_charset_latin1), *res; - - var->save_result.plugin= NULL; - if (var->value->result_type() == STRING_RESULT) - { - LEX_STRING engine_name; - handlerton *hton; - if (!(res=var->value->val_str(&str)) || - !(engine_name.str= (char *)res->ptr()) || - !(engine_name.length= res->length()) || - !(var->save_result.plugin= ha_resolve_by_name(thd, &engine_name)) || - !(hton= plugin_data(var->save_result.plugin, handlerton *)) || - ha_checktype(thd, ha_legacy_type(hton), 1, 0) != hton) - { - value= res ? res->c_ptr() : "NULL"; - goto err; - } - return 0; - } - value= "unknown"; - -err: - my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), value); - return 1; -} - - -uchar *sys_var_thd_storage_engine::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - uchar* result; - handlerton *hton; - LEX_STRING *engine_name; - plugin_ref plugin= thd->variables.*offset; - if (type == OPT_GLOBAL) - plugin= my_plugin_lock(thd, &(global_system_variables.*offset)); - hton= plugin_data(plugin, handlerton*); - engine_name= &hton2plugin[hton->slot]->name; - result= (uchar *) thd->strmake(engine_name->str, engine_name->length); - if (type == OPT_GLOBAL) - plugin_unlock(thd, plugin); - return result; -} - - -void sys_var_thd_storage_engine::set_default(THD *thd, enum_var_type type) -{ - plugin_ref old_value, new_value, *value; - if (type == OPT_GLOBAL) - { - value= &(global_system_variables.*offset); - new_value= ha_lock_engine(NULL, myisam_hton); - } - else - { - value= &(thd->variables.*offset); - new_value= my_plugin_lock(NULL, &(global_system_variables.*offset)); - } - DBUG_ASSERT(new_value); - old_value= *value; - *value= new_value; - plugin_unlock(NULL, old_value); -} - - -bool sys_var_thd_storage_engine::update(THD *thd, set_var *var) -{ - plugin_ref *value= &(global_system_variables.*offset), old_value; - if (var->type != OPT_GLOBAL) - value= &(thd->variables.*offset); - old_value= *value; - if (old_value != var->save_result.plugin) - { - *value= my_plugin_lock(NULL, &var->save_result.plugin); - plugin_unlock(NULL, old_value); - } - return 0; -} - -void sys_var_thd_table_type::warn_deprecated(THD *thd) -{ - WARN_DEPRECATED(thd, "6.0", "@@table_type", "'@@storage_engine'"); -} - -void sys_var_thd_table_type::set_default(THD *thd, enum_var_type type) -{ - warn_deprecated(thd); - sys_var_thd_storage_engine::set_default(thd, type); -} - -bool sys_var_thd_table_type::update(THD *thd, set_var *var) -{ - warn_deprecated(thd); - return sys_var_thd_storage_engine::update(thd, var); -} - - -/**************************************************************************** - Functions to handle sql_mode -****************************************************************************/ - -/** - Make string representation of mode. - - @param[in] thd thread handler - @param[in] val sql_mode value - @param[out] len pointer on length of string - - @return - pointer to string with sql_mode representation -*/ - -bool -sys_var_thd_sql_mode:: -symbolic_mode_representation(THD *thd, ulonglong val, LEX_STRING *rep) -{ - char buff[STRING_BUFFER_USUAL_SIZE*8]; - String tmp(buff, sizeof(buff), &my_charset_latin1); - - tmp.length(0); - - for (uint i= 0; val; val>>= 1, i++) - { - if (val & 1) - { - tmp.append(sql_mode_typelib.type_names[i], - sql_mode_typelib.type_lengths[i]); - tmp.append(','); - } - } - - if (tmp.length()) - tmp.length(tmp.length() - 1); /* trim the trailing comma */ - - rep->str= thd->strmake(tmp.ptr(), tmp.length()); - - rep->length= rep->str ? tmp.length() : 0; - - return rep->length != tmp.length(); -} - - -uchar *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - LEX_STRING sql_mode; - ulonglong val= ((type == OPT_GLOBAL) ? global_system_variables.*offset : - thd->variables.*offset); - (void) symbolic_mode_representation(thd, val, &sql_mode); - return (uchar *) sql_mode.str; -} - - -void sys_var_thd_sql_mode::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - global_system_variables.*offset= 0; - else - thd->variables.*offset= global_system_variables.*offset; -} - - -void fix_sql_mode_var(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - global_system_variables.sql_mode= - fix_sql_mode(global_system_variables.sql_mode); - else - { - thd->variables.sql_mode= fix_sql_mode(thd->variables.sql_mode); - /* - Update thd->server_status - */ - if (thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) - thd->server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES; - else - thd->server_status&= ~SERVER_STATUS_NO_BACKSLASH_ESCAPES; - } -} - -/** Map database specific bits to function bits. */ - -ulong fix_sql_mode(ulong sql_mode) -{ - /* - Note that we dont set - MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | MODE_NO_FIELD_OPTIONS - to allow one to get full use of MySQL in this mode. - */ - - if (sql_mode & MODE_ANSI) - { - sql_mode|= (MODE_REAL_AS_FLOAT | MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | - MODE_IGNORE_SPACE); - /* - MODE_ONLY_FULL_GROUP_BY removed from ANSI mode because it is currently - overly restrictive (see BUG#8510). - */ - } - if (sql_mode & MODE_ORACLE) - sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | - MODE_IGNORE_SPACE | - MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | - MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER); - if (sql_mode & MODE_MSSQL) - sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | - MODE_IGNORE_SPACE | - MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | - MODE_NO_FIELD_OPTIONS); - if (sql_mode & MODE_POSTGRESQL) - sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | - MODE_IGNORE_SPACE | - MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | - MODE_NO_FIELD_OPTIONS); - if (sql_mode & MODE_DB2) - sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | - MODE_IGNORE_SPACE | - MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | - MODE_NO_FIELD_OPTIONS); - if (sql_mode & MODE_MAXDB) - sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | - MODE_IGNORE_SPACE | - MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | - MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER); - if (sql_mode & MODE_MYSQL40) - sql_mode|= MODE_HIGH_NOT_PRECEDENCE; - if (sql_mode & MODE_MYSQL323) - sql_mode|= MODE_HIGH_NOT_PRECEDENCE; - if (sql_mode & MODE_TRADITIONAL) - sql_mode|= (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES | - MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | - MODE_ERROR_FOR_DIVISION_BY_ZERO | MODE_NO_AUTO_CREATE_USER | - MODE_NO_ENGINE_SUBSTITUTION); - return sql_mode; -} - - -bool -sys_var_thd_optimizer_switch:: -symbolic_mode_representation(THD *thd, ulonglong val, LEX_STRING *rep) -{ - char buff[STRING_BUFFER_USUAL_SIZE*8]; - String tmp(buff, sizeof(buff), &my_charset_latin1); - int i; - ulonglong bit; - tmp.length(0); - - for (i= 0, bit=1; bit != OPTIMIZER_SWITCH_LAST; i++, bit= bit << 1) - { - tmp.append(optimizer_switch_typelib.type_names[i], - optimizer_switch_typelib.type_lengths[i]); - tmp.append('='); - tmp.append((val & bit)? "on":"off"); - tmp.append(','); - } - - if (tmp.length()) - tmp.length(tmp.length() - 1); /* trim the trailing comma */ - - rep->str= thd->strmake(tmp.ptr(), tmp.length()); - - rep->length= rep->str ? tmp.length() : 0; - - return rep->length != tmp.length(); -} - - -uchar *sys_var_thd_optimizer_switch::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - LEX_STRING opts; - ulonglong val= ((type == OPT_GLOBAL) ? global_system_variables.*offset : - thd->variables.*offset); - (void) symbolic_mode_representation(thd, val, &opts); - return (uchar *) opts.str; -} - - -/* - Check (and actually parse) string representation of @@optimizer_switch. -*/ - -bool sys_var_thd_optimizer_switch::check(THD *thd, set_var *var) -{ - bool not_used; - char buff[STRING_BUFFER_USUAL_SIZE], *error= 0; - uint error_len= 0; - String str(buff, sizeof(buff), system_charset_info), *res; - - if (!(res= var->value->val_str(&str))) - { - strmov(buff, "NULL"); - goto err; - } - - if (res->length() == 0) - { - buff[0]= 0; - goto err; - } - - var->save_result.ulong_value= - (ulong)find_set_from_flags(&optimizer_switch_typelib, - optimizer_switch_typelib.count, - thd->variables.optimizer_switch, - global_system_variables.optimizer_switch, - res->c_ptr_safe(), res->length(), NULL, - &error, &error_len, ¬_used); - if (error_len) - { - ErrConvString err(error, error_len, res->charset()); - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, err.ptr()); - return TRUE; - } - return FALSE; -err: - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buff); - return TRUE; -} - - -void sys_var_thd_optimizer_switch::set_default(THD *thd, enum_var_type type) -{ - if (type == OPT_GLOBAL) - global_system_variables.*offset= OPTIMIZER_SWITCH_DEFAULT; - else - thd->variables.*offset= global_system_variables.*offset; -} - -/**************************************************************************** - Named list handling -****************************************************************************/ - -uchar* find_named(I_List<NAMED_LIST> *list, const char *name, uint length, - NAMED_LIST **found) -{ - I_List_iterator<NAMED_LIST> it(*list); - NAMED_LIST *element; - while ((element= it++)) - { - if (element->cmp(name, length)) - { - if (found) - *found= element; - return element->data; - } - } - return 0; -} - - -void delete_elements(I_List<NAMED_LIST> *list, - void (*free_element)(const char *name, uchar*)) -{ - NAMED_LIST *element; - DBUG_ENTER("delete_elements"); - while ((element= list->get())) - { - (*free_element)(element->name, element->data); - delete element; - } - DBUG_VOID_RETURN; -} - - -/* Key cache functions */ - -static KEY_CACHE *create_key_cache(const char *name, uint length) -{ - KEY_CACHE *key_cache; - DBUG_ENTER("create_key_cache"); - DBUG_PRINT("enter",("name: %.*s", length, name)); - - if ((key_cache= (KEY_CACHE*) my_malloc(sizeof(KEY_CACHE), - MYF(MY_ZEROFILL | MY_WME)))) - { - if (!new NAMED_LIST(&key_caches, name, length, (uchar*) key_cache)) - { - my_free((char*) key_cache, MYF(0)); - key_cache= 0; - } - else - { - /* - Set default values for a key cache - The values in dflt_key_cache_var is set by my_getopt() at startup - - We don't set 'buff_size' as this is used to enable the key cache - */ - key_cache->param_block_size= dflt_key_cache_var.param_block_size; - key_cache->param_division_limit= dflt_key_cache_var.param_division_limit; - key_cache->param_age_threshold= dflt_key_cache_var.param_age_threshold; - } - } - DBUG_RETURN(key_cache); -} - - -KEY_CACHE *get_or_create_key_cache(const char *name, uint length) -{ - LEX_STRING key_cache_name; - KEY_CACHE *key_cache; - - key_cache_name.str= (char *) name; - key_cache_name.length= length; - pthread_mutex_lock(&LOCK_global_system_variables); - if (!(key_cache= get_key_cache(&key_cache_name))) - key_cache= create_key_cache(name, length); - pthread_mutex_unlock(&LOCK_global_system_variables); - return key_cache; -} - - -void free_key_cache(const char *name, KEY_CACHE *key_cache) -{ - ha_end_key_cache(key_cache); - my_free((char*) key_cache, MYF(0)); -} - +/***************************************************************************** + Functions to handle SET NAMES and SET CHARACTER SET +*****************************************************************************/ -bool process_key_caches(process_key_cache_t func) +int set_var_collation_client::check(THD *thd) { - I_List_iterator<NAMED_LIST> it(key_caches); - NAMED_LIST *element; - - while ((element= it++)) + /* Currently, UCS-2 cannot be used as a client character set */ + if (character_set_client->mbminlen > 1) { - KEY_CACHE *key_cache= (KEY_CACHE *) element->data; - func(element->name, key_cache); + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "character_set_client", + character_set_client->csname); + return 1; } return 0; } - -void sys_var_trust_routine_creators::warn_deprecated(THD *thd) -{ - WARN_DEPRECATED(thd, VER_CELOSIA, "@@log_bin_trust_routine_creators", - "'@@log_bin_trust_function_creators'"); -} - -void sys_var_trust_routine_creators::set_default(THD *thd, enum_var_type type) -{ - warn_deprecated(thd); - sys_var_bool_ptr::set_default(thd, type); -} - -bool sys_var_trust_routine_creators::update(THD *thd, set_var *var) -{ - warn_deprecated(thd); - return sys_var_bool_ptr::update(thd, var); -} - -bool sys_var_opt_readonly::update(THD *thd, set_var *var) -{ - bool result; - - DBUG_ENTER("sys_var_opt_readonly::update"); - - /* Prevent self dead-lock */ - if (thd->locked_tables || thd->active_transaction()) - { - my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0)); - DBUG_RETURN(true); - } - - if (thd->global_read_lock) - { - /* - This connection already holds the global read lock. - This can be the case with: - - FLUSH TABLES WITH READ LOCK - - SET GLOBAL READ_ONLY = 1 - */ - result= sys_var_bool_ptr::update(thd, var); - DBUG_RETURN(result); - } - - /* - Perform a 'FLUSH TABLES WITH READ LOCK'. - This is a 3 step process: - - [1] lock_global_read_lock() - - [2] close_cached_tables() - - [3] make_global_read_lock_block_commit() - [1] prevents new connections from obtaining tables locked for write. - [2] waits until all existing connections close their tables. - [3] prevents transactions from being committed. - */ - - if (lock_global_read_lock(thd)) - DBUG_RETURN(true); - - /* - This call will be blocked by any connection holding a READ or WRITE lock. - Ideally, we want to wait only for pending WRITE locks, but since: - con 1> LOCK TABLE T FOR READ; - con 2> LOCK TABLE T FOR WRITE; (blocked by con 1) - con 3> SET GLOBAL READ ONLY=1; (blocked by con 2) - can cause to wait on a read lock, it's required for the client application - to unlock everything, and acceptable for the server to wait on all locks. - */ - if ((result= close_cached_tables(thd, NULL, FALSE, TRUE, TRUE))) - goto end_with_read_lock; - - if ((result= make_global_read_lock_block_commit(thd))) - goto end_with_read_lock; - - /* Change the opt_readonly system variable, safe because the lock is held */ - result= sys_var_bool_ptr::update(thd, var); - -end_with_read_lock: - /* Release the lock */ - unlock_global_read_lock(thd); - DBUG_RETURN(result); -} - - -#ifndef DBUG_OFF -/* even session variable here requires SUPER, because of -#o,file */ -bool sys_var_thd_dbug::check(THD *thd, set_var *var) -{ - return check_global_access(thd, SUPER_ACL); -} - -bool sys_var_thd_dbug::update(THD *thd, set_var *var) +int set_var_collation_client::update(THD *thd) { - if (var->type == OPT_GLOBAL) - DBUG_SET_INITIAL(var ? var->value->str_value.c_ptr() : ""); - else - DBUG_SET(var ? var->value->str_value.c_ptr() : ""); - + thd->variables.character_set_client= character_set_client; + thd->variables.character_set_results= character_set_results; + thd->variables.collation_connection= collation_connection; + thd->update_charset(); + thd->protocol_text.init(thd); + thd->protocol_binary.init(thd); return 0; } - -uchar *sys_var_thd_dbug::value_ptr(THD *thd, enum_var_type type, LEX_STRING *b) -{ - char buf[256]; - if (type == OPT_GLOBAL) - DBUG_EXPLAIN_INITIAL(buf, sizeof(buf)); - else - DBUG_EXPLAIN(buf, sizeof(buf)); - return (uchar*) thd->strdup(buf); -} -#endif /* DBUG_OFF */ - - -#ifdef HAVE_EVENT_SCHEDULER -bool sys_var_event_scheduler::check(THD *thd, set_var *var) -{ - return check_enum(thd, var, &Events::var_typelib); -} - -/* - The update method of the global variable event_scheduler. - If event_scheduler is switched from 0 to 1 then the scheduler main - thread is resumed and if from 1 to 0 the scheduler thread is suspended - - SYNOPSIS - sys_var_event_scheduler::update() - thd Thread context (unused) - var The new value - - Returns - FALSE OK - TRUE Error -*/ - -bool -sys_var_event_scheduler::update(THD *thd, set_var *var) -{ - int res; - /* here start the thread if not running. */ - DBUG_ENTER("sys_var_event_scheduler::update"); - DBUG_PRINT("info", ("new_value: %d", (int) var->save_result.ulong_value)); - - enum Events::enum_opt_event_scheduler - new_state= - (enum Events::enum_opt_event_scheduler) var->save_result.ulong_value; - - res= Events::switch_event_scheduler_state(new_state); - - DBUG_RETURN((bool) res); -} - - -uchar *sys_var_event_scheduler::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) -{ - return (uchar *) Events::get_opt_event_scheduler_str(); -} -#endif - -/**************************************************************************** - Used templates -****************************************************************************/ - -#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION -template class List<set_var_base>; -template class List_iterator_fast<set_var_base>; -template class I_List_iterator<NAMED_LIST>; -#endif diff --git a/sql/set_var.h b/sql/set_var.h index c08097521d2..4a212d3b685 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -1,7 +1,6 @@ #ifndef SET_VAR_INCLUDED #define SET_VAR_INCLUDED - -/* Copyright (C) 2002-2006 MySQL AB +/* Copyright (C) 2000-2008 MySQL AB, 2008-2010 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,31 +15,23 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Classes to support the SET command */ +/** + @file + "public" interface to sys_var - server configuration variables. +*/ #ifdef USE_PRAGMA_INTERFACE -#pragma interface /* gcc class implementation */ +#pragma interface /* gcc class implementation */ #endif -/**************************************************************************** - Variables that are changable runtime are declared using the - following classes -****************************************************************************/ +#include <my_getopt.h> class sys_var; class set_var; -class sys_var_pluginvar; /* opaque */ -typedef struct system_variables SV; -typedef struct my_locale_st MY_LOCALE; +class sys_var_pluginvar; +class PolyLock; -extern TYPELIB bool_typelib, delay_key_write_typelib, sql_mode_typelib, - optimizer_switch_typelib, slave_exec_mode_typelib; - -typedef int (*sys_check_func)(THD *, set_var *); -typedef bool (*sys_update_func)(THD *, set_var *); -typedef void (*sys_after_update_func)(THD *,enum_var_type); -typedef void (*sys_set_default_func)(THD *, enum_var_type); -typedef uchar *(*sys_value_ptr_func)(THD *thd); +extern TYPELIB bool_typelib; struct sys_var_chain { @@ -48,1322 +39,171 @@ struct sys_var_chain sys_var *last; }; +int mysql_add_sys_var_chain(sys_var *chain); +int mysql_del_sys_var_chain(sys_var *chain); + +/** + A class representing one system variable - that is something + that can be accessed as @@global.variable_name or @@session.variable_name, + visible in SHOW xxx VARIABLES and in INFORMATION_SCHEMA.xxx_VARIABLES, + optionally it can be assigned to, optionally it can have a command-line + counterpart with the same name. +*/ class sys_var { public: + sys_var *next; + LEX_CSTRING name; + enum flag_enum { GLOBAL, SESSION, ONLY_SESSION, SCOPE_MASK=1023, + READONLY=1024, ALLOCATED=2048 }; + static const int PARSE_EARLY= 1; + static const int PARSE_NORMAL= 2; + /** + Enumeration type to indicate for a system variable whether + it will be written to the binlog or not. + */ + enum binlog_status_enum { VARIABLE_NOT_IN_BINLOG, + SESSION_VARIABLE_IN_BINLOG } binlog_status; +protected: + typedef bool (*on_check_function)(sys_var *self, THD *thd, set_var *var); + typedef bool (*on_update_function)(sys_var *self, THD *thd, enum_var_type type); + + int flags; ///< or'ed flag_enum values + int m_parse_flag; ///< either PARSE_EARLY or PARSE_NORMAL. + const SHOW_TYPE show_val_type; ///< what value_ptr() returns for sql_show.cc + my_option option; ///< min, max, default values are stored here + PolyLock *guard; ///< *second* lock that protects the variable + ptrdiff_t offset; ///< offset to the value from global_system_variables + on_check_function on_check; + on_update_function on_update; + struct { uint version; const char *substitute; } deprecated; + bool is_os_charset; ///< true if the value is in character_set_filesystem + +public: + sys_var(sys_var_chain *chain, const char *name_arg, const char *comment, + int flag_args, ptrdiff_t off, int getopt_id, + enum get_opt_arg_type getopt_arg_type, SHOW_TYPE show_val_type_arg, + longlong def_val, PolyLock *lock, enum binlog_status_enum binlog_status_arg, + on_check_function on_check_func, on_update_function on_update_func, + uint deprecated_version, const char *substitute, int parse_flag); /** - Enumeration type to indicate for a system variable whether it will be written to the binlog or not. + The instance should only be destroyed on shutdown, as it doesn't unlink + itself from the chain. */ - enum Binlog_status_enum - { - /* The variable value is not in the binlog. */ - NOT_IN_BINLOG, - /* The value of the @@session variable is in the binlog. */ - SESSION_VARIABLE_IN_BINLOG - /* - Currently, no @@global variable is ever in the binlog, so we - don't need an enumeration value for that. - */ - }; - - sys_var *next; - struct my_option *option_limits; /* Updated by by set_var_init() */ - uint name_length; /* Updated by by set_var_init() */ - const char *name; - - sys_after_update_func after_update; - bool no_support_one_shot; - /* - true if the value is in character_set_filesystem, - false otherwise. - Note that we can't use a pointer to the charset as the system var is - instantiated in global scope and the charset pointers are initialized - later. - */ - bool is_os_charset; - sys_var(const char *name_arg, sys_after_update_func func= NULL, - Binlog_status_enum binlog_status_arg= NOT_IN_BINLOG) - :name(name_arg), after_update(func), no_support_one_shot(1), - is_os_charset (FALSE), - binlog_status(binlog_status_arg), - m_allow_empty_value(TRUE) - {} virtual ~sys_var() {} - void chain_sys_var(sys_var_chain *chain_arg) - { - if (chain_arg->last) - chain_arg->last->next= this; - else - chain_arg->first= this; - chain_arg->last= this; - } - virtual bool check(THD *thd, set_var *var); - bool check_enum(THD *thd, set_var *var, const TYPELIB *enum_names); - bool check_set(THD *thd, set_var *var, TYPELIB *enum_names); - bool is_written_to_binlog(enum_var_type type) - { - return (type == OPT_SESSION || type == OPT_DEFAULT) && - (binlog_status == SESSION_VARIABLE_IN_BINLOG); - } - virtual bool update(THD *thd, set_var *var)=0; - virtual void set_default(THD *thd_arg, enum_var_type type) {} - virtual SHOW_TYPE show_type() { return SHOW_UNDEF; } - virtual uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) - { return 0; } - virtual bool check_type(enum_var_type type) - { return type != OPT_GLOBAL; } /* Error if not GLOBAL */ - virtual bool check_update_type(Item_result type) - { return type != INT_RESULT; } /* Assume INT */ - virtual bool check_default(enum_var_type type) - { return option_limits == 0; } - virtual bool is_struct() { return 0; } - virtual bool is_readonly() const { return 0; } - CHARSET_INFO *charset(THD *thd); + /** + downcast for sys_var_pluginvar. Returns this if it's an instance + of sys_var_pluginvar, and 0 otherwise. + */ virtual sys_var_pluginvar *cast_pluginvar() { return 0; } -protected: - void set_allow_empty_value(bool allow_empty_value) - { - m_allow_empty_value= allow_empty_value; - } - -private: - const Binlog_status_enum binlog_status; - - bool m_allow_empty_value; -}; - - -/* - A base class for all variables that require its access to - be guarded with a mutex. -*/ - -class sys_var_global: public sys_var -{ -protected: - pthread_mutex_t *guard; -public: - sys_var_global(const char *name_arg, sys_after_update_func after_update_arg, - pthread_mutex_t *guard_arg) - :sys_var(name_arg, after_update_arg), guard(guard_arg) {} -}; - - -/* - A global-only ulong variable that requires its access to be - protected with a mutex. -*/ - -class sys_var_long_ptr_global: public sys_var_global -{ -public: - ulong *value; - sys_var_long_ptr_global(sys_var_chain *chain, const char *name_arg, - ulong *value_ptr_arg, - pthread_mutex_t *guard_arg, - sys_after_update_func after_update_arg= NULL) - :sys_var_global(name_arg, after_update_arg, guard_arg), - value(value_ptr_arg) - { chain_sys_var(chain); } - bool check(THD *thd, set_var *var); - bool update(THD *thd, set_var *var); - void set_default(THD *thd, enum_var_type type); - SHOW_TYPE show_type() { return SHOW_LONG; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) - { return (uchar*) value; } -}; - -/** - Unsigned int system variable class - */ -class sys_var_uint_ptr :public sys_var -{ -public: - sys_var_uint_ptr(sys_var_chain *chain, const char *name_arg, - uint *value_ptr_arg, - sys_after_update_func after_update_arg= NULL) - :sys_var(name_arg, after_update_arg), - value(value_ptr_arg) - { chain_sys_var(chain); } - bool check(THD *thd, set_var *var); - bool update(THD *thd, set_var *var); - void set_default(THD *thd, enum_var_type type); - SHOW_TYPE show_type() { return SHOW_INT; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) - { return (uchar*) value; } -private: - uint *value; -}; - -/* - A global ulong variable that is protected by LOCK_global_system_variables -*/ - -class sys_var_long_ptr :public sys_var_long_ptr_global -{ -public: - sys_var_long_ptr(sys_var_chain *chain, const char *name_arg, ulong *value_ptr, - sys_after_update_func after_update_arg= NULL); -}; - - -class sys_var_ulonglong_ptr :public sys_var -{ -public: - ulonglong *value; - sys_var_ulonglong_ptr(sys_var_chain *chain, const char *name_arg, ulonglong *value_ptr_arg) - :sys_var(name_arg),value(value_ptr_arg) - { chain_sys_var(chain); } - sys_var_ulonglong_ptr(sys_var_chain *chain, const char *name_arg, ulonglong *value_ptr_arg, - sys_after_update_func func) - :sys_var(name_arg,func), value(value_ptr_arg) - { chain_sys_var(chain); } - bool update(THD *thd, set_var *var); - void set_default(THD *thd, enum_var_type type); - SHOW_TYPE show_type() { return SHOW_LONGLONG; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) - { return (uchar*) value; } -}; - - -class sys_var_bool_ptr :public sys_var -{ -public: - my_bool *value; - sys_var_bool_ptr(sys_var_chain *chain, const char *name_arg, my_bool *value_arg) - :sys_var(name_arg),value(value_arg) - { chain_sys_var(chain); } - bool check(THD *thd, set_var *var) - { - return check_enum(thd, var, &bool_typelib); - } - bool update(THD *thd, set_var *var); - void set_default(THD *thd, enum_var_type type); - SHOW_TYPE show_type() { return SHOW_MY_BOOL; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) - { return (uchar*) value; } - bool check_update_type(Item_result type) { return 0; } -}; - - -class sys_var_bool_ptr_readonly :public sys_var_bool_ptr -{ -public: - sys_var_bool_ptr_readonly(sys_var_chain *chain, const char *name_arg, - my_bool *value_arg) - :sys_var_bool_ptr(chain, name_arg, value_arg) - {} - bool is_readonly() const { return 1; } -}; - - -class sys_var_str :public sys_var -{ -public: - char *value; // Pointer to allocated string - uint value_length; - sys_check_func check_func; - sys_update_func update_func; - sys_set_default_func set_default_func; - sys_var_str(sys_var_chain *chain, const char *name_arg, - sys_check_func check_func_arg, - sys_update_func update_func_arg, - sys_set_default_func set_default_func_arg, - char *value_arg) - :sys_var(name_arg), value(value_arg), check_func(check_func_arg), - update_func(update_func_arg),set_default_func(set_default_func_arg) - { chain_sys_var(chain); } - bool check(THD *thd, set_var *var); - bool update(THD *thd, set_var *var) - { - return (*update_func)(thd, var); - } - void set_default(THD *thd, enum_var_type type) - { - (*set_default_func)(thd, type); - } - SHOW_TYPE show_type() { return SHOW_CHAR; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) - { return (uchar*) value; } - bool check_update_type(Item_result type) - { - return type != STRING_RESULT; /* Only accept strings */ - } - bool check_default(enum_var_type type) { return 0; } -}; - - -class sys_var_const_str :public sys_var -{ -public: - char *value; // Pointer to const value - sys_var_const_str(sys_var_chain *chain, const char *name_arg, - const char *value_arg) - :sys_var(name_arg), value((char*) value_arg) - { chain_sys_var(chain); } - bool check(THD *thd, set_var *var) - { - return 1; - } - bool update(THD *thd, set_var *var) - { - return 1; - } - SHOW_TYPE show_type() { return SHOW_CHAR; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) - { - return (uchar*) value; - } - bool check_update_type(Item_result type) - { - return 1; - } - bool check_default(enum_var_type type) { return 1; } - bool is_readonly() const { return 1; } -}; - - -class sys_var_const_os_str: public sys_var_const_str -{ -public: - sys_var_const_os_str(sys_var_chain *chain, const char *name_arg, - const char *value_arg) - :sys_var_const_str(chain, name_arg, value_arg) - { - is_os_charset= TRUE; - } -}; - - -class sys_var_const_str_ptr :public sys_var -{ -public: - char **value; // Pointer to const value - sys_var_const_str_ptr(sys_var_chain *chain, const char *name_arg, char **value_arg) - :sys_var(name_arg),value(value_arg) - { chain_sys_var(chain); } - bool check(THD *thd, set_var *var) - { - return 1; - } - bool update(THD *thd, set_var *var) - { - return 1; - } - SHOW_TYPE show_type() { return SHOW_CHAR; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) - { - return (uchar*) *value; - } - bool check_update_type(Item_result type) - { - return 1; - } - bool check_default(enum_var_type type) { return 1; } - bool is_readonly() const { return 1; } -}; - - -class sys_var_const_os_str_ptr :public sys_var_const_str_ptr -{ -public: - sys_var_const_os_str_ptr(sys_var_chain *chain, const char *name_arg, - char **value_arg) - :sys_var_const_str_ptr(chain, name_arg, value_arg) - { - is_os_charset= TRUE; - } -}; - - -class sys_var_enum :public sys_var -{ - uint *value; - TYPELIB *enum_names; -public: - sys_var_enum(sys_var_chain *chain, const char *name_arg, uint *value_arg, - TYPELIB *typelib, sys_after_update_func func) - :sys_var(name_arg,func), value(value_arg), enum_names(typelib) - { chain_sys_var(chain); } - bool check(THD *thd, set_var *var) - { - return check_enum(thd, var, enum_names); - } - bool update(THD *thd, set_var *var); - SHOW_TYPE show_type() { return SHOW_CHAR; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); - bool check_update_type(Item_result type) { return 0; } -}; - - -class sys_var_enum_const :public sys_var -{ - ulong SV::*offset; - TYPELIB *enum_names; -public: - sys_var_enum_const(sys_var_chain *chain, const char *name_arg, ulong SV::*offset_arg, - TYPELIB *typelib, sys_after_update_func func) - :sys_var(name_arg,func), offset(offset_arg), enum_names(typelib) - { chain_sys_var(chain); } - bool check(THD *thd, set_var *var) { return 1; } - bool update(THD *thd, set_var *var) { return 1; } - SHOW_TYPE show_type() { return SHOW_CHAR; } - bool check_update_type(Item_result type) { return 1; } - bool is_readonly() const { return 1; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); -}; - - -class sys_var_thd :public sys_var -{ -public: - sys_var_thd(const char *name_arg, - sys_after_update_func func= NULL, - Binlog_status_enum binlog_status= NOT_IN_BINLOG) - :sys_var(name_arg, func, binlog_status) - {} - bool check_type(enum_var_type type) { return 0; } - bool check_default(enum_var_type type) - { - return type == OPT_GLOBAL && !option_limits; - } -}; - - -class sys_var_thd_ulong :public sys_var_thd -{ - sys_check_func check_func; -public: - ulong SV::*offset; - sys_var_thd_ulong(sys_var_chain *chain, const char *name_arg, - ulong SV::*offset_arg, - sys_check_func c_func= NULL, - sys_after_update_func au_func= NULL, - Binlog_status_enum binlog_status_arg= NOT_IN_BINLOG) - :sys_var_thd(name_arg, au_func, binlog_status_arg), check_func(c_func), - offset(offset_arg) - { chain_sys_var(chain); } bool check(THD *thd, set_var *var); - bool update(THD *thd, set_var *var); - void set_default(THD *thd, enum_var_type type); - SHOW_TYPE show_type() { return SHOW_LONG; } uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); -}; - - -class sys_var_thd_ha_rows :public sys_var_thd -{ -public: - ha_rows SV::*offset; - sys_var_thd_ha_rows(sys_var_chain *chain, const char *name_arg, - ha_rows SV::*offset_arg) - :sys_var_thd(name_arg), offset(offset_arg) - { chain_sys_var(chain); } - sys_var_thd_ha_rows(sys_var_chain *chain, const char *name_arg, - ha_rows SV::*offset_arg, - sys_after_update_func func) - :sys_var_thd(name_arg,func), offset(offset_arg) - { chain_sys_var(chain); } + bool set_default(THD *thd, enum_var_type type); bool update(THD *thd, set_var *var); - void set_default(THD *thd, enum_var_type type); - SHOW_TYPE show_type() { return SHOW_HA_ROWS; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); -}; - -class sys_var_thd_ulonglong :public sys_var_thd -{ -public: - ulonglong SV::*offset; - bool only_global; - sys_var_thd_ulonglong(sys_var_chain *chain, const char *name_arg, - ulonglong SV::*offset_arg) - :sys_var_thd(name_arg), offset(offset_arg) - { chain_sys_var(chain); } - sys_var_thd_ulonglong(sys_var_chain *chain, const char *name_arg, - ulonglong SV::*offset_arg, - sys_after_update_func func, bool only_global_arg) - :sys_var_thd(name_arg, func), offset(offset_arg), - only_global(only_global_arg) - { chain_sys_var(chain); } - bool update(THD *thd, set_var *var); - void set_default(THD *thd, enum_var_type type); - SHOW_TYPE show_type() { return SHOW_LONGLONG; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); - bool check(THD *thd, set_var *var); - bool check_default(enum_var_type type) - { - return type == OPT_GLOBAL && !option_limits; - } + SHOW_TYPE show_type() { return show_val_type; } + int scope() const { return flags & SCOPE_MASK; } + CHARSET_INFO *charset(THD *thd); + bool is_readonly() const { return flags & READONLY; } + /** + the following is only true for keycache variables, + that support the syntax @@keycache_name.variable_name + */ + bool is_struct() { return option.var_type & GET_ASK_ADDR; } + bool is_written_to_binlog(enum_var_type type) + { return type != OPT_GLOBAL && binlog_status == SESSION_VARIABLE_IN_BINLOG; } + virtual bool check_update_type(Item_result type) = 0; bool check_type(enum_var_type type) { - return (only_global && type != OPT_GLOBAL); - } -}; - - -class sys_var_thd_bool :public sys_var_thd -{ -public: - my_bool SV::*offset; - sys_var_thd_bool(sys_var_chain *chain, const char *name_arg, my_bool SV::*offset_arg) - :sys_var_thd(name_arg), offset(offset_arg) - { chain_sys_var(chain); } - sys_var_thd_bool(sys_var_chain *chain, const char *name_arg, my_bool SV::*offset_arg, - sys_after_update_func func) - :sys_var_thd(name_arg,func), offset(offset_arg) - { chain_sys_var(chain); } - bool update(THD *thd, set_var *var); - void set_default(THD *thd, enum_var_type type); - SHOW_TYPE show_type() { return SHOW_MY_BOOL; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); - bool check(THD *thd, set_var *var) - { - return check_enum(thd, var, &bool_typelib); - } - bool check_update_type(Item_result type) { return 0; } -}; - - -class sys_var_thd_enum :public sys_var_thd -{ -protected: - ulong SV::*offset; - TYPELIB *enum_names; - sys_check_func check_func; -public: - sys_var_thd_enum(sys_var_chain *chain, const char *name_arg, - ulong SV::*offset_arg, TYPELIB *typelib, - sys_after_update_func func= NULL, - sys_check_func check= NULL) - :sys_var_thd(name_arg, func), offset(offset_arg), - enum_names(typelib), check_func(check) - { chain_sys_var(chain); } - bool check(THD *thd, set_var *var) - { - /* - check_enum fails if the character representation supplied was wrong - or that the integer value was wrong or missing. - */ - if (check_enum(thd, var, enum_names)) - return TRUE; - else if ((check_func && (*check_func)(thd, var))) - return TRUE; - else - return FALSE; - } - bool update(THD *thd, set_var *var); - void set_default(THD *thd, enum_var_type type); - SHOW_TYPE show_type() { return SHOW_CHAR; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); - bool check_update_type(Item_result type) { return 0; } -}; - - -class sys_var_thd_optimizer_switch :public sys_var_thd_enum -{ -public: - sys_var_thd_optimizer_switch(sys_var_chain *chain, const char *name_arg, - ulong SV::*offset_arg) - :sys_var_thd_enum(chain, name_arg, offset_arg, &optimizer_switch_typelib) - {} - bool check(THD *thd, set_var *var); - void set_default(THD *thd, enum_var_type type); - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); - static bool symbolic_mode_representation(THD *thd, ulonglong sql_mode, - LEX_STRING *rep); -}; - -extern void fix_sql_mode_var(THD *thd, enum_var_type type); - -class sys_var_thd_sql_mode :public sys_var_thd_enum -{ -public: - sys_var_thd_sql_mode(sys_var_chain *chain, const char *name_arg, - ulong SV::*offset_arg) - :sys_var_thd_enum(chain, name_arg, offset_arg, &sql_mode_typelib, - fix_sql_mode_var) - {} - bool check(THD *thd, set_var *var) - { - return check_set(thd, var, enum_names); - } - void set_default(THD *thd, enum_var_type type); - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); - static bool symbolic_mode_representation(THD *thd, ulonglong sql_mode, - LEX_STRING *rep); -}; - - -class sys_var_thd_storage_engine :public sys_var_thd -{ -protected: - plugin_ref SV::*offset; -public: - sys_var_thd_storage_engine(sys_var_chain *chain, const char *name_arg, - plugin_ref SV::*offset_arg) - :sys_var_thd(name_arg), offset(offset_arg) - { chain_sys_var(chain); } - bool check(THD *thd, set_var *var); - SHOW_TYPE show_type() { return SHOW_CHAR; } - bool check_update_type(Item_result type) - { - return type != STRING_RESULT; /* Only accept strings */ - } - void set_default(THD *thd, enum_var_type type); - bool update(THD *thd, set_var *var); - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); -}; - -class sys_var_thd_table_type :public sys_var_thd_storage_engine -{ -public: - sys_var_thd_table_type(sys_var_chain *chain, const char *name_arg, - plugin_ref SV::*offset_arg) - :sys_var_thd_storage_engine(chain, name_arg, offset_arg) - {} - void warn_deprecated(THD *thd); - void set_default(THD *thd, enum_var_type type); - bool update(THD *thd, set_var *var); -}; - -class sys_var_thd_bit :public sys_var_thd -{ - sys_check_func check_func; - sys_update_func update_func; -public: - ulonglong bit_flag; - bool reverse; - sys_var_thd_bit(sys_var_chain *chain, const char *name_arg, - sys_check_func c_func, sys_update_func u_func, - ulonglong bit, bool reverse_arg=0, - Binlog_status_enum binlog_status_arg= NOT_IN_BINLOG) - :sys_var_thd(name_arg, NULL, binlog_status_arg), check_func(c_func), - update_func(u_func), bit_flag(bit), reverse(reverse_arg) - { chain_sys_var(chain); } - bool check(THD *thd, set_var *var); - bool update(THD *thd, set_var *var); - bool check_update_type(Item_result type) { return 0; } - bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } - SHOW_TYPE show_type() { return SHOW_MY_BOOL; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); -}; - -#ifndef DBUG_OFF -class sys_var_thd_dbug :public sys_var_thd -{ -public: - sys_var_thd_dbug(sys_var_chain *chain, const char *name_arg) - :sys_var_thd(name_arg) - { chain_sys_var(chain); } - bool check_update_type(Item_result type) { return type != STRING_RESULT; } - bool check(THD *thd, set_var *var); - SHOW_TYPE show_type() { return SHOW_CHAR; } - bool update(THD *thd, set_var *var); - void set_default(THD *thd, enum_var_type type) { DBUG_POP(); } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *b); -}; -#endif /* DBUG_OFF */ - -#if defined(ENABLED_DEBUG_SYNC) -/* Debug Sync Facility. Implemented in debug_sync.cc. */ -class sys_var_debug_sync :public sys_var_thd -{ -public: - sys_var_debug_sync(sys_var_chain *chain, const char *name_arg) - :sys_var_thd(name_arg) - { chain_sys_var(chain); } - bool check(THD *thd, set_var *var); - bool update(THD *thd, set_var *var); - SHOW_TYPE show_type() { return SHOW_CHAR; } - bool check_update_type(Item_result type) { return type != STRING_RESULT; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); -}; -#endif /* defined(ENABLED_DEBUG_SYNC) */ - -/* some variables that require special handling */ - -class sys_var_timestamp :public sys_var -{ -public: - sys_var_timestamp(sys_var_chain *chain, const char *name_arg, - Binlog_status_enum binlog_status_arg= NOT_IN_BINLOG) - :sys_var(name_arg, NULL, binlog_status_arg) - { chain_sys_var(chain); } - bool update(THD *thd, set_var *var); - void set_default(THD *thd, enum_var_type type); - bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } - bool check_default(enum_var_type type) { return 0; } - SHOW_TYPE show_type() { return SHOW_LONG; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); -}; - - -class sys_var_last_insert_id :public sys_var -{ -public: - sys_var_last_insert_id(sys_var_chain *chain, const char *name_arg, - Binlog_status_enum binlog_status_arg= NOT_IN_BINLOG) - :sys_var(name_arg, NULL, binlog_status_arg) - { chain_sys_var(chain); } - bool update(THD *thd, set_var *var); - bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } - SHOW_TYPE show_type() { return SHOW_LONGLONG; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); -}; - - -class sys_var_insert_id :public sys_var -{ -public: - sys_var_insert_id(sys_var_chain *chain, const char *name_arg) - :sys_var(name_arg) - { chain_sys_var(chain); } - bool update(THD *thd, set_var *var); - bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } - SHOW_TYPE show_type() { return SHOW_LONGLONG; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); -}; - - -class sys_var_rand_seed1 :public sys_var -{ -public: - sys_var_rand_seed1(sys_var_chain *chain, const char *name_arg, - Binlog_status_enum binlog_status_arg= NOT_IN_BINLOG) - :sys_var(name_arg, NULL, binlog_status_arg) - { chain_sys_var(chain); } - bool update(THD *thd, set_var *var); - bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } -}; - -class sys_var_rand_seed2 :public sys_var -{ -public: - sys_var_rand_seed2(sys_var_chain *chain, const char *name_arg, - Binlog_status_enum binlog_status_arg= NOT_IN_BINLOG) - :sys_var(name_arg, NULL, binlog_status_arg) - { chain_sys_var(chain); } - bool update(THD *thd, set_var *var); - bool check_type(enum_var_type type) { return type == OPT_GLOBAL; } -}; - - -class sys_var_collation :public sys_var_thd -{ -public: - sys_var_collation(const char *name_arg, - Binlog_status_enum binlog_status_arg= NOT_IN_BINLOG) - :sys_var_thd(name_arg, NULL, binlog_status_arg) - { - no_support_one_shot= 0; - } - bool check(THD *thd, set_var *var); - SHOW_TYPE show_type() { return SHOW_CHAR; } - bool check_update_type(Item_result type) - { - return ((type != STRING_RESULT) && (type != INT_RESULT)); - } - bool check_default(enum_var_type type) { return 0; } - virtual void set_default(THD *thd, enum_var_type type)= 0; -}; - -class sys_var_character_set :public sys_var_thd -{ -public: - bool nullable; - sys_var_character_set(const char *name_arg, bool is_nullable= 0, - Binlog_status_enum binlog_status_arg= NOT_IN_BINLOG) - :sys_var_thd(name_arg, NULL, binlog_status_arg), nullable(is_nullable) - { - /* - In fact only almost all variables derived from sys_var_character_set - support ONE_SHOT; character_set_results doesn't. But that's good enough. - */ - no_support_one_shot= 0; - } - bool check(THD *thd, set_var *var); - SHOW_TYPE show_type() { return SHOW_CHAR; } - bool check_update_type(Item_result type) - { - return ((type != STRING_RESULT) && (type != INT_RESULT)); - } - bool check_default(enum_var_type type) { return 0; } - bool update(THD *thd, set_var *var); - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); - virtual void set_default(THD *thd, enum_var_type type)= 0; - virtual CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type)= 0; -}; - -class sys_var_character_set_sv :public sys_var_character_set -{ - CHARSET_INFO *SV::*offset; - CHARSET_INFO **global_default; -public: - sys_var_character_set_sv(sys_var_chain *chain, const char *name_arg, - CHARSET_INFO *SV::*offset_arg, - CHARSET_INFO **global_default_arg, - bool is_nullable= 0, - Binlog_status_enum binlog_status_arg= NOT_IN_BINLOG) - : sys_var_character_set(name_arg, is_nullable, binlog_status_arg), - offset(offset_arg), global_default(global_default_arg) - { chain_sys_var(chain); } - void set_default(THD *thd, enum_var_type type); - CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type); -}; - - -class sys_var_character_set_client: public sys_var_character_set_sv -{ -public: - sys_var_character_set_client(sys_var_chain *chain, const char *name_arg, - CHARSET_INFO *SV::*offset_arg, - CHARSET_INFO **global_default_arg, - Binlog_status_enum binlog_status_arg) - : sys_var_character_set_sv(chain, name_arg, offset_arg, global_default_arg, - 0, binlog_status_arg) - { } - bool check(THD *thd, set_var *var); -}; - - -class sys_var_character_set_database :public sys_var_character_set -{ -public: - sys_var_character_set_database(sys_var_chain *chain, const char *name_arg, - Binlog_status_enum binlog_status_arg= - NOT_IN_BINLOG) - : sys_var_character_set(name_arg, 0, binlog_status_arg) - { chain_sys_var(chain); } - void set_default(THD *thd, enum_var_type type); - CHARSET_INFO **ci_ptr(THD *thd, enum_var_type type); -}; - -class sys_var_collation_sv :public sys_var_collation -{ - CHARSET_INFO *SV::*offset; - CHARSET_INFO **global_default; -public: - sys_var_collation_sv(sys_var_chain *chain, const char *name_arg, - CHARSET_INFO *SV::*offset_arg, - CHARSET_INFO **global_default_arg, - Binlog_status_enum binlog_status_arg= NOT_IN_BINLOG) - :sys_var_collation(name_arg, binlog_status_arg), - offset(offset_arg), global_default(global_default_arg) - { - chain_sys_var(chain); - } - bool update(THD *thd, set_var *var); - void set_default(THD *thd, enum_var_type type); - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); -}; - - -class sys_var_key_cache_param :public sys_var -{ -protected: - size_t offset; -public: - sys_var_key_cache_param(sys_var_chain *chain, const char *name_arg, - size_t offset_arg) - :sys_var(name_arg), offset(offset_arg) - { chain_sys_var(chain); } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); - bool check_default(enum_var_type type) { return 1; } - bool is_struct() { return 1; } -}; - - -class sys_var_key_buffer_size :public sys_var_key_cache_param -{ -public: - sys_var_key_buffer_size(sys_var_chain *chain, const char *name_arg) - :sys_var_key_cache_param(chain, name_arg, - offsetof(KEY_CACHE, param_buff_size)) - {} - bool update(THD *thd, set_var *var); - SHOW_TYPE show_type() { return SHOW_LONGLONG; } -}; - - -class sys_var_key_cache_long :public sys_var_key_cache_param -{ -public: - sys_var_key_cache_long(sys_var_chain *chain, const char *name_arg, size_t offset_arg) - :sys_var_key_cache_param(chain, name_arg, offset_arg) - {} - bool update(THD *thd, set_var *var); - SHOW_TYPE show_type() { return SHOW_LONG; } -}; - - -class sys_var_thd_date_time_format :public sys_var_thd -{ - DATE_TIME_FORMAT *SV::*offset; - timestamp_type date_time_type; -public: - sys_var_thd_date_time_format(sys_var_chain *chain, const char *name_arg, - DATE_TIME_FORMAT *SV::*offset_arg, - timestamp_type date_time_type_arg) - :sys_var_thd(name_arg), offset(offset_arg), - date_time_type(date_time_type_arg) - { chain_sys_var(chain); } - SHOW_TYPE show_type() { return SHOW_CHAR; } - bool check_update_type(Item_result type) - { - return type != STRING_RESULT; /* Only accept strings */ - } - bool check_default(enum_var_type type) { return 0; } - bool check(THD *thd, set_var *var); - bool update(THD *thd, set_var *var); - void update2(THD *thd, enum_var_type type, DATE_TIME_FORMAT *new_value); - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); - void set_default(THD *thd, enum_var_type type); -}; - - -class sys_var_log_state :public sys_var_bool_ptr -{ - uint log_type; -public: - sys_var_log_state(sys_var_chain *chain, const char *name_arg, my_bool *value_arg, - uint log_type_arg) - :sys_var_bool_ptr(chain, name_arg, value_arg), log_type(log_type_arg) {} - bool update(THD *thd, set_var *var); - void set_default(THD *thd, enum_var_type type); -}; - - -class sys_var_set :public sys_var -{ -protected: - ulong *value; - TYPELIB *enum_names; -public: - sys_var_set(sys_var_chain *chain, const char *name_arg, ulong *value_arg, - TYPELIB *typelib, sys_after_update_func func) - :sys_var(name_arg, func), value(value_arg), enum_names(typelib) - { chain_sys_var(chain); } - virtual bool check(THD *thd, set_var *var) - { - return check_set(thd, var, enum_names); - } - virtual void set_default(THD *thd, enum_var_type type) - { - *value= 0; - } - bool update(THD *thd, set_var *var); - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); - bool check_update_type(Item_result type) { return 0; } - SHOW_TYPE show_type() { return SHOW_CHAR; } -}; - -class sys_var_set_slave_mode :public sys_var_set -{ -public: - sys_var_set_slave_mode(sys_var_chain *chain, const char *name_arg, - ulong *value_arg, - TYPELIB *typelib, sys_after_update_func func) : - sys_var_set(chain, name_arg, value_arg, typelib, func) {} - void set_default(THD *thd, enum_var_type type); - bool check(THD *thd, set_var *var); - bool update(THD *thd, set_var *var); -}; - -class sys_var_log_output :public sys_var -{ - ulong *value; - TYPELIB *enum_names; -public: - sys_var_log_output(sys_var_chain *chain, const char *name_arg, ulong *value_arg, - TYPELIB *typelib, sys_after_update_func func) - :sys_var(name_arg,func), value(value_arg), enum_names(typelib) - { - chain_sys_var(chain); - set_allow_empty_value(FALSE); - } - virtual bool check(THD *thd, set_var *var) - { - return check_set(thd, var, enum_names); - } - bool update(THD *thd, set_var *var); - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); - bool check_update_type(Item_result type) { return 0; } - void set_default(THD *thd, enum_var_type type); - SHOW_TYPE show_type() { return SHOW_CHAR; } -}; - - -/* Variable that you can only read from */ - -class sys_var_readonly: public sys_var -{ -public: - enum_var_type var_type; - SHOW_TYPE show_type_value; - sys_value_ptr_func value_ptr_func; - sys_var_readonly(sys_var_chain *chain, const char *name_arg, enum_var_type type, - SHOW_TYPE show_type_arg, - sys_value_ptr_func value_ptr_func_arg) - :sys_var(name_arg), var_type(type), - show_type_value(show_type_arg), value_ptr_func(value_ptr_func_arg) - { chain_sys_var(chain); } - bool update(THD *thd, set_var *var) { return 1; } - bool check_default(enum_var_type type) { return 1; } - bool check_type(enum_var_type type) { return type != var_type; } - bool check_update_type(Item_result type) { return 1; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) - { - return (*value_ptr_func)(thd); - } - SHOW_TYPE show_type() { return show_type_value; } - bool is_readonly() const { return 1; } -}; - - -class sys_var_readonly_os: public sys_var_readonly -{ -public: - sys_var_readonly_os(sys_var_chain *chain, const char *name_arg, enum_var_type type, - SHOW_TYPE show_type_arg, - sys_value_ptr_func value_ptr_func_arg) - :sys_var_readonly(chain, name_arg, type, show_type_arg, value_ptr_func_arg) - { - is_os_charset= TRUE; - } -}; - - -/** - Global-only, read-only variable. E.g. command line option. -*/ - -class sys_var_const: public sys_var -{ -public: - enum_var_type var_type; - SHOW_TYPE show_type_value; - uchar *ptr; - sys_var_const(sys_var_chain *chain, const char *name_arg, enum_var_type type, - SHOW_TYPE show_type_arg, uchar *ptr_arg) - :sys_var(name_arg), var_type(type), - show_type_value(show_type_arg), ptr(ptr_arg) - { chain_sys_var(chain); } - bool update(THD *thd, set_var *var) { return 1; } - bool check_default(enum_var_type type) { return 1; } - bool check_type(enum_var_type type) { return type != var_type; } - bool check_update_type(Item_result type) { return 1; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) - { - return ptr; + switch (scope()) + { + case GLOBAL: return type != OPT_GLOBAL; + case SESSION: return false; // always ok + case ONLY_SESSION: return type == OPT_GLOBAL; + } + return true; // keep gcc happy } - SHOW_TYPE show_type() { return show_type_value; } - bool is_readonly() const { return 1; } -}; - - -class sys_var_const_os: public sys_var_const -{ -public: - enum_var_type var_type; - SHOW_TYPE show_type_value; - uchar *ptr; - sys_var_const_os(sys_var_chain *chain, const char *name_arg, - enum_var_type type, - SHOW_TYPE show_type_arg, uchar *ptr_arg) - :sys_var_const(chain, name_arg, type, show_type_arg, ptr_arg) + bool register_option(DYNAMIC_ARRAY *array, int parse_flags) { - is_os_charset= TRUE; + return (option.id != -1) && (m_parse_flag & parse_flags) && + insert_dynamic(array, (uchar*)&option); } -}; - -class sys_var_have_option: public sys_var -{ +private: + virtual bool do_check(THD *thd, set_var *var) = 0; + /** + save the session default value of the variable in var + */ + virtual void session_save_default(THD *thd, set_var *var) = 0; + /** + save the global default value of the variable in var + */ + virtual void global_save_default(THD *thd, set_var *var) = 0; + virtual bool session_update(THD *thd, set_var *var) = 0; + virtual bool global_update(THD *thd, set_var *var) = 0; + void do_deprecated_warning(THD *thd); protected: - virtual SHOW_COMP_OPTION get_option() = 0; -public: - sys_var_have_option(sys_var_chain *chain, const char *variable_name): - sys_var(variable_name) - { chain_sys_var(chain); } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) - { - return (uchar*) show_comp_option_name[get_option()]; - } - bool update(THD *thd, set_var *var) { return 1; } - bool check_default(enum_var_type type) { return 1; } - bool check_type(enum_var_type type) { return type != OPT_GLOBAL; } - bool check_update_type(Item_result type) { return 1; } - SHOW_TYPE show_type() { return SHOW_CHAR; } - bool is_readonly() const { return 1; } -}; - - -class sys_var_have_variable: public sys_var_have_option -{ - SHOW_COMP_OPTION *have_variable; - -public: - sys_var_have_variable(sys_var_chain *chain, const char *variable_name, - SHOW_COMP_OPTION *have_variable_arg): - sys_var_have_option(chain, variable_name), - have_variable(have_variable_arg) - { } - SHOW_COMP_OPTION get_option() { return *have_variable; } -}; - - -class sys_var_have_plugin: public sys_var_have_option -{ - const char *plugin_name_str; - const uint plugin_name_len; - const int plugin_type; - -public: - sys_var_have_plugin(sys_var_chain *chain, const char *variable_name, - const char *plugin_name_str_arg, uint plugin_name_len_arg, - int plugin_type_arg): - sys_var_have_option(chain, variable_name), - plugin_name_str(plugin_name_str_arg), plugin_name_len(plugin_name_len_arg), - plugin_type(plugin_type_arg) - { } - /* the following method is declared in sql_plugin.cc */ - SHOW_COMP_OPTION get_option(); -}; - - -class sys_var_thd_time_zone :public sys_var_thd -{ -public: - sys_var_thd_time_zone(sys_var_chain *chain, const char *name_arg, - Binlog_status_enum binlog_status_arg= NOT_IN_BINLOG) - :sys_var_thd(name_arg, NULL, binlog_status_arg) - { - no_support_one_shot= 0; - chain_sys_var(chain); - } - bool check(THD *thd, set_var *var); - SHOW_TYPE show_type() { return SHOW_CHAR; } - bool check_update_type(Item_result type) - { - return type != STRING_RESULT; /* Only accept strings */ - } - bool check_default(enum_var_type type) { return 0; } - bool update(THD *thd, set_var *var); - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); - virtual void set_default(THD *thd, enum_var_type type); -}; - - -class sys_var_max_user_conn : public sys_var_thd -{ -public: - sys_var_max_user_conn(sys_var_chain *chain, const char *name_arg): - sys_var_thd(name_arg) - { chain_sys_var(chain); } - bool check(THD *thd, set_var *var); - bool update(THD *thd, set_var *var); - bool check_default(enum_var_type type) - { - return type != OPT_GLOBAL || !option_limits; - } - void set_default(THD *thd, enum_var_type type); - SHOW_TYPE show_type() { return SHOW_INT; } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); -}; - - -/** - * @brief This is a specialization of sys_var_thd_ulong that implements a - read-only session variable. The class overrides check() and check_default() - to achieve the read-only property for the session part of the variable. - */ -class sys_var_thd_ulong_session_readonly : public sys_var_thd_ulong -{ -public: - sys_var_thd_ulong_session_readonly(sys_var_chain *chain_arg, - const char *name_arg, ulong SV::*offset_arg, - sys_check_func c_func= NULL, - sys_after_update_func au_func= NULL, - Binlog_status_enum bl_status_arg= NOT_IN_BINLOG): - sys_var_thd_ulong(chain_arg, name_arg, offset_arg, c_func, au_func, bl_status_arg) - { } - bool check(THD *thd, set_var *var); - bool check_default(enum_var_type type) - { - return type != OPT_GLOBAL || !option_limits; - } -}; - - -class sys_var_microseconds :public sys_var_thd -{ - ulonglong SV::*offset; -public: - sys_var_microseconds(sys_var_chain *chain, const char *name_arg, - ulonglong SV::*offset_arg): - sys_var_thd(name_arg), offset(offset_arg) - { chain_sys_var(chain); } - bool check(THD *thd, set_var *var) {return 0;} - bool update(THD *thd, set_var *var); - void set_default(THD *thd, enum_var_type type); - SHOW_TYPE show_type() { return SHOW_DOUBLE; } - bool check_update_type(Item_result type) - { - return (type != INT_RESULT && type != REAL_RESULT && type != DECIMAL_RESULT); - } - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); -}; - - -class sys_var_trust_routine_creators :public sys_var_bool_ptr -{ - /* We need a derived class only to have a warn_deprecated() */ -public: - sys_var_trust_routine_creators(sys_var_chain *chain, - const char *name_arg, my_bool *value_arg) : - sys_var_bool_ptr(chain, name_arg, value_arg) {}; - void warn_deprecated(THD *thd); - void set_default(THD *thd, enum_var_type type); - bool update(THD *thd, set_var *var); -}; - - -/** - Handler for setting the system variable --read-only. -*/ - -class sys_var_opt_readonly :public sys_var_bool_ptr -{ -public: - sys_var_opt_readonly(sys_var_chain *chain, const char *name_arg, - my_bool *value_arg) : - sys_var_bool_ptr(chain, name_arg, value_arg) {}; - ~sys_var_opt_readonly() {}; - bool update(THD *thd, set_var *var); -}; - - - -class sys_var_thd_lc: public sys_var_thd -{ -public: - sys_var_thd_lc(sys_var_chain *chain, const char *name_arg, - Binlog_status_enum binlog_status_arg= NOT_IN_BINLOG) - : sys_var_thd(name_arg, NULL, binlog_status_arg) - { -#if MYSQL_VERSION_ID < 50000 - no_support_one_shot= 0; -#endif - chain_sys_var(chain); - } - bool check(THD *thd, set_var *var); - SHOW_TYPE show_type() { return SHOW_CHAR; } - bool check_update_type(Item_result type) - { - return ((type != STRING_RESULT) && (type != INT_RESULT)); - } - bool check_default(enum_var_type type) { return 0; } -}; - - -class sys_var_thd_lc_time_names :public sys_var_thd_lc -{ -public: - sys_var_thd_lc_time_names(sys_var_chain *chain_arg, const char *name_arg, - Binlog_status_enum binlog_status_arg= NOT_IN_BINLOG) - : sys_var_thd_lc(chain_arg, name_arg, binlog_status_arg) - {} - bool update(THD *thd, set_var *var); - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); - void set_default(THD *thd, enum_var_type type); -}; - - -class sys_var_thd_lc_messages :public sys_var_thd_lc -{ -public: - sys_var_thd_lc_messages(sys_var_chain *chain_arg, const char *name_arg, - Binlog_status_enum binlog_status_arg= NOT_IN_BINLOG) - : sys_var_thd_lc(chain_arg, name_arg, binlog_status_arg) - {} - bool update(THD *thd, set_var *var); - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); - void set_default(THD *thd, enum_var_type type); -}; - - -#ifdef HAVE_EVENT_SCHEDULER -class sys_var_event_scheduler :public sys_var_long_ptr -{ - /* We need a derived class only to have a warn_deprecated() */ -public: - sys_var_event_scheduler(sys_var_chain *chain, const char *name_arg) : - sys_var_long_ptr(chain, name_arg, NULL, NULL) {}; - bool update(THD *thd, set_var *var); - uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); - SHOW_TYPE show_type() { return SHOW_CHAR; } - bool check(THD *thd, set_var *var); - bool check_update_type(Item_result type) - { - return type != STRING_RESULT && type != INT_RESULT; - } -}; -#endif + /** + A pointer to a value of the variable for SHOW. + It must be of show_val_type type (bool for SHOW_BOOL, int for SHOW_INT, + longlong for SHOW_LONGLONG, etc). + */ + virtual uchar *session_value_ptr(THD *thd, LEX_STRING *base); + virtual uchar *global_value_ptr(THD *thd, LEX_STRING *base); -extern void fix_binlog_format_after_update(THD *thd, enum_var_type type); + /** + A pointer to a storage area of the variable, to the raw data. + Typically it's the same as session_value_ptr(), but it's different, + for example, for ENUM, that is printed as a string, but stored as a number. + */ + uchar *session_var_ptr(THD *thd) + { return ((uchar*)&(thd->variables)) + offset; } -class sys_var_thd_binlog_format :public sys_var_thd_enum -{ -public: - sys_var_thd_binlog_format(sys_var_chain *chain, const char *name_arg, - ulong SV::*offset_arg) - :sys_var_thd_enum(chain, name_arg, offset_arg, - &binlog_format_typelib, - fix_binlog_format_after_update) - {}; - bool check(THD *thd, set_var *var); - bool is_readonly() const; + uchar *global_var_ptr() + { return ((uchar*)&global_system_variables) + offset; } }; /**************************************************************************** Classes for parsing of the SET command ****************************************************************************/ +/** + A base class for everything that can be set with SET command. + It's similar to Items, an instance of this is created by the parser + for every assigmnent in SET (or elsewhere, e.g. in SELECT). +*/ class set_var_base :public Sql_alloc { public: set_var_base() {} virtual ~set_var_base() {} - virtual int check(THD *thd)=0; /* To check privileges etc. */ - virtual int update(THD *thd)=0; /* To set the value */ - /* light check for PS */ - virtual int light_check(THD *thd) { return check(thd); } - virtual bool no_support_one_shot() { return 1; } + virtual int check(THD *thd)=0; /* To check privileges etc. */ + virtual int update(THD *thd)=0; /* To set the value */ + virtual int light_check(THD *thd) { return check(thd); } /* for PS */ }; -/* MySQL internal variables, like query_cache_size */ - +/** + set_var_base descendant for assignments to the system variables. +*/ class set_var :public set_var_base { public: - sys_var *var; - Item *value; + sys_var *var; ///< system variable to be updated + Item *value; ///< the expression that provides the new value of the variable enum_var_type type; - union - { - CHARSET_INFO *charset; - ulong ulong_value; - ulonglong ulonglong_value; - plugin_ref plugin; - DATE_TIME_FORMAT *date_time_format; - Time_zone *time_zone; - MY_LOCALE *locale_value; + union ///< temp storage to hold a value between sys_var::check and ::update + { + ulonglong ulonglong_value; ///< for all integer, set, enum sysvars + double double_value; ///< for Sys_var_double + plugin_ref plugin; ///< for Sys_var_plugin + Time_zone *time_zone; ///< for Sys_var_tz + LEX_STRING string_value; ///< for Sys_var_charptr and others + void *ptr; ///< for Sys_var_struct } save_result; - LEX_STRING base; /* for structs */ + LEX_STRING base; /**< for structured variables, like keycache_name.variable_name */ set_var(enum_var_type type_arg, sys_var *var_arg, const LEX_STRING *base_name_arg, Item *value_arg) @@ -1376,10 +216,10 @@ public: if (value_arg && value_arg->type() == Item::FIELD_ITEM) { Item_field *item= (Item_field*) value_arg; - if (!(value=new Item_string(item->field_name, + if (!(value=new Item_string(item->field_name, (uint) strlen(item->field_name), - system_charset_info))) - value=value_arg; /* Give error message later */ + system_charset_info))) // names are utf8 + value=value_arg; /* Give error message later */ } else value=value_arg; @@ -1387,12 +227,10 @@ public: int check(THD *thd); int update(THD *thd); int light_check(THD *thd); - bool no_support_one_shot() { return var->no_support_one_shot; } }; /* User variables like @my_own_variable */ - class set_var_user: public set_var_base { Item_func_set_user_var *user_var_item; @@ -1429,8 +267,8 @@ class set_var_collation_client: public set_var_base CHARSET_INFO *collation_connection; public: set_var_collation_client(CHARSET_INFO *client_coll_arg, - CHARSET_INFO *connection_coll_arg, - CHARSET_INFO *result_coll_arg) + CHARSET_INFO *connection_coll_arg, + CHARSET_INFO *result_coll_arg) :character_set_client(client_coll_arg), character_set_results(result_coll_arg), collation_connection(connection_coll_arg) @@ -1439,86 +277,27 @@ public: int update(THD *thd); }; - -extern "C" -{ - typedef int (*process_key_cache_t) (const char *, KEY_CACHE *); -} - -/* Named lists (used for keycaches) */ - -class NAMED_LIST :public ilink -{ - const char *name; - uint name_length; -public: - uchar* data; - - NAMED_LIST(I_List<NAMED_LIST> *links, const char *name_arg, - uint name_length_arg, uchar* data_arg) - :name_length(name_length_arg), data(data_arg) - { - name= my_strndup(name_arg, name_length, MYF(MY_WME)); - links->push_back(this); - } - inline bool cmp(const char *name_cmp, uint length) - { - return length == name_length && !memcmp(name, name_cmp, length); - } - ~NAMED_LIST() - { - my_free((uchar*) name, MYF(0)); - } - friend bool process_key_caches(process_key_cache_t func); - friend void delete_elements(I_List<NAMED_LIST> *list, - void (*free_element)(const char*, uchar*)); -}; - -/* updated in sql_acl.cc */ - -extern sys_var_thd_bool sys_old_alter_table; -extern sys_var_thd_bool sys_old_passwords; -extern LEX_STRING default_key_cache_base; - -/* For sql_yacc */ -struct sys_var_with_base -{ - sys_var *var; - LEX_STRING base_name; -}; - /* Prototypes for helper functions */ -int set_var_init(); -void set_var_free(); -SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted); -int mysql_add_sys_var_chain(sys_var *chain, struct my_option *long_options); -int mysql_del_sys_var_chain(sys_var *chain); +SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted, enum enum_var_type type); + sys_var *find_sys_var(THD *thd, const char *str, uint length=0); int sql_set_variables(THD *thd, List<set_var_base> *var_list); -bool not_all_support_one_shot(List<set_var_base> *var_list); -void fix_delay_key_write(THD *thd, enum_var_type type); -void fix_slave_exec_mode(enum_var_type type); -ulong fix_sql_mode(ulong sql_mode); -extern sys_var_const_str sys_charset_system; -extern sys_var_str sys_init_connect; -extern sys_var_str sys_init_slave; -extern sys_var_thd_time_zone sys_time_zone; -extern sys_var_thd_bit sys_autocommit; + +bool fix_delay_key_write(sys_var *self, THD *thd, enum_var_type type); + +ulong expand_sql_mode(ulonglong sql_mode); +bool sql_mode_string_representation(THD *thd, ulong sql_mode, LEX_STRING *ls); + +extern sys_var *Sys_autocommit_ptr; + CHARSET_INFO *get_old_charset_by_name(const char *old_name); -uchar* find_named(I_List<NAMED_LIST> *list, const char *name, uint length, - NAMED_LIST **found); -extern sys_var_str sys_var_general_log_path, sys_var_slow_log_path; +int sys_var_init(); +int sys_var_add_options(DYNAMIC_ARRAY *long_options, int parse_flags); +void sys_var_end(void); -/* key_cache functions */ -KEY_CACHE *get_key_cache(LEX_STRING *cache_name); -KEY_CACHE *get_or_create_key_cache(const char *name, uint length); -void free_key_cache(const char *name, KEY_CACHE *key_cache); -bool process_key_caches(process_key_cache_t func); -void delete_elements(I_List<NAMED_LIST> *list, - void (*free_element)(const char*, uchar*)); +#endif -#endif /* SET_VAR_INCLUDED */ diff --git a/sql/share/Makefile.am b/sql/share/Makefile.am index 06b349d5de2..203dbe54254 100644 --- a/sql/share/Makefile.am +++ b/sql/share/Makefile.am @@ -43,8 +43,8 @@ install-data-local: $(DESTDIR)$(pkgdatadir)/$$lang/errmsg.sys; \ done $(mkinstalldirs) $(DESTDIR)$(pkgdatadir)/charsets - $(INSTALL_DATA) $(srcdir)/errmsg-utf8.txt \ - $(DESTDIR)$(pkgdatadir)/errmsg-utf8.txt; \ + $(INSTALL_DATA) $(srcdir)/errmsg-utf8.txt \ + $(DESTDIR)$(pkgdatadir)/errmsg-utf8.txt; \ $(INSTALL_DATA) $(srcdir)/charsets/README $(DESTDIR)$(pkgdatadir)/charsets/README $(INSTALL_DATA) $(srcdir)/charsets/*.xml $(DESTDIR)$(pkgdatadir)/charsets diff --git a/sql/share/errmsg-cnv.sh b/sql/share/errmsg-cnv.sh deleted file mode 100644 index ac6243c9a37..00000000000 --- a/sql/share/errmsg-cnv.sh +++ /dev/null @@ -1,61 +0,0 @@ -# -# This shell script converts errmsg.txt -# from a mixed-charset format -# to utf8 format -# and writes the result to errmgs-utf8.txt -# - - -cat errmsg.txt | while IFS= ; read -r a -do -cs="" - -var="${a#"${a%%[![:space:]]*}"}" - -case $var in -cze*|hun*|pol*|rum*|slo*) - cs=latin2 - ;; -dan*|nla*|eng*|fre*|ger*|ita*|nor*|por*|spa*|swe*) - cs=latin1 - ;; -est*) - cs=latin7 - ;; -greek*) - cs=windows-1253 - ;; -jpn*) - cs=euc-jp - ;; -jps*) - cs=shift-jis - ;; -kor*) - cs=euc-kr - ;; -serbian*) - cs=windows-1250 - ;; -rus*) - cs=koi8-r - ;; -ukr*) - cs=koi8-u - ;; -*) - echo $a -esac - -if [ "x$cs" != "x" ] -then - b=`echo $a | iconv -f $cs -t utf-8` ; rc=$? - if [ "$rc" == "0" ] - then - echo "$b" - else - echo "# This message failed to convert from $cs, skipped" - fi -fi -done > errmsg-utf8.txt - diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index db99890235a..6591f9d5cb7 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -1777,7 +1777,7 @@ ER_TOO_BIG_FIELDLENGTH 42000 S1009 dan "For stor feltlængde for kolonne '%-.192s' (maks = %lu). Brug BLOB i stedet" nla "Te grote kolomlengte voor '%-.192s' (max = %lu). Maak hiervoor gebruik van het type BLOB" eng "Column length too big for column '%-.192s' (max = %lu); use BLOB or TEXT instead" - jps "column '%-.192s' ã¯,確ä¿ã™ã‚‹ column ã®å¤§ãã•ãŒå¤šã™ãŽã¾ã™. (最大 %lu ã¾ã§). BLOB ã‚’ã‹ã‚ã‚Šã«ä½¿ç”¨ã—ã¦ãã ã•ã„.", + jps "column '%-.192s' ã¯,確ä¿ã™ã‚‹ column ã®å¤§ãã•ãŒå¤šã™ãŽã¾ã™. (最大 %lu ã¾ã§). BLOB ã‚’ã‹ã‚ã‚Šã«ä½¿ç”¨ã—ã¦ãã ã•ã„." est "Tulba '%-.192s' pikkus on liiga pikk (maksimaalne pikkus: %lu). Kasuta BLOB väljatüüpi" fre "Champ '%-.192s' trop long (max = %lu). Utilisez un BLOB" ger "Feldlänge für Feld '%-.192s' zu groß (maximal %lu). BLOB- oder TEXT-Spaltentyp verwenden!" @@ -5014,7 +5014,7 @@ ER_WARN_HOSTNAME_WONT_WORK por "MySQL foi inicializado em modo --skip-name-resolve. Você necesita reincializá-lo sem esta opção para este grant funcionar" spa "MySQL esta inicializado en modo --skip-name-resolve. Usted necesita reinicializarlo sin esta opción para este derecho funcionar" ER_UNKNOWN_STORAGE_ENGINE 42000 - eng "Unknown table engine '%s'" + eng "Unknown storage engine '%s'" ger "Unbekannte Speicher-Engine '%s'" por "Motor de tabela desconhecido '%s'" spa "Desconocido motor de tabla '%s'" @@ -6070,8 +6070,7 @@ ER_SLAVE_INCIDENT ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT eng "Table has no partition for some existing values" ER_BINLOG_UNSAFE_STATEMENT - eng "Statement may not be safe to log in statement format." - swe "Detta är inte säkert att logga i statement-format." + eng "Unsafe statement binlogged in statement format since BINLOG_FORMAT = STATEMENT. Reason for unsafeness: %s" ER_SLAVE_FATAL_ERROR eng "Fatal error: %s" ER_SLAVE_RELAY_LOG_READ_FAILURE @@ -6108,7 +6107,7 @@ ER_TRG_CANT_OPEN_TABLE ER_CANT_CREATE_SROUTINE eng "Cannot create stored routine `%-.64s`. Check warnings" -ER_SLAVE_AMBIGOUS_EXEC_MODE +ER_NEVER_USED eng "Ambiguous slave modes combination. %s" ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT @@ -6120,7 +6119,7 @@ ER_LOAD_DATA_INVALID_COLUMN eng "Invalid column reference (%-.64s) in LOAD DATA" ER_LOG_PURGE_NO_FILE - eng "Being purged log %s was not found" + eng "Being purged log %s was not found" ER_XA_RBTIMEOUT XA106 eng "XA_RBTIMEOUT: Transaction branch was rolled back: took too long" @@ -6196,7 +6195,7 @@ ER_RENAMED_NAME eng "Renamed" swe "Namnändrad" ER_TOO_MANY_CONCURRENT_TRXS - eng "Too many active concurrent transactions" + eng "Too many active concurrent transactions" WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED eng "Non-ASCII separator arguments are not fully supported" @@ -6235,7 +6234,7 @@ WARN_COND_ITEM_TRUNCATED ER_COND_ITEM_TOO_LONG eng "Data too long for condition item '%s'" -ER_UNKNOWN_LOCALE +ER_UNKNOWN_LOCALE eng "Unknown locale: '%-.64s'" ER_SLAVE_IGNORE_SERVER_IDS @@ -6260,3 +6259,60 @@ ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD eng "Field '%-.192s' is of a not allowed type for this type of partitioning" ER_PARTITION_FIELDS_TOO_LONG eng "The total length of the partitioning fields is too large" +ER_BINLOG_ROW_ENGINE_AND_STMT_ENGINE + eng "Cannot execute statement: binlogging impossible since both row-incapable engines and statement-incapable engines are involved." +ER_BINLOG_ROW_MODE_AND_STMT_ENGINE + eng "Cannot execute statement: binlogging impossible since BINLOG_FORMAT = ROW and at least one table uses a storage engine limited to statement-logging." +ER_BINLOG_UNSAFE_AND_STMT_ENGINE + eng "Cannot execute statement: binlogging of unsafe statement is impossible when storage engine is limited to statement-logging and BINLOG_FORMAT = MIXED. Reason for unsafeness: %s" +ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE + eng "Cannot execute row injection: binlogging impossible since at least one table uses a storage engine limited to statement-logging." +ER_BINLOG_STMT_MODE_AND_ROW_ENGINE + eng "Cannot execute statement: binlogging impossible since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-logging.%s" +ER_BINLOG_ROW_INJECTION_AND_STMT_MODE + eng "Cannot execute row injection: binlogging impossible since BINLOG_FORMAT = STATEMENT." +ER_BINLOG_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE + eng "Cannot execute statement: binlogging impossible since more than one engine is involved and at least one engine is self-logging." + +ER_BINLOG_UNSAFE_LIMIT + eng "Statement uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted." +ER_BINLOG_UNSAFE_INSERT_DELAYED + eng "Statement uses INSERT DELAYED. This is unsafe because the time when rows are inserted cannot be predicted." +ER_BINLOG_UNSAFE_SYSTEM_TABLE + eng "Statement uses the general_log, slow_log or performance_schema table(s). This is unsafe because system tables may differ on slave." +ER_BINLOG_UNSAFE_AUTOINC_COLUMNS + eng "Statement invokes a trigger or a stored function that inserts into AUTO_INCREMENT column which is unsafe to binlog in STATEMENT format because slave may execute it non-deterministically." +ER_BINLOG_UNSAFE_UDF + eng "Statement uses a UDF. It cannot be determined if the UDF will return the same value on slave." +ER_BINLOG_UNSAFE_SYSTEM_VARIABLE + eng "Statement uses a system variable whose value may differ on slave." +ER_BINLOG_UNSAFE_SYSTEM_FUNCTION + eng "Statement uses a system function whose value may differ on slave." +ER_BINLOG_UNSAFE_NONTRANS_AFTER_TRANS + eng "Non-transactional reads or writes are unsafe if they occur after transactional reads or writes inside a transaction." + +ER_MESSAGE_AND_STATEMENT + eng "%s Statement: %s" + +ER_SLAVE_CONVERSION_FAILED + eng "Column %d of table '%-.192s.%-.192s' cannot be converted from type '%-.32s' to type '%-.32s'" +ER_SLAVE_CANT_CREATE_CONVERSION + eng "Can't create conversion table for table '%-.192s.%-.192s'" +ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT + eng "Cannot modify @@session.binlog_format inside a transaction" +ER_PATH_LENGTH + eng "The path specified for %.64s is too long." +ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT + eng "The syntax '%s' is deprecated and will be removed in MySQL %s." + ger "Die Syntax '%s' ist veraltet und wird in MySQL %s entfernt." + +ER_WRONG_NATIVE_TABLE_STRUCTURE + eng "Native table '%-.64s'.'%-.64s' has the wrong structure" + +ER_WRONG_PERFSCHEMA_USAGE + eng "Invalid performance_schema usage." + +ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT + eng "Cannot modify @@session.binlog_direct_non_transactional_updates inside a transaction" +ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_DIRECT + eng "Cannot change the binlog direct flag inside a stored function or trigger" diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt deleted file mode 100644 index b5f227e5550..00000000000 --- a/sql/share/errmsg.txt +++ /dev/null @@ -1,6262 +0,0 @@ -languages czech=cze latin2, danish=dan latin1, dutch=nla latin1, english=eng latin1, estonian=est latin7, french=fre latin1, german=ger latin1, greek=greek greek, hungarian=hun latin2, italian=ita latin1, japanese=jpn ujis, japanese-sjis=jps sjis, korean=kor euckr, norwegian-ny=norwegian-ny latin1, norwegian=nor latin1, polish=pol latin2, portuguese=por latin1, romanian=rum latin2, russian=rus koi8r, serbian=serbian cp1250, slovak=slo latin2, spanish=spa latin1, swedish=swe latin1, ukrainian=ukr koi8u; - -default-language eng - -start-error-number 1000 - -ER_HASHCHK - eng "hashchk" -ER_NISAMCHK - eng "isamchk" -ER_NO - cze "NE" - dan "NEJ" - nla "NEE" - eng "NO" - est "EI" - fre "NON" - ger "Nein" - greek "Ï×É" - hun "NEM" - kor "¾Æ´Ï¿À" - nor "NEI" - norwegian-ny "NEI" - pol "NIE" - por "NÃO" - rum "NU" - rus "îåô" - serbian "NE" - slo "NIE" - ukr "î¶" -ER_YES - cze "ANO" - dan "JA" - nla "JA" - eng "YES" - est "JAH" - fre "OUI" - ger "Ja" - greek "ÍÁÉ" - hun "IGEN" - ita "SI" - kor "¿¹" - nor "JA" - norwegian-ny "JA" - pol "TAK" - por "SIM" - rum "DA" - rus "äá" - serbian "DA" - slo "Áno" - spa "SI" - ukr "ôáë" -ER_CANT_CREATE_FILE - cze "Nemohu vytvo-Bøit soubor '%-.200s' (chybový kód: %d)" - dan "Kan ikke oprette filen '%-.200s' (Fejlkode: %d)" - nla "Kan file '%-.200s' niet aanmaken (Errcode: %d)" - eng "Can't create file '%-.200s' (errno: %d)" - est "Ei suuda luua faili '%-.200s' (veakood: %d)" - fre "Ne peut créer le fichier '%-.200s' (Errcode: %d)" - ger "Kann Datei '%-.200s' nicht erzeugen (Fehler: %d)" - greek "Áäýíáôç ç äçìéïõñãßá ôïõ áñ÷åßïõ '%-.200s' (êùäéêüò ëÜèïõò: %d)" - hun "A '%-.200s' file nem hozhato letre (hibakod: %d)" - ita "Impossibile creare il file '%-.200s' (errno: %d)" - jpn "'%-.200s' ¥Õ¥¡¥¤¥ë¤¬ºî¤ì¤Þ¤»¤ó (errno: %d)" - kor "ÈÀÏ '%-.200s'¸¦ ¸¸µéÁö ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)" - nor "Kan ikke opprette fila '%-.200s' (Feilkode: %d)" - norwegian-ny "Kan ikkje opprette fila '%-.200s' (Feilkode: %d)" - pol "Nie mo¿na stworzyæ pliku '%-.200s' (Kod b³êdu: %d)" - por "Não pode criar o arquivo '%-.200s' (erro no. %d)" - rum "Nu pot sa creez fisierul '%-.200s' (Eroare: %d)" - rus "îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÆÁÊÌ '%-.200s' (ÏÛÉÂËÁ: %d)" - serbian "Ne mogu da kreiram file '%-.200s' (errno: %d)" - slo "Nemô¾em vytvori» súbor '%-.200s' (chybový kód: %d)" - spa "No puedo crear archivo '%-.200s' (Error: %d)" - swe "Kan inte skapa filen '%-.200s' (Felkod: %d)" - ukr "îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÆÁÊÌ '%-.200s' (ÐÏÍÉÌËÁ: %d)" -ER_CANT_CREATE_TABLE - cze "Nemohu vytvo-Bøit tabulku '%-.200s' (chybový kód: %d)" - dan "Kan ikke oprette tabellen '%-.200s' (Fejlkode: %d)" - nla "Kan tabel '%-.200s' niet aanmaken (Errcode: %d)" - eng "Can't create table '%-.200s' (errno: %d)" - jps "'%-.200s' ƒe[ƒuƒ‹‚ªì‚ê‚Ü‚¹‚ñ.(errno: %d)", - est "Ei suuda luua tabelit '%-.200s' (veakood: %d)" - fre "Ne peut créer la table '%-.200s' (Errcode: %d)" - ger "Kann Tabelle '%-.200s' nicht erzeugen (Fehler: %d)" - greek "Áäýíáôç ç äçìéïõñãßá ôïõ ðßíáêá '%-.200s' (êùäéêüò ëÜèïõò: %d)" - hun "A '%-.200s' tabla nem hozhato letre (hibakod: %d)" - ita "Impossibile creare la tabella '%-.200s' (errno: %d)" - jpn "'%-.200s' ¥Æ¡¼¥Ö¥ë¤¬ºî¤ì¤Þ¤»¤ó.(errno: %d)" - kor "Å×À̺í '%-.200s'¸¦ ¸¸µéÁö ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)" - nor "Kan ikke opprette tabellen '%-.200s' (Feilkode: %d)" - norwegian-ny "Kan ikkje opprette tabellen '%-.200s' (Feilkode: %d)" - pol "Nie mo¿na stworzyæ tabeli '%-.200s' (Kod b³êdu: %d)" - por "Não pode criar a tabela '%-.200s' (erro no. %d)" - rum "Nu pot sa creez tabla '%-.200s' (Eroare: %d)" - rus "îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÔÁÂÌÉÃÕ '%-.200s' (ÏÛÉÂËÁ: %d)" - serbian "Ne mogu da kreiram tabelu '%-.200s' (errno: %d)" - slo "Nemô¾em vytvori» tabuµku '%-.200s' (chybový kód: %d)" - spa "No puedo crear tabla '%-.200s' (Error: %d)" - swe "Kan inte skapa tabellen '%-.200s' (Felkod: %d)" - ukr "îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÔÁÂÌÉÃÀ '%-.200s' (ÐÏÍÉÌËÁ: %d)" -ER_CANT_CREATE_DB - cze "Nemohu vytvo-Bøit databázi '%-.192s' (chybový kód: %d)" - dan "Kan ikke oprette databasen '%-.192s' (Fejlkode: %d)" - nla "Kan database '%-.192s' niet aanmaken (Errcode: %d)" - eng "Can't create database '%-.192s' (errno: %d)" - jps "'%-.192s' ƒf[ƒ^ƒx[ƒX‚ªì‚ê‚Ü‚¹‚ñ (errno: %d)", - est "Ei suuda luua andmebaasi '%-.192s' (veakood: %d)" - fre "Ne peut créer la base '%-.192s' (Erreur %d)" - ger "Kann Datenbank '%-.192s' nicht erzeugen (Fehler: %d)" - greek "Áäýíáôç ç äçìéïõñãßá ôçò âÜóçò äåäïìÝíùí '%-.192s' (êùäéêüò ëÜèïõò: %d)" - hun "Az '%-.192s' adatbazis nem hozhato letre (hibakod: %d)" - ita "Impossibile creare il database '%-.192s' (errno: %d)" - jpn "'%-.192s' ¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬ºî¤ì¤Þ¤»¤ó (errno: %d)" - kor "µ¥ÀÌŸº£À̽º '%-.192s'¸¦ ¸¸µéÁö ¸øÇß½À´Ï´Ù.. (¿¡·¯¹øÈ£: %d)" - nor "Kan ikke opprette databasen '%-.192s' (Feilkode: %d)" - norwegian-ny "Kan ikkje opprette databasen '%-.192s' (Feilkode: %d)" - pol "Nie mo¿na stworzyæ bazy danych '%-.192s' (Kod b³êdu: %d)" - por "Não pode criar o banco de dados '%-.192s' (erro no. %d)" - rum "Nu pot sa creez baza de date '%-.192s' (Eroare: %d)" - rus "îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÂÁÚÕ ÄÁÎÎÙÈ '%-.192s' (ÏÛÉÂËÁ: %d)" - serbian "Ne mogu da kreiram bazu '%-.192s' (errno: %d)" - slo "Nemô¾em vytvori» databázu '%-.192s' (chybový kód: %d)" - spa "No puedo crear base de datos '%-.192s' (Error: %d)" - swe "Kan inte skapa databasen '%-.192s' (Felkod: %d)" - ukr "îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÂÁÚÕ ÄÁÎÎÉÈ '%-.192s' (ÐÏÍÉÌËÁ: %d)" -ER_DB_CREATE_EXISTS - cze "Nemohu vytvo-Bøit databázi '%-.192s'; databáze ji¾ existuje" - dan "Kan ikke oprette databasen '%-.192s'; databasen eksisterer" - nla "Kan database '%-.192s' niet aanmaken; database bestaat reeds" - eng "Can't create database '%-.192s'; database exists" - jps "'%-.192s' ƒf[ƒ^ƒx[ƒX‚ªì‚ê‚Ü‚¹‚ñ.Šù‚É‚»‚̃f[ƒ^ƒx[ƒX‚ª‘¶Ý‚µ‚Ü‚·", - est "Ei suuda luua andmebaasi '%-.192s': andmebaas juba eksisteerib" - fre "Ne peut créer la base '%-.192s'; elle existe déjà" - ger "Kann Datenbank '%-.192s' nicht erzeugen. Datenbank existiert bereits" - greek "Áäýíáôç ç äçìéïõñãßá ôçò âÜóçò äåäïìÝíùí '%-.192s'; Ç âÜóç äåäïìÝíùí õðÜñ÷åé Þäç" - hun "Az '%-.192s' adatbazis nem hozhato letre Az adatbazis mar letezik" - ita "Impossibile creare il database '%-.192s'; il database esiste" - jpn "'%-.192s' ¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬ºî¤ì¤Þ¤»¤ó.´û¤Ë¤½¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬Â¸ºß¤·¤Þ¤¹" - kor "µ¥ÀÌŸº£À̽º '%-.192s'¸¦ ¸¸µéÁö ¸øÇß½À´Ï´Ù.. µ¥ÀÌŸº£À̽º°¡ Á¸ÀçÇÔ" - nor "Kan ikke opprette databasen '%-.192s'; databasen eksisterer" - norwegian-ny "Kan ikkje opprette databasen '%-.192s'; databasen eksisterer" - pol "Nie mo¿na stworzyæ bazy danych '%-.192s'; baza danych ju¿ istnieje" - por "Não pode criar o banco de dados '%-.192s'; este banco de dados já existe" - rum "Nu pot sa creez baza de date '%-.192s'; baza de date exista deja" - rus "îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÂÁÚÕ ÄÁÎÎÙÈ '%-.192s'. âÁÚÁ ÄÁÎÎÙÈ ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ" - serbian "Ne mogu da kreiram bazu '%-.192s'; baza veæ postoji." - slo "Nemô¾em vytvori» databázu '%-.192s'; databáza existuje" - spa "No puedo crear base de datos '%-.192s'; la base de datos ya existe" - swe "Databasen '%-.192s' existerar redan" - ukr "îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÂÁÚÕ ÄÁÎÎÉÈ '%-.192s'. âÁÚÁ ÄÁÎÎÉÈ ¦ÓÎÕ¤" -ER_DB_DROP_EXISTS - cze "Nemohu zru-B¹it databázi '%-.192s', databáze neexistuje" - dan "Kan ikke slette (droppe) '%-.192s'; databasen eksisterer ikke" - nla "Kan database '%-.192s' niet verwijderen; database bestaat niet" - eng "Can't drop database '%-.192s'; database doesn't exist" - jps "'%-.192s' ƒf[ƒ^ƒx[ƒX‚ð”jŠü‚Å‚«‚Ü‚¹‚ñ. ‚»‚̃f[ƒ^ƒx[ƒX‚ª‚È‚¢‚Ì‚Å‚·.", - est "Ei suuda kustutada andmebaasi '%-.192s': andmebaasi ei eksisteeri" - fre "Ne peut effacer la base '%-.192s'; elle n'existe pas" - ger "Kann Datenbank '%-.192s' nicht löschen; Datenbank nicht vorhanden" - greek "Áäýíáôç ç äéáãñáöÞ ôçò âÜóçò äåäïìÝíùí '%-.192s'. Ç âÜóç äåäïìÝíùí äåí õðÜñ÷åé" - hun "A(z) '%-.192s' adatbazis nem szuntetheto meg. Az adatbazis nem letezik" - ita "Impossibile cancellare '%-.192s'; il database non esiste" - jpn "'%-.192s' ¥Ç¡¼¥¿¥Ù¡¼¥¹¤òÇË´þ¤Ç¤¤Þ¤»¤ó. ¤½¤Î¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬¤Ê¤¤¤Î¤Ç¤¹." - kor "µ¥ÀÌŸº£À̽º '%-.192s'¸¦ Á¦°ÅÇÏÁö ¸øÇß½À´Ï´Ù. µ¥ÀÌŸº£À̽º°¡ Á¸ÀçÇÏÁö ¾ÊÀ½ " - nor "Kan ikke fjerne (drop) '%-.192s'; databasen eksisterer ikke" - norwegian-ny "Kan ikkje fjerne (drop) '%-.192s'; databasen eksisterer ikkje" - pol "Nie mo¿na usun?æ bazy danych '%-.192s'; baza danych nie istnieje" - por "Não pode eliminar o banco de dados '%-.192s'; este banco de dados não existe" - rum "Nu pot sa drop baza de date '%-.192s'; baza da date este inexistenta" - rus "îÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ ÂÁÚÕ ÄÁÎÎÙÈ '%-.192s'. ôÁËÏÊ ÂÁÚÙ ÄÁÎÎÙÈ ÎÅÔ" - serbian "Ne mogu da izbrišem bazu '%-.192s'; baza ne postoji." - slo "Nemô¾em zmaza» databázu '%-.192s'; databáza neexistuje" - spa "No puedo eliminar base de datos '%-.192s'; la base de datos no existe" - swe "Kan inte radera databasen '%-.192s'; databasen finns inte" - ukr "îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ ÂÁÚÕ ÄÁÎÎÉÈ '%-.192s'. âÁÚÁ ÄÁÎÎÉÈ ÎÅ ¦ÓÎÕ¤" -ER_DB_DROP_DELETE - cze "Chyba p-Bøi ru¹ení databáze (nemohu vymazat '%-.192s', chyba %d)" - dan "Fejl ved sletning (drop) af databasen (kan ikke slette '%-.192s', Fejlkode %d)" - nla "Fout bij verwijderen database (kan '%-.192s' niet verwijderen, Errcode: %d)" - eng "Error dropping database (can't delete '%-.192s', errno: %d)" - jps "ƒf[ƒ^ƒx[ƒX”jŠüƒGƒ‰[ ('%-.192s' ‚ð휂ł«‚Ü‚¹‚ñ, errno: %d)", - est "Viga andmebaasi kustutamisel (ei suuda kustutada faili '%-.192s', veakood: %d)" - fre "Ne peut effacer la base '%-.192s' (erreur %d)" - ger "Fehler beim Löschen der Datenbank ('%-.192s' kann nicht gelöscht werden, Fehler: %d)" - greek "ÐáñïõóéÜóôçêå ðñüâëçìá êáôÜ ôç äéáãñáöÞ ôçò âÜóçò äåäïìÝíùí (áäýíáôç ç äéáãñáöÞ '%-.192s', êùäéêüò ëÜèïõò: %d)" - hun "Adatbazis megszuntetesi hiba ('%-.192s' nem torolheto, hibakod: %d)" - ita "Errore durante la cancellazione del database (impossibile cancellare '%-.192s', errno: %d)" - jpn "¥Ç¡¼¥¿¥Ù¡¼¥¹ÇË´þ¥¨¥é¡¼ ('%-.192s' ¤òºï½ü¤Ç¤¤Þ¤»¤ó, errno: %d)" - kor "µ¥ÀÌŸº£À̽º Á¦°Å ¿¡·¯('%-.192s'¸¦ »èÁ¦ÇÒ ¼ö ¾øÀ¾´Ï´Ù, ¿¡·¯¹øÈ£: %d)" - nor "Feil ved fjerning (drop) av databasen (kan ikke slette '%-.192s', feil %d)" - norwegian-ny "Feil ved fjerning (drop) av databasen (kan ikkje slette '%-.192s', feil %d)" - pol "B³?d podczas usuwania bazy danych (nie mo¿na usun?æ '%-.192s', b³?d %d)" - por "Erro ao eliminar banco de dados (não pode eliminar '%-.192s' - erro no. %d)" - rum "Eroare dropuind baza de date (nu pot sa sterg '%-.192s', Eroare: %d)" - rus "ïÛÉÂËÁ ÐÒÉ ÕÄÁÌÅÎÉÉ ÂÁÚÙ ÄÁÎÎÙÈ (ÎÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ '%-.192s', ÏÛÉÂËÁ: %d)" - serbian "Ne mogu da izbrišem bazu (ne mogu da izbrišem '%-.192s', errno: %d)" - slo "Chyba pri mazaní databázy (nemô¾em zmaza» '%-.192s', chybový kód: %d)" - spa "Error eliminando la base de datos(no puedo borrar '%-.192s', error %d)" - swe "Fel vid radering av databasen (Kan inte radera '%-.192s'. Felkod: %d)" - ukr "îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ ÂÁÚÕ ÄÁÎÎÉÈ (îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ '%-.192s', ÐÏÍÉÌËÁ: %d)" -ER_DB_DROP_RMDIR - cze "Chyba p-Bøi ru¹ení databáze (nemohu vymazat adresáø '%-.192s', chyba %d)" - dan "Fejl ved sletting af database (kan ikke slette folderen '%-.192s', Fejlkode %d)" - nla "Fout bij verwijderen database (kan rmdir '%-.192s' niet uitvoeren, Errcode: %d)" - eng "Error dropping database (can't rmdir '%-.192s', errno: %d)" - jps "ƒf[ƒ^ƒx[ƒX”jŠüƒGƒ‰[ ('%-.192s' ‚ð rmdir ‚Å‚«‚Ü‚¹‚ñ, errno: %d)", - est "Viga andmebaasi kustutamisel (ei suuda kustutada kataloogi '%-.192s', veakood: %d)" - fre "Erreur en effaçant la base (rmdir '%-.192s', erreur %d)" - ger "Fehler beim Löschen der Datenbank (Verzeichnis '%-.192s' kann nicht gelöscht werden, Fehler: %d)" - greek "ÐáñïõóéÜóôçêå ðñüâëçìá êáôÜ ôç äéáãñáöÞ ôçò âÜóçò äåäïìÝíùí (áäýíáôç ç äéáãñáöÞ ôïõ öáêÝëëïõ '%-.192s', êùäéêüò ëÜèïõò: %d)" - hun "Adatbazis megszuntetesi hiba ('%-.192s' nem szuntetheto meg, hibakod: %d)" - ita "Errore durante la cancellazione del database (impossibile rmdir '%-.192s', errno: %d)" - jpn "¥Ç¡¼¥¿¥Ù¡¼¥¹ÇË´þ¥¨¥é¡¼ ('%-.192s' ¤ò rmdir ¤Ç¤¤Þ¤»¤ó, errno: %d)" - kor "µ¥ÀÌŸº£À̽º Á¦°Å ¿¡·¯(rmdir '%-.192s'¸¦ ÇÒ ¼ö ¾øÀ¾´Ï´Ù, ¿¡·¯¹øÈ£: %d)" - nor "Feil ved sletting av database (kan ikke slette katalogen '%-.192s', feil %d)" - norwegian-ny "Feil ved sletting av database (kan ikkje slette katalogen '%-.192s', feil %d)" - pol "B³?d podczas usuwania bazy danych (nie mo¿na wykonaæ rmdir '%-.192s', b³?d %d)" - por "Erro ao eliminar banco de dados (não pode remover diretório '%-.192s' - erro no. %d)" - rum "Eroare dropuind baza de date (nu pot sa rmdir '%-.192s', Eroare: %d)" - rus "îÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ ÂÁÚÕ ÄÁÎÎÙÈ (ÎÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ ËÁÔÁÌÏÇ '%-.192s', ÏÛÉÂËÁ: %d)" - serbian "Ne mogu da izbrišem bazu (ne mogu da izbrišem direktorijum '%-.192s', errno: %d)" - slo "Chyba pri mazaní databázy (nemô¾em vymaza» adresár '%-.192s', chybový kód: %d)" - spa "Error eliminando la base de datos (No puedo borrar directorio '%-.192s', error %d)" - swe "Fel vid radering av databasen (Kan inte radera biblioteket '%-.192s'. Felkod: %d)" - ukr "îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ ÂÁÚÕ ÄÁÎÎÉÈ (îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ ÔÅËÕ '%-.192s', ÐÏÍÉÌËÁ: %d)" -ER_CANT_DELETE_FILE - cze "Chyba p-Bøi výmazu '%-.192s' (chybový kód: %d)" - dan "Fejl ved sletning af '%-.192s' (Fejlkode: %d)" - nla "Fout bij het verwijderen van '%-.192s' (Errcode: %d)" - eng "Error on delete of '%-.192s' (errno: %d)" - jps "'%-.192s' ‚Ì휂ªƒGƒ‰[ (errno: %d)", - est "Viga '%-.192s' kustutamisel (veakood: %d)" - fre "Erreur en effaçant '%-.192s' (Errcode: %d)" - ger "Fehler beim Löschen von '%-.192s' (Fehler: %d)" - greek "ÐáñïõóéÜóôçêå ðñüâëçìá êáôÜ ôç äéáãñáöÞ '%-.192s' (êùäéêüò ëÜèïõò: %d)" - hun "Torlesi hiba: '%-.192s' (hibakod: %d)" - ita "Errore durante la cancellazione di '%-.192s' (errno: %d)" - jpn "'%-.192s' ¤Îºï½ü¤¬¥¨¥é¡¼ (errno: %d)" - kor "'%-.192s' »èÁ¦ Áß ¿¡·¯ (¿¡·¯¹øÈ£: %d)" - nor "Feil ved sletting av '%-.192s' (Feilkode: %d)" - norwegian-ny "Feil ved sletting av '%-.192s' (Feilkode: %d)" - pol "B³?d podczas usuwania '%-.192s' (Kod b³êdu: %d)" - por "Erro na remoção de '%-.192s' (erro no. %d)" - rum "Eroare incercind sa delete '%-.192s' (Eroare: %d)" - rus "ïÛÉÂËÁ ÐÒÉ ÕÄÁÌÅÎÉÉ '%-.192s' (ÏÛÉÂËÁ: %d)" - serbian "Greška pri brisanju '%-.192s' (errno: %d)" - slo "Chyba pri mazaní '%-.192s' (chybový kód: %d)" - spa "Error en el borrado de '%-.192s' (Error: %d)" - swe "Kan inte radera filen '%-.192s' (Felkod: %d)" - ukr "îÅ ÍÏÖÕ ×ÉÄÁÌÉÔÉ '%-.192s' (ÐÏÍÉÌËÁ: %d)" -ER_CANT_FIND_SYSTEM_REC - cze "Nemohu -Bèíst záznam v systémové tabulce" - dan "Kan ikke læse posten i systemfolderen" - nla "Kan record niet lezen in de systeem tabel" - eng "Can't read record in system table" - jps "system table ‚̃ŒƒR[ƒh‚ð“Ç‚ÞŽ–‚ª‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½", - est "Ei suuda lugeda kirjet süsteemsest tabelist" - fre "Ne peut lire un enregistrement de la table 'system'" - ger "Datensatz in der Systemtabelle nicht lesbar" - greek "Áäýíáôç ç áíÜãíùóç åããñáöÞò áðü ðßíáêá ôïõ óõóôÞìáôïò" - hun "Nem olvashato rekord a rendszertablaban" - ita "Impossibile leggere il record dalla tabella di sistema" - jpn "system table ¤Î¥ì¥³¡¼¥É¤òÆɤà»ö¤¬¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿" - kor "system Å×ÀÌºí¿¡¼ ·¹Äڵ带 ÀÐÀ» ¼ö ¾ø½À´Ï´Ù." - nor "Kan ikke lese posten i systemkatalogen" - norwegian-ny "Kan ikkje lese posten i systemkatalogen" - pol "Nie mo¿na odczytaæ rekordu z tabeli systemowej" - por "Não pode ler um registro numa tabela do sistema" - rum "Nu pot sa citesc cimpurile in tabla de system (system table)" - rus "îÅ×ÏÚÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ ÚÁÐÉÓØ × ÓÉÓÔÅÍÎÏÊ ÔÁÂÌÉÃÅ" - serbian "Ne mogu da proèitam slog iz sistemske tabele" - slo "Nemô¾em èíta» záznam v systémovej tabuµke" - spa "No puedo leer el registro en la tabla del sistema" - swe "Hittar inte posten i systemregistret" - ukr "îÅ ÍÏÖÕ ÚÞÉÔÁÔÉ ÚÁÐÉÓ Ú ÓÉÓÔÅÍÎϧ ÔÁÂÌÉæ" -ER_CANT_GET_STAT - cze "Nemohu z-Bískat stav '%-.200s' (chybový kód: %d)" - dan "Kan ikke læse status af '%-.200s' (Fejlkode: %d)" - nla "Kan de status niet krijgen van '%-.200s' (Errcode: %d)" - eng "Can't get status of '%-.200s' (errno: %d)" - jps "'%-.200s' ‚̃XƒeƒCƒ^ƒX‚ª“¾‚ç‚ê‚Ü‚¹‚ñ. (errno: %d)", - est "Ei suuda lugeda '%-.200s' olekut (veakood: %d)" - fre "Ne peut obtenir le status de '%-.200s' (Errcode: %d)" - ger "Kann Status von '%-.200s' nicht ermitteln (Fehler: %d)" - greek "Áäýíáôç ç ëÞøç ðëçñïöïñéþí ãéá ôçí êáôÜóôáóç ôïõ '%-.200s' (êùäéêüò ëÜèïõò: %d)" - hun "A(z) '%-.200s' statusza nem allapithato meg (hibakod: %d)" - ita "Impossibile leggere lo stato di '%-.200s' (errno: %d)" - jpn "'%-.200s' ¤Î¥¹¥Æ¥¤¥¿¥¹¤¬ÆÀ¤é¤ì¤Þ¤»¤ó. (errno: %d)" - kor "'%-.200s'ÀÇ »óŸ¦ ¾òÁö ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)" - nor "Kan ikke lese statusen til '%-.200s' (Feilkode: %d)" - norwegian-ny "Kan ikkje lese statusen til '%-.200s' (Feilkode: %d)" - pol "Nie mo¿na otrzymaæ statusu '%-.200s' (Kod b³êdu: %d)" - por "Não pode obter o status de '%-.200s' (erro no. %d)" - rum "Nu pot sa obtin statusul lui '%-.200s' (Eroare: %d)" - rus "îÅ×ÏÚÍÏÖÎÏ ÐÏÌÕÞÉÔØ ÓÔÁÔÕÓÎÕÀ ÉÎÆÏÒÍÁÃÉÀ Ï '%-.200s' (ÏÛÉÂËÁ: %d)" - serbian "Ne mogu da dobijem stanje file-a '%-.200s' (errno: %d)" - slo "Nemô¾em zisti» stav '%-.200s' (chybový kód: %d)" - spa "No puedo obtener el estado de '%-.200s' (Error: %d)" - swe "Kan inte läsa filinformationen (stat) från '%-.200s' (Felkod: %d)" - ukr "îÅ ÍÏÖÕ ÏÔÒÉÍÁÔÉ ÓÔÁÔÕÓ '%-.200s' (ÐÏÍÉÌËÁ: %d)" -ER_CANT_GET_WD - cze "Chyba p-Bøi zji¹»ování pracovní adresáø (chybový kód: %d)" - dan "Kan ikke læse aktive folder (Fejlkode: %d)" - nla "Kan de werkdirectory niet krijgen (Errcode: %d)" - eng "Can't get working directory (errno: %d)" - jps "working directory ‚𓾂鎖‚ª‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½ (errno: %d)", - est "Ei suuda identifitseerida jooksvat kataloogi (veakood: %d)" - fre "Ne peut obtenir le répertoire de travail (Errcode: %d)" - ger "Kann Arbeitsverzeichnis nicht ermitteln (Fehler: %d)" - greek "Ï öÜêåëëïò åñãáóßáò äåí âñÝèçêå (êùäéêüò ëÜèïõò: %d)" - hun "A munkakonyvtar nem allapithato meg (hibakod: %d)" - ita "Impossibile leggere la directory di lavoro (errno: %d)" - jpn "working directory ¤òÆÀ¤ë»ö¤¬¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿ (errno: %d)" - kor "¼öÇà µð·ºÅ丮¸¦ ãÁö ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)" - nor "Kan ikke lese aktiv katalog(Feilkode: %d)" - norwegian-ny "Kan ikkje lese aktiv katalog(Feilkode: %d)" - pol "Nie mo¿na rozpoznaæ aktualnego katalogu (Kod b³êdu: %d)" - por "Não pode obter o diretório corrente (erro no. %d)" - rum "Nu pot sa obtin directorul current (working directory) (Eroare: %d)" - rus "îÅ×ÏÚÍÏÖÎÏ ÏÐÒÅÄÅÌÉÔØ ÒÁÂÏÞÉÊ ËÁÔÁÌÏÇ (ÏÛÉÂËÁ: %d)" - serbian "Ne mogu da dobijem trenutni direktorijum (errno: %d)" - slo "Nemô¾em zisti» pracovný adresár (chybový kód: %d)" - spa "No puedo acceder al directorio (Error: %d)" - swe "Kan inte inte läsa aktivt bibliotek. (Felkod: %d)" - ukr "îÅ ÍÏÖÕ ×ÉÚÎÁÞÉÔÉ ÒÏÂÏÞÕ ÔÅËÕ (ÐÏÍÉÌËÁ: %d)" -ER_CANT_LOCK - cze "Nemohu uzamknout soubor (chybov-Bý kód: %d)" - dan "Kan ikke låse fil (Fejlkode: %d)" - nla "Kan de file niet blokeren (Errcode: %d)" - eng "Can't lock file (errno: %d)" - jps "ƒtƒ@ƒCƒ‹‚ðƒƒbƒN‚Å‚«‚Ü‚¹‚ñ (errno: %d)", - est "Ei suuda lukustada faili (veakood: %d)" - fre "Ne peut verrouiller le fichier (Errcode: %d)" - ger "Datei kann nicht gesperrt werden (Fehler: %d)" - greek "Ôï áñ÷åßï äåí ìðïñåß íá êëåéäùèåß (êùäéêüò ëÜèïõò: %d)" - hun "A file nem zarolhato. (hibakod: %d)" - ita "Impossibile il locking il file (errno: %d)" - jpn "¥Õ¥¡¥¤¥ë¤ò¥í¥Ã¥¯¤Ç¤¤Þ¤»¤ó (errno: %d)" - kor "ÈÀÏÀ» Àá±×Áö(lock) ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)" - nor "Kan ikke låse fila (Feilkode: %d)" - norwegian-ny "Kan ikkje låse fila (Feilkode: %d)" - pol "Nie mo¿na zablokowaæ pliku (Kod b³êdu: %d)" - por "Não pode travar o arquivo (erro no. %d)" - rum "Nu pot sa lock fisierul (Eroare: %d)" - rus "îÅ×ÏÚÍÏÖÎÏ ÐÏÓÔÁ×ÉÔØ ÂÌÏËÉÒÏ×ËÕ ÎÁ ÆÁÊÌÅ (ÏÛÉÂËÁ: %d)" - serbian "Ne mogu da zakljuèam file (errno: %d)" - slo "Nemô¾em zamknú» súbor (chybový kód: %d)" - spa "No puedo bloquear archivo: (Error: %d)" - swe "Kan inte låsa filen. (Felkod: %d)" - ukr "îÅ ÍÏÖÕ ÚÁÂÌÏËÕ×ÁÔÉ ÆÁÊÌ (ÐÏÍÉÌËÁ: %d)" -ER_CANT_OPEN_FILE - cze "Nemohu otev-Bøít soubor '%-.200s' (chybový kód: %d)" - dan "Kan ikke åbne fil: '%-.200s' (Fejlkode: %d)" - nla "Kan de file '%-.200s' niet openen (Errcode: %d)" - eng "Can't open file: '%-.200s' (errno: %d)" - jps "'%-.200s' ƒtƒ@ƒCƒ‹‚ðŠJ‚Ž–‚ª‚Å‚«‚Ü‚¹‚ñ (errno: %d)", - est "Ei suuda avada faili '%-.200s' (veakood: %d)" - fre "Ne peut ouvrir le fichier: '%-.200s' (Errcode: %d)" - ger "Kann Datei '%-.200s' nicht öffnen (Fehler: %d)" - greek "Äåí åßíáé äõíáôü íá áíïé÷ôåß ôï áñ÷åßï: '%-.200s' (êùäéêüò ëÜèïõò: %d)" - hun "A '%-.200s' file nem nyithato meg (hibakod: %d)" - ita "Impossibile aprire il file: '%-.200s' (errno: %d)" - jpn "'%-.200s' ¥Õ¥¡¥¤¥ë¤ò³«¤¯»ö¤¬¤Ç¤¤Þ¤»¤ó (errno: %d)" - kor "ÈÀÏÀ» ¿Áö ¸øÇß½À´Ï´Ù.: '%-.200s' (¿¡·¯¹øÈ£: %d)" - nor "Kan ikke åpne fila: '%-.200s' (Feilkode: %d)" - norwegian-ny "Kan ikkje åpne fila: '%-.200s' (Feilkode: %d)" - pol "Nie mo¿na otworzyæ pliku: '%-.200s' (Kod b³êdu: %d)" - por "Não pode abrir o arquivo '%-.200s' (erro no. %d)" - rum "Nu pot sa deschid fisierul: '%-.200s' (Eroare: %d)" - rus "îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÆÁÊÌ: '%-.200s' (ÏÛÉÂËÁ: %d)" - serbian "Ne mogu da otvorim file: '%-.200s' (errno: %d)" - slo "Nemô¾em otvori» súbor: '%-.200s' (chybový kód: %d)" - spa "No puedo abrir archivo: '%-.200s' (Error: %d)" - swe "Kan inte använda '%-.200s' (Felkod: %d)" - ukr "îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÆÁÊÌ: '%-.200s' (ÐÏÍÉÌËÁ: %d)" -ER_FILE_NOT_FOUND - cze "Nemohu naj-Bít soubor '%-.200s' (chybový kód: %d)" - dan "Kan ikke finde fila: '%-.200s' (Fejlkode: %d)" - nla "Kan de file: '%-.200s' niet vinden (Errcode: %d)" - eng "Can't find file: '%-.200s' (errno: %d)" - jps "'%-.200s' ƒtƒ@ƒCƒ‹‚ðŒ©•t‚¯‚鎖‚ª‚Å‚«‚Ü‚¹‚ñ.(errno: %d)", - est "Ei suuda leida faili '%-.200s' (veakood: %d)" - fre "Ne peut trouver le fichier: '%-.200s' (Errcode: %d)" - ger "Kann Datei '%-.200s' nicht finden (Fehler: %d)" - greek "Äåí âñÝèçêå ôï áñ÷åßï: '%-.200s' (êùäéêüò ëÜèïõò: %d)" - hun "A(z) '%-.200s' file nem talalhato (hibakod: %d)" - ita "Impossibile trovare il file: '%-.200s' (errno: %d)" - jpn "'%-.200s' ¥Õ¥¡¥¤¥ë¤ò¸«ÉÕ¤±¤ë»ö¤¬¤Ç¤¤Þ¤»¤ó.(errno: %d)" - kor "ÈÀÏÀ» ãÁö ¸øÇß½À´Ï´Ù.: '%-.200s' (¿¡·¯¹øÈ£: %d)" - nor "Kan ikke finne fila: '%-.200s' (Feilkode: %d)" - norwegian-ny "Kan ikkje finne fila: '%-.200s' (Feilkode: %d)" - pol "Nie mo¿na znale¥æ pliku: '%-.200s' (Kod b³êdu: %d)" - por "Não pode encontrar o arquivo '%-.200s' (erro no. %d)" - rum "Nu pot sa gasesc fisierul: '%-.200s' (Eroare: %d)" - rus "îÅ×ÏÚÍÏÖÎÏ ÎÁÊÔÉ ÆÁÊÌ: '%-.200s' (ÏÛÉÂËÁ: %d)" - serbian "Ne mogu da pronaðem file: '%-.200s' (errno: %d)" - slo "Nemô¾em nájs» súbor: '%-.200s' (chybový kód: %d)" - spa "No puedo encontrar archivo: '%-.200s' (Error: %d)" - swe "Hittar inte filen '%-.200s' (Felkod: %d)" - ukr "îÅ ÍÏÖÕ ÚÎÁÊÔÉ ÆÁÊÌ: '%-.200s' (ÐÏÍÉÌËÁ: %d)" -ER_CANT_READ_DIR - cze "Nemohu -Bèíst adresáø '%-.192s' (chybový kód: %d)" - dan "Kan ikke læse folder '%-.192s' (Fejlkode: %d)" - nla "Kan de directory niet lezen van '%-.192s' (Errcode: %d)" - eng "Can't read dir of '%-.192s' (errno: %d)" - jps "'%-.192s' ƒfƒBƒŒƒNƒgƒŠ‚ª“Ç‚ß‚Ü‚¹‚ñ.(errno: %d)", - est "Ei suuda lugeda kataloogi '%-.192s' (veakood: %d)" - fre "Ne peut lire le répertoire de '%-.192s' (Errcode: %d)" - ger "Verzeichnis von '%-.192s' nicht lesbar (Fehler: %d)" - greek "Äåí åßíáé äõíáôü íá äéáâáóôåß ï öÜêåëëïò ôïõ '%-.192s' (êùäéêüò ëÜèïõò: %d)" - hun "A(z) '%-.192s' konyvtar nem olvashato. (hibakod: %d)" - ita "Impossibile leggere la directory di '%-.192s' (errno: %d)" - jpn "'%-.192s' ¥Ç¥£¥ì¥¯¥È¥ê¤¬Æɤá¤Þ¤»¤ó.(errno: %d)" - kor "'%-.192s'µð·ºÅ丮¸¦ ÀÐÁö ¸øÇß½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)" - nor "Kan ikke lese katalogen '%-.192s' (Feilkode: %d)" - norwegian-ny "Kan ikkje lese katalogen '%-.192s' (Feilkode: %d)" - pol "Nie mo¿na odczytaæ katalogu '%-.192s' (Kod b³êdu: %d)" - por "Não pode ler o diretório de '%-.192s' (erro no. %d)" - rum "Nu pot sa citesc directorul '%-.192s' (Eroare: %d)" - rus "îÅ×ÏÚÍÏÖÎÏ ÐÒÏÞÉÔÁÔØ ËÁÔÁÌÏÇ '%-.192s' (ÏÛÉÂËÁ: %d)" - serbian "Ne mogu da proèitam direktorijum '%-.192s' (errno: %d)" - slo "Nemô¾em èíta» adresár '%-.192s' (chybový kód: %d)" - spa "No puedo leer el directorio de '%-.192s' (Error: %d)" - swe "Kan inte läsa från bibliotek '%-.192s' (Felkod: %d)" - ukr "îÅ ÍÏÖÕ ÐÒÏÞÉÔÁÔÉ ÔÅËÕ '%-.192s' (ÐÏÍÉÌËÁ: %d)" -ER_CANT_SET_WD - cze "Nemohu zm-Bìnit adresáø na '%-.192s' (chybový kód: %d)" - dan "Kan ikke skifte folder til '%-.192s' (Fejlkode: %d)" - nla "Kan de directory niet veranderen naar '%-.192s' (Errcode: %d)" - eng "Can't change dir to '%-.192s' (errno: %d)" - jps "'%-.192s' ƒfƒBƒŒƒNƒgƒŠ‚É chdir ‚Å‚«‚Ü‚¹‚ñ.(errno: %d)", - est "Ei suuda siseneda kataloogi '%-.192s' (veakood: %d)" - fre "Ne peut changer le répertoire pour '%-.192s' (Errcode: %d)" - ger "Kann nicht in das Verzeichnis '%-.192s' wechseln (Fehler: %d)" - greek "Áäýíáôç ç áëëáãÞ ôïõ ôñÝ÷ïíôïò êáôáëüãïõ óå '%-.192s' (êùäéêüò ëÜèïõò: %d)" - hun "Konyvtarvaltas nem lehetseges a(z) '%-.192s'-ba. (hibakod: %d)" - ita "Impossibile cambiare la directory in '%-.192s' (errno: %d)" - jpn "'%-.192s' ¥Ç¥£¥ì¥¯¥È¥ê¤Ë chdir ¤Ç¤¤Þ¤»¤ó.(errno: %d)" - kor "'%-.192s'µð·ºÅ丮·Î À̵¿ÇÒ ¼ö ¾ø¾ú½À´Ï´Ù. (¿¡·¯¹øÈ£: %d)" - nor "Kan ikke skifte katalog til '%-.192s' (Feilkode: %d)" - norwegian-ny "Kan ikkje skifte katalog til '%-.192s' (Feilkode: %d)" - pol "Nie mo¿na zmieniæ katalogu na '%-.192s' (Kod b³êdu: %d)" - por "Não pode mudar para o diretório '%-.192s' (erro no. %d)" - rum "Nu pot sa schimb directorul '%-.192s' (Eroare: %d)" - rus "îÅ×ÏÚÍÏÖÎÏ ÐÅÒÅÊÔÉ × ËÁÔÁÌÏÇ '%-.192s' (ÏÛÉÂËÁ: %d)" - serbian "Ne mogu da promenim direktorijum na '%-.192s' (errno: %d)" - slo "Nemô¾em vojs» do adresára '%-.192s' (chybový kód: %d)" - spa "No puedo cambiar al directorio de '%-.192s' (Error: %d)" - swe "Kan inte byta till '%-.192s' (Felkod: %d)" - ukr "îÅ ÍÏÖÕ ÐÅÒÅÊÔÉ Õ ÔÅËÕ '%-.192s' (ÐÏÍÉÌËÁ: %d)" -ER_CHECKREAD - cze "Z-Báznam byl zmìnìn od posledního ètení v tabulce '%-.192s'" - dan "Posten er ændret siden sidste læsning '%-.192s'" - nla "Record is veranderd sinds de laatste lees activiteit in de tabel '%-.192s'" - eng "Record has changed since last read in table '%-.192s'" - est "Kirje tabelis '%-.192s' on muutunud viimasest lugemisest saadik" - fre "Enregistrement modifié depuis sa dernière lecture dans la table '%-.192s'" - ger "Datensatz hat sich seit dem letzten Zugriff auf Tabelle '%-.192s' geändert" - greek "Ç åããñáöÞ Ý÷åé áëëÜîåé áðü ôçí ôåëåõôáßá öïñÜ ðïõ áíáóýñèçêå áðü ôïí ðßíáêá '%-.192s'" - hun "A(z) '%-.192s' tablaban talalhato rekord megvaltozott az utolso olvasas ota" - ita "Il record e` cambiato dall'ultima lettura della tabella '%-.192s'" - kor "Å×À̺í '%-.192s'¿¡¼ ¸¶Áö¸·À¸·Î ÀÐÀº ÈÄ Record°¡ º¯°æµÇ¾ú½À´Ï´Ù." - nor "Posten har blitt endret siden den ble lest '%-.192s'" - norwegian-ny "Posten har vorte endra sidan den sist vart lesen '%-.192s'" - pol "Rekord zosta³ zmieniony od ostaniego odczytania z tabeli '%-.192s'" - por "Registro alterado desde a última leitura da tabela '%-.192s'" - rum "Cimpul a fost schimbat de la ultima citire a tabelei '%-.192s'" - rus "úÁÐÉÓØ ÉÚÍÅÎÉÌÁÓØ Ó ÍÏÍÅÎÔÁ ÐÏÓÌÅÄÎÅÊ ×ÙÂÏÒËÉ × ÔÁÂÌÉÃÅ '%-.192s'" - serbian "Slog je promenjen od zadnjeg èitanja tabele '%-.192s'" - slo "Záznam bol zmenený od posledného èítania v tabuµke '%-.192s'" - spa "El registro ha cambiado desde la ultima lectura de la tabla '%-.192s'" - swe "Posten har förändrats sedan den lästes i register '%-.192s'" - ukr "úÁÐÉÓ ÂÕÌÏ ÚͦÎÅÎÏ Ú ÞÁÓÕ ÏÓÔÁÎÎØÏÇÏ ÞÉÔÁÎÎÑ Ú ÔÁÂÌÉæ '%-.192s'" -ER_DISK_FULL - cze "Disk je pln-Bý (%s), èekám na uvolnìní nìjakého místa ..." - dan "Ikke mere diskplads (%s). Venter på at få frigjort plads..." - nla "Schijf vol (%s). Aan het wachten totdat er ruimte vrij wordt gemaakt..." - eng "Disk full (%s); waiting for someone to free some space..." - jps "Disk full (%s). ’N‚©‚ª‰½‚©‚ðŒ¸‚ç‚·‚Ü‚Å‚Ü‚Á‚Ä‚‚¾‚³‚¢...", - est "Ketas täis (%s). Ootame kuni tekib vaba ruumi..." - fre "Disque plein (%s). J'attend que quelqu'un libère de l'espace..." - ger "Festplatte voll (%s). Warte, bis jemand Platz schafft ..." - greek "Äåí õðÜñ÷åé ÷þñïò óôï äßóêï (%s). Ðáñáêáëþ, ðåñéìÝíåôå íá åëåõèåñùèåß ÷þñïò..." - hun "A lemez megtelt (%s)." - ita "Disco pieno (%s). In attesa che qualcuno liberi un po' di spazio..." - jpn "Disk full (%s). 狼¤¬²¿¤«¤ò¸º¤é¤¹¤Þ¤Ç¤Þ¤Ã¤Æ¤¯¤À¤µ¤¤..." - kor "Disk full (%s). ´Ù¸¥ »ç¶÷ÀÌ Áö¿ï¶§±îÁö ±â´Ù¸³´Ï´Ù..." - nor "Ikke mer diskplass (%s). Venter på å få frigjort plass..." - norwegian-ny "Ikkje meir diskplass (%s). Ventar på å få frigjort plass..." - pol "Dysk pe³ny (%s). Oczekiwanie na zwolnienie miejsca..." - por "Disco cheio (%s). Aguardando alguém liberar algum espaço..." - rum "Hard-disk-ul este plin (%s). Astept sa se elibereze ceva spatiu..." - rus "äÉÓË ÚÁÐÏÌÎÅÎ. (%s). ïÖÉÄÁÅÍ, ÐÏËÁ ËÔÏ-ÔÏ ÎÅ ÕÂÅÒÅÔ ÐÏÓÌÅ ÓÅÂÑ ÍÕÓÏÒ..." - serbian "Disk je pun (%s). Èekam nekoga da doðe i oslobodi nešto mesta..." - slo "Disk je plný (%s), èakám na uvoµnenie miesta..." - spa "Disco lleno (%s). Esperando para que se libere algo de espacio..." - swe "Disken är full (%s). Väntar tills det finns ledigt utrymme..." - ukr "äÉÓË ÚÁÐÏ×ÎÅÎÉÊ (%s). ÷ÉÞÉËÕÀ, ÄÏËÉ ÚצÌØÎÉÔØÓÑ ÔÒÏÈÉ Í¦ÓÃÑ..." -ER_DUP_KEY 23000 - cze "Nemohu zapsat, zdvojen-Bý klíè v tabulce '%-.192s'" - dan "Kan ikke skrive, flere ens nøgler i tabellen '%-.192s'" - nla "Kan niet schrijven, dubbele zoeksleutel in tabel '%-.192s'" - eng "Can't write; duplicate key in table '%-.192s'" - jps "table '%-.192s' ‚É key ‚ªd•¡‚µ‚Ä‚¢‚Ä‘‚«‚±‚ß‚Ü‚¹‚ñ", - est "Ei saa kirjutada, korduv võti tabelis '%-.192s'" - fre "Ecriture impossible, doublon dans une clé de la table '%-.192s'" - ger "Kann nicht speichern, Grund: doppelter Schlüssel in Tabelle '%-.192s'" - greek "Äåí åßíáé äõíáôÞ ç êáôá÷þñçóç, ç ôéìÞ õðÜñ÷åé Þäç óôïí ðßíáêá '%-.192s'" - hun "Irasi hiba, duplikalt kulcs a '%-.192s' tablaban." - ita "Scrittura impossibile: chiave duplicata nella tabella '%-.192s'" - jpn "table '%-.192s' ¤Ë key ¤¬½ÅÊ£¤·¤Æ¤¤¤Æ½ñ¤¤³¤á¤Þ¤»¤ó" - kor "±â·ÏÇÒ ¼ö ¾øÀ¾´Ï´Ù., Å×À̺í '%-.192s'¿¡¼ Áߺ¹ Å°" - nor "Kan ikke skrive, flere like nøkler i tabellen '%-.192s'" - norwegian-ny "Kan ikkje skrive, flere like nyklar i tabellen '%-.192s'" - pol "Nie mo¿na zapisaæ, powtórzone klucze w tabeli '%-.192s'" - por "Não pode gravar. Chave duplicada na tabela '%-.192s'" - rum "Nu pot sa scriu (can't write), cheie duplicata in tabela '%-.192s'" - rus "îÅ×ÏÚÍÏÖÎÏ ÐÒÏÉÚ×ÅÓÔÉ ÚÁÐÉÓØ, ÄÕÂÌÉÒÕÀÝÉÊÓÑ ËÌÀÞ × ÔÁÂÌÉÃÅ '%-.192s'" - serbian "Ne mogu da pišem pošto postoji duplirani kljuè u tabeli '%-.192s'" - slo "Nemô¾em zapísa», duplikát kµúèa v tabuµke '%-.192s'" - spa "No puedo escribir, clave duplicada en la tabla '%-.192s'" - swe "Kan inte skriva, dubbel söknyckel i register '%-.192s'" - ukr "îÅ ÍÏÖÕ ÚÁÐÉÓÁÔÉ, ÄÕÂÌÀÀÞÉÊÓÑ ËÌÀÞ × ÔÁÂÌÉæ '%-.192s'" -ER_ERROR_ON_CLOSE - cze "Chyba p-Bøi zavírání '%-.192s' (chybový kód: %d)" - dan "Fejl ved lukning af '%-.192s' (Fejlkode: %d)" - nla "Fout bij het sluiten van '%-.192s' (Errcode: %d)" - eng "Error on close of '%-.192s' (errno: %d)" - est "Viga faili '%-.192s' sulgemisel (veakood: %d)" - fre "Erreur a la fermeture de '%-.192s' (Errcode: %d)" - ger "Fehler beim Schließen von '%-.192s' (Fehler: %d)" - greek "ÐáñïõóéÜóôçêå ðñüâëçìá êëåßíïíôáò ôï '%-.192s' (êùäéêüò ëÜèïõò: %d)" - hun "Hiba a(z) '%-.192s' zarasakor. (hibakod: %d)" - ita "Errore durante la chiusura di '%-.192s' (errno: %d)" - kor "'%-.192s'´Ý´Â Áß ¿¡·¯ (¿¡·¯¹øÈ£: %d)" - nor "Feil ved lukking av '%-.192s' (Feilkode: %d)" - norwegian-ny "Feil ved lukking av '%-.192s' (Feilkode: %d)" - pol "B³?d podczas zamykania '%-.192s' (Kod b³êdu: %d)" - por "Erro ao fechar '%-.192s' (erro no. %d)" - rum "Eroare inchizind '%-.192s' (errno: %d)" - rus "ïÛÉÂËÁ ÐÒÉ ÚÁËÒÙÔÉÉ '%-.192s' (ÏÛÉÂËÁ: %d)" - serbian "Greška pri zatvaranju '%-.192s' (errno: %d)" - slo "Chyba pri zatváraní '%-.192s' (chybový kód: %d)" - spa "Error en el cierre de '%-.192s' (Error: %d)" - swe "Fick fel vid stängning av '%-.192s' (Felkod: %d)" - ukr "îÅ ÍÏÖÕ ÚÁËÒÉÔÉ '%-.192s' (ÐÏÍÉÌËÁ: %d)" -ER_ERROR_ON_READ - cze "Chyba p-Bøi ètení souboru '%-.200s' (chybový kód: %d)" - dan "Fejl ved læsning af '%-.200s' (Fejlkode: %d)" - nla "Fout bij het lezen van file '%-.200s' (Errcode: %d)" - eng "Error reading file '%-.200s' (errno: %d)" - jps "'%-.200s' ƒtƒ@ƒCƒ‹‚Ì“Ç‚Ýž‚݃Gƒ‰[ (errno: %d)", - est "Viga faili '%-.200s' lugemisel (veakood: %d)" - fre "Erreur en lecture du fichier '%-.200s' (Errcode: %d)" - ger "Fehler beim Lesen der Datei '%-.200s' (Fehler: %d)" - greek "Ðñüâëçìá êáôÜ ôçí áíÜãíùóç ôïõ áñ÷åßïõ '%-.200s' (êùäéêüò ëÜèïõò: %d)" - hun "Hiba a '%-.200s'file olvasasakor. (hibakod: %d)" - ita "Errore durante la lettura del file '%-.200s' (errno: %d)" - jpn "'%-.200s' ¥Õ¥¡¥¤¥ë¤ÎÆɤ߹þ¤ß¥¨¥é¡¼ (errno: %d)" - kor "'%-.200s'ÈÀÏ Àб⠿¡·¯ (¿¡·¯¹øÈ£: %d)" - nor "Feil ved lesing av '%-.200s' (Feilkode: %d)" - norwegian-ny "Feil ved lesing av '%-.200s' (Feilkode: %d)" - pol "B³?d podczas odczytu pliku '%-.200s' (Kod b³êdu: %d)" - por "Erro ao ler arquivo '%-.200s' (erro no. %d)" - rum "Eroare citind fisierul '%-.200s' (errno: %d)" - rus "ïÛÉÂËÁ ÞÔÅÎÉÑ ÆÁÊÌÁ '%-.200s' (ÏÛÉÂËÁ: %d)" - serbian "Greška pri èitanju file-a '%-.200s' (errno: %d)" - slo "Chyba pri èítaní súboru '%-.200s' (chybový kód: %d)" - spa "Error leyendo el fichero '%-.200s' (Error: %d)" - swe "Fick fel vid läsning av '%-.200s' (Felkod %d)" - ukr "îÅ ÍÏÖÕ ÐÒÏÞÉÔÁÔÉ ÆÁÊÌ '%-.200s' (ÐÏÍÉÌËÁ: %d)" -ER_ERROR_ON_RENAME - cze "Chyba p-Bøi pøejmenování '%-.210s' na '%-.210s' (chybový kód: %d)" - dan "Fejl ved omdøbning af '%-.210s' til '%-.210s' (Fejlkode: %d)" - nla "Fout bij het hernoemen van '%-.210s' naar '%-.210s' (Errcode: %d)" - eng "Error on rename of '%-.210s' to '%-.210s' (errno: %d)" - jps "'%-.210s' ‚ð '%-.210s' ‚É rename ‚Å‚«‚Ü‚¹‚ñ (errno: %d)", - est "Viga faili '%-.210s' ümbernimetamisel '%-.210s'-ks (veakood: %d)" - fre "Erreur en renommant '%-.210s' en '%-.210s' (Errcode: %d)" - ger "Fehler beim Umbenennen von '%-.210s' in '%-.210s' (Fehler: %d)" - greek "Ðñüâëçìá êáôÜ ôçí ìåôïíïìáóßá ôïõ áñ÷åßïõ '%-.210s' to '%-.210s' (êùäéêüò ëÜèïõò: %d)" - hun "Hiba a '%-.210s' file atnevezesekor '%-.210s'. (hibakod: %d)" - ita "Errore durante la rinominazione da '%-.210s' a '%-.210s' (errno: %d)" - jpn "'%-.210s' ¤ò '%-.210s' ¤Ë rename ¤Ç¤¤Þ¤»¤ó (errno: %d)" - kor "'%-.210s'¸¦ '%-.210s'·Î À̸§ º¯°æÁß ¿¡·¯ (¿¡·¯¹øÈ£: %d)" - nor "Feil ved omdøping av '%-.210s' til '%-.210s' (Feilkode: %d)" - norwegian-ny "Feil ved omdøyping av '%-.210s' til '%-.210s' (Feilkode: %d)" - pol "B³?d podczas zmieniania nazwy '%-.210s' na '%-.210s' (Kod b³êdu: %d)" - por "Erro ao renomear '%-.210s' para '%-.210s' (erro no. %d)" - rum "Eroare incercind sa renumesc '%-.210s' in '%-.210s' (errno: %d)" - rus "ïÛÉÂËÁ ÐÒÉ ÐÅÒÅÉÍÅÎÏ×ÁÎÉÉ '%-.210s' × '%-.210s' (ÏÛÉÂËÁ: %d)" - serbian "Greška pri promeni imena '%-.210s' na '%-.210s' (errno: %d)" - slo "Chyba pri premenovávaní '%-.210s' na '%-.210s' (chybový kód: %d)" - spa "Error en el renombrado de '%-.210s' a '%-.210s' (Error: %d)" - swe "Kan inte byta namn från '%-.210s' till '%-.210s' (Felkod: %d)" - ukr "îÅ ÍÏÖÕ ÐÅÒÅÊÍÅÎÕ×ÁÔÉ '%-.210s' Õ '%-.210s' (ÐÏÍÉÌËÁ: %d)" -ER_ERROR_ON_WRITE - cze "Chyba p-Bøi zápisu do souboru '%-.200s' (chybový kód: %d)" - dan "Fejl ved skriving av filen '%-.200s' (Fejlkode: %d)" - nla "Fout bij het wegschrijven van file '%-.200s' (Errcode: %d)" - eng "Error writing file '%-.200s' (errno: %d)" - jps "'%-.200s' ƒtƒ@ƒCƒ‹‚ð‘‚Ž–‚ª‚Å‚«‚Ü‚¹‚ñ (errno: %d)", - est "Viga faili '%-.200s' kirjutamisel (veakood: %d)" - fre "Erreur d'écriture du fichier '%-.200s' (Errcode: %d)" - ger "Fehler beim Speichern der Datei '%-.200s' (Fehler: %d)" - greek "Ðñüâëçìá êáôÜ ôçí áðïèÞêåõóç ôïõ áñ÷åßïõ '%-.200s' (êùäéêüò ëÜèïõò: %d)" - hun "Hiba a '%-.200s' file irasakor. (hibakod: %d)" - ita "Errore durante la scrittura del file '%-.200s' (errno: %d)" - jpn "'%-.200s' ¥Õ¥¡¥¤¥ë¤ò½ñ¤¯»ö¤¬¤Ç¤¤Þ¤»¤ó (errno: %d)" - kor "'%-.200s'ÈÀÏ ±â·Ï Áß ¿¡·¯ (¿¡·¯¹øÈ£: %d)" - nor "Feil ved skriving av fila '%-.200s' (Feilkode: %d)" - norwegian-ny "Feil ved skriving av fila '%-.200s' (Feilkode: %d)" - pol "B³?d podczas zapisywania pliku '%-.200s' (Kod b³êdu: %d)" - por "Erro ao gravar arquivo '%-.200s' (erro no. %d)" - rum "Eroare scriind fisierul '%-.200s' (errno: %d)" - rus "ïÛÉÂËÁ ÚÁÐÉÓÉ × ÆÁÊÌ '%-.200s' (ÏÛÉÂËÁ: %d)" - serbian "Greška pri upisu '%-.200s' (errno: %d)" - slo "Chyba pri zápise do súboru '%-.200s' (chybový kód: %d)" - spa "Error escribiendo el archivo '%-.200s' (Error: %d)" - swe "Fick fel vid skrivning till '%-.200s' (Felkod %d)" - ukr "îÅ ÍÏÖÕ ÚÁÐÉÓÁÔÉ ÆÁÊÌ '%-.200s' (ÐÏÍÉÌËÁ: %d)" -ER_FILE_USED - cze "'%-.192s' je zam-Bèen proti zmìnám" - dan "'%-.192s' er låst mod opdateringer" - nla "'%-.192s' is geblokeerd tegen veranderingen" - eng "'%-.192s' is locked against change" - jps "'%-.192s' ‚̓ƒbƒN‚³‚ê‚Ä‚¢‚Ü‚·", - est "'%-.192s' on lukustatud muudatuste vastu" - fre "'%-.192s' est verrouillé contre les modifications" - ger "'%-.192s' ist für Änderungen gesperrt" - greek "'%-.192s' äåí åðéôñÝðïíôáé áëëáãÝò" - hun "'%-.192s' a valtoztatas ellen zarolva" - ita "'%-.192s' e` soggetto a lock contro i cambiamenti" - jpn "'%-.192s' ¤Ï¥í¥Ã¥¯¤µ¤ì¤Æ¤¤¤Þ¤¹" - kor "'%-.192s'°¡ º¯°æÇÒ ¼ö ¾øµµ·Ï Àá°ÜÀÖÀ¾´Ï´Ù." - nor "'%-.192s' er låst mot oppdateringer" - norwegian-ny "'%-.192s' er låst mot oppdateringar" - pol "'%-.192s' jest zablokowany na wypadek zmian" - por "'%-.192s' está com travamento contra alterações" - rum "'%-.192s' este blocat pentry schimbari (loccked against change)" - rus "'%-.192s' ÚÁÂÌÏËÉÒÏ×ÁÎ ÄÌÑ ÉÚÍÅÎÅÎÉÊ" - serbian "'%-.192s' je zakljuèan za upis" - slo "'%-.192s' je zamknutý proti zmenám" - spa "'%-.192s' esta bloqueado contra cambios" - swe "'%-.192s' är låst mot användning" - ukr "'%-.192s' ÚÁÂÌÏËÏ×ÁÎÉÊ ÎÁ ×ÎÅÓÅÎÎÑ ÚͦÎ" -ER_FILSORT_ABORT - cze "T-Bøídìní pøeru¹eno" - dan "Sortering afbrudt" - nla "Sorteren afgebroken" - eng "Sort aborted" - jps "Sort ’†’f", - est "Sorteerimine katkestatud" - fre "Tri alphabétique abandonné" - ger "Sortiervorgang abgebrochen" - greek "Ç äéáäéêáóßá ôáîéíüìéóçò áêõñþèçêå" - hun "Sikertelen rendezes" - ita "Operazione di ordinamento abbandonata" - jpn "Sort ÃæÃÇ" - kor "¼ÒÆ®°¡ ÁߴܵǾú½À´Ï´Ù." - nor "Sortering avbrutt" - norwegian-ny "Sortering avbrote" - pol "Sortowanie przerwane" - por "Ordenação abortada" - rum "Sortare intrerupta" - rus "óÏÒÔÉÒÏ×ËÁ ÐÒÅÒ×ÁÎÁ" - serbian "Sortiranje je prekinuto" - slo "Triedenie preru¹ené" - spa "Ordeancion cancelada" - swe "Sorteringen avbruten" - ukr "óÏÒÔÕ×ÁÎÎÑ ÐÅÒÅÒ×ÁÎÏ" -ER_FORM_NOT_FOUND - cze "Pohled '%-.192s' pro '%-.192s' neexistuje" - dan "View '%-.192s' eksisterer ikke for '%-.192s'" - nla "View '%-.192s' bestaat niet voor '%-.192s'" - eng "View '%-.192s' doesn't exist for '%-.192s'" - jps "View '%-.192s' ‚ª '%-.192s' ‚É’è‹`‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ", - est "Vaade '%-.192s' ei eksisteeri '%-.192s' jaoks" - fre "La vue (View) '%-.192s' n'existe pas pour '%-.192s'" - ger "View '%-.192s' existiert für '%-.192s' nicht" - greek "Ôï View '%-.192s' äåí õðÜñ÷åé ãéá '%-.192s'" - hun "A(z) '%-.192s' nezet nem letezik a(z) '%-.192s'-hoz" - ita "La view '%-.192s' non esiste per '%-.192s'" - jpn "View '%-.192s' ¤¬ '%-.192s' ¤ËÄêµÁ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" - kor "ºä '%-.192s'°¡ '%-.192s'¿¡¼´Â Á¸ÀçÇÏÁö ¾ÊÀ¾´Ï´Ù." - nor "View '%-.192s' eksisterer ikke for '%-.192s'" - norwegian-ny "View '%-.192s' eksisterar ikkje for '%-.192s'" - pol "Widok '%-.192s' nie istnieje dla '%-.192s'" - por "Visão '%-.192s' não existe para '%-.192s'" - rum "View '%-.192s' nu exista pentru '%-.192s'" - rus "ðÒÅÄÓÔÁ×ÌÅÎÉÅ '%-.192s' ÎÅ ÓÕÝÅÓÔ×ÕÅÔ ÄÌÑ '%-.192s'" - serbian "View '%-.192s' ne postoji za '%-.192s'" - slo "Pohµad '%-.192s' neexistuje pre '%-.192s'" - spa "La vista '%-.192s' no existe para '%-.192s'" - swe "Formulär '%-.192s' finns inte i '%-.192s'" - ukr "÷ÉÇÌÑÄ '%-.192s' ÎÅ ¦ÓÎÕ¤ ÄÌÑ '%-.192s'" -ER_GET_ERRNO - cze "Obsluha tabulky vr-Bátila chybu %d" - dan "Modtog fejl %d fra tabel håndteringen" - nla "Fout %d van tabel handler" - eng "Got error %d from storage engine" - est "Tabeli handler tagastas vea %d" - fre "Reçu l'erreur %d du handler de la table" - ger "Fehler %d (Speicher-Engine)" - greek "ÅëÞöèç ìÞíõìá ëÜèïõò %d áðü ôïí ÷åéñéóôÞ ðßíáêá (table handler)" - hun "%d hibajelzes a tablakezelotol" - ita "Rilevato l'errore %d dal gestore delle tabelle" - jpn "Got error %d from table handler" - kor "Å×À̺í handler¿¡¼ %d ¿¡·¯°¡ ¹ß»ý ÇÏ¿´½À´Ï´Ù." - nor "Mottok feil %d fra tabell håndterer" - norwegian-ny "Mottok feil %d fra tabell handterar" - pol "Otrzymano b³?d %d z obs³ugi tabeli" - por "Obteve erro %d no manipulador de tabelas" - rum "Eroarea %d obtinuta din handlerul tabelei" - rus "ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ %d ÏÔ ÏÂÒÁÂÏÔÞÉËÁ ÔÁÂÌÉÃ" - serbian "Handler tabela je vratio grešku %d" - slo "Obsluha tabuµky vrátila chybu %d" - spa "Error %d desde el manejador de la tabla" - swe "Fick felkod %d från databashanteraren" - ukr "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d ×¦Ä ÄÅÓËÒÉÐÔÏÒÁ ÔÁÂÌÉæ" -ER_ILLEGAL_HA - cze "Obsluha tabulky '%-.192s' nem-Bá tento parametr" - dan "Denne mulighed eksisterer ikke for tabeltypen '%-.192s'" - nla "Tabel handler voor '%-.192s' heeft deze optie niet" - eng "Table storage engine for '%-.192s' doesn't have this option" - est "Tabeli '%-.192s' handler ei toeta antud operatsiooni" - fre "Le handler de la table '%-.192s' n'a pas cette option" - ger "Diese Option gibt es nicht (Speicher-Engine für '%-.192s')" - greek "Ï ÷åéñéóôÞò ðßíáêá (table handler) ãéá '%-.192s' äåí äéáèÝôåé áõôÞ ôçí åðéëïãÞ" - hun "A(z) '%-.192s' tablakezelonek nincs ilyen opcioja" - ita "Il gestore delle tabelle per '%-.192s' non ha questa opzione" - jpn "Table handler for '%-.192s' doesn't have this option" - kor "'%-.192s'ÀÇ Å×À̺í handler´Â ÀÌ·¯ÇÑ ¿É¼ÇÀ» Á¦°øÇÏÁö ¾ÊÀ¾´Ï´Ù." - nor "Tabell håndtereren for '%-.192s' har ikke denne muligheten" - norwegian-ny "Tabell håndteraren for '%-.192s' har ikkje denne moglegheita" - pol "Obs³uga tabeli '%-.192s' nie posiada tej opcji" - por "Manipulador de tabela para '%-.192s' não tem esta opção" - rum "Handlerul tabelei pentru '%-.192s' nu are aceasta optiune" - rus "ïÂÒÁÂÏÔÞÉË ÔÁÂÌÉÃÙ '%-.192s' ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ÜÔÕ ×ÏÚÍÏÖÎÏÓÔØ" - serbian "Handler tabela za '%-.192s' nema ovu opciju" - slo "Obsluha tabuµky '%-.192s' nemá tento parameter" - spa "El manejador de la tabla de '%-.192s' no tiene esta opcion" - swe "Tabellhanteraren for tabell '%-.192s' stödjer ej detta" - ukr "äÅÓËÒÉÐÔÏÒ ÔÁÂÌÉæ '%-.192s' ÎÅ ÍÁ¤ 椧 ×ÌÁÓÔÉ×ÏÓÔ¦" -ER_KEY_NOT_FOUND - cze "Nemohu naj-Bít záznam v '%-.192s'" - dan "Kan ikke finde posten i '%-.192s'" - nla "Kan record niet vinden in '%-.192s'" - eng "Can't find record in '%-.192s'" - jps "'%-.192s'‚Ì‚È‚©‚ɃŒƒR[ƒh‚ªŒ©•t‚©‚è‚Ü‚¹‚ñ", - est "Ei suuda leida kirjet '%-.192s'-s" - fre "Ne peut trouver l'enregistrement dans '%-.192s'" - ger "Kann Datensatz in '%-.192s' nicht finden" - greek "Áäýíáôç ç áíåýñåóç åããñáöÞò óôï '%-.192s'" - hun "Nem talalhato a rekord '%-.192s'-ben" - ita "Impossibile trovare il record in '%-.192s'" - jpn "'%-.192s'¤Î¤Ê¤«¤Ë¥ì¥³¡¼¥É¤¬¸«ÉÕ¤«¤ê¤Þ¤»¤ó" - kor "'%-.192s'¿¡¼ ·¹Äڵ带 ãÀ» ¼ö ¾øÀ¾´Ï´Ù." - nor "Kan ikke finne posten i '%-.192s'" - norwegian-ny "Kan ikkje finne posten i '%-.192s'" - pol "Nie mo¿na znale¥æ rekordu w '%-.192s'" - por "Não pode encontrar registro em '%-.192s'" - rum "Nu pot sa gasesc recordul in '%-.192s'" - rus "îÅ×ÏÚÍÏÖÎÏ ÎÁÊÔÉ ÚÁÐÉÓØ × '%-.192s'" - serbian "Ne mogu da pronaðem slog u '%-.192s'" - slo "Nemô¾em nájs» záznam v '%-.192s'" - spa "No puedo encontrar el registro en '%-.192s'" - swe "Hittar inte posten '%-.192s'" - ukr "îÅ ÍÏÖÕ ÚÁÐÉÓÁÔÉ Õ '%-.192s'" -ER_NOT_FORM_FILE - cze "Nespr-Bávná informace v souboru '%-.200s'" - dan "Forkert indhold i: '%-.200s'" - nla "Verkeerde info in file: '%-.200s'" - eng "Incorrect information in file: '%-.200s'" - jps "ƒtƒ@ƒCƒ‹ '%-.200s' ‚Ì info ‚ªŠÔˆá‚Á‚Ä‚¢‚é‚悤‚Å‚·", - est "Vigane informatsioon failis '%-.200s'" - fre "Information erronnée dans le fichier: '%-.200s'" - ger "Falsche Information in Datei '%-.200s'" - greek "ËÜèïò ðëçñïöïñßåò óôï áñ÷åßï: '%-.200s'" - hun "Ervenytelen info a file-ban: '%-.200s'" - ita "Informazione errata nel file: '%-.200s'" - jpn "¥Õ¥¡¥¤¥ë '%-.200s' ¤Î info ¤¬´Ö°ã¤Ã¤Æ¤¤¤ë¤è¤¦¤Ç¤¹" - kor "ÈÀÏÀÇ ºÎÁ¤È®ÇÑ Á¤º¸: '%-.200s'" - nor "Feil informasjon i filen: '%-.200s'" - norwegian-ny "Feil informasjon i fila: '%-.200s'" - pol "Niew³a?ciwa informacja w pliku: '%-.200s'" - por "Informação incorreta no arquivo '%-.200s'" - rum "Informatie incorecta in fisierul: '%-.200s'" - rus "îÅËÏÒÒÅËÔÎÁÑ ÉÎÆÏÒÍÁÃÉÑ × ÆÁÊÌÅ '%-.200s'" - serbian "Pogrešna informacija u file-u: '%-.200s'" - slo "Nesprávna informácia v súbore: '%-.200s'" - spa "Informacion erronea en el archivo: '%-.200s'" - swe "Felaktig fil: '%-.200s'" - ukr "èÉÂÎÁ ¦ÎÆÏÒÍÁÃ¦Ñ Õ ÆÁÊ̦: '%-.200s'" -ER_NOT_KEYFILE - cze "Nespr-Bávný klíè pro tabulku '%-.200s'; pokuste se ho opravit" - dan "Fejl i indeksfilen til tabellen '%-.200s'; prøv at reparere den" - nla "Verkeerde zoeksleutel file voor tabel: '%-.200s'; probeer het te repareren" - eng "Incorrect key file for table '%-.200s'; try to repair it" - jps "'%-.200s' ƒe[ƒuƒ‹‚Ì key file ‚ªŠÔˆá‚Á‚Ä‚¢‚é‚悤‚Å‚·. C•œ‚ð‚µ‚Ä‚‚¾‚³‚¢", - est "Tabeli '%-.200s' võtmefail on vigane; proovi seda parandada" - fre "Index corrompu dans la table: '%-.200s'; essayez de le réparer" - ger "Fehlerhafte Index-Datei für Tabelle '%-.200s'; versuche zu reparieren" - greek "ËÜèïò áñ÷åßï ôáîéíüìéóçò (key file) ãéá ôïí ðßíáêá: '%-.200s'; Ðáñáêáëþ, äéïñèþóôå ôï!" - hun "Ervenytelen kulcsfile a tablahoz: '%-.200s'; probalja kijavitani!" - ita "File chiave errato per la tabella : '%-.200s'; prova a riparalo" - jpn "'%-.200s' ¥Æ¡¼¥Ö¥ë¤Î key file ¤¬´Ö°ã¤Ã¤Æ¤¤¤ë¤è¤¦¤Ç¤¹. ½¤Éü¤ò¤·¤Æ¤¯¤À¤µ¤¤" - kor "'%-.200s' Å×À̺íÀÇ ºÎÁ¤È®ÇÑ Å° Á¸Àç. ¼öÁ¤ÇϽÿÀ!" - nor "Tabellen '%-.200s' har feil i nøkkelfilen; forsøk å reparer den" - norwegian-ny "Tabellen '%-.200s' har feil i nykkelfila; prøv å reparere den" - pol "Niew³a?ciwy plik kluczy dla tabeli: '%-.200s'; spróbuj go naprawiæ" - por "Arquivo de índice incorreto para tabela '%-.200s'; tente repará-lo" - rum "Cheia fisierului incorecta pentru tabela: '%-.200s'; incearca s-o repari" - rus "îÅËÏÒÒÅËÔÎÙÊ ÉÎÄÅËÓÎÙÊ ÆÁÊÌ ÄÌÑ ÔÁÂÌÉÃÙ: '%-.200s'. ðÏÐÒÏÂÕÊÔÅ ×ÏÓÓÔÁÎÏ×ÉÔØ ÅÇÏ" - serbian "Pogrešan key file za tabelu: '%-.200s'; probajte da ga ispravite" - slo "Nesprávny kµúè pre tabuµku '%-.200s'; pokúste sa ho opravi»" - spa "Clave de archivo erronea para la tabla: '%-.200s'; intente repararlo" - swe "Fatalt fel vid hantering av register '%-.200s'; kör en reparation" - ukr "èÉÂÎÉÊ ÆÁÊÌ ËÌÀÞÅÊ ÄÌÑ ÔÁÂÌÉæ: '%-.200s'; óÐÒÏÂÕÊÔÅ ÊÏÇÏ ×¦ÄÎÏ×ÉÔÉ" -ER_OLD_KEYFILE - cze "Star-Bý klíèový soubor pro '%-.192s'; opravte ho." - dan "Gammel indeksfil for tabellen '%-.192s'; reparer den" - nla "Oude zoeksleutel file voor tabel '%-.192s'; repareer het!" - eng "Old key file for table '%-.192s'; repair it!" - jps "'%-.192s' ƒe[ƒuƒ‹‚͌¢Œ`Ž®‚Ì key file ‚̂悤‚Å‚·; C•œ‚ð‚µ‚Ä‚‚¾‚³‚¢", - est "Tabeli '%-.192s' võtmefail on aegunud; paranda see!" - fre "Vieux fichier d'index pour la table '%-.192s'; réparez le!" - ger "Alte Index-Datei für Tabelle '%-.192s'. Bitte reparieren" - greek "Ðáëáéü áñ÷åßï ôáîéíüìéóçò (key file) ãéá ôïí ðßíáêá '%-.192s'; Ðáñáêáëþ, äéïñèþóôå ôï!" - hun "Regi kulcsfile a '%-.192s'tablahoz; probalja kijavitani!" - ita "File chiave vecchio per la tabella '%-.192s'; riparalo!" - jpn "'%-.192s' ¥Æ¡¼¥Ö¥ë¤Ï¸Å¤¤·Á¼°¤Î key file ¤Î¤è¤¦¤Ç¤¹; ½¤Éü¤ò¤·¤Æ¤¯¤À¤µ¤¤" - kor "'%-.192s' Å×À̺íÀÇ ÀÌÀü¹öÁ¯ÀÇ Å° Á¸Àç. ¼öÁ¤ÇϽÿÀ!" - nor "Gammel nøkkelfil for tabellen '%-.192s'; reparer den!" - norwegian-ny "Gammel nykkelfil for tabellen '%-.192s'; reparer den!" - pol "Plik kluczy dla tabeli '%-.192s' jest starego typu; napraw go!" - por "Arquivo de índice desatualizado para tabela '%-.192s'; repare-o!" - rum "Cheia fisierului e veche pentru tabela '%-.192s'; repar-o!" - rus "óÔÁÒÙÊ ÉÎÄÅËÓÎÙÊ ÆÁÊÌ ÄÌÑ ÔÁÂÌÉÃÙ '%-.192s'; ÏÔÒÅÍÏÎÔÉÒÕÊÔÅ ÅÇÏ!" - serbian "Zastareo key file za tabelu '%-.192s'; ispravite ga" - slo "Starý kµúèový súbor pre '%-.192s'; opravte ho!" - spa "Clave de archivo antigua para la tabla '%-.192s'; reparelo!" - swe "Gammal nyckelfil '%-.192s'; reparera registret" - ukr "óÔÁÒÉÊ ÆÁÊÌ ËÌÀÞÅÊ ÄÌÑ ÔÁÂÌÉæ '%-.192s'; ÷¦ÄÎÏצÔØ ÊÏÇÏ!" -ER_OPEN_AS_READONLY - cze "'%-.192s' je jen pro -Bètení" - dan "'%-.192s' er skrivebeskyttet" - nla "'%-.192s' is alleen leesbaar" - eng "Table '%-.192s' is read only" - jps "'%-.192s' ‚Í“Ç‚Ýž‚Ýê—p‚Å‚·", - est "Tabel '%-.192s' on ainult lugemiseks" - fre "'%-.192s' est en lecture seulement" - ger "Tabelle '%-.192s' ist nur lesbar" - greek "'%-.192s' åðéôñÝðåôáé ìüíï ç áíÜãíùóç" - hun "'%-.192s' irasvedett" - ita "'%-.192s' e` di sola lettura" - jpn "'%-.192s' ¤ÏÆɤ߹þ¤ßÀìÍѤǤ¹" - kor "Å×À̺í '%-.192s'´Â ÀбâÀü¿ë ÀÔ´Ï´Ù." - nor "'%-.192s' er skrivebeskyttet" - norwegian-ny "'%-.192s' er skrivetryggja" - pol "'%-.192s' jest tylko do odczytu" - por "Tabela '%-.192s' é somente para leitura" - rum "Tabela '%-.192s' e read-only" - rus "ôÁÂÌÉÃÁ '%-.192s' ÐÒÅÄÎÁÚÎÁÞÅÎÁ ÔÏÌØËÏ ÄÌÑ ÞÔÅÎÉÑ" - serbian "Tabelu '%-.192s' je dozvoljeno samo èitati" - slo "'%-.192s' is èíta» only" - spa "'%-.192s' es de solo lectura" - swe "'%-.192s' är skyddad mot förändring" - ukr "ôÁÂÌÉÃÑ '%-.192s' Ô¦ÌØËÉ ÄÌÑ ÞÉÔÁÎÎÑ" -ER_OUTOFMEMORY HY001 S1001 - cze "M-Bálo pamìti. Pøestartujte daemona a zkuste znovu (je potøeba %d bytù)" - dan "Ikke mere hukommelse. Genstart serveren og prøv igen (mangler %d bytes)" - nla "Geen geheugen meer. Herstart server en probeer opnieuw (%d bytes nodig)" - eng "Out of memory; restart server and try again (needed %d bytes)" - jps "Out of memory. ƒf[ƒ‚ƒ“‚ðƒŠƒXƒ^[ƒg‚µ‚Ä‚Ý‚Ä‚‚¾‚³‚¢ (%d bytes •K—v)", - est "Mälu sai otsa. Proovi MySQL uuesti käivitada (puudu jäi %d baiti)" - fre "Manque de mémoire. Redémarrez le démon et ré-essayez (%d octets nécessaires)" - ger "Kein Speicher vorhanden (%d Bytes benötigt). Bitte Server neu starten" - greek "Äåí õðÜñ÷åé äéáèÝóéìç ìíÞìç. ÐñïóðáèÞóôå ðÜëé, åðáíåêéíþíôáò ôç äéáäéêáóßá (demon) (÷ñåéÜæïíôáé %d bytes)" - hun "Nincs eleg memoria. Inditsa ujra a demont, es probalja ismet. (%d byte szukseges.)" - ita "Memoria esaurita. Fai ripartire il demone e riprova (richiesti %d bytes)" - jpn "Out of memory. ¥Ç¡¼¥â¥ó¤ò¥ê¥¹¥¿¡¼¥È¤·¤Æ¤ß¤Æ¤¯¤À¤µ¤¤ (%d bytes ɬÍ×)" - kor "Out of memory. µ¥¸óÀ» Àç ½ÇÇà ÈÄ ´Ù½Ã ½ÃÀÛÇϽÿÀ (needed %d bytes)" - nor "Ikke mer minne. Star på nytt tjenesten og prøv igjen (trengte %d byter)" - norwegian-ny "Ikkje meir minne. Start på nytt tenesten og prøv igjen (trengte %d bytar)" - pol "Zbyt ma³o pamiêci. Uruchom ponownie demona i spróbuj ponownie (potrzeba %d bajtów)" - por "Sem memória. Reinicie o programa e tente novamente (necessita de %d bytes)" - rum "Out of memory. Porneste daemon-ul din nou si incearca inca o data (e nevoie de %d bytes)" - rus "îÅÄÏÓÔÁÔÏÞÎÏ ÐÁÍÑÔÉ. ðÅÒÅÚÁÐÕÓÔÉÔÅ ÓÅÒ×ÅÒ É ÐÏÐÒÏÂÕÊÔÅ ÅÝÅ ÒÁÚ (ÎÕÖÎÏ %d ÂÁÊÔ)" - serbian "Nema memorije. Restartujte MySQL server i probajte ponovo (potrebno je %d byte-ova)" - slo "Málo pamäti. Re¹tartujte daemona a skúste znova (je potrebných %d bytov)" - spa "Memoria insuficiente. Reinicie el demonio e intentelo otra vez (necesita %d bytes)" - swe "Oväntat slut på minnet, starta om programmet och försök på nytt (Behövde %d bytes)" - ukr "âÒÁË ÐÁÍ'ÑÔ¦. òÅÓÔÁÒÔÕÊÔÅ ÓÅÒ×ÅÒ ÔÁ ÓÐÒÏÂÕÊÔÅ ÚÎÏ×Õ (ÐÏÔÒ¦ÂÎÏ %d ÂÁÊÔ¦×)" -ER_OUT_OF_SORTMEMORY HY001 S1001 - cze "M-Bálo pamìti pro tøídìní. Zvy¹te velikost tøídícího bufferu" - dan "Ikke mere sorteringshukommelse. Øg sorteringshukommelse (sort buffer size) for serveren" - nla "Geen geheugen om te sorteren. Verhoog de server sort buffer size" - eng "Out of sort memory; increase server sort buffer size" - jps "Out of sort memory. sort buffer size ‚ª‘«‚è‚È‚¢‚悤‚Å‚·.", - est "Mälu sai sorteerimisel otsa. Suurenda MySQL-i sorteerimispuhvrit" - fre "Manque de mémoire pour le tri. Augmentez-la." - ger "Kein Speicher zum Sortieren vorhanden. sort_buffer_size sollte im Server erhöht werden" - greek "Äåí õðÜñ÷åé äéáèÝóéìç ìíÞìç ãéá ôáîéíüìéóç. ÁõîÞóôå ôï sort buffer size ãéá ôç äéáäéêáóßá (demon)" - hun "Nincs eleg memoria a rendezeshez. Novelje a rendezo demon puffermeretet" - ita "Memoria per gli ordinamenti esaurita. Incrementare il 'sort_buffer' al demone" - jpn "Out of sort memory. sort buffer size ¤¬Â¤ê¤Ê¤¤¤è¤¦¤Ç¤¹." - kor "Out of sort memory. daemon sort bufferÀÇ Å©±â¸¦ Áõ°¡½ÃÅ°¼¼¿ä" - nor "Ikke mer sorteringsminne. Øk sorteringsminnet (sort buffer size) for tjenesten" - norwegian-ny "Ikkje meir sorteringsminne. Auk sorteringsminnet (sorteringsbffer storleik) for tenesten" - pol "Zbyt ma³o pamiêci dla sortowania. Zwiêksz wielko?æ bufora demona dla sortowania" - por "Sem memória para ordenação. Aumente tamanho do 'buffer' de ordenação" - rum "Out of memory pentru sortare. Largeste marimea buffer-ului pentru sortare in daemon (sort buffer size)" - rus "îÅÄÏÓÔÁÔÏÞÎÏ ÐÁÍÑÔÉ ÄÌÑ ÓÏÒÔÉÒÏ×ËÉ. õ×ÅÌÉÞØÔÅ ÒÁÚÍÅÒ ÂÕÆÅÒÁ ÓÏÒÔÉÒÏ×ËÉ ÎÁ ÓÅÒ×ÅÒÅ" - serbian "Nema memorije za sortiranje. Poveæajte velièinu sort buffer-a MySQL server-u" - slo "Málo pamäti pre triedenie, zvý¹te veµkos» triediaceho bufferu" - spa "Memoria de ordenacion insuficiente. Incremente el tamano del buffer de ordenacion" - swe "Sorteringsbufferten räcker inte till. Kontrollera startparametrarna" - ukr "âÒÁË ÐÁÍ'ÑÔ¦ ÄÌÑ ÓÏÒÔÕ×ÁÎÎÑ. ôÒÅÂÁ Ú¦ÌØÛÉÔÉ ÒÏÚÍ¦Ò ÂÕÆÅÒÁ ÓÏÒÔÕ×ÁÎÎÑ Õ ÓÅÒ×ÅÒÁ" -ER_UNEXPECTED_EOF - cze "Neo-Bèekávaný konec souboru pøi ètení '%-.192s' (chybový kód: %d)" - dan "Uventet afslutning på fil (eof) ved læsning af filen '%-.192s' (Fejlkode: %d)" - nla "Onverwachte eof gevonden tijdens het lezen van file '%-.192s' (Errcode: %d)" - eng "Unexpected EOF found when reading file '%-.192s' (errno: %d)" - jps "'%-.192s' ƒtƒ@ƒCƒ‹‚ð“Ç‚Ýž‚Ý’†‚É EOF ‚ª—\Šú‚¹‚ÊŠ‚ÅŒ»‚ê‚Ü‚µ‚½. (errno: %d)", - est "Ootamatu faililõpumärgend faili '%-.192s' lugemisel (veakood: %d)" - fre "Fin de fichier inattendue en lisant '%-.192s' (Errcode: %d)" - ger "Unerwartetes Ende beim Lesen der Datei '%-.192s' (Fehler: %d)" - greek "ÊáôÜ ôç äéÜñêåéá ôçò áíÜãíùóçò, âñÝèçêå áðñïóäüêçôá ôï ôÝëïò ôïõ áñ÷åßïõ '%-.192s' (êùäéêüò ëÜèïõò: %d)" - hun "Varatlan filevege-jel a '%-.192s'olvasasakor. (hibakod: %d)" - ita "Fine del file inaspettata durante la lettura del file '%-.192s' (errno: %d)" - jpn "'%-.192s' ¥Õ¥¡¥¤¥ë¤òÆɤ߹þ¤ßÃæ¤Ë EOF ¤¬Í½´ü¤»¤Ì½ê¤Ç¸½¤ì¤Þ¤·¤¿. (errno: %d)" - kor "'%-.192s' ÈÀÏÀ» Àд µµÁß À߸øµÈ eofÀ» ¹ß°ß (¿¡·¯¹øÈ£: %d)" - nor "Uventet slutt på fil (eof) ved lesing av filen '%-.192s' (Feilkode: %d)" - norwegian-ny "Uventa slutt på fil (eof) ved lesing av fila '%-.192s' (Feilkode: %d)" - pol "Nieoczekiwany 'eof' napotkany podczas czytania z pliku '%-.192s' (Kod b³êdu: %d)" - por "Encontrado fim de arquivo inesperado ao ler arquivo '%-.192s' (erro no. %d)" - rum "Sfirsit de fisier neasteptat in citirea fisierului '%-.192s' (errno: %d)" - rus "îÅÏÖÉÄÁÎÎÙÊ ËÏÎÅà ÆÁÊÌÁ '%-.192s' (ÏÛÉÂËÁ: %d)" - serbian "Neoèekivani kraj pri èitanju file-a '%-.192s' (errno: %d)" - slo "Neoèakávaný koniec súboru pri èítaní '%-.192s' (chybový kód: %d)" - spa "Inesperado fin de ficheroU mientras leiamos el archivo '%-.192s' (Error: %d)" - swe "Oväntat filslut vid läsning från '%-.192s' (Felkod: %d)" - ukr "èÉÂÎÉÊ Ë¦ÎÅÃØ ÆÁÊÌÕ '%-.192s' (ÐÏÍÉÌËÁ: %d)" -ER_CON_COUNT_ERROR 08004 - cze "P-Bøíli¹ mnoho spojení" - dan "For mange forbindelser (connections)" - nla "Te veel verbindingen" - eng "Too many connections" - jps "Ú‘±‚ª‘½‚·‚¬‚Ü‚·", - est "Liiga palju samaaegseid ühendusi" - fre "Trop de connexions" - ger "Zu viele Verbindungen" - greek "ÕðÜñ÷ïõí ðïëëÝò óõíäÝóåéò..." - hun "Tul sok kapcsolat" - ita "Troppe connessioni" - jpn "Àܳ¤¬Â¿¤¹¤®¤Þ¤¹" - kor "³Ê¹« ¸¹Àº ¿¬°á... max_connectionÀ» Áõ°¡ ½ÃÅ°½Ã¿À..." - nor "For mange tilkoblinger (connections)" - norwegian-ny "For mange tilkoplingar (connections)" - pol "Zbyt wiele po³?czeñ" - por "Excesso de conexões" - rum "Prea multe conectiuni" - rus "óÌÉÛËÏÍ ÍÎÏÇÏ ÓÏÅÄÉÎÅÎÉÊ" - serbian "Previše konekcija" - slo "Príli¹ mnoho spojení" - spa "Demasiadas conexiones" - swe "För många anslutningar" - ukr "úÁÂÁÇÁÔÏ Ú'¤ÄÎÁÎØ" -ER_OUT_OF_RESOURCES - cze "M-Bálo prostoru/pamìti pro thread" - dan "Udgået for tråde/hukommelse" - nla "Geen thread geheugen meer; controleer of mysqld of andere processen al het beschikbare geheugen gebruikt. Zo niet, dan moet u wellicht 'ulimit' gebruiken om mysqld toe te laten meer geheugen te benutten, of u kunt extra swap ruimte toevoegen" - eng "Out of memory; check if mysqld or some other process uses all available memory; if not, you may have to use 'ulimit' to allow mysqld to use more memory or you can add more swap space" - jps "Out of memory; mysqld ‚©‚»‚Ì‘¼‚̃vƒƒZƒX‚ªƒƒ‚ƒŠ[‚ð‘S‚ÄŽg‚Á‚Ä‚¢‚é‚©Šm”F‚µ‚Ä‚‚¾‚³‚¢. ƒƒ‚ƒŠ[‚ðŽg‚¢Ø‚Á‚Ä‚¢‚È‚¢ê‡A'ulimit' ‚ðݒ肵‚Ä mysqld ‚̃ƒ‚ƒŠ[Žg—pŒÀŠE—ʂ𑽂‚·‚é‚©Aswap space ‚ð‘‚₵‚Ä‚Ý‚Ä‚‚¾‚³‚¢", - est "Mälu sai otsa. Võimalik, et aitab swap-i lisamine või käsu 'ulimit' abil MySQL-le rohkema mälu kasutamise lubamine" - fre "Manque de 'threads'/mémoire" - ger "Kein Speicher mehr vorhanden. Prüfen Sie, ob mysqld oder ein anderer Prozess den gesamten Speicher verbraucht. Wenn nicht, sollten Sie mit 'ulimit' dafür sorgen, dass mysqld mehr Speicher benutzen darf, oder mehr Swap-Speicher einrichten" - greek "Ðñüâëçìá ìå ôç äéáèÝóéìç ìíÞìç (Out of thread space/memory)" - hun "Elfogyott a thread-memoria" - ita "Fine dello spazio/memoria per i thread" - jpn "Out of memory; mysqld ¤«¤½¤Î¾¤Î¥×¥í¥»¥¹¤¬¥á¥â¥ê¡¼¤òÁ´¤Æ»È¤Ã¤Æ¤¤¤ë¤«³Îǧ¤·¤Æ¤¯¤À¤µ¤¤. ¥á¥â¥ê¡¼¤ò»È¤¤ÀڤäƤ¤¤Ê¤¤¾ì¹ç¡¢'ulimit' ¤òÀßÄꤷ¤Æ mysqld ¤Î¥á¥â¥ê¡¼»ÈÍѸ³¦Î̤ò¿¤¯¤¹¤ë¤«¡¢swap space ¤òÁý¤ä¤·¤Æ¤ß¤Æ¤¯¤À¤µ¤¤" - kor "Out of memory; mysqld³ª ¶Ç´Ù¸¥ ÇÁ·Î¼¼¼¿¡¼ »ç¿ë°¡´ÉÇÑ ¸Þ¸ð¸®¸¦ »ç¿ëÇÑÁö äũÇϽÿÀ. ¸¸¾à ±×·¸Áö ¾Ê´Ù¸é ulimit ¸í·ÉÀ» ÀÌ¿¿ëÇÏ¿© ´õ¸¹Àº ¸Þ¸ð¸®¸¦ »ç¿ëÇÒ ¼ö ÀÖµµ·Ï Çϰųª ½º¿Ò ½ºÆÐÀ̽º¸¦ Áõ°¡½ÃÅ°½Ã¿À" - nor "Tomt for tråd plass/minne" - norwegian-ny "Tomt for tråd plass/minne" - pol "Zbyt ma³o miejsca/pamiêci dla w?tku" - por "Sem memória. Verifique se o mysqld ou algum outro processo está usando toda memória disponível. Se não, você pode ter que usar 'ulimit' para permitir ao mysqld usar mais memória ou você pode adicionar mais área de 'swap'" - rum "Out of memory; Verifica daca mysqld sau vreun alt proces foloseste toate memoria disponbila. Altfel, trebuie sa folosesi 'ulimit' ca sa permiti lui memoria disponbila. Altfel, trebuie sa folosesi 'ulimit' ca sa permiti lui mysqld sa foloseasca mai multa memorie ori adauga mai mult spatiu pentru swap (swap space)" - rus "îÅÄÏÓÔÁÔÏÞÎÏ ÐÁÍÑÔÉ; ÕÄÏÓÔÏ×ÅÒØÔÅÓØ, ÞÔÏ mysqld ÉÌÉ ËÁËÏÊ-ÌÉÂÏ ÄÒÕÇÏÊ ÐÒÏÃÅÓÓ ÎÅ ÚÁÎÉÍÁÅÔ ×ÓÀ ÄÏÓÔÕÐÎÕÀ ÐÁÍÑÔØ. åÓÌÉ ÎÅÔ, ÔÏ ×Ù ÍÏÖÅÔÅ ÉÓÐÏÌØÚÏ×ÁÔØ ulimit, ÞÔÏÂÙ ×ÙÄÅÌÉÔØ ÄÌÑ mysqld ÂÏÌØÛÅ ÐÁÍÑÔÉ, ÉÌÉ Õ×ÅÌÉÞÉÔØ ÏÂßÅÍ ÆÁÊÌÁ ÐÏÄËÁÞËÉ" - serbian "Nema memorije; Proverite da li MySQL server ili neki drugi proces koristi svu slobodnu memoriju. (UNIX: Ako ne, probajte da upotrebite 'ulimit' komandu da biste dozvolili daemon-u da koristi više memorije ili probajte da dodate više swap memorije)" - slo "Málo miesta-pamäti pre vlákno" - spa "Memoria/espacio de tranpaso insuficiente" - swe "Fick slut på minnet. Kontrollera om mysqld eller någon annan process använder allt tillgängligt minne. Om inte, försök använda 'ulimit' eller allokera mera swap" - ukr "âÒÁË ÐÁÍ'ÑÔ¦; ðÅÒÅצÒÔÅ ÞÉ mysqld ÁÂÏ Ñ˦ÓØ ¦ÎÛ¦ ÐÒÏÃÅÓÉ ×ÉËÏÒÉÓÔÏ×ÕÀÔØ ÕÓÀ ÄÏÓÔÕÐÎÕ ÐÁÍ'ÑÔØ. ñË Î¦, ÔÏ ×É ÍÏÖÅÔÅ ÓËÏÒÉÓÔÁÔÉÓÑ 'ulimit', ÁÂÉ ÄÏÚ×ÏÌÉÔÉ mysqld ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ Â¦ÌØÛÅ ÐÁÍ'ÑÔ¦ ÁÂÏ ×É ÍÏÖÅÔÅ ÄÏÄÁÔÉ Â¦ÌØÛŠͦÓÃÑ Ð¦Ä Ó×ÁÐ" -ER_BAD_HOST_ERROR 08S01 - cze "Nemohu zjistit jm-Béno stroje pro Va¹i adresu" - dan "Kan ikke få værtsnavn for din adresse" - nla "Kan de hostname niet krijgen van uw adres" - eng "Can't get hostname for your address" - jps "‚»‚Ì address ‚Ì hostname ‚ªˆø‚¯‚Ü‚¹‚ñ.", - est "Ei suuda lahendada IP aadressi masina nimeks" - fre "Ne peut obtenir de hostname pour votre adresse" - ger "Kann Hostnamen für diese Adresse nicht erhalten" - greek "Äåí Ýãéíå ãíùóôü ôï hostname ãéá ôçí address óáò" - hun "A gepnev nem allapithato meg a cimbol" - ita "Impossibile risalire al nome dell'host dall'indirizzo (risoluzione inversa)" - jpn "¤½¤Î address ¤Î hostname ¤¬°ú¤±¤Þ¤»¤ó." - kor "´ç½ÅÀÇ ÄÄÇ»ÅÍÀÇ È£½ºÆ®À̸§À» ¾òÀ» ¼ö ¾øÀ¾´Ï´Ù." - nor "Kan ikke få tak i vertsnavn for din adresse" - norwegian-ny "Kan ikkje få tak i vertsnavn for di adresse" - pol "Nie mo¿na otrzymaæ nazwy hosta dla twojego adresu" - por "Não pode obter nome do 'host' para seu endereço" - rum "Nu pot sa obtin hostname-ul adresei tale" - rus "îÅ×ÏÚÍÏÖÎÏ ÐÏÌÕÞÉÔØ ÉÍÑ ÈÏÓÔÁ ÄÌÑ ×ÁÛÅÇÏ ÁÄÒÅÓÁ" - serbian "Ne mogu da dobijem ime host-a za vašu IP adresu" - slo "Nemô¾em zisti» meno hostiteµa pre va¹u adresu" - spa "No puedo obtener el nombre de maquina de tu direccion" - swe "Kan inte hitta 'hostname' för din adress" - ukr "îÅ ÍÏÖÕ ×ÉÚÎÁÞÉÔÉ ¦Í'Ñ ÈÏÓÔÕ ÄÌÑ ×ÁÛϧ ÁÄÒÅÓÉ" -ER_HANDSHAKE_ERROR 08S01 - cze "Chyba p-Bøi ustavování spojení" - dan "Forkert håndtryk (handshake)" - nla "Verkeerde handshake" - eng "Bad handshake" - est "Väär handshake" - fre "Mauvais 'handshake'" - ger "Ungültiger Handshake" - greek "Ç áíáãíþñéóç (handshake) äåí Ýãéíå óùóôÜ" - hun "A kapcsolatfelvetel nem sikerult (Bad handshake)" - ita "Negoziazione impossibile" - nor "Feil håndtrykk (handshake)" - norwegian-ny "Feil handtrykk (handshake)" - pol "Z³y uchwyt(handshake)" - por "Negociação de acesso falhou" - rum "Prost inceput de conectie (bad handshake)" - rus "îÅËÏÒÒÅËÔÎÏÅ ÐÒÉ×ÅÔÓÔ×ÉÅ" - serbian "Loš poèetak komunikacije (handshake)" - slo "Chyba pri nadväzovaní spojenia" - spa "Protocolo erroneo" - swe "Fel vid initiering av kommunikationen med klienten" - ukr "îÅצÒÎÁ ÕÓÔÁÎÏ×ËÁ Ú×'ÑÚËÕ" -ER_DBACCESS_DENIED_ERROR 42000 - cze "P-Bøístup pro u¾ivatele '%-.48s'@'%-.64s' k databázi '%-.192s' není povolen" - dan "Adgang nægtet bruger: '%-.48s'@'%-.64s' til databasen '%-.192s'" - nla "Toegang geweigerd voor gebruiker: '%-.48s'@'%-.64s' naar database '%-.192s'" - eng "Access denied for user '%-.48s'@'%-.64s' to database '%-.192s'" - jps "ƒ†[ƒU[ '%-.48s'@'%-.64s' ‚Ì '%-.192s' ƒf[ƒ^ƒx[ƒX‚ւ̃AƒNƒZƒX‚ð‹‘”Û‚µ‚Ü‚·", - est "Ligipääs keelatud kasutajale '%-.48s'@'%-.64s' andmebaasile '%-.192s'" - fre "Accès refusé pour l'utilisateur: '%-.48s'@'@%-.64s'. Base '%-.192s'" - ger "Benutzer '%-.48s'@'%-.64s' hat keine Zugriffsberechtigung für Datenbank '%-.192s'" - greek "Äåí åðéôÝñåôáé ç ðñüóâáóç óôï ÷ñÞóôç: '%-.48s'@'%-.64s' óôç âÜóç äåäïìÝíùí '%-.192s'" - hun "A(z) '%-.48s'@'%-.64s' felhasznalo szamara tiltott eleres az '%-.192s' adabazishoz." - ita "Accesso non consentito per l'utente: '%-.48s'@'%-.64s' al database '%-.192s'" - jpn "¥æ¡¼¥¶¡¼ '%-.48s'@'%-.64s' ¤Î '%-.192s' ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Ø¤Î¥¢¥¯¥»¥¹¤òµñÈݤ·¤Þ¤¹" - kor "'%-.48s'@'%-.64s' »ç¿ëÀÚ´Â '%-.192s' µ¥ÀÌŸº£À̽º¿¡ Á¢±ÙÀÌ °ÅºÎ µÇ¾ú½À´Ï´Ù." - nor "Tilgang nektet for bruker: '%-.48s'@'%-.64s' til databasen '%-.192s' nektet" - norwegian-ny "Tilgang ikkje tillate for brukar: '%-.48s'@'%-.64s' til databasen '%-.192s' nekta" - por "Acesso negado para o usuário '%-.48s'@'%-.64s' ao banco de dados '%-.192s'" - rum "Acces interzis pentru utilizatorul: '%-.48s'@'%-.64s' la baza de date '%-.192s'" - rus "äÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%-.48s'@'%-.64s' ÄÏÓÔÕÐ Ë ÂÁÚÅ ÄÁÎÎÙÈ '%-.192s' ÚÁËÒÙÔ" - serbian "Pristup je zabranjen korisniku '%-.48s'@'%-.64s' za bazu '%-.192s'" - slo "Zakázaný prístup pre u¾ívateµa: '%-.48s'@'%-.64s' k databázi '%-.192s'" - spa "Acceso negado para usuario: '%-.48s'@'%-.64s' para la base de datos '%-.192s'" - swe "Användare '%-.48s'@'%-.64s' är ej berättigad att använda databasen %-.192s" - ukr "äÏÓÔÕÐ ÚÁÂÏÒÏÎÅÎÏ ÄÌÑ ËÏÒÉÓÔÕ×ÁÞÁ: '%-.48s'@'%-.64s' ÄÏ ÂÁÚÉ ÄÁÎÎÉÈ '%-.192s'" -ER_ACCESS_DENIED_ERROR 28000 - cze "P-Bøístup pro u¾ivatele '%-.48s'@'%-.64s' (s heslem %s)" - dan "Adgang nægtet bruger: '%-.48s'@'%-.64s' (Bruger adgangskode: %s)" - nla "Toegang geweigerd voor gebruiker: '%-.48s'@'%-.64s' (Wachtwoord gebruikt: %s)" - eng "Access denied for user '%-.48s'@'%-.64s' (using password: %s)" - jps "ƒ†[ƒU[ '%-.48s'@'%-.64s' ‚ð‹‘”Û‚µ‚Ü‚·.uUsing password: %s)", - est "Ligipääs keelatud kasutajale '%-.48s'@'%-.64s' (kasutab parooli: %s)" - fre "Accès refusé pour l'utilisateur: '%-.48s'@'@%-.64s' (mot de passe: %s)" - ger "Benutzer '%-.48s'@'%-.64s' hat keine Zugriffsberechtigung (verwendetes Passwort: %s)" - greek "Äåí åðéôÝñåôáé ç ðñüóâáóç óôï ÷ñÞóôç: '%-.48s'@'%-.64s' (÷ñÞóç password: %s)" - hun "A(z) '%-.48s'@'%-.64s' felhasznalo szamara tiltott eleres. (Hasznalja a jelszot: %s)" - ita "Accesso non consentito per l'utente: '%-.48s'@'%-.64s' (Password: %s)" - jpn "¥æ¡¼¥¶¡¼ '%-.48s'@'%-.64s' ¤òµñÈݤ·¤Þ¤¹.uUsing password: %s)" - kor "'%-.48s'@'%-.64s' »ç¿ëÀÚ´Â Á¢±ÙÀÌ °ÅºÎ µÇ¾ú½À´Ï´Ù. (using password: %s)" - nor "Tilgang nektet for bruker: '%-.48s'@'%-.64s' (Bruker passord: %s)" - norwegian-ny "Tilgang ikke tillate for brukar: '%-.48s'@'%-.64s' (Brukar passord: %s)" - por "Acesso negado para o usuário '%-.48s'@'%-.64s' (senha usada: %s)" - rum "Acces interzis pentru utilizatorul: '%-.48s'@'%-.64s' (Folosind parola: %s)" - rus "äÏÓÔÕÐ ÚÁËÒÙÔ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%-.48s'@'%-.64s' (ÂÙÌ ÉÓÐÏÌØÚÏ×ÁÎ ÐÁÒÏÌØ: %s)" - serbian "Pristup je zabranjen korisniku '%-.48s'@'%-.64s' (koristi lozinku: '%s')" - slo "Zakázaný prístup pre u¾ívateµa: '%-.48s'@'%-.64s' (pou¾itie hesla: %s)" - spa "Acceso negado para usuario: '%-.48s'@'%-.64s' (Usando clave: %s)" - swe "Användare '%-.48s'@'%-.64s' är ej berättigad att logga in (Använder lösen: %s)" - ukr "äÏÓÔÕÐ ÚÁÂÏÒÏÎÅÎÏ ÄÌÑ ËÏÒÉÓÔÕ×ÁÞÁ: '%-.48s'@'%-.64s' (÷ÉËÏÒÉÓÔÁÎÏ ÐÁÒÏÌØ: %s)" -ER_NO_DB_ERROR 3D000 - cze "Nebyla vybr-Bána ¾ádná databáze" - dan "Ingen database valgt" - nla "Geen database geselecteerd" - eng "No database selected" - jps "ƒf[ƒ^ƒx[ƒX‚ª‘I‘ð‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ.", - est "Andmebaasi ei ole valitud" - fre "Aucune base n'a été sélectionnée" - ger "Keine Datenbank ausgewählt" - greek "Äåí åðéëÝ÷èçêå âÜóç äåäïìÝíùí" - hun "Nincs kivalasztott adatbazis" - ita "Nessun database selezionato" - jpn "¥Ç¡¼¥¿¥Ù¡¼¥¹¤¬ÁªÂò¤µ¤ì¤Æ¤¤¤Þ¤»¤ó." - kor "¼±ÅÃµÈ µ¥ÀÌŸº£À̽º°¡ ¾ø½À´Ï´Ù." - nor "Ingen database valgt" - norwegian-ny "Ingen database vald" - pol "Nie wybrano ¿adnej bazy danych" - por "Nenhum banco de dados foi selecionado" - rum "Nici o baza de data nu a fost selectata inca" - rus "âÁÚÁ ÄÁÎÎÙÈ ÎÅ ×ÙÂÒÁÎÁ" - serbian "Ni jedna baza nije selektovana" - slo "Nebola vybraná databáza" - spa "Base de datos no seleccionada" - swe "Ingen databas i användning" - ukr "âÁÚÕ ÄÁÎÎÉÈ ÎÅ ×ÉÂÒÁÎÏ" -ER_UNKNOWN_COM_ERROR 08S01 - cze "Nezn-Bámý pøíkaz" - dan "Ukendt kommando" - nla "Onbekend commando" - eng "Unknown command" - jps "‚»‚̃Rƒ}ƒ“ƒh‚͉½H", - est "Tundmatu käsk" - fre "Commande inconnue" - ger "Unbekannter Befehl" - greek "Áãíùóôç åíôïëÞ" - hun "Ervenytelen parancs" - ita "Comando sconosciuto" - jpn "¤½¤Î¥³¥Þ¥ó¥É¤Ï²¿¡©" - kor "¸í·É¾î°¡ ¹ºÁö ¸ð¸£°Ú¾î¿ä..." - nor "Ukjent kommando" - norwegian-ny "Ukjent kommando" - pol "Nieznana komenda" - por "Comando desconhecido" - rum "Comanda invalida" - rus "îÅÉÚ×ÅÓÔÎÁÑ ËÏÍÁÎÄÁ ËÏÍÍÕÎÉËÁÃÉÏÎÎÏÇÏ ÐÒÏÔÏËÏÌÁ" - serbian "Nepoznata komanda" - slo "Neznámy príkaz" - spa "Comando desconocido" - swe "Okänt commando" - ukr "îÅצÄÏÍÁ ËÏÍÁÎÄÁ" -ER_BAD_NULL_ERROR 23000 - cze "Sloupec '%-.192s' nem-Bù¾e být null" - dan "Kolonne '%-.192s' kan ikke være NULL" - nla "Kolom '%-.192s' kan niet null zijn" - eng "Column '%-.192s' cannot be null" - jps "Column '%-.192s' ‚Í null ‚É‚Í‚Å‚«‚È‚¢‚Ì‚Å‚·", - est "Tulp '%-.192s' ei saa omada nullväärtust" - fre "Le champ '%-.192s' ne peut être vide (null)" - ger "Feld '%-.192s' darf nicht NULL sein" - greek "Ôï ðåäßï '%-.192s' äåí ìðïñåß íá åßíáé êåíü (null)" - hun "A(z) '%-.192s' oszlop erteke nem lehet nulla" - ita "La colonna '%-.192s' non puo` essere nulla" - jpn "Column '%-.192s' ¤Ï null ¤Ë¤Ï¤Ç¤¤Ê¤¤¤Î¤Ç¤¹" - kor "Ä®·³ '%-.192s'´Â ³Î(Null)ÀÌ µÇ¸é ¾ÈµË´Ï´Ù. " - nor "Kolonne '%-.192s' kan ikke vere null" - norwegian-ny "Kolonne '%-.192s' kan ikkje vere null" - pol "Kolumna '%-.192s' nie mo¿e byæ null" - por "Coluna '%-.192s' não pode ser vazia" - rum "Coloana '%-.192s' nu poate sa fie null" - rus "óÔÏÌÂÅà '%-.192s' ÎÅ ÍÏÖÅÔ ÐÒÉÎÉÍÁÔØ ×ÅÌÉÞÉÎÕ NULL" - serbian "Kolona '%-.192s' ne može biti NULL" - slo "Pole '%-.192s' nemô¾e by» null" - spa "La columna '%-.192s' no puede ser nula" - swe "Kolumn '%-.192s' får inte vara NULL" - ukr "óÔÏ×ÂÅÃØ '%-.192s' ÎÅ ÍÏÖÅ ÂÕÔÉ ÎÕÌØÏ×ÉÍ" -ER_BAD_DB_ERROR 42000 - cze "Nezn-Bámá databáze '%-.192s'" - dan "Ukendt database '%-.192s'" - nla "Onbekende database '%-.192s'" - eng "Unknown database '%-.192s'" - jps "'%-.192s' ‚È‚ñ‚ăf[ƒ^ƒx[ƒX‚Í’m‚è‚Ü‚¹‚ñ.", - est "Tundmatu andmebaas '%-.192s'" - fre "Base '%-.192s' inconnue" - ger "Unbekannte Datenbank '%-.192s'" - greek "Áãíùóôç âÜóç äåäïìÝíùí '%-.192s'" - hun "Ervenytelen adatbazis: '%-.192s'" - ita "Database '%-.192s' sconosciuto" - jpn "'%-.192s' ¤Ê¤ó¤Æ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ÏÃΤê¤Þ¤»¤ó." - kor "µ¥ÀÌŸº£À̽º '%-.192s'´Â ¾Ë¼ö ¾øÀ½" - nor "Ukjent database '%-.192s'" - norwegian-ny "Ukjent database '%-.192s'" - pol "Nieznana baza danych '%-.192s'" - por "Banco de dados '%-.192s' desconhecido" - rum "Baza de data invalida '%-.192s'" - rus "îÅÉÚ×ÅÓÔÎÁÑ ÂÁÚÁ ÄÁÎÎÙÈ '%-.192s'" - serbian "Nepoznata baza '%-.192s'" - slo "Neznáma databáza '%-.192s'" - spa "Base de datos desconocida '%-.192s'" - swe "Okänd databas: '%-.192s'" - ukr "îÅצÄÏÍÁ ÂÁÚÁ ÄÁÎÎÉÈ '%-.192s'" -ER_TABLE_EXISTS_ERROR 42S01 - cze "Tabulka '%-.192s' ji-B¾ existuje" - dan "Tabellen '%-.192s' findes allerede" - nla "Tabel '%-.192s' bestaat al" - eng "Table '%-.192s' already exists" - jps "Table '%-.192s' ‚ÍŠù‚É‚ ‚è‚Ü‚·", - est "Tabel '%-.192s' juba eksisteerib" - fre "La table '%-.192s' existe déjà" - ger "Tabelle '%-.192s' bereits vorhanden" - greek "Ï ðßíáêáò '%-.192s' õðÜñ÷åé Þäç" - hun "A(z) '%-.192s' tabla mar letezik" - ita "La tabella '%-.192s' esiste gia`" - jpn "Table '%-.192s' ¤Ï´û¤Ë¤¢¤ê¤Þ¤¹" - kor "Å×À̺í '%-.192s'´Â ÀÌ¹Ì Á¸ÀçÇÔ" - nor "Tabellen '%-.192s' eksisterer allerede" - norwegian-ny "Tabellen '%-.192s' eksisterar allereide" - pol "Tabela '%-.192s' ju¿ istnieje" - por "Tabela '%-.192s' já existe" - rum "Tabela '%-.192s' exista deja" - rus "ôÁÂÌÉÃÁ '%-.192s' ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ" - serbian "Tabela '%-.192s' veæ postoji" - slo "Tabuµka '%-.192s' u¾ existuje" - spa "La tabla '%-.192s' ya existe" - swe "Tabellen '%-.192s' finns redan" - ukr "ôÁÂÌÉÃÑ '%-.192s' ×ÖÅ ¦ÓÎÕ¤" -ER_BAD_TABLE_ERROR 42S02 - cze "Nezn-Bámá tabulka '%-.100s'" - dan "Ukendt tabel '%-.100s'" - nla "Onbekende tabel '%-.100s'" - eng "Unknown table '%-.100s'" - jps "table '%-.100s' ‚Í‚ ‚è‚Ü‚¹‚ñ.", - est "Tundmatu tabel '%-.100s'" - fre "Table '%-.100s' inconnue" - ger "Unbekannte Tabelle '%-.100s'" - greek "Áãíùóôïò ðßíáêáò '%-.100s'" - hun "Ervenytelen tabla: '%-.100s'" - ita "Tabella '%-.100s' sconosciuta" - jpn "table '%-.100s' ¤Ï¤¢¤ê¤Þ¤»¤ó." - kor "Å×À̺í '%-.100s'´Â ¾Ë¼ö ¾øÀ½" - nor "Ukjent tabell '%-.100s'" - norwegian-ny "Ukjent tabell '%-.100s'" - pol "Nieznana tabela '%-.100s'" - por "Tabela '%-.100s' desconhecida" - rum "Tabela '%-.100s' este invalida" - rus "îÅÉÚ×ÅÓÔÎÁÑ ÔÁÂÌÉÃÁ '%-.100s'" - serbian "Nepoznata tabela '%-.100s'" - slo "Neznáma tabuµka '%-.100s'" - spa "Tabla '%-.100s' desconocida" - swe "Okänd tabell '%-.100s'" - ukr "îÅצÄÏÍÁ ÔÁÂÌÉÃÑ '%-.100s'" -ER_NON_UNIQ_ERROR 23000 - cze "Sloupec '%-.192s' v %-.192s nen-Bí zcela jasný" - dan "Felt: '%-.192s' i tabel %-.192s er ikke entydigt" - nla "Kolom: '%-.192s' in %-.192s is niet eenduidig" - eng "Column '%-.192s' in %-.192s is ambiguous" - est "Väli '%-.192s' %-.192s-s ei ole ühene" - fre "Champ: '%-.192s' dans %-.192s est ambigu" - ger "Feld '%-.192s' in %-.192s ist nicht eindeutig" - greek "Ôï ðåäßï: '%-.192s' óå %-.192s äåí Ý÷åé êáèïñéóôåß" - hun "A(z) '%-.192s' oszlop %-.192s-ben ketertelmu" - ita "Colonna: '%-.192s' di %-.192s e` ambigua" - jpn "Column: '%-.192s' in %-.192s is ambiguous" - kor "Ä®·³: '%-.192s' in '%-.192s' ÀÌ ¸ðÈ£ÇÔ" - nor "Felt: '%-.192s' i tabell %-.192s er ikke entydig" - norwegian-ny "Kolonne: '%-.192s' i tabell %-.192s er ikkje eintydig" - pol "Kolumna: '%-.192s' w %-.192s jest dwuznaczna" - por "Coluna '%-.192s' em '%-.192s' é ambígua" - rum "Coloana: '%-.192s' in %-.192s este ambigua" - rus "óÔÏÌÂÅà '%-.192s' × %-.192s ÚÁÄÁÎ ÎÅÏÄÎÏÚÎÁÞÎÏ" - serbian "Kolona '%-.192s' u %-.192s nije jedinstvena u kontekstu" - slo "Pole: '%-.192s' v %-.192s je nejasné" - spa "La columna: '%-.192s' en %-.192s es ambigua" - swe "Kolumn '%-.192s' i %-.192s är inte unik" - ukr "óÔÏ×ÂÅÃØ '%-.192s' Õ %-.192s ×ÉÚÎÁÞÅÎÉÊ ÎÅÏÄÎÏÚÎÁÞÎÏ" -ER_SERVER_SHUTDOWN 08S01 - cze "Prob-Bíhá ukonèování práce serveru" - dan "Database nedlukning er i gang" - nla "Bezig met het stoppen van de server" - eng "Server shutdown in progress" - jps "Server ‚ð shutdown ’†...", - est "Serveri seiskamine käib" - fre "Arrêt du serveur en cours" - ger "Der Server wird heruntergefahren" - greek "Åíáñîç äéáäéêáóßáò áðïóýíäåóçò ôïõ åîõðçñåôçôÞ (server shutdown)" - hun "A szerver leallitasa folyamatban" - ita "Shutdown del server in corso" - jpn "Server ¤ò shutdown Ãæ..." - kor "Server°¡ ¼Ë´Ù¿î ÁßÀÔ´Ï´Ù." - nor "Database nedkobling er i gang" - norwegian-ny "Tenar nedkopling er i gang" - pol "Trwa koñczenie dzia³ania serwera" - por "'Shutdown' do servidor em andamento" - rum "Terminarea serverului este in desfasurare" - rus "óÅÒ×ÅÒ ÎÁÈÏÄÉÔÓÑ × ÐÒÏÃÅÓÓÅ ÏÓÔÁÎÏ×ËÉ" - serbian "Gašenje servera je u toku" - slo "Prebieha ukonèovanie práce servera" - spa "Desconexion de servidor en proceso" - swe "Servern går nu ned" - ukr "úÁ×ÅÒÛÕ¤ÔØÓÑ ÒÁÂÏÔÁ ÓÅÒ×ÅÒÁ" -ER_BAD_FIELD_ERROR 42S22 S0022 - cze "Nezn-Bámý sloupec '%-.192s' v %-.192s" - dan "Ukendt kolonne '%-.192s' i tabel %-.192s" - nla "Onbekende kolom '%-.192s' in %-.192s" - eng "Unknown column '%-.192s' in '%-.192s'" - jps "'%-.192s' column ‚Í '%-.192s' ‚É‚Í‚ ‚è‚Ü‚¹‚ñ.", - est "Tundmatu tulp '%-.192s' '%-.192s'-s" - fre "Champ '%-.192s' inconnu dans %-.192s" - ger "Unbekanntes Tabellenfeld '%-.192s' in %-.192s" - greek "Áãíùóôï ðåäßï '%-.192s' óå '%-.192s'" - hun "A(z) '%-.192s' oszlop ervenytelen '%-.192s'-ben" - ita "Colonna sconosciuta '%-.192s' in '%-.192s'" - jpn "'%-.192s' column ¤Ï '%-.192s' ¤Ë¤Ï¤¢¤ê¤Þ¤»¤ó." - kor "Unknown Ä®·³ '%-.192s' in '%-.192s'" - nor "Ukjent kolonne '%-.192s' i tabell %-.192s" - norwegian-ny "Ukjent felt '%-.192s' i tabell %-.192s" - pol "Nieznana kolumna '%-.192s' w %-.192s" - por "Coluna '%-.192s' desconhecida em '%-.192s'" - rum "Coloana invalida '%-.192s' in '%-.192s'" - rus "îÅÉÚ×ÅÓÔÎÙÊ ÓÔÏÌÂÅà '%-.192s' × '%-.192s'" - serbian "Nepoznata kolona '%-.192s' u '%-.192s'" - slo "Neznáme pole '%-.192s' v '%-.192s'" - spa "La columna '%-.192s' en %-.192s es desconocida" - swe "Okänd kolumn '%-.192s' i %-.192s" - ukr "îÅצÄÏÍÉÊ ÓÔÏ×ÂÅÃØ '%-.192s' Õ '%-.192s'" -ER_WRONG_FIELD_WITH_GROUP 42000 S1009 - cze "Pou-B¾ité '%-.192s' nebylo v group by" - dan "Brugte '%-.192s' som ikke var i group by" - nla "Opdracht gebruikt '%-.192s' dat niet in de GROUP BY voorkomt" - eng "'%-.192s' isn't in GROUP BY" - jps "'%-.192s' isn't in GROUP BY", - est "'%-.192s' puudub GROUP BY klauslis" - fre "'%-.192s' n'est pas dans 'group by'" - ger "'%-.192s' ist nicht in GROUP BY vorhanden" - greek "×ñçóéìïðïéÞèçêå '%-.192s' ðïõ äåí õðÞñ÷å óôï group by" - hun "Used '%-.192s' with wasn't in group by" - ita "Usato '%-.192s' che non e` nel GROUP BY" - kor "'%-.192s'Àº GROUP BY¼Ó¿¡ ¾øÀ½" - nor "Brukte '%-.192s' som ikke var i group by" - norwegian-ny "Brukte '%-.192s' som ikkje var i group by" - pol "U¿yto '%-.192s' bez umieszczenia w group by" - por "'%-.192s' não está em 'GROUP BY'" - rum "'%-.192s' nu exista in clauza GROUP BY" - rus "'%-.192s' ÎÅ ÐÒÉÓÕÔÓÔ×ÕÅÔ × GROUP BY" - serbian "Entitet '%-.192s' nije naveden u komandi 'GROUP BY'" - slo "Pou¾ité '%-.192s' nebolo v 'group by'" - spa "Usado '%-.192s' el cual no esta group by" - swe "'%-.192s' finns inte i GROUP BY" - ukr "'%-.192s' ÎÅ ¤ Õ GROUP BY" -ER_WRONG_GROUP_FIELD 42000 S1009 - cze "Nemohu pou-B¾ít group na '%-.192s'" - dan "Kan ikke gruppere på '%-.192s'" - nla "Kan '%-.192s' niet groeperen" - eng "Can't group on '%-.192s'" - est "Ei saa grupeerida '%-.192s' järgi" - fre "Ne peut regrouper '%-.192s'" - ger "Gruppierung über '%-.192s' nicht möglich" - greek "Áäýíáôç ç ïìáäïðïßçóç (group on) '%-.192s'" - hun "A group nem hasznalhato: '%-.192s'" - ita "Impossibile raggruppare per '%-.192s'" - kor "'%-.192s'¸¦ ±×·ìÇÒ ¼ö ¾øÀ½" - nor "Kan ikke gruppere på '%-.192s'" - norwegian-ny "Kan ikkje gruppere på '%-.192s'" - pol "Nie mo¿na grupowaæ po '%-.192s'" - por "Não pode agrupar em '%-.192s'" - rum "Nu pot sa grupez pe (group on) '%-.192s'" - rus "îÅ×ÏÚÍÏÖÎÏ ÐÒÏÉÚ×ÅÓÔÉ ÇÒÕÐÐÉÒÏ×ËÕ ÐÏ '%-.192s'" - serbian "Ne mogu da grupišem po '%-.192s'" - slo "Nemô¾em pou¾i» 'group' na '%-.192s'" - spa "No puedo agrupar por '%-.192s'" - swe "Kan inte använda GROUP BY med '%-.192s'" - ukr "îÅ ÍÏÖÕ ÇÒÕÐÕ×ÁÔÉ ÐÏ '%-.192s'" -ER_WRONG_SUM_SELECT 42000 S1009 - cze "P-Bøíkaz obsahuje zároveò funkci sum a sloupce" - dan "Udtrykket har summer (sum) funktioner og kolonner i samme udtryk" - nla "Opdracht heeft totaliseer functies en kolommen in dezelfde opdracht" - eng "Statement has sum functions and columns in same statement" - est "Lauses on korraga nii tulbad kui summeerimisfunktsioonid" - fre "Vous demandez la fonction sum() et des champs dans la même commande" - ger "Die Verwendung von Summierungsfunktionen und Spalten im selben Befehl ist nicht erlaubt" - greek "Ç äéáôýðùóç ðåñéÝ÷åé sum functions êáé columns óôçí ßäéá äéáôýðùóç" - ita "Il comando ha una funzione SUM e una colonna non specificata nella GROUP BY" - kor "Statement °¡ sum±â´ÉÀ» µ¿ÀÛÁßÀÌ°í Ä®·³µµ µ¿ÀÏÇÑ statementÀÔ´Ï´Ù." - nor "Uttrykket har summer (sum) funksjoner og kolonner i samme uttrykk" - norwegian-ny "Uttrykket har summer (sum) funksjoner og kolonner i same uttrykk" - pol "Zapytanie ma funkcje sumuj?ce i kolumny w tym samym zapytaniu" - por "Cláusula contém funções de soma e colunas juntas" - rum "Comanda are functii suma si coloane in aceeasi comanda" - rus "÷ÙÒÁÖÅÎÉÅ ÓÏÄÅÒÖÉÔ ÇÒÕÐÐÏ×ÙÅ ÆÕÎËÃÉÉ É ÓÔÏÌÂÃÙ, ÎÏ ÎÅ ×ËÌÀÞÁÅÔ GROUP BY. á ËÁË ×Ù ÕÍÕÄÒÉÌÉÓØ ÐÏÌÕÞÉÔØ ÜÔÏ ÓÏÏÂÝÅÎÉÅ Ï ÏÛÉÂËÅ?" - serbian "Izraz ima 'SUM' agregatnu funkciju i kolone u isto vreme" - slo "Príkaz obsahuje zároveò funkciu 'sum' a poµa" - spa "El estamento tiene funciones de suma y columnas en el mismo estamento" - swe "Kommandot har både sum functions och enkla funktioner" - ukr "õ ×ÉÒÁÚ¦ ×ÉËÏÒÉÓÔÁÎÏ Ð¦ÄÓÕÍÏ×ÕÀÞ¦ ÆÕÎËæ§ ÐÏÒÑÄ Ú ¦ÍÅÎÁÍÉ ÓÔÏ×Âæ×" -ER_WRONG_VALUE_COUNT 21S01 - cze "Po-Bèet sloupcù neodpovídá zadané hodnotì" - dan "Kolonne tæller stemmer ikke med antallet af værdier" - nla "Het aantal kolommen komt niet overeen met het aantal opgegeven waardes" - eng "Column count doesn't match value count" - est "Tulpade arv erineb väärtuste arvust" - ger "Die Anzahl der Spalten entspricht nicht der Anzahl der Werte" - greek "Ôï Column count äåí ôáéñéÜæåé ìå ôï value count" - hun "Az oszlopban levo ertek nem egyezik meg a szamitott ertekkel" - ita "Il numero delle colonne non e` uguale al numero dei valori" - kor "Ä®·³ÀÇ Ä«¿îÆ®°¡ °ªÀÇ Ä«¿îÆ®¿Í ÀÏÄ¡ÇÏÁö ¾Ê½À´Ï´Ù." - nor "Felt telling stemmer verdi telling" - norwegian-ny "Kolonne telling stemmer verdi telling" - pol "Liczba kolumn nie odpowiada liczbie warto?ci" - por "Contagem de colunas não confere com a contagem de valores" - rum "Numarul de coloane nu este acelasi cu numarul valoarei" - rus "ëÏÌÉÞÅÓÔ×Ï ÓÔÏÌÂÃÏ× ÎÅ ÓÏ×ÐÁÄÁÅÔ Ó ËÏÌÉÞÅÓÔ×ÏÍ ÚÎÁÞÅÎÉÊ" - serbian "Broj kolona ne odgovara broju vrednosti" - slo "Poèet polí nezodpovedá zadanej hodnote" - spa "La columna con count no tiene valores para contar" - swe "Antalet kolumner motsvarar inte antalet värden" - ukr "ë¦ÌØ˦ÓÔØ ÓÔÏ×ÂÃ¦× ÎÅ ÓЦ×ÐÁÄÁ¤ Ú Ë¦ÌØ˦ÓÔÀ ÚÎÁÞÅÎØ" -ER_TOO_LONG_IDENT 42000 S1009 - cze "Jm-Béno identifikátoru '%-.100s' je pøíli¹ dlouhé" - dan "Navnet '%-.100s' er for langt" - nla "Naam voor herkenning '%-.100s' is te lang" - eng "Identifier name '%-.100s' is too long" - jps "Identifier name '%-.100s' ‚Í’·‚·‚¬‚Ü‚·", - est "Identifikaatori '%-.100s' nimi on liiga pikk" - fre "Le nom de l'identificateur '%-.100s' est trop long" - ger "Name des Bezeichners '%-.100s' ist zu lang" - greek "Ôï identifier name '%-.100s' åßíáé ðïëý ìåãÜëï" - hun "A(z) '%-.100s' azonositonev tul hosszu." - ita "Il nome dell'identificatore '%-.100s' e` troppo lungo" - jpn "Identifier name '%-.100s' ¤ÏŤ¹¤®¤Þ¤¹" - kor "Identifier '%-.100s'´Â ³Ê¹« ±æ±º¿ä." - nor "Identifikator '%-.100s' er for lang" - norwegian-ny "Identifikator '%-.100s' er for lang" - pol "Nazwa identyfikatora '%-.100s' jest zbyt d³uga" - por "Nome identificador '%-.100s' é longo demais" - rum "Numele indentificatorului '%-.100s' este prea lung" - rus "óÌÉÛËÏÍ ÄÌÉÎÎÙÊ ÉÄÅÎÔÉÆÉËÁÔÏÒ '%-.100s'" - serbian "Ime '%-.100s' je predugaèko" - slo "Meno identifikátora '%-.100s' je príli¹ dlhé" - spa "El nombre del identificador '%-.100s' es demasiado grande" - swe "Kolumnnamn '%-.100s' är för långt" - ukr "¶Í'Ñ ¦ÄÅÎÔÉƦËÁÔÏÒÁ '%-.100s' ÚÁÄÏ×ÇÅ" -ER_DUP_FIELDNAME 42S21 S1009 - cze "Zdvojen-Bé jméno sloupce '%-.192s'" - dan "Feltnavnet '%-.192s' findes allerede" - nla "Dubbele kolom naam '%-.192s'" - eng "Duplicate column name '%-.192s'" - jps "'%-.192s' ‚Æ‚¢‚¤ column –¼‚Íd•¡‚µ‚Ä‚Ü‚·", - est "Kattuv tulba nimi '%-.192s'" - fre "Nom du champ '%-.192s' déjà utilisé" - ger "Doppelter Spaltenname: '%-.192s'" - greek "ÅðáíÜëçøç column name '%-.192s'" - hun "Duplikalt oszlopazonosito: '%-.192s'" - ita "Nome colonna duplicato '%-.192s'" - jpn "'%-.192s' ¤È¤¤¤¦ column ̾¤Ï½ÅÊ£¤·¤Æ¤Þ¤¹" - kor "Áߺ¹µÈ Ä®·³ À̸§: '%-.192s'" - nor "Feltnavnet '%-.192s' eksisterte fra før" - norwegian-ny "Feltnamnet '%-.192s' eksisterte frå før" - pol "Powtórzona nazwa kolumny '%-.192s'" - por "Nome da coluna '%-.192s' duplicado" - rum "Numele coloanei '%-.192s' e duplicat" - rus "äÕÂÌÉÒÕÀÝÅÅÓÑ ÉÍÑ ÓÔÏÌÂÃÁ '%-.192s'" - serbian "Duplirano ime kolone '%-.192s'" - slo "Opakované meno poµa '%-.192s'" - spa "Nombre de columna duplicado '%-.192s'" - swe "Kolumnnamn '%-.192s finns flera gånger" - ukr "äÕÂÌÀÀÞÅ ¦Í'Ñ ÓÔÏ×ÂÃÑ '%-.192s'" -ER_DUP_KEYNAME 42000 S1009 - cze "Zdvojen-Bé jméno klíèe '%-.192s'" - dan "Indeksnavnet '%-.192s' findes allerede" - nla "Dubbele zoeksleutel naam '%-.192s'" - eng "Duplicate key name '%-.192s'" - jps "'%-.192s' ‚Æ‚¢‚¤ key ‚Ì–¼‘O‚Íd•¡‚µ‚Ä‚¢‚Ü‚·", - est "Kattuv võtme nimi '%-.192s'" - fre "Nom de clef '%-.192s' déjà utilisé" - ger "Doppelter Name für Schlüssel vorhanden: '%-.192s'" - greek "ÅðáíÜëçøç key name '%-.192s'" - hun "Duplikalt kulcsazonosito: '%-.192s'" - ita "Nome chiave duplicato '%-.192s'" - jpn "'%-.192s' ¤È¤¤¤¦ key ¤Î̾Á°¤Ï½ÅÊ£¤·¤Æ¤¤¤Þ¤¹" - kor "Áߺ¹µÈ Å° À̸§ : '%-.192s'" - nor "Nøkkelnavnet '%-.192s' eksisterte fra før" - norwegian-ny "Nøkkelnamnet '%-.192s' eksisterte frå før" - pol "Powtórzony nazwa klucza '%-.192s'" - por "Nome da chave '%-.192s' duplicado" - rum "Numele cheiei '%-.192s' e duplicat" - rus "äÕÂÌÉÒÕÀÝÅÅÓÑ ÉÍÑ ËÌÀÞÁ '%-.192s'" - serbian "Duplirano ime kljuèa '%-.192s'" - slo "Opakované meno kµúèa '%-.192s'" - spa "Nombre de clave duplicado '%-.192s'" - swe "Nyckelnamn '%-.192s' finns flera gånger" - ukr "äÕÂÌÀÀÞÅ ¦Í'Ñ ËÌÀÞÁ '%-.192s'" -# When using this error code, please use ER(ER_DUP_ENTRY_WITH_KEY_NAME) -# for the message string. See, for example, code in handler.cc. -ER_DUP_ENTRY 23000 S1009 - cze "Zdvojen-Bý klíè '%-.192s' (èíslo klíèe %d)" - dan "Ens værdier '%-.192s' for indeks %d" - nla "Dubbele ingang '%-.192s' voor zoeksleutel %d" - eng "Duplicate entry '%-.192s' for key %d" - jps "'%-.192s' ‚Í key %d ‚É‚¨‚¢‚Äd•¡‚µ‚Ä‚¢‚Ü‚·", - est "Kattuv väärtus '%-.192s' võtmele %d" - fre "Duplicata du champ '%-.192s' pour la clef %d" - ger "Doppelter Eintrag '%-.192s' für Schlüssel %d" - greek "ÄéðëÞ åããñáöÞ '%-.192s' ãéá ôï êëåéäß %d" - hun "Duplikalt bejegyzes '%-.192s' a %d kulcs szerint." - ita "Valore duplicato '%-.192s' per la chiave %d" - jpn "'%-.192s' ¤Ï key %d ¤Ë¤ª¤¤¤Æ½ÅÊ£¤·¤Æ¤¤¤Þ¤¹" - kor "Áߺ¹µÈ ÀÔ·Â °ª '%-.192s': key %d" - nor "Like verdier '%-.192s' for nøkkel %d" - norwegian-ny "Like verdiar '%-.192s' for nykkel %d" - pol "Powtórzone wyst?pienie '%-.192s' dla klucza %d" - por "Entrada '%-.192s' duplicada para a chave %d" - rum "Cimpul '%-.192s' e duplicat pentru cheia %d" - rus "äÕÂÌÉÒÕÀÝÁÑÓÑ ÚÁÐÉÓØ '%-.192s' ÐÏ ËÌÀÞÕ %d" - serbian "Dupliran unos '%-.192s' za kljuè '%d'" - slo "Opakovaný kµúè '%-.192s' (èíslo kµúèa %d)" - spa "Entrada duplicada '%-.192s' para la clave %d" - swe "Dubbel nyckel '%-.192s' för nyckel %d" - ukr "äÕÂÌÀÀÞÉÊ ÚÁÐÉÓ '%-.192s' ÄÌÑ ËÌÀÞÁ %d" -ER_WRONG_FIELD_SPEC 42000 S1009 - cze "Chybn-Bá specifikace sloupce '%-.192s'" - dan "Forkert kolonnespecifikaton for felt '%-.192s'" - nla "Verkeerde kolom specificatie voor kolom '%-.192s'" - eng "Incorrect column specifier for column '%-.192s'" - est "Vigane tulba kirjeldus tulbale '%-.192s'" - fre "Mauvais paramètre de champ pour le champ '%-.192s'" - ger "Falsche Spezifikation für Feld '%-.192s'" - greek "ÅóöáëìÝíï column specifier ãéá ôï ðåäßï '%-.192s'" - hun "Rossz oszlopazonosito: '%-.192s'" - ita "Specifica errata per la colonna '%-.192s'" - kor "Ä®·³ '%-.192s'ÀÇ ºÎÁ¤È®ÇÑ Ä®·³ Á¤ÀÇÀÚ" - nor "Feil kolonne spesifikator for felt '%-.192s'" - norwegian-ny "Feil kolonne spesifikator for kolonne '%-.192s'" - pol "B³êdna specyfikacja kolumny dla kolumny '%-.192s'" - por "Especificador de coluna incorreto para a coluna '%-.192s'" - rum "Specificandul coloanei '%-.192s' este incorect" - rus "îÅËÏÒÒÅËÔÎÙÊ ÏÐÒÅÄÅÌÉÔÅÌØ ÓÔÏÌÂÃÁ ÄÌÑ ÓÔÏÌÂÃÁ '%-.192s'" - serbian "Pogrešan naziv kolone za kolonu '%-.192s'" - slo "Chyba v ¹pecifikácii poµa '%-.192s'" - spa "Especificador de columna erroneo para la columna '%-.192s'" - swe "Felaktigt kolumntyp för kolumn '%-.192s'" - ukr "îÅצÒÎÉÊ ÓÐÅÃÉƦËÁÔÏÒ ÓÔÏ×ÂÃÑ '%-.192s'" -ER_PARSE_ERROR 42000 s1009 - cze "%s bl-Bízko '%-.80s' na øádku %d" - dan "%s nær '%-.80s' på linje %d" - nla "%s bij '%-.80s' in regel %d" - eng "%s near '%-.80s' at line %d" - jps "%s : '%-.80s' •t‹ß : %d s–Ú", - est "%s '%-.80s' ligidal real %d" - fre "%s près de '%-.80s' à la ligne %d" - ger "%s bei '%-.80s' in Zeile %d" - greek "%s ðëçóßïí '%-.80s' óôç ãñáììÞ %d" - hun "A %s a '%-.80s'-hez kozeli a %d sorban" - ita "%s vicino a '%-.80s' linea %d" - jpn "%s : '%-.80s' ÉÕ¶á : %d ¹ÔÌÜ" - kor "'%s' ¿¡·¯ °°À¾´Ï´Ù. ('%-.80s' ¸í·É¾î ¶óÀÎ %d)" - nor "%s nær '%-.80s' på linje %d" - norwegian-ny "%s attmed '%-.80s' på line %d" - pol "%s obok '%-.80s' w linii %d" - por "%s próximo a '%-.80s' na linha %d" - rum "%s linga '%-.80s' pe linia %d" - rus "%s ÏËÏÌÏ '%-.80s' ÎÁ ÓÔÒÏËÅ %d" - serbian "'%s' u iskazu '%-.80s' na liniji %d" - slo "%s blízko '%-.80s' na riadku %d" - spa "%s cerca '%-.80s' en la linea %d" - swe "%s nära '%-.80s' på rad %d" - ukr "%s ¦ÌÑ '%-.80s' × ÓÔÒÏæ %d" -ER_EMPTY_QUERY 42000 - cze "V-Býsledek dotazu je prázdný" - dan "Forespørgsel var tom" - nla "Query was leeg" - eng "Query was empty" - jps "Query ‚ª‹ó‚Å‚·.", - est "Tühi päring" - fre "Query est vide" - ger "Leere Abfrage" - greek "Ôï åñþôçìá (query) ðïõ èÝóáôå Þôáí êåíü" - hun "Ures lekerdezes." - ita "La query e` vuota" - jpn "Query ¤¬¶õ¤Ç¤¹." - kor "Äõ¸®°á°ú°¡ ¾ø½À´Ï´Ù." - nor "Forespørsel var tom" - norwegian-ny "Førespurnad var tom" - pol "Zapytanie by³o puste" - por "Consulta (query) estava vazia" - rum "Query-ul a fost gol" - rus "úÁÐÒÏÓ ÏËÁÚÁÌÓÑ ÐÕÓÔÙÍ" - serbian "Upit je bio prazan" - slo "Výsledok po¾iadavky bol prázdny" - spa "La query estaba vacia" - swe "Frågan var tom" - ukr "ðÕÓÔÉÊ ÚÁÐÉÔ" -ER_NONUNIQ_TABLE 42000 S1009 - cze "Nejednozna-Bèná tabulka/alias: '%-.192s'" - dan "Tabellen/aliaset: '%-.192s' er ikke unikt" - nla "Niet unieke waarde tabel/alias: '%-.192s'" - eng "Not unique table/alias: '%-.192s'" - jps "'%-.192s' ‚͈êˆÓ‚Ì table/alias –¼‚Å‚Í‚ ‚è‚Ü‚¹‚ñ", - est "Ei ole unikaalne tabel/alias '%-.192s'" - fre "Table/alias: '%-.192s' non unique" - ger "Tabellenname/Alias '%-.192s' nicht eindeutig" - greek "Áäýíáôç ç áíåýñåóç unique table/alias: '%-.192s'" - hun "Nem egyedi tabla/alias: '%-.192s'" - ita "Tabella/alias non unico: '%-.192s'" - jpn "'%-.192s' ¤Ï°ì°Õ¤Î table/alias ̾¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó" - kor "Unique ÇÏÁö ¾ÊÀº Å×À̺í/alias: '%-.192s'" - nor "Ikke unikt tabell/alias: '%-.192s'" - norwegian-ny "Ikkje unikt tabell/alias: '%-.192s'" - pol "Tabela/alias nie s? unikalne: '%-.192s'" - por "Tabela/alias '%-.192s' não única" - rum "Tabela/alias: '%-.192s' nu este unic" - rus "ðÏ×ÔÏÒÑÀÝÁÑÓÑ ÔÁÂÌÉÃÁ/ÐÓÅ×ÄÏÎÉÍ '%-.192s'" - serbian "Tabela ili alias nisu bili jedinstveni: '%-.192s'" - slo "Nie jednoznaèná tabuµka/alias: '%-.192s'" - spa "Tabla/alias: '%-.192s' es no unica" - swe "Icke unikt tabell/alias: '%-.192s'" - ukr "îÅÕΦËÁÌØÎÁ ÔÁÂÌÉÃÑ/ÐÓÅ×ÄÏΦÍ: '%-.192s'" -ER_INVALID_DEFAULT 42000 S1009 - cze "Chybn-Bá defaultní hodnota pro '%-.192s'" - dan "Ugyldig standardværdi for '%-.192s'" - nla "Foutieve standaard waarde voor '%-.192s'" - eng "Invalid default value for '%-.192s'" - est "Vigane vaikeväärtus '%-.192s' jaoks" - fre "Valeur par défaut invalide pour '%-.192s'" - ger "Fehlerhafter Vorgabewert (DEFAULT) für '%-.192s'" - greek "ÅóöáëìÝíç ðñïêáèïñéóìÝíç ôéìÞ (default value) ãéá '%-.192s'" - hun "Ervenytelen ertek: '%-.192s'" - ita "Valore di default non valido per '%-.192s'" - kor "'%-.192s'ÀÇ À¯È¿ÇÏÁö ¸øÇÑ µðÆúÆ® °ªÀ» »ç¿ëÇϼ̽À´Ï´Ù." - nor "Ugyldig standardverdi for '%-.192s'" - norwegian-ny "Ugyldig standardverdi for '%-.192s'" - pol "Niew³a?ciwa warto?æ domy?lna dla '%-.192s'" - por "Valor padrão (default) inválido para '%-.192s'" - rum "Valoarea de default este invalida pentru '%-.192s'" - rus "îÅËÏÒÒÅËÔÎÏÅ ÚÎÁÞÅÎÉÅ ÐÏ ÕÍÏÌÞÁÎÉÀ ÄÌÑ '%-.192s'" - serbian "Loša default vrednost za '%-.192s'" - slo "Chybná implicitná hodnota pre '%-.192s'" - spa "Valor por defecto invalido para '%-.192s'" - swe "Ogiltigt DEFAULT värde för '%-.192s'" - ukr "îÅצÒÎÅ ÚÎÁÞÅÎÎÑ ÐÏ ÚÁÍÏ×ÞÕ×ÁÎÎÀ ÄÌÑ '%-.192s'" -ER_MULTIPLE_PRI_KEY 42000 S1009 - cze "Definov-Báno více primárních klíèù" - dan "Flere primærnøgler specificeret" - nla "Meerdere primaire zoeksleutels gedefinieerd" - eng "Multiple primary key defined" - jps "•¡”‚Ì primary key ‚ª’è‹`‚³‚ê‚Ü‚µ‚½", - est "Mitut primaarset võtit ei saa olla" - fre "Plusieurs clefs primaires définies" - ger "Mehrere Primärschlüssel (PRIMARY KEY) definiert" - greek "Ðåñéóóüôåñá áðü Ýíá primary key ïñßóôçêáí" - hun "Tobbszoros elsodleges kulcs definialas." - ita "Definite piu` chiave primarie" - jpn "Ê£¿ô¤Î primary key ¤¬ÄêµÁ¤µ¤ì¤Þ¤·¤¿" - kor "Multiple primary key°¡ Á¤ÀǵǾî ÀÖ½¿" - nor "Fleire primærnøkle spesifisert" - norwegian-ny "Fleire primærnyklar spesifisert" - pol "Zdefiniowano wiele kluczy podstawowych" - por "Definida mais de uma chave primária" - rum "Chei primare definite de mai multe ori" - rus "õËÁÚÁÎÏ ÎÅÓËÏÌØËÏ ÐÅÒ×ÉÞÎÙÈ ËÌÀÞÅÊ" - serbian "Definisani višestruki primarni kljuèevi" - slo "Zadefinovaných viac primárnych kµúèov" - spa "Multiples claves primarias definidas" - swe "Flera PRIMARY KEY använda" - ukr "ðÅÒ×ÉÎÎÏÇÏ ËÌÀÞÁ ×ÉÚÎÁÞÅÎÏ ÎÅÏÄÎÏÒÁÚÏ×Ï" -ER_TOO_MANY_KEYS 42000 S1009 - cze "Zad-Báno pøíli¹ mnoho klíèù, je povoleno nejvíce %d klíèù" - dan "For mange nøgler specificeret. Kun %d nøgler må bruges" - nla "Teveel zoeksleutels gedefinieerd. Maximaal zijn %d zoeksleutels toegestaan" - eng "Too many keys specified; max %d keys allowed" - jps "key ‚ÌŽw’肪‘½‚·‚¬‚Ü‚·. key ‚ÍÅ‘å %d ‚Ü‚Å‚Å‚·", - est "Liiga palju võtmeid. Maksimaalselt võib olla %d võtit" - fre "Trop de clefs sont définies. Maximum de %d clefs alloué" - ger "Zu viele Schlüssel definiert. Maximal %d Schlüssel erlaubt" - greek "ÐÜñá ðïëëÜ key ïñßóèçêáí. Ôï ðïëý %d åðéôñÝðïíôáé" - hun "Tul sok kulcs. Maximum %d kulcs engedelyezett." - ita "Troppe chiavi. Sono ammesse max %d chiavi" - jpn "key ¤Î»ØÄ꤬¿¤¹¤®¤Þ¤¹. key ¤ÏºÇÂç %d ¤Þ¤Ç¤Ç¤¹" - kor "³Ê¹« ¸¹Àº Å°°¡ Á¤ÀǵǾî ÀÖÀ¾´Ï´Ù.. ÃÖ´ë %dÀÇ Å°°¡ °¡´ÉÇÔ" - nor "For mange nøkler spesifisert. Maks %d nøkler tillatt" - norwegian-ny "For mange nykler spesifisert. Maks %d nyklar tillatt" - pol "Okre?lono zbyt wiele kluczy. Dostêpnych jest maksymalnie %d kluczy" - por "Especificadas chaves demais. O máximo permitido são %d chaves" - rum "Prea multe chei. Numarul de chei maxim este %d" - rus "õËÁÚÁÎÏ ÓÌÉÛËÏÍ ÍÎÏÇÏ ËÌÀÞÅÊ. òÁÚÒÅÛÁÅÔÓÑ ÕËÁÚÙ×ÁÔØ ÎÅ ÂÏÌÅÅ %d ËÌÀÞÅÊ" - serbian "Navedeno je previše kljuèeva. Maksimum %d kljuèeva je dozvoljeno" - slo "Zadaných ríli¹ veµa kµúèov. Najviac %d kµúèov je povolených" - spa "Demasiadas claves primarias declaradas. Un maximo de %d claves son permitidas" - swe "För många nycklar använda. Man får ha högst %d nycklar" - ukr "úÁÂÁÇÁÔÏ ËÌÀÞ¦× ÚÁÚÎÁÞÅÎÏ. äÏÚ×ÏÌÅÎÏ ÎŠ¦ÌØÛÅ %d ËÌÀÞ¦×" -ER_TOO_MANY_KEY_PARTS 42000 S1009 - cze "Zad-Báno pøíli¹ mnoho èást klíèù, je povoleno nejvíce %d èástí" - dan "For mange nøgledele specificeret. Kun %d dele må bruges" - nla "Teveel zoeksleutel onderdelen gespecificeerd. Maximaal %d onderdelen toegestaan" - eng "Too many key parts specified; max %d parts allowed" - est "Võti koosneb liiga paljudest osadest. Maksimaalselt võib olla %d osa" - fre "Trop de parties specifiées dans la clef. Maximum de %d parties" - ger "Zu viele Teilschlüssel definiert. Maximal %d Teilschlüssel erlaubt" - greek "ÐÜñá ðïëëÜ key parts ïñßóèçêáí. Ôï ðïëý %d åðéôñÝðïíôáé" - hun "Tul sok kulcsdarabot definialt. Maximum %d resz engedelyezett" - ita "Troppe parti di chiave specificate. Sono ammesse max %d parti" - kor "³Ê¹« ¸¹Àº Å° ºÎºÐ(parts)µéÀÌ Á¤ÀǵǾî ÀÖÀ¾´Ï´Ù.. ÃÖ´ë %d ºÎºÐÀÌ °¡´ÉÇÔ" - nor "For mange nøkkeldeler spesifisert. Maks %d deler tillatt" - norwegian-ny "For mange nykkeldelar spesifisert. Maks %d delar tillatt" - pol "Okre?lono zbyt wiele czê?ci klucza. Dostêpnych jest maksymalnie %d czê?ci" - por "Especificadas partes de chave demais. O máximo permitido são %d partes" - rum "Prea multe chei. Numarul de chei maxim este %d" - rus "õËÁÚÁÎÏ ÓÌÉÛËÏÍ ÍÎÏÇÏ ÞÁÓÔÅÊ ÓÏÓÔÁ×ÎÏÇÏ ËÌÀÞÁ. òÁÚÒÅÛÁÅÔÓÑ ÕËÁÚÙ×ÁÔØ ÎÅ ÂÏÌÅÅ %d ÞÁÓÔÅÊ" - serbian "Navedeno je previše delova kljuèa. Maksimum %d delova je dozvoljeno" - slo "Zadaných ríli¹ veµa èastí kµúèov. Je povolených najviac %d èastí" - spa "Demasiadas partes de clave declaradas. Un maximo de %d partes son permitidas" - swe "För många nyckeldelar använda. Man får ha högst %d nyckeldelar" - ukr "úÁÂÁÇÁÔÏ ÞÁÓÔÉÎ ËÌÀÞÁ ÚÁÚÎÁÞÅÎÏ. äÏÚ×ÏÌÅÎÏ ÎŠ¦ÌØÛÅ %d ÞÁÓÔÉÎ" -ER_TOO_LONG_KEY 42000 S1009 - cze "Zadan-Bý klíè byl pøíli¹ dlouhý, nejvìt¹í délka klíèe je %d" - dan "Specificeret nøgle var for lang. Maksimal nøglelængde er %d" - nla "Gespecificeerde zoeksleutel was te lang. De maximale lengte is %d" - eng "Specified key was too long; max key length is %d bytes" - jps "key ‚ª’·‚·‚¬‚Ü‚·. key ‚Ì’·‚³‚ÍÅ‘å %d ‚Å‚·", - est "Võti on liiga pikk. Maksimaalne võtmepikkus on %d" - fre "La clé est trop longue. Longueur maximale: %d" - ger "Schlüssel ist zu lang. Die maximale Schlüssellänge beträgt %d" - greek "Ôï êëåéäß ðïõ ïñßóèçêå åßíáé ðïëý ìåãÜëï. Ôï ìÝãéóôï ìÞêïò åßíáé %d" - hun "A megadott kulcs tul hosszu. Maximalis kulcshosszusag: %d" - ita "La chiave specificata e` troppo lunga. La max lunghezza della chiave e` %d" - jpn "key ¤¬Ä¹¤¹¤®¤Þ¤¹. key ¤ÎŤµ¤ÏºÇÂç %d ¤Ç¤¹" - kor "Á¤ÀÇµÈ Å°°¡ ³Ê¹« ±é´Ï´Ù. ÃÖ´ë Å°ÀÇ ±æÀÌ´Â %dÀÔ´Ï´Ù." - nor "Spesifisert nøkkel var for lang. Maks nøkkellengde er is %d" - norwegian-ny "Spesifisert nykkel var for lang. Maks nykkellengde er %d" - pol "Zdefinowany klucz jest zbyt d³ugi. Maksymaln? d³ugo?ci? klucza jest %d" - por "Chave especificada longa demais. O comprimento de chave máximo permitido é %d" - rum "Cheia specificata este prea lunga. Marimea maxima a unei chei este de %d" - rus "õËÁÚÁÎ ÓÌÉÛËÏÍ ÄÌÉÎÎÙÊ ËÌÀÞ. íÁËÓÉÍÁÌØÎÁÑ ÄÌÉÎÁ ËÌÀÞÁ ÓÏÓÔÁ×ÌÑÅÔ %d ÂÁÊÔ" - serbian "Navedeni kljuè je predug. Maksimalna dužina kljuèa je %d" - slo "Zadaný kµúè je príli¹ dlhý, najväè¹ia då¾ka kµúèa je %d" - spa "Declaracion de clave demasiado larga. La maxima longitud de clave es %d" - swe "För lång nyckel. Högsta tillåtna nyckellängd är %d" - ukr "úÁÚÎÁÞÅÎÉÊ ËÌÀÞ ÚÁÄÏ×ÇÉÊ. îÁʦÌØÛÁ ÄÏ×ÖÉÎÁ ËÌÀÞÁ %d ÂÁÊÔ¦×" -ER_KEY_COLUMN_DOES_NOT_EXITS 42000 S1009 - cze "Kl-Bíèový sloupec '%-.192s' v tabulce neexistuje" - dan "Nøglefeltet '%-.192s' eksisterer ikke i tabellen" - nla "Zoeksleutel kolom '%-.192s' bestaat niet in tabel" - eng "Key column '%-.192s' doesn't exist in table" - jps "Key column '%-.192s' ‚ªƒe[ƒuƒ‹‚É‚ ‚è‚Ü‚¹‚ñ.", - est "Võtme tulp '%-.192s' puudub tabelis" - fre "La clé '%-.192s' n'existe pas dans la table" - ger "In der Tabelle gibt es kein Schlüsselfeld '%-.192s'" - greek "Ôï ðåäßï êëåéäß '%-.192s' äåí õðÜñ÷åé óôïí ðßíáêá" - hun "A(z) '%-.192s'kulcsoszlop nem letezik a tablaban" - ita "La colonna chiave '%-.192s' non esiste nella tabella" - jpn "Key column '%-.192s' ¤¬¥Æ¡¼¥Ö¥ë¤Ë¤¢¤ê¤Þ¤»¤ó." - kor "Key Ä®·³ '%-.192s'´Â Å×ÀÌºí¿¡ Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù." - nor "Nøkkel felt '%-.192s' eksiterer ikke i tabellen" - norwegian-ny "Nykkel kolonne '%-.192s' eksiterar ikkje i tabellen" - pol "Kolumna '%-.192s' zdefiniowana w kluczu nie istnieje w tabeli" - por "Coluna chave '%-.192s' não existe na tabela" - rum "Coloana cheie '%-.192s' nu exista in tabela" - rus "ëÌÀÞÅ×ÏÊ ÓÔÏÌÂÅà '%-.192s' × ÔÁÂÌÉÃÅ ÎÅ ÓÕÝÅÓÔ×ÕÅÔ" - serbian "Kljuèna kolona '%-.192s' ne postoji u tabeli" - slo "Kµúèový ståpec '%-.192s' v tabuµke neexistuje" - spa "La columna clave '%-.192s' no existe en la tabla" - swe "Nyckelkolumn '%-.192s' finns inte" - ukr "ëÌÀÞÏ×ÉÊ ÓÔÏ×ÂÅÃØ '%-.192s' ÎÅ ¦ÓÎÕ¤ Õ ÔÁÂÌÉæ" -ER_BLOB_USED_AS_KEY 42000 S1009 - cze "Blob sloupec '%-.192s' nem-Bù¾e být pou¾it jako klíè" - dan "BLOB feltet '%-.192s' kan ikke bruges ved specifikation af indeks" - nla "BLOB kolom '%-.192s' kan niet gebruikt worden bij zoeksleutel specificatie" - eng "BLOB column '%-.192s' can't be used in key specification with the used table type" - est "BLOB-tüüpi tulpa '%-.192s' ei saa kasutada võtmena" - fre "Champ BLOB '%-.192s' ne peut être utilisé dans une clé" - ger "BLOB-Feld '%-.192s' kann beim verwendeten Tabellentyp nicht als Schlüssel verwendet werden" - greek "Ðåäßï ôýðïõ Blob '%-.192s' äåí ìðïñåß íá ÷ñçóéìïðïéçèåß óôïí ïñéóìü åíüò êëåéäéïý (key specification)" - hun "Blob objektum '%-.192s' nem hasznalhato kulcskent" - ita "La colonna BLOB '%-.192s' non puo` essere usata nella specifica della chiave" - kor "BLOB Ä®·³ '%-.192s'´Â Å° Á¤ÀÇ¿¡¼ »ç¿ëµÉ ¼ö ¾ø½À´Ï´Ù." - nor "Blob felt '%-.192s' kan ikke brukes ved spesifikasjon av nøkler" - norwegian-ny "Blob kolonne '%-.192s' kan ikkje brukast ved spesifikasjon av nyklar" - pol "Kolumna typu Blob '%-.192s' nie mo¿e byæ u¿yta w specyfikacji klucza" - por "Coluna BLOB '%-.192s' não pode ser utilizada na especificação de chave para o tipo de tabela usado" - rum "Coloana de tip BLOB '%-.192s' nu poate fi folosita in specificarea cheii cu tipul de tabla folosit" - rus "óÔÏÌÂÅà ÔÉÐÁ BLOB '%-.192s' ÎÅ ÍÏÖÅÔ ÂÙÔØ ÉÓÐÏÌØÚÏ×ÁÎ ËÁË ÚÎÁÞÅÎÉÅ ËÌÀÞÁ × ÔÁÂÌÉÃÅ ÔÁËÏÇÏ ÔÉÐÁ" - serbian "BLOB kolona '%-.192s' ne može biti upotrebljena za navoðenje kljuèa sa tipom tabele koji se trenutno koristi" - slo "Blob pole '%-.192s' nemô¾e by» pou¾ité ako kµúè" - spa "La columna Blob '%-.192s' no puede ser usada en una declaracion de clave" - swe "En BLOB '%-.192s' kan inte vara nyckel med den använda tabelltypen" - ukr "BLOB ÓÔÏ×ÂÅÃØ '%-.192s' ÎÅ ÍÏÖÅ ÂÕÔÉ ×ÉËÏÒÉÓÔÁÎÉÊ Õ ×ÉÚÎÁÞÅÎΦ ËÌÀÞÁ × ÃØÏÍÕ ÔÉЦ ÔÁÂÌÉæ" -ER_TOO_BIG_FIELDLENGTH 42000 S1009 - cze "P-Bøíli¹ velká délka sloupce '%-.192s' (nejvíce %lu). Pou¾ijte BLOB" - dan "For stor feltlængde for kolonne '%-.192s' (maks = %lu). Brug BLOB i stedet" - nla "Te grote kolomlengte voor '%-.192s' (max = %lu). Maak hiervoor gebruik van het type BLOB" - eng "Column length too big for column '%-.192s' (max = %lu); use BLOB or TEXT instead" - jps "column '%-.192s' ‚Í,Šm•Û‚·‚é column ‚Ì‘å‚«‚³‚ª‘½‚·‚¬‚Ü‚·. (Å‘å %lu ‚Ü‚Å). BLOB ‚ð‚©‚í‚è‚ÉŽg—p‚µ‚Ä‚‚¾‚³‚¢.", - est "Tulba '%-.192s' pikkus on liiga pikk (maksimaalne pikkus: %lu). Kasuta BLOB väljatüüpi" - fre "Champ '%-.192s' trop long (max = %lu). Utilisez un BLOB" - ger "Feldlänge für Feld '%-.192s' zu groß (maximal %lu). BLOB- oder TEXT-Spaltentyp verwenden!" - greek "Ðïëý ìåãÜëï ìÞêïò ãéá ôï ðåäßï '%-.192s' (max = %lu). Ðáñáêáëþ ÷ñçóéìïðïéåßóôå ôïí ôýðï BLOB" - hun "A(z) '%-.192s' oszlop tul hosszu. (maximum = %lu). Hasznaljon BLOB tipust inkabb." - ita "La colonna '%-.192s' e` troppo grande (max=%lu). Utilizza un BLOB." - jpn "column '%-.192s' ¤Ï,³ÎÊݤ¹¤ë column ¤ÎÂ礤µ¤¬Â¿¤¹¤®¤Þ¤¹. (ºÇÂç %lu ¤Þ¤Ç). BLOB ¤ò¤«¤ï¤ê¤Ë»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤." - kor "Ä®·³ '%-.192s'ÀÇ Ä®·³ ±æÀÌ°¡ ³Ê¹« ±é´Ï´Ù (ÃÖ´ë = %lu). ´ë½Å¿¡ BLOB¸¦ »ç¿ëÇϼ¼¿ä." - nor "For stor nøkkellengde for kolonne '%-.192s' (maks = %lu). Bruk BLOB istedenfor" - norwegian-ny "For stor nykkellengde for felt '%-.192s' (maks = %lu). Bruk BLOB istadenfor" - pol "Zbyt du¿a d³ugo?æ kolumny '%-.192s' (maks. = %lu). W zamian u¿yj typu BLOB" - por "Comprimento da coluna '%-.192s' grande demais (max = %lu); use BLOB em seu lugar" - rum "Lungimea coloanei '%-.192s' este prea lunga (maximum = %lu). Foloseste BLOB mai bine" - rus "óÌÉÛËÏÍ ÂÏÌØÛÁÑ ÄÌÉÎÁ ÓÔÏÌÂÃÁ '%-.192s' (ÍÁËÓÉÍÕÍ = %lu). éÓÐÏÌØÚÕÊÔÅ ÔÉÐ BLOB ÉÌÉ TEXT ×ÍÅÓÔÏ ÔÅËÕÝÅÇÏ" - serbian "Previše podataka za kolonu '%-.192s' (maksimum je %lu). Upotrebite BLOB polje" - slo "Príli¹ veµká då¾ka pre pole '%-.192s' (maximum = %lu). Pou¾ite BLOB" - spa "Longitud de columna demasiado grande para la columna '%-.192s' (maximo = %lu).Usar BLOB en su lugar" - swe "För stor kolumnlängd angiven för '%-.192s' (max= %lu). Använd en BLOB instället" - ukr "úÁÄÏ×ÇÁ ÄÏ×ÖÉÎÁ ÓÔÏ×ÂÃÑ '%-.192s' (max = %lu). ÷ÉËÏÒÉÓÔÁÊÔÅ ÔÉÐ BLOB" -ER_WRONG_AUTO_KEY 42000 S1009 - cze "M-Bù¾ete mít pouze jedno AUTO pole a to musí být definováno jako klíè" - dan "Der kan kun specificeres eet AUTO_INCREMENT-felt, og det skal være indekseret" - nla "Er kan slechts 1 autofield zijn en deze moet als zoeksleutel worden gedefinieerd." - eng "Incorrect table definition; there can be only one auto column and it must be defined as a key" - jps "ƒe[ƒuƒ‹‚Ì’è‹`‚ªˆá‚¢‚Ü‚·; there can be only one auto column and it must be defined as a key", - est "Vigane tabelikirjeldus; Tabelis tohib olla üks auto_increment tüüpi tulp ning see peab olema defineeritud võtmena" - fre "Un seul champ automatique est permis et il doit être indexé" - ger "Falsche Tabellendefinition. Es darf nur eine AUTO_INCREMENT-Spalte geben, und diese muss als Schlüssel definiert werden" - greek "Ìðïñåß íá õðÜñ÷åé ìüíï Ýíá auto field êáé ðñÝðåé íá Ý÷åé ïñéóèåß óáí key" - hun "Csak egy auto mezo lehetseges, es azt kulcskent kell definialni." - ita "Puo` esserci solo un campo AUTO e deve essere definito come chiave" - jpn "¥Æ¡¼¥Ö¥ë¤ÎÄêµÁ¤¬°ã¤¤¤Þ¤¹; there can be only one auto column and it must be defined as a key" - kor "ºÎÁ¤È®ÇÑ Å×À̺í Á¤ÀÇ; Å×À̺íÀº ÇϳªÀÇ auto Ä®·³ÀÌ Á¸ÀçÇÏ°í Å°·Î Á¤ÀǵǾîÁ®¾ß ÇÕ´Ï´Ù." - nor "Bare ett auto felt kan være definert som nøkkel." - norwegian-ny "Bare eitt auto felt kan være definert som nøkkel." - pol "W tabeli mo¿e byæ tylko jedno pole auto i musi ono byæ zdefiniowane jako klucz" - por "Definição incorreta de tabela. Somente é permitido um único campo auto-incrementado e ele tem que ser definido como chave" - rum "Definitia tabelei este incorecta; Nu pot fi mai mult de o singura coloana de tip auto si aceasta trebuie definita ca cheie" - rus "îÅËÏÒÒÅËÔÎÏÅ ÏÐÒÅÄÅÌÅÎÉÅ ÔÁÂÌÉÃÙ: ÍÏÖÅÔ ÓÕÝÅÓÔ×Ï×ÁÔØ ÔÏÌØËÏ ÏÄÉÎ Á×ÔÏÉÎËÒÅÍÅÎÔÎÙÊ ÓÔÏÌÂÅÃ, É ÏÎ ÄÏÌÖÅÎ ÂÙÔØ ÏÐÒÅÄÅÌÅÎ ËÁË ËÌÀÞ" - serbian "Pogrešna definicija tabele; U tabeli može postojati samo jedna 'AUTO' kolona i ona mora biti istovremeno definisana kao kolona kljuèa" - slo "Mô¾ete ma» iba jedno AUTO pole a to musí by» definované ako kµúè" - spa "Puede ser solamente un campo automatico y este debe ser definido como una clave" - swe "Det får finnas endast ett AUTO_INCREMENT-fält och detta måste vara en nyckel" - ukr "îÅצÒÎÅ ×ÉÚÎÁÞÅÎÎÑ ÔÁÂÌÉæ; íÏÖÅ ÂÕÔÉ ÌÉÛÅ ÏÄÉÎ Á×ÔÏÍÁÔÉÞÎÉÊ ÓÔÏ×ÂÅÃØ, ÝÏ ÐÏ×ÉÎÅÎ ÂÕÔÉ ×ÉÚÎÁÞÅÎÉÊ ÑË ËÌÀÞ" -ER_READY - cze "%s: p-Bøipraven na spojení\nVersion: '%s' socket: '%s' port: %d"" - dan "%s: klar til tilslutninger\nVersion: '%s' socket: '%s' port: %d"" - nla "%s: klaar voor verbindingen\nVersion: '%s' socket: '%s' port: %d"" - eng "%s: ready for connections.\nVersion: '%s' socket: '%s' port: %d" - jps "%s: €”õŠ®—¹\nVersion: '%s' socket: '%s' port: %d"", - est "%s: ootab ühendusi\nVersion: '%s' socket: '%s' port: %d"" - fre "%s: Prêt pour des connexions\nVersion: '%s' socket: '%s' port: %d"" - ger "%s: Bereit für Verbindungen.\nVersion: '%s' Socket: '%s' Port: %d" - greek "%s: óå áíáìïíÞ óõíäÝóåùí\nVersion: '%s' socket: '%s' port: %d"" - hun "%s: kapcsolatra kesz\nVersion: '%s' socket: '%s' port: %d"" - ita "%s: Pronto per le connessioni\nVersion: '%s' socket: '%s' port: %d"" - jpn "%s: ½àÈ÷´°Î»\nVersion: '%s' socket: '%s' port: %d"" - kor "%s: ¿¬°á ÁغñÁßÀÔ´Ï´Ù\nVersion: '%s' socket: '%s' port: %d"" - nor "%s: klar for tilkoblinger\nVersion: '%s' socket: '%s' port: %d"" - norwegian-ny "%s: klar for tilkoblingar\nVersion: '%s' socket: '%s' port: %d"" - pol "%s: gotowe do po³?czenia\nVersion: '%s' socket: '%s' port: %d"" - por "%s: Pronto para conexões\nVersion: '%s' socket: '%s' port: %d"" - rum "%s: sint gata pentru conectii\nVersion: '%s' socket: '%s' port: %d"" - rus "%s: çÏÔÏ× ÐÒÉÎÉÍÁÔØ ÓÏÅÄÉÎÅÎÉÑ.\n÷ÅÒÓÉÑ: '%s' ÓÏËÅÔ: '%s' ÐÏÒÔ: %d" - serbian "%s: Spreman za konekcije\nVersion: '%s' socket: '%s' port: %d"" - slo "%s: pripravený na spojenie\nVersion: '%s' socket: '%s' port: %d"" - spa "%s: preparado para conexiones\nVersion: '%s' socket: '%s' port: %d"" - swe "%s: klar att ta emot klienter\nVersion: '%s' socket: '%s' port: %d"" - ukr "%s: çÏÔÏ×ÉÊ ÄÌÑ Ú'¤ÄÎÁÎØ!\nVersion: '%s' socket: '%s' port: %d"" -ER_NORMAL_SHUTDOWN - cze "%s: norm-Bální ukonèení\n" - dan "%s: Normal nedlukning\n" - nla "%s: Normaal afgesloten \n" - eng "%s: Normal shutdown\n" - est "%s: MySQL lõpetas\n" - fre "%s: Arrêt normal du serveur\n" - ger "%s: Normal heruntergefahren\n" - greek "%s: ÖõóéïëïãéêÞ äéáäéêáóßá shutdown\n" - hun "%s: Normal leallitas\n" - ita "%s: Shutdown normale\n" - kor "%s: Á¤»óÀûÀÎ shutdown\n" - nor "%s: Normal avslutning\n" - norwegian-ny "%s: Normal nedkopling\n" - pol "%s: Standardowe zakoñczenie dzia³ania\n" - por "%s: 'Shutdown' normal\n" - rum "%s: Terminare normala\n" - rus "%s: ëÏÒÒÅËÔÎÁÑ ÏÓÔÁÎÏ×ËÁ\n" - serbian "%s: Normalno gašenje\n" - slo "%s: normálne ukonèenie\n" - spa "%s: Apagado normal\n" - swe "%s: Normal avslutning\n" - ukr "%s: îÏÒÍÁÌØÎÅ ÚÁ×ÅÒÛÅÎÎÑ\n" -ER_GOT_SIGNAL - cze "%s: p-Bøijat signal %d, konèím\n" - dan "%s: Fangede signal %d. Afslutter!!\n" - nla "%s: Signaal %d. Systeem breekt af!\n" - eng "%s: Got signal %d. Aborting!\n" - jps "%s: Got signal %d. ’†’f!\n", - est "%s: sain signaali %d. Lõpetan!\n" - fre "%s: Reçu le signal %d. Abandonne!\n" - ger "%s: Signal %d erhalten. Abbruch!\n" - greek "%s: ÅëÞöèç ôï ìÞíõìá %d. Ç äéáäéêáóßá åãêáôáëåßðåôáé!\n" - hun "%s: %d jelzes. Megszakitva!\n" - ita "%s: Ricevuto segnale %d. Interruzione!\n" - jpn "%s: Got signal %d. ÃæÃÇ!\n" - kor "%s: %d ½ÅÈ£°¡ µé¾î¿ÔÀ½. ÁßÁö!\n" - nor "%s: Oppdaget signal %d. Avslutter!\n" - norwegian-ny "%s: Oppdaga signal %d. Avsluttar!\n" - pol "%s: Otrzymano sygna³ %d. Koñczenie dzia³ania!\n" - por "%s: Obteve sinal %d. Abortando!\n" - rum "%s: Semnal %d obtinut. Aborting!\n" - rus "%s: ðÏÌÕÞÅÎ ÓÉÇÎÁÌ %d. ðÒÅËÒÁÝÁÅÍ!\n" - serbian "%s: Dobio signal %d. Prekidam!\n" - slo "%s: prijatý signál %d, ukonèenie (Abort)!\n" - spa "%s: Recibiendo signal %d. Abortando!\n" - swe "%s: Fick signal %d. Avslutar!\n" - ukr "%s: ïÔÒÉÍÁÎÏ ÓÉÇÎÁÌ %d. ðÅÒÅÒÉ×ÁÀÓØ!\n" -ER_SHUTDOWN_COMPLETE - cze "%s: ukon-Bèení práce hotovo\n" - dan "%s: Server lukket\n" - nla "%s: Afsluiten afgerond\n" - eng "%s: Shutdown complete\n" - jps "%s: Shutdown Š®—¹\n", - est "%s: Lõpp\n" - fre "%s: Arrêt du serveur terminé\n" - ger "%s: Herunterfahren beendet\n" - greek "%s: Ç äéáäéêáóßá Shutdown ïëïêëçñþèçêå\n" - hun "%s: A leallitas kesz\n" - ita "%s: Shutdown completato\n" - jpn "%s: Shutdown ´°Î»\n" - kor "%s: Shutdown ÀÌ ¿Ï·áµÊ!\n" - nor "%s: Avslutning komplett\n" - norwegian-ny "%s: Nedkopling komplett\n" - pol "%s: Zakoñczenie dzia³ania wykonane\n" - por "%s: 'Shutdown' completo\n" - rum "%s: Terminare completa\n" - rus "%s: ïÓÔÁÎÏ×ËÁ ÚÁ×ÅÒÛÅÎÁ\n" - serbian "%s: Gašenje završeno\n" - slo "%s: práca ukonèená\n" - spa "%s: Apagado completado\n" - swe "%s: Avslutning klar\n" - ukr "%s: òÏÂÏÔÕ ÚÁ×ÅÒÛÅÎÏ\n" -ER_FORCING_CLOSE 08S01 - cze "%s: n-Básilné uzavøení threadu %ld u¾ivatele '%-.48s'\n" - dan "%s: Forceret nedlukning af tråd: %ld bruger: '%-.48s'\n" - nla "%s: Afsluiten afgedwongen van thread %ld gebruiker: '%-.48s'\n" - eng "%s: Forcing close of thread %ld user: '%-.48s'\n" - jps "%s: ƒXƒŒƒbƒh %ld ‹§I—¹ user: '%-.48s'\n", - est "%s: Sulgen jõuga lõime %ld kasutaja: '%-.48s'\n" - fre "%s: Arrêt forcé de la tâche (thread) %ld utilisateur: '%-.48s'\n" - ger "%s: Thread %ld zwangsweise beendet. Benutzer: '%-.48s'\n" - greek "%s: Ôï thread èá êëåßóåé %ld user: '%-.48s'\n" - hun "%s: A(z) %ld thread kenyszeritett zarasa. Felhasznalo: '%-.48s'\n" - ita "%s: Forzata la chiusura del thread %ld utente: '%-.48s'\n" - jpn "%s: ¥¹¥ì¥Ã¥É %ld ¶¯À©½ªÎ» user: '%-.48s'\n" - kor "%s: thread %ldÀÇ °Á¦ Á¾·á user: '%-.48s'\n" - nor "%s: Påtvinget avslutning av tråd %ld bruker: '%-.48s'\n" - norwegian-ny "%s: Påtvinga avslutning av tråd %ld brukar: '%-.48s'\n" - pol "%s: Wymuszenie zamkniêcia w?tku %ld u¿ytkownik: '%-.48s'\n" - por "%s: Forçando finalização da 'thread' %ld - usuário '%-.48s'\n" - rum "%s: Terminare fortata a thread-ului %ld utilizatorului: '%-.48s'\n" - rus "%s: ðÒÉÎÕÄÉÔÅÌØÎÏ ÚÁËÒÙ×ÁÅÍ ÐÏÔÏË %ld ÐÏÌØÚÏ×ÁÔÅÌÑ: '%-.48s'\n" - serbian "%s: Usiljeno gašenje thread-a %ld koji pripada korisniku: '%-.48s'\n" - slo "%s: násilné ukonèenie vlákna %ld u¾ívateµa '%-.48s'\n" - spa "%s: Forzando a cerrar el thread %ld usuario: '%-.48s'\n" - swe "%s: Stänger av tråd %ld; användare: '%-.48s'\n" - ukr "%s: ðÒÉÓËÏÒÀÀ ÚÁËÒÉÔÔÑ Ç¦ÌËÉ %ld ËÏÒÉÓÔÕ×ÁÞÁ: '%-.48s'\n" -ER_IPSOCK_ERROR 08S01 - cze "Nemohu vytvo-Bøit IP socket" - dan "Kan ikke oprette IP socket" - nla "Kan IP-socket niet openen" - eng "Can't create IP socket" - jps "IP socket ‚ªì‚ê‚Ü‚¹‚ñ", - est "Ei suuda luua IP socketit" - fre "Ne peut créer la connexion IP (socket)" - ger "Kann IP-Socket nicht erzeugen" - greek "Äåí åßíáé äõíáôÞ ç äçìéïõñãßá IP socket" - hun "Az IP socket nem hozhato letre" - ita "Impossibile creare il socket IP" - jpn "IP socket ¤¬ºî¤ì¤Þ¤»¤ó" - kor "IP ¼ÒÄÏÀ» ¸¸µéÁö ¸øÇß½À´Ï´Ù." - nor "Kan ikke opprette IP socket" - norwegian-ny "Kan ikkje opprette IP socket" - pol "Nie mo¿na stworzyæ socket'u IP" - por "Não pode criar o soquete IP" - rum "Nu pot crea IP socket" - rus "îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ IP-ÓÏËÅÔ" - serbian "Ne mogu da kreiram IP socket" - slo "Nemô¾em vytvori» IP socket" - spa "No puedo crear IP socket" - swe "Kan inte skapa IP-socket" - ukr "îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ IP ÒÏÚ'¤Í" -ER_NO_SUCH_INDEX 42S12 S1009 - cze "Tabulka '%-.192s' nem-Bá index odpovídající CREATE INDEX. Vytvoøte tabulku znovu" - dan "Tabellen '%-.192s' har ikke den nøgle, som blev brugt i CREATE INDEX. Genopret tabellen" - nla "Tabel '%-.192s' heeft geen INDEX zoals deze gemaakt worden met CREATE INDEX. Maak de tabel opnieuw" - eng "Table '%-.192s' has no index like the one used in CREATE INDEX; recreate the table" - jps "Table '%-.192s' ‚Í‚»‚̂悤‚È index ‚ðŽ‚Á‚Ä‚¢‚Ü‚¹‚ñ(CREATE INDEX ŽÀsŽž‚ÉŽw’肳‚ê‚Ä‚¢‚Ü‚¹‚ñ). ƒe[ƒuƒ‹‚ðì‚è’¼‚µ‚Ä‚‚¾‚³‚¢", - est "Tabelil '%-.192s' puuduvad võtmed. Loo tabel uuesti" - fre "La table '%-.192s' n'a pas d'index comme celle utilisée dans CREATE INDEX. Recréez la table" - ger "Tabelle '%-.192s' besitzt keinen wie den in CREATE INDEX verwendeten Index. Tabelle neu anlegen" - greek "Ï ðßíáêáò '%-.192s' äåí Ý÷åé åõñåôÞñéï (index) óáí áõôü ðïõ ÷ñçóéìïðïéåßôå óôçí CREATE INDEX. Ðáñáêáëþ, îáíáäçìéïõñãÞóôå ôïí ðßíáêá" - hun "A(z) '%-.192s' tablahoz nincs meg a CREATE INDEX altal hasznalt index. Alakitsa at a tablat" - ita "La tabella '%-.192s' non ha nessun indice come quello specificatato dalla CREATE INDEX. Ricrea la tabella" - jpn "Table '%-.192s' ¤Ï¤½¤Î¤è¤¦¤Ê index ¤ò»ý¤Ã¤Æ¤¤¤Þ¤»¤ó(CREATE INDEX ¼Â¹Ô»þ¤Ë»ØÄꤵ¤ì¤Æ¤¤¤Þ¤»¤ó). ¥Æ¡¼¥Ö¥ë¤òºî¤êľ¤·¤Æ¤¯¤À¤µ¤¤" - kor "Å×À̺í '%-.192s'´Â À妽º¸¦ ¸¸µéÁö ¾Ê¾Ò½À´Ï´Ù. alter Å×À̺í¸í·ÉÀ» ÀÌ¿ëÇÏ¿© Å×À̺íÀ» ¼öÁ¤Çϼ¼¿ä..." - nor "Tabellen '%-.192s' har ingen index som den som er brukt i CREATE INDEX. Gjenopprett tabellen" - norwegian-ny "Tabellen '%-.192s' har ingen index som den som er brukt i CREATE INDEX. Oprett tabellen på nytt" - pol "Tabela '%-.192s' nie ma indeksu takiego jak w CREATE INDEX. Stwórz tabelê" - por "Tabela '%-.192s' não possui um índice como o usado em CREATE INDEX. Recrie a tabela" - rum "Tabela '%-.192s' nu are un index ca acela folosit in CREATE INDEX. Re-creeaza tabela" - rus "÷ ÔÁÂÌÉÃÅ '%-.192s' ÎÅÔ ÔÁËÏÇÏ ÉÎÄÅËÓÁ, ËÁË × CREATE INDEX. óÏÚÄÁÊÔÅ ÔÁÂÌÉÃÕ ÚÁÎÏ×Ï" - serbian "Tabela '%-.192s' nema isti indeks kao onaj upotrebljen pri komandi 'CREATE INDEX'. Napravite tabelu ponovo" - slo "Tabuµka '%-.192s' nemá index zodpovedajúci CREATE INDEX. Vytvorte tabulku znova" - spa "La tabla '%-.192s' no tiene indice como el usado en CREATE INDEX. Crea de nuevo la tabla" - swe "Tabellen '%-.192s' har inget index som motsvarar det angivna i CREATE INDEX. Skapa om tabellen" - ukr "ôÁÂÌÉÃÑ '%-.192s' ÍÁ¤ ¦ÎÄÅËÓ, ÝÏ ÎÅ ÓЦ×ÐÁÄÁ¤ Ú ×ËÁÚÁÎÎÉÍ Õ CREATE INDEX. óÔ×ÏÒ¦ÔØ ÔÁÂÌÉÃÀ ÚÎÏ×Õ" -ER_WRONG_FIELD_TERMINATORS 42000 S1009 - cze "Argument separ-Bátoru polo¾ek nebyl oèekáván. Pøeètìte si manuál" - dan "Felt adskiller er ikke som forventet, se dokumentationen" - nla "De argumenten om velden te scheiden zijn anders dan verwacht. Raadpleeg de handleiding" - eng "Field separator argument is not what is expected; check the manual" - est "Väljade eraldaja erineb oodatust. Tutvu kasutajajuhendiga" - fre "Séparateur de champs inconnu. Vérifiez dans le manuel" - ger "Feldbegrenzer-Argument ist nicht in der erwarteten Form. Bitte im Handbuch nachlesen" - greek "Ï äéá÷ùñéóôÞò ðåäßùí äåí åßíáé áõôüò ðïõ áíáìåíüôáí. Ðáñáêáëþ áíáôñÝîôå óôï manual" - hun "A mezoelvalaszto argumentumok nem egyeznek meg a varttal. Nezze meg a kezikonyvben!" - ita "L'argomento 'Field separator' non e` quello atteso. Controlla il manuale" - kor "ÇÊµå ±¸ºÐÀÚ ÀμöµéÀÌ ¿ÏÀüÇÏÁö ¾Ê½À´Ï´Ù. ¸Þ´º¾óÀ» ã¾Æ º¸¼¼¿ä." - nor "Felt skiller argumentene er ikke som forventet, se dokumentasjonen" - norwegian-ny "Felt skiljer argumenta er ikkje som venta, sjå dokumentasjonen" - pol "Nie oczekiwano separatora. Sprawd¥ podrêcznik" - por "Argumento separador de campos não é o esperado. Cheque o manual" - rum "Argumentul pentru separatorul de cimpuri este diferit de ce ma asteptam. Verifica manualul" - rus "áÒÇÕÍÅÎÔ ÒÁÚÄÅÌÉÔÅÌÑ ÐÏÌÅÊ - ÎÅ ÔÏÔ, ËÏÔÏÒÙÊ ÏÖÉÄÁÌÓÑ. ïÂÒÁÝÁÊÔÅÓØ Ë ÄÏËÕÍÅÎÔÁÃÉÉ" - serbian "Argument separatora polja nije ono što se oèekivalo. Proverite uputstvo MySQL server-a" - slo "Argument oddeµovaè polí nezodpovedá po¾iadavkám. Skontrolujte v manuáli" - spa "Los separadores de argumentos del campo no son los especificados. Comprueba el manual" - swe "Fältseparatorerna är vad som förväntades. Kontrollera mot manualen" - ukr "èÉÂÎÉÊ ÒÏÚĦÌÀ×ÁÞ ÐÏ̦×. ðÏÞÉÔÁÊÔÅ ÄÏËÕÍÅÎÔÁæÀ" -ER_BLOBS_AND_NO_TERMINATED 42000 S1009 - cze "Nen-Bí mo¾né pou¾ít pevný rowlength s BLOBem. Pou¾ijte 'fields terminated by'." - dan "Man kan ikke bruge faste feltlængder med BLOB. Brug i stedet 'fields terminated by'." - nla "Bij het gebruik van BLOBs is het niet mogelijk om vaste rijlengte te gebruiken. Maak s.v.p. gebruik van 'fields terminated by'." - eng "You can't use fixed rowlength with BLOBs; please use 'fields terminated by'" - est "BLOB-tüüpi väljade olemasolul ei saa kasutada fikseeritud väljapikkust. Vajalik 'fields terminated by' määrang." - fre "Vous ne pouvez utiliser des lignes de longueur fixe avec des BLOBs. Utiliser 'fields terminated by'." - ger "Eine feste Zeilenlänge kann für BLOB-Felder nicht verwendet werden. Bitte 'fields terminated by' verwenden" - greek "Äåí ìðïñåßôå íá ÷ñçóéìïðïéÞóåôå fixed rowlength óå BLOBs. Ðáñáêáëþ ÷ñçóéìïðïéåßóôå 'fields terminated by'." - hun "Fix hosszusagu BLOB-ok nem hasznalhatok. Hasznalja a 'mezoelvalaszto jelet' ." - ita "Non possono essere usate righe a lunghezza fissa con i BLOB. Usa 'FIELDS TERMINATED BY'." - jpn "You can't use fixed rowlength with BLOBs; please use 'fields terminated by'." - kor "BLOB·Î´Â °íÁ¤±æÀÌÀÇ lowlength¸¦ »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù. 'fields terminated by'¸¦ »ç¿ëÇϼ¼¿ä." - nor "En kan ikke bruke faste feltlengder med BLOB. Vennlisgt bruk 'fields terminated by'." - norwegian-ny "Ein kan ikkje bruke faste feltlengder med BLOB. Vennlisgt bruk 'fields terminated by'." - pol "Nie mo¿na u¿yæ sta³ej d³ugo?ci wiersza z polami typu BLOB. U¿yj 'fields terminated by'." - por "Você não pode usar comprimento de linha fixo com BLOBs. Por favor, use campos com comprimento limitado." - rum "Nu poti folosi lungime de cimp fix pentru BLOB-uri. Foloseste 'fields terminated by'." - rus "æÉËÓÉÒÏ×ÁÎÎÙÊ ÒÁÚÍÅÒ ÚÁÐÉÓÉ Ó ÐÏÌÑÍÉ ÔÉÐÁ BLOB ÉÓÐÏÌØÚÏ×ÁÔØ ÎÅÌØÚÑ, ÐÒÉÍÅÎÑÊÔÅ 'fields terminated by'" - serbian "Ne možete koristiti fiksnu velièinu sloga kada imate BLOB polja. Molim koristite 'fields terminated by' opciju." - slo "Nie je mo¾né pou¾i» fixnú då¾ku s BLOBom. Pou¾ite 'fields terminated by'." - spa "No puedes usar longitudes de filas fijos con BLOBs. Por favor usa 'campos terminados por '." - swe "Man kan inte använda fast radlängd med blobs. Använd 'fields terminated by'" - ukr "îÅ ÍÏÖÎÁ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ ÓÔÁÌÕ ÄÏ×ÖÉÎÕ ÓÔÒÏËÉ Ú BLOB. úËÏÒÉÓÔÁÊÔÅÓÑ 'fields terminated by'" -ER_TEXTFILE_NOT_READABLE - cze "Soubor '%-.128s' mus-Bí být v adresáøi databáze nebo èitelný pro v¹echny" - dan "Filen '%-.128s' skal være i database-folderen og kunne læses af alle" - nla "Het bestand '%-.128s' dient in de database directory voor the komen of leesbaar voor iedereen te zijn." - eng "The file '%-.128s' must be in the database directory or be readable by all" - jps "ƒtƒ@ƒCƒ‹ '%-.128s' ‚Í databse ‚Ì directory ‚É‚ ‚é‚©‘S‚Ẵ†[ƒU[‚ª“Ç‚ß‚é‚悤‚É‹–‰Â‚³‚ê‚Ä‚¢‚È‚¯‚ê‚΂Ȃè‚Ü‚¹‚ñ.", - est "Fail '%-.128s' peab asuma andmebaasi kataloogis või olema kõigile loetav" - fre "Le fichier '%-.128s' doit être dans le répertoire de la base et lisible par tous" - ger "Datei '%-.128s' muss im Datenbank-Verzeichnis vorhanden oder lesbar für alle sein" - greek "Ôï áñ÷åßï '%-.128s' ðñÝðåé íá õðÜñ÷åé óôï database directory Þ íá ìðïñåß íá äéáâáóôåß áðü üëïõò" - hun "A(z) '%-.128s'-nak az adatbazis konyvtarban kell lennie, vagy mindenki szamara olvashatonak" - ita "Il file '%-.128s' deve essere nella directory del database e deve essere leggibile da tutti" - jpn "¥Õ¥¡¥¤¥ë '%-.128s' ¤Ï databse ¤Î directory ¤Ë¤¢¤ë¤«Á´¤Æ¤Î¥æ¡¼¥¶¡¼¤¬Æɤá¤ë¤è¤¦¤Ëµö²Ä¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó." - kor "'%-.128s' ÈÀÏ´Â µ¥ÀÌŸº£À̽º µð·ºÅ丮¿¡ Á¸ÀçÇϰųª ¸ðµÎ¿¡°Ô Àб⠰¡´ÉÇÏ¿©¾ß ÇÕ´Ï´Ù." - nor "Filen '%-.128s' må være i database-katalogen for å være lesbar for alle" - norwegian-ny "Filen '%-.128s' må være i database-katalogen for å være lesbar for alle" - pol "Plik '%-.128s' musi znajdowaæ sie w katalogu bazy danych lub mieæ prawa czytania przez wszystkich" - por "Arquivo '%-.128s' tem que estar no diretório do banco de dados ou ter leitura possível para todos" - rum "Fisierul '%-.128s' trebuie sa fie in directorul bazei de data sau trebuie sa poata sa fie citit de catre toata lumea (verifica permisiile)" - rus "æÁÊÌ '%-.128s' ÄÏÌÖÅÎ ÎÁÈÏÄÉÔØÓÑ × ÔÏÍ ÖÅ ËÁÔÁÌÏÇÅ, ÞÔÏ É ÂÁÚÁ ÄÁÎÎÙÈ, ÉÌÉ ÂÙÔØ ÏÂÝÅÄÏÓÔÕÐÎÙÍ ÄÌÑ ÞÔÅÎÉÑ" - serbian "File '%-.128s' mora biti u direktorijumu gde su file-ovi baze i mora imati odgovarajuæa prava pristupa" - slo "Súbor '%-.128s' musí by» v adresári databázy, alebo èitateµný pre v¹etkých" - spa "El archivo '%-.128s' debe estar en el directorio de la base de datos o ser de lectura por todos" - swe "Textfilen '%-.128s' måste finnas i databasbiblioteket eller vara läsbar för alla" - ukr "æÁÊÌ '%-.128s' ÐÏ×ÉÎÅÎ ÂÕÔÉ Õ ÔÅæ ÂÁÚÉ ÄÁÎÎÉÈ ÁÂÏ ÍÁÔÉ ×ÓÔÁÎÏ×ÌÅÎÅ ÐÒÁ×Ï ÎÁ ÞÉÔÁÎÎÑ ÄÌÑ ÕÓ¦È" -ER_FILE_EXISTS_ERROR - cze "Soubor '%-.200s' ji-B¾ existuje" - dan "Filen '%-.200s' eksisterer allerede" - nla "Het bestand '%-.200s' bestaat reeds" - eng "File '%-.200s' already exists" - jps "File '%-.200s' ‚ÍŠù‚É‘¶Ý‚µ‚Ü‚·", - est "Fail '%-.200s' juba eksisteerib" - fre "Le fichier '%-.200s' existe déjà" - ger "Datei '%-.200s' bereits vorhanden" - greek "Ôï áñ÷åßï '%-.200s' õðÜñ÷åé Þäç" - hun "A '%-.200s' file mar letezik." - ita "Il file '%-.200s' esiste gia`" - jpn "File '%-.200s' ¤Ï´û¤Ë¸ºß¤·¤Þ¤¹" - kor "'%-.200s' ÈÀÏÀº ÀÌ¹Ì Á¸ÀçÇÕ´Ï´Ù." - nor "Filen '%-.200s' eksisterte allerede" - norwegian-ny "Filen '%-.200s' eksisterte allereide" - pol "Plik '%-.200s' ju¿ istnieje" - por "Arquivo '%-.200s' já existe" - rum "Fisierul '%-.200s' exista deja" - rus "æÁÊÌ '%-.200s' ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ" - serbian "File '%-.200s' veæ postoji" - slo "Súbor '%-.200s' u¾ existuje" - spa "El archivo '%-.200s' ya existe" - swe "Filen '%-.200s' existerar redan" - ukr "æÁÊÌ '%-.200s' ×ÖÅ ¦ÓÎÕ¤" -ER_LOAD_INFO - cze "Z-Báznamù: %ld Vymazáno: %ld Pøeskoèeno: %ld Varování: %ld" - dan "Poster: %ld Fjernet: %ld Sprunget over: %ld Advarsler: %ld" - nla "Records: %ld Verwijderd: %ld Overgeslagen: %ld Waarschuwingen: %ld" - eng "Records: %ld Deleted: %ld Skipped: %ld Warnings: %ld" - jps "ƒŒƒR[ƒh”: %ld íœ: %ld Skipped: %ld Warnings: %ld", - est "Kirjeid: %ld Kustutatud: %ld Vahele jäetud: %ld Hoiatusi: %ld" - fre "Enregistrements: %ld Effacés: %ld Non traités: %ld Avertissements: %ld" - ger "Datensätze: %ld Gelöscht: %ld Ausgelassen: %ld Warnungen: %ld" - greek "ÅããñáöÝò: %ld ÄéáãñáöÝò: %ld ÐáñåêÜìöèçóáí: %ld ÐñïåéäïðïéÞóåéò: %ld" - hun "Rekordok: %ld Torolve: %ld Skipped: %ld Warnings: %ld" - ita "Records: %ld Cancellati: %ld Saltati: %ld Avvertimenti: %ld" - jpn "¥ì¥³¡¼¥É¿ô: %ld ºï½ü: %ld Skipped: %ld Warnings: %ld" - kor "·¹ÄÚµå: %ld°³ »èÁ¦: %ld°³ ½ºÅµ: %ld°³ °æ°í: %ld°³" - nor "Poster: %ld Fjernet: %ld Hoppet over: %ld Advarsler: %ld" - norwegian-ny "Poster: %ld Fjerna: %ld Hoppa over: %ld Åtvaringar: %ld" - pol "Recordów: %ld Usuniêtych: %ld Pominiêtych: %ld Ostrze¿eñ: %ld" - por "Registros: %ld - Deletados: %ld - Ignorados: %ld - Avisos: %ld" - rum "Recorduri: %ld Sterse: %ld Sarite (skipped): %ld Atentionari (warnings): %ld" - rus "úÁÐÉÓÅÊ: %ld õÄÁÌÅÎÏ: %ld ðÒÏÐÕÝÅÎÏ: %ld ðÒÅÄÕÐÒÅÖÄÅÎÉÊ: %ld" - serbian "Slogova: %ld Izbrisano: %ld Preskoèeno: %ld Upozorenja: %ld" - slo "Záznamov: %ld Zmazaných: %ld Preskoèených: %ld Varovania: %ld" - spa "Registros: %ld Borrados: %ld Saltados: %ld Peligros: %ld" - swe "Rader: %ld Bortagna: %ld Dubletter: %ld Varningar: %ld" - ukr "úÁÐÉÓ¦×: %ld ÷ÉÄÁÌÅÎÏ: %ld ðÒÏÐÕÝÅÎÏ: %ld úÁÓÔÅÒÅÖÅÎØ: %ld" -ER_ALTER_INFO - cze "Z-Báznamù: %ld Zdvojených: %ld" - dan "Poster: %ld Ens: %ld" - nla "Records: %ld Dubbel: %ld" - eng "Records: %ld Duplicates: %ld" - jps "ƒŒƒR[ƒh”: %ld d•¡: %ld", - est "Kirjeid: %ld Kattuvaid: %ld" - fre "Enregistrements: %ld Doublons: %ld" - ger "Datensätze: %ld Duplikate: %ld" - greek "ÅããñáöÝò: %ld ÅðáíáëÞøåéò: %ld" - hun "Rekordok: %ld Duplikalva: %ld" - ita "Records: %ld Duplicati: %ld" - jpn "¥ì¥³¡¼¥É¿ô: %ld ½ÅÊ£: %ld" - kor "·¹ÄÚµå: %ld°³ Áߺ¹: %ld°³" - nor "Poster: %ld Like: %ld" - norwegian-ny "Poster: %ld Like: %ld" - pol "Rekordów: %ld Duplikatów: %ld" - por "Registros: %ld - Duplicados: %ld" - rum "Recorduri: %ld Duplicate: %ld" - rus "úÁÐÉÓÅÊ: %ld äÕÂÌÉËÁÔÏ×: %ld" - serbian "Slogova: %ld Duplikata: %ld" - slo "Záznamov: %ld Opakovaných: %ld" - spa "Registros: %ld Duplicados: %ld" - swe "Rader: %ld Dubletter: %ld" - ukr "úÁÐÉÓ¦×: %ld äÕÂ̦ËÁÔ¦×: %ld" -ER_WRONG_SUB_KEY - cze "Chybn-Bá podèást klíèe -- není to øetìzec nebo je del¹í ne¾ délka èásti klíèe" - dan "Forkert indeksdel. Den anvendte nøgledel er ikke en streng eller længden er større end nøglelængden" - nla "Foutief sub-gedeelte van de zoeksleutel. De gebruikte zoeksleutel is geen onderdeel van een string of of de gebruikte lengte is langer dan de zoeksleutel" - eng "Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys" - est "Vigane võtme osa. Kasutatud võtmeosa ei ole string tüüpi, määratud pikkus on pikem kui võtmeosa või tabelihandler ei toeta seda tüüpi võtmeid" - fre "Mauvaise sous-clef. Ce n'est pas un 'string' ou la longueur dépasse celle définie dans la clef" - ger "Falscher Unterteilschlüssel. Der verwendete Schlüsselteil ist entweder kein String, die verwendete Länge ist länger als der Teilschlüssel oder die Speicher-Engine unterstützt keine Unterteilschlüssel" - greek "ÅóöáëìÝíï sub part key. Ôï ÷ñçóéìïðïéïýìåíï key part äåí åßíáé string Þ ôï ìÞêïò ôïõ åßíáé ìåãáëýôåñï" - hun "Rossz alkulcs. A hasznalt kulcsresz nem karaktersorozat vagy hosszabb, mint a kulcsresz" - ita "Sotto-parte della chiave errata. La parte di chiave utilizzata non e` una stringa o la lunghezza e` maggiore della parte di chiave." - jpn "Incorrect prefix key; the used key part isn't a string or the used length is longer than the key part" - kor "ºÎÁ¤È®ÇÑ ¼¹ö ÆÄÆ® Å°. »ç¿ëµÈ Å° ÆÄÆ®°¡ ½ºÆ®¸µÀÌ ¾Æ´Ï°Å³ª Å° ÆÄÆ®ÀÇ ±æÀÌ°¡ ³Ê¹« ±é´Ï´Ù." - nor "Feil delnøkkel. Den brukte delnøkkelen er ikke en streng eller den oppgitte lengde er lengre enn nøkkel lengden" - norwegian-ny "Feil delnykkel. Den brukte delnykkelen er ikkje ein streng eller den oppgitte lengda er lengre enn nykkellengden" - pol "B³êdna podczê?æ klucza. U¿yta czê?æ klucza nie jest ³añcuchem lub u¿yta d³ugo?æ jest wiêksza ni¿ czê?æ klucza" - por "Sub parte da chave incorreta. A parte da chave usada não é uma 'string' ou o comprimento usado é maior que parte da chave ou o manipulador de tabelas não suporta sub chaves únicas" - rum "Componentul cheii este incorrect. Componentul folosit al cheii nu este un sir sau lungimea folosita este mai lunga decit lungimea cheii" - rus "îÅËÏÒÒÅËÔÎÁÑ ÞÁÓÔØ ËÌÀÞÁ. éÓÐÏÌØÚÕÅÍÁÑ ÞÁÓÔØ ËÌÀÞÁ ÎÅ Ñ×ÌÑÅÔÓÑ ÓÔÒÏËÏÊ, ÕËÁÚÁÎÎÁÑ ÄÌÉÎÁ ÂÏÌØÛÅ, ÞÅÍ ÄÌÉÎÁ ÞÁÓÔÉ ËÌÀÞÁ, ÉÌÉ ÏÂÒÁÂÏÔÞÉË ÔÁÂÌÉÃÙ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ÕÎÉËÁÌØÎÙÅ ÞÁÓÔÉ ËÌÀÞÁ" - serbian "Pogrešan pod-kljuè dela kljuèa. Upotrebljeni deo kljuèa nije string, upotrebljena dužina je veæa od dela kljuèa ili handler tabela ne podržava jedinstvene pod-kljuèeve" - slo "Incorrect prefix key; the used key part isn't a string or the used length is longer than the key part" - spa "Parte de la clave es erronea. Una parte de la clave no es una cadena o la longitud usada es tan grande como la parte de la clave" - swe "Felaktig delnyckel. Nyckeldelen är inte en sträng eller den angivna längden är längre än kolumnlängden" - ukr "îÅצÒÎÁ ÞÁÓÔÉÎÁ ËÌÀÞÁ. ÷ÉËÏÒÉÓÔÁÎÁ ÞÁÓÔÉÎÁ ËÌÀÞÁ ÎÅ ¤ ÓÔÒÏËÏÀ, ÚÁÄÏ×ÇÁ ÁÂÏ ×ËÁÚ¦×ÎÉË ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕ¤ ÕΦËÁÌØÎÉÈ ÞÁÓÔÉÎ ËÌÀÞÅÊ" -ER_CANT_REMOVE_ALL_FIELDS 42000 - cze "Nen-Bí mo¾né vymazat v¹echny polo¾ky s ALTER TABLE. Pou¾ijte DROP TABLE" - dan "Man kan ikke slette alle felter med ALTER TABLE. Brug DROP TABLE i stedet." - nla "Het is niet mogelijk alle velden te verwijderen met ALTER TABLE. Gebruik a.u.b. DROP TABLE hiervoor!" - eng "You can't delete all columns with ALTER TABLE; use DROP TABLE instead" - jps "ALTER TABLE ‚Å‘S‚Ä‚Ì column ‚Í휂ł«‚Ü‚¹‚ñ. DROP TABLE ‚ðŽg—p‚µ‚Ä‚‚¾‚³‚¢", - est "ALTER TABLE kasutades ei saa kustutada kõiki tulpasid. Kustuta tabel DROP TABLE abil" - fre "Vous ne pouvez effacer tous les champs avec ALTER TABLE. Utilisez DROP TABLE" - ger "Mit ALTER TABLE können nicht alle Felder auf einmal gelöscht werden. Dafür DROP TABLE verwenden" - greek "Äåí åßíáé äõíáôÞ ç äéáãñáöÞ üëùí ôùí ðåäßùí ìå ALTER TABLE. Ðáñáêáëþ ÷ñçóéìïðïéåßóôå DROP TABLE" - hun "Az osszes mezo nem torolheto az ALTER TABLE-lel. Hasznalja a DROP TABLE-t helyette" - ita "Non si possono cancellare tutti i campi con una ALTER TABLE. Utilizzare DROP TABLE" - jpn "ALTER TABLE ¤ÇÁ´¤Æ¤Î column ¤Ïºï½ü¤Ç¤¤Þ¤»¤ó. DROP TABLE ¤ò»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤" - kor "ALTER TABLE ¸í·ÉÀ¸·Î´Â ¸ðµç Ä®·³À» Áö¿ï ¼ö ¾ø½À´Ï´Ù. DROP TABLE ¸í·ÉÀ» ÀÌ¿ëÇϼ¼¿ä." - nor "En kan ikke slette alle felt med ALTER TABLE. Bruk DROP TABLE isteden." - norwegian-ny "Ein kan ikkje slette alle felt med ALTER TABLE. Bruk DROP TABLE istadenfor." - pol "Nie mo¿na usun?æ wszystkich pól wykorzystuj?c ALTER TABLE. W zamian u¿yj DROP TABLE" - por "Você não pode deletar todas as colunas com ALTER TABLE; use DROP TABLE em seu lugar" - rum "Nu poti sterge toate coloanele cu ALTER TABLE. Foloseste DROP TABLE in schimb" - rus "îÅÌØÚÑ ÕÄÁÌÉÔØ ×ÓÅ ÓÔÏÌÂÃÙ Ó ÐÏÍÏÝØÀ ALTER TABLE. éÓÐÏÌØÚÕÊÔÅ DROP TABLE" - serbian "Ne možete da izbrišete sve kolone pomoæu komande 'ALTER TABLE'. Upotrebite komandu 'DROP TABLE' ako želite to da uradite" - slo "One nemô¾em zmaza» all fields with ALTER TABLE; use DROP TABLE instead" - spa "No puede borrar todos los campos con ALTER TABLE. Usa DROP TABLE para hacerlo" - swe "Man kan inte radera alla fält med ALTER TABLE. Använd DROP TABLE istället" - ukr "îÅ ÍÏÖÌÉ×Ï ×ÉÄÁÌÉÔÉ ×Ó¦ ÓÔÏ×Âæ ÚÁ ÄÏÐÏÍÏÇÏÀ ALTER TABLE. äÌÑ ÃØÏÇÏ ÓËÏÒÉÓÔÁÊÔÅÓÑ DROP TABLE" -ER_CANT_DROP_FIELD_OR_KEY 42000 - cze "Nemohu zru-B¹it '%-.192s' (provést DROP). Zkontrolujte, zda neexistují záznamy/klíèe" - dan "Kan ikke udføre DROP '%-.192s'. Undersøg om feltet/nøglen eksisterer." - nla "Kan '%-.192s' niet weggooien. Controleer of het veld of de zoeksleutel daadwerkelijk bestaat." - eng "Can't DROP '%-.192s'; check that column/key exists" - jps "'%-.192s' ‚ð”jŠü‚Å‚«‚Ü‚¹‚ñ‚Å‚µ‚½; check that column/key exists", - est "Ei suuda kustutada '%-.192s'. Kontrolli kas tulp/võti eksisteerib" - fre "Ne peut effacer (DROP) '%-.192s'. Vérifiez s'il existe" - ger "Kann '%-.192s' nicht löschen. Existiert die Spalte oder der Schlüssel?" - greek "Áäýíáôç ç äéáãñáöÞ (DROP) '%-.192s'. Ðáñáêáëþ åëÝãîôå áí ôï ðåäßï/êëåéäß õðÜñ÷åé" - hun "A DROP '%-.192s' nem lehetseges. Ellenorizze, hogy a mezo/kulcs letezik-e" - ita "Impossibile cancellare '%-.192s'. Controllare che il campo chiave esista" - jpn "'%-.192s' ¤òÇË´þ¤Ç¤¤Þ¤»¤ó¤Ç¤·¤¿; check that column/key exists" - kor "'%-.192s'¸¦ DROPÇÒ ¼ö ¾ø½À´Ï´Ù. Ä®·³À̳ª Å°°¡ Á¸ÀçÇÏ´ÂÁö äũÇϼ¼¿ä." - nor "Kan ikke DROP '%-.192s'. Undersøk om felt/nøkkel eksisterer." - norwegian-ny "Kan ikkje DROP '%-.192s'. Undersøk om felt/nøkkel eksisterar." - pol "Nie mo¿na wykonaæ operacji DROP '%-.192s'. Sprawd¥, czy to pole/klucz istnieje" - por "Não se pode fazer DROP '%-.192s'. Confira se esta coluna/chave existe" - rum "Nu pot sa DROP '%-.192s'. Verifica daca coloana/cheia exista" - rus "îÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ (DROP) '%-.192s'. õÂÅÄÉÔÅÓØ ÞÔÏ ÓÔÏÌÂÅÃ/ËÌÀÞ ÄÅÊÓÔ×ÉÔÅÌØÎÏ ÓÕÝÅÓÔ×ÕÅÔ" - serbian "Ne mogu da izvršim komandu drop 'DROP' na '%-.192s'. Proverite da li ta kolona (odnosno kljuè) postoji" - slo "Nemô¾em zru¹i» (DROP) '%-.192s'. Skontrolujte, èi neexistujú záznamy/kµúèe" - spa "No puedo ELIMINAR '%-.192s'. compuebe que el campo/clave existe" - swe "Kan inte ta bort '%-.192s'. Kontrollera att fältet/nyckel finns" - ukr "îÅ ÍÏÖÕ DROP '%-.192s'. ðÅÒÅצÒÔÅ, ÞÉ ÃÅÊ ÓÔÏ×ÂÅÃØ/ËÌÀÞ ¦ÓÎÕ¤" -ER_INSERT_INFO - cze "Z-Báznamù: %ld Zdvojených: %ld Varování: %ld" - dan "Poster: %ld Ens: %ld Advarsler: %ld" - nla "Records: %ld Dubbel: %ld Waarschuwing: %ld" - eng "Records: %ld Duplicates: %ld Warnings: %ld" - jps "ƒŒƒR[ƒh”: %ld d•¡”: %ld Warnings: %ld", - est "Kirjeid: %ld Kattuvaid: %ld Hoiatusi: %ld" - fre "Enregistrements: %ld Doublons: %ld Avertissements: %ld" - ger "Datensätze: %ld Duplikate: %ld Warnungen: %ld" - greek "ÅããñáöÝò: %ld ÅðáíáëÞøåéò: %ld ÐñïåéäïðïéÞóåéò: %ld" - hun "Rekordok: %ld Duplikalva: %ld Warnings: %ld" - ita "Records: %ld Duplicati: %ld Avvertimenti: %ld" - jpn "¥ì¥³¡¼¥É¿ô: %ld ½ÅÊ£¿ô: %ld Warnings: %ld" - kor "·¹ÄÚµå: %ld°³ Áߺ¹: %ld°³ °æ°í: %ld°³" - nor "Poster: %ld Like: %ld Advarsler: %ld" - norwegian-ny "Postar: %ld Like: %ld Åtvaringar: %ld" - pol "Rekordów: %ld Duplikatów: %ld Ostrze¿eñ: %ld" - por "Registros: %ld - Duplicados: %ld - Avisos: %ld" - rum "Recorduri: %ld Duplicate: %ld Atentionari (warnings): %ld" - rus "úÁÐÉÓÅÊ: %ld äÕÂÌÉËÁÔÏ×: %ld ðÒÅÄÕÐÒÅÖÄÅÎÉÊ: %ld" - serbian "Slogova: %ld Duplikata: %ld Upozorenja: %ld" - slo "Záznamov: %ld Opakovaných: %ld Varovania: %ld" - spa "Registros: %ld Duplicados: %ld Peligros: %ld" - swe "Rader: %ld Dubletter: %ld Varningar: %ld" - ukr "úÁÐÉÓ¦×: %ld äÕÂ̦ËÁÔ¦×: %ld úÁÓÔÅÒÅÖÅÎØ: %ld" -ER_UPDATE_TABLE_USED - eng "You can't specify target table '%-.192s' for update in FROM clause" - ger "Die Verwendung der zu aktualisierenden Zieltabelle '%-.192s' ist in der FROM-Klausel nicht zulässig." - rus "îÅ ÄÏÐÕÓËÁÅÔÓÑ ÕËÁÚÁÎÉÅ ÔÁÂÌÉÃÙ '%-.192s' × ÓÐÉÓËÅ ÔÁÂÌÉà FROM ÄÌÑ ×ÎÅÓÅÎÉÑ × ÎÅÅ ÉÚÍÅÎÅÎÉÊ" - swe "INSERT-table '%-.192s' får inte finnas i FROM tabell-listan" - ukr "ôÁÂÌÉÃÑ '%-.192s' ÝÏ ÚͦÎÀ¤ÔØÓÑ ÎÅ ÄÏÚ×ÏÌÅÎÁ Õ ÐÅÒÅ̦ËÕ ÔÁÂÌÉÃØ FROM" -ER_NO_SUCH_THREAD - cze "Nezn-Bámá identifikace threadu: %lu" - dan "Ukendt tråd id: %lu" - nla "Onbekend thread id: %lu" - eng "Unknown thread id: %lu" - jps "thread id: %lu ‚Í‚ ‚è‚Ü‚¹‚ñ", - est "Tundmatu lõim: %lu" - fre "Numéro de tâche inconnu: %lu" - ger "Unbekannte Thread-ID: %lu" - greek "Áãíùóôï thread id: %lu" - hun "Ervenytelen szal (thread) id: %lu" - ita "Thread id: %lu sconosciuto" - jpn "thread id: %lu ¤Ï¤¢¤ê¤Þ¤»¤ó" - kor "¾Ë¼ö ¾ø´Â ¾²·¹µå id: %lu" - nor "Ukjent tråd id: %lu" - norwegian-ny "Ukjent tråd id: %lu" - pol "Nieznany identyfikator w?tku: %lu" - por "'Id' de 'thread' %lu desconhecido" - rum "Id-ul: %lu thread-ului este necunoscut" - rus "îÅÉÚ×ÅÓÔÎÙÊ ÎÏÍÅÒ ÐÏÔÏËÁ: %lu" - serbian "Nepoznat thread identifikator: %lu" - slo "Neznáma identifikácia vlákna: %lu" - spa "Identificador del thread: %lu desconocido" - swe "Finns ingen tråd med id %lu" - ukr "îÅצÄÏÍÉÊ ¦ÄÅÎÔÉƦËÁÔÏÒ Ç¦ÌËÉ: %lu" -ER_KILL_DENIED_ERROR - cze "Nejste vlastn-Bíkem threadu %lu" - dan "Du er ikke ejer af tråden %lu" - nla "U bent geen bezitter van thread %lu" - eng "You are not owner of thread %lu" - jps "thread %lu ‚̃I[ƒi[‚Å‚Í‚ ‚è‚Ü‚¹‚ñ", - est "Ei ole lõime %lu omanik" - fre "Vous n'êtes pas propriétaire de la tâche no: %lu" - ger "Sie sind nicht Eigentümer von Thread %lu" - greek "Äåí åßóèå owner ôïõ thread %lu" - hun "A %lu thread-nek mas a tulajdonosa" - ita "Utente non proprietario del thread %lu" - jpn "thread %lu ¤Î¥ª¡¼¥Ê¡¼¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó" - kor "¾²·¹µå(Thread) %luÀÇ ¼ÒÀ¯ÀÚ°¡ ¾Æ´Õ´Ï´Ù." - nor "Du er ikke eier av tråden %lu" - norwegian-ny "Du er ikkje eigar av tråd %lu" - pol "Nie jeste? w³a?cicielem w?tku %lu" - por "Você não é proprietário da 'thread' %lu" - rum "Nu sinteti proprietarul threadului %lu" - rus "÷Ù ÎÅ Ñ×ÌÑÅÔÅÓØ ×ÌÁÄÅÌØÃÅÍ ÐÏÔÏËÁ %lu" - serbian "Vi niste vlasnik thread-a %lu" - slo "Nie ste vlastníkom vlákna %lu" - spa "Tu no eres el propietario del thread%lu" - swe "Du är inte ägare till tråd %lu" - ukr "÷É ÎÅ ×ÏÌÏÄÁÒ Ç¦ÌËÉ %lu" -ER_NO_TABLES_USED - cze "Nejsou pou-B¾ity ¾ádné tabulky" - dan "Ingen tabeller i brug" - nla "Geen tabellen gebruikt." - eng "No tables used" - est "Ühtegi tabelit pole kasutusel" - fre "Aucune table utilisée" - ger "Keine Tabellen verwendet" - greek "Äåí ÷ñçóéìïðïéÞèçêáí ðßíáêåò" - hun "Nincs hasznalt tabla" - ita "Nessuna tabella usata" - kor "¾î¶² Å×ÀÌºíµµ »ç¿ëµÇÁö ¾Ê¾Ò½À´Ï´Ù." - nor "Ingen tabeller i bruk" - norwegian-ny "Ingen tabellar i bruk" - pol "Nie ma ¿adej u¿ytej tabeli" - por "Nenhuma tabela usada" - rum "Nici o tabela folosita" - rus "îÉËÁËÉÅ ÔÁÂÌÉÃÙ ÎÅ ÉÓÐÏÌØÚÏ×ÁÎÙ" - serbian "Nema upotrebljenih tabela" - slo "Nie je pou¾itá ¾iadna tabuµka" - spa "No ha tablas usadas" - swe "Inga tabeller angivna" - ukr "îÅ ×ÉËÏÒÉÓÔÁÎÏ ÔÁÂÌÉÃØ" -ER_TOO_BIG_SET - cze "P-Bøíli¹ mnoho øetìzcù pro sloupec %-.192s a SET" - dan "For mange tekststrenge til specifikationen af SET i kolonne %-.192s" - nla "Teveel strings voor kolom %-.192s en SET" - eng "Too many strings for column %-.192s and SET" - est "Liiga palju string tulbale %-.192s tüübile SET" - fre "Trop de chaînes dans la colonne %-.192s avec SET" - ger "Zu viele Strings für Feld %-.192s und SET angegeben" - greek "ÐÜñá ðïëëÜ strings ãéá ôï ðåäßï %-.192s êáé SET" - hun "Tul sok karakter: %-.192s es SET" - ita "Troppe stringhe per la colonna %-.192s e la SET" - kor "Ä®·³ %-.192s¿Í SET¿¡¼ ½ºÆ®¸µÀÌ ³Ê¹« ¸¹½À´Ï´Ù." - nor "For mange tekststrenger kolonne %-.192s og SET" - norwegian-ny "For mange tekststrengar felt %-.192s og SET" - pol "Zbyt wiele ³añcuchów dla kolumny %-.192s i polecenia SET" - por "'Strings' demais para coluna '%-.192s' e SET" - rum "Prea multe siruri pentru coloana %-.192s si SET" - rus "óÌÉÛËÏÍ ÍÎÏÇÏ ÚÎÁÞÅÎÉÊ ÄÌÑ ÓÔÏÌÂÃÁ %-.192s × SET" - serbian "Previše string-ova za kolonu '%-.192s' i komandu 'SET'" - slo "Príli¹ mnoho re»azcov pre pole %-.192s a SET" - spa "Muchas strings para columna %-.192s y SET" - swe "För många alternativ till kolumn %-.192s för SET" - ukr "úÁÂÁÇÁÔÏ ÓÔÒÏË ÄÌÑ ÓÔÏ×ÂÃÑ %-.192s ÔÁ SET" -ER_NO_UNIQUE_LOGFILE - cze "Nemohu vytvo-Bøit jednoznaèné jméno logovacího souboru %-.200s.(1-999)\n" - dan "Kan ikke lave unikt log-filnavn %-.200s.(1-999)\n" - nla "Het is niet mogelijk een unieke naam te maken voor de logfile %-.200s.(1-999)\n" - eng "Can't generate a unique log-filename %-.200s.(1-999)\n" - est "Ei suuda luua unikaalset logifaili nime %-.200s.(1-999)\n" - fre "Ne peut générer un unique nom de journal %-.200s.(1-999)\n" - ger "Kann keinen eindeutigen Dateinamen für die Logdatei %-.200s(1-999) erzeugen\n" - greek "Áäýíáôç ç äçìéïõñãßá unique log-filename %-.200s.(1-999)\n" - hun "Egyedi log-filenev nem generalhato: %-.200s.(1-999)\n" - ita "Impossibile generare un nome del file log unico %-.200s.(1-999)\n" - kor "Unique ·Î±×ÈÀÏ '%-.200s'¸¦ ¸¸µé¼ö ¾ø½À´Ï´Ù.(1-999)\n" - nor "Kan ikke lage unikt loggfilnavn %-.200s.(1-999)\n" - norwegian-ny "Kan ikkje lage unikt loggfilnavn %-.200s.(1-999)\n" - pol "Nie mo¿na stworzyæ unikalnej nazwy pliku z logiem %-.200s.(1-999)\n" - por "Não pode gerar um nome de arquivo de 'log' único '%-.200s'.(1-999)\n" - rum "Nu pot sa generez un nume de log unic %-.200s.(1-999)\n" - rus "îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÕÎÉËÁÌØÎÏÅ ÉÍÑ ÆÁÊÌÁ ÖÕÒÎÁÌÁ %-.200s.(1-999)\n" - serbian "Ne mogu da generišem jedinstveno ime log-file-a: '%-.200s.(1-999)'\n" - slo "Nemô¾em vytvori» unikátne meno log-súboru %-.200s.(1-999)\n" - spa "No puede crear un unico archivo log %-.200s.(1-999)\n" - swe "Kan inte generera ett unikt filnamn %-.200s.(1-999)\n" - ukr "îÅ ÍÏÖÕ ÚÇÅÎÅÒÕ×ÁÔÉ ÕΦËÁÌØÎÅ ¦Í'Ñ log-ÆÁÊÌÕ %-.200s.(1-999)\n" -ER_TABLE_NOT_LOCKED_FOR_WRITE - cze "Tabulka '%-.192s' byla zam-Bèena s READ a nemù¾e být zmìnìna" - dan "Tabellen '%-.192s' var låst med READ lås og kan ikke opdateres" - nla "Tabel '%-.192s' was gelocked met een lock om te lezen. Derhalve kunnen geen wijzigingen worden opgeslagen." - eng "Table '%-.192s' was locked with a READ lock and can't be updated" - jps "Table '%-.192s' ‚Í READ lock ‚É‚È‚Á‚Ä‚¢‚ÄAXV‚Í‚Å‚«‚Ü‚¹‚ñ", - est "Tabel '%-.192s' on lukustatud READ lukuga ning ei ole muudetav" - fre "Table '%-.192s' verrouillée lecture (READ): modification impossible" - ger "Tabelle '%-.192s' ist mit Lesesperre versehen und kann nicht aktualisiert werden" - greek "Ï ðßíáêáò '%-.192s' Ý÷åé êëåéäùèåß ìå READ lock êáé äåí åðéôñÝðïíôáé áëëáãÝò" - hun "A(z) '%-.192s' tabla zarolva lett (READ lock) es nem lehet frissiteni" - ita "La tabella '%-.192s' e` soggetta a lock in lettura e non puo` essere aggiornata" - jpn "Table '%-.192s' ¤Ï READ lock ¤Ë¤Ê¤Ã¤Æ¤¤¤Æ¡¢¹¹¿·¤Ï¤Ç¤¤Þ¤»¤ó" - kor "Å×À̺í '%-.192s'´Â READ ¶ôÀÌ Àá°ÜÀÖ¾î¼ °»½ÅÇÒ ¼ö ¾ø½À´Ï´Ù." - nor "Tabellen '%-.192s' var låst med READ lås og kan ikke oppdateres" - norwegian-ny "Tabellen '%-.192s' var låst med READ lås og kan ikkje oppdaterast" - pol "Tabela '%-.192s' zosta³a zablokowana przez READ i nie mo¿e zostaæ zaktualizowana" - por "Tabela '%-.192s' foi travada com trava de leitura e não pode ser atualizada" - rum "Tabela '%-.192s' a fost locked cu un READ lock si nu poate fi actualizata" - rus "ôÁÂÌÉÃÁ '%-.192s' ÚÁÂÌÏËÉÒÏ×ÁÎÁ ÕÒÏ×ÎÅÍ READ lock É ÎÅ ÍÏÖÅÔ ÂÙÔØ ÉÚÍÅÎÅÎÁ" - serbian "Tabela '%-.192s' je zakljuèana READ lock-om; iz nje se može samo èitati ali u nju se ne može pisati" - slo "Tabuµka '%-.192s' bola zamknutá s READ a nemô¾e by» zmenená" - spa "Tabla '%-.192s' fue trabada con un READ lock y no puede ser actualizada" - swe "Tabell '%-.192s' kan inte uppdateras emedan den är låst för läsning" - ukr "ôÁÂÌÉÃÀ '%-.192s' ÚÁÂÌÏËÏ×ÁÎÏ Ô¦ÌØËÉ ÄÌÑ ÞÉÔÁÎÎÑ, ÔÏÍÕ §§ ÎÅ ÍÏÖÎÁ ÏÎÏ×ÉÔÉ" -ER_TABLE_NOT_LOCKED - cze "Tabulka '%-.192s' nebyla zam-Bèena s LOCK TABLES" - dan "Tabellen '%-.192s' var ikke låst med LOCK TABLES" - nla "Tabel '%-.192s' was niet gelocked met LOCK TABLES" - eng "Table '%-.192s' was not locked with LOCK TABLES" - jps "Table '%-.192s' ‚Í LOCK TABLES ‚É‚æ‚Á‚ăƒbƒN‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ", - est "Tabel '%-.192s' ei ole lukustatud käsuga LOCK TABLES" - fre "Table '%-.192s' non verrouillée: utilisez LOCK TABLES" - ger "Tabelle '%-.192s' wurde nicht mit LOCK TABLES gesperrt" - greek "Ï ðßíáêáò '%-.192s' äåí Ý÷åé êëåéäùèåß ìå LOCK TABLES" - hun "A(z) '%-.192s' tabla nincs zarolva a LOCK TABLES-szel" - ita "Non e` stato impostato il lock per la tabella '%-.192s' con LOCK TABLES" - jpn "Table '%-.192s' ¤Ï LOCK TABLES ¤Ë¤è¤Ã¤Æ¥í¥Ã¥¯¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" - kor "Å×À̺í '%-.192s'´Â LOCK TABLES ¸í·ÉÀ¸·Î Àá±âÁö ¾Ê¾Ò½À´Ï´Ù." - nor "Tabellen '%-.192s' var ikke låst med LOCK TABLES" - norwegian-ny "Tabellen '%-.192s' var ikkje låst med LOCK TABLES" - pol "Tabela '%-.192s' nie zosta³a zablokowana poleceniem LOCK TABLES" - por "Tabela '%-.192s' não foi travada com LOCK TABLES" - rum "Tabela '%-.192s' nu a fost locked cu LOCK TABLES" - rus "ôÁÂÌÉÃÁ '%-.192s' ÎÅ ÂÙÌÁ ÚÁÂÌÏËÉÒÏ×ÁÎÁ Ó ÐÏÍÏÝØÀ LOCK TABLES" - serbian "Tabela '%-.192s' nije bila zakljuèana komandom 'LOCK TABLES'" - slo "Tabuµka '%-.192s' nebola zamknutá s LOCK TABLES" - spa "Tabla '%-.192s' no fue trabada con LOCK TABLES" - swe "Tabell '%-.192s' är inte låst med LOCK TABLES" - ukr "ôÁÂÌÉÃÀ '%-.192s' ÎÅ ÂÕÌÏ ÂÌÏËÏ×ÁÎÏ Ú LOCK TABLES" -ER_BLOB_CANT_HAVE_DEFAULT 42000 - cze "Blob polo-B¾ka '%-.192s' nemù¾e mít defaultní hodnotu" - dan "BLOB feltet '%-.192s' kan ikke have en standard værdi" - nla "Blob veld '%-.192s' can geen standaardwaarde bevatten" - eng "BLOB/TEXT column '%-.192s' can't have a default value" - est "BLOB-tüüpi tulp '%-.192s' ei saa omada vaikeväärtust" - fre "BLOB '%-.192s' ne peut avoir de valeur par défaut" - ger "BLOB/TEXT-Feld '%-.192s' darf keinen Vorgabewert (DEFAULT) haben" - greek "Ôá Blob ðåäßá '%-.192s' äåí ìðïñïýí íá Ý÷ïõí ðñïêáèïñéóìÝíåò ôéìÝò (default value)" - hun "A(z) '%-.192s' blob objektumnak nem lehet alapertelmezett erteke" - ita "Il campo BLOB '%-.192s' non puo` avere un valore di default" - jpn "BLOB column '%-.192s' can't have a default value" - kor "BLOB Ä®·³ '%-.192s' ´Â µðÆúÆ® °ªÀ» °¡Áú ¼ö ¾ø½À´Ï´Ù." - nor "Blob feltet '%-.192s' kan ikke ha en standard verdi" - norwegian-ny "Blob feltet '%-.192s' kan ikkje ha ein standard verdi" - pol "Pole typu blob '%-.192s' nie mo¿e mieæ domy?lnej warto?ci" - por "Coluna BLOB '%-.192s' não pode ter um valor padrão (default)" - rum "Coloana BLOB '%-.192s' nu poate avea o valoare default" - rus "îÅ×ÏÚÍÏÖÎÏ ÕËÁÚÙ×ÁÔØ ÚÎÁÞÅÎÉÅ ÐÏ ÕÍÏÌÞÁÎÉÀ ÄÌÑ ÓÔÏÌÂÃÁ BLOB '%-.192s'" - serbian "BLOB kolona '%-.192s' ne može imati default vrednost" - slo "Pole BLOB '%-.192s' nemô¾e ma» implicitnú hodnotu" - spa "Campo Blob '%-.192s' no puede tener valores patron" - swe "BLOB fält '%-.192s' kan inte ha ett DEFAULT-värde" - ukr "óÔÏ×ÂÅÃØ BLOB '%-.192s' ÎÅ ÍÏÖÅ ÍÁÔÉ ÚÎÁÞÅÎÎÑ ÐÏ ÚÁÍÏ×ÞÕ×ÁÎÎÀ" -ER_WRONG_DB_NAME 42000 - cze "Nep-Bøípustné jméno databáze '%-.100s'" - dan "Ugyldigt database navn '%-.100s'" - nla "Databasenaam '%-.100s' is niet getoegestaan" - eng "Incorrect database name '%-.100s'" - jps "Žw’肵‚½ database –¼ '%-.100s' ‚ªŠÔˆá‚Á‚Ä‚¢‚Ü‚·", - est "Vigane andmebaasi nimi '%-.100s'" - fre "Nom de base de donnée illégal: '%-.100s'" - ger "Unerlaubter Datenbankname '%-.100s'" - greek "ËÜèïò üíïìá âÜóçò äåäïìÝíùí '%-.100s'" - hun "Hibas adatbazisnev: '%-.100s'" - ita "Nome database errato '%-.100s'" - jpn "»ØÄꤷ¤¿ database ̾ '%-.100s' ¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹" - kor "'%-.100s' µ¥ÀÌŸº£À̽ºÀÇ À̸§ÀÌ ºÎÁ¤È®ÇÕ´Ï´Ù." - nor "Ugyldig database navn '%-.100s'" - norwegian-ny "Ugyldig database namn '%-.100s'" - pol "Niedozwolona nazwa bazy danych '%-.100s'" - por "Nome de banco de dados '%-.100s' incorreto" - rum "Numele bazei de date este incorect '%-.100s'" - rus "îÅËÏÒÒÅËÔÎÏÅ ÉÍÑ ÂÁÚÙ ÄÁÎÎÙÈ '%-.100s'" - serbian "Pogrešno ime baze '%-.100s'" - slo "Neprípustné meno databázy '%-.100s'" - spa "Nombre de base de datos ilegal '%-.100s'" - swe "Felaktigt databasnamn '%-.100s'" - ukr "îÅצÒÎÅ ¦Í'Ñ ÂÁÚÉ ÄÁÎÎÉÈ '%-.100s'" -ER_WRONG_TABLE_NAME 42000 - cze "Nep-Bøípustné jméno tabulky '%-.100s'" - dan "Ugyldigt tabel navn '%-.100s'" - nla "Niet toegestane tabelnaam '%-.100s'" - eng "Incorrect table name '%-.100s'" - jps "Žw’肵‚½ table –¼ '%-.100s' ‚Í‚Ü‚¿‚ª‚Á‚Ä‚¢‚Ü‚·", - est "Vigane tabeli nimi '%-.100s'" - fre "Nom de table illégal: '%-.100s'" - ger "Unerlaubter Tabellenname '%-.100s'" - greek "ËÜèïò üíïìá ðßíáêá '%-.100s'" - hun "Hibas tablanev: '%-.100s'" - ita "Nome tabella errato '%-.100s'" - jpn "»ØÄꤷ¤¿ table ̾ '%-.100s' ¤Ï¤Þ¤Á¤¬¤Ã¤Æ¤¤¤Þ¤¹" - kor "'%-.100s' Å×À̺í À̸§ÀÌ ºÎÁ¤È®ÇÕ´Ï´Ù." - nor "Ugyldig tabell navn '%-.100s'" - norwegian-ny "Ugyldig tabell namn '%-.100s'" - pol "Niedozwolona nazwa tabeli '%-.100s'..." - por "Nome de tabela '%-.100s' incorreto" - rum "Numele tabelei este incorect '%-.100s'" - rus "îÅËÏÒÒÅËÔÎÏÅ ÉÍÑ ÔÁÂÌÉÃÙ '%-.100s'" - serbian "Pogrešno ime tabele '%-.100s'" - slo "Neprípustné meno tabuµky '%-.100s'" - spa "Nombre de tabla ilegal '%-.100s'" - swe "Felaktigt tabellnamn '%-.100s'" - ukr "îÅצÒÎÅ ¦Í'Ñ ÔÁÂÌÉæ '%-.100s'" -ER_TOO_BIG_SELECT 42000 - cze "Zadan-Bý SELECT by procházel pøíli¹ mnoho záznamù a trval velmi dlouho. Zkontrolujte tvar WHERE a je-li SELECT v poøádku, pou¾ijte SET SQL_BIG_SELECTS=1" - dan "SELECT ville undersøge for mange poster og ville sandsynligvis tage meget lang tid. Undersøg WHERE delen og brug SET SQL_BIG_SELECTS=1 hvis udtrykket er korrekt" - nla "Het SELECT-statement zou te veel records analyseren en dus veel tijd in beslagnemen. Kijk het WHERE-gedeelte van de query na en kies SET SQL_BIG_SELECTS=1 als het stament in orde is." - eng "The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay" - est "SELECT lause peab läbi vaatama suure hulga kirjeid ja võtaks tõenäoliselt liiga kaua aega. Tasub kontrollida WHERE klauslit ja vajadusel kasutada käsku SET SQL_BIG_SELECTS=1" - fre "SELECT va devoir examiner beaucoup d'enregistrements ce qui va prendre du temps. Vérifiez la clause WHERE et utilisez SET SQL_BIG_SELECTS=1 si SELECT se passe bien" - ger "Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange dauern. Bitte WHERE-Klausel überprüfen und gegebenenfalls SET SQL_BIG_SELECTS=1 oder SET SQL_MAX_JOIN_SIZE=# verwenden" - greek "Ôï SELECT èá åîåôÜóåé ìåãÜëï áñéèìü åããñáöþí êáé ðéèáíþò èá êáèõóôåñÞóåé. Ðáñáêáëþ åîåôÜóôå ôéò ðáñáìÝôñïõò ôïõ WHERE êáé ÷ñçóéìïðïéåßóôå SET SQL_BIG_SELECTS=1 áí ôï SELECT åßíáé óùóôü" - hun "A SELECT tul sok rekordot fog megvizsgalni es nagyon sokaig fog tartani. Ellenorizze a WHERE-t es hasznalja a SET SQL_BIG_SELECTS=1 beallitast, ha a SELECT okay" - ita "La SELECT dovrebbe esaminare troppi record e usare troppo tempo. Controllare la WHERE e usa SET SQL_BIG_SELECTS=1 se e` tutto a posto." - kor "SELECT ¸í·É¿¡¼ ³Ê¹« ¸¹Àº ·¹Äڵ带 ã±â ¶§¹®¿¡ ¸¹Àº ½Ã°£ÀÌ ¼Ò¿äµË´Ï´Ù. µû¶ó¼ WHERE ¹®À» Á¡°ËÇϰųª, ¸¸¾à SELECT°¡ okµÇ¸é SET SQL_BIG_SELECTS=1 ¿É¼ÇÀ» »ç¿ëÇϼ¼¿ä." - nor "SELECT ville undersøke for mange poster og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET SQL_BIG_SELECTS=1 om SELECTen er korrekt" - norwegian-ny "SELECT ville undersøkje for mange postar og ville sannsynligvis ta veldig lang tid. Undersøk WHERE klausulen og bruk SET SQL_BIG_SELECTS=1 om SELECTen er korrekt" - pol "Operacja SELECT bêdzie dotyczy³a zbyt wielu rekordów i prawdopodobnie zajmie bardzo du¿o czasu. Sprawd¥ warunek WHERE i u¿yj SQL_OPTION BIG_SELECTS=1 je?li operacja SELECT jest poprawna" - por "O SELECT examinaria registros demais e provavelmente levaria muito tempo. Cheque sua cláusula WHERE e use SET SQL_BIG_SELECTS=1, se o SELECT estiver correto" - rum "SELECT-ul ar examina prea multe cimpuri si probabil ar lua prea mult timp; verifica clauza WHERE si foloseste SET SQL_BIG_SELECTS=1 daca SELECT-ul e okay" - rus "äÌÑ ÔÁËÏÊ ×ÙÂÏÒËÉ SELECT ÄÏÌÖÅÎ ÂÕÄÅÔ ÐÒÏÓÍÏÔÒÅÔØ ÓÌÉÛËÏÍ ÍÎÏÇÏ ÚÁÐÉÓÅÊ É, ×ÉÄÉÍÏ, ÜÔÏ ÚÁÊÍÅÔ ÏÞÅÎØ ÍÎÏÇÏ ×ÒÅÍÅÎÉ. ðÒÏ×ÅÒØÔÅ ×ÁÛÅ ÕËÁÚÁÎÉÅ WHERE, É, ÅÓÌÉ × ÎÅÍ ×ÓÅ × ÐÏÒÑÄËÅ, ÕËÁÖÉÔÅ SET SQL_BIG_SELECTS=1" - serbian "Komanda 'SELECT' æe ispitati previše slogova i potrošiti previše vremena. Proverite vaš 'WHERE' filter i upotrebite 'SET OPTION SQL_BIG_SELECTS=1' ako želite baš ovakvu komandu" - slo "Zadaná po¾iadavka SELECT by prechádzala príli¹ mnoho záznamov a trvala by príli¹ dlho. Skontrolujte tvar WHERE a ak je v poriadku, pou¾ite SET SQL_BIG_SELECTS=1" - spa "El SELECT puede examinar muchos registros y probablemente con mucho tiempo. Verifique tu WHERE y usa SET SQL_BIG_SELECTS=1 si el SELECT esta correcto" - swe "Den angivna frågan skulle läsa mer än MAX_JOIN_SIZE rader. Kontrollera din WHERE och använd SET SQL_BIG_SELECTS=1 eller SET MAX_JOIN_SIZE=# ifall du vill hantera stora joins" - ukr "úÁÐÉÔÕ SELECT ÐÏÔÒ¦ÂÎÏ ÏÂÒÏÂÉÔÉ ÂÁÇÁÔÏ ÚÁÐÉÓ¦×, ÝÏ, ÐÅ×ÎÅ, ÚÁÊÍÅ ÄÕÖÅ ÂÁÇÁÔÏ ÞÁÓÕ. ðÅÒÅצÒÔÅ ×ÁÛÅ WHERE ÔÁ ×ÉËÏÒÉÓÔÏ×ÕÊÔÅ SET SQL_BIG_SELECTS=1, ÑËÝÏ ÃÅÊ ÚÁÐÉÔ SELECT ¤ צÒÎÉÍ" -ER_UNKNOWN_ERROR - cze "Nezn-Bámá chyba" - dan "Ukendt fejl" - nla "Onbekende Fout" - eng "Unknown error" - est "Tundmatu viga" - fre "Erreur inconnue" - ger "Unbekannter Fehler" - greek "ÐñïÝêõøå Üãíùóôï ëÜèïò" - hun "Ismeretlen hiba" - ita "Errore sconosciuto" - kor "¾Ë¼ö ¾ø´Â ¿¡·¯ÀÔ´Ï´Ù." - nor "Ukjent feil" - norwegian-ny "Ukjend feil" - por "Erro desconhecido" - rum "Eroare unknown" - rus "îÅÉÚ×ÅÓÔÎÁÑ ÏÛÉÂËÁ" - serbian "Nepoznata greška" - slo "Neznámá chyba" - spa "Error desconocido" - swe "Oidentifierat fel" - ukr "îÅצÄÏÍÁ ÐÏÍÉÌËÁ" -ER_UNKNOWN_PROCEDURE 42000 - cze "Nezn-Bámá procedura %-.192s" - dan "Ukendt procedure %-.192s" - nla "Onbekende procedure %-.192s" - eng "Unknown procedure '%-.192s'" - est "Tundmatu protseduur '%-.192s'" - fre "Procédure %-.192s inconnue" - ger "Unbekannte Prozedur '%-.192s'" - greek "Áãíùóôç äéáäéêáóßá '%-.192s'" - hun "Ismeretlen eljaras: '%-.192s'" - ita "Procedura '%-.192s' sconosciuta" - kor "¾Ë¼ö ¾ø´Â ¼öÇ๮ : '%-.192s'" - nor "Ukjent prosedyre %-.192s" - norwegian-ny "Ukjend prosedyre %-.192s" - pol "Unkown procedure %-.192s" - por "'Procedure' '%-.192s' desconhecida" - rum "Procedura unknown '%-.192s'" - rus "îÅÉÚ×ÅÓÔÎÁÑ ÐÒÏÃÅÄÕÒÁ '%-.192s'" - serbian "Nepoznata procedura '%-.192s'" - slo "Neznámá procedúra '%-.192s'" - spa "Procedimiento desconocido %-.192s" - swe "Okänd procedur: %-.192s" - ukr "îÅצÄÏÍÁ ÐÒÏÃÅÄÕÒÁ '%-.192s'" -ER_WRONG_PARAMCOUNT_TO_PROCEDURE 42000 - cze "Chybn-Bý poèet parametrù procedury %-.192s" - dan "Forkert antal parametre til proceduren %-.192s" - nla "Foutief aantal parameters doorgegeven aan procedure %-.192s" - eng "Incorrect parameter count to procedure '%-.192s'" - est "Vale parameetrite hulk protseduurile '%-.192s'" - fre "Mauvais nombre de paramètres pour la procedure %-.192s" - ger "Falsche Parameterzahl für Prozedur '%-.192s'" - greek "ËÜèïò áñéèìüò ðáñáìÝôñùí óôç äéáäéêáóßá '%-.192s'" - hun "Rossz parameter a(z) '%-.192s'eljaras szamitasanal" - ita "Numero di parametri errato per la procedura '%-.192s'" - kor "'%-.192s' ¼öÇ๮¿¡ ´ëÇÑ ºÎÁ¤È®ÇÑ ÆĶó¸ÞÅÍ" - nor "Feil parameter antall til prosedyren %-.192s" - norwegian-ny "Feil parameter tal til prosedyra %-.192s" - pol "Incorrect parameter count to procedure %-.192s" - por "Número de parâmetros incorreto para a 'procedure' '%-.192s'" - rum "Procedura '%-.192s' are un numar incorect de parametri" - rus "îÅËÏÒÒÅËÔÎÏÅ ËÏÌÉÞÅÓÔ×Ï ÐÁÒÁÍÅÔÒÏ× ÄÌÑ ÐÒÏÃÅÄÕÒÙ '%-.192s'" - serbian "Pogrešan broj parametara za proceduru '%-.192s'" - slo "Chybný poèet parametrov procedúry '%-.192s'" - spa "Equivocado parametro count para procedimiento %-.192s" - swe "Felaktigt antal parametrar till procedur %-.192s" - ukr "èÉÂÎÁ ˦ÌØ˦ÓÔØ ÐÁÒÁÍÅÔÒ¦× ÐÒÏÃÅÄÕÒÉ '%-.192s'" -ER_WRONG_PARAMETERS_TO_PROCEDURE - cze "Chybn-Bé parametry procedury %-.192s" - dan "Forkert(e) parametre til proceduren %-.192s" - nla "Foutieve parameters voor procedure %-.192s" - eng "Incorrect parameters to procedure '%-.192s'" - est "Vigased parameetrid protseduurile '%-.192s'" - fre "Paramètre erroné pour la procedure %-.192s" - ger "Falsche Parameter für Prozedur '%-.192s'" - greek "ËÜèïò ðáñÜìåôñïé óôçí äéáäéêáóßá '%-.192s'" - hun "Rossz parameter a(z) '%-.192s' eljarasban" - ita "Parametri errati per la procedura '%-.192s'" - kor "'%-.192s' ¼öÇ๮¿¡ ´ëÇÑ ºÎÁ¤È®ÇÑ ÆĶó¸ÞÅÍ" - nor "Feil parametre til prosedyren %-.192s" - norwegian-ny "Feil parameter til prosedyra %-.192s" - pol "Incorrect parameters to procedure %-.192s" - por "Parâmetros incorretos para a 'procedure' '%-.192s'" - rum "Procedura '%-.192s' are parametrii incorecti" - rus "îÅËÏÒÒÅËÔÎÙÅ ÐÁÒÁÍÅÔÒÙ ÄÌÑ ÐÒÏÃÅÄÕÒÙ '%-.192s'" - serbian "Pogrešni parametri prosleðeni proceduri '%-.192s'" - slo "Chybné parametre procedúry '%-.192s'" - spa "Equivocados parametros para procedimiento %-.192s" - swe "Felaktiga parametrar till procedur %-.192s" - ukr "èÉÂÎÉÊ ÐÁÒÁÍÅÔÅÒ ÐÒÏÃÅÄÕÒÉ '%-.192s'" -ER_UNKNOWN_TABLE 42S02 - cze "Nezn-Bámá tabulka '%-.192s' v %-.32s" - dan "Ukendt tabel '%-.192s' i %-.32s" - nla "Onbekende tabel '%-.192s' in %-.32s" - eng "Unknown table '%-.192s' in %-.32s" - est "Tundmatu tabel '%-.192s' %-.32s-s" - fre "Table inconnue '%-.192s' dans %-.32s" - ger "Unbekannte Tabelle '%-.192s' in '%-.32s'" - greek "Áãíùóôïò ðßíáêáò '%-.192s' óå %-.32s" - hun "Ismeretlen tabla: '%-.192s' %-.32s-ban" - ita "Tabella '%-.192s' sconosciuta in %-.32s" - jpn "Unknown table '%-.192s' in %-.32s" - kor "¾Ë¼ö ¾ø´Â Å×À̺í '%-.192s' (µ¥ÀÌŸº£À̽º %-.32s)" - nor "Ukjent tabell '%-.192s' i %-.32s" - norwegian-ny "Ukjend tabell '%-.192s' i %-.32s" - pol "Unknown table '%-.192s' in %-.32s" - por "Tabela '%-.192s' desconhecida em '%-.32s'" - rum "Tabla '%-.192s' invalida in %-.32s" - rus "îÅÉÚ×ÅÓÔÎÁÑ ÔÁÂÌÉÃÁ '%-.192s' × %-.32s" - serbian "Nepoznata tabela '%-.192s' u '%-.32s'" - slo "Neznáma tabuµka '%-.192s' v %-.32s" - spa "Tabla desconocida '%-.192s' in %-.32s" - swe "Okänd tabell '%-.192s' i '%-.32s'" - ukr "îÅצÄÏÍÁ ÔÁÂÌÉÃÑ '%-.192s' Õ %-.32s" -ER_FIELD_SPECIFIED_TWICE 42000 - cze "Polo-B¾ka '%-.192s' je zadána dvakrát" - dan "Feltet '%-.192s' er anvendt to gange" - nla "Veld '%-.192s' is dubbel gespecificeerd" - eng "Column '%-.192s' specified twice" - est "Tulp '%-.192s' on määratletud topelt" - fre "Champ '%-.192s' spécifié deux fois" - ger "Feld '%-.192s' wurde zweimal angegeben" - greek "Ôï ðåäßï '%-.192s' Ý÷åé ïñéóèåß äýï öïñÝò" - hun "A(z) '%-.192s' mezot ketszer definialta" - ita "Campo '%-.192s' specificato 2 volte" - kor "Ä®·³ '%-.192s'´Â µÎ¹ø Á¤ÀǵǾî ÀÖÀ¾´Ï´Ù." - nor "Feltet '%-.192s' er spesifisert to ganger" - norwegian-ny "Feltet '%-.192s' er spesifisert to gangar" - pol "Field '%-.192s' specified twice" - por "Coluna '%-.192s' especificada duas vezes" - rum "Coloana '%-.192s' specificata de doua ori" - rus "óÔÏÌÂÅà '%-.192s' ÕËÁÚÁÎ Ä×ÁÖÄÙ" - serbian "Kolona '%-.192s' je navedena dva puta" - slo "Pole '%-.192s' je zadané dvakrát" - spa "Campo '%-.192s' especificado dos veces" - swe "Fält '%-.192s' är redan använt" - ukr "óÔÏ×ÂÅÃØ '%-.192s' ÚÁÚÎÁÞÅÎÏ Äצަ" -ER_INVALID_GROUP_FUNC_USE - cze "Nespr-Bávné pou¾ití funkce group" - dan "Forkert brug af grupperings-funktion" - nla "Ongeldig gebruik van GROUP-functie" - eng "Invalid use of group function" - est "Vigane grupeerimisfunktsiooni kasutus" - fre "Utilisation invalide de la clause GROUP" - ger "Falsche Verwendung einer Gruppierungsfunktion" - greek "ÅóöáëìÝíç ÷ñÞóç ôçò group function" - hun "A group funkcio ervenytelen hasznalata" - ita "Uso non valido di una funzione di raggruppamento" - kor "À߸øµÈ ±×·ì ÇÔ¼ö¸¦ »ç¿ëÇÏ¿´½À´Ï´Ù." - por "Uso inválido de função de agrupamento (GROUP)" - rum "Folosire incorecta a functiei group" - rus "îÅÐÒÁ×ÉÌØÎÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ÇÒÕÐÐÏ×ÙÈ ÆÕÎËÃÉÊ" - serbian "Pogrešna upotreba 'GROUP' funkcije" - slo "Nesprávne pou¾itie funkcie GROUP" - spa "Invalido uso de función en grupo" - swe "Felaktig användning av SQL grupp function" - ukr "èÉÂÎÅ ×ÉËÏÒÉÓÔÁÎÎÑ ÆÕÎËæ§ ÇÒÕÐÕ×ÁÎÎÑ" -ER_UNSUPPORTED_EXTENSION 42000 - cze "Tabulka '%-.192s' pou-B¾ívá roz¹íøení, které v této verzi MySQL není" - dan "Tabellen '%-.192s' bruger et filtypenavn som ikke findes i denne MySQL version" - nla "Tabel '%-.192s' gebruikt een extensie, die niet in deze MySQL-versie voorkomt." - eng "Table '%-.192s' uses an extension that doesn't exist in this MySQL version" - est "Tabel '%-.192s' kasutab laiendust, mis ei eksisteeri antud MySQL versioonis" - fre "Table '%-.192s' : utilise une extension invalide pour cette version de MySQL" - ger "Tabelle '%-.192s' verwendet eine Erweiterung, die in dieser MySQL-Version nicht verfügbar ist" - greek "Ï ðßíáêò '%-.192s' ÷ñçóéìïðïéåß êÜðïéï extension ðïõ äåí õðÜñ÷åé óôçí Ýêäïóç áõôÞ ôçò MySQL" - hun "A(z) '%-.192s' tabla olyan bovitest hasznal, amely nem letezik ebben a MySQL versioban." - ita "La tabella '%-.192s' usa un'estensione che non esiste in questa versione di MySQL" - kor "Å×À̺í '%-.192s'´Â È®Àå¸í·ÉÀ» ÀÌ¿ëÇÏÁö¸¸ ÇöÀçÀÇ MySQL ¹öÁ¯¿¡¼´Â Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù." - nor "Table '%-.192s' uses a extension that doesn't exist in this MySQL version" - norwegian-ny "Table '%-.192s' uses a extension that doesn't exist in this MySQL version" - pol "Table '%-.192s' uses a extension that doesn't exist in this MySQL version" - por "Tabela '%-.192s' usa uma extensão que não existe nesta versão do MySQL" - rum "Tabela '%-.192s' foloseste o extensire inexistenta in versiunea curenta de MySQL" - rus "÷ ÔÁÂÌÉÃÅ '%-.192s' ÉÓÐÏÌØÚÕÀÔÓÑ ×ÏÚÍÏÖÎÏÓÔÉ, ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÍÙÅ × ÜÔÏÊ ×ÅÒÓÉÉ MySQL" - serbian "Tabela '%-.192s' koristi ekstenziju koje ne postoji u ovoj verziji MySQL-a" - slo "Tabuµka '%-.192s' pou¾íva roz¹írenie, ktoré v tejto verzii MySQL nie je" - spa "Tabla '%-.192s' usa una extensión que no existe en esta MySQL versión" - swe "Tabell '%-.192s' har en extension som inte finns i denna version av MySQL" - ukr "ôÁÂÌÉÃÑ '%-.192s' ×ÉËÏÒÉÓÔÏ×Õ¤ ÒÏÚÛÉÒÅÎÎÑ, ÝÏ ÎÅ ¦ÓÎÕ¤ Õ Ã¦Ê ×ÅÒÓ¦§ MySQL" -ER_TABLE_MUST_HAVE_COLUMNS 42000 - cze "Tabulka mus-Bí mít alespoò jeden sloupec" - dan "En tabel skal have mindst een kolonne" - nla "Een tabel moet minstens 1 kolom bevatten" - eng "A table must have at least 1 column" - jps "ƒe[ƒuƒ‹‚ÍÅ’á 1 ŒÂ‚Ì column ‚ª•K—v‚Å‚·", - est "Tabelis peab olema vähemalt üks tulp" - fre "Une table doit comporter au moins une colonne" - ger "Eine Tabelle muss mindestens eine Spalte besitzen" - greek "Åíáò ðßíáêáò ðñÝðåé íá Ý÷åé ôïõëÜ÷éóôïí Ýíá ðåäßï" - hun "A tablanak legalabb egy oszlopot tartalmazni kell" - ita "Una tabella deve avere almeno 1 colonna" - jpn "¥Æ¡¼¥Ö¥ë¤ÏºÇÄã 1 ¸Ä¤Î column ¤¬É¬ÍפǤ¹" - kor "ÇϳªÀÇ Å×ÀÌºí¿¡¼´Â Àû¾îµµ ÇϳªÀÇ Ä®·³ÀÌ Á¸ÀçÇÏ¿©¾ß ÇÕ´Ï´Ù." - por "Uma tabela tem que ter pelo menos uma (1) coluna" - rum "O tabela trebuie sa aiba cel putin o coloana" - rus "÷ ÔÁÂÌÉÃÅ ÄÏÌÖÅÎ ÂÙÔØ ËÁË ÍÉÎÉÍÕÍ ÏÄÉÎ ÓÔÏÌÂÅÃ" - serbian "Tabela mora imati najmanje jednu kolonu" - slo "Tabuµka musí ma» aspoò 1 pole" - spa "Una tabla debe tener al menos 1 columna" - swe "Tabeller måste ha minst 1 kolumn" - ukr "ôÁÂÌÉÃÑ ÐÏ×ÉÎÎÁ ÍÁÔÉ ÈÏÞÁ ÏÄÉÎ ÓÔÏ×ÂÅÃØ" -ER_RECORD_FILE_FULL - cze "Tabulka '%-.192s' je pln-Bá" - dan "Tabellen '%-.192s' er fuld" - nla "De tabel '%-.192s' is vol" - eng "The table '%-.192s' is full" - jps "table '%-.192s' ‚Í‚¢‚Á‚Ï‚¢‚Å‚·", - est "Tabel '%-.192s' on täis" - fre "La table '%-.192s' est pleine" - ger "Tabelle '%-.192s' ist voll" - greek "Ï ðßíáêáò '%-.192s' åßíáé ãåìÜôïò" - hun "A '%-.192s' tabla megtelt" - ita "La tabella '%-.192s' e` piena" - jpn "table '%-.192s' ¤Ï¤¤¤Ã¤Ñ¤¤¤Ç¤¹" - kor "Å×À̺í '%-.192s'°¡ full³µ½À´Ï´Ù. " - por "Tabela '%-.192s' está cheia" - rum "Tabela '%-.192s' e plina" - rus "ôÁÂÌÉÃÁ '%-.192s' ÐÅÒÅÐÏÌÎÅÎÁ" - serbian "Tabela '%-.192s' je popunjena do kraja" - slo "Tabuµka '%-.192s' je plná" - spa "La tabla '%-.192s' está llena" - swe "Tabellen '%-.192s' är full" - ukr "ôÁÂÌÉÃÑ '%-.192s' ÚÁÐÏ×ÎÅÎÁ" -ER_UNKNOWN_CHARACTER_SET 42000 - cze "Nezn-Bámá znaková sada: '%-.64s'" - dan "Ukendt tegnsæt: '%-.64s'" - nla "Onbekende character set: '%-.64s'" - eng "Unknown character set: '%-.64s'" - jps "character set '%-.64s' ‚̓Tƒ|[ƒg‚µ‚Ä‚¢‚Ü‚¹‚ñ", - est "Vigane kooditabel '%-.64s'" - fre "Jeu de caractères inconnu: '%-.64s'" - ger "Unbekannter Zeichensatz: '%-.64s'" - greek "Áãíùóôï character set: '%-.64s'" - hun "Ervenytelen karakterkeszlet: '%-.64s'" - ita "Set di caratteri '%-.64s' sconosciuto" - jpn "character set '%-.64s' ¤Ï¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤Þ¤»¤ó" - kor "¾Ë¼ö¾ø´Â ¾ð¾î Set: '%-.64s'" - por "Conjunto de caracteres '%-.64s' desconhecido" - rum "Set de caractere invalid: '%-.64s'" - rus "îÅÉÚ×ÅÓÔÎÁÑ ËÏÄÉÒÏ×ËÁ '%-.64s'" - serbian "Nepoznati karakter-set: '%-.64s'" - slo "Neznáma znaková sada: '%-.64s'" - spa "Juego de caracteres desconocido: '%-.64s'" - swe "Okänd teckenuppsättning: '%-.64s'" - ukr "îÅצÄÏÍÁ ËÏÄÏ×Á ÔÁÂÌÉÃÑ: '%-.64s'" -ER_TOO_MANY_TABLES - cze "P-Bøíli¹ mnoho tabulek, MySQL jich mù¾e mít v joinu jen %d" - dan "For mange tabeller. MySQL kan kun bruge %d tabeller i et join" - nla "Teveel tabellen. MySQL kan slechts %d tabellen in een join bevatten" - eng "Too many tables; MySQL can only use %d tables in a join" - jps "ƒe[ƒuƒ‹‚ª‘½‚·‚¬‚Ü‚·; MySQL can only use %d tables in a join", - est "Liiga palju tabeleid. MySQL suudab JOINiga ühendada kuni %d tabelit" - fre "Trop de tables. MySQL ne peut utiliser que %d tables dans un JOIN" - ger "Zu viele Tabellen. MySQL kann in einem Join maximal %d Tabellen verwenden" - greek "Ðïëý ìåãÜëïò áñéèìüò ðéíÜêùí. Ç MySQL ìðïñåß íá ÷ñçóéìïðïéÞóåé %d ðßíáêåò óå äéáäéêáóßá join" - hun "Tul sok tabla. A MySQL csak %d tablat tud kezelni osszefuzeskor" - ita "Troppe tabelle. MySQL puo` usare solo %d tabelle in una join" - jpn "¥Æ¡¼¥Ö¥ë¤¬Â¿¤¹¤®¤Þ¤¹; MySQL can only use %d tables in a join" - kor "³Ê¹« ¸¹Àº Å×À̺íÀÌ JoinµÇ¾ú½À´Ï´Ù. MySQL¿¡¼´Â JOIN½Ã %d°³ÀÇ Å×ÀÌºí¸¸ »ç¿ëÇÒ ¼ö ÀÖ½À´Ï´Ù." - por "Tabelas demais. O MySQL pode usar somente %d tabelas em uma junção (JOIN)" - rum "Prea multe tabele. MySQL nu poate folosi mai mult de %d tabele intr-un join" - rus "óÌÉÛËÏÍ ÍÎÏÇÏ ÔÁÂÌÉÃ. MySQL ÍÏÖÅÔ ÉÓÐÏÌØÚÏ×ÁÔØ ÔÏÌØËÏ %d ÔÁÂÌÉÃ × ÓÏÅÄÉÎÅÎÉÉ" - serbian "Previše tabela. MySQL može upotrebiti maksimum %d tabela pri 'JOIN' operaciji" - slo "Príli¹ mnoho tabuliek. MySQL mô¾e pou¾i» len %d v JOIN-e" - spa "Muchas tablas. MySQL solamente puede usar %d tablas en un join" - swe "För många tabeller. MySQL can ha högst %d tabeller i en och samma join" - ukr "úÁÂÁÇÁÔÏ ÔÁÂÌÉÃØ. MySQL ÍÏÖÅ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ ÌÉÛÅ %d ÔÁÂÌÉÃØ Õ ÏÂ'¤ÄÎÁÎΦ" -ER_TOO_MANY_FIELDS - cze "P-Bøíli¹ mnoho polo¾ek" - dan "For mange felter" - nla "Te veel velden" - eng "Too many columns" - jps "column ‚ª‘½‚·‚¬‚Ü‚·", - est "Liiga palju tulpasid" - fre "Trop de champs" - ger "Zu viele Felder" - greek "Ðïëý ìåãÜëïò áñéèìüò ðåäßùí" - hun "Tul sok mezo" - ita "Troppi campi" - jpn "column ¤¬Â¿¤¹¤®¤Þ¤¹" - kor "Ä®·³ÀÌ ³Ê¹« ¸¹½À´Ï´Ù." - por "Colunas demais" - rum "Prea multe coloane" - rus "óÌÉÛËÏÍ ÍÎÏÇÏ ÓÔÏÌÂÃÏ×" - serbian "Previše kolona" - slo "Príli¹ mnoho polí" - spa "Muchos campos" - swe "För många fält" - ukr "úÁÂÁÇÁÔÏ ÓÔÏ×Âæ×" -ER_TOO_BIG_ROWSIZE 42000 - cze "-BØádek je pøíli¹ velký. Maximální velikost øádku, nepoèítaje polo¾ky blob, je %ld. Musíte zmìnit nìkteré polo¾ky na blob" - dan "For store poster. Max post størrelse, uden BLOB's, er %ld. Du må lave nogle felter til BLOB's" - nla "Rij-grootte is groter dan toegestaan. Maximale rij grootte, blobs niet meegeteld, is %ld. U dient sommige velden in blobs te veranderen." - eng "Row size too large. The maximum row size for the used table type, not counting BLOBs, is %ld. You have to change some columns to TEXT or BLOBs" - jps "row size ‚ª‘å‚«‚·‚¬‚Ü‚·. BLOB ‚ðŠÜ‚Ü‚È‚¢ê‡‚Ì row size ‚ÌÅ‘å‚Í %ld ‚Å‚·. ‚¢‚‚‚©‚Ì field ‚ð BLOB ‚É•Ï‚¦‚Ä‚‚¾‚³‚¢.", - est "Liiga pikk kirje. Kirje maksimumpikkus arvestamata BLOB-tüüpi välju on %ld. Muuda mõned väljad BLOB-tüüpi väljadeks" - fre "Ligne trop grande. Le taille maximale d'une ligne, sauf les BLOBs, est %ld. Changez le type de quelques colonnes en BLOB" - ger "Zeilenlänge zu groß. Die maximale Zeilenlänge für den verwendeten Tabellentyp (ohne BLOB-Felder) beträgt %ld. Einige Felder müssen in BLOB oder TEXT umgewandelt werden" - greek "Ðïëý ìåãÜëï ìÝãåèïò åããñáöÞò. Ôï ìÝãéóôï ìÝãåèïò åããñáöÞò, ÷ùñßò íá õðïëïãßæïíôáé ôá blobs, åßíáé %ld. ÐñÝðåé íá ïñßóåôå êÜðïéá ðåäßá óáí blobs" - hun "Tul nagy sormeret. A maximalis sormeret (nem szamolva a blob objektumokat) %ld. Nehany mezot meg kell valtoztatnia" - ita "Riga troppo grande. La massima grandezza di una riga, non contando i BLOB, e` %ld. Devi cambiare alcuni campi in BLOB" - jpn "row size ¤¬Â礤¹¤®¤Þ¤¹. BLOB ¤ò´Þ¤Þ¤Ê¤¤¾ì¹ç¤Î row size ¤ÎºÇÂç¤Ï %ld ¤Ç¤¹. ¤¤¤¯¤Ä¤«¤Î field ¤ò BLOB ¤ËÊѤ¨¤Æ¤¯¤À¤µ¤¤." - kor "³Ê¹« Å« row »çÀÌÁîÀÔ´Ï´Ù. BLOB¸¦ °è»êÇÏÁö ¾Ê°í ÃÖ´ë row »çÀÌÁî´Â %ldÀÔ´Ï´Ù. ¾ó¸¶°£ÀÇ ÇʵåµéÀ» BLOB·Î ¹Ù²Ù¼Å¾ß °Ú±º¿ä.." - por "Tamanho de linha grande demais. O máximo tamanho de linha, não contando BLOBs, é %ld. Você tem que mudar alguns campos para BLOBs" - rum "Marimea liniei (row) prea mare. Marimea maxima a liniei, excluzind BLOB-urile este de %ld. Trebuie sa schimbati unele cimpuri in BLOB-uri" - rus "óÌÉÛËÏÍ ÂÏÌØÛÏÊ ÒÁÚÍÅÒ ÚÁÐÉÓÉ. íÁËÓÉÍÁÌØÎÙÊ ÒÁÚÍÅÒ ÓÔÒÏËÉ, ÉÓËÌÀÞÁÑ ÐÏÌÑ BLOB, - %ld. ÷ÏÚÍÏÖÎÏ, ×ÁÍ ÓÌÅÄÕÅÔ ÉÚÍÅÎÉÔØ ÔÉÐ ÎÅËÏÔÏÒÙÈ ÐÏÌÅÊ ÎÁ BLOB" - serbian "Prevelik slog. Maksimalna velièina sloga, ne raèunajuæi BLOB polja, je %ld. Trebali bi da promenite tip nekih polja u BLOB" - slo "Riadok je príli¹ veµký. Maximálna veµkos» riadku, okrem 'BLOB', je %ld. Musíte zmeni» niektoré polo¾ky na BLOB" - spa "Tamaño de línea muy grande. Máximo tamaño de línea, no contando blob, es %ld. Tu tienes que cambiar algunos campos para blob" - swe "För stor total radlängd. Den högst tillåtna radlängden, förutom BLOBs, är %ld. Ändra några av dina fält till BLOB" - ukr "úÁÄÏ×ÇÁ ÓÔÒÏËÁ. îÁʦÌØÛÏÀ ÄÏ×ÖÉÎÏÀ ÓÔÒÏËÉ, ÎÅ ÒÁÈÕÀÞÉ BLOB, ¤ %ld. ÷ÁÍ ÐÏÔÒ¦ÂÎÏ ÐÒÉ×ÅÓÔÉ ÄÅÑ˦ ÓÔÏ×Âæ ÄÏ ÔÉÐÕ BLOB" -ER_STACK_OVERRUN - cze "P-Bøeteèení zásobníku threadu: pou¾ito %ld z %ld. Pou¾ijte 'mysqld -O thread_stack=#' k zadání vìt¹ího zásobníku" - dan "Thread stack brugt: Brugt: %ld af en %ld stak. Brug 'mysqld -O thread_stack=#' for at allokere en større stak om nødvendigt" - nla "Thread stapel overrun: Gebruikte: %ld van een %ld stack. Gebruik 'mysqld -O thread_stack=#' om een grotere stapel te definieren (indien noodzakelijk)." - eng "Thread stack overrun: Used: %ld of a %ld stack. Use 'mysqld -O thread_stack=#' to specify a bigger stack if needed" - jps "Thread stack overrun: Used: %ld of a %ld stack. ƒXƒ^ƒbƒN—̈æ‚𑽂‚Ƃ肽‚¢ê‡A'mysqld -O thread_stack=#' ‚ÆŽw’肵‚Ä‚‚¾‚³‚¢", - fre "Débordement de la pile des tâches (Thread stack). Utilisées: %ld pour une pile de %ld. Essayez 'mysqld -O thread_stack=#' pour indiquer une plus grande valeur" - ger "Thread-Stack-Überlauf. Benutzt: %ld von %ld Stack. 'mysqld -O thread_stack=#' verwenden, um bei Bedarf einen größeren Stack anzulegen" - greek "Stack overrun óôï thread: Used: %ld of a %ld stack. Ðáñáêáëþ ÷ñçóéìïðïéåßóôå 'mysqld -O thread_stack=#' ãéá íá ïñßóåôå Ýíá ìåãáëýôåñï stack áí ÷ñåéÜæåôáé" - hun "Thread verem tullepes: Used: %ld of a %ld stack. Hasznalja a 'mysqld -O thread_stack=#' nagyobb verem definialasahoz" - ita "Thread stack overrun: Usati: %ld di uno stack di %ld. Usa 'mysqld -O thread_stack=#' per specificare uno stack piu` grande." - jpn "Thread stack overrun: Used: %ld of a %ld stack. ¥¹¥¿¥Ã¥¯Îΰè¤ò¿¤¯¤È¤ê¤¿¤¤¾ì¹ç¡¢'mysqld -O thread_stack=#' ¤È»ØÄꤷ¤Æ¤¯¤À¤µ¤¤" - kor "¾²·¹µå ½ºÅÃÀÌ ³ÑÃƽÀ´Ï´Ù. »ç¿ë: %ld°³ ½ºÅÃ: %ld°³. ¸¸¾à ÇÊ¿ä½Ã ´õÅ« ½ºÅÃÀ» ¿øÇÒ¶§¿¡´Â 'mysqld -O thread_stack=#' ¸¦ Á¤ÀÇÇϼ¼¿ä" - por "Estouro da pilha do 'thread'. Usados %ld de uma pilha de %ld. Use 'mysqld -O thread_stack=#' para especificar uma pilha maior, se necessário" - rum "Stack-ul thread-ului a fost depasit (prea mic): Folositi: %ld intr-un stack de %ld. Folositi 'mysqld -O thread_stack=#' ca sa specifici un stack mai mare" - rus "óÔÅË ÐÏÔÏËÏ× ÐÅÒÅÐÏÌÎÅÎ: ÉÓÐÏÌØÚÏ×ÁÎÏ: %ld ÉÚ %ld ÓÔÅËÁ. ðÒÉÍÅÎÑÊÔÅ 'mysqld -O thread_stack=#' ÄÌÑ ÕËÁÚÁÎÉÑ ÂÏÌØÛÅÇÏ ÒÁÚÍÅÒÁ ÓÔÅËÁ, ÅÓÌÉ ÎÅÏÂÈÏÄÉÍÏ" - serbian "Prepisivanje thread stack-a: Upotrebljeno: %ld od %ld stack memorije. Upotrebite 'mysqld -O thread_stack=#' da navedete veæi stack ako je potrebno" - slo "Preteèenie zásobníku vlákna: pou¾ité: %ld z %ld. Pou¾ite 'mysqld -O thread_stack=#' k zadaniu väè¹ieho zásobníka" - spa "Sobrecarga de la pila de thread: Usada: %ld de una %ld pila. Use 'mysqld -O thread_stack=#' para especificar una mayor pila si necesario" - swe "Trådstacken tog slut: Har använt %ld av %ld bytes. Använd 'mysqld -O thread_stack=#' ifall du behöver en större stack" - ukr "óÔÅË Ç¦ÌÏË ÐÅÒÅÐÏ×ÎÅÎÏ: ÷ÉËÏÒÉÓÔÁÎÏ: %ld Ú %ld. ÷ÉËÏÒÉÓÔÏ×ÕÊÔÅ 'mysqld -O thread_stack=#' ÁÂÉ ÚÁÚÎÁÞÉÔÉ Â¦ÌØÛÉÊ ÓÔÅË, ÑËÝÏ ÎÅÏÂȦÄÎÏ" -ER_WRONG_OUTER_JOIN 42000 - cze "V OUTER JOIN byl nalezen k-Bøí¾ový odkaz. Provìøte ON podmínky" - dan "Krydsreferencer fundet i OUTER JOIN; check dine ON conditions" - nla "Gekruiste afhankelijkheid gevonden in OUTER JOIN. Controleer uw ON-conditions" - eng "Cross dependency found in OUTER JOIN; examine your ON conditions" - est "Ristsõltuvus OUTER JOIN klauslis. Kontrolli oma ON tingimusi" - fre "Dépendance croisée dans une clause OUTER JOIN. Vérifiez la condition ON" - ger "OUTER JOIN enthält fehlerhafte Abhängigkeiten. In ON verwendete Bedingungen überprüfen" - greek "Cross dependency âñÝèçêå óå OUTER JOIN. Ðáñáêáëþ åîåôÜóôå ôéò óõíèÞêåò ðïõ èÝóáôå óôï ON" - hun "Keresztfuggoseg van az OUTER JOIN-ban. Ellenorizze az ON felteteleket" - ita "Trovata una dipendenza incrociata nella OUTER JOIN. Controlla le condizioni ON" - por "Dependência cruzada encontrada em junção externa (OUTER JOIN); examine as condições utilizadas nas cláusulas 'ON'" - rum "Dependinta incrucisata (cross dependency) gasita in OUTER JOIN. Examinati conditiile ON" - rus "÷ OUTER JOIN ÏÂÎÁÒÕÖÅÎÁ ÐÅÒÅËÒÅÓÔÎÁÑ ÚÁ×ÉÓÉÍÏÓÔØ. ÷ÎÉÍÁÔÅÌØÎÏ ÐÒÏÁÎÁÌÉÚÉÒÕÊÔÅ Ó×ÏÉ ÕÓÌÏ×ÉÑ ON" - serbian "Unakrsna zavisnost pronaðena u komandi 'OUTER JOIN'. Istražite vaše 'ON' uslove" - slo "V OUTER JOIN bol nájdený krí¾ový odkaz. Skontrolujte podmienky ON" - spa "Dependencia cruzada encontrada en OUTER JOIN. Examine su condición ON" - swe "Felaktigt referens i OUTER JOIN. Kontrollera ON-uttrycket" - ukr "ðÅÒÅÈÒÅÓÎÁ ÚÁÌÅÖΦÓÔØ Õ OUTER JOIN. ðÅÒÅצÒÔÅ ÕÍÏ×Õ ON" -ER_NULL_COLUMN_IN_INDEX 42000 - eng "Table handler doesn't support NULL in given index. Please change column '%-.192s' to be NOT NULL or use another handler" - swe "Tabell hanteraren kan inte indexera NULL kolumner för den givna index typen. Ändra '%-.192s' till NOT NULL eller använd en annan hanterare" -ER_CANT_FIND_UDF - cze "Nemohu na-Bèíst funkci '%-.192s'" - dan "Kan ikke læse funktionen '%-.192s'" - nla "Kan functie '%-.192s' niet laden" - eng "Can't load function '%-.192s'" - jps "function '%-.192s' ‚ð ƒ[ƒh‚Å‚«‚Ü‚¹‚ñ", - est "Ei suuda avada funktsiooni '%-.192s'" - fre "Imposible de charger la fonction '%-.192s'" - ger "Kann Funktion '%-.192s' nicht laden" - greek "Äåí åßíáé äõíáôÞ ç äéáäéêáóßá load ãéá ôç óõíÜñôçóç '%-.192s'" - hun "A(z) '%-.192s' fuggveny nem toltheto be" - ita "Impossibile caricare la funzione '%-.192s'" - jpn "function '%-.192s' ¤ò ¥í¡¼¥É¤Ç¤¤Þ¤»¤ó" - kor "'%-.192s' ÇÔ¼ö¸¦ ·ÎµåÇÏÁö ¸øÇß½À´Ï´Ù." - por "Não pode carregar a função '%-.192s'" - rum "Nu pot incarca functia '%-.192s'" - rus "îÅ×ÏÚÍÏÖÎÏ ÚÁÇÒÕÚÉÔØ ÆÕÎËÃÉÀ '%-.192s'" - serbian "Ne mogu da uèitam funkciju '%-.192s'" - slo "Nemô¾em naèíta» funkciu '%-.192s'" - spa "No puedo cargar función '%-.192s'" - swe "Kan inte ladda funktionen '%-.192s'" - ukr "îÅ ÍÏÖÕ ÚÁ×ÁÎÔÁÖÉÔÉ ÆÕÎËæÀ '%-.192s'" -ER_CANT_INITIALIZE_UDF - cze "Nemohu inicializovat funkci '%-.192s'; %-.80s" - dan "Kan ikke starte funktionen '%-.192s'; %-.80s" - nla "Kan functie '%-.192s' niet initialiseren; %-.80s" - eng "Can't initialize function '%-.192s'; %-.80s" - jps "function '%-.192s' ‚ð‰Šú‰»‚Å‚«‚Ü‚¹‚ñ; %-.80s", - est "Ei suuda algväärtustada funktsiooni '%-.192s'; %-.80s" - fre "Impossible d'initialiser la fonction '%-.192s'; %-.80s" - ger "Kann Funktion '%-.192s' nicht initialisieren: %-.80s" - greek "Äåí åßíáé äõíáôÞ ç Ýíáñîç ôçò óõíÜñôçóçò '%-.192s'; %-.80s" - hun "A(z) '%-.192s' fuggveny nem inicializalhato; %-.80s" - ita "Impossibile inizializzare la funzione '%-.192s'; %-.80s" - jpn "function '%-.192s' ¤ò½é´ü²½¤Ç¤¤Þ¤»¤ó; %-.80s" - kor "'%-.192s' ÇÔ¼ö¸¦ ÃʱâÈ ÇÏÁö ¸øÇß½À´Ï´Ù.; %-.80s" - por "Não pode inicializar a função '%-.192s' - '%-.80s'" - rum "Nu pot initializa functia '%-.192s'; %-.80s" - rus "îÅ×ÏÚÍÏÖÎÏ ÉÎÉÃÉÁÌÉÚÉÒÏ×ÁÔØ ÆÕÎËÃÉÀ '%-.192s'; %-.80s" - serbian "Ne mogu da inicijalizujem funkciju '%-.192s'; %-.80s" - slo "Nemô¾em inicializova» funkciu '%-.192s'; %-.80s" - spa "No puedo inicializar función '%-.192s'; %-.80s" - swe "Kan inte initialisera funktionen '%-.192s'; '%-.80s'" - ukr "îÅ ÍÏÖÕ ¦Î¦Ã¦Á̦ÚÕ×ÁÔÉ ÆÕÎËæÀ '%-.192s'; %-.80s" -ER_UDF_NO_PATHS - cze "Pro sd-Bílenou knihovnu nejsou povoleny cesty" - dan "Angivelse af sti ikke tilladt for delt bibliotek" - nla "Geen pad toegestaan voor shared library" - eng "No paths allowed for shared library" - jps "shared library ‚ւ̃pƒX‚ª’Ê‚Á‚Ä‚¢‚Ü‚¹‚ñ", - est "Teegi nimes ei tohi olla kataloogi" - fre "Chemin interdit pour les bibliothèques partagées" - ger "Keine Pfade gestattet für Shared Library" - greek "Äåí âñÝèçêáí paths ãéá ôçí shared library" - hun "Nincs ut a megosztott konyvtarakhoz (shared library)" - ita "Non sono ammessi path per le librerie condivisa" - jpn "shared library ¤Ø¤Î¥Ñ¥¹¤¬Ä̤äƤ¤¤Þ¤»¤ó" - kor "°øÀ¯ ¶óÀ̹ö·¯¸®¸¦ À§ÇÑ Æнº°¡ Á¤ÀǵǾî ÀÖÁö ¾Ê½À´Ï´Ù." - por "Não há caminhos (paths) permitidos para biblioteca compartilhada" - rum "Nici un paths nu e permis pentru o librarie shared" - rus "îÅÄÏÐÕÓÔÉÍÏ ÕËÁÚÙ×ÁÔØ ÐÕÔÉ ÄÌÑ ÄÉÎÁÍÉÞÅÓËÉÈ ÂÉÂÌÉÏÔÅË" - serbian "Ne postoje dozvoljene putanje do share-ovane biblioteke" - slo "Neprípustné ¾iadne cesty k zdieµanej kni¾nici" - spa "No pasos permitidos para librarias conjugadas" - swe "Man får inte ange sökväg för dynamiska bibliotek" - ukr "îÅ ÄÏÚ×ÏÌÅÎÏ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ ÐÕÔ¦ ÄÌÑ ÒÏÚĦÌÀ×ÁÎÉÈ Â¦Â̦ÏÔÅË" -ER_UDF_EXISTS - cze "Funkce '%-.192s' ji-B¾ existuje" - dan "Funktionen '%-.192s' findes allerede" - nla "Functie '%-.192s' bestaat reeds" - eng "Function '%-.192s' already exists" - jps "Function '%-.192s' ‚ÍŠù‚É’è‹`‚³‚ê‚Ä‚¢‚Ü‚·", - est "Funktsioon '%-.192s' juba eksisteerib" - fre "La fonction '%-.192s' existe déjà" - ger "Funktion '%-.192s' existiert schon" - greek "Ç óõíÜñôçóç '%-.192s' õðÜñ÷åé Þäç" - hun "A '%-.192s' fuggveny mar letezik" - ita "La funzione '%-.192s' esiste gia`" - jpn "Function '%-.192s' ¤Ï´û¤ËÄêµÁ¤µ¤ì¤Æ¤¤¤Þ¤¹" - kor "'%-.192s' ÇÔ¼ö´Â ÀÌ¹Ì Á¸ÀçÇÕ´Ï´Ù." - por "Função '%-.192s' já existe" - rum "Functia '%-.192s' exista deja" - rus "æÕÎËÃÉÑ '%-.192s' ÕÖÅ ÓÕÝÅÓÔ×ÕÅÔ" - serbian "Funkcija '%-.192s' veæ postoji" - slo "Funkcia '%-.192s' u¾ existuje" - spa "Función '%-.192s' ya existe" - swe "Funktionen '%-.192s' finns redan" - ukr "æÕÎËÃ¦Ñ '%-.192s' ×ÖÅ ¦ÓÎÕ¤" -ER_CANT_OPEN_LIBRARY - cze "Nemohu otev-Bøít sdílenou knihovnu '%-.192s' (errno: %d %-.128s)" - dan "Kan ikke åbne delt bibliotek '%-.192s' (errno: %d %-.128s)" - nla "Kan shared library '%-.192s' niet openen (Errcode: %d %-.128s)" - eng "Can't open shared library '%-.192s' (errno: %d %-.128s)" - jps "shared library '%-.192s' ‚ðŠJ‚Ž–‚ª‚Å‚«‚Ü‚¹‚ñ (errno: %d %-.128s)", - est "Ei suuda avada jagatud teeki '%-.192s' (veakood: %d %-.128s)" - fre "Impossible d'ouvrir la bibliothèque partagée '%-.192s' (errno: %d %-.128s)" - ger "Kann Shared Library '%-.192s' nicht öffnen (Fehler: %d %-.128s)" - greek "Äåí åßíáé äõíáôÞ ç áíÜãíùóç ôçò shared library '%-.192s' (êùäéêüò ëÜèïõò: %d %-.128s)" - hun "A(z) '%-.192s' megosztott konyvtar nem hasznalhato (hibakod: %d %-.128s)" - ita "Impossibile aprire la libreria condivisa '%-.192s' (errno: %d %-.128s)" - jpn "shared library '%-.192s' ¤ò³«¤¯»ö¤¬¤Ç¤¤Þ¤»¤ó (errno: %d %-.128s)" - kor "'%-.192s' °øÀ¯ ¶óÀ̹ö·¯¸®¸¦ ¿¼ö ¾ø½À´Ï´Ù.(¿¡·¯¹øÈ£: %d %-.128s)" - nor "Can't open shared library '%-.192s' (errno: %d %-.128s)" - norwegian-ny "Can't open shared library '%-.192s' (errno: %d %-.128s)" - pol "Can't open shared library '%-.192s' (errno: %d %-.128s)" - por "Não pode abrir biblioteca compartilhada '%-.192s' (erro no. %d '%-.128s')" - rum "Nu pot deschide libraria shared '%-.192s' (Eroare: %d %-.128s)" - rus "îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÄÉÎÁÍÉÞÅÓËÕÀ ÂÉÂÌÉÏÔÅËÕ '%-.192s' (ÏÛÉÂËÁ: %d %-.128s)" - serbian "Ne mogu da otvorim share-ovanu biblioteku '%-.192s' (errno: %d %-.128s)" - slo "Nemô¾em otvori» zdieµanú kni¾nicu '%-.192s' (chybový kód: %d %-.128s)" - spa "No puedo abrir libraria conjugada '%-.192s' (errno: %d %-.128s)" - swe "Kan inte öppna det dynamiska biblioteket '%-.192s' (Felkod: %d %-.128s)" - ukr "îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÒÏÚĦÌÀ×ÁÎÕ Â¦Â̦ÏÔÅËÕ '%-.192s' (ÐÏÍÉÌËÁ: %d %-.128s)" -ER_CANT_FIND_DL_ENTRY - cze "Nemohu naj-Bít funkci '%-.128s' v knihovnì" - dan "Kan ikke finde funktionen '%-.128s' i bibliotek" - nla "Kan functie '%-.128s' niet in library vinden" - eng "Can't find symbol '%-.128s' in library" - jps "function '%-.128s' ‚ðƒ‰ƒCƒuƒ‰ƒŠ[’†‚ÉŒ©•t‚¯‚鎖‚ª‚Å‚«‚Ü‚¹‚ñ", - est "Ei leia funktsiooni '%-.128s' antud teegis" - fre "Impossible de trouver la fonction '%-.128s' dans la bibliothèque" - ger "Kann Funktion '%-.128s' in der Library nicht finden" - greek "Äåí åßíáé äõíáôÞ ç áíåýñåóç ôçò óõíÜñôçóçò '%-.128s' óôçí âéâëéïèÞêç" - hun "A(z) '%-.128s' fuggveny nem talalhato a konyvtarban" - ita "Impossibile trovare la funzione '%-.128s' nella libreria" - jpn "function '%-.128s' ¤ò¥é¥¤¥Ö¥é¥ê¡¼Ãæ¤Ë¸«ÉÕ¤±¤ë»ö¤¬¤Ç¤¤Þ¤»¤ó" - kor "¶óÀ̹ö·¯¸®¿¡¼ '%-.128s' ÇÔ¼ö¸¦ ãÀ» ¼ö ¾ø½À´Ï´Ù." - por "Não pode encontrar a função '%-.128s' na biblioteca" - rum "Nu pot gasi functia '%-.128s' in libraria" - rus "îÅ×ÏÚÍÏÖÎÏ ÏÔÙÓËÁÔØ ÓÉÍ×ÏÌ '%-.128s' × ÂÉÂÌÉÏÔÅËÅ" - serbian "Ne mogu da pronadjem funkciju '%-.128s' u biblioteci" - slo "Nemô¾em nájs» funkciu '%-.128s' v kni¾nici" - spa "No puedo encontrar función '%-.128s' en libraria" - swe "Hittar inte funktionen '%-.128s' in det dynamiska biblioteket" - ukr "îÅ ÍÏÖÕ ÚÎÁÊÔÉ ÆÕÎËæÀ '%-.128s' Õ Â¦Â̦ÏÔÅæ" -ER_FUNCTION_NOT_DEFINED - cze "Funkce '%-.192s' nen-Bí definována" - dan "Funktionen '%-.192s' er ikke defineret" - nla "Functie '%-.192s' is niet gedefinieerd" - eng "Function '%-.192s' is not defined" - jps "Function '%-.192s' ‚Í’è‹`‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ", - est "Funktsioon '%-.192s' ei ole defineeritud" - fre "La fonction '%-.192s' n'est pas définie" - ger "Funktion '%-.192s' ist nicht definiert" - greek "Ç óõíÜñôçóç '%-.192s' äåí Ý÷åé ïñéóèåß" - hun "A '%-.192s' fuggveny nem definialt" - ita "La funzione '%-.192s' non e` definita" - jpn "Function '%-.192s' ¤ÏÄêµÁ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" - kor "'%-.192s' ÇÔ¼ö°¡ Á¤ÀǵǾî ÀÖÁö ¾Ê½À´Ï´Ù." - por "Função '%-.192s' não está definida" - rum "Functia '%-.192s' nu e definita" - rus "æÕÎËÃÉÑ '%-.192s' ÎÅ ÏÐÒÅÄÅÌÅÎÁ" - serbian "Funkcija '%-.192s' nije definisana" - slo "Funkcia '%-.192s' nie je definovaná" - spa "Función '%-.192s' no está definida" - swe "Funktionen '%-.192s' är inte definierad" - ukr "æÕÎËæÀ '%-.192s' ÎÅ ×ÉÚÎÁÞÅÎÏ" -ER_HOST_IS_BLOCKED - cze "Stroj '%-.64s' je zablokov-Bán kvùli mnoha chybám pøi pøipojování. Odblokujete pou¾itím 'mysqladmin flush-hosts'" - dan "Værten '%-.64s' er blokeret på grund af mange fejlforespørgsler. Lås op med 'mysqladmin flush-hosts'" - nla "Host '%-.64s' is geblokkeeerd vanwege te veel verbindings fouten. Deblokkeer met 'mysqladmin flush-hosts'" - eng "Host '%-.64s' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'" - jps "Host '%-.64s' ‚Í many connection error ‚Ì‚½‚ßA‹‘”Û‚³‚ê‚Ü‚µ‚½. 'mysqladmin flush-hosts' ‚ʼn𜂵‚Ä‚‚¾‚³‚¢", - est "Masin '%-.64s' on blokeeritud hulgaliste ühendusvigade tõttu. Blokeeringu saab tühistada 'mysqladmin flush-hosts' käsuga" - fre "L'hôte '%-.64s' est bloqué à cause d'un trop grand nombre d'erreur de connexion. Débloquer le par 'mysqladmin flush-hosts'" - ger "Host '%-.64s' blockiert wegen zu vieler Verbindungsfehler. Aufheben der Blockierung mit 'mysqladmin flush-hosts'" - greek "Ï õðïëïãéóôÞò '%-.64s' Ý÷åé áðïêëåéóèåß ëüãù ðïëëáðëþí ëáèþí óýíäåóçò. ÐñïóðáèÞóôå íá äéïñþóåôå ìå 'mysqladmin flush-hosts'" - hun "A '%-.64s' host blokkolodott, tul sok kapcsolodasi hiba miatt. Hasznalja a 'mysqladmin flush-hosts' parancsot" - ita "Sistema '%-.64s' bloccato a causa di troppi errori di connessione. Per sbloccarlo: 'mysqladmin flush-hosts'" - jpn "Host '%-.64s' ¤Ï many connection error ¤Î¤¿¤á¡¢µñÈݤµ¤ì¤Þ¤·¤¿. 'mysqladmin flush-hosts' ¤Ç²ò½ü¤·¤Æ¤¯¤À¤µ¤¤" - kor "³Ê¹« ¸¹Àº ¿¬°á¿À·ù·Î ÀÎÇÏ¿© È£½ºÆ® '%-.64s'´Â ºí¶ôµÇ¾ú½À´Ï´Ù. 'mysqladmin flush-hosts'¸¦ ÀÌ¿ëÇÏ¿© ºí¶ôÀ» ÇØÁ¦Çϼ¼¿ä" - por "'Host' '%-.64s' está bloqueado devido a muitos erros de conexão. Desbloqueie com 'mysqladmin flush-hosts'" - rum "Host-ul '%-.64s' e blocat din cauza multelor erori de conectie. Poti deploca folosind 'mysqladmin flush-hosts'" - rus "èÏÓÔ '%-.64s' ÚÁÂÌÏËÉÒÏ×ÁÎ ÉÚ-ÚÁ ÓÌÉÛËÏÍ ÂÏÌØÛÏÇÏ ËÏÌÉÞÅÓÔ×Á ÏÛÉÂÏË ÓÏÅÄÉÎÅÎÉÑ. òÁÚÂÌÏËÉÒÏ×ÁÔØ ÅÇÏ ÍÏÖÎÏ Ó ÐÏÍÏÝØÀ 'mysqladmin flush-hosts'" - serbian "Host '%-.64s' je blokiran zbog previše grešaka u konekciji. Možete ga odblokirati pomoæu komande 'mysqladmin flush-hosts'" - spa "Servidor '%-.64s' está bloqueado por muchos errores de conexión. Desbloquear con 'mysqladmin flush-hosts'" - swe "Denna dator, '%-.64s', är blockerad pga många felaktig paket. Gör 'mysqladmin flush-hosts' för att ta bort alla blockeringarna" - ukr "èÏÓÔ '%-.64s' ÚÁÂÌÏËÏ×ÁÎÏ Ú ÐÒÉÞÉÎÉ ×ÅÌÉËϧ ˦ÌØËÏÓÔ¦ ÐÏÍÉÌÏË Ú'¤ÄÎÁÎÎÑ. äÌÑ ÒÏÚÂÌÏËÕ×ÁÎÎÑ ×ÉËÏÒÉÓÔÏ×ÕÊÔÅ 'mysqladmin flush-hosts'" -ER_HOST_NOT_PRIVILEGED - cze "Stroj '%-.64s' nem-Bá povoleno se k tomuto MySQL serveru pøipojit" - dan "Værten '%-.64s' kan ikke tilkoble denne MySQL-server" - nla "Het is host '%-.64s' is niet toegestaan verbinding te maken met deze MySQL server" - eng "Host '%-.64s' is not allowed to connect to this MySQL server" - jps "Host '%-.64s' ‚Í MySQL server ‚ÉÚ‘±‚ð‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ", - est "Masinal '%-.64s' puudub ligipääs sellele MySQL serverile" - fre "Le hôte '%-.64s' n'est pas authorisé à se connecter à ce serveur MySQL" - ger "Host '%-.64s' hat keine Berechtigung, sich mit diesem MySQL-Server zu verbinden" - greek "Ï õðïëïãéóôÞò '%-.64s' äåí Ý÷åé äéêáßùìá óýíäåóçò ìå ôïí MySQL server" - hun "A '%-.64s' host szamara nem engedelyezett a kapcsolodas ehhez a MySQL szerverhez" - ita "Al sistema '%-.64s' non e` consentita la connessione a questo server MySQL" - jpn "Host '%-.64s' ¤Ï MySQL server ¤ËÀܳ¤òµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" - kor "'%-.64s' È£½ºÆ®´Â ÀÌ MySQL¼¹ö¿¡ Á¢¼ÓÇÒ Çã°¡¸¦ ¹ÞÁö ¸øÇß½À´Ï´Ù." - por "'Host' '%-.64s' não tem permissão para se conectar com este servidor MySQL" - rum "Host-ul '%-.64s' nu este permis a se conecta la aceste server MySQL" - rus "èÏÓÔÕ '%-.64s' ÎÅ ÒÁÚÒÅÛÁÅÔÓÑ ÐÏÄËÌÀÞÁÔØÓÑ Ë ÜÔÏÍÕ ÓÅÒ×ÅÒÕ MySQL" - serbian "Host-u '%-.64s' nije dozvoljeno da se konektuje na ovaj MySQL server" - spa "Servidor '%-.64s' no está permitido para conectar con este servidor MySQL" - swe "Denna dator, '%-.64s', har inte privileger att använda denna MySQL server" - ukr "èÏÓÔÕ '%-.64s' ÎÅ ÄÏ×ÏÌÅÎÏ Ú×'ÑÚÕ×ÁÔÉÓØ Ú ÃÉÍ ÓÅÒ×ÅÒÏÍ MySQL" -ER_PASSWORD_ANONYMOUS_USER 42000 - cze "Pou-B¾íváte MySQL jako anonymní u¾ivatel a anonymní u¾ivatelé nemají povoleno mìnit hesla" - dan "Du bruger MySQL som anonym bruger. Anonyme brugere må ikke ændre adgangskoder" - nla "U gebruikt MySQL als anonieme gebruiker en deze mogen geen wachtwoorden wijzigen" - eng "You are using MySQL as an anonymous user and anonymous users are not allowed to change passwords" - jps "MySQL ‚ð anonymous users ‚ÅŽg—p‚µ‚Ä‚¢‚éó‘Ô‚Å‚ÍAƒpƒXƒ[ƒh‚Ì•ÏX‚Í‚Å‚«‚Ü‚¹‚ñ", - est "Te kasutate MySQL-i anonüümse kasutajana, kelledel pole parooli muutmise õigust" - fre "Vous utilisez un utilisateur anonyme et les utilisateurs anonymes ne sont pas autorisés à changer les mots de passe" - ger "Sie benutzen MySQL als anonymer Benutzer und dürfen daher keine Passwörter ändern" - greek "×ñçóéìïðïéåßôå ôçí MySQL óáí anonymous user êáé Ýôóé äåí ìðïñåßôå íá áëëÜîåôå ôá passwords Üëëùí ÷ñçóôþí" - hun "Nevtelen (anonymous) felhasznalokent nem negedelyezett a jelszovaltoztatas" - ita "Impossibile cambiare la password usando MySQL come utente anonimo" - jpn "MySQL ¤ò anonymous users ¤Ç»ÈÍѤ·¤Æ¤¤¤ë¾õÂ֤Ǥϡ¢¥Ñ¥¹¥ï¡¼¥É¤ÎÊѹ¹¤Ï¤Ç¤¤Þ¤»¤ó" - kor "´ç½ÅÀº MySQL¼¹ö¿¡ À͸íÀÇ »ç¿ëÀÚ·Î Á¢¼ÓÀ» Çϼ̽À´Ï´Ù.À͸íÀÇ »ç¿ëÀÚ´Â ¾ÏÈ£¸¦ º¯°æÇÒ ¼ö ¾ø½À´Ï´Ù." - por "Você está usando o MySQL como usuário anônimo e usuários anônimos não têm permissão para mudar senhas" - rum "Dumneavoastra folositi MySQL ca un utilizator anonim si utilizatorii anonimi nu au voie sa schime parolele" - rus "÷Ù ÉÓÐÏÌØÚÕÅÔÅ MySQL ÏÔ ÉÍÅÎÉ ÁÎÏÎÉÍÎÏÇÏ ÐÏÌØÚÏ×ÁÔÅÌÑ, Á ÁÎÏÎÉÍÎÙÍ ÐÏÌØÚÏ×ÁÔÅÌÑÍ ÎÅ ÒÁÚÒÅÛÁÅÔÓÑ ÍÅÎÑÔØ ÐÁÒÏÌÉ" - serbian "Vi koristite MySQL kao anonimni korisnik a anonimnim korisnicima nije dozvoljeno da menjaju lozinke" - spa "Tu estás usando MySQL como un usuario anonimo y usuarios anonimos no tienen permiso para cambiar las claves" - swe "Du använder MySQL som en anonym användare och som sådan får du inte ändra ditt lösenord" - ukr "÷É ×ÉËÏÒÉÓÔÏ×Õ¤ÔÅ MySQL ÑË ÁÎÏΦÍÎÉÊ ËÏÒÉÓÔÕ×ÁÞ, ÔÏÍÕ ×ÁÍ ÎÅ ÄÏÚ×ÏÌÅÎÏ ÚͦÎÀ×ÁÔÉ ÐÁÒÏ̦" -ER_PASSWORD_NOT_ALLOWED 42000 - cze "Na zm-Bìnu hesel ostatním musíte mít právo provést update tabulek v databázi mysql" - dan "Du skal have tilladelse til at opdatere tabeller i MySQL databasen for at ændre andres adgangskoder" - nla "U moet tabel update priveleges hebben in de mysql database om wachtwoorden voor anderen te mogen wijzigen" - eng "You must have privileges to update tables in the mysql database to be able to change passwords for others" - jps "‘¼‚̃†[ƒU[‚̃pƒXƒ[ƒh‚ð•ÏX‚·‚邽‚ß‚É‚Í, mysql ƒf[ƒ^ƒx[ƒX‚ɑ΂µ‚Ä update ‚Ì‹–‰Â‚ª‚È‚¯‚ê‚΂Ȃè‚Ü‚¹‚ñ.", - est "Teiste paroolide muutmiseks on nõutav tabelite muutmisõigus 'mysql' andmebaasis" - fre "Vous devez avoir le privilège update sur les tables de la base de donnée mysql pour pouvoir changer les mots de passe des autres" - ger "Sie benötigen die Berechtigung zum Aktualisieren von Tabellen in der Datenbank 'mysql', um die Passwörter anderer Benutzer ändern zu können" - greek "ÐñÝðåé íá Ý÷åôå äéêáßùìá äéüñèùóçò ðéíÜêùí (update) óôç âÜóç äåäïìÝíùí mysql ãéá íá ìðïñåßôå íá áëëÜîåôå ôá passwords Üëëùí ÷ñçóôþí" - hun "Onnek tabla-update joggal kell rendelkeznie a mysql adatbazisban masok jelszavanak megvaltoztatasahoz" - ita "E` necessario il privilegio di update sulle tabelle del database mysql per cambiare le password per gli altri utenti" - jpn "¾¤Î¥æ¡¼¥¶¡¼¤Î¥Ñ¥¹¥ï¡¼¥É¤òÊѹ¹¤¹¤ë¤¿¤á¤Ë¤Ï, mysql ¥Ç¡¼¥¿¥Ù¡¼¥¹¤ËÂФ·¤Æ update ¤Îµö²Ä¤¬¤Ê¤±¤ì¤Ð¤Ê¤ê¤Þ¤»¤ó." - kor "´ç½ÅÀº ´Ù¸¥»ç¿ëÀÚµéÀÇ ¾ÏÈ£¸¦ º¯°æÇÒ ¼ö ÀÖµµ·Ï µ¥ÀÌŸº£À̽º º¯°æ±ÇÇÑÀ» °¡Á®¾ß ÇÕ´Ï´Ù." - por "Você deve ter privilégios para atualizar tabelas no banco de dados mysql para ser capaz de mudar a senha de outros" - rum "Trebuie sa aveti privilegii sa actualizati tabelele in bazele de date mysql ca sa puteti sa schimati parolele altora" - rus "äÌÑ ÔÏÇÏ ÞÔÏÂÙ ÉÚÍÅÎÑÔØ ÐÁÒÏÌÉ ÄÒÕÇÉÈ ÐÏÌØÚÏ×ÁÔÅÌÅÊ, Õ ×ÁÓ ÄÏÌÖÎÙ ÂÙÔØ ÐÒÉ×ÉÌÅÇÉÉ ÎÁ ÉÚÍÅÎÅÎÉÅ ÔÁÂÌÉÃ × ÂÁÚÅ ÄÁÎÎÙÈ mysql" - serbian "Morate imati privilegije da možete da update-ujete odreðene tabele ako želite da menjate lozinke za druge korisnike" - spa "Tu debes de tener permiso para actualizar tablas en la base de datos mysql para cambiar las claves para otros" - swe "För att ändra lösenord för andra måste du ha rättigheter att uppdatera mysql-databasen" - ukr "÷É ÐÏ×ÉΦ ÍÁÔÉ ÐÒÁ×Ï ÎÁ ÏÎÏ×ÌÅÎÎÑ ÔÁÂÌÉÃØ Õ ÂÁÚ¦ ÄÁÎÎÉÈ mysql, ÁÂÉ ÍÁÔÉ ÍÏÖÌÉצÓÔØ ÚͦÎÀ×ÁÔÉ ÐÁÒÏÌØ ¦ÎÛÉÍ" -ER_PASSWORD_NO_MATCH 42000 - cze "V tabulce user nen-Bí ¾ádný odpovídající øádek" - dan "Kan ikke finde nogen tilsvarende poster i bruger tabellen" - nla "Kan geen enkele passende rij vinden in de gebruikers tabel" - eng "Can't find any matching row in the user table" - est "Ei leia vastavat kirjet kasutajate tabelis" - fre "Impossible de trouver un enregistrement correspondant dans la table user" - ger "Kann keinen passenden Datensatz in Tabelle 'user' finden" - greek "Äåí åßíáé äõíáôÞ ç áíåýñåóç ôçò áíôßóôïé÷çò åããñáöÞò óôïí ðßíáêá ôùí ÷ñçóôþí" - hun "Nincs megegyezo sor a user tablaban" - ita "Impossibile trovare la riga corrispondente nella tabella user" - kor "»ç¿ëÀÚ Å×ÀÌºí¿¡¼ ÀÏÄ¡ÇÏ´Â °ÍÀ» ãÀ» ¼ö ¾øÀ¾´Ï´Ù." - por "Não pode encontrar nenhuma linha que combine na tabela usuário (user table)" - rum "Nu pot gasi nici o linie corespunzatoare in tabela utilizatorului" - rus "îÅ×ÏÚÍÏÖÎÏ ÏÔÙÓËÁÔØ ÐÏÄÈÏÄÑÝÕÀ ÚÁÐÉÓØ × ÔÁÂÌÉÃÅ ÐÏÌØÚÏ×ÁÔÅÌÅÊ" - serbian "Ne mogu da pronaðem odgovarajuæi slog u 'user' tabeli" - spa "No puedo encontrar una línea correponsdiente en la tabla user" - swe "Hittade inte användaren i 'user'-tabellen" - ukr "îÅ ÍÏÖÕ ÚÎÁÊÔÉ ×¦ÄÐÏצÄÎÉÈ ÚÁÐÉÓ¦× Õ ÔÁÂÌÉæ ËÏÒÉÓÔÕ×ÁÞÁ" -ER_UPDATE_INFO - cze "Nalezen-Bých øádkù: %ld Zmìnìno: %ld Varování: %ld" - dan "Poster fundet: %ld Ændret: %ld Advarsler: %ld" - nla "Passende rijen: %ld Gewijzigd: %ld Waarschuwingen: %ld" - eng "Rows matched: %ld Changed: %ld Warnings: %ld" - jps "ˆê’v”(Rows matched): %ld •ÏX: %ld Warnings: %ld", - est "Sobinud kirjeid: %ld Muudetud: %ld Hoiatusi: %ld" - fre "Enregistrements correspondants: %ld Modifiés: %ld Warnings: %ld" - ger "Datensätze gefunden: %ld Geändert: %ld Warnungen: %ld" - hun "Megegyezo sorok szama: %ld Valtozott: %ld Warnings: %ld" - ita "Rows riconosciute: %ld Cambiate: %ld Warnings: %ld" - jpn "°ìÃ׿ô(Rows matched): %ld Êѹ¹: %ld Warnings: %ld" - kor "ÀÏÄ¡ÇÏ´Â Rows : %ld°³ º¯°æµÊ: %ld°³ °æ°í: %ld°³" - por "Linhas que combinaram: %ld - Alteradas: %ld - Avisos: %ld" - rum "Linii identificate (matched): %ld Schimbate: %ld Atentionari (warnings): %ld" - rus "óÏ×ÐÁÌÏ ÚÁÐÉÓÅÊ: %ld éÚÍÅÎÅÎÏ: %ld ðÒÅÄÕÐÒÅÖÄÅÎÉÊ: %ld" - serbian "Odgovarajuæih slogova: %ld Promenjeno: %ld Upozorenja: %ld" - spa "Líneas correspondientes: %ld Cambiadas: %ld Avisos: %ld" - swe "Rader: %ld Uppdaterade: %ld Varningar: %ld" - ukr "úÁÐÉÓ¦× ×¦ÄÐÏצÄÁ¤: %ld úͦÎÅÎÏ: %ld úÁÓÔÅÒÅÖÅÎØ: %ld" -ER_CANT_CREATE_THREAD - cze "Nemohu vytvo-Bøit nový thread (errno %d). Pokud je je¹tì nìjaká volná pamì», podívejte se do manuálu na èást o chybách specifických pro jednotlivé operaèní systémy" - dan "Kan ikke danne en ny tråd (fejl nr. %d). Hvis computeren ikke er løbet tør for hukommelse, kan du se i brugervejledningen for en mulig operativ-system - afhængig fejl" - nla "Kan geen nieuwe thread aanmaken (Errcode: %d). Indien er geen tekort aan geheugen is kunt u de handleiding consulteren over een mogelijke OS afhankelijke fout" - eng "Can't create a new thread (errno %d); if you are not out of available memory, you can consult the manual for a possible OS-dependent bug" - jps "V‹K‚ɃXƒŒƒbƒh‚ªì‚ê‚Ü‚¹‚ñ‚Å‚µ‚½ (errno %d). ‚à‚µÅ‘åŽg—p‹–‰Âƒƒ‚ƒŠ[”‚ð‰z‚¦‚Ä‚¢‚È‚¢‚̂ɃGƒ‰[‚ª”¶‚µ‚Ä‚¢‚é‚È‚ç, ƒ}ƒjƒ…ƒAƒ‹‚Ì’†‚©‚ç 'possible OS-dependent bug' ‚Æ‚¢‚¤•¶Žš‚ð’T‚µ‚Ä‚‚Ý‚Ä‚¾‚³‚¢.", - est "Ei suuda luua uut lõime (veakood %d). Kui mälu ei ole otsas, on tõenäoliselt tegemist operatsioonisüsteemispetsiifilise veaga" - fre "Impossible de créer une nouvelle tâche (errno %d). S'il reste de la mémoire libre, consultez le manual pour trouver un éventuel bug dépendant de l'OS" - ger "Kann keinen neuen Thread erzeugen (Fehler: %d). Sollte noch Speicher verfügbar sein, bitte im Handbuch wegen möglicher Fehler im Betriebssystem nachschlagen" - hun "Uj thread letrehozasa nem lehetseges (Hibakod: %d). Amenyiben van meg szabad memoria, olvassa el a kezikonyv operacios rendszerfuggo hibalehetosegekrol szolo reszet" - ita "Impossibile creare un nuovo thread (errno %d). Se non ci sono problemi di memoria disponibile puoi consultare il manuale per controllare possibili problemi dipendenti dal SO" - jpn "¿·µ¬¤Ë¥¹¥ì¥Ã¥É¤¬ºî¤ì¤Þ¤»¤ó¤Ç¤·¤¿ (errno %d). ¤â¤·ºÇÂç»ÈÍѵö²Ä¥á¥â¥ê¡¼¿ô¤ò±Û¤¨¤Æ¤¤¤Ê¤¤¤Î¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤Æ¤¤¤ë¤Ê¤é, ¥Þ¥Ë¥å¥¢¥ë¤ÎÃ椫¤é 'possible OS-dependent bug' ¤È¤¤¤¦Ê¸»ú¤òõ¤·¤Æ¤¯¤ß¤Æ¤À¤µ¤¤." - kor "»õ·Î¿î ¾²·¹µå¸¦ ¸¸µé ¼ö ¾ø½À´Ï´Ù.(¿¡·¯¹øÈ£ %d). ¸¸¾à ¿©À¯¸Þ¸ð¸®°¡ ÀÖ´Ù¸é OS-dependent¹ö±× ÀÇ ¸Þ´º¾ó ºÎºÐÀ» ã¾Æº¸½Ã¿À." - nor "Can't create a new thread (errno %d); if you are not out of available memory you can consult the manual for any possible OS dependent bug" - norwegian-ny "Can't create a new thread (errno %d); if you are not out of available memory you can consult the manual for any possible OS dependent bug" - pol "Can't create a new thread (errno %d); if you are not out of available memory you can consult the manual for any possible OS dependent bug" - por "Não pode criar uma nova 'thread' (erro no. %d). Se você não estiver sem memória disponível, você pode consultar o manual sobre um possível 'bug' dependente do sistema operacional" - rum "Nu pot crea un thread nou (Eroare %d). Daca mai aveti memorie disponibila in sistem, puteti consulta manualul - ar putea exista un potential bug in legatura cu sistemul de operare" - rus "îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÎÏ×ÙÊ ÐÏÔÏË (ÏÛÉÂËÁ %d). åÓÌÉ ÜÔÏ ÎÅ ÓÉÔÕÁÃÉÑ, Ó×ÑÚÁÎÎÁÑ Ó ÎÅÈ×ÁÔËÏÊ ÐÁÍÑÔÉ, ÔÏ ×ÁÍ ÓÌÅÄÕÅÔ ÉÚÕÞÉÔØ ÄÏËÕÍÅÎÔÁÃÉÀ ÎÁ ÐÒÅÄÍÅÔ ÏÐÉÓÁÎÉÑ ×ÏÚÍÏÖÎÏÊ ÏÛÉÂËÉ ÒÁÂÏÔÙ × ËÏÎËÒÅÔÎÏÊ ïó" - serbian "Ne mogu da kreiram novi thread (errno %d). Ako imate još slobodne memorije, trebali biste da pogledate u priruèniku da li je ovo specifièna greška vašeg operativnog sistema" - spa "No puedo crear un nuevo thread (errno %d). Si tu está con falta de memoria disponible, tu puedes consultar el Manual para posibles problemas con SO" - swe "Kan inte skapa en ny tråd (errno %d)" - ukr "îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ ÎÏ×Õ Ç¦ÌËÕ (ÐÏÍÉÌËÁ %d). ñËÝÏ ×É ÎÅ ×ÉËÏÒÉÓÔÁÌÉ ÕÓÀ ÐÁÍ'ÑÔØ, ÔÏ ÐÒÏÞÉÔÁÊÔÅ ÄÏËÕÍÅÎÔÁæÀ ÄÏ ×ÁÛϧ ïó - ÍÏÖÌÉ×Ï ÃÅ ÐÏÍÉÌËÁ ïó" -ER_WRONG_VALUE_COUNT_ON_ROW 21S01 - cze "Po-Bèet sloupcù neodpovídá poètu hodnot na øádku %ld" - dan "Kolonne antallet stemmer ikke overens med antallet af værdier i post %ld" - nla "Kolom aantal komt niet overeen met waarde aantal in rij %ld" - eng "Column count doesn't match value count at row %ld" - est "Tulpade hulk erineb väärtuste hulgast real %ld" - ger "Anzahl der Felder stimmt nicht mit der Anzahl der Werte in Zeile %ld überein" - hun "Az oszlopban talalhato ertek nem egyezik meg a %ld sorban szamitott ertekkel" - ita "Il numero delle colonne non corrisponde al conteggio alla riga %ld" - kor "Row %ld¿¡¼ Ä®·³ Ä«¿îÆ®¿Í value Ä«¿îÅÍ¿Í ÀÏÄ¡ÇÏÁö ¾Ê½À´Ï´Ù." - por "Contagem de colunas não confere com a contagem de valores na linha %ld" - rum "Numarul de coloane nu corespunde cu numarul de valori la linia %ld" - rus "ëÏÌÉÞÅÓÔ×Ï ÓÔÏÌÂÃÏ× ÎÅ ÓÏ×ÐÁÄÁÅÔ Ó ËÏÌÉÞÅÓÔ×ÏÍ ÚÎÁÞÅÎÉÊ × ÚÁÐÉÓÉ %ld" - serbian "Broj kolona ne odgovara broju vrednosti u slogu %ld" - spa "El número de columnas no corresponde al número en la línea %ld" - swe "Antalet kolumner motsvarar inte antalet värden på rad: %ld" - ukr "ë¦ÌØ˦ÓÔØ ÓÔÏ×ÂÃ¦× ÎÅ ÓЦ×ÐÁÄÁ¤ Ú Ë¦ÌØ˦ÓÔÀ ÚÎÁÞÅÎØ Õ ÓÔÒÏæ %ld" -ER_CANT_REOPEN_TABLE - cze "Nemohu znovuotev-Bøít tabulku: '%-.192s" - dan "Kan ikke genåbne tabel '%-.192s" - nla "Kan tabel niet opnieuw openen: '%-.192s" - eng "Can't reopen table: '%-.192s'" - est "Ei suuda taasavada tabelit '%-.192s'" - fre "Impossible de réouvrir la table: '%-.192s" - ger "Kann Tabelle'%-.192s' nicht erneut öffnen" - hun "Nem lehet ujra-megnyitni a tablat: '%-.192s" - ita "Impossibile riaprire la tabella: '%-.192s'" - kor "Å×À̺íÀ» ´Ù½Ã ¿¼ö ¾ø±º¿ä: '%-.192s" - nor "Can't reopen table: '%-.192s" - norwegian-ny "Can't reopen table: '%-.192s" - pol "Can't reopen table: '%-.192s" - por "Não pode reabrir a tabela '%-.192s" - rum "Nu pot redeschide tabela: '%-.192s'" - rus "îÅ×ÏÚÍÏÖÎÏ ÚÁÎÏ×Ï ÏÔËÒÙÔØ ÔÁÂÌÉÃÕ '%-.192s'" - serbian "Ne mogu da ponovo otvorim tabelu '%-.192s'" - slo "Can't reopen table: '%-.192s" - spa "No puedo reabrir tabla: '%-.192s" - swe "Kunde inte stänga och öppna tabell '%-.192s" - ukr "îÅ ÍÏÖÕ ÐÅÒÅצÄËÒÉÔÉ ÔÁÂÌÉÃÀ: '%-.192s'" -ER_INVALID_USE_OF_NULL 22004 - cze "Neplatn-Bé u¾ití hodnoty NULL" - dan "Forkert brug af nulværdi (NULL)" - nla "Foutief gebruik van de NULL waarde" - eng "Invalid use of NULL value" - jps "NULL ’l‚ÌŽg—p•û–@‚ª•s“KØ‚Å‚·", - est "NULL väärtuse väärkasutus" - fre "Utilisation incorrecte de la valeur NULL" - ger "Unerlaubte Verwendung eines NULL-Werts" - hun "A NULL ervenytelen hasznalata" - ita "Uso scorretto del valore NULL" - jpn "NULL ÃͤλÈÍÑÊýË¡¤¬ÉÔŬÀڤǤ¹" - kor "NULL °ªÀ» À߸ø »ç¿ëÇϼ̱º¿ä..." - por "Uso inválido do valor NULL" - rum "Folosirea unei value NULL e invalida" - rus "îÅÐÒÁ×ÉÌØÎÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ×ÅÌÉÞÉÎÙ NULL" - serbian "Pogrešna upotreba vrednosti NULL" - spa "Invalido uso de valor NULL" - swe "Felaktig använding av NULL" - ukr "èÉÂÎÅ ×ÉËÏÒÉÓÔÁÎÎÑ ÚÎÁÞÅÎÎÑ NULL" -ER_REGEXP_ERROR 42000 - cze "Regul-Bární výraz vrátil chybu '%-.64s'" - dan "Fik fejl '%-.64s' fra regexp" - nla "Fout '%-.64s' ontvangen van regexp" - eng "Got error '%-.64s' from regexp" - est "regexp tagastas vea '%-.64s'" - fre "Erreur '%-.64s' provenant de regexp" - ger "regexp lieferte Fehler '%-.64s'" - hun "'%-.64s' hiba a regularis kifejezes hasznalata soran (regexp)" - ita "Errore '%-.64s' da regexp" - kor "regexp¿¡¼ '%-.64s'°¡ ³µ½À´Ï´Ù." - por "Obteve erro '%-.64s' em regexp" - rum "Eroarea '%-.64s' obtinuta din expresia regulara (regexp)" - rus "ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ '%-.64s' ÏÔ ÒÅÇÕÌÑÒÎÏÇÏ ×ÙÒÁÖÅÎÉÑ" - serbian "Funkcija regexp je vratila grešku '%-.64s'" - spa "Obtenido error '%-.64s' de regexp" - swe "Fick fel '%-.64s' från REGEXP" - ukr "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ '%-.64s' ×¦Ä ÒÅÇÕÌÑÒÎÏÇÏ ×ÉÒÁÚÕ" -ER_MIX_OF_GROUP_FUNC_AND_FIELDS 42000 - cze "Pokud nen-Bí ¾ádná GROUP BY klauzule, není dovoleno souèasné pou¾ití GROUP polo¾ek (MIN(),MAX(),COUNT()...) s ne GROUP polo¾kami" - dan "Sammenblanding af GROUP kolonner (MIN(),MAX(),COUNT()...) uden GROUP kolonner er ikke tilladt, hvis der ikke er noget GROUP BY prædikat" - nla "Het mixen van GROUP kolommen (MIN(),MAX(),COUNT()...) met no-GROUP kolommen is foutief indien er geen GROUP BY clausule is" - eng "Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause" - est "GROUP tulpade (MIN(),MAX(),COUNT()...) kooskasutamine tavaliste tulpadega ilma GROUP BY klauslita ei ole lubatud" - fre "Mélanger les colonnes GROUP (MIN(),MAX(),COUNT()...) avec des colonnes normales est interdit s'il n'y a pas de clause GROUP BY" - ger "Das Vermischen von GROUP-Feldern (MIN(),MAX(),COUNT()...) mit Nicht-GROUP-Feldern ist nicht zulässig, wenn keine GROUP-BY-Klausel vorhanden ist" - hun "A GROUP mezok (MIN(),MAX(),COUNT()...) kevert hasznalata nem lehetseges GROUP BY hivatkozas nelkul" - ita "Il mescolare funzioni di aggregazione (MIN(),MAX(),COUNT()...) e non e` illegale se non c'e` una clausula GROUP BY" - kor "Mixing of GROUP Ä®·³s (MIN(),MAX(),COUNT(),...) with no GROUP Ä®·³s is illegal if there is no GROUP BY clause" - por "Mistura de colunas agrupadas (com MIN(), MAX(), COUNT(), ...) com colunas não agrupadas é ilegal, se não existir uma cláusula de agrupamento (cláusula GROUP BY)" - rum "Amestecarea de coloane GROUP (MIN(),MAX(),COUNT()...) fara coloane GROUP este ilegala daca nu exista o clauza GROUP BY" - rus "ïÄÎÏ×ÒÅÍÅÎÎÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ÓÇÒÕÐÐÉÒÏ×ÁÎÎÙÈ (GROUP) ÓÔÏÌÂÃÏ× (MIN(),MAX(),COUNT(),...) Ó ÎÅÓÇÒÕÐÐÉÒÏ×ÁÎÎÙÍÉ ÓÔÏÌÂÃÁÍÉ Ñ×ÌÑÅÔÓÑ ÎÅËÏÒÒÅËÔÎÙÍ, ÅÓÌÉ × ×ÙÒÁÖÅÎÉÉ ÅÓÔØ GROUP BY" - serbian "Upotreba agregatnih funkcija (MIN(),MAX(),COUNT()...) bez 'GROUP' kolona je pogrešna ako ne postoji 'GROUP BY' iskaz" - spa "Mezcla de columnas GROUP (MIN(),MAX(),COUNT()...) con no GROUP columnas es ilegal si no hat la clausula GROUP BY" - swe "Man får ha både GROUP-kolumner (MIN(),MAX(),COUNT()...) och fält i en fråga om man inte har en GROUP BY-del" - ukr "úͦÛÕ×ÁÎÎÑ GROUP ÓÔÏ×ÂÃ¦× (MIN(),MAX(),COUNT()...) Ú ÎÅ GROUP ÓÔÏ×ÂÃÑÍÉ ¤ ÚÁÂÏÒÏÎÅÎÉÍ, ÑËÝÏ ÎÅ ÍÁ¤ GROUP BY" -ER_NONEXISTING_GRANT 42000 - cze "Neexistuje odpov-Bídající grant pro u¾ivatele '%-.48s' na stroji '%-.64s'" - dan "Denne tilladelse findes ikke for brugeren '%-.48s' på vært '%-.64s'" - nla "Deze toegang (GRANT) is niet toegekend voor gebruiker '%-.48s' op host '%-.64s'" - eng "There is no such grant defined for user '%-.48s' on host '%-.64s'" - jps "ƒ†[ƒU[ '%-.48s' (ƒzƒXƒg '%-.64s' ‚̃†[ƒU[) ‚Í‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ", - est "Sellist õigust ei ole defineeritud kasutajale '%-.48s' masinast '%-.64s'" - fre "Un tel droit n'est pas défini pour l'utilisateur '%-.48s' sur l'hôte '%-.64s'" - ger "Für Benutzer '%-.48s' auf Host '%-.64s' gibt es keine solche Berechtigung" - hun "A '%-.48s' felhasznalonak nincs ilyen joga a '%-.64s' host-on" - ita "GRANT non definita per l'utente '%-.48s' dalla macchina '%-.64s'" - jpn "¥æ¡¼¥¶¡¼ '%-.48s' (¥Û¥¹¥È '%-.64s' ¤Î¥æ¡¼¥¶¡¼) ¤Ïµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" - kor "»ç¿ëÀÚ '%-.48s' (È£½ºÆ® '%-.64s')¸¦ À§ÇÏ¿© Á¤ÀÇµÈ ±×·± ½ÂÀÎÀº ¾ø½À´Ï´Ù." - por "Não existe tal permissão (grant) definida para o usuário '%-.48s' no 'host' '%-.64s'" - rum "Nu exista un astfel de grant definit pentru utilzatorul '%-.48s' de pe host-ul '%-.64s'" - rus "ôÁËÉÅ ÐÒÁ×Á ÎÅ ÏÐÒÅÄÅÌÅÎÙ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%-.48s' ÎÁ ÈÏÓÔÅ '%-.64s'" - serbian "Ne postoji odobrenje za pristup korisniku '%-.48s' na host-u '%-.64s'" - spa "No existe permiso definido para usuario '%-.48s' en el servidor '%-.64s'" - swe "Det finns inget privilegium definierat för användare '%-.48s' på '%-.64s'" - ukr "ðÏ×ÎÏ×ÁÖÅÎØ ÎÅ ×ÉÚÎÁÞÅÎÏ ÄÌÑ ËÏÒÉÓÔÕ×ÁÞÁ '%-.48s' Ú ÈÏÓÔÕ '%-.64s'" -ER_TABLEACCESS_DENIED_ERROR 42000 - cze "%-.16s p-Bøíkaz nepøístupný pro u¾ivatele: '%-.48s'@'%-.64s' pro tabulku '%-.192s'" - dan "%-.16s-kommandoen er ikke tilladt for brugeren '%-.48s'@'%-.64s' for tabellen '%-.192s'" - nla "%-.16s commando geweigerd voor gebruiker: '%-.48s'@'%-.64s' voor tabel '%-.192s'" - eng "%-.16s command denied to user '%-.48s'@'%-.64s' for table '%-.192s'" - jps "ƒRƒ}ƒ“ƒh %-.16s ‚Í ƒ†[ƒU[ '%-.48s'@'%-.64s' ,ƒe[ƒuƒ‹ '%-.192s' ‚ɑ΂µ‚Ä‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ", - est "%-.16s käsk ei ole lubatud kasutajale '%-.48s'@'%-.64s' tabelis '%-.192s'" - fre "La commande '%-.16s' est interdite à l'utilisateur: '%-.48s'@'@%-.64s' sur la table '%-.192s'" - ger "%-.16s Befehl nicht erlaubt für Benutzer '%-.48s'@'%-.64s' auf Tabelle '%-.192s'" - hun "%-.16s parancs a '%-.48s'@'%-.64s' felhasznalo szamara nem engedelyezett a '%-.192s' tablaban" - ita "Comando %-.16s negato per l'utente: '%-.48s'@'%-.64s' sulla tabella '%-.192s'" - jpn "¥³¥Þ¥ó¥É %-.16s ¤Ï ¥æ¡¼¥¶¡¼ '%-.48s'@'%-.64s' ,¥Æ¡¼¥Ö¥ë '%-.192s' ¤ËÂФ·¤Æµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" - kor "'%-.16s' ¸í·ÉÀº ´ÙÀ½ »ç¿ëÀÚ¿¡°Ô °ÅºÎµÇ¾ú½À´Ï´Ù. : '%-.48s'@'%-.64s' for Å×À̺í '%-.192s'" - por "Comando '%-.16s' negado para o usuário '%-.48s'@'%-.64s' na tabela '%-.192s'" - rum "Comanda %-.16s interzisa utilizatorului: '%-.48s'@'%-.64s' pentru tabela '%-.192s'" - rus "ëÏÍÁÎÄÁ %-.16s ÚÁÐÒÅÝÅÎÁ ÐÏÌØÚÏ×ÁÔÅÌÀ '%-.48s'@'%-.64s' ÄÌÑ ÔÁÂÌÉÃÙ '%-.192s'" - serbian "%-.16s komanda zabranjena za korisnika '%-.48s'@'%-.64s' za tabelu '%-.192s'" - spa "%-.16s comando negado para usuario: '%-.48s'@'%-.64s' para tabla '%-.192s'" - swe "%-.16s ej tillåtet för '%-.48s'@'%-.64s' för tabell '%-.192s'" - ukr "%-.16s ËÏÍÁÎÄÁ ÚÁÂÏÒÏÎÅÎÁ ËÏÒÉÓÔÕ×ÁÞÕ: '%-.48s'@'%-.64s' Õ ÔÁÂÌÉæ '%-.192s'" -ER_COLUMNACCESS_DENIED_ERROR 42000 - cze "%-.16s p-Bøíkaz nepøístupný pro u¾ivatele: '%-.48s'@'%-.64s' pro sloupec '%-.192s' v tabulce '%-.192s'" - dan "%-.16s-kommandoen er ikke tilladt for brugeren '%-.48s'@'%-.64s' for kolonne '%-.192s' in tabellen '%-.192s'" - nla "%-.16s commando geweigerd voor gebruiker: '%-.48s'@'%-.64s' voor kolom '%-.192s' in tabel '%-.192s'" - eng "%-.16s command denied to user '%-.48s'@'%-.64s' for column '%-.192s' in table '%-.192s'" - jps "ƒRƒ}ƒ“ƒh %-.16s ‚Í ƒ†[ƒU[ '%-.48s'@'%-.64s'\n ƒJƒ‰ƒ€ '%-.192s' ƒe[ƒuƒ‹ '%-.192s' ‚ɑ΂µ‚Ä‹–‰Â‚³‚ê‚Ä‚¢‚Ü‚¹‚ñ", - est "%-.16s käsk ei ole lubatud kasutajale '%-.48s'@'%-.64s' tulbale '%-.192s' tabelis '%-.192s'" - fre "La commande '%-.16s' est interdite à l'utilisateur: '%-.48s'@'@%-.64s' sur la colonne '%-.192s' de la table '%-.192s'" - ger "%-.16s Befehl nicht erlaubt für Benutzer '%-.48s'@'%-.64s' und Feld '%-.192s' in Tabelle '%-.192s'" - hun "%-.16s parancs a '%-.48s'@'%-.64s' felhasznalo szamara nem engedelyezett a '%-.192s' mezo eseten a '%-.192s' tablaban" - ita "Comando %-.16s negato per l'utente: '%-.48s'@'%-.64s' sulla colonna '%-.192s' della tabella '%-.192s'" - jpn "¥³¥Þ¥ó¥É %-.16s ¤Ï ¥æ¡¼¥¶¡¼ '%-.48s'@'%-.64s'\n ¥«¥é¥à '%-.192s' ¥Æ¡¼¥Ö¥ë '%-.192s' ¤ËÂФ·¤Æµö²Ä¤µ¤ì¤Æ¤¤¤Þ¤»¤ó" - kor "'%-.16s' ¸í·ÉÀº ´ÙÀ½ »ç¿ëÀÚ¿¡°Ô °ÅºÎµÇ¾ú½À´Ï´Ù. : '%-.48s'@'%-.64s' for Ä®·³ '%-.192s' in Å×À̺í '%-.192s'" - por "Comando '%-.16s' negado para o usuário '%-.48s'@'%-.64s' na coluna '%-.192s', na tabela '%-.192s'" - rum "Comanda %-.16s interzisa utilizatorului: '%-.48s'@'%-.64s' pentru coloana '%-.192s' in tabela '%-.192s'" - rus "ëÏÍÁÎÄÁ %-.16s ÚÁÐÒÅÝÅÎÁ ÐÏÌØÚÏ×ÁÔÅÌÀ '%-.48s'@'%-.64s' ÄÌÑ ÓÔÏÌÂÃÁ '%-.192s' × ÔÁÂÌÉÃÅ '%-.192s'" - serbian "%-.16s komanda zabranjena za korisnika '%-.48s'@'%-.64s' za kolonu '%-.192s' iz tabele '%-.192s'" - spa "%-.16s comando negado para usuario: '%-.48s'@'%-.64s' para columna '%-.192s' en la tabla '%-.192s'" - swe "%-.16s ej tillåtet för '%-.48s'@'%-.64s' för kolumn '%-.192s' i tabell '%-.192s'" - ukr "%-.16s ËÏÍÁÎÄÁ ÚÁÂÏÒÏÎÅÎÁ ËÏÒÉÓÔÕ×ÁÞÕ: '%-.48s'@'%-.64s' ÄÌÑ ÓÔÏ×ÂÃÑ '%-.192s' Õ ÔÁÂÌÉæ '%-.192s'" -ER_ILLEGAL_GRANT_FOR_TABLE 42000 - cze "Neplatn-Bý pøíkaz GRANT/REVOKE. Prosím, pøeètìte si v manuálu, jaká privilegia je mo¾né pou¾ít." - dan "Forkert GRANT/REVOKE kommando. Se i brugervejledningen hvilke privilegier der kan specificeres." - nla "Foutief GRANT/REVOKE commando. Raadpleeg de handleiding welke priveleges gebruikt kunnen worden." - eng "Illegal GRANT/REVOKE command; please consult the manual to see which privileges can be used" - est "Vigane GRANT/REVOKE käsk. Tutvu kasutajajuhendiga" - fre "Commande GRANT/REVOKE incorrecte. Consultez le manuel." - ger "Unzulässiger GRANT- oder REVOKE-Befehl. Verfügbare Berechtigungen sind im Handbuch aufgeführt" - greek "Illegal GRANT/REVOKE command; please consult the manual to see which privileges can be used." - hun "Ervenytelen GRANT/REVOKE parancs. Kerem, nezze meg a kezikonyvben, milyen jogok lehetsegesek" - ita "Comando GRANT/REVOKE illegale. Prego consultare il manuale per sapere quali privilegi possono essere usati." - jpn "Illegal GRANT/REVOKE command; please consult the manual to see which privleges can be used." - kor "À߸øµÈ GRANT/REVOKE ¸í·É. ¾î¶² ±Ç¸®¿Í ½ÂÀÎÀÌ »ç¿ëµÇ¾î Áú ¼ö ÀÖ´ÂÁö ¸Þ´º¾óÀ» º¸½Ã¿À." - nor "Illegal GRANT/REVOKE command; please consult the manual to see which privleges can be used." - norwegian-ny "Illegal GRANT/REVOKE command; please consult the manual to see which privleges can be used." - pol "Illegal GRANT/REVOKE command; please consult the manual to see which privleges can be used." - por "Comando GRANT/REVOKE ilegal. Por favor consulte no manual quais privilégios podem ser usados." - rum "Comanda GRANT/REVOKE ilegala. Consultati manualul in privinta privilegiilor ce pot fi folosite." - rus "îÅ×ÅÒÎÁÑ ËÏÍÁÎÄÁ GRANT ÉÌÉ REVOKE. ïÂÒÁÔÉÔÅÓØ Ë ÄÏËÕÍÅÎÔÁÃÉÉ, ÞÔÏÂÙ ×ÙÑÓÎÉÔØ, ËÁËÉÅ ÐÒÉ×ÉÌÅÇÉÉ ÍÏÖÎÏ ÉÓÐÏÌØÚÏ×ÁÔØ" - serbian "Pogrešna 'GRANT' odnosno 'REVOKE' komanda. Molim Vas pogledajte u priruèniku koje vrednosti mogu biti upotrebljene." - slo "Illegal GRANT/REVOKE command; please consult the manual to see which privleges can be used." - spa "Ilegal comando GRANT/REVOKE. Por favor consulte el manual para cuales permisos pueden ser usados." - swe "Felaktigt GRANT-privilegium använt" - ukr "èÉÂÎÁ GRANT/REVOKE ËÏÍÁÎÄÁ; ÐÒÏÞÉÔÁÊÔÅ ÄÏËÕÍÅÎÔÁæÀ ÓÔÏÓÏ×ÎÏ ÔÏÇÏ, Ñ˦ ÐÒÁ×Á ÍÏÖÎÁ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ" -ER_GRANT_WRONG_HOST_OR_USER 42000 - cze "Argument p-Bøíkazu GRANT u¾ivatel nebo stroj je pøíli¹ dlouhý" - dan "Værts- eller brugernavn for langt til GRANT" - nla "De host of gebruiker parameter voor GRANT is te lang" - eng "The host or user argument to GRANT is too long" - est "Masina või kasutaja nimi GRANT lauses on liiga pikk" - fre "L'hôte ou l'utilisateur donné en argument à GRANT est trop long" - ger "Das Host- oder User-Argument für GRANT ist zu lang" - hun "A host vagy felhasznalo argumentuma tul hosszu a GRANT parancsban" - ita "L'argomento host o utente per la GRANT e` troppo lungo" - kor "½ÂÀÎ(GRANT)À» À§ÇÏ¿© »ç¿ëÇÑ »ç¿ëÀÚ³ª È£½ºÆ®ÀÇ °ªµéÀÌ ³Ê¹« ±é´Ï´Ù." - por "Argumento de 'host' ou de usuário para o GRANT é longo demais" - rum "Argumentul host-ului sau utilizatorului pentru GRANT e prea lung" - rus "óÌÉÛËÏÍ ÄÌÉÎÎÏÅ ÉÍÑ ÐÏÌØÚÏ×ÁÔÅÌÑ/ÈÏÓÔÁ ÄÌÑ GRANT" - serbian "Argument 'host' ili 'korisnik' prosleðen komandi 'GRANT' je predugaèak" - spa "El argumento para servidor o usuario para GRANT es demasiado grande" - swe "Felaktigt maskinnamn eller användarnamn använt med GRANT" - ukr "áÒÇÕÍÅÎÔ host ÁÂÏ user ÄÌÑ GRANT ÚÁÄÏ×ÇÉÊ" -ER_NO_SUCH_TABLE 42S02 - cze "Tabulka '%-.192s.%-.192s' neexistuje" - dan "Tabellen '%-.192s.%-.192s' eksisterer ikke" - nla "Tabel '%-.192s.%-.192s' bestaat niet" - eng "Table '%-.192s.%-.192s' doesn't exist" - est "Tabelit '%-.192s.%-.192s' ei eksisteeri" - fre "La table '%-.192s.%-.192s' n'existe pas" - ger "Tabelle '%-.192s.%-.192s' existiert nicht" - hun "A '%-.192s.%-.192s' tabla nem letezik" - ita "La tabella '%-.192s.%-.192s' non esiste" - jpn "Table '%-.192s.%-.192s' doesn't exist" - kor "Å×À̺í '%-.192s.%-.192s' ´Â Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù." - nor "Table '%-.192s.%-.192s' doesn't exist" - norwegian-ny "Table '%-.192s.%-.192s' doesn't exist" - pol "Table '%-.192s.%-.192s' doesn't exist" - por "Tabela '%-.192s.%-.192s' não existe" - rum "Tabela '%-.192s.%-.192s' nu exista" - rus "ôÁÂÌÉÃÁ '%-.192s.%-.192s' ÎÅ ÓÕÝÅÓÔ×ÕÅÔ" - serbian "Tabela '%-.192s.%-.192s' ne postoji" - slo "Table '%-.192s.%-.192s' doesn't exist" - spa "Tabla '%-.192s.%-.192s' no existe" - swe "Det finns ingen tabell som heter '%-.192s.%-.192s'" - ukr "ôÁÂÌÉÃÑ '%-.192s.%-.192s' ÎÅ ¦ÓÎÕ¤" -ER_NONEXISTING_TABLE_GRANT 42000 - cze "Neexistuje odpov-Bídající grant pro u¾ivatele '%-.48s' na stroji '%-.64s' pro tabulku '%-.192s'" - dan "Denne tilladelse eksisterer ikke for brugeren '%-.48s' på vært '%-.64s' for tabellen '%-.192s'" - nla "Deze toegang (GRANT) is niet toegekend voor gebruiker '%-.48s' op host '%-.64s' op tabel '%-.192s'" - eng "There is no such grant defined for user '%-.48s' on host '%-.64s' on table '%-.192s'" - est "Sellist õigust ei ole defineeritud kasutajale '%-.48s' masinast '%-.64s' tabelile '%-.192s'" - fre "Un tel droit n'est pas défini pour l'utilisateur '%-.48s' sur l'hôte '%-.64s' sur la table '%-.192s'" - ger "Eine solche Berechtigung ist für User '%-.48s' auf Host '%-.64s' an Tabelle '%-.192s' nicht definiert" - hun "A '%-.48s' felhasznalo szamara a '%-.64s' host '%-.192s' tablajaban ez a parancs nem engedelyezett" - ita "GRANT non definita per l'utente '%-.48s' dalla macchina '%-.64s' sulla tabella '%-.192s'" - kor "»ç¿ëÀÚ '%-.48s'(È£½ºÆ® '%-.64s')´Â Å×À̺í '%-.192s'¸¦ »ç¿ëÇϱâ À§ÇÏ¿© Á¤ÀÇµÈ ½ÂÀÎÀº ¾ø½À´Ï´Ù. " - por "Não existe tal permissão (grant) definido para o usuário '%-.48s' no 'host' '%-.64s', na tabela '%-.192s'" - rum "Nu exista un astfel de privilegiu (grant) definit pentru utilizatorul '%-.48s' de pe host-ul '%-.64s' pentru tabela '%-.192s'" - rus "ôÁËÉÅ ÐÒÁ×Á ÎÅ ÏÐÒÅÄÅÌÅÎÙ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%-.48s' ÎÁ ËÏÍÐØÀÔÅÒÅ '%-.64s' ÄÌÑ ÔÁÂÌÉÃÙ '%-.192s'" - serbian "Ne postoji odobrenje za pristup korisniku '%-.48s' na host-u '%-.64s' tabeli '%-.192s'" - spa "No existe tal permiso definido para usuario '%-.48s' en el servidor '%-.64s' en la tabla '%-.192s'" - swe "Det finns inget privilegium definierat för användare '%-.48s' på '%-.64s' för tabell '%-.192s'" - ukr "ðÏ×ÎÏ×ÁÖÅÎØ ÎÅ ×ÉÚÎÁÞÅÎÏ ÄÌÑ ËÏÒÉÓÔÕ×ÁÞÁ '%-.48s' Ú ÈÏÓÔÕ '%-.64s' ÄÌÑ ÔÁÂÌÉæ '%-.192s'" -ER_NOT_ALLOWED_COMMAND 42000 - cze "Pou-B¾itý pøíkaz není v této verzi MySQL povolen" - dan "Den brugte kommando er ikke tilladt med denne udgave af MySQL" - nla "Het used commando is niet toegestaan in deze MySQL versie" - eng "The used command is not allowed with this MySQL version" - est "Antud käsk ei ole lubatud käesolevas MySQL versioonis" - fre "Cette commande n'existe pas dans cette version de MySQL" - ger "Der verwendete Befehl ist in dieser MySQL-Version nicht zulässig" - hun "A hasznalt parancs nem engedelyezett ebben a MySQL verzioban" - ita "Il comando utilizzato non e` supportato in questa versione di MySQL" - kor "»ç¿ëµÈ ¸í·ÉÀº ÇöÀçÀÇ MySQL ¹öÁ¯¿¡¼´Â ÀÌ¿ëµÇÁö ¾Ê½À´Ï´Ù." - por "Comando usado não é permitido para esta versão do MySQL" - rum "Comanda folosita nu este permisa pentru aceasta versiune de MySQL" - rus "üÔÁ ËÏÍÁÎÄÁ ÎÅ ÄÏÐÕÓËÁÅÔÓÑ × ÄÁÎÎÏÊ ×ÅÒÓÉÉ MySQL" - serbian "Upotrebljena komanda nije dozvoljena sa ovom verzijom MySQL servera" - spa "El comando usado no es permitido con esta versión de MySQL" - swe "Du kan inte använda detta kommando med denna MySQL version" - ukr "÷ÉËÏÒÉÓÔÏ×Õ×ÁÎÁ ËÏÍÁÎÄÁ ÎÅ ÄÏÚ×ÏÌÅÎÁ Õ Ã¦Ê ×ÅÒÓ¦§ MySQL" -ER_SYNTAX_ERROR 42000 - cze "Va-B¹e syntaxe je nìjaká divná" - dan "Der er en fejl i SQL syntaksen" - nla "Er is iets fout in de gebruikte syntax" - eng "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use" - est "Viga SQL süntaksis" - fre "Erreur de syntaxe" - ger "Fehler in der SQL-Syntax. Bitte die korrekte Syntax im Handbuch nachschlagen" - greek "You have an error in your SQL syntax" - hun "Szintaktikai hiba" - ita "Errore di sintassi nella query SQL" - jpn "Something is wrong in your syntax" - kor "SQL ±¸¹®¿¡ ¿À·ù°¡ ÀÖ½À´Ï´Ù." - nor "Something is wrong in your syntax" - norwegian-ny "Something is wrong in your syntax" - pol "Something is wrong in your syntax" - por "Você tem um erro de sintaxe no seu SQL" - rum "Aveti o eroare in sintaxa RSQL" - rus "õ ×ÁÓ ÏÛÉÂËÁ × ÚÁÐÒÏÓÅ. éÚÕÞÉÔÅ ÄÏËÕÍÅÎÔÁÃÉÀ ÐÏ ÉÓÐÏÌØÚÕÅÍÏÊ ×ÅÒÓÉÉ MySQL ÎÁ ÐÒÅÄÍÅÔ ËÏÒÒÅËÔÎÏÇÏ ÓÉÎÔÁËÓÉÓÁ" - serbian "Imate grešku u vašoj SQL sintaksi" - slo "Something is wrong in your syntax" - spa "Algo está equivocado en su sintax" - swe "Du har något fel i din syntax" - ukr "õ ×ÁÓ ÐÏÍÉÌËÁ Õ ÓÉÎÔÁËÓÉÓ¦ SQL" -ER_DELAYED_CANT_CHANGE_LOCK - cze "Zpo-B¾dìný insert threadu nebyl schopen získat po¾adovaný zámek pro tabulku %-.192s" - dan "Forsinket indsættelse tråden (delayed insert thread) kunne ikke opnå lås på tabellen %-.192s" - nla "'Delayed insert' thread kon de aangevraagde 'lock' niet krijgen voor tabel %-.192s" - eng "Delayed insert thread couldn't get requested lock for table %-.192s" - est "INSERT DELAYED lõim ei suutnud saada soovitud lukku tabelile %-.192s" - fre "La tâche 'delayed insert' n'a pas pu obtenir le verrou démandé sur la table %-.192s" - ger "Verzögerter (DELAYED) Einfüge-Thread konnte die angeforderte Sperre für Tabelle '%-.192s' nicht erhalten" - hun "A kesleltetett beillesztes (delayed insert) thread nem kapott zatolast a %-.192s tablahoz" - ita "Il thread di inserimento ritardato non riesce ad ottenere il lock per la tabella %-.192s" - kor "Áö¿¬µÈ insert ¾²·¹µå°¡ Å×À̺í %-.192sÀÇ ¿ä±¸µÈ ¶ôÅ·À» ó¸®ÇÒ ¼ö ¾ø¾ú½À´Ï´Ù." - por "'Thread' de inserção retardada (atrasada) pois não conseguiu obter a trava solicitada para tabela '%-.192s'" - rum "Thread-ul pentru inserarea aminata nu a putut obtine lacatul (lock) pentru tabela %-.192s" - rus "ðÏÔÏË, ÏÂÓÌÕÖÉ×ÁÀÝÉÊ ÏÔÌÏÖÅÎÎÕÀ ×ÓÔÁ×ËÕ (delayed insert), ÎÅ ÓÍÏÇ ÐÏÌÕÞÉÔØ ÚÁÐÒÁÛÉ×ÁÅÍÕÀ ÂÌÏËÉÒÏ×ËÕ ÎÁ ÔÁÂÌÉÃÕ %-.192s" - serbian "Prolongirani 'INSERT' thread nije mogao da dobije traženo zakljuèavanje tabele '%-.192s'" - spa "Thread de inserción retarda no pudiendo bloquear para la tabla %-.192s" - swe "DELAYED INSERT-tråden kunde inte låsa tabell '%-.192s'" - ukr "ç¦ÌËÁ ÄÌÑ INSERT DELAYED ÎÅ ÍÏÖÅ ÏÔÒÉÍÁÔÉ ÂÌÏËÕ×ÁÎÎÑ ÄÌÑ ÔÁÂÌÉæ %-.192s" -ER_TOO_MANY_DELAYED_THREADS - cze "P-Bøíli¹ mnoho zpo¾dìných threadù" - dan "For mange slettede tråde (threads) i brug" - nla "Te veel 'delayed' threads in gebruik" - eng "Too many delayed threads in use" - est "Liiga palju DELAYED lõimesid kasutusel" - fre "Trop de tâche 'delayed' en cours" - ger "Zu viele verzögerte (DELAYED) Threads in Verwendung" - hun "Tul sok kesletetett thread (delayed)" - ita "Troppi threads ritardati in uso" - kor "³Ê¹« ¸¹Àº Áö¿¬ ¾²·¹µå¸¦ »ç¿ëÇÏ°í ÀÖ½À´Ï´Ù." - por "Excesso de 'threads' retardadas (atrasadas) em uso" - rum "Prea multe threaduri aminate care sint in uz" - rus "óÌÉÛËÏÍ ÍÎÏÇÏ ÐÏÔÏËÏ×, ÏÂÓÌÕÖÉ×ÁÀÝÉÈ ÏÔÌÏÖÅÎÎÕÀ ×ÓÔÁ×ËÕ (delayed insert)" - serbian "Previše prolongiranih thread-ova je u upotrebi" - spa "Muchos threads retardados en uso" - swe "Det finns redan 'max_delayed_threads' trådar i använding" - ukr "úÁÂÁÇÁÔÏ ÚÁÔÒÉÍÁÎÉÈ Ç¦ÌÏË ×ÉËÏÒÉÓÔÏ×Õ¤ÔØÓÑ" -ER_ABORTING_CONNECTION 08S01 - cze "Zru-B¹eno spojení %ld do databáze: '%-.192s' u¾ivatel: '%-.48s' (%-.64s)" - dan "Afbrudt forbindelse %ld til database: '%-.192s' bruger: '%-.48s' (%-.64s)" - nla "Afgebroken verbinding %ld naar db: '%-.192s' gebruiker: '%-.48s' (%-.64s)" - eng "Aborted connection %ld to db: '%-.192s' user: '%-.48s' (%-.64s)" - est "Ühendus katkestatud %ld andmebaasile: '%-.192s' kasutajale: '%-.48s' (%-.64s)" - fre "Connection %ld avortée vers la bd: '%-.192s' utilisateur: '%-.48s' (%-.64s)" - ger "Abbruch der Verbindung %ld zur Datenbank '%-.192s'. Benutzer: '%-.48s' (%-.64s)" - hun "Megszakitott kapcsolat %ld db: '%-.192s' adatbazishoz, felhasznalo: '%-.48s' (%-.64s)" - ita "Interrotta la connessione %ld al db: '%-.192s' utente: '%-.48s' (%-.64s)" - jpn "Aborted connection %ld to db: '%-.192s' user: '%-.48s' (%-.64s)" - kor "µ¥ÀÌŸº£À̽º Á¢¼ÓÀ» À§ÇÑ ¿¬°á %ld°¡ Áß´ÜµÊ : '%-.192s' »ç¿ëÀÚ: '%-.48s' (%-.64s)" - nor "Aborted connection %ld to db: '%-.192s' user: '%-.48s' (%-.64s)" - norwegian-ny "Aborted connection %ld to db: '%-.192s' user: '%-.48s' (%-.64s)" - pol "Aborted connection %ld to db: '%-.192s' user: '%-.48s' (%-.64s)" - por "Conexão %ld abortou para o banco de dados '%-.192s' - usuário '%-.48s' (%-.64s)" - rum "Conectie terminata %ld la baza de date: '%-.192s' utilizator: '%-.48s' (%-.64s)" - rus "ðÒÅÒ×ÁÎÏ ÓÏÅÄÉÎÅÎÉÅ %ld Ë ÂÁÚÅ ÄÁÎÎÙÈ '%-.192s' ÐÏÌØÚÏ×ÁÔÅÌÑ '%-.48s' (%-.64s)" - serbian "Prekinuta konekcija broj %ld ka bazi: '%-.192s' korisnik je bio: '%-.48s' (%-.64s)" - slo "Aborted connection %ld to db: '%-.192s' user: '%-.48s' (%-.64s)" - spa "Conexión abortada %ld para db: '%-.192s' usuario: '%-.48s' (%-.64s)" - swe "Avbröt länken för tråd %ld till db '%-.192s', användare '%-.48s' (%-.64s)" - ukr "ðÅÒÅÒ×ÁÎÏ Ú'¤ÄÎÁÎÎÑ %ld ÄÏ ÂÁÚÉ ÄÁÎÎÉÈ: '%-.192s' ËÏÒÉÓÔÕ×ÁÞÁ: '%-.48s' (%-.64s)" -ER_NET_PACKET_TOO_LARGE 08S01 - cze "Zji-B¹tìn pøíchozí packet del¹í ne¾ 'max_allowed_packet'" - dan "Modtog en datapakke som var større end 'max_allowed_packet'" - nla "Groter pakket ontvangen dan 'max_allowed_packet'" - eng "Got a packet bigger than 'max_allowed_packet' bytes" - est "Saabus suurem pakett kui lubatud 'max_allowed_packet' muutujaga" - fre "Paquet plus grand que 'max_allowed_packet' reçu" - ger "Empfangenes Paket ist größer als 'max_allowed_packet' Bytes" - hun "A kapott csomag nagyobb, mint a maximalisan engedelyezett: 'max_allowed_packet'" - ita "Ricevuto un pacchetto piu` grande di 'max_allowed_packet'" - kor "'max_allowed_packet'º¸´Ù ´õÅ« ÆÐŶÀ» ¹Þ¾Ò½À´Ï´Ù." - por "Obteve um pacote maior do que a taxa máxima de pacotes definida (max_allowed_packet)" - rum "Un packet mai mare decit 'max_allowed_packet' a fost primit" - rus "ðÏÌÕÞÅÎÎÙÊ ÐÁËÅÔ ÂÏÌØÛÅ, ÞÅÍ 'max_allowed_packet'" - serbian "Primio sam mrežni paket veæi od definisane vrednosti 'max_allowed_packet'" - spa "Obtenido un paquete mayor que 'max_allowed_packet'" - swe "Kommunkationspaketet är större än 'max_allowed_packet'" - ukr "ïÔÒÉÍÁÎÏ ÐÁËÅÔ Â¦ÌØÛÉÊ Î¦Ö max_allowed_packet" -ER_NET_READ_ERROR_FROM_PIPE 08S01 - cze "Zji-B¹tìna chyba pøi ètení z roury spojení" - dan "Fik læsefejl fra forbindelse (connection pipe)" - nla "Kreeg leesfout van de verbindings pipe" - eng "Got a read error from the connection pipe" - est "Viga ühendustoru lugemisel" - fre "Erreur de lecture reçue du pipe de connexion" - ger "Lese-Fehler bei einer Verbindungs-Pipe" - hun "Olvasasi hiba a kapcsolat soran" - ita "Rilevato un errore di lettura dalla pipe di connessione" - kor "¿¬°á ÆÄÀÌÇÁ·ÎºÎÅÍ ¿¡·¯°¡ ¹ß»ýÇÏ¿´½À´Ï´Ù." - por "Obteve um erro de leitura no 'pipe' da conexão" - rum "Eroare la citire din cauza lui 'connection pipe'" - rus "ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ ÞÔÅÎÉÑ ÏÔ ÐÏÔÏËÁ ÓÏÅÄÉÎÅÎÉÑ (connection pipe)" - serbian "Greška pri èitanju podataka sa pipe-a" - spa "Obtenido un error de lectura de la conexión pipe" - swe "Fick läsfel från klienten vid läsning från 'PIPE'" - ukr "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ ÞÉÔÁÎÎÑ Ú ËÏÍÕΦËÁæÊÎÏÇÏ ËÁÎÁÌÕ" -ER_NET_FCNTL_ERROR 08S01 - cze "Zji-B¹tìna chyba fcntl()" - dan "Fik fejlmeddelelse fra fcntl()" - nla "Kreeg fout van fcntl()" - eng "Got an error from fcntl()" - est "fcntl() tagastas vea" - fre "Erreur reçue de fcntl() " - ger "fcntl() lieferte einen Fehler" - hun "Hiba a fcntl() fuggvenyben" - ita "Rilevato un errore da fcntl()" - kor "fcntl() ÇÔ¼ö·ÎºÎÅÍ ¿¡·¯°¡ ¹ß»ýÇÏ¿´½À´Ï´Ù." - por "Obteve um erro em fcntl()" - rum "Eroare obtinuta de la fcntl()" - rus "ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ ÏÔ fcntl()" - serbian "Greška pri izvršavanju funkcije fcntl()" - spa "Obtenido un error de fcntl()" - swe "Fick fatalt fel från 'fcntl()'" - ukr "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËËÕ ×¦Ä fcntl()" -ER_NET_PACKETS_OUT_OF_ORDER 08S01 - cze "P-Bøíchozí packety v chybném poøadí" - dan "Modtog ikke datapakker i korrekt rækkefølge" - nla "Pakketten in verkeerde volgorde ontvangen" - eng "Got packets out of order" - est "Paketid saabusid vales järjekorras" - fre "Paquets reçus dans le désordre" - ger "Pakete nicht in der richtigen Reihenfolge empfangen" - hun "Helytelen sorrendben erkezett adatcsomagok" - ita "Ricevuti pacchetti non in ordine" - kor "¼ø¼°¡ ¸ÂÁö¾Ê´Â ÆÐŶÀ» ¹Þ¾Ò½À´Ï´Ù." - por "Obteve pacotes fora de ordem" - rum "Packets care nu sint ordonati au fost gasiti" - rus "ðÁËÅÔÙ ÐÏÌÕÞÅÎÙ × ÎÅ×ÅÒÎÏÍ ÐÏÒÑÄËÅ" - serbian "Primio sam mrežne pakete van reda" - spa "Obtenido paquetes desordenados" - swe "Kommunikationspaketen kom i fel ordning" - ukr "ïÔÒÉÍÁÎÏ ÐÁËÅÔÉ Õ ÎÅÎÁÌÅÖÎÏÍÕ ÐÏÒÑÄËÕ" -ER_NET_UNCOMPRESS_ERROR 08S01 - cze "Nemohu rozkomprimovat komunika-Bèní packet" - dan "Kunne ikke dekomprimere kommunikations-pakke (communication packet)" - nla "Communicatiepakket kon niet worden gedecomprimeerd" - eng "Couldn't uncompress communication packet" - est "Viga andmepaketi lahtipakkimisel" - fre "Impossible de décompresser le paquet reçu" - ger "Kommunikationspaket lässt sich nicht entpacken" - hun "A kommunikacios adatcsomagok nem tomorithetok ki" - ita "Impossibile scompattare i pacchetti di comunicazione" - kor "Åë½Å ÆÐŶÀÇ ¾ÐÃàÇØÁ¦¸¦ ÇÒ ¼ö ¾ø¾ú½À´Ï´Ù." - por "Não conseguiu descomprimir pacote de comunicação" - rum "Nu s-a putut decompresa pachetul de comunicatie (communication packet)" - rus "îÅ×ÏÚÍÏÖÎÏ ÒÁÓÐÁËÏ×ÁÔØ ÐÁËÅÔ, ÐÏÌÕÞÅÎÎÙÊ ÞÅÒÅÚ ËÏÍÍÕÎÉËÁÃÉÏÎÎÙÊ ÐÒÏÔÏËÏÌ" - serbian "Ne mogu da dekompresujem mrežne pakete" - spa "No puedo descomprimir paquetes de comunicación" - swe "Kunde inte packa up kommunikationspaketet" - ukr "îÅ ÍÏÖÕ ÄÅËÏÍÐÒÅÓÕ×ÁÔÉ ËÏÍÕΦËÁæÊÎÉÊ ÐÁËÅÔ" -ER_NET_READ_ERROR 08S01 - cze "Zji-B¹tìna chyba pøi ètení komunikaèního packetu" - dan "Fik fejlmeddelelse ved læsning af kommunikations-pakker (communication packets)" - nla "Fout bij het lezen van communicatiepakketten" - eng "Got an error reading communication packets" - est "Viga andmepaketi lugemisel" - fre "Erreur de lecture des paquets reçus" - ger "Fehler beim Lesen eines Kommunikationspakets" - hun "HIba a kommunikacios adatcsomagok olvasasa soran" - ita "Rilevato un errore ricevendo i pacchetti di comunicazione" - kor "Åë½Å ÆÐŶÀ» Àд Áß ¿À·ù°¡ ¹ß»ýÇÏ¿´½À´Ï´Ù." - por "Obteve um erro na leitura de pacotes de comunicação" - rum "Eroare obtinuta citind pachetele de comunicatie (communication packets)" - rus "ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ × ÐÒÏÃÅÓÓÅ ÐÏÌÕÞÅÎÉÑ ÐÁËÅÔÁ ÞÅÒÅÚ ËÏÍÍÕÎÉËÁÃÉÏÎÎÙÊ ÐÒÏÔÏËÏÌ " - serbian "Greška pri primanju mrežnih paketa" - spa "Obtenido un error leyendo paquetes de comunicación" - swe "Fick ett fel vid läsning från klienten" - ukr "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ ÞÉÔÁÎÎÑ ËÏÍÕΦËÁæÊÎÉÈ ÐÁËÅÔ¦×" -ER_NET_READ_INTERRUPTED 08S01 - cze "Zji-B¹tìn timeout pøi ètení komunikaèního packetu" - dan "Timeout-fejl ved læsning af kommunukations-pakker (communication packets)" - nla "Timeout bij het lezen van communicatiepakketten" - eng "Got timeout reading communication packets" - est "Kontrollaja ületamine andmepakettide lugemisel" - fre "Timeout en lecture des paquets reçus" - ger "Zeitüberschreitung beim Lesen eines Kommunikationspakets" - hun "Idotullepes a kommunikacios adatcsomagok olvasasa soran" - ita "Rilevato un timeout ricevendo i pacchetti di comunicazione" - kor "Åë½Å ÆÐŶÀ» Àд Áß timeoutÀÌ ¹ß»ýÇÏ¿´½À´Ï´Ù." - por "Obteve expiração de tempo (timeout) na leitura de pacotes de comunicação" - rum "Timeout obtinut citind pachetele de comunicatie (communication packets)" - rus "ðÏÌÕÞÅÎ ÔÁÊÍÁÕÔ ÏÖÉÄÁÎÉÑ ÐÁËÅÔÁ ÞÅÒÅÚ ËÏÍÍÕÎÉËÁÃÉÏÎÎÙÊ ÐÒÏÔÏËÏÌ " - serbian "Vremenski limit za èitanje mrežnih paketa je istekao" - spa "Obtenido timeout leyendo paquetes de comunicación" - swe "Fick 'timeout' vid läsning från klienten" - ukr "ïÔÒÉÍÁÎÏ ÚÁÔÒÉÍËÕ ÞÉÔÁÎÎÑ ËÏÍÕΦËÁæÊÎÉÈ ÐÁËÅÔ¦×" -ER_NET_ERROR_ON_WRITE 08S01 - cze "Zji-B¹tìna chyba pøi zápisu komunikaèního packetu" - dan "Fik fejlmeddelelse ved skrivning af kommunukations-pakker (communication packets)" - nla "Fout bij het schrijven van communicatiepakketten" - eng "Got an error writing communication packets" - est "Viga andmepaketi kirjutamisel" - fre "Erreur d'écriture des paquets envoyés" - ger "Fehler beim Schreiben eines Kommunikationspakets" - hun "Hiba a kommunikacios csomagok irasa soran" - ita "Rilevato un errore inviando i pacchetti di comunicazione" - kor "Åë½Å ÆÐŶÀ» ±â·ÏÇÏ´Â Áß ¿À·ù°¡ ¹ß»ýÇÏ¿´½À´Ï´Ù." - por "Obteve um erro na escrita de pacotes de comunicação" - rum "Eroare in scrierea pachetelor de comunicatie (communication packets)" - rus "ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ ÐÒÉ ÐÅÒÅÄÁÞÅ ÐÁËÅÔÁ ÞÅÒÅÚ ËÏÍÍÕÎÉËÁÃÉÏÎÎÙÊ ÐÒÏÔÏËÏÌ " - serbian "Greška pri slanju mrežnih paketa" - spa "Obtenido un error de escribiendo paquetes de comunicación" - swe "Fick ett fel vid skrivning till klienten" - ukr "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ ÚÁÐÉÓÕ ËÏÍÕΦËÁæÊÎÉÈ ÐÁËÅÔ¦×" -ER_NET_WRITE_INTERRUPTED 08S01 - cze "Zji-B¹tìn timeout pøi zápisu komunikaèního packetu" - dan "Timeout-fejl ved skrivning af kommunukations-pakker (communication packets)" - nla "Timeout bij het schrijven van communicatiepakketten" - eng "Got timeout writing communication packets" - est "Kontrollaja ületamine andmepakettide kirjutamisel" - fre "Timeout d'écriture des paquets envoyés" - ger "Zeitüberschreitung beim Schreiben eines Kommunikationspakets" - hun "Idotullepes a kommunikacios csomagok irasa soran" - ita "Rilevato un timeout inviando i pacchetti di comunicazione" - kor "Åë½Å ÆÐÆÂÀ» ±â·ÏÇÏ´Â Áß timeoutÀÌ ¹ß»ýÇÏ¿´½À´Ï´Ù." - por "Obteve expiração de tempo ('timeout') na escrita de pacotes de comunicação" - rum "Timeout obtinut scriind pachetele de comunicatie (communication packets)" - rus "ðÏÌÕÞÅÎ ÔÁÊÍÁÕÔ × ÐÒÏÃÅÓÓÅ ÐÅÒÅÄÁÞÉ ÐÁËÅÔÁ ÞÅÒÅÚ ËÏÍÍÕÎÉËÁÃÉÏÎÎÙÊ ÐÒÏÔÏËÏÌ " - serbian "Vremenski limit za slanje mrežnih paketa je istekao" - spa "Obtenido timeout escribiendo paquetes de comunicación" - swe "Fick 'timeout' vid skrivning till klienten" - ukr "ïÔÒÉÍÁÎÏ ÚÁÔÒÉÍËÕ ÚÁÐÉÓÕ ËÏÍÕΦËÁæÊÎÉÈ ÐÁËÅÔ¦×" -ER_TOO_LONG_STRING 42000 - cze "V-Býsledný øetìzec je del¹í ne¾ 'max_allowed_packet'" - dan "Strengen med resultater er større end 'max_allowed_packet'" - nla "Resultaat string is langer dan 'max_allowed_packet'" - eng "Result string is longer than 'max_allowed_packet' bytes" - est "Tulemus on pikem kui lubatud 'max_allowed_packet' muutujaga" - fre "La chaîne résultat est plus grande que 'max_allowed_packet'" - ger "Ergebnis-String ist länger als 'max_allowed_packet' Bytes" - hun "Ez eredmeny sztring nagyobb, mint a lehetseges maximum: 'max_allowed_packet'" - ita "La stringa di risposta e` piu` lunga di 'max_allowed_packet'" - por "'String' resultante é mais longa do que 'max_allowed_packet'" - rum "Sirul rezultat este mai lung decit 'max_allowed_packet'" - rus "òÅÚÕÌØÔÉÒÕÀÝÁÑ ÓÔÒÏËÁ ÂÏÌØÛÅ, ÞÅÍ 'max_allowed_packet'" - serbian "Rezultujuèi string je duži nego što to dozvoljava parametar servera 'max_allowed_packet'" - spa "La string resultante es mayor que max_allowed_packet" - swe "Resultatsträngen är längre än max_allowed_packet" - ukr "óÔÒÏËÁ ÒÅÚÕÌØÔÁÔÕ ÄÏ×ÛÁ Î¦Ö max_allowed_packet" -ER_TABLE_CANT_HANDLE_BLOB 42000 - cze "Typ pou-B¾ité tabulky nepodporuje BLOB/TEXT sloupce" - dan "Denne tabeltype understøtter ikke brug af BLOB og TEXT kolonner" - nla "Het gebruikte tabel type ondersteunt geen BLOB/TEXT kolommen" - eng "The used table type doesn't support BLOB/TEXT columns" - est "Valitud tabelitüüp ei toeta BLOB/TEXT tüüpi välju" - fre "Ce type de table ne supporte pas les colonnes BLOB/TEXT" - ger "Der verwendete Tabellentyp unterstützt keine BLOB- und TEXT-Felder" - hun "A hasznalt tabla tipus nem tamogatja a BLOB/TEXT mezoket" - ita "Il tipo di tabella usata non supporta colonne di tipo BLOB/TEXT" - por "Tipo de tabela usado não permite colunas BLOB/TEXT" - rum "Tipul de tabela folosit nu suporta coloane de tip BLOB/TEXT" - rus "éÓÐÏÌØÚÕÅÍÁÑ ÔÁÂÌÉÃÁ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ÔÉÐÙ BLOB/TEXT" - serbian "Iskorišteni tip tabele ne podržava kolone tipa 'BLOB' odnosno 'TEXT'" - spa "El tipo de tabla usada no permite soporte para columnas BLOB/TEXT" - swe "Den använda tabelltypen kan inte hantera BLOB/TEXT-kolumner" - ukr "÷ÉËÏÒÉÓÔÁÎÉÊ ÔÉÐ ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕ¤ BLOB/TEXT ÓÔÏ×Âæ" -ER_TABLE_CANT_HANDLE_AUTO_INCREMENT 42000 - cze "Typ pou-B¾ité tabulky nepodporuje AUTO_INCREMENT sloupce" - dan "Denne tabeltype understøtter ikke brug af AUTO_INCREMENT kolonner" - nla "Het gebruikte tabel type ondersteunt geen AUTO_INCREMENT kolommen" - eng "The used table type doesn't support AUTO_INCREMENT columns" - est "Valitud tabelitüüp ei toeta AUTO_INCREMENT tüüpi välju" - fre "Ce type de table ne supporte pas les colonnes AUTO_INCREMENT" - ger "Der verwendete Tabellentyp unterstützt keine AUTO_INCREMENT-Felder" - hun "A hasznalt tabla tipus nem tamogatja az AUTO_INCREMENT tipusu mezoket" - ita "Il tipo di tabella usata non supporta colonne di tipo AUTO_INCREMENT" - por "Tipo de tabela usado não permite colunas AUTO_INCREMENT" - rum "Tipul de tabela folosit nu suporta coloane de tip AUTO_INCREMENT" - rus "éÓÐÏÌØÚÕÅÍÁÑ ÔÁÂÌÉÃÁ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ Á×ÔÏÉÎËÒÅÍÅÎÔÎÙÅ ÓÔÏÌÂÃÙ" - serbian "Iskorišteni tip tabele ne podržava kolone tipa 'AUTO_INCREMENT'" - spa "El tipo de tabla usada no permite soporte para columnas AUTO_INCREMENT" - swe "Den använda tabelltypen kan inte hantera AUTO_INCREMENT-kolumner" - ukr "÷ÉËÏÒÉÓÔÁÎÉÊ ÔÉÐ ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕ¤ AUTO_INCREMENT ÓÔÏ×Âæ" -ER_DELAYED_INSERT_TABLE_LOCKED - cze "INSERT DELAYED nen-Bí mo¾no s tabulkou '%-.192s' pou¾ít, proto¾e je zamèená pomocí LOCK TABLES" - dan "INSERT DELAYED kan ikke bruges med tabellen '%-.192s', fordi tabellen er låst med LOCK TABLES" - nla "INSERT DELAYED kan niet worden gebruikt bij table '%-.192s', vanwege een 'lock met LOCK TABLES" - eng "INSERT DELAYED can't be used with table '%-.192s' because it is locked with LOCK TABLES" - est "INSERT DELAYED ei saa kasutada tabeli '%-.192s' peal, kuna see on lukustatud LOCK TABLES käsuga" - fre "INSERT DELAYED ne peut être utilisé avec la table '%-.192s', car elle est verrouée avec LOCK TABLES" - ger "INSERT DELAYED kann für Tabelle '%-.192s' nicht verwendet werden, da sie mit LOCK TABLES gesperrt ist" - greek "INSERT DELAYED can't be used with table '%-.192s', because it is locked with LOCK TABLES" - hun "Az INSERT DELAYED nem hasznalhato a '%-.192s' tablahoz, mert a tabla zarolt (LOCK TABLES)" - ita "L'inserimento ritardato (INSERT DELAYED) non puo` essere usato con la tabella '%-.192s', perche` soggetta a lock da 'LOCK TABLES'" - jpn "INSERT DELAYED can't be used with table '%-.192s', because it is locked with LOCK TABLES" - kor "INSERT DELAYED can't be used with table '%-.192s', because it is locked with LOCK TABLES" - nor "INSERT DELAYED can't be used with table '%-.192s', because it is locked with LOCK TABLES" - norwegian-ny "INSERT DELAYED can't be used with table '%-.192s', because it is locked with LOCK TABLES" - pol "INSERT DELAYED can't be used with table '%-.192s', because it is locked with LOCK TABLES" - por "INSERT DELAYED não pode ser usado com a tabela '%-.192s', porque ela está travada com LOCK TABLES" - rum "INSERT DELAYED nu poate fi folosit cu tabela '%-.192s', deoarece este locked folosing LOCK TABLES" - rus "îÅÌØÚÑ ÉÓÐÏÌØÚÏ×ÁÔØ INSERT DELAYED ÄÌÑ ÔÁÂÌÉÃÙ '%-.192s', ÐÏÔÏÍÕ ÞÔÏ ÏÎÁ ÚÁÂÌÏËÉÒÏ×ÁÎÁ Ó ÐÏÍÏÝØÀ LOCK TABLES" - serbian "Komanda 'INSERT DELAYED' ne može biti iskorištena u tabeli '%-.192s', zbog toga što je zakljuèana komandom 'LOCK TABLES'" - slo "INSERT DELAYED can't be used with table '%-.192s', because it is locked with LOCK TABLES" - spa "INSERT DELAYED no puede ser usado con tablas '%-.192s', porque esta bloqueada con LOCK TABLES" - swe "INSERT DELAYED kan inte användas med tabell '%-.192s', emedan den är låst med LOCK TABLES" - ukr "INSERT DELAYED ÎÅ ÍÏÖÅ ÂÕÔÉ ×ÉËÏÒÉÓÔÁÎÏ Ú ÔÁÂÌÉÃÅÀ '%-.192s', ÔÏÍÕ ÝÏ §§ ÚÁÂÌÏËÏ×ÁÎÏ Ú LOCK TABLES" -ER_WRONG_COLUMN_NAME 42000 - cze "Nespr-Bávné jméno sloupce '%-.100s'" - dan "Forkert kolonnenavn '%-.100s'" - nla "Incorrecte kolom naam '%-.100s'" - eng "Incorrect column name '%-.100s'" - est "Vigane tulba nimi '%-.100s'" - fre "Nom de colonne '%-.100s' incorrect" - ger "Falscher Spaltenname '%-.100s'" - hun "Ervenytelen mezonev: '%-.100s'" - ita "Nome colonna '%-.100s' non corretto" - por "Nome de coluna '%-.100s' incorreto" - rum "Nume increct de coloana '%-.100s'" - rus "îÅ×ÅÒÎÏÅ ÉÍÑ ÓÔÏÌÂÃÁ '%-.100s'" - serbian "Pogrešno ime kolone '%-.100s'" - spa "Incorrecto nombre de columna '%-.100s'" - swe "Felaktigt kolumnnamn '%-.100s'" - ukr "îÅצÒÎÅ ¦Í'Ñ ÓÔÏ×ÂÃÑ '%-.100s'" -ER_WRONG_KEY_COLUMN 42000 - cze "Handler pou-B¾ité tabulky neumí indexovat sloupce '%-.192s'" - dan "Den brugte tabeltype kan ikke indeksere kolonnen '%-.192s'" - nla "De gebruikte tabel 'handler' kan kolom '%-.192s' niet indexeren" - eng "The used storage engine can't index column '%-.192s'" - est "Tabelihandler ei oska indekseerida tulpa '%-.192s'" - fre "Le handler de la table ne peut indexé la colonne '%-.192s'" - ger "Die verwendete Speicher-Engine kann die Spalte '%-.192s' nicht indizieren" - greek "The used table handler can't index column '%-.192s'" - hun "A hasznalt tablakezelo nem tudja a '%-.192s' mezot indexelni" - ita "Il gestore delle tabelle non puo` indicizzare la colonna '%-.192s'" - jpn "The used table handler can't index column '%-.192s'" - kor "The used table handler can't index column '%-.192s'" - nor "The used table handler can't index column '%-.192s'" - norwegian-ny "The used table handler can't index column '%-.192s'" - pol "The used table handler can't index column '%-.192s'" - por "O manipulador de tabela usado não pode indexar a coluna '%-.192s'" - rum "Handler-ul tabelei folosite nu poate indexa coloana '%-.192s'" - rus "éÓÐÏÌØÚÏ×ÁÎÎÙÊ ÏÂÒÁÂÏÔÞÉË ÔÁÂÌÉÃÙ ÎÅ ÍÏÖÅÔ ÐÒÏÉÎÄÅËÓÉÒÏ×ÁÔØ ÓÔÏÌÂÅà '%-.192s'" - serbian "Handler tabele ne može da indeksira kolonu '%-.192s'" - slo "The used table handler can't index column '%-.192s'" - spa "El manipulador de tabla usado no puede indexar columna '%-.192s'" - swe "Den använda tabelltypen kan inte indexera kolumn '%-.192s'" - ukr "÷ÉËÏÒÉÓÔÁÎÉÊ ×ËÁÚ¦×ÎÉË ÔÁÂÌÉæ ÎÅ ÍÏÖÅ ¦ÎÄÅËÓÕ×ÁÔÉ ÓÔÏ×ÂÅÃØ '%-.192s'" -ER_WRONG_MRG_TABLE - cze "V-B¹echny tabulky v MERGE tabulce nejsou definovány stejnì" - dan "Tabellerne i MERGE er ikke defineret ens" - nla "Niet alle tabellen in de MERGE tabel hebben identieke gedefinities" - eng "Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist" - est "Kõik tabelid MERGE tabeli määratluses ei ole identsed" - fre "Toutes les tables de la table de type MERGE n'ont pas la même définition" - ger "Nicht alle Tabellen in der MERGE-Tabelle sind gleich definiert" - hun "A MERGE tablaban talalhato tablak definicioja nem azonos" - ita "Non tutte le tabelle nella tabella di MERGE sono definite in maniera identica" - jpn "All tables in the MERGE table are not defined identically" - kor "All tables in the MERGE table are not defined identically" - nor "All tables in the MERGE table are not defined identically" - norwegian-ny "All tables in the MERGE table are not defined identically" - pol "All tables in the MERGE table are not defined identically" - por "Todas as tabelas contidas na tabela fundida (MERGE) não estão definidas identicamente" - rum "Toate tabelele din tabela MERGE nu sint definite identic" - rus "îÅ ×ÓÅ ÔÁÂÌÉÃÙ × MERGE ÏÐÒÅÄÅÌÅÎÙ ÏÄÉÎÁËÏ×Ï" - serbian "Tabele iskorištene u 'MERGE' tabeli nisu definisane na isti naèin" - slo "All tables in the MERGE table are not defined identically" - spa "Todas las tablas en la MERGE tabla no estan definidas identicamente" - swe "Tabellerna i MERGE-tabellen är inte identiskt definierade" - ukr "ôÁÂÌÉæ Õ MERGE TABLE ÍÁÀÔØ Ò¦ÚÎÕ ÓÔÒÕËÔÕÒÕ" -ER_DUP_UNIQUE 23000 - cze "Kv-Bùli unique constraintu nemozu zapsat do tabulky '%-.192s'" - dan "Kan ikke skrive til tabellen '%-.192s' fordi det vil bryde CONSTRAINT regler" - nla "Kan niet opslaan naar table '%-.192s' vanwege 'unique' beperking" - eng "Can't write, because of unique constraint, to table '%-.192s'" - est "Ei suuda kirjutada tabelisse '%-.192s', kuna see rikub ühesuse kitsendust" - fre "Écriture impossible à cause d'un index UNIQUE sur la table '%-.192s'" - ger "Schreiben in Tabelle '%-.192s' nicht möglich wegen einer Eindeutigkeitsbeschränkung (unique constraint)" - hun "A '%-.192s' nem irhato, az egyedi mezok miatt" - ita "Impossibile scrivere nella tabella '%-.192s' per limitazione di unicita`" - por "Não pode gravar, devido à restrição UNIQUE, na tabela '%-.192s'" - rum "Nu pot scrie pe hard-drive, din cauza constraintului unic (unique constraint) pentru tabela '%-.192s'" - rus "îÅ×ÏÚÍÏÖÎÏ ÚÁÐÉÓÁÔØ × ÔÁÂÌÉÃÕ '%-.192s' ÉÚ-ÚÁ ÏÇÒÁÎÉÞÅÎÉÊ ÕÎÉËÁÌØÎÏÇÏ ËÌÀÞÁ" - serbian "Zbog provere jedinstvenosti ne mogu da upišem podatke u tabelu '%-.192s'" - spa "No puedo escribir, debido al único constraint, para tabla '%-.192s'" - swe "Kan inte skriva till tabell '%-.192s'; UNIQUE-test" - ukr "îÅ ÍÏÖÕ ÚÁÐÉÓÁÔÉ ÄÏ ÔÁÂÌÉæ '%-.192s', Ú ÐÒÉÞÉÎÉ ×ÉÍÏÇ ÕΦËÁÌØÎÏÓÔ¦" -ER_BLOB_KEY_WITHOUT_LENGTH 42000 - cze "BLOB sloupec '%-.192s' je pou-B¾it ve specifikaci klíèe bez délky" - dan "BLOB kolonnen '%-.192s' brugt i nøglespecifikation uden nøglelængde" - nla "BLOB kolom '%-.192s' gebruikt in zoeksleutel specificatie zonder zoeksleutel lengte" - eng "BLOB/TEXT column '%-.192s' used in key specification without a key length" - est "BLOB-tüüpi tulp '%-.192s' on kasutusel võtmes ilma pikkust määratlemata" - fre "La colonne '%-.192s' de type BLOB est utilisée dans une définition d'index sans longueur d'index" - ger "BLOB- oder TEXT-Spalte '%-.192s' wird in der Schlüsseldefinition ohne Schlüssellängenangabe verwendet" - greek "BLOB column '%-.192s' used in key specification without a key length" - hun "BLOB mezo '%-.192s' hasznalt a mezo specifikacioban, a mezohossz megadasa nelkul" - ita "La colonna '%-.192s' di tipo BLOB e` usata in una chiave senza specificarne la lunghezza" - jpn "BLOB column '%-.192s' used in key specification without a key length" - kor "BLOB column '%-.192s' used in key specification without a key length" - nor "BLOB column '%-.192s' used in key specification without a key length" - norwegian-ny "BLOB column '%-.192s' used in key specification without a key length" - pol "BLOB column '%-.192s' used in key specification without a key length" - por "Coluna BLOB '%-.192s' usada na especificação de chave sem o comprimento da chave" - rum "Coloana BLOB '%-.192s' este folosita in specificarea unei chei fara ca o lungime de cheie sa fie folosita" - rus "óÔÏÌÂÅà ÔÉÐÁ BLOB '%-.192s' ÂÙÌ ÕËÁÚÁÎ × ÏÐÒÅÄÅÌÅÎÉÉ ËÌÀÞÁ ÂÅÚ ÕËÁÚÁÎÉÑ ÄÌÉÎÙ ËÌÀÞÁ" - serbian "BLOB kolona '%-.192s' je upotrebljena u specifikaciji kljuèa bez navoðenja dužine kljuèa" - slo "BLOB column '%-.192s' used in key specification without a key length" - spa "Columna BLOB column '%-.192s' usada en especificación de clave sin tamaño de la clave" - swe "Du har inte angett någon nyckellängd för BLOB '%-.192s'" - ukr "óÔÏ×ÂÅÃØ BLOB '%-.192s' ×ÉËÏÒÉÓÔÁÎÏ Õ ×ÉÚÎÁÞÅÎΦ ËÌÀÞÁ ÂÅÚ ×ËÁÚÁÎÎÑ ÄÏ×ÖÉÎÉ ËÌÀÞÁ" -ER_PRIMARY_CANT_HAVE_NULL 42000 - cze "V-B¹echny èásti primárního klíèe musejí být NOT NULL; pokud potøebujete NULL, pou¾ijte UNIQUE" - dan "Alle dele af en PRIMARY KEY skal være NOT NULL; Hvis du skal bruge NULL i nøglen, brug UNIQUE istedet" - nla "Alle delen van een PRIMARY KEY moeten NOT NULL zijn; Indien u NULL in een zoeksleutel nodig heeft kunt u UNIQUE gebruiken" - eng "All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead" - est "Kõik PRIMARY KEY peavad olema määratletud NOT NULL piiranguga; vajadusel kasuta UNIQUE tüüpi võtit" - fre "Toutes les parties d'un index PRIMARY KEY doivent être NOT NULL; Si vous avez besoin d'un NULL dans l'index, utilisez un index UNIQUE" - ger "Alle Teile eines PRIMARY KEY müssen als NOT NULL definiert sein. Wenn NULL in einem Schlüssel benötigt wird, muss ein UNIQUE-Schlüssel verwendet werden" - hun "Az elsodleges kulcs teljes egeszeben csak NOT NULL tipusu lehet; Ha NULL mezot szeretne a kulcskent, hasznalja inkabb a UNIQUE-ot" - ita "Tutte le parti di una chiave primaria devono essere dichiarate NOT NULL; se necessitano valori NULL nelle chiavi utilizzare UNIQUE" - por "Todas as partes de uma chave primária devem ser não-nulas. Se você precisou usar um valor nulo (NULL) em uma chave, use a cláusula UNIQUE em seu lugar" - rum "Toate partile unei chei primare (PRIMARY KEY) trebuie sa fie NOT NULL; Daca aveti nevoie de NULL in vreo cheie, folositi UNIQUE in schimb" - rus "÷ÓÅ ÞÁÓÔÉ ÐÅÒ×ÉÞÎÏÇÏ ËÌÀÞÁ (PRIMARY KEY) ÄÏÌÖÎÙ ÂÙÔØ ÏÐÒÅÄÅÌÅÎÙ ËÁË NOT NULL; åÓÌÉ ×ÁÍ ÎÕÖÎÁ ÐÏÄÄÅÒÖËÁ ×ÅÌÉÞÉÎ NULL × ËÌÀÞÅ, ×ÏÓÐÏÌØÚÕÊÔÅÓØ ÉÎÄÅËÓÏÍ UNIQUE" - serbian "Svi delovi primarnog kljuèa moraju biti razlièiti od NULL; Ako Vam ipak treba NULL vrednost u kljuèu, upotrebite 'UNIQUE'" - spa "Todas las partes de un PRIMARY KEY deben ser NOT NULL; Si necesitas NULL en una clave, use UNIQUE" - swe "Alla delar av en PRIMARY KEY måste vara NOT NULL; Om du vill ha en nyckel med NULL, använd UNIQUE istället" - ukr "õÓ¦ ÞÁÓÔÉÎÉ PRIMARY KEY ÐÏ×ÉÎΦ ÂÕÔÉ NOT NULL; ñËÝÏ ×É ÐÏÔÒÅÂÕ¤ÔÅ NULL Õ ËÌÀÞ¦, ÓËÏÒÉÓÔÁÊÔÅÓÑ UNIQUE" -ER_TOO_MANY_ROWS 42000 - cze "V-Býsledek obsahuje více ne¾ jeden øádek" - dan "Resultatet bestod af mere end een række" - nla "Resultaat bevatte meer dan een rij" - eng "Result consisted of more than one row" - est "Tulemis oli rohkem kui üks kirje" - fre "Le résultat contient plus d'un enregistrement" - ger "Ergebnis besteht aus mehr als einer Zeile" - hun "Az eredmeny tobb, mint egy sort tartalmaz" - ita "Il risultato consiste di piu` di una riga" - por "O resultado consistiu em mais do que uma linha" - rum "Resultatul constista din mai multe linii" - rus "÷ ÒÅÚÕÌØÔÁÔÅ ×ÏÚ×ÒÁÝÅÎÁ ÂÏÌÅÅ ÞÅÍ ÏÄÎÁ ÓÔÒÏËÁ" - serbian "Rezultat je saèinjen od više slogova" - spa "Resultado compuesto de mas que una línea" - swe "Resultet bestod av mera än en rad" - ukr "òÅÚÕÌØÔÁÔ ÚÎÁÈÏÄÉÔØÓÑ Õ Â¦ÌØÛÅ Î¦Ö ÏÄÎ¦Ê ÓÔÒÏæ" -ER_REQUIRES_PRIMARY_KEY 42000 - cze "Tento typ tabulky vy-B¾aduje primární klíè" - dan "Denne tabeltype kræver en primærnøgle" - nla "Dit tabel type heeft een primaire zoeksleutel nodig" - eng "This table type requires a primary key" - est "Antud tabelitüüp nõuab primaarset võtit" - fre "Ce type de table nécessite une clé primaire (PRIMARY KEY)" - ger "Dieser Tabellentyp benötigt einen Primärschlüssel (PRIMARY KEY)" - hun "Az adott tablatipushoz elsodleges kulcs hasznalata kotelezo" - ita "Questo tipo di tabella richiede una chiave primaria" - por "Este tipo de tabela requer uma chave primária" - rum "Aceast tip de tabela are nevoie de o cheie primara" - rus "üÔÏÔ ÔÉÐ ÔÁÂÌÉÃÙ ÔÒÅÂÕÅÔ ÏÐÒÅÄÅÌÅÎÉÑ ÐÅÒ×ÉÞÎÏÇÏ ËÌÀÞÁ" - serbian "Ovaj tip tabele zahteva da imate definisan primarni kljuè" - spa "Este tipo de tabla necesita de una primary key" - swe "Denna tabelltyp kräver en PRIMARY KEY" - ukr "ãÅÊ ÔÉÐ ÔÁÂÌÉæ ÐÏÔÒÅÂÕ¤ ÐÅÒ×ÉÎÎÏÇÏ ËÌÀÞÁ" -ER_NO_RAID_COMPILED - cze "Tato verze MySQL nen-Bí zkompilována s podporou RAID" - dan "Denne udgave af MySQL er ikke oversat med understøttelse af RAID" - nla "Deze versie van MySQL is niet gecompileerd met RAID ondersteuning" - eng "This version of MySQL is not compiled with RAID support" - est "Antud MySQL versioon on kompileeritud ilma RAID toeta" - fre "Cette version de MySQL n'est pas compilée avec le support RAID" - ger "Diese MySQL-Version ist nicht mit RAID-Unterstützung kompiliert" - hun "Ezen leforditott MySQL verzio nem tartalmaz RAID support-ot" - ita "Questa versione di MYSQL non e` compilata con il supporto RAID" - por "Esta versão do MySQL não foi compilada com suporte a RAID" - rum "Aceasta versiune de MySQL, nu a fost compilata cu suport pentru RAID" - rus "üÔÁ ×ÅÒÓÉÑ MySQL ÓËÏÍÐÉÌÉÒÏ×ÁÎÁ ÂÅÚ ÐÏÄÄÅÒÖËÉ RAID" - serbian "Ova verzija MySQL servera nije kompajlirana sa podrškom za RAID ureðaje" - spa "Esta versión de MySQL no es compilada con soporte RAID" - swe "Denna version av MySQL är inte kompilerad med RAID" - ukr "ãÑ ×ÅÒÓ¦Ñ MySQL ÎÅ ÚËÏÍЦÌØÏ×ÁÎÁ Ú Ð¦ÄÔÒÉÍËÏÀ RAID" -ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE - cze "Update tabulky bez WHERE s kl-Bíèem není v módu bezpeèných update dovoleno" - dan "Du bruger sikker opdaterings modus ('safe update mode') og du forsøgte at opdatere en tabel uden en WHERE klausul, der gør brug af et KEY felt" - nla "U gebruikt 'safe update mode' en u probeerde een tabel te updaten zonder een WHERE met een KEY kolom" - eng "You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column" - est "Katse muuta tabelit turvalises rezhiimis ilma WHERE klauslita" - fre "Vous êtes en mode 'safe update' et vous essayez de faire un UPDATE sans clause WHERE utilisant un index" - ger "MySQL läuft im sicheren Aktualisierungsmodus (safe update mode). Sie haben versucht, eine Tabelle zu aktualisieren, ohne in der WHERE-Klausel ein KEY-Feld anzugeben" - hun "On a biztonsagos update modot hasznalja, es WHERE that uses a KEY column" - ita "In modalita` 'safe update' si e` cercato di aggiornare una tabella senza clausola WHERE su una chiave" - por "Você está usando modo de atualização seguro e tentou atualizar uma tabela sem uma cláusula WHERE que use uma coluna chave" - rus "÷Ù ÒÁÂÏÔÁÅÔÅ × ÒÅÖÉÍÅ ÂÅÚÏÐÁÓÎÙÈ ÏÂÎÏ×ÌÅÎÉÊ (safe update mode) É ÐÏÐÒÏÂÏ×ÁÌÉ ÉÚÍÅÎÉÔØ ÔÁÂÌÉÃÕ ÂÅÚ ÉÓÐÏÌØÚÏ×ÁÎÉÑ ËÌÀÞÅ×ÏÇÏ ÓÔÏÌÂÃÁ × ÞÁÓÔÉ WHERE" - serbian "Vi koristite safe update mod servera, a probali ste da promenite podatke bez 'WHERE' komande koja koristi kolonu kljuèa" - spa "Tu estás usando modo de actualización segura y tentado actualizar una tabla sin un WHERE que usa una KEY columna" - swe "Du använder 'säker uppdateringsmod' och försökte uppdatera en tabell utan en WHERE-sats som använder sig av en nyckel" - ukr "÷É Õ ÒÅÖÉͦ ÂÅÚÐÅÞÎÏÇÏ ÏÎÏ×ÌÅÎÎÑ ÔÁ ÎÁÍÁÇÁ¤ÔÅÓØ ÏÎÏ×ÉÔÉ ÔÁÂÌÉÃÀ ÂÅÚ ÏÐÅÒÁÔÏÒÁ WHERE, ÝÏ ×ÉËÏÒÉÓÔÏ×Õ¤ KEY ÓÔÏ×ÂÅÃØ" -ER_KEY_DOES_NOT_EXITS 42000 S1009 - cze "Kl-Bíè '%-.192s' v tabulce '%-.192s' neexistuje" - dan "Nøglen '%-.192s' eksisterer ikke i tabellen '%-.192s'" - nla "Zoeksleutel '%-.192s' bestaat niet in tabel '%-.192s'" - eng "Key '%-.192s' doesn't exist in table '%-.192s'" - est "Võti '%-.192s' ei eksisteeri tabelis '%-.192s'" - fre "L'index '%-.192s' n'existe pas sur la table '%-.192s'" - ger "Schlüssel '%-.192s' existiert in der Tabelle '%-.192s' nicht" - hun "A '%-.192s' kulcs nem letezik a '%-.192s' tablaban" - ita "La chiave '%-.192s' non esiste nella tabella '%-.192s'" - por "Chave '%-.192s' não existe na tabela '%-.192s'" - rus "ëÌÀÞ '%-.192s' ÎÅ ÓÕÝÅÓÔ×ÕÅÔ × ÔÁÂÌÉÃÅ '%-.192s'" - serbian "Kljuè '%-.192s' ne postoji u tabeli '%-.192s'" - spa "Clave '%-.192s' no existe en la tabla '%-.192s'" - swe "Nyckel '%-.192s' finns inte in tabell '%-.192s'" - ukr "ëÌÀÞ '%-.192s' ÎÅ ¦ÓÎÕ¤ × ÔÁÂÌÉæ '%-.192s'" -ER_CHECK_NO_SUCH_TABLE 42000 - cze "Nemohu otev-Bøít tabulku" - dan "Kan ikke åbne tabellen" - nla "Kan tabel niet openen" - eng "Can't open table" - est "Ei suuda avada tabelit" - fre "Impossible d'ouvrir la table" - ger "Kann Tabelle nicht öffnen" - hun "Nem tudom megnyitni a tablat" - ita "Impossibile aprire la tabella" - por "Não pode abrir a tabela" - rus "îÅ×ÏÚÍÏÖÎÏ ÏÔËÒÙÔØ ÔÁÂÌÉÃÕ" - serbian "Ne mogu da otvorim tabelu" - spa "No puedo abrir tabla" - swe "Kan inte öppna tabellen" - ukr "îÅ ÍÏÖÕ ×¦ÄËÒÉÔÉ ÔÁÂÌÉÃÀ" -ER_CHECK_NOT_IMPLEMENTED 42000 - cze "Handler tabulky nepodporuje %s" - dan "Denne tabeltype understøtter ikke %s" - nla "De 'handler' voor de tabel ondersteund geen %s" - eng "The storage engine for the table doesn't support %s" - est "Antud tabelitüüp ei toeta %s käske" - fre "Ce type de table ne supporte pas les %s" - ger "Die Speicher-Engine für diese Tabelle unterstützt kein %s" - greek "The handler for the table doesn't support %s" - hun "A tabla kezeloje (handler) nem tamogatja az %s" - ita "Il gestore per la tabella non supporta il %s" - jpn "The handler for the table doesn't support %s" - kor "The handler for the table doesn't support %s" - nor "The handler for the table doesn't support %s" - norwegian-ny "The handler for the table doesn't support %s" - pol "The handler for the table doesn't support %s" - por "O manipulador de tabela não suporta %s" - rum "The handler for the table doesn't support %s" - rus "ïÂÒÁÂÏÔÞÉË ÔÁÂÌÉÃÙ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ÜÔÏÇÏ: %s" - serbian "Handler za ovu tabelu ne dozvoljava %s komande" - slo "The handler for the table doesn't support %s" - spa "El manipulador de la tabla no permite soporte para %s" - swe "Tabellhanteraren för denna tabell kan inte göra %s" - ukr "÷ËÁÚ¦×ÎÉË ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕÅ %s" -ER_CANT_DO_THIS_DURING_AN_TRANSACTION 25000 - cze "Proveden-Bí tohoto pøíkazu není v transakci dovoleno" - dan "Du må ikke bruge denne kommando i en transaktion" - nla "Het is u niet toegestaan dit commando uit te voeren binnen een transactie" - eng "You are not allowed to execute this command in a transaction" - est "Seda käsku ei saa kasutada transaktsiooni sees" - fre "Vous n'êtes pas autorisé à exécute cette commande dans une transaction" - ger "Sie dürfen diesen Befehl nicht in einer Transaktion ausführen" - hun "Az On szamara nem engedelyezett a parancs vegrehajtasa a tranzakcioban" - ita "Non puoi eseguire questo comando in una transazione" - por "Não lhe é permitido executar este comando em uma transação" - rus "÷ÁÍ ÎÅ ÒÁÚÒÅÛÅÎÏ ×ÙÐÏÌÎÑÔØ ÜÔÕ ËÏÍÁÎÄÕ × ÔÒÁÎÚÁËÃÉÉ" - serbian "Nije Vam dozvoljeno da izvršite ovu komandu u transakciji" - spa "No tienes el permiso para ejecutar este comando en una transición" - swe "Du får inte utföra detta kommando i en transaktion" - ukr "÷ÁÍ ÎÅ ÄÏÚ×ÏÌÅÎÏ ×ÉËÏÎÕ×ÁÔÉ ÃÀ ËÏÍÁÎÄÕ × ÔÒÁÎÚÁËæ§" -ER_ERROR_DURING_COMMIT - cze "Chyba %d p-Bøi COMMIT" - dan "Modtog fejl %d mens kommandoen COMMIT blev udført" - nla "Kreeg fout %d tijdens COMMIT" - eng "Got error %d during COMMIT" - est "Viga %d käsu COMMIT täitmisel" - fre "Erreur %d lors du COMMIT" - ger "Fehler %d beim COMMIT" - hun "%d hiba a COMMIT vegrehajtasa soran" - ita "Rilevato l'errore %d durante il COMMIT" - por "Obteve erro %d durante COMMIT" - rus "ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ %d × ÐÒÏÃÅÓÓÅ COMMIT" - serbian "Greška %d za vreme izvršavanja komande 'COMMIT'" - spa "Obtenido error %d durante COMMIT" - swe "Fick fel %d vid COMMIT" - ukr "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d Ð¦Ä ÞÁÓ COMMIT" -ER_ERROR_DURING_ROLLBACK - cze "Chyba %d p-Bøi ROLLBACK" - dan "Modtog fejl %d mens kommandoen ROLLBACK blev udført" - nla "Kreeg fout %d tijdens ROLLBACK" - eng "Got error %d during ROLLBACK" - est "Viga %d käsu ROLLBACK täitmisel" - fre "Erreur %d lors du ROLLBACK" - ger "Fehler %d beim ROLLBACK" - hun "%d hiba a ROLLBACK vegrehajtasa soran" - ita "Rilevato l'errore %d durante il ROLLBACK" - por "Obteve erro %d durante ROLLBACK" - rus "ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ %d × ÐÒÏÃÅÓÓÅ ROLLBACK" - serbian "Greška %d za vreme izvršavanja komande 'ROLLBACK'" - spa "Obtenido error %d durante ROLLBACK" - swe "Fick fel %d vid ROLLBACK" - ukr "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d Ð¦Ä ÞÁÓ ROLLBACK" -ER_ERROR_DURING_FLUSH_LOGS - cze "Chyba %d p-Bøi FLUSH_LOGS" - dan "Modtog fejl %d mens kommandoen FLUSH_LOGS blev udført" - nla "Kreeg fout %d tijdens FLUSH_LOGS" - eng "Got error %d during FLUSH_LOGS" - est "Viga %d käsu FLUSH_LOGS täitmisel" - fre "Erreur %d lors du FLUSH_LOGS" - ger "Fehler %d bei FLUSH_LOGS" - hun "%d hiba a FLUSH_LOGS vegrehajtasa soran" - ita "Rilevato l'errore %d durante il FLUSH_LOGS" - por "Obteve erro %d durante FLUSH_LOGS" - rus "ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ %d × ÐÒÏÃÅÓÓÅ FLUSH_LOGS" - serbian "Greška %d za vreme izvršavanja komande 'FLUSH_LOGS'" - spa "Obtenido error %d durante FLUSH_LOGS" - swe "Fick fel %d vid FLUSH_LOGS" - ukr "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d Ð¦Ä ÞÁÓ FLUSH_LOGS" -ER_ERROR_DURING_CHECKPOINT - cze "Chyba %d p-Bøi CHECKPOINT" - dan "Modtog fejl %d mens kommandoen CHECKPOINT blev udført" - nla "Kreeg fout %d tijdens CHECKPOINT" - eng "Got error %d during CHECKPOINT" - est "Viga %d käsu CHECKPOINT täitmisel" - fre "Erreur %d lors du CHECKPOINT" - ger "Fehler %d bei CHECKPOINT" - hun "%d hiba a CHECKPOINT vegrehajtasa soran" - ita "Rilevato l'errore %d durante il CHECKPOINT" - por "Obteve erro %d durante CHECKPOINT" - rus "ðÏÌÕÞÅÎÁ ÏÛÉÂËÁ %d × ÐÒÏÃÅÓÓÅ CHECKPOINT" - serbian "Greška %d za vreme izvršavanja komande 'CHECKPOINT'" - spa "Obtenido error %d durante CHECKPOINT" - swe "Fick fel %d vid CHECKPOINT" - ukr "ïÔÒÉÍÁÎÏ ÐÏÍÉÌËÕ %d Ð¦Ä ÞÁÓ CHECKPOINT" -ER_NEW_ABORTING_CONNECTION 08S01 - cze "Spojen-Bí %ld do databáze: '%-.192s' u¾ivatel: '%-.48s' stroj: '%-.64s' (%-.64s) bylo pøeru¹eno" - dan "Afbrød forbindelsen %ld til databasen '%-.192s' bruger: '%-.48s' vært: '%-.64s' (%-.64s)" - nla "Afgebroken verbinding %ld naar db: '%-.192s' gebruiker: '%-.48s' host: '%-.64s' (%-.64s)" - eng "Aborted connection %ld to db: '%-.192s' user: '%-.48s' host: '%-.64s' (%-.64s)" - est "Ühendus katkestatud %ld andmebaas: '%-.192s' kasutaja: '%-.48s' masin: '%-.64s' (%-.64s)" - fre "Connection %ld avortée vers la bd: '%-.192s' utilisateur: '%-.48s' hôte: '%-.64s' (%-.64s)" - ger "Abbruch der Verbindung %ld zur Datenbank '%-.192s'. Benutzer: '%-.48s', Host: '%-.64s' (%-.64s)" - ita "Interrotta la connessione %ld al db: ''%-.192s' utente: '%-.48s' host: '%-.64s' (%-.64s)" - por "Conexão %ld abortada para banco de dados '%-.192s' - usuário '%-.48s' - 'host' '%-.64s' ('%-.64s')" - rus "ðÒÅÒ×ÁÎÏ ÓÏÅÄÉÎÅÎÉÅ %ld Ë ÂÁÚÅ ÄÁÎÎÙÈ '%-.192s' ÐÏÌØÚÏ×ÁÔÅÌÑ '%-.48s' Ó ÈÏÓÔÁ '%-.64s' (%-.64s)" - serbian "Prekinuta konekcija broj %ld ka bazi: '%-.192s' korisnik je bio: '%-.48s' a host: '%-.64s' (%-.64s)" - spa "Abortada conexión %ld para db: '%-.192s' usuario: '%-.48s' servidor: '%-.64s' (%-.64s)" - swe "Avbröt länken för tråd %ld till db '%-.192s', användare '%-.48s', host '%-.64s' (%-.64s)" - ukr "ðÅÒÅÒ×ÁÎÏ Ú'¤ÄÎÁÎÎÑ %ld ÄÏ ÂÁÚÉ ÄÁÎÎÉÈ: '%-.192s' ËÏÒÉÓÔÕ×ÁÞ: '%-.48s' ÈÏÓÔ: '%-.64s' (%-.64s)" -ER_DUMP_NOT_IMPLEMENTED - cze "Handler tabulky nepodporuje bin-Bární dump" - dan "Denne tabeltype unserstøtter ikke binært tabeldump" - nla "De 'handler' voor de tabel ondersteund geen binaire tabel dump" - eng "The storage engine for the table does not support binary table dump" - fre "Ce type de table ne supporte pas les copies binaires" - ger "Die Speicher-Engine für die Tabelle unterstützt keinen binären Tabellen-Dump" - ita "Il gestore per la tabella non supporta il dump binario" - jpn "The handler for the table does not support binary table dump" - por "O manipulador de tabela não suporta 'dump' binário de tabela" - rum "The handler for the table does not support binary table dump" - rus "ïÂÒÁÂÏÔÞÉË ÜÔÏÊ ÔÁÂÌÉÃÙ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ Ä×ÏÉÞÎÏÇÏ ÓÏÈÒÁÎÅÎÉÑ ÏÂÒÁÚÁ ÔÁÂÌÉÃÙ (dump)" - serbian "Handler tabele ne podržava binarni dump tabele" - spa "El manipulador de tabla no soporta dump para tabla binaria" - swe "Tabellhanteraren klarar inte en binär kopiering av tabellen" - ukr "ãÅÊ ÔÉÐ ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕ¤ ¦ÎÁÒÎÕ ÐÅÒÅÄÁÞÕ ÔÁÂÌÉæ" -ER_FLUSH_MASTER_BINLOG_CLOSED - eng "Binlog closed, cannot RESET MASTER" - ger "Binlog geschlossen. Kann RESET MASTER nicht ausführen" - por "Binlog fechado. Não pode fazer RESET MASTER" - rus "ä×ÏÉÞÎÙÊ ÖÕÒÎÁÌ ÏÂÎÏ×ÌÅÎÉÑ ÚÁËÒÙÔ, ÎÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ RESET MASTER" - serbian "Binarni log file zatvoren, ne mogu da izvršim komandu 'RESET MASTER'" - ukr "òÅÐ̦ËÁæÊÎÉÊ ÌÏÇ ÚÁËÒÉÔÏ, ÎÅ ÍÏÖÕ ×ÉËÏÎÁÔÉ RESET MASTER" -ER_INDEX_REBUILD - cze "P-Bøebudování indexu dumpnuté tabulky '%-.192s' nebylo úspì¹né" - dan "Kunne ikke genopbygge indekset for den dumpede tabel '%-.192s'" - nla "Gefaald tijdens heropbouw index van gedumpte tabel '%-.192s'" - eng "Failed rebuilding the index of dumped table '%-.192s'" - fre "La reconstruction de l'index de la table copiée '%-.192s' a échoué" - ger "Neuerstellung des Index der Dump-Tabelle '%-.192s' fehlgeschlagen" - greek "Failed rebuilding the index of dumped table '%-.192s'" - hun "Failed rebuilding the index of dumped table '%-.192s'" - ita "Fallita la ricostruzione dell'indice della tabella copiata '%-.192s'" - por "Falhou na reconstrução do índice da tabela 'dumped' '%-.192s'" - rus "ïÛÉÂËÁ ÐÅÒÅÓÔÒÏÊËÉ ÉÎÄÅËÓÁ ÓÏÈÒÁÎÅÎÎÏÊ ÔÁÂÌÉÃÙ '%-.192s'" - serbian "Izgradnja indeksa dump-ovane tabele '%-.192s' nije uspela" - spa "Falla reconstruyendo el indice de la tabla dumped '%-.192s'" - ukr "îÅ×ÄÁÌŠצÄÎÏ×ÌÅÎÎÑ ¦ÎÄÅËÓÁ ÐÅÒÅÄÁÎϧ ÔÁÂÌÉæ '%-.192s'" -ER_MASTER - cze "Chyba masteru: '%-.64s'" - dan "Fejl fra master: '%-.64s'" - nla "Fout van master: '%-.64s'" - eng "Error from master: '%-.64s'" - fre "Erreur reçue du maître: '%-.64s'" - ger "Fehler vom Master: '%-.64s'" - ita "Errore dal master: '%-.64s" - por "Erro no 'master' '%-.64s'" - rus "ïÛÉÂËÁ ÏÔ ÇÏÌÏ×ÎÏÇÏ ÓÅÒ×ÅÒÁ: '%-.64s'" - serbian "Greška iz glavnog servera '%-.64s' u klasteru" - spa "Error del master: '%-.64s'" - swe "Fick en master: '%-.64s'" - ukr "ðÏÍÉÌËÁ ×¦Ä ÇÏÌÏ×ÎÏÇÏ: '%-.64s'" -ER_MASTER_NET_READ 08S01 - cze "S-Bí»ová chyba pøi ètení z masteru" - dan "Netværksfejl ved læsning fra master" - nla "Net fout tijdens lezen van master" - eng "Net error reading from master" - fre "Erreur de lecture réseau reçue du maître" - ger "Netzfehler beim Lesen vom Master" - ita "Errore di rete durante la ricezione dal master" - por "Erro de rede lendo do 'master'" - rus "÷ÏÚÎÉËÌÁ ÏÛÉÂËÁ ÞÔÅÎÉÑ × ÐÒÏÃÅÓÓÅ ËÏÍÍÕÎÉËÁÃÉÉ Ó ÇÏÌÏ×ÎÙÍ ÓÅÒ×ÅÒÏÍ" - serbian "Greška u primanju mrežnih paketa sa glavnog servera u klasteru" - spa "Error de red leyendo del master" - swe "Fick nätverksfel vid läsning från master" - ukr "íÅÒÅÖÅ×Á ÐÏÍÉÌËÁ ÞÉÔÁÎÎÑ ×¦Ä ÇÏÌÏ×ÎÏÇÏ" -ER_MASTER_NET_WRITE 08S01 - cze "S-Bí»ová chyba pøi zápisu na master" - dan "Netværksfejl ved skrivning til master" - nla "Net fout tijdens schrijven naar master" - eng "Net error writing to master" - fre "Erreur d'écriture réseau reçue du maître" - ger "Netzfehler beim Schreiben zum Master" - ita "Errore di rete durante l'invio al master" - por "Erro de rede gravando no 'master'" - rus "÷ÏÚÎÉËÌÁ ÏÛÉÂËÁ ÚÁÐÉÓÉ × ÐÒÏÃÅÓÓÅ ËÏÍÍÕÎÉËÁÃÉÉ Ó ÇÏÌÏ×ÎÙÍ ÓÅÒ×ÅÒÏÍ" - serbian "Greška u slanju mrežnih paketa na glavni server u klasteru" - spa "Error de red escribiendo para el master" - swe "Fick nätverksfel vid skrivning till master" - ukr "íÅÒÅÖÅ×Á ÐÏÍÉÌËÁ ÚÁÐÉÓÕ ÄÏ ÇÏÌÏ×ÎÏÇÏ" -ER_FT_MATCHING_KEY_NOT_FOUND - cze "-B®ádný sloupec nemá vytvoøen fulltextový index" - dan "Kan ikke finde en FULLTEXT nøgle som svarer til kolonne listen" - nla "Kan geen FULLTEXT index vinden passend bij de kolom lijst" - eng "Can't find FULLTEXT index matching the column list" - est "Ei suutnud leida FULLTEXT indeksit, mis kattuks kasutatud tulpadega" - fre "Impossible de trouver un index FULLTEXT correspondant à cette liste de colonnes" - ger "Kann keinen FULLTEXT-Index finden, der der Feldliste entspricht" - ita "Impossibile trovare un indice FULLTEXT che corrisponda all'elenco delle colonne" - por "Não pode encontrar um índice para o texto todo que combine com a lista de colunas" - rus "îÅ×ÏÚÍÏÖÎÏ ÏÔÙÓËÁÔØ ÐÏÌÎÏÔÅËÓÔÏ×ÙÊ (FULLTEXT) ÉÎÄÅËÓ, ÓÏÏÔ×ÅÔÓÔ×ÕÀÝÉÊ ÓÐÉÓËÕ ÓÔÏÌÂÃÏ×" - serbian "Ne mogu da pronaðem 'FULLTEXT' indeks koli odgovara listi kolona" - spa "No puedo encontrar índice FULLTEXT correspondiendo a la lista de columnas" - swe "Hittar inte ett FULLTEXT-index i kolumnlistan" - ukr "îÅ ÍÏÖÕ ÚÎÁÊÔÉ FULLTEXT ¦ÎÄÅËÓ, ÝÏ ×¦ÄÐÏצÄÁ¤ ÐÅÒÅ̦ËÕ ÓÔÏ×Âæ×" -ER_LOCK_OR_ACTIVE_TRANSACTION - cze "Nemohu prov-Bést zadaný pøíkaz, proto¾e existují aktivní zamèené tabulky nebo aktivní transakce" - dan "Kan ikke udføre den givne kommando fordi der findes aktive, låste tabeller eller fordi der udføres en transaktion" - nla "Kan het gegeven commando niet uitvoeren, want u heeft actieve gelockte tabellen of een actieve transactie" - eng "Can't execute the given command because you have active locked tables or an active transaction" - est "Ei suuda täita antud käsku kuna on aktiivseid lukke või käimasolev transaktsioon" - fre "Impossible d'exécuter la commande car vous avez des tables verrouillées ou une transaction active" - ger "Kann den angegebenen Befehl wegen einer aktiven Tabellensperre oder einer aktiven Transaktion nicht ausführen" - ita "Impossibile eseguire il comando richiesto: tabelle sotto lock o transazione in atto" - por "Não pode executar o comando dado porque você tem tabelas ativas travadas ou uma transação ativa" - rus "îÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ ÕËÁÚÁÎÎÕÀ ËÏÍÁÎÄÕ, ÐÏÓËÏÌØËÕ Õ ×ÁÓ ÐÒÉÓÕÔÓÔ×ÕÀÔ ÁËÔÉ×ÎÏ ÚÁÂÌÏËÉÒÏ×ÁÎÎÙÅ ÔÁÂÌÉÃÁ ÉÌÉ ÏÔËÒÙÔÁÑ ÔÒÁÎÚÁËÃÉÑ" - serbian "Ne mogu da izvršim datu komandu zbog toga što su tabele zakljuèane ili je transakcija u toku" - spa "No puedo ejecutar el comando dado porque tienes tablas bloqueadas o una transición activa" - swe "Kan inte utföra kommandot emedan du har en låst tabell eller an aktiv transaktion" - ukr "îÅ ÍÏÖÕ ×ÉËÏÎÁÔÉ ÐÏÄÁÎÕ ËÏÍÁÎÄÕ ÔÏÍÕ, ÝÏ ÔÁÂÌÉÃÑ ÚÁÂÌÏËÏ×ÁÎÁ ÁÂÏ ×ÉËÏÎÕ¤ÔØÓÑ ÔÒÁÎÚÁËæÑ" -ER_UNKNOWN_SYSTEM_VARIABLE - cze "Nezn-Bámá systémová promìnná '%-.64s'" - dan "Ukendt systemvariabel '%-.64s'" - nla "Onbekende systeem variabele '%-.64s'" - eng "Unknown system variable '%-.64s'" - est "Tundmatu süsteemne muutuja '%-.64s'" - fre "Variable système '%-.64s' inconnue" - ger "Unbekannte Systemvariable '%-.64s'" - ita "Variabile di sistema '%-.64s' sconosciuta" - por "Variável de sistema '%-.64s' desconhecida" - rus "îÅÉÚ×ÅÓÔÎÁÑ ÓÉÓÔÅÍÎÁÑ ÐÅÒÅÍÅÎÎÁÑ '%-.64s'" - serbian "Nepoznata sistemska promenljiva '%-.64s'" - spa "Desconocida variable de sistema '%-.64s'" - swe "Okänd systemvariabel: '%-.64s'" - ukr "îÅצÄÏÍÁ ÓÉÓÔÅÍÎÁ ÚͦÎÎÁ '%-.64s'" -ER_CRASHED_ON_USAGE - cze "Tabulka '%-.192s' je ozna-Bèena jako poru¹ená a mìla by být opravena" - dan "Tabellen '%-.192s' er markeret med fejl og bør repareres" - nla "Tabel '%-.192s' staat als gecrashed gemarkeerd en dient te worden gerepareerd" - eng "Table '%-.192s' is marked as crashed and should be repaired" - est "Tabel '%-.192s' on märgitud vigaseks ja tuleb parandada" - fre "La table '%-.192s' est marquée 'crashed' et devrait être réparée" - ger "Tabelle '%-.192s' ist als defekt markiert und sollte repariert werden" - ita "La tabella '%-.192s' e` segnalata come corrotta e deve essere riparata" - por "Tabela '%-.192s' está marcada como danificada e deve ser reparada" - rus "ôÁÂÌÉÃÁ '%-.192s' ÐÏÍÅÞÅÎÁ ËÁË ÉÓÐÏÒÞÅÎÎÁÑ É ÄÏÌÖÎÁ ÐÒÏÊÔÉ ÐÒÏ×ÅÒËÕ É ÒÅÍÏÎÔ" - serbian "Tabela '%-.192s' je markirana kao ošteæena i trebala bi biti popravljena" - spa "Tabla '%-.192s' está marcada como crashed y debe ser reparada" - swe "Tabell '%-.192s' är trasig och bör repareras med REPAIR TABLE" - ukr "ôÁÂÌÉÃÀ '%-.192s' ÍÁÒËÏ×ÁÎÏ ÑË Ú¦ÐÓÏ×ÁÎÕ ÔÁ §§ ÐÏÔÒ¦ÂÎÏ ×¦ÄÎÏ×ÉÔÉ" -ER_CRASHED_ON_REPAIR - cze "Tabulka '%-.192s' je ozna-Bèena jako poru¹ená a poslední (automatická?) oprava se nezdaøila" - dan "Tabellen '%-.192s' er markeret med fejl og sidste (automatiske?) REPAIR fejlede" - nla "Tabel '%-.192s' staat als gecrashed gemarkeerd en de laatste (automatische?) reparatie poging mislukte" - eng "Table '%-.192s' is marked as crashed and last (automatic?) repair failed" - est "Tabel '%-.192s' on märgitud vigaseks ja viimane (automaatne?) parandus ebaõnnestus" - fre "La table '%-.192s' est marquée 'crashed' et le dernier 'repair' a échoué" - ger "Tabelle '%-.192s' ist als defekt markiert und der letzte (automatische?) Reparaturversuch schlug fehl" - ita "La tabella '%-.192s' e` segnalata come corrotta e l'ultima ricostruzione (automatica?) e` fallita" - por "Tabela '%-.192s' está marcada como danificada e a última reparação (automática?) falhou" - rus "ôÁÂÌÉÃÁ '%-.192s' ÐÏÍÅÞÅÎÁ ËÁË ÉÓÐÏÒÞÅÎÎÁÑ É ÐÏÓÌÅÄÎÉÊ (Á×ÔÏÍÁÔÉÞÅÓËÉÊ?) ÒÅÍÏÎÔ ÎÅ ÂÙÌ ÕÓÐÅÛÎÙÍ" - serbian "Tabela '%-.192s' je markirana kao ošteæena, a zadnja (automatska?) popravka je bila neuspela" - spa "Tabla '%-.192s' está marcada como crashed y la última reparación (automactica?) falló" - swe "Tabell '%-.192s' är trasig och senast (automatiska?) reparation misslyckades" - ukr "ôÁÂÌÉÃÀ '%-.192s' ÍÁÒËÏ×ÁÎÏ ÑË Ú¦ÐÓÏ×ÁÎÕ ÔÁ ÏÓÔÁÎΤ (Á×ÔÏÍÁÔÉÞÎÅ?) צÄÎÏ×ÌÅÎÎÑ ÎÅ ×ÄÁÌÏÓÑ" -ER_WARNING_NOT_COMPLETE_ROLLBACK - dan "Advarsel: Visse data i tabeller der ikke understøtter transaktioner kunne ikke tilbagestilles" - nla "Waarschuwing: Roll back mislukt voor sommige buiten transacties gewijzigde tabellen" - eng "Some non-transactional changed tables couldn't be rolled back" - est "Hoiatus: mõnesid transaktsioone mittetoetavaid tabeleid ei suudetud tagasi kerida" - fre "Attention: certaines tables ne supportant pas les transactions ont été changées et elles ne pourront pas être restituées" - ger "Änderungen an einigen nicht transaktionalen Tabellen konnten nicht zurückgerollt werden" - ita "Attenzione: Alcune delle modifiche alle tabelle non transazionali non possono essere ripristinate (roll back impossibile)" - por "Aviso: Algumas tabelas não-transacionais alteradas não puderam ser reconstituídas (rolled back)" - rus "÷ÎÉÍÁÎÉÅ: ÐÏ ÎÅËÏÔÏÒÙÍ ÉÚÍÅÎÅÎÎÙÍ ÎÅÔÒÁÎÚÁËÃÉÏÎÎÙÍ ÔÁÂÌÉÃÁÍ ÎÅ×ÏÚÍÏÖÎÏ ÂÕÄÅÔ ÐÒÏÉÚ×ÅÓÔÉ ÏÔËÁÔ ÔÒÁÎÚÁËÃÉÉ" - serbian "Upozorenje: Neke izmenjene tabele ne podržavaju komandu 'ROLLBACK'" - spa "Aviso: Algunas tablas no transancionales no pueden tener rolled back" - swe "Warning: Några icke transaktionella tabeller kunde inte återställas vid ROLLBACK" - ukr "úÁÓÔÅÒÅÖÅÎÎÑ: äÅÑ˦ ÎÅÔÒÁÎÚÁËæÊΦ ÚͦÎÉ ÔÁÂÌÉÃØ ÎÅ ÍÏÖÎÁ ÂÕÄÅ ÐÏ×ÅÒÎÕÔÉ" -ER_TRANS_CACHE_FULL - dan "Fler-udtryks transaktion krævede mere plads en 'max_binlog_cache_size' bytes. Forhøj værdien af denne variabel og prøv igen" - nla "Multi-statement transactie vereist meer dan 'max_binlog_cache_size' bytes opslag. Verhoog deze mysqld variabele en probeer opnieuw" - eng "Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again" - est "Mitme lausendiga transaktsioon nõudis rohkem ruumi kui lubatud 'max_binlog_cache_size' muutujaga. Suurenda muutuja väärtust ja proovi uuesti" - fre "Cette transaction à commandes multiples nécessite plus de 'max_binlog_cache_size' octets de stockage, augmentez cette variable de mysqld et réessayez" - ger "Transaktionen, die aus mehreren Befehlen bestehen, benötigten mehr als 'max_binlog_cache_size' Bytes an Speicher. Btte vergrössern Sie diese Server-Variable versuchen Sie es noch einmal" - ita "La transazione a comandi multipli (multi-statement) ha richiesto piu` di 'max_binlog_cache_size' bytes di disco: aumentare questa variabile di mysqld e riprovare" - por "Transações multi-declaradas (multi-statement transactions) requeriram mais do que o valor limite (max_binlog_cache_size) de bytes para armazenagem. Aumente o valor desta variável do mysqld e tente novamente" - rus "ôÒÁÎÚÁËÃÉÉ, ×ËÌÀÞÁÀÝÅÊ ÂÏÌØÛÏÅ ËÏÌÉÞÅÓÔ×Ï ËÏÍÁÎÄ, ÐÏÔÒÅÂÏ×ÁÌÏÓØ ÂÏÌÅÅ ÞÅÍ 'max_binlog_cache_size' ÂÁÊÔ. õ×ÅÌÉÞØÔÅ ÜÔÕ ÐÅÒÅÍÅÎÎÕÀ ÓÅÒ×ÅÒÁ mysqld É ÐÏÐÒÏÂÕÊÔÅ ÅÝÅ ÒÁÚ" - spa "Multipla transición necesita mas que 'max_binlog_cache_size' bytes de almacenamiento. Aumente esta variable mysqld y tente de nuevo" - swe "Transaktionen krävde mera än 'max_binlog_cache_size' minne. Öka denna mysqld-variabel och försök på nytt" - ukr "ôÒÁÎÚÁËÃ¦Ñ Ú ÂÁÇÁÔØÍÁ ×ÉÒÁÚÁÍÉ ×ÉÍÁÇÁ¤ ¦ÌØÛÅ Î¦Ö 'max_binlog_cache_size' ÂÁÊÔ¦× ÄÌÑ ÚÂÅÒ¦ÇÁÎÎÑ. ú¦ÌØÛÔÅ ÃÀ ÚͦÎÎÕ mysqld ÔÁ ÓÐÒÏÂÕÊÔÅ ÚÎÏ×Õ" -ER_SLAVE_MUST_STOP - dan "Denne handling kunne ikke udføres med kørende slave, brug først kommandoen STOP SLAVE" - nla "Deze operatie kan niet worden uitgevoerd met een actieve slave, doe eerst STOP SLAVE" - eng "This operation cannot be performed with a running slave; run STOP SLAVE first" - fre "Cette opération ne peut être réalisée avec un esclave actif, faites STOP SLAVE d'abord" - ger "Diese Operation kann bei einem aktiven Slave nicht durchgeführt werden. Bitte zuerst STOP SLAVE ausführen" - ita "Questa operazione non puo' essere eseguita con un database 'slave' che gira, lanciare prima STOP SLAVE" - por "Esta operação não pode ser realizada com um 'slave' em execução. Execute STOP SLAVE primeiro" - rus "üÔÕ ÏÐÅÒÁÃÉÀ ÎÅ×ÏÚÍÏÖÎÏ ×ÙÐÏÌÎÉÔØ ÐÒÉ ÒÁÂÏÔÁÀÝÅÍ ÐÏÔÏËÅ ÐÏÄÞÉÎÅÎÎÏÇÏ ÓÅÒ×ÅÒÁ. óÎÁÞÁÌÁ ×ÙÐÏÌÎÉÔÅ STOP SLAVE" - serbian "Ova operacija ne može biti izvršena dok je aktivan podreðeni server. Zadajte prvo komandu 'STOP SLAVE' da zaustavite podreðeni server." - spa "Esta operación no puede ser hecha con el esclavo funcionando, primero use STOP SLAVE" - swe "Denna operation kan inte göras under replikering; Gör STOP SLAVE först" - ukr "ïÐÅÒÁÃ¦Ñ ÎÅ ÍÏÖÅ ÂÕÔÉ ×ÉËÏÎÁÎÁ Ú ÚÁÐÕÝÅÎÉÍ Ð¦ÄÌÅÇÌÉÍ, ÓÐÏÞÁÔËÕ ×ÉËÏÎÁÊÔÅ STOP SLAVE" -ER_SLAVE_NOT_RUNNING - dan "Denne handling kræver en kørende slave. Konfigurer en slave og brug kommandoen START SLAVE" - nla "Deze operatie vereist een actieve slave, configureer slave en doe dan START SLAVE" - eng "This operation requires a running slave; configure slave and do START SLAVE" - fre "Cette opération nécessite un esclave actif, configurez les esclaves et faites START SLAVE" - ger "Diese Operation benötigt einen aktiven Slave. Bitte Slave konfigurieren und mittels START SLAVE aktivieren" - ita "Questa operaione richiede un database 'slave', configurarlo ed eseguire START SLAVE" - por "Esta operação requer um 'slave' em execução. Configure o 'slave' e execute START SLAVE" - rus "äÌÑ ÜÔÏÊ ÏÐÅÒÁÃÉÉ ÔÒÅÂÕÅÔÓÑ ÒÁÂÏÔÁÀÝÉÊ ÐÏÄÞÉÎÅÎÎÙÊ ÓÅÒ×ÅÒ. óÎÁÞÁÌÁ ×ÙÐÏÌÎÉÔÅ START SLAVE" - serbian "Ova operacija zahteva da je aktivan podreðeni server. Konfigurišite prvo podreðeni server i onda izvršite komandu 'START SLAVE'" - spa "Esta operación necesita el esclavo funcionando, configure esclavo y haga el START SLAVE" - swe "Denna operation kan endast göras under replikering; Konfigurera slaven och gör START SLAVE" - ukr "ïÐÅÒÁÃ¦Ñ ×ÉÍÁÇÁ¤ ÚÁÐÕÝÅÎÏÇÏ Ð¦ÄÌÅÇÌÏÇÏ, ÚËÏÎƦÇÕÒÕÊÔŠЦÄÌÅÇÌÏÇÏ ÔÁ ×ÉËÏÎÁÊÔÅ START SLAVE" -ER_BAD_SLAVE - dan "Denne server er ikke konfigureret som slave. Ret in config-filen eller brug kommandoen CHANGE MASTER TO" - nla "De server is niet geconfigureerd als slave, fix in configuratie bestand of met CHANGE MASTER TO" - eng "The server is not configured as slave; fix in config file or with CHANGE MASTER TO" - fre "Le server n'est pas configuré comme un esclave, changez le fichier de configuration ou utilisez CHANGE MASTER TO" - ger "Der Server ist nicht als Slave konfiguriert. Bitte in der Konfigurationsdatei oder mittels CHANGE MASTER TO beheben" - ita "Il server non e' configurato come 'slave', correggere il file di configurazione cambiando CHANGE MASTER TO" - por "O servidor não está configurado como 'slave'. Acerte o arquivo de configuração ou use CHANGE MASTER TO" - rus "üÔÏÔ ÓÅÒ×ÅÒ ÎÅ ÎÁÓÔÒÏÅÎ ËÁË ÐÏÄÞÉÎÅÎÎÙÊ. ÷ÎÅÓÉÔÅ ÉÓÐÒÁ×ÌÅÎÉÑ × ËÏÎÆÉÇÕÒÁÃÉÏÎÎÏÍ ÆÁÊÌÅ ÉÌÉ Ó ÐÏÍÏÝØÀ CHANGE MASTER TO" - serbian "Server nije konfigurisan kao podreðeni server, ispravite konfiguracioni file ili na njemu izvršite komandu 'CHANGE MASTER TO'" - spa "El servidor no está configurado como esclavo, edite el archivo config file o con CHANGE MASTER TO" - swe "Servern är inte konfigurerade som en replikationsslav. Ändra konfigurationsfilen eller gör CHANGE MASTER TO" - ukr "óÅÒ×ÅÒ ÎÅ ÚËÏÎƦÇÕÒÏ×ÁÎÏ ÑË Ð¦ÄÌÅÇÌÉÊ, ×ÉÐÒÁ×ÔÅ ÃÅ Õ ÆÁÊ̦ ËÏÎƦÇÕÒÁæ§ ÁÂÏ Ú CHANGE MASTER TO" -ER_MASTER_INFO - eng "Could not initialize master info structure; more error messages can be found in the MySQL error log" - fre "Impossible d'initialiser les structures d'information de maître, vous trouverez des messages d'erreur supplémentaires dans le journal des erreurs de MySQL" - ger "Konnte Master-Info-Struktur nicht initialisieren. Weitere Fehlermeldungen können im MySQL-Error-Log eingesehen werden" - serbian "Nisam mogao da inicijalizujem informacionu strukturu glavnog servera, proverite da li imam privilegije potrebne za pristup file-u 'master.info'" - swe "Kunde inte initialisera replikationsstrukturerna. See MySQL fel fil för mera information" -ER_SLAVE_THREAD - dan "Kunne ikke danne en slave-tråd; check systemressourcerne" - nla "Kon slave thread niet aanmaken, controleer systeem resources" - eng "Could not create slave thread; check system resources" - fre "Impossible de créer une tâche esclave, vérifiez les ressources système" - ger "Konnte Slave-Thread nicht starten. Bitte System-Ressourcen überprüfen" - ita "Impossibile creare il thread 'slave', controllare le risorse di sistema" - por "Não conseguiu criar 'thread' de 'slave'. Verifique os recursos do sistema" - rus "îÅ×ÏÚÍÏÖÎÏ ÓÏÚÄÁÔØ ÐÏÔÏË ÐÏÄÞÉÎÅÎÎÏÇÏ ÓÅÒ×ÅÒÁ. ðÒÏ×ÅÒØÔÅ ÓÉÓÔÅÍÎÙÅ ÒÅÓÕÒÓÙ" - serbian "Nisam mogao da startujem thread za podreðeni server, proverite sistemske resurse" - spa "No puedo crear el thread esclavo, verifique recursos del sistema" - swe "Kunde inte starta en tråd för replikering" - ukr "îÅ ÍÏÖÕ ÓÔ×ÏÒÉÔÉ Ð¦ÄÌÅÇÌÕ Ç¦ÌËÕ, ÐÅÒÅצÒÔÅ ÓÉÓÔÅÍΦ ÒÅÓÕÒÓÉ" -ER_TOO_MANY_USER_CONNECTIONS 42000 - dan "Brugeren %-.64s har allerede mere end 'max_user_connections' aktive forbindelser" - nla "Gebruiker %-.64s heeft reeds meer dan 'max_user_connections' actieve verbindingen" - eng "User %-.64s already has more than 'max_user_connections' active connections" - est "Kasutajal %-.64s on juba rohkem ühendusi kui lubatud 'max_user_connections' muutujaga" - fre "L'utilisateur %-.64s possède déjà plus de 'max_user_connections' connexions actives" - ger "Benutzer '%-.64s' hat mehr als 'max_user_connections' aktive Verbindungen" - ita "L'utente %-.64s ha gia' piu' di 'max_user_connections' connessioni attive" - por "Usuário '%-.64s' já possui mais que o valor máximo de conexões (max_user_connections) ativas" - rus "õ ÐÏÌØÚÏ×ÁÔÅÌÑ %-.64s ÕÖÅ ÂÏÌØÛÅ ÞÅÍ 'max_user_connections' ÁËÔÉ×ÎÙÈ ÓÏÅÄÉÎÅÎÉÊ" - serbian "Korisnik %-.64s veæ ima više aktivnih konekcija nego što je to odreðeno 'max_user_connections' promenljivom" - spa "Usario %-.64s ya tiene mas que 'max_user_connections' conexiones activas" - swe "Användare '%-.64s' har redan 'max_user_connections' aktiva inloggningar" - ukr "ëÏÒÉÓÔÕ×ÁÞ %-.64s ×ÖÅ ÍÁ¤ ¦ÌØÛÅ Î¦Ö 'max_user_connections' ÁËÔÉ×ÎÉÈ Ú'¤ÄÎÁÎØ" -ER_SET_CONSTANTS_ONLY - dan "Du må kun bruge konstantudtryk med SET" - nla "U mag alleen constante expressies gebruiken bij SET" - eng "You may only use constant expressions with SET" - est "Ainult konstantsed suurused on lubatud SET klauslis" - fre "Seules les expressions constantes sont autorisées avec SET" - ger "Bei SET dürfen nur konstante Ausdrücke verwendet werden" - ita "Si possono usare solo espressioni costanti con SET" - por "Você pode usar apenas expressões constantes com SET" - rus "÷Ù ÍÏÖÅÔÅ ÉÓÐÏÌØÚÏ×ÁÔØ × SET ÔÏÌØËÏ ËÏÎÓÔÁÎÔÎÙÅ ×ÙÒÁÖÅÎÉÑ" - serbian "Možete upotrebiti samo konstantan iskaz sa komandom 'SET'" - spa "Tu solo debes usar expresiones constantes con SET" - swe "Man kan endast använda konstantuttryck med SET" - ukr "íÏÖÎÁ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ ÌÉÛÅ ×ÉÒÁÚÉ Ú¦ ÓÔÁÌÉÍÉ Õ SET" -ER_LOCK_WAIT_TIMEOUT - dan "Lock wait timeout overskredet" - nla "Lock wacht tijd overschreden" - eng "Lock wait timeout exceeded; try restarting transaction" - est "Kontrollaeg ületatud luku järel ootamisel; Proovi transaktsiooni otsast alata" - fre "Timeout sur l'obtention du verrou" - ger "Beim Warten auf eine Sperre wurde die zulässige Wartezeit überschritten. Bitte versuchen Sie, die Transaktion neu zu starten" - ita "E' scaduto il timeout per l'attesa del lock" - por "Tempo de espera (timeout) de travamento excedido. Tente reiniciar a transação." - rus "ôÁÊÍÁÕÔ ÏÖÉÄÁÎÉÑ ÂÌÏËÉÒÏ×ËÉ ÉÓÔÅË; ÐÏÐÒÏÂÕÊÔÅ ÐÅÒÅÚÁÐÕÓÔÉÔØ ÔÒÁÎÚÁËÃÉÀ" - serbian "Vremenski limit za zakljuèavanje tabele je istekao; Probajte da ponovo startujete transakciju" - spa "Tiempo de bloqueo de espera excedido" - swe "Fick inte ett lås i tid ; Försök att starta om transaktionen" - ukr "úÁÔÒÉÍËÕ ÏÞ¦ËÕ×ÁÎÎÑ ÂÌÏËÕ×ÁÎÎÑ ×ÉÞÅÒÐÁÎÏ" -ER_LOCK_TABLE_FULL - dan "Det totale antal låse overstiger størrelsen på låse-tabellen" - nla "Het totale aantal locks overschrijdt de lock tabel grootte" - eng "The total number of locks exceeds the lock table size" - est "Lukkude koguarv ületab lukutabeli suuruse" - fre "Le nombre total de verrou dépasse la taille de la table des verrous" - ger "Die Gesamtzahl der Sperren überschreitet die Größe der Sperrtabelle" - ita "Il numero totale di lock e' maggiore della grandezza della tabella di lock" - por "O número total de travamentos excede o tamanho da tabela de travamentos" - rus "ïÂÝÅÅ ËÏÌÉÞÅÓÔ×Ï ÂÌÏËÉÒÏ×ÏË ÐÒÅ×ÙÓÉÌÏ ÒÁÚÍÅÒÙ ÔÁÂÌÉÃÙ ÂÌÏËÉÒÏ×ÏË" - serbian "Broj totalnih zakljuèavanja tabele premašuje velièinu tabele zakljuèavanja" - spa "El número total de bloqueos excede el tamaño de bloqueo de la tabla" - swe "Antal lås överskrider antalet reserverade lås" - ukr "úÁÇÁÌØÎÁ ˦ÌØ˦ÓÔØ ÂÌÏËÕ×ÁÎØ ÐÅÒÅ×ÉÝÉÌÁ ÒÏÚÍ¦Ò ÂÌÏËÕ×ÁÎØ ÄÌÑ ÔÁÂÌÉæ" -ER_READ_ONLY_TRANSACTION 25000 - dan "Update lås kan ikke opnås under en READ UNCOMMITTED transaktion" - nla "Update locks kunnen niet worden verkregen tijdens een READ UNCOMMITTED transactie" - eng "Update locks cannot be acquired during a READ UNCOMMITTED transaction" - est "Uuenduslukke ei saa kasutada READ UNCOMMITTED transaktsiooni käigus" - fre "Un verrou en update ne peut être acquit pendant une transaction READ UNCOMMITTED" - ger "Während einer READ-UNCOMMITTED-Transaktion können keine UPDATE-Sperren angefordert werden" - ita "I lock di aggiornamento non possono essere acquisiti durante una transazione 'READ UNCOMMITTED'" - por "Travamentos de atualização não podem ser obtidos durante uma transação de tipo READ UNCOMMITTED" - rus "âÌÏËÉÒÏ×ËÉ ÏÂÎÏ×ÌÅÎÉÊ ÎÅÌØÚÑ ÐÏÌÕÞÉÔØ × ÐÒÏÃÅÓÓÅ ÞÔÅÎÉÑ ÎÅ ÐÒÉÎÑÔÏÊ (× ÒÅÖÉÍÅ READ UNCOMMITTED) ÔÒÁÎÚÁËÃÉÉ" - serbian "Zakljuèavanja izmena ne mogu biti realizovana sve dok traje 'READ UNCOMMITTED' transakcija" - spa "Bloqueos de actualización no pueden ser adqueridos durante una transición READ UNCOMMITTED" - swe "Updateringslås kan inte göras när man använder READ UNCOMMITTED" - ukr "ïÎÏ×ÉÔÉ ÂÌÏËÕ×ÁÎÎÑ ÎÅ ÍÏÖÌÉ×Ï ÎÁ ÐÒÏÔÑÚ¦ ÔÒÁÎÚÁËæ§ READ UNCOMMITTED" -ER_DROP_DB_WITH_READ_LOCK - dan "DROP DATABASE er ikke tilladt mens en tråd holder på globalt read lock" - nla "DROP DATABASE niet toegestaan terwijl thread een globale 'read lock' bezit" - eng "DROP DATABASE not allowed while thread is holding global read lock" - est "DROP DATABASE ei ole lubatud kui lõim omab globaalset READ lukku" - fre "DROP DATABASE n'est pas autorisée pendant qu'une tâche possède un verrou global en lecture" - ger "DROP DATABASE ist nicht erlaubt, solange der Thread eine globale Lesesperre hält" - ita "DROP DATABASE non e' permesso mentre il thread ha un lock globale di lettura" - por "DROP DATABASE não permitido enquanto uma 'thread' está mantendo um travamento global de leitura" - rus "îÅ ÄÏÐÕÓËÁÅÔÓÑ DROP DATABASE, ÐÏËÁ ÐÏÔÏË ÄÅÒÖÉÔ ÇÌÏÂÁÌØÎÕÀ ÂÌÏËÉÒÏ×ËÕ ÞÔÅÎÉÑ" - serbian "Komanda 'DROP DATABASE' nije dozvoljena dok thread globalno zakljuèava èitanje podataka" - spa "DROP DATABASE no permitido mientras un thread está ejerciendo un bloqueo de lectura global" - swe "DROP DATABASE är inte tillåtet när man har ett globalt läslås" - ukr "DROP DATABASE ÎÅ ÄÏÚ×ÏÌÅÎÏ ÄÏËÉ Ç¦ÌËÁ ÐÅÒÅÂÕ×Á¤ Ð¦Ä ÚÁÇÁÌØÎÉÍ ÂÌÏËÕ×ÁÎÎÑÍ ÞÉÔÁÎÎÑ" -ER_CREATE_DB_WITH_READ_LOCK - dan "CREATE DATABASE er ikke tilladt mens en tråd holder på globalt read lock" - nla "CREATE DATABASE niet toegestaan terwijl thread een globale 'read lock' bezit" - eng "CREATE DATABASE not allowed while thread is holding global read lock" - est "CREATE DATABASE ei ole lubatud kui lõim omab globaalset READ lukku" - fre "CREATE DATABASE n'est pas autorisée pendant qu'une tâche possède un verrou global en lecture" - ger "CREATE DATABASE ist nicht erlaubt, solange der Thread eine globale Lesesperre hält" - ita "CREATE DATABASE non e' permesso mentre il thread ha un lock globale di lettura" - por "CREATE DATABASE não permitido enquanto uma 'thread' está mantendo um travamento global de leitura" - rus "îÅ ÄÏÐÕÓËÁÅÔÓÑ CREATE DATABASE, ÐÏËÁ ÐÏÔÏË ÄÅÒÖÉÔ ÇÌÏÂÁÌØÎÕÀ ÂÌÏËÉÒÏ×ËÕ ÞÔÅÎÉÑ" - serbian "Komanda 'CREATE DATABASE' nije dozvoljena dok thread globalno zakljuèava èitanje podataka" - spa "CREATE DATABASE no permitido mientras un thread está ejerciendo un bloqueo de lectura global" - swe "CREATE DATABASE är inte tillåtet när man har ett globalt läslås" - ukr "CREATE DATABASE ÎÅ ÄÏÚ×ÏÌÅÎÏ ÄÏËÉ Ç¦ÌËÁ ÐÅÒÅÂÕ×Á¤ Ð¦Ä ÚÁÇÁÌØÎÉÍ ÂÌÏËÕ×ÁÎÎÑÍ ÞÉÔÁÎÎÑ" -ER_WRONG_ARGUMENTS - nla "Foutieve parameters voor %s" - eng "Incorrect arguments to %s" - est "Vigased parameetrid %s-le" - fre "Mauvais arguments à %s" - ger "Falsche Argumente für %s" - ita "Argomenti errati a %s" - por "Argumentos errados para %s" - rus "îÅ×ÅÒÎÙÅ ÐÁÒÁÍÅÔÒÙ ÄÌÑ %s" - serbian "Pogrešni argumenti prosleðeni na %s" - spa "Argumentos errados para %s" - swe "Felaktiga argument till %s" - ukr "èÉÂÎÉÊ ÁÒÇÕÍÅÎÔ ÄÌÑ %s" -ER_NO_PERMISSION_TO_CREATE_USER 42000 - nla "'%-.48s'@'%-.64s' mag geen nieuwe gebruikers creeren" - eng "'%-.48s'@'%-.64s' is not allowed to create new users" - est "Kasutajal '%-.48s'@'%-.64s' ei ole lubatud luua uusi kasutajaid" - fre "'%-.48s'@'%-.64s' n'est pas autorisé à créer de nouveaux utilisateurs" - ger "'%-.48s'@'%-.64s' ist nicht berechtigt, neue Benutzer hinzuzufügen" - ita "A '%-.48s'@'%-.64s' non e' permesso creare nuovi utenti" - por "Não é permitido a '%-.48s'@'%-.64s' criar novos usuários" - rus "'%-.48s'@'%-.64s' ÎÅ ÒÁÚÒÅÛÁÅÔÓÑ ÓÏÚÄÁ×ÁÔØ ÎÏ×ÙÈ ÐÏÌØÚÏ×ÁÔÅÌÅÊ" - serbian "Korisniku '%-.48s'@'%-.64s' nije dozvoljeno da kreira nove korisnike" - spa "'%-.48s`@`%-.64s` no es permitido para crear nuevos usuarios" - swe "'%-.48s'@'%-.64s' har inte rättighet att skapa nya användare" - ukr "ëÏÒÉÓÔÕ×ÁÞÕ '%-.48s'@'%-.64s' ÎÅ ÄÏÚ×ÏÌÅÎÏ ÓÔ×ÏÒÀ×ÁÔÉ ÎÏ×ÉÈ ËÏÒÉÓÔÕ×ÁÞ¦×" -ER_UNION_TABLES_IN_DIFFERENT_DIR - nla "Incorrecte tabel definitie; alle MERGE tabellen moeten tot dezelfde database behoren" - eng "Incorrect table definition; all MERGE tables must be in the same database" - est "Vigane tabelimääratlus; kõik MERGE tabeli liikmed peavad asuma samas andmebaasis" - fre "Définition de table incorrecte; toutes les tables MERGE doivent être dans la même base de donnée" - ger "Falsche Tabellendefinition. Alle MERGE-Tabellen müssen sich in derselben Datenbank befinden" - ita "Definizione della tabella errata; tutte le tabelle di tipo MERGE devono essere nello stesso database" - por "Definição incorreta da tabela. Todas as tabelas contidas na junção devem estar no mesmo banco de dados." - rus "îÅ×ÅÒÎÏÅ ÏÐÒÅÄÅÌÅÎÉÅ ÔÁÂÌÉÃÙ; ÷ÓÅ ÔÁÂÌÉÃÙ × MERGE ÄÏÌÖÎÙ ÐÒÉÎÁÄÌÅÖÁÔØ ÏÄÎÏÊ É ÔÏÊ ÖÅ ÂÁÚÅ ÄÁÎÎÙÈ" - serbian "Pogrešna definicija tabele; sve 'MERGE' tabele moraju biti u istoj bazi podataka" - spa "Incorrecta definición de la tabla; Todas las tablas MERGE deben estar en el mismo banco de datos" - swe "Felaktig tabelldefinition; alla tabeller i en MERGE-tabell måste vara i samma databas" -ER_LOCK_DEADLOCK 40001 - nla "Deadlock gevonden tijdens lock-aanvraag poging; Probeer herstart van de transactie" - eng "Deadlock found when trying to get lock; try restarting transaction" - est "Lukustamisel tekkis tupik (deadlock); alusta transaktsiooni otsast" - fre "Deadlock découvert en essayant d'obtenir les verrous : essayez de redémarrer la transaction" - ger "Beim Versuch, eine Sperre anzufordern, ist ein Deadlock aufgetreten. Versuchen Sie, die Transaktion neu zu starten" - ita "Trovato deadlock durante il lock; Provare a far ripartire la transazione" - por "Encontrado um travamento fatal (deadlock) quando tentava obter uma trava. Tente reiniciar a transação." - rus "÷ÏÚÎÉËÌÁ ÔÕÐÉËÏ×ÁÑ ÓÉÔÕÁÃÉÑ × ÐÒÏÃÅÓÓÅ ÐÏÌÕÞÅÎÉÑ ÂÌÏËÉÒÏ×ËÉ; ðÏÐÒÏÂÕÊÔÅ ÐÅÒÅÚÁÐÕÓÔÉÔØ ÔÒÁÎÚÁËÃÉÀ" - serbian "Unakrsno zakljuèavanje pronaðeno kada sam pokušao da dobijem pravo na zakljuèavanje; Probajte da restartujete transakciju" - spa "Encontrado deadlock cuando tentando obtener el bloqueo; Tente recomenzar la transición" - swe "Fick 'DEADLOCK' vid låsförsök av block/rad. Försök att starta om transaktionen" -ER_TABLE_CANT_HANDLE_FT - nla "Het gebruikte tabel type ondersteund geen FULLTEXT indexen" - eng "The used table type doesn't support FULLTEXT indexes" - est "Antud tabelitüüp ei toeta FULLTEXT indekseid" - fre "Le type de table utilisé ne supporte pas les index FULLTEXT" - ger "Der verwendete Tabellentyp unterstützt keine FULLTEXT-Indizes" - ita "La tabella usata non supporta gli indici FULLTEXT" - por "O tipo de tabela utilizado não suporta índices de texto completo (fulltext indexes)" - rus "éÓÐÏÌØÚÕÅÍÙÊ ÔÉÐ ÔÁÂÌÉà ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ ÐÏÌÎÏÔÅËÓÔÏ×ÙÈ ÉÎÄÅËÓÏ×" - serbian "Upotrebljeni tip tabele ne podržava 'FULLTEXT' indekse" - spa "El tipo de tabla usada no soporta índices FULLTEXT" - swe "Tabelltypen har inte hantering av FULLTEXT-index" - ukr "÷ÉËÏÒÉÓÔÁÎÉÊ ÔÉÐ ÔÁÂÌÉæ ΊЦÄÔÒÉÍÕ¤ FULLTEXT ¦ÎÄÅËÓ¦×" -ER_CANNOT_ADD_FOREIGN - nla "Kan foreign key beperking niet toevoegen" - eng "Cannot add foreign key constraint" - fre "Impossible d'ajouter des contraintes d'index externe" - ger "Fremdschlüssel-Beschränkung kann nicht hinzugefügt werden" - ita "Impossibile aggiungere il vincolo di integrita' referenziale (foreign key constraint)" - por "Não pode acrescentar uma restrição de chave estrangeira" - rus "îÅ×ÏÚÍÏÖÎÏ ÄÏÂÁ×ÉÔØ ÏÇÒÁÎÉÞÅÎÉÑ ×ÎÅÛÎÅÇÏ ËÌÀÞÁ" - serbian "Ne mogu da dodam proveru spoljnog kljuèa" - spa "No puede adicionar clave extranjera constraint" - swe "Kan inte lägga till 'FOREIGN KEY constraint'" -ER_NO_REFERENCED_ROW 23000 - nla "Kan onderliggende rij niet toevoegen: foreign key beperking gefaald" - eng "Cannot add or update a child row: a foreign key constraint fails" - fre "Impossible d'ajouter un enregistrement fils : une constrainte externe l'empèche" - ger "Hinzufügen oder Aktualisieren eines Kind-Datensatzes schlug aufgrund einer Fremdschlüssel-Beschränkung fehl" - greek "Cannot add a child row: a foreign key constraint fails" - hun "Cannot add a child row: a foreign key constraint fails" - ita "Impossibile aggiungere la riga: un vincolo d'integrita' referenziale non e' soddisfatto" - norwegian-ny "Cannot add a child row: a foreign key constraint fails" - por "Não pode acrescentar uma linha filha: uma restrição de chave estrangeira falhou" - rus "îÅ×ÏÚÍÏÖÎÏ ÄÏÂÁ×ÉÔØ ÉÌÉ ÏÂÎÏ×ÉÔØ ÄÏÞÅÒÎÀÀ ÓÔÒÏËÕ: ÐÒÏ×ÅÒËÁ ÏÇÒÁÎÉÞÅÎÉÊ ×ÎÅÛÎÅÇÏ ËÌÀÞÁ ÎÅ ×ÙÐÏÌÎÑÅÔÓÑ" - spa "No puede adicionar una línea hijo: falla de clave extranjera constraint" - swe "FOREIGN KEY-konflikt: Kan inte skriva barn" -ER_ROW_IS_REFERENCED 23000 - eng "Cannot delete or update a parent row: a foreign key constraint fails" - fre "Impossible de supprimer un enregistrement père : une constrainte externe l'empèche" - ger "Löschen oder Aktualisieren eines Eltern-Datensatzes schlug aufgrund einer Fremdschlüssel-Beschränkung fehl" - greek "Cannot delete a parent row: a foreign key constraint fails" - hun "Cannot delete a parent row: a foreign key constraint fails" - ita "Impossibile cancellare la riga: un vincolo d'integrita' referenziale non e' soddisfatto" - por "Não pode apagar uma linha pai: uma restrição de chave estrangeira falhou" - rus "îÅ×ÏÚÍÏÖÎÏ ÕÄÁÌÉÔØ ÉÌÉ ÏÂÎÏ×ÉÔØ ÒÏÄÉÔÅÌØÓËÕÀ ÓÔÒÏËÕ: ÐÒÏ×ÅÒËÁ ÏÇÒÁÎÉÞÅÎÉÊ ×ÎÅÛÎÅÇÏ ËÌÀÞÁ ÎÅ ×ÙÐÏÌÎÑÅÔÓÑ" - serbian "Ne mogu da izbrišem roditeljski slog: provera spoljnog kljuèa je neuspela" - spa "No puede deletar una línea padre: falla de clave extranjera constraint" - swe "FOREIGN KEY-konflikt: Kan inte radera fader" -ER_CONNECT_TO_MASTER 08S01 - nla "Fout bij opbouwen verbinding naar master: %-.128s" - eng "Error connecting to master: %-.128s" - ger "Fehler bei der Verbindung zum Master: %-.128s" - ita "Errore durante la connessione al master: %-.128s" - por "Erro conectando com o master: %-.128s" - rus "ïÛÉÂËÁ ÓÏÅÄÉÎÅÎÉÑ Ó ÇÏÌÏ×ÎÙÍ ÓÅÒ×ÅÒÏÍ: %-.128s" - spa "Error de coneccion a master: %-.128s" - swe "Fick fel vid anslutning till master: %-.128s" -ER_QUERY_ON_MASTER - nla "Fout bij uitvoeren query op master: %-.128s" - eng "Error running query on master: %-.128s" - ger "Beim Ausführen einer Abfrage auf dem Master trat ein Fehler auf: %-.128s" - ita "Errore eseguendo una query sul master: %-.128s" - por "Erro rodando consulta no master: %-.128s" - rus "ïÛÉÂËÁ ×ÙÐÏÌÎÅÎÉÑ ÚÁÐÒÏÓÁ ÎÁ ÇÏÌÏ×ÎÏÍ ÓÅÒ×ÅÒÅ: %-.128s" - spa "Error executando el query en master: %-.128s" - swe "Fick fel vid utförande av command på mastern: %-.128s" -ER_ERROR_WHEN_EXECUTING_COMMAND - nla "Fout tijdens uitvoeren van commando %s: %-.128s" - eng "Error when executing command %s: %-.128s" - est "Viga käsu %s täitmisel: %-.128s" - ger "Fehler beim Ausführen des Befehls %s: %-.128s" - ita "Errore durante l'esecuzione del comando %s: %-.128s" - por "Erro quando executando comando %s: %-.128s" - rus "ïÛÉÂËÁ ÐÒÉ ×ÙÐÏÌÎÅÎÉÉ ËÏÍÁÎÄÙ %s: %-.128s" - serbian "Greška pri izvršavanju komande %s: %-.128s" - spa "Error de %s: %-.128s" - swe "Fick fel vid utförande av %s: %-.128s" -ER_WRONG_USAGE - nla "Foutief gebruik van %s en %s" - eng "Incorrect usage of %s and %s" - est "Vigane %s ja %s kasutus" - ger "Falsche Verwendung von %s und %s" - ita "Uso errato di %s e %s" - por "Uso errado de %s e %s" - rus "îÅ×ÅÒÎÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ %s É %s" - serbian "Pogrešna upotreba %s i %s" - spa "Equivocado uso de %s y %s" - swe "Felaktig använding av %s and %s" - ukr "Wrong usage of %s and %s" -ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT 21000 - nla "De gebruikte SELECT commando's hebben een verschillend aantal kolommen" - eng "The used SELECT statements have a different number of columns" - est "Tulpade arv kasutatud SELECT lausetes ei kattu" - ger "Die verwendeten SELECT-Befehle liefern unterschiedliche Anzahlen von Feldern zurück" - ita "La SELECT utilizzata ha un numero di colonne differente" - por "Os comandos SELECT usados têm diferente número de colunas" - rus "éÓÐÏÌØÚÏ×ÁÎÎÙÅ ÏÐÅÒÁÔÏÒÙ ×ÙÂÏÒËÉ (SELECT) ÄÁÀÔ ÒÁÚÎÏÅ ËÏÌÉÞÅÓÔ×Ï ÓÔÏÌÂÃÏ×" - serbian "Upotrebljene 'SELECT' komande adresiraju razlièit broj kolona" - spa "El comando SELECT usado tiene diferente número de columnas" - swe "SELECT-kommandona har olika antal kolumner" -ER_CANT_UPDATE_WITH_READLOCK - nla "Kan de query niet uitvoeren vanwege een conflicterende read lock" - eng "Can't execute the query because you have a conflicting read lock" - est "Ei suuda täita päringut konfliktse luku tõttu" - ger "Augrund eines READ-LOCK-Konflikts kann die Abfrage nicht ausgeführt werden" - ita "Impossibile eseguire la query perche' c'e' un conflitto con in lock di lettura" - por "Não posso executar a consulta porque você tem um conflito de travamento de leitura" - rus "îÅ×ÏÚÍÏÖÎÏ ÉÓÐÏÌÎÉÔØ ÚÁÐÒÏÓ, ÐÏÓËÏÌØËÕ Õ ×ÁÓ ÕÓÔÁÎÏ×ÌÅÎÙ ËÏÎÆÌÉËÔÕÀÝÉÅ ÂÌÏËÉÒÏ×ËÉ ÞÔÅÎÉÑ" - serbian "Ne mogu da izvršim upit zbog toga što imate zakljuèavanja èitanja podataka u konfliktu" - spa "No puedo ejecutar el query porque usted tiene conflicto de traba de lectura" - swe "Kan inte utföra kommandot emedan du har ett READ-lås" -ER_MIXING_NOT_ALLOWED - nla "Het combineren van transactionele en niet-transactionele tabellen is uitgeschakeld." - eng "Mixing of transactional and non-transactional tables is disabled" - est "Transaktsioone toetavate ning mittetoetavate tabelite kooskasutamine ei ole lubatud" - ger "Die gleichzeitige Verwendung von Tabellen mit und ohne Transaktionsunterstützung ist deaktiviert" - ita "E' disabilitata la possibilita' di mischiare tabelle transazionali e non-transazionali" - por "Mistura de tabelas transacional e não-transacional está desabilitada" - rus "éÓÐÏÌØÚÏ×ÁÎÉÅ ÔÒÁÎÚÁËÃÉÏÎÎÙÈ ÔÁÂÌÉà ÎÁÒÑÄÕ Ó ÎÅÔÒÁÎÚÁËÃÉÏÎÎÙÍÉ ÚÁÐÒÅÝÅÎÏ" - serbian "Mešanje tabela koje podržavaju transakcije i onih koje ne podržavaju transakcije je iskljuèeno" - spa "Mezla de transancional y no-transancional tablas está deshabilitada" - swe "Blandning av transaktionella och icke-transaktionella tabeller är inaktiverat" -ER_DUP_ARGUMENT - nla "Optie '%s' tweemaal gebruikt in opdracht" - eng "Option '%s' used twice in statement" - est "Määrangut '%s' on lauses kasutatud topelt" - ger "Option '%s' wird im Befehl zweimal verwendet" - ita "L'opzione '%s' e' stata usata due volte nel comando" - por "Opção '%s' usada duas vezes no comando" - rus "ïÐÃÉÑ '%s' Ä×ÁÖÄÙ ÉÓÐÏÌØÚÏ×ÁÎÁ × ×ÙÒÁÖÅÎÉÉ" - spa "Opción '%s' usada dos veces en el comando" - swe "Option '%s' användes två gånger" -ER_USER_LIMIT_REACHED 42000 - nla "Gebruiker '%-.64s' heeft het maximale gebruik van de '%s' faciliteit overschreden (huidige waarde: %ld)" - eng "User '%-.64s' has exceeded the '%s' resource (current value: %ld)" - ger "Benutzer '%-.64s' hat die Ressourcenbeschränkung '%s' überschritten (aktueller Wert: %ld)" - ita "L'utente '%-.64s' ha ecceduto la risorsa '%s' (valore corrente: %ld)" - por "Usuário '%-.64s' tem excedido o '%s' recurso (atual valor: %ld)" - rus "ðÏÌØÚÏ×ÁÔÅÌØ '%-.64s' ÐÒÅ×ÙÓÉÌ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ÒÅÓÕÒÓÁ '%s' (ÔÅËÕÝÅÅ ÚÎÁÞÅÎÉÅ: %ld)" - spa "Usuario '%-.64s' ha excedido el recurso '%s' (actual valor: %ld)" - swe "Användare '%-.64s' har överskridit '%s' (nuvarande värde: %ld)" -ER_SPECIFIC_ACCESS_DENIED_ERROR 42000 - nla "Toegang geweigerd. U moet het %-.128s privilege hebben voor deze operatie" - eng "Access denied; you need (at least one of) the %-.128s privilege(s) for this operation" - ger "Kein Zugriff. Hierfür wird die Berechtigung %-.128s benötigt" - ita "Accesso non consentito. Serve il privilegio %-.128s per questa operazione" - por "Acesso negado. Você precisa o privilégio %-.128s para essa operação" - rus "÷ ÄÏÓÔÕÐÅ ÏÔËÁÚÁÎÏ. ÷ÁÍ ÎÕÖÎÙ ÐÒÉ×ÉÌÅÇÉÉ %-.128s ÄÌÑ ÜÔÏÊ ÏÐÅÒÁÃÉÉ" - spa "Acceso negado. Usted necesita el privilegio %-.128s para esta operación" - swe "Du har inte privlegiet '%-.128s' som behövs för denna operation" - ukr "Access denied. You need the %-.128s privilege for this operation" -ER_LOCAL_VARIABLE - nla "Variabele '%-.64s' is SESSION en kan niet worden gebruikt met SET GLOBAL" - eng "Variable '%-.64s' is a SESSION variable and can't be used with SET GLOBAL" - ger "Variable '%-.64s' ist eine lokale Variable und kann nicht mit SET GLOBAL verändert werden" - ita "La variabile '%-.64s' e' una variabile locale ( SESSION ) e non puo' essere cambiata usando SET GLOBAL" - por "Variável '%-.64s' é uma SESSION variável e não pode ser usada com SET GLOBAL" - rus "ðÅÒÅÍÅÎÎÁÑ '%-.64s' Ñ×ÌÑÅÔÓÑ ÐÏÔÏËÏ×ÏÊ (SESSION) ÐÅÒÅÍÅÎÎÏÊ É ÎÅ ÍÏÖÅÔ ÂÙÔØ ÉÚÍÅÎÅÎÁ Ó ÐÏÍÏÝØÀ SET GLOBAL" - spa "Variable '%-.64s' es una SESSION variable y no puede ser usada con SET GLOBAL" - swe "Variabel '%-.64s' är en SESSION variabel och kan inte ändrad med SET GLOBAL" -ER_GLOBAL_VARIABLE - nla "Variabele '%-.64s' is GLOBAL en dient te worden gewijzigd met SET GLOBAL" - eng "Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL" - ger "Variable '%-.64s' ist eine globale Variable und muss mit SET GLOBAL verändert werden" - ita "La variabile '%-.64s' e' una variabile globale ( GLOBAL ) e deve essere cambiata usando SET GLOBAL" - por "Variável '%-.64s' é uma GLOBAL variável e deve ser configurada com SET GLOBAL" - rus "ðÅÒÅÍÅÎÎÁÑ '%-.64s' Ñ×ÌÑÅÔÓÑ ÇÌÏÂÁÌØÎÏÊ (GLOBAL) ÐÅÒÅÍÅÎÎÏÊ, É ÅÅ ÓÌÅÄÕÅÔ ÉÚÍÅÎÑÔØ Ó ÐÏÍÏÝØÀ SET GLOBAL" - spa "Variable '%-.64s' es una GLOBAL variable y no puede ser configurada con SET GLOBAL" - swe "Variabel '%-.64s' är en GLOBAL variabel och bör sättas med SET GLOBAL" -ER_NO_DEFAULT 42000 - nla "Variabele '%-.64s' heeft geen standaard waarde" - eng "Variable '%-.64s' doesn't have a default value" - ger "Variable '%-.64s' hat keinen Vorgabewert" - ita "La variabile '%-.64s' non ha un valore di default" - por "Variável '%-.64s' não tem um valor padrão" - rus "ðÅÒÅÍÅÎÎÁÑ '%-.64s' ÎÅ ÉÍÅÅÔ ÚÎÁÞÅÎÉÑ ÐÏ ÕÍÏÌÞÁÎÉÀ" - spa "Variable '%-.64s' no tiene un valor patrón" - swe "Variabel '%-.64s' har inte ett DEFAULT-värde" -ER_WRONG_VALUE_FOR_VAR 42000 - nla "Variabele '%-.64s' kan niet worden gewijzigd naar de waarde '%-.200s'" - eng "Variable '%-.64s' can't be set to the value of '%-.200s'" - ger "Variable '%-.64s' kann nicht auf '%-.200s' gesetzt werden" - ita "Alla variabile '%-.64s' non puo' essere assegato il valore '%-.200s'" - por "Variável '%-.64s' não pode ser configurada para o valor de '%-.200s'" - rus "ðÅÒÅÍÅÎÎÁÑ '%-.64s' ÎÅ ÍÏÖÅÔ ÂÙÔØ ÕÓÔÁÎÏ×ÌÅÎÁ × ÚÎÁÞÅÎÉÅ '%-.200s'" - spa "Variable '%-.64s' no puede ser configurada para el valor de '%-.200s'" - swe "Variabel '%-.64s' kan inte sättas till '%-.200s'" -ER_WRONG_TYPE_FOR_VAR 42000 - nla "Foutief argumenttype voor variabele '%-.64s'" - eng "Incorrect argument type to variable '%-.64s'" - ger "Falscher Argumenttyp für Variable '%-.64s'" - ita "Tipo di valore errato per la variabile '%-.64s'" - por "Tipo errado de argumento para variável '%-.64s'" - rus "îÅ×ÅÒÎÙÊ ÔÉÐ ÁÒÇÕÍÅÎÔÁ ÄÌÑ ÐÅÒÅÍÅÎÎÏÊ '%-.64s'" - spa "Tipo de argumento equivocado para variable '%-.64s'" - swe "Fel typ av argument till variabel '%-.64s'" -ER_VAR_CANT_BE_READ - nla "Variabele '%-.64s' kan alleen worden gewijzigd, niet gelezen" - eng "Variable '%-.64s' can only be set, not read" - ger "Variable '%-.64s' kann nur verändert, nicht gelesen werden" - ita "Alla variabile '%-.64s' e' di sola scrittura quindi puo' essere solo assegnato un valore, non letto" - por "Variável '%-.64s' somente pode ser configurada, não lida" - rus "ðÅÒÅÍÅÎÎÁÑ '%-.64s' ÍÏÖÅÔ ÂÙÔØ ÔÏÌØËÏ ÕÓÔÁÎÏ×ÌÅÎÁ, ÎÏ ÎÅ ÓÞÉÔÁÎÁ" - spa "Variable '%-.64s' solamente puede ser configurada, no leída" - swe "Variabeln '%-.64s' kan endast sättas, inte läsas" -ER_CANT_USE_OPTION_HERE 42000 - nla "Foutieve toepassing/plaatsing van '%s'" - eng "Incorrect usage/placement of '%s'" - ger "Falsche Verwendung oder Platzierung von '%s'" - ita "Uso/posizione di '%s' sbagliato" - por "Errado uso/colocação de '%s'" - rus "îÅ×ÅÒÎÏÅ ÉÓÐÏÌØÚÏ×ÁÎÉÅ ÉÌÉ × ÎÅ×ÅÒÎÏÍ ÍÅÓÔÅ ÕËÁÚÁÎ '%s'" - spa "Equivocado uso/colocación de '%s'" - swe "Fel använding/placering av '%s'" -ER_NOT_SUPPORTED_YET 42000 - nla "Deze versie van MySQL ondersteunt nog geen '%s'" - eng "This version of MySQL doesn't yet support '%s'" - ger "Diese MySQL-Version unterstützt '%s' nicht" - ita "Questa versione di MySQL non supporta ancora '%s'" - por "Esta versão de MySQL não suporta ainda '%s'" - rus "üÔÁ ×ÅÒÓÉÑ MySQL ÐÏËÁ ÅÝÅ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔ '%s'" - spa "Esta versión de MySQL no soporta todavia '%s'" - swe "Denna version av MySQL kan ännu inte utföra '%s'" -ER_MASTER_FATAL_ERROR_READING_BINLOG - nla "Kreeg fatale fout %d: '%-.128s' van master tijdens lezen van data uit binaire log" - eng "Got fatal error %d from master when reading data from binary log: '%-.128s'" - ger "Schwerer Fehler %d: '%-.128s vom Master beim Lesen des binären Logs" - ita "Errore fatale %d: '%-.128s' dal master leggendo i dati dal log binario" - por "Obteve fatal erro %d: '%-.128s' do master quando lendo dados do binary log" - rus "ðÏÌÕÞÅÎÁ ÎÅÉÓÐÒÁ×ÉÍÁÑ ÏÛÉÂËÁ %d: '%-.128s' ÏÔ ÇÏÌÏ×ÎÏÇÏ ÓÅÒ×ÅÒÁ × ÐÒÏÃÅÓÓÅ ×ÙÂÏÒËÉ ÄÁÎÎÙÈ ÉÚ Ä×ÏÉÞÎÏÇÏ ÖÕÒÎÁÌÁ" - spa "Recibió fatal error %d: '%-.128s' del master cuando leyendo datos del binary log" - swe "Fick fatalt fel %d: '%-.128s' från master vid läsning av binärloggen" -ER_SLAVE_IGNORED_TABLE - eng "Slave SQL thread ignored the query because of replicate-*-table rules" - ger "Slave-SQL-Thread hat die Abfrage aufgrund von replicate-*-table-Regeln ignoriert" - nla "Slave SQL thread negeerde de query vanwege replicate-*-table opties" - por "Slave SQL thread ignorado a consulta devido às normas de replicação-*-tabela" - spa "Slave SQL thread ignorado el query debido a las reglas de replicación-*-tabla" - swe "Slav SQL tråden ignorerade frågan pga en replicate-*-table regel" -ER_INCORRECT_GLOBAL_LOCAL_VAR - eng "Variable '%-.192s' is a %s variable" - serbian "Promenljiva '%-.192s' je %s promenljiva" - ger "Variable '%-.192s' ist eine %s-Variable" - nla "Variabele '%-.192s' is geen %s variabele" - spa "Variable '%-.192s' es una %s variable" - swe "Variabel '%-.192s' är av typ %s" -ER_WRONG_FK_DEF 42000 - eng "Incorrect foreign key definition for '%-.192s': %s" - ger "Falsche Fremdschlüssel-Definition für '%-.192s': %s" - nla "Incorrecte foreign key definitie voor '%-.192s': %s" - por "Definição errada da chave estrangeira para '%-.192s': %s" - spa "Equivocada definición de llave extranjera para '%-.192s': %s" - swe "Felaktig FOREIGN KEY-definition för '%-.192s': %s" -ER_KEY_REF_DO_NOT_MATCH_TABLE_REF - eng "Key reference and table reference don't match" - ger "Schlüssel- und Tabellenverweis passen nicht zusammen" - nla "Sleutel- en tabelreferentie komen niet overeen" - por "Referência da chave e referência da tabela não coincidem" - spa "Referencia de llave y referencia de tabla no coinciden" - swe "Nyckelreferensen och tabellreferensen stämmer inte överens" -ER_OPERAND_COLUMNS 21000 - eng "Operand should contain %d column(s)" - ger "Operand sollte %d Spalte(n) enthalten" - nla "Operand behoort %d kolommen te bevatten" - rus "ïÐÅÒÁÎÄ ÄÏÌÖÅÎ ÓÏÄÅÒÖÁÔØ %d ËÏÌÏÎÏË" - spa "Operando debe tener %d columna(s)" - ukr "ïÐÅÒÁÎÄ ÍÁ¤ ÓËÌÁÄÁÔÉÓÑ Ú %d ÓÔÏ×Âæ×" -ER_SUBQUERY_NO_1_ROW 21000 - eng "Subquery returns more than 1 row" - ger "Unterabfrage lieferte mehr als einen Datensatz zurück" - nla "Subquery retourneert meer dan 1 rij" - por "Subconsulta retorna mais que 1 registro" - rus "ðÏÄÚÁÐÒÏÓ ×ÏÚ×ÒÁÝÁÅÔ ÂÏÌÅÅ ÏÄÎÏÊ ÚÁÐÉÓÉ" - spa "Subconsulta retorna mas que 1 línea" - swe "Subquery returnerade mer än 1 rad" - ukr "ð¦ÄÚÁÐÉÔ ÐÏ×ÅÒÔÁ¤ ¦ÌØÛ ÎiÖ 1 ÚÁÐÉÓ" -ER_UNKNOWN_STMT_HANDLER - dan "Unknown prepared statement handler (%.*s) given to %s" - eng "Unknown prepared statement handler (%.*s) given to %s" - ger "Unbekannter Prepared-Statement-Handler (%.*s) für %s angegeben" - nla "Onebekende prepared statement handler (%.*s) voor %s aangegeven" - por "Desconhecido manipulador de declaração preparado (%.*s) determinado para %s" - spa "Desconocido preparado comando handler (%.*s) dado para %s" - swe "Okänd PREPARED STATEMENT id (%.*s) var given till %s" - ukr "Unknown prepared statement handler (%.*s) given to %s" -ER_CORRUPT_HELP_DB - eng "Help database is corrupt or does not exist" - ger "Die Hilfe-Datenbank ist beschädigt oder existiert nicht" - nla "Help database is beschadigd of bestaat niet" - por "Banco de dado de ajuda corrupto ou não existente" - spa "Base de datos Help está corrupto o no existe" - swe "Hjälpdatabasen finns inte eller är skadad" -ER_CYCLIC_REFERENCE - eng "Cyclic reference on subqueries" - ger "Zyklischer Verweis in Unterabfragen" - nla "Cyclische verwijzing in subqueries" - por "Referência cíclica em subconsultas" - rus "ãÉËÌÉÞÅÓËÁÑ ÓÓÙÌËÁ ÎÁ ÐÏÄÚÁÐÒÏÓ" - spa "Cíclica referencia en subconsultas" - swe "Cyklisk referens i subqueries" - ukr "ãÉË̦ÞÎÅ ÐÏÓÉÌÁÎÎÑ ÎÁ ЦÄÚÁÐÉÔ" -ER_AUTO_CONVERT - eng "Converting column '%s' from %s to %s" - ger "Feld '%s' wird von %s nach %s umgewandelt" - nla "Veld '%s' wordt van %s naar %s geconverteerd" - por "Convertendo coluna '%s' de %s para %s" - rus "ðÒÅÏÂÒÁÚÏ×ÁÎÉÅ ÐÏÌÑ '%s' ÉÚ %s × %s" - spa "Convirtiendo columna '%s' de %s para %s" - swe "Konvertar kolumn '%s' från %s till %s" - ukr "ðÅÒÅÔ×ÏÒÅÎÎÑ ÓÔÏ×ÂÃÁ '%s' Ú %s Õ %s" -ER_ILLEGAL_REFERENCE 42S22 - eng "Reference '%-.64s' not supported (%s)" - ger "Verweis '%-.64s' wird nicht unterstützt (%s)" - nla "Verwijzing '%-.64s' niet ondersteund (%s)" - por "Referência '%-.64s' não suportada (%s)" - rus "óÓÙÌËÁ '%-.64s' ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ (%s)" - spa "Referencia '%-.64s' no soportada (%s)" - swe "Referens '%-.64s' stöds inte (%s)" - ukr "ðÏÓÉÌÁÎÎÑ '%-.64s' ÎÅ ÐiÄÔÒÉÍÕÅÔÓÑ (%s)" -ER_DERIVED_MUST_HAVE_ALIAS 42000 - eng "Every derived table must have its own alias" - ger "Für jede abgeleitete Tabelle muss ein eigener Alias angegeben werden" - nla "Voor elke afgeleide tabel moet een unieke alias worden gebruikt" - por "Cada tabela derivada deve ter seu próprio alias" - spa "Cada tabla derivada debe tener su propio alias" - swe "Varje 'derived table' måste ha sitt eget alias" -ER_SELECT_REDUCED 01000 - eng "Select %u was reduced during optimization" - ger "Select %u wurde während der Optimierung reduziert" - nla "Select %u werd geredureerd tijdens optimtalisatie" - por "Select %u foi reduzido durante otimização" - rus "Select %u ÂÙÌ ÕÐÒÁÚÄÎÅÎ × ÐÒÏÃÅÓÓÅ ÏÐÔÉÍÉÚÁÃÉÉ" - spa "Select %u fué reducido durante optimización" - swe "Select %u reducerades vid optimiering" - ukr "Select %u was ÓËÁÓÏ×ÁÎÏ ÐÒÉ ÏÐÔÉÍiÚÁÃii" -ER_TABLENAME_NOT_ALLOWED_HERE 42000 - eng "Table '%-.192s' from one of the SELECTs cannot be used in %-.32s" - ger "Tabelle '%-.192s', die in einem der SELECT-Befehle verwendet wurde, kann nicht in %-.32s verwendet werden" - nla "Tabel '%-.192s' uit een van de SELECTS kan niet in %-.32s gebruikt worden" - por "Tabela '%-.192s' de um dos SELECTs não pode ser usada em %-.32s" - spa "Tabla '%-.192s' de uno de los SELECT no puede ser usada en %-.32s" - swe "Tabell '%-.192s' från en SELECT kan inte användas i %-.32s" -ER_NOT_SUPPORTED_AUTH_MODE 08004 - eng "Client does not support authentication protocol requested by server; consider upgrading MySQL client" - ger "Client unterstützt das vom Server erwartete Authentifizierungsprotokoll nicht. Bitte aktualisieren Sie Ihren MySQL-Client" - nla "Client ondersteunt het door de server verwachtte authenticatieprotocol niet. Overweeg een nieuwere MySQL client te gebruiken" - por "Cliente não suporta o protocolo de autenticação exigido pelo servidor; considere a atualização do cliente MySQL" - spa "Cliente no soporta protocolo de autenticación solicitado por el servidor; considere actualizar el cliente MySQL" - swe "Klienten stöder inte autentiseringsprotokollet som begärts av servern; överväg uppgradering av klientprogrammet." -ER_SPATIAL_CANT_HAVE_NULL 42000 - eng "All parts of a SPATIAL index must be NOT NULL" - ger "Alle Teile eines SPATIAL-Index müssen als NOT NULL deklariert sein" - nla "Alle delete van een SPATIAL index dienen als NOT NULL gedeclareerd te worden" - por "Todas as partes de uma SPATIAL index devem ser NOT NULL" - spa "Todas las partes de una SPATIAL index deben ser NOT NULL" - swe "Alla delar av en SPATIAL index måste vara NOT NULL" -ER_COLLATION_CHARSET_MISMATCH 42000 - eng "COLLATION '%s' is not valid for CHARACTER SET '%s'" - ger "COLLATION '%s' ist für CHARACTER SET '%s' ungültig" - nla "COLLATION '%s' is niet geldig voor CHARACTER SET '%s'" - por "COLLATION '%s' não é válida para CHARACTER SET '%s'" - spa "COLLATION '%s' no es válido para CHARACTER SET '%s'" - swe "COLLATION '%s' är inte tillåtet för CHARACTER SET '%s'" -ER_SLAVE_WAS_RUNNING - eng "Slave is already running" - ger "Slave läuft bereits" - nla "Slave is reeds actief" - por "O slave já está rodando" - spa "Slave ya está funcionando" - swe "Slaven har redan startat" -ER_SLAVE_WAS_NOT_RUNNING - eng "Slave already has been stopped" - ger "Slave wurde bereits angehalten" - nla "Slave is reeds gestopt" - por "O slave já está parado" - spa "Slave ya fué parado" - swe "Slaven har redan stoppat" -ER_TOO_BIG_FOR_UNCOMPRESS - eng "Uncompressed data size too large; the maximum size is %d (probably, length of uncompressed data was corrupted)" - ger "Unkomprimierte Daten sind zu groß. Die maximale Größe beträgt %d (wahrscheinlich wurde die Länge der unkomprimierten Daten beschädigt)" - nla "Ongecomprimeerder data is te groot; de maximum lengte is %d (waarschijnlijk, de lengte van de gecomprimeerde data was beschadigd)" - por "Tamanho muito grande dos dados des comprimidos. O máximo tamanho é %d. (provavelmente, o comprimento dos dados descomprimidos está corrupto)" - spa "Tamaño demasiado grande para datos descomprimidos. El máximo tamaño es %d. (probablemente, extensión de datos descomprimidos fué corrompida)" -ER_ZLIB_Z_MEM_ERROR - eng "ZLIB: Not enough memory" - ger "ZLIB: Nicht genug Speicher" - nla "ZLIB: Onvoldoende geheugen" - por "ZLIB: Não suficiente memória disponível" - spa "Z_MEM_ERROR: No suficiente memoria para zlib" -ER_ZLIB_Z_BUF_ERROR - eng "ZLIB: Not enough room in the output buffer (probably, length of uncompressed data was corrupted)" - ger "ZLIB: Im Ausgabepuffer ist nicht genug Platz vorhanden (wahrscheinlich wurde die Länge der unkomprimierten Daten beschädigt)" - nla "ZLIB: Onvoldoende ruimte in uitgaande buffer (waarschijnlijk, de lengte van de ongecomprimeerde data was beschadigd)" - por "ZLIB: Não suficiente espaço no buffer emissor (provavelmente, o comprimento dos dados descomprimidos está corrupto)" - spa "Z_BUF_ERROR: No suficiente espacio en el búfer de salida para zlib (probablemente, extensión de datos descomprimidos fué corrompida)" -ER_ZLIB_Z_DATA_ERROR - eng "ZLIB: Input data corrupted" - ger "ZLIB: Eingabedaten beschädigt" - nla "ZLIB: Invoer data beschadigd" - por "ZLIB: Dados de entrada está corrupto" - spa "ZLIB: Dato de entrada fué corrompido para zlib" -ER_CUT_VALUE_GROUP_CONCAT - eng "Row %u was cut by GROUP_CONCAT()" -ER_WARN_TOO_FEW_RECORDS 01000 - eng "Row %ld doesn't contain data for all columns" - ger "Zeile %ld enthält nicht für alle Felder Daten" - nla "Rij %ld bevat niet de data voor alle kolommen" - por "Conta de registro é menor que a conta de coluna na linha %ld" - spa "Línea %ld no contiene datos para todas las columnas" -ER_WARN_TOO_MANY_RECORDS 01000 - eng "Row %ld was truncated; it contained more data than there were input columns" - ger "Zeile %ld gekürzt, die Zeile enthielt mehr Daten, als es Eingabefelder gibt" - nla "Regel %ld ingekort, bevatte meer data dan invoer kolommen" - por "Conta de registro é maior que a conta de coluna na linha %ld" - spa "Línea %ld fué truncada; La misma contine mas datos que las que existen en las columnas de entrada" -ER_WARN_NULL_TO_NOTNULL 22004 - eng "Column set to default value; NULL supplied to NOT NULL column '%s' at row %ld" - ger "Feld auf Vorgabewert gesetzt, da NULL für NOT-NULL-Feld '%s' in Zeile %ld angegeben" - por "Dado truncado, NULL fornecido para NOT NULL coluna '%s' na linha %ld" - spa "Datos truncado, NULL suministrado para NOT NULL columna '%s' en la línea %ld" -ER_WARN_DATA_OUT_OF_RANGE 22003 - eng "Out of range value for column '%s' at row %ld" -WARN_DATA_TRUNCATED 01000 - eng "Data truncated for column '%s' at row %ld" - ger "Daten abgeschnitten für Feld '%s' in Zeile %ld" - por "Dado truncado para coluna '%s' na linha %ld" - spa "Datos truncados para columna '%s' en la línea %ld" -ER_WARN_USING_OTHER_HANDLER - eng "Using storage engine %s for table '%s'" - ger "Für Tabelle '%s' wird Speicher-Engine %s benutzt" - por "Usando engine de armazenamento %s para tabela '%s'" - spa "Usando motor de almacenamiento %s para tabla '%s'" - swe "Använder handler %s för tabell '%s'" -ER_CANT_AGGREGATE_2COLLATIONS - eng "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'" - ger "Unerlaubte Mischung von Sortierreihenfolgen (%s, %s) und (%s, %s) für Operation '%s'" - por "Combinação ilegal de collations (%s,%s) e (%s,%s) para operação '%s'" - spa "Ilegal mezcla de collations (%s,%s) y (%s,%s) para operación '%s'" -ER_DROP_USER - eng "Cannot drop one or more of the requested users" - ger "Kann einen oder mehrere der angegebenen Benutzer nicht löschen" -ER_REVOKE_GRANTS - eng "Can't revoke all privileges for one or more of the requested users" - ger "Kann nicht alle Berechtigungen widerrufen, die für einen oder mehrere Benutzer gewährt wurden" - por "Não pode revocar todos os privilégios, grant para um ou mais dos usuários pedidos" - spa "No puede revocar todos los privilegios, derecho para uno o mas de los usuarios solicitados" -ER_CANT_AGGREGATE_3COLLATIONS - eng "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'" - ger "Unerlaubte Mischung von Sortierreihenfolgen (%s, %s), (%s, %s), (%s, %s) für Operation '%s'" - por "Ilegal combinação de collations (%s,%s), (%s,%s), (%s,%s) para operação '%s'" - spa "Ilegal mezcla de collations (%s,%s), (%s,%s), (%s,%s) para operación '%s'" -ER_CANT_AGGREGATE_NCOLLATIONS - eng "Illegal mix of collations for operation '%s'" - ger "Unerlaubte Mischung von Sortierreihenfolgen für Operation '%s'" - por "Ilegal combinação de collations para operação '%s'" - spa "Ilegal mezcla de collations para operación '%s'" -ER_VARIABLE_IS_NOT_STRUCT - eng "Variable '%-.64s' is not a variable component (can't be used as XXXX.variable_name)" - ger "Variable '%-.64s' ist keine Variablen-Komponente (kann nicht als XXXX.variablen_name verwendet werden)" - por "Variável '%-.64s' não é uma variável componente (Não pode ser usada como XXXX.variável_nome)" - spa "Variable '%-.64s' no es una variable componente (No puede ser usada como XXXX.variable_name)" -ER_UNKNOWN_COLLATION - eng "Unknown collation: '%-.64s'" - ger "Unbekannte Sortierreihenfolge: '%-.64s'" - por "Collation desconhecida: '%-.64s'" - spa "Collation desconocida: '%-.64s'" -ER_SLAVE_IGNORED_SSL_PARAMS - eng "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support; they can be used later if MySQL slave with SSL is started" - ger "SSL-Parameter in CHANGE MASTER werden ignoriert, weil dieser MySQL-Slave ohne SSL-Unterstützung kompiliert wurde. Sie können aber später verwendet werden, wenn ein MySQL-Slave mit SSL gestartet wird" - por "SSL parâmetros em CHANGE MASTER são ignorados porque este escravo MySQL foi compilado sem o SSL suporte. Os mesmos podem ser usados mais tarde quando o escravo MySQL com SSL seja iniciado." - spa "Parametros SSL en CHANGE MASTER son ignorados porque este slave MySQL fue compilado sin soporte SSL; pueden ser usados despues cuando el slave MySQL con SSL sea inicializado" -ER_SERVER_IS_IN_SECURE_AUTH_MODE - eng "Server is running in --secure-auth mode, but '%s'@'%s' has a password in the old format; please change the password to the new format" - ger "Server läuft im Modus --secure-auth, aber '%s'@'%s' hat ein Passwort im alten Format. Bitte Passwort ins neue Format ändern" - por "Servidor está rodando em --secure-auth modo, porêm '%s'@'%s' tem senha no formato antigo; por favor troque a senha para o novo formato" - rus "óÅÒ×ÅÒ ÚÁÐÕÝÅÎ × ÒÅÖÉÍÅ --secure-auth (ÂÅÚÏÐÁÓÎÏÊ Á×ÔÏÒÉÚÁÃÉÉ), ÎÏ ÄÌÑ ÐÏÌØÚÏ×ÁÔÅÌÑ '%s'@'%s' ÐÁÒÏÌØ ÓÏÈÒÁÎ£Î × ÓÔÁÒÏÍ ÆÏÒÍÁÔÅ; ÎÅÏÂÈÏÄÉÍÏ ÏÂÎÏ×ÉÔØ ÆÏÒÍÁÔ ÐÁÒÏÌÑ" - spa "Servidor está rodando en modo --secure-auth, pero '%s'@'%s' tiene clave en el antiguo formato; por favor cambie la clave para el nuevo formato" -ER_WARN_FIELD_RESOLVED - eng "Field or reference '%-.192s%s%-.192s%s%-.192s' of SELECT #%d was resolved in SELECT #%d" - ger "Feld oder Verweis '%-.192s%s%-.192s%s%-.192s' im SELECT-Befehl Nr. %d wurde im SELECT-Befehl Nr. %d aufgelöst" - por "Campo ou referência '%-.192s%s%-.192s%s%-.192s' de SELECT #%d foi resolvido em SELECT #%d" - rus "ðÏÌÅ ÉÌÉ ÓÓÙÌËÁ '%-.192s%s%-.192s%s%-.192s' ÉÚ SELECTÁ #%d ÂÙÌÁ ÎÁÊÄÅÎÁ × SELECTÅ #%d" - spa "Campo o referencia '%-.192s%s%-.192s%s%-.192s' de SELECT #%d fue resolvido en SELECT #%d" - ukr "óÔÏ×ÂÅÃØ ÁÂÏ ÐÏÓÉÌÁÎÎÑ '%-.192s%s%-.192s%s%-.192s' ¦Ú SELECTÕ #%d ÂÕÌÏ ÚÎÁÊÄÅÎÅ Õ SELECT¦ #%d" -ER_BAD_SLAVE_UNTIL_COND - eng "Incorrect parameter or combination of parameters for START SLAVE UNTIL" - ger "Falscher Parameter oder falsche Kombination von Parametern für START SLAVE UNTIL" - por "Parâmetro ou combinação de parâmetros errado para START SLAVE UNTIL" - spa "Parametro equivocado o combinación de parametros para START SLAVE UNTIL" -ER_MISSING_SKIP_SLAVE - eng "It is recommended to use --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL; otherwise, you will get problems if you get an unexpected slave's mysqld restart" - ger "Es wird empfohlen, mit --skip-slave-start zu starten, wenn mit START SLAVE UNTIL eine Schritt-für-Schritt-Replikation ausgeführt wird. Ansonsten gibt es Probleme, wenn ein Slave-Server unerwartet neu startet" - por "É recomendado para rodar com --skip-slave-start quando fazendo replicação passo-por-passo com START SLAVE UNTIL, de outra forma você não está seguro em caso de inesperada reinicialição do mysqld escravo" - spa "Es recomendado rodar con --skip-slave-start cuando haciendo replicación step-by-step con START SLAVE UNTIL, a menos que usted no esté seguro en caso de inesperada reinicialización del mysqld slave" -ER_UNTIL_COND_IGNORED - eng "SQL thread is not to be started so UNTIL options are ignored" - ger "SQL-Thread soll nicht gestartet werden. Daher werden UNTIL-Optionen ignoriert" - por "Thread SQL não pode ser inicializado tal que opções UNTIL são ignoradas" - spa "SQL thread no es inicializado tal que opciones UNTIL son ignoradas" -ER_WRONG_NAME_FOR_INDEX 42000 - eng "Incorrect index name '%-.100s'" - ger "Falscher Indexname '%-.100s'" - por "Incorreto nome de índice '%-.100s'" - spa "Nombre de índice incorrecto '%-.100s'" - swe "Felaktigt index namn '%-.100s'" -ER_WRONG_NAME_FOR_CATALOG 42000 - eng "Incorrect catalog name '%-.100s'" - ger "Falscher Katalogname '%-.100s'" - por "Incorreto nome de catálogo '%-.100s'" - spa "Nombre de catalog incorrecto '%-.100s'" - swe "Felaktigt katalog namn '%-.100s'" -ER_WARN_QC_RESIZE - eng "Query cache failed to set size %lu; new query cache size is %lu" - ger "Änderung der Query-Cache-Größe auf %lu fehlgeschlagen; neue Query-Cache-Größe ist %lu" - por "Falha em Query cache para configurar tamanho %lu, novo tamanho de query cache é %lu" - rus "ëÅÛ ÚÁÐÒÏÓÏ× ÎÅ ÍÏÖÅÔ ÕÓÔÁÎÏ×ÉÔØ ÒÁÚÍÅÒ %lu, ÎÏ×ÙÊ ÒÁÚÍÅÒ ËÅÛÁ ÚÐÒÏÓÏ× - %lu" - spa "Query cache fallada para configurar tamaño %lu, nuevo tamaño de query cache es %lu" - swe "Storleken av "Query cache" kunde inte sättas till %lu, ny storlek är %lu" - ukr "ëÅÛ ÚÁÐÉÔ¦× ÎÅÓÐÒÏÍÏÖÅÎ ×ÓÔÁÎÏ×ÉÔÉ ÒÏÚÍ¦Ò %lu, ÎÏ×ÉÊ ÒÏÚÍ¦Ò ËÅÛÁ ÚÁÐÉÔ¦× - %lu" -ER_BAD_FT_COLUMN - eng "Column '%-.192s' cannot be part of FULLTEXT index" - ger "Feld '%-.192s' kann nicht Teil eines FULLTEXT-Index sein" - por "Coluna '%-.192s' não pode ser parte de índice FULLTEXT" - spa "Columna '%-.192s' no puede ser parte de FULLTEXT index" - swe "Kolumn '%-.192s' kan inte vara del av ett FULLTEXT index" -ER_UNKNOWN_KEY_CACHE - eng "Unknown key cache '%-.100s'" - ger "Unbekannter Schlüssel-Cache '%-.100s'" - por "Key cache desconhecida '%-.100s'" - spa "Desconocida key cache '%-.100s'" - swe "Okänd nyckel cache '%-.100s'" -ER_WARN_HOSTNAME_WONT_WORK - eng "MySQL is started in --skip-name-resolve mode; you must restart it without this switch for this grant to work" - ger "MySQL wurde mit --skip-name-resolve gestartet. Diese Option darf nicht verwendet werden, damit diese Rechtevergabe möglich ist" - por "MySQL foi inicializado em modo --skip-name-resolve. Você necesita reincializá-lo sem esta opção para este grant funcionar" - spa "MySQL esta inicializado en modo --skip-name-resolve. Usted necesita reinicializarlo sin esta opción para este derecho funcionar" -ER_UNKNOWN_STORAGE_ENGINE 42000 - eng "Unknown table engine '%s'" - ger "Unbekannte Speicher-Engine '%s'" - por "Motor de tabela desconhecido '%s'" - spa "Desconocido motor de tabla '%s'" -# When using this error code, use ER(ER_WARN_DEPRECATED_SYNTAX_WITH_VER) -# for the message string. See, for example, code in mysql_priv.h. -ER_WARN_DEPRECATED_SYNTAX - eng "'%s' is deprecated; use '%s' instead" - ger "'%s' ist veraltet. Bitte benutzen Sie '%s'" - por "'%s' é desatualizado. Use '%s' em seu lugar" - spa "'%s' está desaprobado, use '%s' en su lugar" -ER_NON_UPDATABLE_TABLE - eng "The target table %-.100s of the %s is not updatable" - ger "Die Zieltabelle %-.100s von %s ist nicht aktualisierbar" - por "A tabela destino %-.100s do %s não é atualizável" - rus "ôÁÂÌÉÃÁ %-.100s × %s ÎÅ ÍÏÖÅÔ ÉÚÍÅÎÑÔÓÑ" - spa "La tabla destino %-.100s del %s no es actualizable" - swe "Tabell %-.100s använd med '%s' är inte uppdateringsbar" - ukr "ôÁÂÌÉÃÑ %-.100s Õ %s ÎÅ ÍÏÖÅ ÏÎÏ×ÌÀ×ÁÔÉÓØ" -ER_FEATURE_DISABLED - eng "The '%s' feature is disabled; you need MySQL built with '%s' to have it working" - ger "Das Feature '%s' ist ausgeschaltet, Sie müssen MySQL mit '%s' übersetzen, damit es verfügbar ist" - por "O recurso '%s' foi desativado; você necessita MySQL construído com '%s' para ter isto funcionando" - spa "El recurso '%s' fue deshabilitado; usted necesita construir MySQL con '%s' para tener eso funcionando" - swe "'%s' är inte aktiverad; För att aktivera detta måste du bygga om MySQL med '%s' definerad" -ER_OPTION_PREVENTS_STATEMENT - eng "The MySQL server is running with the %s option so it cannot execute this statement" - ger "Der MySQL-Server läuft mit der Option %s und kann diese Anweisung deswegen nicht ausführen" - por "O servidor MySQL está rodando com a opção %s razão pela qual não pode executar esse commando" - spa "El servidor MySQL está rodando con la opción %s tal que no puede ejecutar este comando" - swe "MySQL är startad med %s. Pga av detta kan du inte använda detta kommando" -ER_DUPLICATED_VALUE_IN_TYPE - eng "Column '%-.100s' has duplicated value '%-.64s' in %s" - ger "Feld '%-.100s' hat doppelten Wert '%-.64s' in %s" - por "Coluna '%-.100s' tem valor duplicado '%-.64s' em %s" - spa "Columna '%-.100s' tiene valor doblado '%-.64s' en %s" -ER_TRUNCATED_WRONG_VALUE 22007 - eng "Truncated incorrect %-.32s value: '%-.128s'" - ger "Falscher %-.32s-Wert gekürzt: '%-.128s'" - por "Truncado errado %-.32s valor: '%-.128s'" - spa "Equivocado truncado %-.32s valor: '%-.128s'" -ER_TOO_MUCH_AUTO_TIMESTAMP_COLS - eng "Incorrect table definition; there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause" - ger "Fehlerhafte Tabellendefinition. Es kann nur eine einzige TIMESTAMP-Spalte mit CURRENT_TIMESTAMP als DEFAULT oder in einer ON-UPDATE-Klausel geben" - por "Incorreta definição de tabela; Pode ter somente uma coluna TIMESTAMP com CURRENT_TIMESTAMP em DEFAULT ou ON UPDATE cláusula" - spa "Incorrecta definición de tabla; Solamente debe haber una columna TIMESTAMP con CURRENT_TIMESTAMP en DEFAULT o ON UPDATE cláusula" -ER_INVALID_ON_UPDATE - eng "Invalid ON UPDATE clause for '%-.192s' column" - ger "Ungültige ON-UPDATE-Klausel für Spalte '%-.192s'" - por "Inválida cláusula ON UPDATE para campo '%-.192s'" - spa "Inválido ON UPDATE cláusula para campo '%-.192s'" -ER_UNSUPPORTED_PS - eng "This command is not supported in the prepared statement protocol yet" - ger "Dieser Befehl wird im Protokoll für vorbereitete Anweisungen noch nicht unterstützt" -ER_GET_ERRMSG - dan "Modtog fejl %d '%-.100s' fra %s" - eng "Got error %d '%-.100s' from %s" - ger "Fehler %d '%-.100s' von %s" - nor "Mottok feil %d '%-.100s' fa %s" - norwegian-ny "Mottok feil %d '%-.100s' fra %s" -ER_GET_TEMPORARY_ERRMSG - dan "Modtog temporary fejl %d '%-.100s' fra %s" - eng "Got temporary error %d '%-.100s' from %s" - ger "Temporärer Fehler %d '%-.100s' von %s" - nor "Mottok temporary feil %d '%-.100s' fra %s" - norwegian-ny "Mottok temporary feil %d '%-.100s' fra %s" -ER_UNKNOWN_TIME_ZONE - eng "Unknown or incorrect time zone: '%-.64s'" - ger "Unbekannte oder falsche Zeitzone: '%-.64s'" -ER_WARN_INVALID_TIMESTAMP - eng "Invalid TIMESTAMP value in column '%s' at row %ld" - ger "Ungültiger TIMESTAMP-Wert in Feld '%s', Zeile %ld" -ER_INVALID_CHARACTER_STRING - eng "Invalid %s character string: '%.64s'" - ger "Ungültiger %s-Zeichen-String: '%.64s'" -ER_WARN_ALLOWED_PACKET_OVERFLOWED - eng "Result of %s() was larger than max_allowed_packet (%ld) - truncated" - ger "Ergebnis von %s() war größer als max_allowed_packet (%ld) Bytes und wurde deshalb gekürzt" -ER_CONFLICTING_DECLARATIONS - eng "Conflicting declarations: '%s%s' and '%s%s'" - ger "Widersprüchliche Deklarationen: '%s%s' und '%s%s'" -ER_SP_NO_RECURSIVE_CREATE 2F003 - eng "Can't create a %s from within another stored routine" - ger "Kann kein %s innerhalb einer anderen gespeicherten Routine erzeugen" -ER_SP_ALREADY_EXISTS 42000 - eng "%s %s already exists" - ger "%s %s existiert bereits" -ER_SP_DOES_NOT_EXIST 42000 - eng "%s %s does not exist" - ger "%s %s existiert nicht" -ER_SP_DROP_FAILED - eng "Failed to DROP %s %s" - ger "DROP %s %s ist fehlgeschlagen" -ER_SP_STORE_FAILED - eng "Failed to CREATE %s %s" - ger "CREATE %s %s ist fehlgeschlagen" -ER_SP_LILABEL_MISMATCH 42000 - eng "%s with no matching label: %s" - ger "%s ohne passende Marke: %s" -ER_SP_LABEL_REDEFINE 42000 - eng "Redefining label %s" - ger "Neudefinition der Marke %s" -ER_SP_LABEL_MISMATCH 42000 - eng "End-label %s without match" - ger "Ende-Marke %s ohne zugehörigen Anfang" -ER_SP_UNINIT_VAR 01000 - eng "Referring to uninitialized variable %s" - ger "Zugriff auf nichtinitialisierte Variable %s" -ER_SP_BADSELECT 0A000 - eng "PROCEDURE %s can't return a result set in the given context" - ger "PROCEDURE %s kann im gegebenen Kontext keine Ergebnismenge zurückgeben" -ER_SP_BADRETURN 42000 - eng "RETURN is only allowed in a FUNCTION" - ger "RETURN ist nur innerhalb einer FUNCTION erlaubt" -ER_SP_BADSTATEMENT 0A000 - eng "%s is not allowed in stored procedures" - ger "%s ist in gespeicherten Prozeduren nicht erlaubt" -ER_UPDATE_LOG_DEPRECATED_IGNORED 42000 - eng "The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been ignored. This option will be removed in MySQL 5.6." - ger "Das Update-Log ist veraltet und wurde durch das Binär-Log ersetzt. SET SQL_LOG_UPDATE wird ignoriert. Diese Option wird in MySQL 5.6 entfernt." -ER_UPDATE_LOG_DEPRECATED_TRANSLATED 42000 - eng "The update log is deprecated and replaced by the binary log; SET SQL_LOG_UPDATE has been translated to SET SQL_LOG_BIN. This option will be removed in MySQL 5.6." - ger "Das Update-Log ist veraltet und wurde durch das Binär-Log ersetzt. SET SQL_LOG_UPDATE wurde in SET SQL_LOG_BIN übersetzt. Diese Option wird in MySQL 5.6 entfernt." -ER_QUERY_INTERRUPTED 70100 - eng "Query execution was interrupted" - ger "Ausführung der Abfrage wurde unterbrochen" -ER_SP_WRONG_NO_OF_ARGS 42000 - eng "Incorrect number of arguments for %s %s; expected %u, got %u" - ger "Falsche Anzahl von Argumenten für %s %s; erwarte %u, erhalte %u" -ER_SP_COND_MISMATCH 42000 - eng "Undefined CONDITION: %s" - ger "Undefinierte CONDITION: %s" -ER_SP_NORETURN 42000 - eng "No RETURN found in FUNCTION %s" - ger "Kein RETURN in FUNCTION %s gefunden" -ER_SP_NORETURNEND 2F005 - eng "FUNCTION %s ended without RETURN" - ger "FUNCTION %s endete ohne RETURN" -ER_SP_BAD_CURSOR_QUERY 42000 - eng "Cursor statement must be a SELECT" - ger "Cursor-Anweisung muss ein SELECT sein" -ER_SP_BAD_CURSOR_SELECT 42000 - eng "Cursor SELECT must not have INTO" - ger "Cursor-SELECT darf kein INTO haben" -ER_SP_CURSOR_MISMATCH 42000 - eng "Undefined CURSOR: %s" - ger "Undefinierter CURSOR: %s" -ER_SP_CURSOR_ALREADY_OPEN 24000 - eng "Cursor is already open" - ger "Cursor ist schon geöffnet" -ER_SP_CURSOR_NOT_OPEN 24000 - eng "Cursor is not open" - ger "Cursor ist nicht geöffnet" -ER_SP_UNDECLARED_VAR 42000 - eng "Undeclared variable: %s" - ger "Nicht deklarierte Variable: %s" -ER_SP_WRONG_NO_OF_FETCH_ARGS - eng "Incorrect number of FETCH variables" - ger "Falsche Anzahl von FETCH-Variablen" -ER_SP_FETCH_NO_DATA 02000 - eng "No data - zero rows fetched, selected, or processed" - ger "Keine Daten - null Zeilen geholt (fetch), ausgewählt oder verarbeitet" -ER_SP_DUP_PARAM 42000 - eng "Duplicate parameter: %s" - ger "Doppelter Parameter: %s" -ER_SP_DUP_VAR 42000 - eng "Duplicate variable: %s" - ger "Doppelte Variable: %s" -ER_SP_DUP_COND 42000 - eng "Duplicate condition: %s" - ger "Doppelte Bedingung: %s" -ER_SP_DUP_CURS 42000 - eng "Duplicate cursor: %s" - ger "Doppelter Cursor: %s" -ER_SP_CANT_ALTER - eng "Failed to ALTER %s %s" - ger "ALTER %s %s fehlgeschlagen" -ER_SP_SUBSELECT_NYI 0A000 - eng "Subquery value not supported" - ger "Subquery-Wert wird nicht unterstützt" -ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG 0A000 - eng "%s is not allowed in stored function or trigger" - ger "%s ist in gespeicherten Funktionen und in Triggern nicht erlaubt" -ER_SP_VARCOND_AFTER_CURSHNDLR 42000 - eng "Variable or condition declaration after cursor or handler declaration" - ger "Deklaration einer Variablen oder einer Bedingung nach der Deklaration eines Cursors oder eines Handlers" -ER_SP_CURSOR_AFTER_HANDLER 42000 - eng "Cursor declaration after handler declaration" - ger "Deklaration eines Cursors nach der Deklaration eines Handlers" -ER_SP_CASE_NOT_FOUND 20000 - eng "Case not found for CASE statement" - ger "Fall für CASE-Anweisung nicht gefunden" -ER_FPARSER_TOO_BIG_FILE - eng "Configuration file '%-.192s' is too big" - ger "Konfigurationsdatei '%-.192s' ist zu groß" - rus "óÌÉÛËÏÍ ÂÏÌØÛÏÊ ËÏÎÆÉÇÕÒÁÃÉÏÎÎÙÊ ÆÁÊÌ '%-.192s'" - ukr "úÁÎÁÄÔÏ ×ÅÌÉËÉÊ ËÏÎƦÇÕÒÁæÊÎÉÊ ÆÁÊÌ '%-.192s'" -ER_FPARSER_BAD_HEADER - eng "Malformed file type header in file '%-.192s'" - ger "Nicht wohlgeformter Dateityp-Header in Datei '%-.192s'" - rus "îÅ×ÅÒÎÙÊ ÚÁÇÏÌÏ×ÏË ÔÉÐÁ ÆÁÊÌÁ '%-.192s'" - ukr "îÅצÒÎÉÊ ÚÁÇÏÌÏ×ÏË ÔÉÐÕ Õ ÆÁÊ̦ '%-.192s'" -ER_FPARSER_EOF_IN_COMMENT - eng "Unexpected end of file while parsing comment '%-.200s'" - ger "Unerwartetes Dateiende beim Parsen des Kommentars '%-.200s'" - rus "îÅÏÖÉÄÁÎÎÙÊ ËÏÎÅà ÆÁÊÌÁ × ËÏÍÅÎÔÁÒÉÉ '%-.200s'" - ukr "îÅÓÐÏĦ×ÁÎÎÉÊ Ë¦ÎÅÃØ ÆÁÊÌÕ Õ ËÏÍÅÎÔÁÒ¦ '%-.200s'" -ER_FPARSER_ERROR_IN_PARAMETER - eng "Error while parsing parameter '%-.192s' (line: '%-.192s')" - ger "Fehler beim Parsen des Parameters '%-.192s' (Zeile: '%-.192s')" - rus "ïÛÉÂËÁ ÐÒÉ ÒÁÓÐÏÚÎÁ×ÁÎÉÉ ÐÁÒÁÍÅÔÒÁ '%-.192s' (ÓÔÒÏËÁ: '%-.192s')" - ukr "ðÏÍÉÌËÁ × ÒÏÓЦÚÎÁ×ÁÎΦ ÐÁÒÁÍÅÔÒÕ '%-.192s' (ÒÑÄÏË: '%-.192s')" -ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER - eng "Unexpected end of file while skipping unknown parameter '%-.192s'" - ger "Unerwartetes Dateiende beim Überspringen des unbekannten Parameters '%-.192s'" - rus "îÅÏÖÉÄÁÎÎÙÊ ËÏÎÅà ÆÁÊÌÁ ÐÒÉ ÐÒÏÐÕÓËÅ ÎÅÉÚ×ÅÓÔÎÏÇÏ ÐÁÒÁÍÅÔÒÁ '%-.192s'" - ukr "îÅÓÐÏĦ×ÁÎÎÉÊ Ë¦ÎÅÃØ ÆÁÊÌÕ Õ ÓÐÒϦ ÐÒÏÍÉÎÕÔÉ ÎÅצÄÏÍÉÊ ÐÁÒÁÍÅÔÒ '%-.192s'" -ER_VIEW_NO_EXPLAIN - eng "EXPLAIN/SHOW can not be issued; lacking privileges for underlying table" - ger "EXPLAIN/SHOW kann nicht verlangt werden. Rechte für zugrunde liegende Tabelle fehlen" - rus "EXPLAIN/SHOW ÎÅ ÍÏÖÅÔ ÂÙÔØ ×ÙÐÏÌÎÅÎÎÏ; ÎÅÄÏÓÔÁÔÏÞÎÏ ÐÒÁ× ÎÁ ÔÁËÂÌÉÃÙ ÚÁÐÒÏÓÁ" - ukr "EXPLAIN/SHOW ÎÅ ÍÏÖÅ ÂÕÔÉ ×¦ËÏÎÁÎÏ; ÎÅÍÁ¤ ÐÒÁ× ÎÁ ÔÉÂÌÉæ ÚÁÐÉÔÕ" -ER_FRM_UNKNOWN_TYPE - eng "File '%-.192s' has unknown type '%-.64s' in its header" - ger "Datei '%-.192s' hat unbekannten Typ '%-.64s' im Header" - rus "æÁÊÌ '%-.192s' ÓÏÄÅÒÖÉÔ ÎÅÉÚ×ÅÓÔÎÙÊ ÔÉÐ '%-.64s' × ÚÁÇÏÌÏ×ËÅ" - ukr "æÁÊÌ '%-.192s' ÍÁ¤ ÎÅצÄÏÍÉÊ ÔÉÐ '%-.64s' Õ ÚÁÇÏÌÏ×ËÕ" -ER_WRONG_OBJECT - eng "'%-.192s.%-.192s' is not %s" - ger "'%-.192s.%-.192s' ist nicht %s" - rus "'%-.192s.%-.192s' - ÎÅ %s" - ukr "'%-.192s.%-.192s' ÎÅ ¤ %s" -ER_NONUPDATEABLE_COLUMN - eng "Column '%-.192s' is not updatable" - ger "Feld '%-.192s' ist nicht aktualisierbar" - rus "óÔÏÌÂÅà '%-.192s' ÎÅ ÏÂÎÏ×ÌÑÅÍÙÊ" - ukr "óÔÏ×ÂÅÃØ '%-.192s' ÎÅ ÍÏÖÅ ÂÕÔÉ ÚÍÉÎÅÎÉÊ" -ER_VIEW_SELECT_DERIVED - eng "View's SELECT contains a subquery in the FROM clause" - ger "SELECT der View enthält eine Subquery in der FROM-Klausel" - rus "View SELECT ÓÏÄÅÒÖÉÔ ÐÏÄÚÁÐÒÏÓ × ËÏÎÓÔÒÕËÃÉÉ FROM" - ukr "View SELECT ÍÁ¤ ЦÄÚÁÐÉÔ Õ ËÏÎÓÔÒÕËæ§ FROM" -ER_VIEW_SELECT_CLAUSE - eng "View's SELECT contains a '%s' clause" - ger "SELECT der View enthält eine '%s'-Klausel" - rus "View SELECT ÓÏÄÅÒÖÉÔ ËÏÎÓÔÒÕËÃÉÀ '%s'" - ukr "View SELECT ÍÁ¤ ËÏÎÓÔÒÕËæÀ '%s'" -ER_VIEW_SELECT_VARIABLE - eng "View's SELECT contains a variable or parameter" - ger "SELECT der View enthält eine Variable oder einen Parameter" - rus "View SELECT ÓÏÄÅÒÖÉÔ ÐÅÒÅÍÅÎÎÕÀ ÉÌÉ ÐÁÒÁÍÅÔÒ" - ukr "View SELECT ÍÁ¤ ÚÍÉÎÎÕ ÁÂÏ ÐÁÒÁÍÅÔÅÒ" -ER_VIEW_SELECT_TMPTABLE - eng "View's SELECT refers to a temporary table '%-.192s'" - ger "SELECT der View verweist auf eine temporäre Tabelle '%-.192s'" - rus "View SELECT ÓÏÄÅÒÖÉÔ ÓÓÙÌËÕ ÎÁ ×ÒÅÍÅÎÎÕÀ ÔÁÂÌÉÃÕ '%-.192s'" - ukr "View SELECT ×ÉËÏÒÉÓÔÏ×Õ¤ ÔÉÍÞÁÓÏ×Õ ÔÁÂÌÉÃÀ '%-.192s'" -ER_VIEW_WRONG_LIST - eng "View's SELECT and view's field list have different column counts" - ger "SELECT- und Feldliste der Views haben unterschiedliche Anzahlen von Spalten" - rus "View SELECT É ÓÐÉÓÏË ÐÏÌÅÊ view ÉÍÅÀÔ ÒÁÚÎÏÅ ËÏÌÉÞÅÓÔ×Ï ÓÔÏÌÂÃÏ×" - ukr "View SELECT ¦ ÐÅÒÅÌ¦Ë ÓÔÏ×ÂÃ¦× view ÍÁÀÔØ Ò¦ÚÎÕ Ë¦ÌØ˦ÓÔØ ÓËÏ×Âæ×" -ER_WARN_VIEW_MERGE - eng "View merge algorithm can't be used here for now (assumed undefined algorithm)" - ger "View-Merge-Algorithmus kann hier momentan nicht verwendet werden (undefinierter Algorithmus wird angenommen)" - rus "áÌÇÏÒÉÔÍ ÓÌÉÑÎÉÑ view ÎÅ ÍÏÖÅÔ ÂÙÔØ ÉÓÐÏÌØÚÏ×ÁÎ ÓÅÊÞÁÓ (ÁÌÇÏÒÉÔÍ ÂÕÄÅÔ ÎÅÏÐÅÒÅÄÅÌÅÎÎÙÍ)" - ukr "áÌÇÏÒÉÔÍ ÚÌÉ×ÁÎÎÑ view ÎÅ ÍÏÖÅ ÂÕÔÉ ×ÉËÏÒÉÓÔÁÎÉÊ ÚÁÒÁÚ (ÁÌÇÏÒÉÔÍ ÂÕÄÅ ÎÅ×ÉÚÎÁÞÅÎÉÊ)" -ER_WARN_VIEW_WITHOUT_KEY - eng "View being updated does not have complete key of underlying table in it" - ger "Die aktualisierte View enthält nicht den vollständigen Schlüssel der zugrunde liegenden Tabelle" - rus "ïÂÎÏ×ÌÑÅÍÙÊ view ÎÅ ÓÏÄÅÒÖÉÔ ËÌÀÞÁ ÉÓÐÏÌØÚÏ×ÁÎÎÙÈ(ÏÊ) × ÎÅÍ ÔÁÂÌÉÃ(Ù)" - ukr "View, ÝÏ ÏÎÏ×ÌÀÅÔØÓÑ, ΊͦÓÔÉÔØ ÐÏ×ÎÏÇÏ ËÌÀÞÁ ÔÁÂÌÉæ(Ø), ÝÏ ×ÉËÏÒ¦ÓÔÁÎÁ × ÎØÀÏÍÕ" -ER_VIEW_INVALID - eng "View '%-.192s.%-.192s' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them" -ER_SP_NO_DROP_SP - eng "Can't drop or alter a %s from within another stored routine" - ger "Kann eine %s nicht von innerhalb einer anderen gespeicherten Routine löschen oder ändern" -ER_SP_GOTO_IN_HNDLR - eng "GOTO is not allowed in a stored procedure handler" - ger "GOTO ist im Handler einer gespeicherten Prozedur nicht erlaubt" -ER_TRG_ALREADY_EXISTS - eng "Trigger already exists" - ger "Trigger existiert bereits" -ER_TRG_DOES_NOT_EXIST - eng "Trigger does not exist" - ger "Trigger existiert nicht" -ER_TRG_ON_VIEW_OR_TEMP_TABLE - eng "Trigger's '%-.192s' is view or temporary table" - ger "'%-.192s' des Triggers ist View oder temporäre Tabelle" -ER_TRG_CANT_CHANGE_ROW - eng "Updating of %s row is not allowed in %strigger" - ger "Aktualisieren einer %s-Zeile ist in einem %s-Trigger nicht erlaubt" -ER_TRG_NO_SUCH_ROW_IN_TRG - eng "There is no %s row in %s trigger" - ger "Es gibt keine %s-Zeile im %s-Trigger" -ER_NO_DEFAULT_FOR_FIELD - eng "Field '%-.192s' doesn't have a default value" - ger "Feld '%-.192s' hat keinen Vorgabewert" -ER_DIVISION_BY_ZERO 22012 - eng "Division by 0" - ger "Division durch 0" -ER_TRUNCATED_WRONG_VALUE_FOR_FIELD - eng "Incorrect %-.32s value: '%-.128s' for column '%.192s' at row %ld" - ger "Falscher %-.32s-Wert: '%-.128s' für Feld '%.192s' in Zeile %ld" -ER_ILLEGAL_VALUE_FOR_TYPE 22007 - eng "Illegal %s '%-.192s' value found during parsing" - ger "Nicht zulässiger %s-Wert '%-.192s' beim Parsen gefunden" -ER_VIEW_NONUPD_CHECK - eng "CHECK OPTION on non-updatable view '%-.192s.%-.192s'" - ger "CHECK OPTION auf nicht-aktualisierbarem View '%-.192s.%-.192s'" - rus "CHECK OPTION ÄÌÑ ÎÅÏÂÎÏ×ÌÑÅÍÏÇÏ VIEW '%-.192s.%-.192s'" - ukr "CHECK OPTION ÄÌÑ VIEW '%-.192s.%-.192s' ÝÏ ÎÅ ÍÏÖÅ ÂÕÔÉ ÏÎÏ×ÌÅÎÎÉÍ" -ER_VIEW_CHECK_FAILED - eng "CHECK OPTION failed '%-.192s.%-.192s'" - ger "CHECK OPTION fehlgeschlagen: '%-.192s.%-.192s'" - rus "ÐÒÏ×ÅÒËÁ CHECK OPTION ÄÌÑ VIEW '%-.192s.%-.192s' ÐÒÏ×ÁÌÉÌÁÓØ" - ukr "ðÅÒÅצÒËÁ CHECK OPTION ÄÌÑ VIEW '%-.192s.%-.192s' ÎÅ ÐÒÏÊÛÌÁ" -ER_PROCACCESS_DENIED_ERROR 42000 - eng "%-.16s command denied to user '%-.48s'@'%-.64s' for routine '%-.192s'" - ger "Befehl %-.16s nicht zulässig für Benutzer '%-.48s'@'%-.64s' in Routine '%-.192s'" -ER_RELAY_LOG_FAIL - eng "Failed purging old relay logs: %s" - ger "Bereinigen alter Relais-Logs fehlgeschlagen: %s" -ER_PASSWD_LENGTH - eng "Password hash should be a %d-digit hexadecimal number" - ger "Passwort-Hash sollte eine Hexdaezimalzahl mit %d Stellen sein" -ER_UNKNOWN_TARGET_BINLOG - eng "Target log not found in binlog index" - ger "Ziel-Log im Binlog-Index nicht gefunden" -ER_IO_ERR_LOG_INDEX_READ - eng "I/O error reading log index file" - ger "Fehler beim Lesen der Log-Index-Datei" -ER_BINLOG_PURGE_PROHIBITED - eng "Server configuration does not permit binlog purge" - ger "Server-Konfiguration erlaubt keine Binlog-Bereinigung" -ER_FSEEK_FAIL - eng "Failed on fseek()" - ger "fseek() fehlgeschlagen" -ER_BINLOG_PURGE_FATAL_ERR - eng "Fatal error during log purge" - ger "Schwerwiegender Fehler bei der Log-Bereinigung" -ER_LOG_IN_USE - eng "A purgeable log is in use, will not purge" - ger "Ein zu bereinigendes Log wird gerade benutzt, daher keine Bereinigung" -ER_LOG_PURGE_UNKNOWN_ERR - eng "Unknown error during log purge" - ger "Unbekannter Fehler bei Log-Bereinigung" -ER_RELAY_LOG_INIT - eng "Failed initializing relay log position: %s" - ger "Initialisierung der Relais-Log-Position fehlgeschlagen: %s" -ER_NO_BINARY_LOGGING - eng "You are not using binary logging" - ger "Sie verwenden keine Binärlogs" -ER_RESERVED_SYNTAX - eng "The '%-.64s' syntax is reserved for purposes internal to the MySQL server" - ger "Die Schreibweise '%-.64s' ist für interne Zwecke des MySQL-Servers reserviert" -ER_WSAS_FAILED - eng "WSAStartup Failed" - ger "WSAStartup fehlgeschlagen" -ER_DIFF_GROUPS_PROC - eng "Can't handle procedures with different groups yet" - ger "Kann Prozeduren mit unterschiedlichen Gruppen noch nicht verarbeiten" -ER_NO_GROUP_FOR_PROC - eng "Select must have a group with this procedure" - ger "SELECT muss bei dieser Prozedur ein GROUP BY haben" -ER_ORDER_WITH_PROC - eng "Can't use ORDER clause with this procedure" - ger "Kann bei dieser Prozedur keine ORDER-BY-Klausel verwenden" -ER_LOGGING_PROHIBIT_CHANGING_OF - eng "Binary logging and replication forbid changing the global server %s" - ger "Binärlogs und Replikation verhindern Wechsel des globalen Servers %s" -ER_NO_FILE_MAPPING - eng "Can't map file: %-.200s, errno: %d" - ger "Kann Datei nicht abbilden: %-.200s, Fehler: %d" -ER_WRONG_MAGIC - eng "Wrong magic in %-.64s" - ger "Falsche magische Zahlen in %-.64s" -ER_PS_MANY_PARAM - eng "Prepared statement contains too many placeholders" - ger "Vorbereitete Anweisung enthält zu viele Platzhalter" -ER_KEY_PART_0 - eng "Key part '%-.192s' length cannot be 0" - ger "Länge des Schlüsselteils '%-.192s' kann nicht 0 sein" -ER_VIEW_CHECKSUM - eng "View text checksum failed" - ger "View-Text-Prüfsumme fehlgeschlagen" - rus "ðÒÏ×ÅÒËÁ ËÏÎÔÒÏÌØÎÏÊ ÓÕÍÍÙ ÔÅËÓÔÁ VIEW ÐÒÏ×ÁÌÉÌÁÓØ" - ukr "ðÅÒÅצÒËÁ ËÏÎÔÒÏÌØÎϧ ÓÕÍÉ ÔÅËÓÔÕ VIEW ÎÅ ÐÒÏÊÛÌÁ" -ER_VIEW_MULTIUPDATE - eng "Can not modify more than one base table through a join view '%-.192s.%-.192s'" - ger "Kann nicht mehr als eine Basistabelle über Join-View '%-.192s.%-.192s' ändern" - rus "îÅÌØÚÑ ÉÚÍÅÎÉÔØ ÂÏÌØÛÅ ÞÅÍ ÏÄÎÕ ÂÁÚÏ×ÕÀ ÔÁÂÌÉÃÕ ÉÓÐÏÌØÚÕÑ ÍÎÏÇÏÔÁÂÌÉÞÎÙÊ VIEW '%-.192s.%-.192s'" - ukr "îÅÍÏÖÌÉ×Ï ÏÎÏ×ÉÔÉ Â¦ÌØÛ ÎÉÖ ÏÄÎÕ ÂÁÚÏ×Õ ÔÁÂÌÉÃÀ ×ÙËÏÒÉÓÔÏ×ÕÀÞÉ VIEW '%-.192s.%-.192s', ÝÏ Í¦ÓÔ¦ÔØ ÄÅ˦ÌØËÁ ÔÁÂÌÉÃØ" -ER_VIEW_NO_INSERT_FIELD_LIST - eng "Can not insert into join view '%-.192s.%-.192s' without fields list" - ger "Kann nicht ohne Feldliste in Join-View '%-.192s.%-.192s' einfügen" - rus "îÅÌØÚÑ ×ÓÔÁ×ÌÑÔØ ÚÁÐÉÓÉ × ÍÎÏÇÏÔÁÂÌÉÞÎÙÊ VIEW '%-.192s.%-.192s' ÂÅÚ ÓÐÉÓËÁ ÐÏÌÅÊ" - ukr "îÅÍÏÖÌÉ×Ï ÕÓÔÁ×ÉÔÉ ÒÑÄËÉ Õ VIEW '%-.192s.%-.192s', ÝÏ Í¦ÓÔÉÔØ ÄÅ˦ÌØËÁ ÔÁÂÌÉÃØ, ÂÅÚ ÓÐÉÓËÕ ÓÔÏ×Âæ×" -ER_VIEW_DELETE_MERGE_VIEW - eng "Can not delete from join view '%-.192s.%-.192s'" - ger "Kann nicht aus Join-View '%-.192s.%-.192s' löschen" - rus "îÅÌØÚÑ ÕÄÁÌÑÔØ ÉÚ ÍÎÏÇÏÔÁÂÌÉÞÎÏÇÏ VIEW '%-.192s.%-.192s'" - ukr "îÅÍÏÖÌÉ×Ï ×ÉÄÁÌÉÔÉ ÒÑÄËÉ Õ VIEW '%-.192s.%-.192s', ÝÏ Í¦ÓÔÉÔØ ÄÅ˦ÌØËÁ ÔÁÂÌÉÃØ" -ER_CANNOT_USER - eng "Operation %s failed for %.256s" - ger "Operation %s schlug fehl für %.256s" - norwegian-ny "Operation %s failed for '%.256s'" -ER_XAER_NOTA XAE04 - eng "XAER_NOTA: Unknown XID" - ger "XAER_NOTA: Unbekannte XID" -ER_XAER_INVAL XAE05 - eng "XAER_INVAL: Invalid arguments (or unsupported command)" - ger "XAER_INVAL: Ungültige Argumente (oder nicht unterstützter Befehl)" -ER_XAER_RMFAIL XAE07 - eng "XAER_RMFAIL: The command cannot be executed when global transaction is in the %.64s state" - ger "XAER_RMFAIL: DEr Befehl kann nicht ausgeführt werden, wenn die globale Transaktion im Zustand %.64s ist" - rus "XAER_RMFAIL: ÜÔÕ ËÏÍÁÎÄÕ ÎÅÌØÚÑ ×ÙÐÏÌÎÑÔØ ËÏÇÄÁ ÇÌÏÂÁÌØÎÁÑ ÔÒÁÎÚÁËÃÉÑ ÎÁÈÏÄÉÔÓÑ × ÓÏÓÔÏÑÎÉÉ '%.64s'" -ER_XAER_OUTSIDE XAE09 - eng "XAER_OUTSIDE: Some work is done outside global transaction" - ger "XAER_OUTSIDE: Einige Arbeiten werden außerhalb der globalen Transaktion verrichtet" -ER_XAER_RMERR XAE03 - eng "XAER_RMERR: Fatal error occurred in the transaction branch - check your data for consistency" - ger "XAER_RMERR: Schwerwiegender Fehler im Transaktionszweig - prüfen Sie Ihre Daten auf Konsistenz" -ER_XA_RBROLLBACK XA100 - eng "XA_RBROLLBACK: Transaction branch was rolled back" - ger "XA_RBROLLBACK: Transaktionszweig wurde zurückgerollt" -ER_NONEXISTING_PROC_GRANT 42000 - eng "There is no such grant defined for user '%-.48s' on host '%-.64s' on routine '%-.192s'" - ger "Es gibt diese Berechtigung für Benutzer '%-.48s' auf Host '%-.64s' für Routine '%-.192s' nicht" -ER_PROC_AUTO_GRANT_FAIL - eng "Failed to grant EXECUTE and ALTER ROUTINE privileges" - ger "Gewährung von EXECUTE- und ALTER-ROUTINE-Rechten fehlgeschlagen" -ER_PROC_AUTO_REVOKE_FAIL - eng "Failed to revoke all privileges to dropped routine" - ger "Rücknahme aller Rechte für die gelöschte Routine fehlgeschlagen" -ER_DATA_TOO_LONG 22001 - eng "Data too long for column '%s' at row %ld" - ger "Daten zu lang für Feld '%s' in Zeile %ld" -ER_SP_BAD_SQLSTATE 42000 - eng "Bad SQLSTATE: '%s'" - ger "Ungültiger SQLSTATE: '%s'" -ER_STARTUP - eng "%s: ready for connections.\nVersion: '%s' socket: '%s' port: %d %s" - ger "%s: bereit für Verbindungen.\nVersion: '%s' Socket: '%s' Port: %d %s" -ER_LOAD_FROM_FIXED_SIZE_ROWS_TO_VAR - eng "Can't load value from file with fixed size rows to variable" - ger "Kann Wert aus Datei mit Zeilen fester Größe nicht in Variable laden" -ER_CANT_CREATE_USER_WITH_GRANT 42000 - eng "You are not allowed to create a user with GRANT" - ger "Sie dürfen keinen Benutzer mit GRANT anlegen" -ER_WRONG_VALUE_FOR_TYPE - eng "Incorrect %-.32s value: '%-.128s' for function %-.32s" - ger "Falscher %-.32s-Wert: '%-.128s' für Funktion %-.32s" -ER_TABLE_DEF_CHANGED - eng "Table definition has changed, please retry transaction" - ger "Tabellendefinition wurde geändert, bitte starten Sie die Transaktion neu" -ER_SP_DUP_HANDLER 42000 - eng "Duplicate handler declared in the same block" - ger "Doppelter Handler im selben Block deklariert" -ER_SP_NOT_VAR_ARG 42000 - eng "OUT or INOUT argument %d for routine %s is not a variable or NEW pseudo-variable in BEFORE trigger" - ger "OUT- oder INOUT-Argument %d für Routine %s ist keine Variable" -ER_SP_NO_RETSET 0A000 - eng "Not allowed to return a result set from a %s" - ger "Rückgabe einer Ergebnismenge aus einer %s ist nicht erlaubt" -ER_CANT_CREATE_GEOMETRY_OBJECT 22003 - eng "Cannot get geometry object from data you send to the GEOMETRY field" - ger "Kann kein Geometrieobjekt aus den Daten machen, die Sie dem GEOMETRY-Feld übergeben haben" -ER_FAILED_ROUTINE_BREAK_BINLOG - eng "A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes" - ger "Eine Routine, die weder NO SQL noch READS SQL DATA in der Deklaration hat, schlug fehl und Binärlogging ist aktiv. Wenn Nicht-Transaktions-Tabellen aktualisiert wurden, enthält das Binärlog ihre Änderungen nicht" -ER_BINLOG_UNSAFE_ROUTINE - eng "This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)" - ger "Diese Routine hat weder DETERMINISTIC, NO SQL noch READS SQL DATA in der Deklaration und Binärlogging ist aktiv (*vielleicht* sollten Sie die weniger sichere Variable log_bin_trust_routine_creators verwenden)" -ER_BINLOG_CREATE_ROUTINE_NEED_SUPER - eng "You do not have the SUPER privilege and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)" - ger "Sie haben keine SUPER-Berechtigung und Binärlogging ist aktiv (*vielleicht* sollten Sie die weniger sichere Variable log_bin_trust_routine_creators verwenden)" -ER_EXEC_STMT_WITH_OPEN_CURSOR - eng "You can't execute a prepared statement which has an open cursor associated with it. Reset the statement to re-execute it." - ger "Sie können keine vorbereitete Anweisung ausführen, die mit einem geöffneten Cursor verknüpft ist. Setzen Sie die Anweisung zurück, um sie neu auszuführen" -ER_STMT_HAS_NO_OPEN_CURSOR - eng "The statement (%lu) has no open cursor." - ger "Die Anweisung (%lu) hat keinen geöffneten Cursor" -ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG - eng "Explicit or implicit commit is not allowed in stored function or trigger." - ger "Explizites oder implizites Commit ist in gespeicherten Funktionen und in Triggern nicht erlaubt" -ER_NO_DEFAULT_FOR_VIEW_FIELD - eng "Field of view '%-.192s.%-.192s' underlying table doesn't have a default value" - ger "Ein Feld der dem View '%-.192s.%-.192s' zugrundeliegenden Tabelle hat keinen Vorgabewert" -ER_SP_NO_RECURSION - eng "Recursive stored functions and triggers are not allowed." - ger "Rekursive gespeicherte Routinen und Triggers sind nicht erlaubt" -ER_TOO_BIG_SCALE 42000 S1009 - eng "Too big scale %d specified for column '%-.192s'. Maximum is %lu." - ger "Zu großer Skalierungsfaktor %d für Feld '%-.192s' angegeben. Maximum ist %lu" -ER_TOO_BIG_PRECISION 42000 S1009 - eng "Too big precision %d specified for column '%-.192s'. Maximum is %lu." - ger "Zu große Genauigkeit %d für Feld '%-.192s' angegeben. Maximum ist %lu" -ER_M_BIGGER_THAN_D 42000 S1009 - eng "For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column '%-.192s')." - ger "Für FLOAT(M,D), DOUBLE(M,D) oder DECIMAL(M,D) muss M >= D sein (Feld '%-.192s')" -ER_WRONG_LOCK_OF_SYSTEM_TABLE - eng "You can't combine write-locking of system tables with other tables or lock types" - ger "Sie können Schreibsperren auf der Systemtabelle nicht mit anderen Tabellen kombinieren" -ER_CONNECT_TO_FOREIGN_DATA_SOURCE - eng "Unable to connect to foreign data source: %.64s" - ger "Kann nicht mit Fremddatenquelle verbinden: %.64s" -ER_QUERY_ON_FOREIGN_DATA_SOURCE - eng "There was a problem processing the query on the foreign data source. Data source error: %-.64s" - ger "Bei der Verarbeitung der Abfrage ist in der Fremddatenquelle ein Problem aufgetreten. Datenquellenfehlermeldung: %-.64s" -ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST - eng "The foreign data source you are trying to reference does not exist. Data source error: %-.64s" - ger "Die Fremddatenquelle, auf die Sie zugreifen wollen, existiert nicht. Datenquellenfehlermeldung: %-.64s" -ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE - eng "Can't create federated table. The data source connection string '%-.64s' is not in the correct format" - ger "Kann föderierte Tabelle nicht erzeugen. Der Datenquellen-Verbindungsstring '%-.64s' hat kein korrektes Format" -ER_FOREIGN_DATA_STRING_INVALID - eng "The data source connection string '%-.64s' is not in the correct format" - ger "Der Datenquellen-Verbindungsstring '%-.64s' hat kein korrektes Format" -ER_CANT_CREATE_FEDERATED_TABLE - eng "Can't create federated table. Foreign data src error: %-.64s" - ger "Kann föderierte Tabelle nicht erzeugen. Fremddatenquellenfehlermeldung: %-.64s" -ER_TRG_IN_WRONG_SCHEMA - eng "Trigger in wrong schema" - ger "Trigger im falschen Schema" -ER_STACK_OVERRUN_NEED_MORE - eng "Thread stack overrun: %ld bytes used of a %ld byte stack, and %ld bytes needed. Use 'mysqld -O thread_stack=#' to specify a bigger stack." - ger "Thread-Stack-Überlauf: %ld Bytes eines %ld-Byte-Stacks in Verwendung, und %ld Bytes benötigt. Verwenden Sie 'mysqld -O thread_stack=#', um einen größeren Stack anzugeben" -ER_TOO_LONG_BODY 42000 S1009 - eng "Routine body for '%-.100s' is too long" - ger "Routinen-Body für '%-.100s' ist zu lang" -ER_WARN_CANT_DROP_DEFAULT_KEYCACHE - eng "Cannot drop default keycache" - ger "Der vorgabemäßige Schlüssel-Cache kann nicht gelöscht werden" -ER_TOO_BIG_DISPLAYWIDTH 42000 S1009 - eng "Display width out of range for column '%-.192s' (max = %lu)" - ger "Anzeigebreite außerhalb des zulässigen Bereichs für Spalte '%-.192s' (Maximum: %lu)" -ER_XAER_DUPID XAE08 - eng "XAER_DUPID: The XID already exists" - ger "XAER_DUPID: Die XID existiert bereits" -ER_DATETIME_FUNCTION_OVERFLOW 22008 - eng "Datetime function: %-.32s field overflow" - ger "Datetime-Funktion: %-.32s Feldüberlauf" -ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG - eng "Can't update table '%-.192s' in stored function/trigger because it is already used by statement which invoked this stored function/trigger." - ger "Kann Tabelle '%-.192s' in gespeicherter Funktion oder Trigger nicht aktualisieren, weil sie bereits von der Anweisung verwendet wird, die diese gespeicherte Funktion oder den Trigger aufrief" -ER_VIEW_PREVENT_UPDATE - eng "The definition of table '%-.192s' prevents operation %.192s on table '%-.192s'." - ger "Die Definition der Tabelle '%-.192s' verhindert die Operation %.192s auf Tabelle '%-.192s'" -ER_PS_NO_RECURSION - eng "The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner" - ger "Die vorbereitete Anweisung enthält einen Aufruf einer gespeicherten Routine, die auf eben dieselbe Anweisung verweist. Es ist nicht erlaubt, eine vorbereitete Anweisung in solch rekursiver Weise auszuführen" -ER_SP_CANT_SET_AUTOCOMMIT - eng "Not allowed to set autocommit from a stored function or trigger" - ger "Es ist nicht erlaubt, innerhalb einer gespeicherten Funktion oder eines Triggers AUTOCOMMIT zu setzen" -ER_MALFORMED_DEFINER - eng "Definer is not fully qualified" - ger "Definierer des View ist nicht vollständig spezifiziert" -ER_VIEW_FRM_NO_USER - eng "View '%-.192s'.'%-.192s' has no definer information (old table format). Current user is used as definer. Please recreate the view!" - ger "View '%-.192s'.'%-.192s' hat keine Definierer-Information (altes Tabellenformat). Der aktuelle Benutzer wird als Definierer verwendet. Bitte erstellen Sie den View neu" -ER_VIEW_OTHER_USER - eng "You need the SUPER privilege for creation view with '%-.192s'@'%-.192s' definer" - ger "Sie brauchen die SUPER-Berechtigung, um einen View mit dem Definierer '%-.192s'@'%-.192s' zu erzeugen" -ER_NO_SUCH_USER - eng "The user specified as a definer ('%-.64s'@'%-.64s') does not exist" -ER_FORBID_SCHEMA_CHANGE - eng "Changing schema from '%-.192s' to '%-.192s' is not allowed." - ger "Wechsel des Schemas von '%-.192s' auf '%-.192s' ist nicht erlaubt" -ER_ROW_IS_REFERENCED_2 23000 - eng "Cannot delete or update a parent row: a foreign key constraint fails (%.192s)" - ger "Kann Eltern-Zeile nicht löschen oder aktualisieren: eine Fremdschlüsselbedingung schlägt fehl (%.192s)" -ER_NO_REFERENCED_ROW_2 23000 - eng "Cannot add or update a child row: a foreign key constraint fails (%.192s)" - ger "Kann Kind-Zeile nicht hinzufügen oder aktualisieren: eine Fremdschlüsselbedingung schlägt fehl (%.192s)" -ER_SP_BAD_VAR_SHADOW 42000 - eng "Variable '%-.64s' must be quoted with `...`, or renamed" - ger "Variable '%-.64s' muss mit `...` geschützt oder aber umbenannt werden" -ER_TRG_NO_DEFINER - eng "No definer attribute for trigger '%-.192s'.'%-.192s'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger." - ger "Kein Definierer-Attribut für Trigger '%-.192s'.'%-.192s'. Der Trigger wird mit der Autorisierung des Aufrufers aktiviert, der möglicherweise keine zureichenden Berechtigungen hat. Bitte legen Sie den Trigger neu an." -ER_OLD_FILE_FORMAT - eng "'%-.192s' has an old format, you should re-create the '%s' object(s)" - ger "'%-.192s' hat altes Format, Sie sollten die '%s'-Objekt(e) neu erzeugen" -ER_SP_RECURSION_LIMIT - eng "Recursive limit %d (as set by the max_sp_recursion_depth variable) was exceeded for routine %.192s" - ger "Rekursionsgrenze %d (durch Variable max_sp_recursion_depth gegeben) wurde für Routine %.192s überschritten" -ER_SP_PROC_TABLE_CORRUPT - eng "Failed to load routine %-.192s. The table mysql.proc is missing, corrupt, or contains bad data (internal code %d)" - ger "Routine %-.192s konnte nicht geladen werden. Die Tabelle mysql.proc fehlt, ist beschädigt, oder enthält fehlerhaften Daten (interner Code: %d)" -ER_SP_WRONG_NAME 42000 - eng "Incorrect routine name '%-.192s'" - ger "Ungültiger Routinenname '%-.192s'" -ER_TABLE_NEEDS_UPGRADE - eng "Table upgrade required. Please do \"REPAIR TABLE `%-.32s`\" or dump/reload to fix it!" - ger "Tabellenaktualisierung erforderlich. Bitte zum Reparieren \"REPAIR TABLE `%-.32s`\" eingeben!" -ER_SP_NO_AGGREGATE 42000 - eng "AGGREGATE is not supported for stored functions" - ger "AGGREGATE wird bei gespeicherten Funktionen nicht unterstützt" -ER_MAX_PREPARED_STMT_COUNT_REACHED 42000 - eng "Can't create more than max_prepared_stmt_count statements (current value: %lu)" - ger "Kann nicht mehr Anweisungen als max_prepared_stmt_count erzeugen (aktueller Wert: %lu)" -ER_VIEW_RECURSIVE - eng "`%-.192s`.`%-.192s` contains view recursion" - ger "`%-.192s`.`%-.192s` enthält View-Rekursion" -ER_NON_GROUPING_FIELD_USED 42000 - eng "non-grouping field '%-.192s' is used in %-.64s clause" - ger "In der %-.192s-Klausel wird das die Nicht-Gruppierungsspalte '%-.64s' verwendet" -ER_TABLE_CANT_HANDLE_SPKEYS - eng "The used table type doesn't support SPATIAL indexes" - ger "Der verwendete Tabellentyp unterstützt keine SPATIAL-Indizes" -ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA - eng "Triggers can not be created on system tables" - ger "Trigger können nicht auf Systemtabellen erzeugt werden" -ER_REMOVED_SPACES - eng "Leading spaces are removed from name '%s'" - ger "Führende Leerzeichen werden aus dem Namen '%s' entfernt" -ER_AUTOINC_READ_FAILED - eng "Failed to read auto-increment value from storage engine" - ger "Lesen des Autoincrement-Werts von der Speicher-Engine fehlgeschlagen" -ER_USERNAME - eng "user name" - ger "Benutzername" -ER_HOSTNAME - eng "host name" - ger "Hostname" -ER_WRONG_STRING_LENGTH - eng "String '%-.70s' is too long for %s (should be no longer than %d)" - ger "String '%-.70s' ist zu lang für %s (sollte nicht länger sein als %d)" -ER_NON_INSERTABLE_TABLE - eng "The target table %-.100s of the %s is not insertable-into" - ger "Die Zieltabelle %-.100s von %s ist nicht einfügbar" -ER_ADMIN_WRONG_MRG_TABLE - eng "Table '%-.64s' is differently defined or of non-MyISAM type or doesn't exist" -ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT - eng "Too high level of nesting for select" -ER_NAME_BECOMES_EMPTY - eng "Name '%-.64s' has become ''" -ER_AMBIGUOUS_FIELD_TERM - eng "First character of the FIELDS TERMINATED string is ambiguous; please use non-optional and non-empty FIELDS ENCLOSED BY" -ER_FOREIGN_SERVER_EXISTS - eng "The foreign server, %s, you are trying to create already exists." -ER_FOREIGN_SERVER_DOESNT_EXIST - eng "The foreign server name you are trying to reference does not exist. Data source error: %-.64s" - ger "Die externe Verbindung, auf die Sie zugreifen wollen, existiert nicht. Datenquellenfehlermeldung: %-.64s" -ER_ILLEGAL_HA_CREATE_OPTION - eng "Table storage engine '%-.64s' does not support the create option '%.64s'" - ger "Speicher-Engine '%-.64s' der Tabelle unterstützt die Option '%.64s' nicht" -ER_PARTITION_REQUIRES_VALUES_ERROR - eng "Syntax error: %-.64s PARTITIONING requires definition of VALUES %-.64s for each partition" - ger "Fehler in der SQL-Syntax: %-.64s-PARTITIONierung erfordert Definition von VALUES %-.64s für jede Partition" - swe "Syntaxfel: %-.64s PARTITIONering kräver definition av VALUES %-.64s för varje partition" -ER_PARTITION_WRONG_VALUES_ERROR - eng "Only %-.64s PARTITIONING can use VALUES %-.64s in partition definition" - ger "Nur %-.64s-PARTITIONierung kann VALUES %-.64s in der Partitionsdefinition verwenden" - swe "Endast %-.64s partitionering kan använda VALUES %-.64s i definition av partitionen" -ER_PARTITION_MAXVALUE_ERROR - eng "MAXVALUE can only be used in last partition definition" - ger "MAXVALUE kann nur für die Definition der letzten Partition verwendet werden" - swe "MAXVALUE kan bara användas i definitionen av den sista partitionen" -ER_PARTITION_SUBPARTITION_ERROR - eng "Subpartitions can only be hash partitions and by key" - ger "Unterpartitionen dürfen nur HASH- oder KEY-Partitionen sein" - swe "Subpartitioner kan bara vara hash och key partitioner" -ER_PARTITION_SUBPART_MIX_ERROR - eng "Must define subpartitions on all partitions if on one partition" - ger "Unterpartitionen können nur Hash- oder Key-Partitionen sein" - swe "Subpartitioner mÃ¥ste definieras pÃ¥ alla partitioner om pÃ¥ en" -ER_PARTITION_WRONG_NO_PART_ERROR - eng "Wrong number of partitions defined, mismatch with previous setting" - ger "Falsche Anzahl von Partitionen definiert, stimmt nicht mit vorherigen Einstellungen überein" - swe "Antal partitioner definierade och antal partitioner är inte lika" -ER_PARTITION_WRONG_NO_SUBPART_ERROR - eng "Wrong number of subpartitions defined, mismatch with previous setting" - ger "Falsche Anzahl von Unterpartitionen definiert, stimmt nicht mit vorherigen Einstellungen überein" - swe "Antal subpartitioner definierade och antal subpartitioner är inte lika" -ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR - eng "Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed" - ger "Konstante oder Random-Ausdrücke in (Unter-)Partitionsfunktionen sind nicht erlaubt" - swe "Konstanta uttryck eller slumpmässiga uttryck är inte tillåtna (sub)partitioneringsfunktioner" -ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR - eng "Expression in RANGE/LIST VALUES must be constant" - ger "Ausdrücke in RANGE/LIST VALUES müssen konstant sein" - swe "Uttryck i RANGE/LIST VALUES måste vara ett konstant uttryck" -ER_FIELD_NOT_FOUND_PART_ERROR - eng "Field in list of fields for partition function not found in table" - ger "Felder in der Feldliste der Partitionierungsfunktion wurden in der Tabelle nicht gefunden" - swe "Fält i listan av fält för partitionering med key inte funnen i tabellen" -ER_LIST_OF_FIELDS_ONLY_IN_HASH_ERROR - eng "List of fields is only allowed in KEY partitions" - ger "Eine Feldliste ist nur in KEY-Partitionen erlaubt" - swe "En lista av fält är endast tillåtet för KEY partitioner" -ER_INCONSISTENT_PARTITION_INFO_ERROR - eng "The partition info in the frm file is not consistent with what can be written into the frm file" - ger "Die Partitionierungsinformationen in der frm-Datei stimmen nicht mit dem überein, was in die frm-Datei geschrieben werden kann" - swe "Partitioneringsinformationen i frm-filen är inte konsistent med vad som kan skrivas i frm-filen" -ER_PARTITION_FUNC_NOT_ALLOWED_ERROR - eng "The %-.192s function returns the wrong type" - ger "Die %-.192s-Funktion gibt einen falschen Typ zurück" - swe "%-.192s-funktionen returnerar felaktig typ" -ER_PARTITIONS_MUST_BE_DEFINED_ERROR - eng "For %-.64s partitions each partition must be defined" - ger "Für %-.64s-Partitionen muss jede Partition definiert sein" - swe "För %-.64s partitionering så måste varje partition definieras" -ER_RANGE_NOT_INCREASING_ERROR - eng "VALUES LESS THAN value must be strictly increasing for each partition" - ger "Werte in VALUES LESS THAN müssen für jede Partition strikt aufsteigend sein" - swe "Värden i VALUES LESS THAN måste vara strikt växande för varje partition" -ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR - eng "VALUES value must be of same type as partition function" - ger "VALUES-Werte müssen vom selben Typ wie die Partitionierungsfunktion sein" - swe "Värden i VALUES måste vara av samma typ som partitioneringsfunktionen" -ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR - eng "Multiple definition of same constant in list partitioning" - ger "Mehrfachdefinition derselben Konstante bei Listen-Partitionierung" - swe "Multipel definition av samma konstant i list partitionering" -ER_PARTITION_ENTRY_ERROR - eng "Partitioning can not be used stand-alone in query" - ger "Partitionierung kann in einer Abfrage nicht alleinstehend benutzt werden" - swe "Partitioneringssyntax kan inte användas på egen hand i en SQL-fråga" -ER_MIX_HANDLER_ERROR - eng "The mix of handlers in the partitions is not allowed in this version of MySQL" - ger "Das Vermischen von Handlern in Partitionen ist in dieser Version von MySQL nicht erlaubt" - swe "Denna mix av lagringsmotorer är inte tillåten i denna version av MySQL" -ER_PARTITION_NOT_DEFINED_ERROR - eng "For the partitioned engine it is necessary to define all %-.64s" - ger "Für die partitionierte Engine müssen alle %-.64s definiert sein" - swe "För partitioneringsmotorn så är det nödvändigt att definiera alla %-.64s" -ER_TOO_MANY_PARTITIONS_ERROR - eng "Too many partitions (including subpartitions) were defined" - ger "Es wurden zu vielen Partitionen (einschließlich Unterpartitionen) definiert" - swe "För många partitioner (inkluderande subpartitioner) definierades" -ER_SUBPARTITION_ERROR - eng "It is only possible to mix RANGE/LIST partitioning with HASH/KEY partitioning for subpartitioning" - ger "RANGE/LIST-Partitionierung kann bei Unterpartitionen nur zusammen mit HASH/KEY-Partitionierung verwendet werden" - swe "Det är endast möjligt att blanda RANGE/LIST partitionering med HASH/KEY partitionering för subpartitionering" -ER_CANT_CREATE_HANDLER_FILE - eng "Failed to create specific handler file" - ger "Erzeugen einer spezifischen Handler-Datei fehlgeschlagen" - swe "Misslyckades med att skapa specifik fil i lagringsmotor" -ER_BLOB_FIELD_IN_PART_FUNC_ERROR - eng "A BLOB field is not allowed in partition function" - ger "In der Partitionierungsfunktion sind BLOB-Spalten nicht erlaubt" - swe "Ett BLOB-fält är inte tillåtet i partitioneringsfunktioner" -ER_UNIQUE_KEY_NEED_ALL_FIELDS_IN_PF - eng "A %-.192s must include all columns in the table's partitioning function" -ER_NO_PARTS_ERROR - eng "Number of %-.64s = 0 is not an allowed value" - ger "Eine Anzahl von %-.64s = 0 ist kein erlaubter Wert" - swe "Antal %-.64s = 0 är inte ett tillåten värde" -ER_PARTITION_MGMT_ON_NONPARTITIONED - eng "Partition management on a not partitioned table is not possible" - ger "Partitionsverwaltung einer nicht partitionierten Tabelle ist nicht möglich" - swe "Partitioneringskommando på en opartitionerad tabell är inte möjligt" -ER_FOREIGN_KEY_ON_PARTITIONED - eng "Foreign key clause is not yet supported in conjunction with partitioning" - ger "Fremdschlüssel-Beschränkungen sind im Zusammenhang mit Partitionierung nicht zulässig" - swe "Foreign key klausul är inte ännu implementerad i kombination med partitionering" -ER_DROP_PARTITION_NON_EXISTENT - eng "Error in list of partitions to %-.64s" - ger "Fehler in der Partitionsliste bei %-.64s" - swe "Fel i listan av partitioner att %-.64s" -ER_DROP_LAST_PARTITION - eng "Cannot remove all partitions, use DROP TABLE instead" - ger "Es lassen sich nicht sämtliche Partitionen löschen, benutzen Sie statt dessen DROP TABLE" - swe "Det är inte tillåtet att ta bort alla partitioner, använd DROP TABLE istället" -ER_COALESCE_ONLY_ON_HASH_PARTITION - eng "COALESCE PARTITION can only be used on HASH/KEY partitions" - ger "COALESCE PARTITION kann nur auf HASH- oder KEY-Partitionen benutzt werden" - swe "COALESCE PARTITION kan bara användas på HASH/KEY partitioner" -ER_REORG_HASH_ONLY_ON_SAME_NO - eng "REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers" - ger "REORGANIZE PARTITION kann nur zur Reorganisation von Partitionen verwendet werden, nicht, um ihre Nummern zu ändern" - swe "REORGANIZE PARTITION kan bara användas för att omorganisera partitioner, inte för att ändra deras antal" -ER_REORG_NO_PARAM_ERROR - eng "REORGANIZE PARTITION without parameters can only be used on auto-partitioned tables using HASH PARTITIONs" - ger "REORGANIZE PARTITION ohne Parameter kann nur für auto-partitionierte Tabellen verwendet werden, die HASH-Partitionierung benutzen" - swe "REORGANIZE PARTITION utan parametrar kan bara användas på auto-partitionerade tabeller som använder HASH partitionering" -ER_ONLY_ON_RANGE_LIST_PARTITION - eng "%-.64s PARTITION can only be used on RANGE/LIST partitions" - ger "%-.64s PARTITION kann nur für RANGE- oder LIST-Partitionen verwendet werden" - swe "%-.64s PARTITION kan bara användas på RANGE/LIST-partitioner" -ER_ADD_PARTITION_SUBPART_ERROR - eng "Trying to Add partition(s) with wrong number of subpartitions" - ger "Es wurde versucht, eine oder mehrere Partitionen mit der falschen Anzahl von Unterpartitionen hinzuzufügen" - swe "ADD PARTITION med fel antal subpartitioner" -ER_ADD_PARTITION_NO_NEW_PARTITION - eng "At least one partition must be added" - ger "Es muss zumindest eine Partition hinzugefügt werden" - swe "Åtminstone en partition måste läggas till vid ADD PARTITION" -ER_COALESCE_PARTITION_NO_PARTITION - eng "At least one partition must be coalesced" - ger "Zumindest eine Partition muss mit COALESCE PARTITION zusammengefügt werden" - swe "Åtminstone en partition måste slås ihop vid COALESCE PARTITION" -ER_REORG_PARTITION_NOT_EXIST - eng "More partitions to reorganize than there are partitions" - ger "Es wurde versucht, mehr Partitionen als vorhanden zu reorganisieren" - swe "Fler partitioner att reorganisera än det finns partitioner" -ER_SAME_NAME_PARTITION - eng "Duplicate partition name %-.192s" - ger "Doppelter Partitionsname: %-.192s" - swe "Duplicerat partitionsnamn %-.192s" -ER_NO_BINLOG_ERROR - eng "It is not allowed to shut off binlog on this command" - ger "Es es nicht erlaubt, bei diesem Befehl binlog abzuschalten" - swe "Det är inte tillåtet att stänga av binlog på detta kommando" -ER_CONSECUTIVE_REORG_PARTITIONS - eng "When reorganizing a set of partitions they must be in consecutive order" - ger "Bei der Reorganisation eines Satzes von Partitionen müssen diese in geordneter Reihenfolge vorliegen" - swe "När ett antal partitioner omorganiseras måste de vara i konsekutiv ordning" -ER_REORG_OUTSIDE_RANGE - eng "Reorganize of range partitions cannot change total ranges except for last partition where it can extend the range" - ger "Die Reorganisation von RANGE-Partitionen kann Gesamtbereiche nicht verändern, mit Ausnahme der letzten Partition, die den Bereich erweitern kann" - swe "Reorganisering av rangepartitioner kan inte ändra den totala intervallet utom för den sista partitionen där intervallet kan utökas" -ER_PARTITION_FUNCTION_FAILURE - eng "Partition function not supported in this version for this handler" - ger "Partitionsfunktion in dieser Version dieses Handlers nicht unterstützt" -ER_PART_STATE_ERROR - eng "Partition state cannot be defined from CREATE/ALTER TABLE" - ger "Partitionszustand kann nicht von CREATE oder ALTER TABLE aus definiert werden" - swe "Partition state kan inte definieras från CREATE/ALTER TABLE" -ER_LIMITED_PART_RANGE - eng "The %-.64s handler only supports 32 bit integers in VALUES" - ger "Der Handler %-.64s unterstützt in VALUES nur 32-Bit-Integers" - swe "%-.64s stödjer endast 32 bitar i integers i VALUES" -ER_PLUGIN_IS_NOT_LOADED - eng "Plugin '%-.192s' is not loaded" - ger "Plugin '%-.192s' ist nicht geladen" -ER_WRONG_VALUE - eng "Incorrect %-.32s value: '%-.128s'" - ger "Falscher %-.32s-Wert: '%-.128s'" -ER_NO_PARTITION_FOR_GIVEN_VALUE - eng "Table has no partition for value %-.64s" - ger "Tabelle hat für den Wert %-.64s keine Partition" -ER_FILEGROUP_OPTION_ONLY_ONCE - eng "It is not allowed to specify %s more than once" - ger "%s darf nicht mehr als einmal angegegeben werden" -ER_CREATE_FILEGROUP_FAILED - eng "Failed to create %s" - ger "Anlegen von %s fehlgeschlagen" -ER_DROP_FILEGROUP_FAILED - eng "Failed to drop %s" - ger "Löschen (drop) von %s fehlgeschlagen" -ER_TABLESPACE_AUTO_EXTEND_ERROR - eng "The handler doesn't support autoextend of tablespaces" - ger "Der Handler unterstützt keine automatische Erweiterung (Autoextend) von Tablespaces" -ER_WRONG_SIZE_NUMBER - eng "A size parameter was incorrectly specified, either number or on the form 10M" - ger "Ein Größen-Parameter wurde unkorrekt angegeben, muss entweder Zahl sein oder im Format 10M" -ER_SIZE_OVERFLOW_ERROR - eng "The size number was correct but we don't allow the digit part to be more than 2 billion" - ger "Die Zahl für die Größe war korrekt, aber der Zahlanteil darf nicht größer als 2 Milliarden sein" -ER_ALTER_FILEGROUP_FAILED - eng "Failed to alter: %s" - ger "Änderung von %s fehlgeschlagen" -ER_BINLOG_ROW_LOGGING_FAILED - eng "Writing one row to the row-based binary log failed" - ger "Schreiben einer Zeilen ins zeilenbasierte Binärlog fehlgeschlagen" -ER_BINLOG_ROW_WRONG_TABLE_DEF - eng "Table definition on master and slave does not match: %s" - ger "Tabellendefinition auf Master und Slave stimmt nicht überein: %s" -ER_BINLOG_ROW_RBR_TO_SBR - eng "Slave running with --log-slave-updates must use row-based binary logging to be able to replicate row-based binary log events" - ger "Slave, die mit --log-slave-updates laufen, müssen zeilenbasiertes Loggen verwenden, um zeilenbasierte Binärlog-Ereignisse loggen zu können" -ER_EVENT_ALREADY_EXISTS - eng "Event '%-.192s' already exists" - ger "Event '%-.192s' existiert bereits" -ER_EVENT_STORE_FAILED - eng "Failed to store event %s. Error code %d from storage engine." - ger "Speichern von Event %s fehlgeschlagen. Fehlercode der Speicher-Engine: %d" -ER_EVENT_DOES_NOT_EXIST - eng "Unknown event '%-.192s'" - ger "Unbekanntes Event '%-.192s'" -ER_EVENT_CANT_ALTER - eng "Failed to alter event '%-.192s'" - ger "Ändern des Events '%-.192s' fehlgeschlagen" -ER_EVENT_DROP_FAILED - eng "Failed to drop %s" - ger "Löschen von %s fehlgeschlagen" -ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG - eng "INTERVAL is either not positive or too big" - ger "INTERVAL ist entweder nicht positiv oder zu groß" -ER_EVENT_ENDS_BEFORE_STARTS - eng "ENDS is either invalid or before STARTS" - ger "ENDS ist entweder ungültig oder liegt vor STARTS" -ER_EVENT_EXEC_TIME_IN_THE_PAST - eng "Event execution time is in the past. Event has been disabled" -ER_EVENT_OPEN_TABLE_FAILED - eng "Failed to open mysql.event" - ger "Öffnen von mysql.event fehlgeschlagen" -ER_EVENT_NEITHER_M_EXPR_NOR_M_AT - eng "No datetime expression provided" - ger "Kein DATETIME-Ausdruck angegeben" -ER_COL_COUNT_DOESNT_MATCH_CORRUPTED - eng "Column count of mysql.%s is wrong. Expected %d, found %d. The table is probably corrupted" - ger "Spaltenanzahl von mysql.%s falsch. %d erwartet, aber %d gefunden. Tabelle ist wahrscheinlich beschädigt" -ER_CANNOT_LOAD_FROM_TABLE - eng "Cannot load from mysql.%s. The table is probably corrupted" - ger "Kann mysql.%s nicht einlesen. Tabelle ist wahrscheinlich beschädigt" -ER_EVENT_CANNOT_DELETE - eng "Failed to delete the event from mysql.event" - ger "Löschen des Events aus mysql.event fehlgeschlagen" -ER_EVENT_COMPILE_ERROR - eng "Error during compilation of event's body" - ger "Fehler beim Kompilieren des Event-Bodys" -ER_EVENT_SAME_NAME - eng "Same old and new event name" - ger "Alter und neuer Event-Name sind gleich" -ER_EVENT_DATA_TOO_LONG - eng "Data for column '%s' too long" - ger "Daten der Spalte '%s' zu lang" -ER_DROP_INDEX_FK - eng "Cannot drop index '%-.192s': needed in a foreign key constraint" - ger "Kann Index '%-.192s' nicht löschen: wird für einen Fremdschlüssel benötigt" -# When using this error message, use the ER_WARN_DEPRECATED_SYNTAX error -# code. See, for example, code in mysql_priv.h. -ER_WARN_DEPRECATED_SYNTAX_WITH_VER - eng "The syntax '%s' is deprecated and will be removed in MySQL %s. Please use %s instead" - ger "Die Syntax '%s' ist veraltet und wird in MySQL %s entfernt. Bitte benutzen Sie statt dessen %s" -ER_CANT_WRITE_LOCK_LOG_TABLE - eng "You can't write-lock a log table. Only read access is possible" - ger "Eine Log-Tabelle kann nicht schreibgesperrt werden. Es ist ohnehin nur Lesezugriff möglich" -ER_CANT_LOCK_LOG_TABLE - eng "You can't use locks with log tables." - ger "Log-Tabellen können nicht mit normalen Lesesperren gesperrt werden. Verwenden Sie statt dessen READ LOCAL" -ER_FOREIGN_DUPLICATE_KEY 23000 S1009 - eng "Upholding foreign key constraints for table '%.192s', entry '%-.192s', key %d would lead to a duplicate entry" - ger "Aufrechterhalten der Fremdschlüssel-Constraints für Tabelle '%.192s', Eintrag '%-.192s', Schlüssel %d würde zu einem doppelten Eintrag führen" -ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE - eng "Column count of mysql.%s is wrong. Expected %d, found %d. Created with MySQL %d, now running %d. Please use mysql_upgrade to fix this error." - ger "Spaltenanzahl von mysql.%s falsch. %d erwartet, aber %d erhalten. Erzeugt mit MySQL %d, jetzt unter %d. Bitte benutzen Sie mysql_upgrade, um den Fehler zu beheben" -ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR - eng "Cannot switch out of the row-based binary log format when the session has open temporary tables" - ger "Kann nicht aus dem zeilenbasierten Binärlog-Format herauswechseln, wenn die Sitzung offene temporäre Tabellen hat" -ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT - eng "Cannot change the binary logging format inside a stored function or trigger" - ger "Das Binärlog-Format kann innerhalb einer gespeicherten Funktion oder eines Triggers nicht geändert werden" -ER_NDB_CANT_SWITCH_BINLOG_FORMAT - eng "The NDB cluster engine does not support changing the binlog format on the fly yet" - ger "Die Speicher-Engine NDB Cluster unterstützt das Ändern des Binärlog-Formats zur Laufzeit noch nicht" -ER_PARTITION_NO_TEMPORARY - eng "Cannot create temporary table with partitions" - ger "Anlegen temporärer Tabellen mit Partitionen nicht möglich" -ER_PARTITION_CONST_DOMAIN_ERROR - eng "Partition constant is out of partition function domain" - ger "Partitionskonstante liegt außerhalb der Partitionsfunktionsdomäne" - swe "Partitionskonstanten är utanför partitioneringsfunktionens domän" -ER_PARTITION_FUNCTION_IS_NOT_ALLOWED - eng "This partition function is not allowed" - ger "Diese Partitionierungsfunktion ist nicht erlaubt" - swe "Denna partitioneringsfunktion är inte tillåten" -ER_DDL_LOG_ERROR - eng "Error in DDL log" - ger "Fehler im DDL-Log" -ER_NULL_IN_VALUES_LESS_THAN - eng "Not allowed to use NULL value in VALUES LESS THAN" - ger "In VALUES LESS THAN dürfen keine NULL-Werte verwendet werden" - swe "Det är inte tillåtet att använda NULL-värden i VALUES LESS THAN" -ER_WRONG_PARTITION_NAME - eng "Incorrect partition name" - ger "Falscher Partitionsname" - swe "Felaktigt partitionsnamn" -ER_CANT_CHANGE_TX_ISOLATION 25001 - eng "Transaction isolation level can't be changed while a transaction is in progress" - ger "Transaktionsisolationsebene kann während einer laufenden Transaktion nicht geändert werden" -ER_DUP_ENTRY_AUTOINCREMENT_CASE - eng "ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '%-.192s' for key '%-.192s'" - ger "ALTER TABLE führt zur Neusequenzierung von auto_increment, wodurch der doppelte Eintrag '%-.192s' für Schlüssel '%-.192s' auftritt" -ER_EVENT_MODIFY_QUEUE_ERROR - eng "Internal scheduler error %d" - ger "Interner Scheduler-Fehler %d" -ER_EVENT_SET_VAR_ERROR - eng "Error during starting/stopping of the scheduler. Error code %u" - ger "Fehler während des Startens oder Anhalten des Schedulers. Fehlercode %u" -ER_PARTITION_MERGE_ERROR - eng "Engine cannot be used in partitioned tables" - ger "Engine kann in partitionierten Tabellen nicht verwendet werden" - swe "Engine inte användas i en partitionerad tabell" -ER_CANT_ACTIVATE_LOG - eng "Cannot activate '%-.64s' log" - ger "Kann Logdatei '%-.64s' nicht aktivieren" -ER_RBR_NOT_AVAILABLE - eng "The server was not built with row-based replication" -ER_BASE64_DECODE_ERROR - eng "Decoding of base64 string failed" - swe "Avkodning av base64 sträng misslyckades" - ger "Der Server hat keine zeilenbasierte Replikation" -ER_EVENT_RECURSION_FORBIDDEN - eng "Recursion of EVENT DDL statements is forbidden when body is present" - ger "Rekursivität von EVENT-DDL-Anweisungen ist unzulässig wenn ein Hauptteil (Body) existiert" -ER_EVENTS_DB_ERROR - eng "Cannot proceed because system tables used by Event Scheduler were found damaged at server start" - ger "Kann nicht weitermachen, weil die Tabellen, die von Events verwendet werden, beim Serverstart als beschädigt markiert wurden" -ER_ONLY_INTEGERS_ALLOWED - eng "Only integers allowed as number here" - ger "An dieser Stelle sind nur Ganzzahlen zulässig" -ER_UNSUPORTED_LOG_ENGINE - eng "This storage engine cannot be used for log tables"" - ger "Diese Speicher-Engine kann für Logtabellen nicht verwendet werden" -ER_BAD_LOG_STATEMENT - eng "You cannot '%s' a log table if logging is enabled" - ger "Sie können eine Logtabelle nicht '%s', wenn Loggen angeschaltet ist" -ER_CANT_RENAME_LOG_TABLE - eng "Cannot rename '%s'. When logging enabled, rename to/from log table must rename two tables: the log table to an archive table and another table back to '%s'" - ger "Kann '%s' nicht umbenennen. Wenn Loggen angeschaltet ist, müssen beim Umbenennen zu/von einer Logtabelle zwei Tabellen angegeben werden: die Logtabelle zu einer Archivtabelle und eine weitere Tabelle zurück zu '%s'" -ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT 42000 - eng "Incorrect parameter count in the call to native function '%-.192s'" - ger "Falsche Anzahl von Parametern beim Aufruf der nativen Funktion '%-.192s'" -ER_WRONG_PARAMETERS_TO_NATIVE_FCT 42000 - eng "Incorrect parameters in the call to native function '%-.192s'" - ger "Falscher Parameter beim Aufruf der nativen Funktion '%-.192s'" -ER_WRONG_PARAMETERS_TO_STORED_FCT 42000 - eng "Incorrect parameters in the call to stored function '%-.192s'" - ger "Falsche Parameter beim Aufruf der gespeicherten Funktion '%-.192s'" -ER_NATIVE_FCT_NAME_COLLISION - eng "This function '%-.192s' has the same name as a native function" - ger "Die Funktion '%-.192s' hat denselben Namen wie eine native Funktion" -# When using this error message, use the ER_DUP_ENTRY error code. See, for -# example, code in handler.cc. -ER_DUP_ENTRY_WITH_KEY_NAME 23000 S1009 - cze "Zvojen-Bý klíè '%-.64s' (èíslo klíèe '%-.192s')" - dan "Ens værdier '%-.64s' for indeks '%-.192s'" - nla "Dubbele ingang '%-.64s' voor zoeksleutel '%-.192s'" - eng "Duplicate entry '%-.64s' for key '%-.192s'" - jps "'%-.64s' ‚Í key '%-.192s' ‚É‚¨‚¢‚Äd•¡‚µ‚Ä‚¢‚Ü‚·", - est "Kattuv väärtus '%-.64s' võtmele '%-.192s'" - fre "Duplicata du champ '%-.64s' pour la clef '%-.192s'" - ger "Doppelter Eintrag '%-.64s' für Schlüssel '%-.192s'" - greek "ÄéðëÞ åããñáöÞ '%-.64s' ãéá ôï êëåéäß '%-.192s'" - hun "Duplikalt bejegyzes '%-.64s' a '%-.192s' kulcs szerint." - ita "Valore duplicato '%-.64s' per la chiave '%-.192s'" - jpn "'%-.64s' ¤Ï key '%-.192s' ¤Ë¤ª¤¤¤Æ½ÅÊ£¤·¤Æ¤¤¤Þ¤¹" - kor "Áߺ¹µÈ ÀÔ·Â °ª '%-.64s': key '%-.192s'" - nor "Like verdier '%-.64s' for nøkkel '%-.192s'" - norwegian-ny "Like verdiar '%-.64s' for nykkel '%-.192s'" - pol "Powtórzone wyst?pienie '%-.64s' dla klucza '%-.192s'" - por "Entrada '%-.64s' duplicada para a chave '%-.192s'" - rum "Cimpul '%-.64s' e duplicat pentru cheia '%-.192s'" - rus "äÕÂÌÉÒÕÀÝÁÑÓÑ ÚÁÐÉÓØ '%-.64s' ÐÏ ËÌÀÞÕ '%-.192s'" - serbian "Dupliran unos '%-.64s' za kljuè '%-.192s'" - slo "Opakovaný kµúè '%-.64s' (èíslo kµúèa '%-.192s')" - spa "Entrada duplicada '%-.64s' para la clave '%-.192s'" - swe "Dubbel nyckel '%-.64s' för nyckel '%-.192s'" - ukr "äÕÂÌÀÀÞÉÊ ÚÁÐÉÓ '%-.64s' ÄÌÑ ËÌÀÞÁ '%-.192s'" -ER_BINLOG_PURGE_EMFILE - eng "Too many files opened, please execute the command again" - ger "Zu viele offene Dateien, bitte führen Sie den Befehl noch einmal aus" -ER_EVENT_CANNOT_CREATE_IN_THE_PAST - eng "Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation." -ER_EVENT_CANNOT_ALTER_IN_THE_PAST - eng "Event execution time is in the past and ON COMPLETION NOT PRESERVE is set. The event was dropped immediately after creation." -ER_SLAVE_INCIDENT - eng "The incident %s occured on the master. Message: %-.64s" -ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT - eng "Table has no partition for some existing values" -ER_BINLOG_UNSAFE_STATEMENT - eng "Statement may not be safe to log in statement format." - swe "Detta är inte säkert att logga i statement-format." -ER_SLAVE_FATAL_ERROR - eng "Fatal error: %s" -ER_SLAVE_RELAY_LOG_READ_FAILURE - eng "Relay log read failure: %s" -ER_SLAVE_RELAY_LOG_WRITE_FAILURE - eng "Relay log write failure: %s" -ER_SLAVE_CREATE_EVENT_FAILURE - eng "Failed to create %s" -ER_SLAVE_MASTER_COM_FAILURE - eng "Master command %s failed: %s" -ER_BINLOG_LOGGING_IMPOSSIBLE - eng "Binary logging not possible. Message: %s" - -ER_VIEW_NO_CREATION_CTX - eng "View `%-.64s`.`%-.64s` has no creation context" -ER_VIEW_INVALID_CREATION_CTX - eng "Creation context of view `%-.64s`.`%-.64s' is invalid" - -ER_SR_INVALID_CREATION_CTX - eng "Creation context of stored routine `%-.64s`.`%-.64s` is invalid" - -ER_TRG_CORRUPTED_FILE - eng "Corrupted TRG file for table `%-.64s`.`%-.64s`" -ER_TRG_NO_CREATION_CTX - eng "Triggers for table `%-.64s`.`%-.64s` have no creation context" -ER_TRG_INVALID_CREATION_CTX - eng "Trigger creation context of table `%-.64s`.`%-.64s` is invalid" - -ER_EVENT_INVALID_CREATION_CTX - eng "Creation context of event `%-.64s`.`%-.64s` is invalid" - -ER_TRG_CANT_OPEN_TABLE - eng "Cannot open table for trigger `%-.64s`.`%-.64s`" - -ER_CANT_CREATE_SROUTINE - eng "Cannot create stored routine `%-.64s`. Check warnings" -ER_SLAVE_AMBIGOUS_EXEC_MODE - eng "Ambiguous slave modes combination. %s" - -ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT - eng "The BINLOG statement of type `%s` was not preceded by a format description BINLOG statement." -ER_SLAVE_CORRUPT_EVENT - eng "Corrupted replication event was detected" - -ER_LOAD_DATA_INVALID_COLUMN - eng "Invalid column reference (%-.64s) in LOAD DATA" - -ER_LOG_PURGE_NO_FILE - eng "Being purged log %s was not found" - -ER_XA_RBTIMEOUT XA106 - eng "XA_RBTIMEOUT: Transaction branch was rolled back: took too long" - -ER_XA_RBDEADLOCK XA102 - eng "XA_RBDEADLOCK: Transaction branch was rolled back: deadlock was detected" - -ER_NEED_REPREPARE - eng "Prepared statement needs to be re-prepared" - -ER_DELAYED_NOT_SUPPORTED - eng "DELAYED option not supported for table '%-.192s'" - -WARN_NO_MASTER_INFO - eng "The master info structure does not exist" - -WARN_OPTION_IGNORED - eng "<%-.64s> option ignored" - -WARN_PLUGIN_DELETE_BUILTIN - eng "Built-in plugins cannot be deleted" - -WARN_PLUGIN_BUSY - eng "Plugin is busy and will be uninstalled on shutdown" - -ER_VARIABLE_IS_READONLY - eng "%s variable '%s' is read-only. Use SET %s to assign the value" - -ER_WARN_ENGINE_TRANSACTION_ROLLBACK - eng "Storage engine %s does not support rollback for this statement. Transaction rolled back and must be restarted" - -ER_SLAVE_HEARTBEAT_FAILURE - eng "Unexpected master's heartbeat data: %s" -ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE - eng "The requested value for the heartbeat period %s %s" - -ER_NDB_REPLICATION_SCHEMA_ERROR - eng "Bad schema for mysql.ndb_replication table. Message: %-.64s" -ER_CONFLICT_FN_PARSE_ERROR - eng "Error in parsing conflict function. Message: %-.64s" -ER_EXCEPTIONS_WRITE_ERROR - eng "Write to exceptions table failed. Message: %-.128s"" - -ER_TOO_LONG_TABLE_COMMENT - eng "Comment for table '%-.64s' is too long (max = %lu)" - por "Comentário para a tabela '%-.64s' é longo demais (max = %lu)" - -ER_TOO_LONG_FIELD_COMMENT - eng "Comment for field '%-.64s' is too long (max = %lu)" - por "Comentário para o campo '%-.64s' é longo demais (max = %lu)" - -ER_FUNC_INEXISTENT_NAME_COLLISION 42000 - eng "FUNCTION %s does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual" - -# When updating these, please update EXPLAIN_FILENAME_MAX_EXTRA_LENGTH in -# mysql_priv.h with the new maximal additional length for explain_filename. -ER_DATABASE_NAME - eng "Database" - swe "Databas" -ER_TABLE_NAME - eng "Table" - swe "Tabell" -ER_PARTITION_NAME - eng "Partition" - swe "Partition" -ER_SUBPARTITION_NAME - eng "Subpartition" - swe "Subpartition" -ER_TEMPORARY_NAME - eng "Temporary" - swe "Temporär" -ER_RENAMED_NAME - eng "Renamed" - swe "Namnändrad" -ER_TOO_MANY_CONCURRENT_TRXS - eng "Too many active concurrent transactions" - -WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED - eng "Non-ASCII separator arguments are not fully supported" - -ER_DEBUG_SYNC_TIMEOUT - eng "debug sync point wait timed out" - ger "Debug Sync Point Wartezeit überschritten" -ER_DEBUG_SYNC_HIT_LIMIT - eng "debug sync point hit limit reached" - ger "Debug Sync Point Hit Limit erreicht" - -ER_DUP_SIGNAL_SET 42000 - eng "Duplicate condition information item '%s'" - -# Note that the SQLSTATE is not 01000, it is provided by SIGNAL/RESIGNAL -ER_SIGNAL_WARN 01000 - eng "Unhandled user-defined warning condition" - -# Note that the SQLSTATE is not 02000, it is provided by SIGNAL/RESIGNAL -ER_SIGNAL_NOT_FOUND 02000 - eng "Unhandled user-defined not found condition" - -# Note that the SQLSTATE is not HY000, it is provided by SIGNAL/RESIGNAL -ER_SIGNAL_EXCEPTION HY000 - eng "Unhandled user-defined exception condition" - -ER_RESIGNAL_WITHOUT_ACTIVE_HANDLER 0K000 - eng "RESIGNAL when handler not active" - -ER_SIGNAL_BAD_CONDITION_TYPE - eng "SIGNAL/RESIGNAL can only use a CONDITION defined with SQLSTATE" - -WARN_COND_ITEM_TRUNCATED - eng "Data truncated for condition item '%s'" - -ER_COND_ITEM_TOO_LONG - eng "Data too long for condition item '%s'" - -ER_UNKNOWN_LOCALE - eng "Unknown locale: '%-.64s'" - -ER_SLAVE_IGNORE_SERVER_IDS - eng "The requested server id %d clashes with the slave startup option --replicate-same-server-id" -ER_QUERY_CACHE_DISABLED - eng "Query cache is disabled; restart the server with query_cache_type=1 to enable it" -ER_SAME_NAME_PARTITION_FIELD - eng "Duplicate partition field name '%-.192s'" -ER_PARTITION_COLUMN_LIST_ERROR - eng "Inconsistency in usage of column lists for partitioning" -ER_WRONG_TYPE_COLUMN_VALUE_ERROR - eng "Partition column values of incorrect type" -ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR - eng "Too many fields in '%-.192s'" -ER_MAXVALUE_IN_VALUES_IN - eng "Cannot use MAXVALUE as value in VALUES IN" -ER_TOO_MANY_VALUES_ERROR - eng "Cannot have more than one value for this type of %-.64s partitioning" -ER_ROW_SINGLE_PARTITION_FIELD_ERROR - eng "Row expressions in VALUES IN only allowed for multi-field column partitioning" -ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD - eng "Field '%-.192s' is of a not allowed type for this type of partitioning" -ER_PARTITION_FIELDS_TOO_LONG - eng "The total length of the partitioning fields is too large" diff --git a/sql/slave.cc b/sql/slave.cc index 3678c2497de..c7469d41a26 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -144,15 +144,12 @@ static int connect_to_master(THD* thd, MYSQL* mysql, Master_info* mi, bool reconnect, bool suppress_warnings); static int safe_sleep(THD* thd, int sec, CHECK_KILLED_FUNC thread_killed, void* thread_killed_arg); -static int request_table_dump(MYSQL* mysql, const char* db, const char* table); -static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db, - const char* table_name, bool overwrite); static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi); static Log_event* next_event(Relay_log_info* rli); static int queue_event(Master_info* mi,const char* buf,ulong event_len); static int terminate_slave_thread(THD *thd, - pthread_mutex_t *term_lock, - pthread_cond_t *term_cond, + mysql_mutex_t *term_lock, + mysql_cond_t *term_cond, volatile uint *slave_running, bool skip_lock); static bool check_io_slave_killed(THD *thd, Master_info *mi, const char *info); @@ -201,8 +198,8 @@ void lock_slave_threads(Master_info* mi) DBUG_ENTER("lock_slave_threads"); //TODO: see if we can do this without dual mutex - pthread_mutex_lock(&mi->run_lock); - pthread_mutex_lock(&mi->rli.run_lock); + mysql_mutex_lock(&mi->run_lock); + mysql_mutex_lock(&mi->rli.run_lock); DBUG_VOID_RETURN; } @@ -216,11 +213,32 @@ void unlock_slave_threads(Master_info* mi) DBUG_ENTER("unlock_slave_threads"); //TODO: see if we can do this without dual mutex - pthread_mutex_unlock(&mi->rli.run_lock); - pthread_mutex_unlock(&mi->run_lock); + mysql_mutex_unlock(&mi->rli.run_lock); + mysql_mutex_unlock(&mi->run_lock); DBUG_VOID_RETURN; } +#ifdef HAVE_PSI_INTERFACE +static PSI_thread_key key_thread_slave_io, key_thread_slave_sql; + +static PSI_thread_info all_slave_threads[]= +{ + { &key_thread_slave_io, "slave_io", PSI_FLAG_GLOBAL}, + { &key_thread_slave_sql, "slave_sql", PSI_FLAG_GLOBAL} +}; + +static void init_slave_psi_keys(void) +{ + const char* category= "sql"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_slave_threads); + PSI_server->register_thread(category, all_slave_threads, count); +} +#endif /* HAVE_PSI_INTERFACE */ /* Initialize slave structures */ @@ -229,12 +247,16 @@ int init_slave() DBUG_ENTER("init_slave"); int error= 0; +#ifdef HAVE_PSI_INTERFACE + init_slave_psi_keys(); +#endif + /* This is called when mysqld starts. Before client connections are accepted. However bootstrap may conflict with us if it does START SLAVE. So it's safer to take the lock. */ - pthread_mutex_lock(&LOCK_active_mi); + mysql_mutex_lock(&LOCK_active_mi); /* TODO: re-write this to interate through the list of files for multi-master @@ -266,19 +288,16 @@ int init_slave() } if (init_master_info(active_mi,master_info_file,relay_log_info_file, - !master_host, (SLAVE_IO | SLAVE_SQL))) + 1, (SLAVE_IO | SLAVE_SQL))) { sql_print_error("Failed to initialize the master info structure"); error= 1; goto err; } - if (server_id && !master_host && active_mi->host[0]) - master_host= active_mi->host; - /* If server id is not set, start_slave_thread() will say it */ - if (master_host && !opt_skip_slave_start) + if (active_mi->host[0] && !opt_skip_slave_start) { if (start_slave_threads(1 /* need mutex */, 0 /* no wait for start*/, @@ -294,7 +313,7 @@ int init_slave() } err: - pthread_mutex_unlock(&LOCK_active_mi); + mysql_mutex_unlock(&LOCK_active_mi); DBUG_RETURN(error); } @@ -368,6 +387,9 @@ static void print_slave_skip_errors(void) DBUG_ASSERT(sizeof(slave_skip_error_names) > MIN_ROOM); DBUG_ASSERT(MAX_SLAVE_ERROR <= 999999); // 6 digits + /* Make @@slave_skip_errors show the nice human-readable value. */ + opt_slave_skip_errors= slave_skip_error_names; + if (!use_slave_mask || bitmap_is_clear_all(&slave_error_mask)) { /* purecov: begin tested */ @@ -469,7 +491,8 @@ int terminate_slave_threads(Master_info* mi,int thread_mask,bool skip_lock) if (!mi->inited) DBUG_RETURN(0); /* successfully do nothing */ int error,force_all = (thread_mask & SLAVE_FORCE_ALL); - pthread_mutex_t *sql_lock = &mi->rli.run_lock, *io_lock = &mi->run_lock; + mysql_mutex_t *sql_lock = &mi->rli.run_lock, *io_lock = &mi->run_lock; + mysql_mutex_t *log_lock= mi->rli.relay_log.get_log_lock(); if (thread_mask & (SLAVE_IO|SLAVE_FORCE_ALL)) { @@ -481,6 +504,22 @@ int terminate_slave_threads(Master_info* mi,int thread_mask,bool skip_lock) skip_lock)) && !force_all) DBUG_RETURN(error); + + mysql_mutex_lock(log_lock); + + DBUG_PRINT("info",("Flushing relay log and master info file.")); + if (current_thd) + thd_proc_info(current_thd, "Flushing relay log and master info files."); + if (flush_master_info(mi, TRUE, FALSE)) + DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS); + + if (my_sync(mi->rli.relay_log.get_log_file()->file, MYF(MY_WME))) + DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS); + + if (my_sync(mi->fd, MYF(MY_WME))) + DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS); + + mysql_mutex_unlock(log_lock); } if (thread_mask & (SLAVE_SQL|SLAVE_FORCE_ALL)) { @@ -492,8 +531,21 @@ int terminate_slave_threads(Master_info* mi,int thread_mask,bool skip_lock) skip_lock)) && !force_all) DBUG_RETURN(error); + + mysql_mutex_lock(log_lock); + + DBUG_PRINT("info",("Flushing relay-log info file.")); + if (current_thd) + thd_proc_info(current_thd, "Flushing relay-log info file."); + if (flush_relay_log_info(&mi->rli)) + DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS); + + if (my_sync(mi->rli.info_fd, MYF(MY_WME))) + DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS); + + mysql_mutex_unlock(log_lock); } - DBUG_RETURN(0); + DBUG_RETURN(0); } @@ -533,19 +585,19 @@ int terminate_slave_threads(Master_info* mi,int thread_mask,bool skip_lock) */ static int terminate_slave_thread(THD *thd, - pthread_mutex_t *term_lock, - pthread_cond_t *term_cond, + mysql_mutex_t *term_lock, + mysql_cond_t *term_cond, volatile uint *slave_running, bool skip_lock) { DBUG_ENTER("terminate_slave_thread"); if (!skip_lock) { - pthread_mutex_lock(term_lock); + mysql_mutex_lock(term_lock); } else { - safe_mutex_assert_owner(term_lock); + mysql_mutex_assert_owner(term_lock); } if (!*slave_running) { @@ -555,7 +607,7 @@ terminate_slave_thread(THD *thd, if run_lock (term_lock) is acquired locally then either slave_running status is fine */ - pthread_mutex_unlock(term_lock); + mysql_mutex_unlock(term_lock); DBUG_RETURN(0); } else @@ -576,7 +628,7 @@ terminate_slave_thread(THD *thd, int error; DBUG_PRINT("loop", ("killing slave thread")); - pthread_mutex_lock(&thd->LOCK_thd_data); + mysql_mutex_lock(&thd->LOCK_thd_data); #ifndef DONT_USE_THR_ALARM /* Error codes from pthread_kill are: @@ -587,7 +639,7 @@ terminate_slave_thread(THD *thd, DBUG_ASSERT(err != EINVAL); #endif thd->awake(THD::NOT_KILLED); - pthread_mutex_unlock(&thd->LOCK_thd_data); + mysql_mutex_unlock(&thd->LOCK_thd_data); /* There is a small chance that slave thread might miss the first @@ -595,25 +647,28 @@ terminate_slave_thread(THD *thd, */ struct timespec abstime; set_timespec(abstime,2); - error= pthread_cond_timedwait(term_cond, term_lock, &abstime); + error= mysql_cond_timedwait(term_cond, term_lock, &abstime); DBUG_ASSERT(error == ETIMEDOUT || error == 0); } DBUG_ASSERT(*slave_running == 0); if (!skip_lock) - pthread_mutex_unlock(term_lock); + mysql_mutex_unlock(term_lock); DBUG_RETURN(0); } -int start_slave_thread(pthread_handler h_func, pthread_mutex_t *start_lock, - pthread_mutex_t *cond_lock, - pthread_cond_t *start_cond, +int start_slave_thread( +#ifdef HAVE_PSI_INTERFACE + PSI_thread_key thread_key, +#endif + pthread_handler h_func, mysql_mutex_t *start_lock, + mysql_mutex_t *cond_lock, + mysql_cond_t *start_cond, volatile uint *slave_running, volatile ulong *slave_run_id, - Master_info* mi, - bool high_priority) + Master_info* mi) { pthread_t th; ulong start_id; @@ -622,13 +677,13 @@ int start_slave_thread(pthread_handler h_func, pthread_mutex_t *start_lock, DBUG_ASSERT(mi->inited); if (start_lock) - pthread_mutex_lock(start_lock); + mysql_mutex_lock(start_lock); if (!server_id) { if (start_cond) - pthread_cond_broadcast(start_cond); + mysql_cond_broadcast(start_cond); if (start_lock) - pthread_mutex_unlock(start_lock); + mysql_mutex_unlock(start_lock); sql_print_error("Server id not set, will not start slave"); DBUG_RETURN(ER_BAD_SLAVE); } @@ -636,19 +691,18 @@ int start_slave_thread(pthread_handler h_func, pthread_mutex_t *start_lock, if (*slave_running) { if (start_cond) - pthread_cond_broadcast(start_cond); + mysql_cond_broadcast(start_cond); if (start_lock) - pthread_mutex_unlock(start_lock); + mysql_mutex_unlock(start_lock); DBUG_RETURN(ER_SLAVE_MUST_STOP); } start_id= *slave_run_id; DBUG_PRINT("info",("Creating new slave thread")); - if (high_priority) - my_pthread_attr_setprio(&connection_attrib,CONNECT_PRIOR); - if (pthread_create(&th, &connection_attrib, h_func, (void*)mi)) + if (mysql_thread_create(thread_key, + &th, &connection_attrib, h_func, (void*)mi)) { if (start_lock) - pthread_mutex_unlock(start_lock); + mysql_mutex_unlock(start_lock); DBUG_RETURN(ER_SLAVE_THREAD); } if (start_cond && cond_lock) // caller has cond_lock @@ -659,15 +713,19 @@ int start_slave_thread(pthread_handler h_func, pthread_mutex_t *start_lock, DBUG_PRINT("sleep",("Waiting for slave thread to start")); const char* old_msg = thd->enter_cond(start_cond,cond_lock, "Waiting for slave thread to start"); - pthread_cond_wait(start_cond,cond_lock); + mysql_cond_wait(start_cond, cond_lock); thd->exit_cond(old_msg); - pthread_mutex_lock(cond_lock); // re-acquire it as exit_cond() released + mysql_mutex_lock(cond_lock); // re-acquire it as exit_cond() released if (thd->killed) + { + if (start_lock) + mysql_mutex_unlock(start_lock); DBUG_RETURN(thd->killed_errno()); + } } } if (start_lock) - pthread_mutex_unlock(start_lock); + mysql_mutex_unlock(start_lock); DBUG_RETURN(0); } @@ -685,8 +743,8 @@ int start_slave_threads(bool need_slave_mutex, bool wait_for_start, Master_info* mi, const char* master_info_fname, const char* slave_info_fname, int thread_mask) { - pthread_mutex_t *lock_io=0,*lock_sql=0,*lock_cond_io=0,*lock_cond_sql=0; - pthread_cond_t* cond_io=0,*cond_sql=0; + mysql_mutex_t *lock_io=0, *lock_sql=0, *lock_cond_io=0, *lock_cond_sql=0; + mysql_cond_t* cond_io=0, *cond_sql=0; int error=0; DBUG_ENTER("start_slave_threads"); @@ -704,16 +762,24 @@ int start_slave_threads(bool need_slave_mutex, bool wait_for_start, } if (thread_mask & SLAVE_IO) - error=start_slave_thread(handle_slave_io,lock_io,lock_cond_io, - cond_io, - &mi->slave_running, &mi->slave_run_id, - mi, 1); //high priority, to read the most possible + error= start_slave_thread( +#ifdef HAVE_PSI_INTERFACE + key_thread_slave_io, +#endif + handle_slave_io, lock_io, lock_cond_io, + cond_io, + &mi->slave_running, &mi->slave_run_id, + mi); if (!error && (thread_mask & SLAVE_SQL)) { - error=start_slave_thread(handle_slave_sql,lock_sql,lock_cond_sql, - cond_sql, - &mi->rli.slave_running, &mi->rli.slave_run_id, - mi, 0); + error= start_slave_thread( +#ifdef HAVE_PSI_INTERFACE + key_thread_slave_sql, +#endif + handle_slave_sql, lock_sql, lock_cond_sql, + cond_sql, + &mi->rli.slave_running, &mi->rli.slave_run_id, + mi); if (error) terminate_slave_threads(mi, thread_mask & SLAVE_IO, !need_slave_mutex); } @@ -750,7 +816,7 @@ void end_slave() will make us wait until slave threads have started, and START SLAVE returns, then we terminate them here. */ - pthread_mutex_lock(&LOCK_active_mi); + mysql_mutex_lock(&LOCK_active_mi); if (active_mi) { /* @@ -760,7 +826,7 @@ void end_slave() */ terminate_slave_threads(active_mi,SLAVE_FORCE_ALL); } - pthread_mutex_unlock(&LOCK_active_mi); + mysql_mutex_unlock(&LOCK_active_mi); DBUG_VOID_RETURN; } @@ -775,14 +841,14 @@ void end_slave() */ void close_active_mi() { - pthread_mutex_lock(&LOCK_active_mi); + mysql_mutex_lock(&LOCK_active_mi); if (active_mi) { end_master_info(active_mi); delete active_mi; active_mi= 0; } - pthread_mutex_unlock(&LOCK_active_mi); + mysql_mutex_unlock(&LOCK_active_mi); } static bool io_slave_killed(THD* thd, Master_info* mi) @@ -1045,7 +1111,7 @@ int init_dynarray_intvar_from_file(DYNAMIC_ARRAY* arr, IO_CACHE* f) memcpy(buf_act, buf, read_size); snd_size= my_b_gets(f, buf_act + read_size, max_size - read_size); if (snd_size == 0 || - (snd_size + 1 == max_size - read_size) && buf[max_size - 2] != '\n') + ((snd_size + 1 == max_size - read_size) && buf[max_size - 2] != '\n')) { /* failure to make the 2nd read or short read again @@ -1082,17 +1148,6 @@ err: } -static bool check_io_slave_killed(THD *thd, Master_info *mi, const char *info) -{ - if (io_slave_killed(thd, mi)) - { - if (info && global_system_variables.log_warnings) - sql_print_information("%s", info); - return TRUE; - } - return FALSE; -} - /* Check if the error is caused by network. @param[in] errorno Number of the error. @@ -1222,6 +1277,8 @@ static int get_master_version_and_clock(MYSQL* mysql, Master_info* mi) mi->clock_diff_with_master= (long) (time((time_t*) 0) - strtoul(master_row[0], 0, 10)); } + else if (check_io_slave_killed(mi->io_thd, mi, NULL)) + goto slave_killed_err; else if (is_network_error(mysql_errno(mysql))) { mi->report(WARNING_LEVEL, mysql_errno(mysql), @@ -1274,7 +1331,9 @@ not always make sense; please check the manual before using it)."; } else if (mysql_errno(mysql)) { - if (is_network_error(mysql_errno(mysql))) + if (check_io_slave_killed(mi->io_thd, mi, NULL)) + goto slave_killed_err; + else if (is_network_error(mysql_errno(mysql))) { mi->report(WARNING_LEVEL, mysql_errno(mysql), "Get master SERVER_ID failed with error: %s", mysql_error(mysql)); @@ -1345,6 +1404,8 @@ be equal for the Statement-format replication to work"; goto err; } } + else if (check_io_slave_killed(mi->io_thd, mi, NULL)) + goto slave_killed_err; else if (is_network_error(mysql_errno(mysql))) { mi->report(WARNING_LEVEL, mysql_errno(mysql), @@ -1406,6 +1467,8 @@ be equal for the Statement-format replication to work"; goto err; } } + else if (check_io_slave_killed(mi->io_thd, mi, NULL)) + goto slave_killed_err; else if (is_network_error(mysql_errno(mysql))) { mi->report(WARNING_LEVEL, mysql_errno(mysql), @@ -1469,201 +1532,13 @@ network_err: if (master_res) mysql_free_result(master_res); DBUG_RETURN(2); -} - -/* - Used by fetch_master_table (used by LOAD TABLE tblname FROM MASTER and LOAD - DATA FROM MASTER). Drops the table (if 'overwrite' is true) and recreates it - from the dump. Honours replication inclusion/exclusion rules. - db must be non-zero (guarded by assertion). - - RETURN VALUES - 0 success - 1 error -*/ - -static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db, - const char* table_name, bool overwrite) -{ - ulong packet_len; - char *query, *save_db; - uint32 save_db_length; - Vio* save_vio; - HA_CHECK_OPT check_opt; - TABLE_LIST tables; - int error= 1; - handler *file; - ulonglong save_options; - NET *net= &mysql->net; - const char *found_semicolon= NULL; - DBUG_ENTER("create_table_from_dump"); - - packet_len= my_net_read(net); // read create table statement - if (packet_len == packet_error) - { - my_message(ER_MASTER_NET_READ, ER(ER_MASTER_NET_READ), MYF(0)); - DBUG_RETURN(1); - } - if (net->read_pos[0] == 255) // error from master - { - char *err_msg; - err_msg= (char*) net->read_pos + ((mysql->server_capabilities & - CLIENT_PROTOCOL_41) ? - 3+SQLSTATE_LENGTH+1 : 3); - my_error(ER_MASTER, MYF(0), err_msg); - DBUG_RETURN(1); - } - thd->command = COM_TABLE_DUMP; - if (!(query = thd->strmake((char*) net->read_pos, packet_len))) - { - sql_print_error("create_table_from_dump: out of memory"); - my_message(ER_GET_ERRNO, "Out of memory", MYF(0)); - DBUG_RETURN(1); - } - thd->set_query(query, packet_len); - thd->is_slave_error = 0; - - bzero((char*) &tables,sizeof(tables)); - tables.db = (char*)db; - tables.alias= tables.table_name= (char*)table_name; - - /* Drop the table if 'overwrite' is true */ - if (overwrite) - { - if (mysql_rm_table(thd,&tables,1,0)) /* drop if exists */ - { - sql_print_error("create_table_from_dump: failed to drop the table"); - goto err; - } - else - { - /* Clear the OK result of mysql_rm_table(). */ - thd->stmt_da->reset_diagnostics_area(); - } - } - - /* Create the table. We do not want to log the "create table" statement */ - save_options = thd->options; - thd->options &= ~ (OPTION_BIN_LOG); - thd_proc_info(thd, "Creating table from master dump"); - // save old db in case we are creating in a different database - save_db = thd->db; - save_db_length= thd->db_length; - thd->db = (char*)db; - DBUG_ASSERT(thd->db != 0); - thd->db_length= strlen(thd->db); - /* run create table */ - mysql_parse(thd, thd->query(), packet_len, &found_semicolon); - thd->db = save_db; // leave things the way the were before - thd->db_length= save_db_length; - thd->options = save_options; - - if (thd->is_slave_error) - goto err; // mysql_parse took care of the error send - - thd_proc_info(thd, "Opening master dump table"); - thd->stmt_da->reset_diagnostics_area(); /* cleanup from CREATE_TABLE */ - /* - Note: If this function starts to fail for MERGE tables, - change the next two lines to these: - tables.table= NULL; // was set by mysql_rm_table() - if (!open_n_lock_single_table(thd, &tables, TL_WRITE)) - */ - tables.lock_type = TL_WRITE; - if (!open_ltable(thd, &tables, TL_WRITE, 0)) - { - sql_print_error("create_table_from_dump: could not open created table"); - goto err; - } - - file = tables.table->file; - thd_proc_info(thd, "Reading master dump table data"); - /* Copy the data file */ - if (file->net_read_dump(net)) - { - my_message(ER_MASTER_NET_READ, ER(ER_MASTER_NET_READ), MYF(0)); - sql_print_error("create_table_from_dump: failed in\ - handler::net_read_dump()"); - goto err; - } - - check_opt.init(); - check_opt.flags|= T_VERY_SILENT | T_CALC_CHECKSUM | T_QUICK; - thd_proc_info(thd, "Rebuilding the index on master dump table"); - /* - We do not want repair() to spam us with messages - just send them to the error log, and report the failure in case of - problems. - */ - save_vio = thd->net.vio; - thd->net.vio = 0; - /* Rebuild the index file from the copied data file (with REPAIR) */ - error=file->ha_repair(thd,&check_opt) != 0; - thd->net.vio = save_vio; - if (error) - my_error(ER_INDEX_REBUILD, MYF(0), tables.table->s->table_name.str); - -err: - close_thread_tables(thd); - DBUG_RETURN(error); -} - - -int fetch_master_table(THD *thd, const char *db_name, const char *table_name, - Master_info *mi, MYSQL *mysql, bool overwrite) -{ - int error= 1; - const char *errmsg=0; - bool called_connected= (mysql != NULL); - DBUG_ENTER("fetch_master_table"); - DBUG_PRINT("enter", ("db_name: '%s' table_name: '%s'", - db_name,table_name)); - - if (!called_connected) - { - if (!(mysql = mysql_init(NULL))) - { - DBUG_RETURN(1); - } - if (connect_to_master(thd, mysql, mi)) - { - my_error(ER_CONNECT_TO_MASTER, MYF(0), mysql_error(mysql)); - /* - We need to clear the active VIO since, theoretically, somebody - might issue an awake() on this thread. If we are then in the - middle of closing and destroying the VIO inside the - mysql_close(), we will have a problem. - */ -#ifdef SIGNAL_WITH_VIO_CLOSE - thd->clear_active_vio(); -#endif - mysql_close(mysql); - DBUG_RETURN(1); - } - if (thd->killed) - goto err; - } - - if (request_table_dump(mysql, db_name, table_name)) - { - error= ER_UNKNOWN_ERROR; - errmsg= "Failed on table dump request"; - goto err; - } - if (create_table_from_dump(thd, mysql, db_name, - table_name, overwrite)) - goto err; // create_table_from_dump have sent the error already - error = 0; - err: - if (!called_connected) - mysql_close(mysql); - if (errmsg && thd->vio_ok()) - my_message(error, errmsg, MYF(0)); - DBUG_RETURN(test(error)); // Return 1 on error +slave_killed_err: + if (master_res) + mysql_free_result(master_res); + DBUG_RETURN(2); } - static bool wait_for_relay_log_space(Relay_log_info* rli) { bool slave_killed=0; @@ -1672,7 +1547,7 @@ static bool wait_for_relay_log_space(Relay_log_info* rli) THD* thd = mi->io_thd; DBUG_ENTER("wait_for_relay_log_space"); - pthread_mutex_lock(&rli->log_space_lock); + mysql_mutex_lock(&rli->log_space_lock); save_proc_info= thd->enter_cond(&rli->log_space_cond, &rli->log_space_lock, "\ @@ -1680,7 +1555,7 @@ Waiting for the slave SQL thread to free enough relay log space"); while (rli->log_space_limit < rli->log_space_total && !(slave_killed=io_slave_killed(thd,mi)) && !rli->ignore_log_space_limit) - pthread_cond_wait(&rli->log_space_cond, &rli->log_space_lock); + mysql_cond_wait(&rli->log_space_cond, &rli->log_space_lock); thd->exit_cond(save_proc_info); DBUG_RETURN(slave_killed); } @@ -1702,11 +1577,11 @@ Waiting for the slave SQL thread to free enough relay log space"); static void write_ignored_events_info_to_relay_log(THD *thd, Master_info *mi) { Relay_log_info *rli= &mi->rli; - pthread_mutex_t *log_lock= rli->relay_log.get_log_lock(); + mysql_mutex_t *log_lock= rli->relay_log.get_log_lock(); DBUG_ENTER("write_ignored_events_info_to_relay_log"); DBUG_ASSERT(thd == mi->io_thd); - pthread_mutex_lock(log_lock); + mysql_mutex_lock(log_lock); if (rli->ign_master_log_name_end[0]) { DBUG_PRINT("info",("writing a Rotate event to track down ignored events")); @@ -1715,7 +1590,7 @@ static void write_ignored_events_info_to_relay_log(THD *thd, Master_info *mi) Rotate_log_event::DUP_NAME); rli->ign_master_log_name_end[0]= 0; /* can unlock before writing as slave SQL thd will soon see our Rotate */ - pthread_mutex_unlock(log_lock); + mysql_mutex_unlock(log_lock); if (likely((bool)ev)) { ev->server_id= 0; // don't be ignored by slave SQL thread @@ -1737,7 +1612,7 @@ static void write_ignored_events_info_to_relay_log(THD *thd, Master_info *mi) " SHOW SLAVE STATUS may be inaccurate"); } else - pthread_mutex_unlock(log_lock); + mysql_mutex_unlock(log_lock); DBUG_VOID_RETURN; } @@ -1746,28 +1621,54 @@ int register_slave_on_master(MYSQL* mysql, Master_info *mi, bool *suppress_warnings) { uchar buf[1024], *pos= buf; - uint report_host_len, report_user_len=0, report_password_len=0; + uint report_host_len=0, report_user_len=0, report_password_len=0; DBUG_ENTER("register_slave_on_master"); *suppress_warnings= FALSE; - if (!report_host) + if (report_host) + report_host_len= strlen(report_host); + if (report_host_len > HOSTNAME_LENGTH) + { + sql_print_warning("The length of report_host is %d. " + "It is larger than the max length(%d), so this " + "slave cannot be registered to the master.", + report_host_len, HOSTNAME_LENGTH); DBUG_RETURN(0); - report_host_len= strlen(report_host); + } + if (report_user) report_user_len= strlen(report_user); + if (report_user_len > USERNAME_LENGTH) + { + sql_print_warning("The length of report_user is %d. " + "It is larger than the max length(%d), so this " + "slave cannot be registered to the master.", + report_user_len, USERNAME_LENGTH); + DBUG_RETURN(0); + } + if (report_password) report_password_len= strlen(report_password); - /* 30 is a good safety margin */ - if (report_host_len + report_user_len + report_password_len + 30 > - sizeof(buf)) - DBUG_RETURN(0); // safety + if (report_password_len > MAX_PASSWORD_LENGTH) + { + sql_print_warning("The length of report_password is %d. " + "It is larger than the max length(%d), so this " + "slave cannot be registered to the master.", + report_password_len, MAX_PASSWORD_LENGTH); + DBUG_RETURN(0); + } int4store(pos, server_id); pos+= 4; pos= net_store_data(pos, (uchar*) report_host, report_host_len); pos= net_store_data(pos, (uchar*) report_user, report_user_len); pos= net_store_data(pos, (uchar*) report_password, report_password_len); int2store(pos, (uint16) report_port); pos+= 2; - int4store(pos, rpl_recovery_rank); pos+= 4; + /* + Fake rpl_recovery_rank, which was removed in BUG#13963, + so that this server can register itself on old servers, + see BUG#49259. + */ + int4store(pos, /* rpl_recovery_rank */ 0); pos+= 4; /* The master will fill in master_id */ int4store(pos, 0); pos+= 4; @@ -1888,14 +1789,14 @@ bool show_master_info(THD* thd, Master_info* mi) slave_running can be accessed without run_lock but not other non-volotile members like mi->io_thd, which is guarded by the mutex. */ - pthread_mutex_lock(&mi->run_lock); + mysql_mutex_lock(&mi->run_lock); protocol->store(mi->io_thd ? mi->io_thd->proc_info : "", &my_charset_bin); - pthread_mutex_unlock(&mi->run_lock); + mysql_mutex_unlock(&mi->run_lock); - pthread_mutex_lock(&mi->data_lock); - pthread_mutex_lock(&mi->rli.data_lock); - pthread_mutex_lock(&mi->err_lock); - pthread_mutex_lock(&mi->rli.err_lock); + mysql_mutex_lock(&mi->data_lock); + mysql_mutex_lock(&mi->rli.data_lock); + mysql_mutex_lock(&mi->err_lock); + mysql_mutex_lock(&mi->rli.err_lock); protocol->store(mi->host, &my_charset_bin); protocol->store(mi->user, &my_charset_bin); protocol->store((uint32) mi->port); @@ -2022,10 +1923,10 @@ bool show_master_info(THD* thd, Master_info* mi) // Master_Server_id protocol->store((uint32) mi->master_id); - pthread_mutex_unlock(&mi->rli.err_lock); - pthread_mutex_unlock(&mi->err_lock); - pthread_mutex_unlock(&mi->rli.data_lock); - pthread_mutex_unlock(&mi->data_lock); + mysql_mutex_unlock(&mi->rli.err_lock); + mysql_mutex_unlock(&mi->err_lock); + mysql_mutex_unlock(&mi->rli.data_lock); + mysql_mutex_unlock(&mi->data_lock); if (my_net_write(&thd->net, (uchar*) thd->packet.ptr(), packet->length())) DBUG_RETURN(TRUE); @@ -2047,12 +1948,12 @@ void set_slave_thread_options(THD* thd) when max_join_size is 4G, OPTION_BIG_SELECTS is automatically set, but only for client threads. */ - ulonglong options= thd->options | OPTION_BIG_SELECTS; + ulonglong options= thd->variables.option_bits | OPTION_BIG_SELECTS; if (opt_log_slave_updates) options|= OPTION_BIN_LOG; else options&= ~OPTION_BIN_LOG; - thd->options= options; + thd->variables.option_bits= options; thd->variables.completion_type= 0; DBUG_VOID_RETURN; } @@ -2104,9 +2005,9 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) thd->enable_slow_log= opt_log_slow_slave_statements; set_slave_thread_options(thd); thd->client_capabilities = CLIENT_LOCAL_FILES; - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); DBUG_EXECUTE_IF("simulate_io_slave_error_on_init", simulate_error|= (1 << SLAVE_THD_IO);); @@ -2121,7 +2022,6 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) thd->cleanup(); DBUG_RETURN(-1); } - lex_start(thd); if (thd_type == SLAVE_THD_SQL) thd_proc_info(thd, "Waiting for the next event in relay log"); @@ -2198,37 +2098,7 @@ static int request_dump(THD *thd, MYSQL* mysql, Master_info* mi, else sql_print_error("Error on COM_BINLOG_DUMP: %d %s, will retry in %d secs", mysql_errno(mysql), mysql_error(mysql), - master_connect_retry); - DBUG_RETURN(1); - } - - DBUG_RETURN(0); -} - - -static int request_table_dump(MYSQL* mysql, const char* db, const char* table) -{ - uchar buf[1024], *p = buf; - DBUG_ENTER("request_table_dump"); - - uint table_len = (uint) strlen(table); - uint db_len = (uint) strlen(db); - if (table_len + db_len > sizeof(buf) - 2) - { - sql_print_error("request_table_dump: Buffer overrun"); - DBUG_RETURN(1); - } - - *p++ = db_len; - memcpy(p, db, db_len); - p += db_len; - *p++ = table_len; - memcpy(p, table, table_len); - - if (simple_command(mysql, COM_TABLE_DUMP, buf, p - buf + table_len, 1)) - { - sql_print_error("request_table_dump: Error sending the table dump \ -command"); + mi->connect_retry); DBUG_RETURN(1); } @@ -2394,8 +2264,8 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli) ev->get_type_str(), ev->get_type_code(), ev->server_id)); DBUG_PRINT("info", ("thd->options: %s%s; rli->last_event_start_time: %lu", - FLAGSTR(thd->options, OPTION_NOT_AUTOCOMMIT), - FLAGSTR(thd->options, OPTION_BEGIN), + FLAGSTR(thd->variables.option_bits, OPTION_NOT_AUTOCOMMIT), + FLAGSTR(thd->variables.option_bits, OPTION_BEGIN), rli->last_event_start_time)); /* @@ -2431,8 +2301,8 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli) int reason= ev->shall_skip(rli); if (reason == Log_event::EVENT_SKIP_COUNT) - --rli->slave_skip_counter; - pthread_mutex_unlock(&rli->data_lock); + sql_slave_skip_counter= --rli->slave_skip_counter; + mysql_mutex_unlock(&rli->data_lock); if (reason == Log_event::EVENT_SKIP_NOT) exec_res= ev->apply_event(rli); @@ -2451,7 +2321,7 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli) "skipped because event skip counter was non-zero" }; DBUG_PRINT("info", ("OPTION_BEGIN: %d; IN_STMT: %d", - thd->options & OPTION_BEGIN ? 1 : 0, + test(thd->variables.option_bits & OPTION_BEGIN), rli->get_flag(Relay_log_info::IN_STMT))); DBUG_PRINT("skip_event", ("%s event was %s", ev->get_type_str(), explain[reason])); @@ -2538,7 +2408,7 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli) event execution. But we will release it in places where we will wait for something for example inside of next_event(). */ - pthread_mutex_lock(&rli->data_lock); + mysql_mutex_lock(&rli->data_lock); Log_event * ev = next_event(rli); @@ -2546,7 +2416,7 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli) if (sql_slave_killed(thd,rli)) { - pthread_mutex_unlock(&rli->data_lock); + mysql_mutex_unlock(&rli->data_lock); delete ev; DBUG_RETURN(1); } @@ -2569,7 +2439,7 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli) error in query execution to be printed. */ rli->abort_slave= 1; - pthread_mutex_unlock(&rli->data_lock); + mysql_mutex_unlock(&rli->data_lock); delete ev; DBUG_RETURN(1); } @@ -2587,7 +2457,7 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli) { DBUG_ASSERT(thd->transaction.all.modified_non_trans_table); rli->abort_slave= 1; - pthread_mutex_unlock(&rli->data_lock); + mysql_mutex_unlock(&rli->data_lock); delete ev; rli->inc_event_relay_log_pos(); DBUG_RETURN(0); @@ -2651,10 +2521,10 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli) /* chance for concurrent connection to get more locks */ safe_sleep(thd, min(rli->trans_retries, MAX_SLAVE_RETRY_PAUSE), (CHECK_KILLED_FUNC)sql_slave_killed, (void*)rli); - pthread_mutex_lock(&rli->data_lock); // because of SHOW STATUS + mysql_mutex_lock(&rli->data_lock); // because of SHOW STATUS rli->trans_retries++; rli->retried_trans++; - pthread_mutex_unlock(&rli->data_lock); + mysql_mutex_unlock(&rli->data_lock); DBUG_PRINT("info", ("Slave retries transaction " "rli->trans_retries: %lu", rli->trans_retries)); } @@ -2682,7 +2552,7 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli) } DBUG_RETURN(exec_res); } - pthread_mutex_unlock(&rli->data_lock); + mysql_mutex_unlock(&rli->data_lock); rli->report(ERROR_LEVEL, ER_SLAVE_RELAY_LOG_READ_FAILURE, ER(ER_SLAVE_RELAY_LOG_READ_FAILURE), "\ Could not parse relay log event entry. The possible reasons are: the master's \ @@ -2697,6 +2567,17 @@ on this slave.\ } +static bool check_io_slave_killed(THD *thd, Master_info *mi, const char *info) +{ + if (io_slave_killed(thd, mi)) + { + if (info && global_system_variables.log_warnings) + sql_print_information("%s", info); + return TRUE; + } + return FALSE; +} + /** @brief Try to reconnect slave IO thread. @@ -2802,7 +2683,7 @@ pthread_handler_t handle_slave_io(void *arg) mysql= NULL ; retry_count= 0; - pthread_mutex_lock(&mi->run_lock); + mysql_mutex_lock(&mi->run_lock); /* Inform waiting threads that slave has started */ mi->slave_run_id++; @@ -2819,18 +2700,18 @@ pthread_handler_t handle_slave_io(void *arg) mi->clear_error(); if (init_slave_thread(thd, SLAVE_THD_IO)) { - pthread_cond_broadcast(&mi->start_cond); - pthread_mutex_unlock(&mi->run_lock); + mysql_cond_broadcast(&mi->start_cond); + mysql_mutex_unlock(&mi->run_lock); sql_print_error("Failed during slave I/O thread initialization"); goto err; } - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); threads.append(thd); - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); mi->slave_running = 1; mi->abort_slave = 0; - pthread_mutex_unlock(&mi->run_lock); - pthread_cond_broadcast(&mi->start_cond); + mysql_mutex_unlock(&mi->run_lock); + mysql_cond_broadcast(&mi->start_cond); DBUG_PRINT("master_info",("log_file_name: '%s' position: %s", mi->master_log_name, @@ -2885,7 +2766,7 @@ connected: if (ret == 1) /* Fatal error */ goto err; - + if (ret == 2) { if (check_io_slave_killed(mi->io_thd, mi, "Slave I/O thread killed" @@ -3113,7 +2994,7 @@ err: } write_ignored_events_info_to_relay_log(thd, mi); thd_proc_info(thd, "Waiting for slave mutex on exit"); - pthread_mutex_lock(&mi->run_lock); + mysql_mutex_lock(&mi->run_lock); /* Forget the relay log's format */ delete mi->rli.relay_log.description_event_for_queue; @@ -3123,10 +3004,10 @@ err: DBUG_ASSERT(thd->net.buff != 0); net_end(&thd->net); // destructor will not free it, because net.vio is 0 close_thread_tables(thd); - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); THD_CHECK_SENTRY(thd); delete thd; - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); mi->abort_slave= 0; mi->slave_running= 0; mi->io_thd= 0; @@ -3135,9 +3016,9 @@ err: is important. Otherwise a killer_thread can execute between the calls and delete the mi structure leading to a crash! (see BUG#25306 for details) */ - pthread_cond_broadcast(&mi->stop_cond); // tell the world we are done + mysql_cond_broadcast(&mi->stop_cond); // tell the world we are done DBUG_EXECUTE_IF("simulate_slave_delay_at_terminate_bug38694", sleep(5);); - pthread_mutex_unlock(&mi->run_lock); + mysql_mutex_unlock(&mi->run_lock); DBUG_LEAVE; // Must match DBUG_ENTER() my_thread_end(); @@ -3174,16 +3055,17 @@ int check_temp_dir(char* tmp_file) /* Check permissions to create a file. */ - if ((fd= my_create(tmp_file, CREATE_MODE, - O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW, - MYF(MY_WME))) < 0) + if ((fd= mysql_file_create(key_file_misc, + tmp_file, CREATE_MODE, + O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW, + MYF(MY_WME))) < 0) DBUG_RETURN(1); /* Clean up. */ - my_close(fd, MYF(0)); - my_delete(tmp_file, MYF(0)); + mysql_file_close(fd, MYF(0)); + mysql_file_delete(key_file_misc, tmp_file, MYF(0)); DBUG_RETURN(0); } @@ -3209,7 +3091,7 @@ pthread_handler_t handle_slave_sql(void *arg) DBUG_ENTER("handle_slave_sql"); DBUG_ASSERT(rli->inited); - pthread_mutex_lock(&rli->run_lock); + mysql_mutex_lock(&rli->run_lock); DBUG_ASSERT(!rli->slave_running); errmsg= 0; #ifndef DBUG_OFF @@ -3231,8 +3113,8 @@ pthread_handler_t handle_slave_sql(void *arg) TODO: this is currently broken - slave start and change master will be stuck if we fail here */ - pthread_cond_broadcast(&rli->start_cond); - pthread_mutex_unlock(&rli->run_lock); + mysql_cond_broadcast(&rli->start_cond); + mysql_mutex_unlock(&rli->run_lock); rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, "Failed during slave thread initialization"); goto err; @@ -3240,9 +3122,9 @@ pthread_handler_t handle_slave_sql(void *arg) thd->init_for_queries(); thd->temporary_tables = rli->save_temporary_tables; // restore temp tables set_thd_in_use_temporary_tables(rli); // (re)set sql_thd in use for saved temp tables - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); threads.append(thd); - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); /* We are going to set slave_running to 1. Assuming slave I/O thread is alive and connected, this is going to make Seconds_Behind_Master be 0 @@ -3252,8 +3134,8 @@ pthread_handler_t handle_slave_sql(void *arg) Seconds_Behind_Master grows. No big deal. */ rli->abort_slave = 0; - pthread_mutex_unlock(&rli->run_lock); - pthread_cond_broadcast(&rli->start_cond); + mysql_mutex_unlock(&rli->run_lock); + mysql_cond_broadcast(&rli->start_cond); /* Reset errors for a clean start (otherwise, if the master is idle, the SQL @@ -3268,9 +3150,9 @@ pthread_handler_t handle_slave_sql(void *arg) rli->clear_error(); //tell the I/O thread to take relay_log_space_limit into account from now on - pthread_mutex_lock(&rli->log_space_lock); + mysql_mutex_lock(&rli->log_space_lock); rli->ignore_log_space_limit= 0; - pthread_mutex_unlock(&rli->log_space_lock); + mysql_mutex_unlock(&rli->log_space_lock); rli->trans_retries= 0; // start from "no error" DBUG_PRINT("info", ("rli->trans_retries: %lu", rli->trans_retries)); @@ -3329,9 +3211,9 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME, } /* execute init_slave variable */ - if (sys_init_slave.value_length) + if (opt_init_slave.length) { - execute_init_command(thd, &sys_init_slave, &LOCK_sys_init_slave); + execute_init_command(thd, &opt_init_slave, &LOCK_sys_init_slave); if (thd->is_slave_error) { rli->report(ERROR_LEVEL, thd->stmt_da->sql_errno(), @@ -3344,17 +3226,17 @@ log '%s' at position %s, relay log '%s' position: %s", RPL_LOG_NAME, First check until condition - probably there is nothing to execute. We do not want to wait for next event in this case. */ - pthread_mutex_lock(&rli->data_lock); + mysql_mutex_lock(&rli->data_lock); if (rli->until_condition != Relay_log_info::UNTIL_NONE && rli->is_until_satisfied(thd, NULL)) { char buf[22]; sql_print_information("Slave SQL thread stopped because it reached its" " UNTIL position %s", llstr(rli->until_pos(), buf)); - pthread_mutex_unlock(&rli->data_lock); + mysql_mutex_unlock(&rli->data_lock); goto err; } - pthread_mutex_unlock(&rli->data_lock); + mysql_mutex_unlock(&rli->data_lock); /* Read queries from the IO/THREAD until this thread is killed */ @@ -3457,9 +3339,9 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ thd->set_query(NULL, 0); thd->reset_db(NULL, 0); thd_proc_info(thd, "Waiting for slave mutex on exit"); - pthread_mutex_lock(&rli->run_lock); + mysql_mutex_lock(&rli->run_lock); /* We need data_lock, at least to wake up any waiting master_pos_wait() */ - pthread_mutex_lock(&rli->data_lock); + mysql_mutex_lock(&rli->data_lock); DBUG_ASSERT(rli->slave_running == 1); // tracking buffer overrun /* When master_pos_wait() wakes up it will check this and terminate */ rli->slave_running= 0; @@ -3467,9 +3349,9 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ delete rli->relay_log.description_event_for_exec; rli->relay_log.description_event_for_exec= 0; /* Wake up master_pos_wait() */ - pthread_mutex_unlock(&rli->data_lock); + mysql_mutex_unlock(&rli->data_lock); DBUG_PRINT("info",("Signaling possibly waiting master_pos_wait() functions")); - pthread_cond_broadcast(&rli->data_cond); + mysql_cond_broadcast(&rli->data_cond); rli->ignore_log_space_limit= 0; /* don't need any lock */ /* we die so won't remember charset - re-update them on next thread start */ rli->cached_charset_invalidate(); @@ -3486,18 +3368,18 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \ THD_CHECK_SENTRY(thd); rli->sql_thd= 0; set_thd_in_use_temporary_tables(rli); // (re)set sql_thd in use for saved temp tables - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); THD_CHECK_SENTRY(thd); delete thd; - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); /* Note: the order of the broadcast and unlock calls below (first broadcast, then unlock) is important. Otherwise a killer_thread can execute between the calls and delete the mi structure leading to a crash! (see BUG#25306 for details) */ - pthread_cond_broadcast(&rli->stop_cond); + mysql_cond_broadcast(&rli->stop_cond); DBUG_EXECUTE_IF("simulate_slave_delay_at_terminate_bug38694", sleep(5);); - pthread_mutex_unlock(&rli->run_lock); // tell the world we are done + mysql_mutex_unlock(&rli->run_lock); // tell the world we are done DBUG_LEAVE; // Must match DBUG_ENTER() my_thread_end(); @@ -3640,7 +3522,7 @@ err: static int process_io_rotate(Master_info *mi, Rotate_log_event *rev) { DBUG_ENTER("process_io_rotate"); - safe_mutex_assert_owner(&mi->data_lock); + mysql_mutex_assert_owner(&mi->data_lock); if (unlikely(!rev->is_valid())) DBUG_RETURN(1); @@ -3736,7 +3618,7 @@ static int queue_binlog_ver_1_event(Master_info *mi, const char *buf, DBUG_RETURN(1); } - pthread_mutex_lock(&mi->data_lock); + mysql_mutex_lock(&mi->data_lock); ev->log_pos= mi->master_log_pos; /* 3.23 events don't contain log_pos */ switch (ev->get_type_code()) { case STOP_EVENT: @@ -3747,7 +3629,7 @@ static int queue_binlog_ver_1_event(Master_info *mi, const char *buf, if (unlikely(process_io_rotate(mi,(Rotate_log_event*)ev))) { delete ev; - pthread_mutex_unlock(&mi->data_lock); + mysql_mutex_unlock(&mi->data_lock); DBUG_RETURN(1); } inc_pos= 0; @@ -3768,7 +3650,7 @@ static int queue_binlog_ver_1_event(Master_info *mi, const char *buf, delete ev; mi->master_log_pos += inc_pos; DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos)); - pthread_mutex_unlock(&mi->data_lock); + mysql_mutex_unlock(&mi->data_lock); my_free((char*)tmp_buf, MYF(0)); DBUG_RETURN(error); } @@ -3787,7 +3669,7 @@ static int queue_binlog_ver_1_event(Master_info *mi, const char *buf, if (unlikely(rli->relay_log.append(ev))) { delete ev; - pthread_mutex_unlock(&mi->data_lock); + mysql_mutex_unlock(&mi->data_lock); DBUG_RETURN(1); } rli->relay_log.harvest_bytes_written(&rli->log_space_total); @@ -3795,7 +3677,7 @@ static int queue_binlog_ver_1_event(Master_info *mi, const char *buf, delete ev; mi->master_log_pos+= inc_pos; DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos)); - pthread_mutex_unlock(&mi->data_lock); + mysql_mutex_unlock(&mi->data_lock); DBUG_RETURN(0); } @@ -3823,7 +3705,7 @@ static int queue_binlog_ver_3_event(Master_info *mi, const char *buf, my_free((char*) tmp_buf, MYF(MY_ALLOW_ZERO_PTR)); DBUG_RETURN(1); } - pthread_mutex_lock(&mi->data_lock); + mysql_mutex_lock(&mi->data_lock); switch (ev->get_type_code()) { case STOP_EVENT: goto err; @@ -3831,7 +3713,7 @@ static int queue_binlog_ver_3_event(Master_info *mi, const char *buf, if (unlikely(process_io_rotate(mi,(Rotate_log_event*)ev))) { delete ev; - pthread_mutex_unlock(&mi->data_lock); + mysql_mutex_unlock(&mi->data_lock); DBUG_RETURN(1); } inc_pos= 0; @@ -3843,7 +3725,7 @@ static int queue_binlog_ver_3_event(Master_info *mi, const char *buf, if (unlikely(rli->relay_log.append(ev))) { delete ev; - pthread_mutex_unlock(&mi->data_lock); + mysql_mutex_unlock(&mi->data_lock); DBUG_RETURN(1); } rli->relay_log.harvest_bytes_written(&rli->log_space_total); @@ -3851,7 +3733,7 @@ static int queue_binlog_ver_3_event(Master_info *mi, const char *buf, mi->master_log_pos+= inc_pos; err: DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->master_log_pos)); - pthread_mutex_unlock(&mi->data_lock); + mysql_mutex_unlock(&mi->data_lock); DBUG_RETURN(0); } @@ -3901,7 +3783,7 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) String error_msg; ulong inc_pos; Relay_log_info *rli= &mi->rli; - pthread_mutex_t *log_lock= rli->relay_log.get_log_lock(); + mysql_mutex_t *log_lock= rli->relay_log.get_log_lock(); ulong s_id; DBUG_ENTER("queue_event"); @@ -3912,7 +3794,7 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) DBUG_RETURN(queue_old_event(mi,buf,event_len)); LINT_INIT(inc_pos); - pthread_mutex_lock(&mi->data_lock); + mysql_mutex_lock(&mi->data_lock); switch (buf[EVENT_TYPE_OFFSET]) { case STOP_EVENT: @@ -4048,7 +3930,7 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) direct master (an unsupported, useless setup!). */ - pthread_mutex_lock(log_lock); + mysql_mutex_lock(log_lock); s_id= uint4korr(buf + SERVER_ID_OFFSET); if ((s_id == ::server_id && !mi->rli.replicate_same_server_id) || /* @@ -4061,8 +3943,8 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) /* everything is filtered out from non-master */ (s_id != mi->master_id || /* for the master meta information is necessary */ - buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT && - buf[EVENT_TYPE_OFFSET] != ROTATE_EVENT))) + (buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT && + buf[EVENT_TYPE_OFFSET] != ROTATE_EVENT)))) { /* Do not write it to the relay log. @@ -4082,9 +3964,9 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) as well as rli->group_relay_log_pos. */ if (!(s_id == ::server_id && !mi->rli.replicate_same_server_id) || - buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT && - buf[EVENT_TYPE_OFFSET] != ROTATE_EVENT && - buf[EVENT_TYPE_OFFSET] != STOP_EVENT) + (buf[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT && + buf[EVENT_TYPE_OFFSET] != ROTATE_EVENT && + buf[EVENT_TYPE_OFFSET] != STOP_EVENT)) { mi->master_log_pos+= inc_pos; memcpy(rli->ign_master_log_name_end, mi->master_log_name, FN_REFLEN); @@ -4110,12 +3992,12 @@ static int queue_event(Master_info* mi,const char* buf, ulong event_len) } rli->ign_master_log_name_end[0]= 0; // last event is not ignored } - pthread_mutex_unlock(log_lock); + mysql_mutex_unlock(log_lock); skip_relay_logging: err: - pthread_mutex_unlock(&mi->data_lock); + mysql_mutex_unlock(&mi->data_lock); DBUG_PRINT("info", ("error: %d", error)); if (error) mi->report(ERROR_LEVEL, error, ER(error), @@ -4135,13 +4017,13 @@ void end_relay_log_info(Relay_log_info* rli) if (rli->info_fd >= 0) { end_io_cache(&rli->info_file); - (void) my_close(rli->info_fd, MYF(MY_WME)); + mysql_file_close(rli->info_fd, MYF(MY_WME)); rli->info_fd = -1; } if (rli->cur_log_fd >= 0) { end_io_cache(&rli->cache_buf); - (void)my_close(rli->cur_log_fd, MYF(MY_WME)); + mysql_file_close(rli->cur_log_fd, MYF(MY_WME)); rli->cur_log_fd = -1; } rli->inited = 0; @@ -4401,8 +4283,9 @@ MYSQL *rpl_connect_master(MYSQL *mysql) rli Relay log information NOTES - - As this is only called by the slave thread, we don't need to - have a lock on this. + - As this is only called by the slave thread or on STOP SLAVE, with the + log_lock grabbed and the slave thread stopped, we don't need to have + a lock here. - If there is an active transaction, then we don't update the position in the relay log. This is to ensure that we re-execute statements if we die in the middle of an transaction that was rolled back. @@ -4453,7 +4336,10 @@ bool flush_relay_log_info(Relay_log_info* rli) error=1; rli->sync_counter= 0; } - /* Flushing the relay log is done by the slave I/O thread */ + /* + Flushing the relay log is done by the slave I/O thread + or by the user on STOP SLAVE. + */ DBUG_RETURN(error); } @@ -4497,7 +4383,7 @@ static Log_event* next_event(Relay_log_info* rli) { Log_event* ev; IO_CACHE* cur_log = rli->cur_log; - pthread_mutex_t *log_lock = rli->relay_log.get_log_lock(); + mysql_mutex_t *log_lock = rli->relay_log.get_log_lock(); const char* errmsg=0; THD* thd = rli->sql_thd; DBUG_ENTER("next_event"); @@ -4514,9 +4400,9 @@ static Log_event* next_event(Relay_log_info* rli) so we assume calling function acquired this mutex for us and we will hold it for the most of the loop below However, we will release it whenever it is worth the hassle, and in the cases when we go into a - pthread_cond_wait() with the non-data_lock mutex + mysql_cond_wait() with the non-data_lock mutex */ - safe_mutex_assert_owner(&rli->data_lock); + mysql_mutex_assert_owner(&rli->data_lock); while (!sql_slave_killed(thd,rli)) { @@ -4535,7 +4421,7 @@ static Log_event* next_event(Relay_log_info* rli) if ((hot_log = (cur_log != &rli->cache_buf))) { DBUG_ASSERT(rli->cur_log_fd == -1); // foreign descriptor - pthread_mutex_lock(log_lock); + mysql_mutex_lock(log_lock); /* Reading xxx_file_id is safe because the log will only @@ -4545,7 +4431,7 @@ static Log_event* next_event(Relay_log_info* rli) { // The master has switched to a new log file; Reopen the old log file cur_log=reopen_relay_log(rli, &errmsg); - pthread_mutex_unlock(log_lock); + mysql_mutex_unlock(log_lock); if (!cur_log) // No more log files goto err; hot_log=0; // Using old binary log @@ -4592,7 +4478,7 @@ static Log_event* next_event(Relay_log_info* rli) */ rli->future_event_relay_log_pos= my_b_tell(cur_log); if (hot_log) - pthread_mutex_unlock(log_lock); + mysql_mutex_unlock(log_lock); DBUG_RETURN(ev); } DBUG_ASSERT(thd==rli->sql_thd); @@ -4602,7 +4488,7 @@ static Log_event* next_event(Relay_log_info* rli) { errmsg = "slave SQL thread aborted because of I/O error"; if (hot_log) - pthread_mutex_unlock(log_lock); + mysql_mutex_unlock(log_lock); goto err; } if (!cur_log->error) /* EOF */ @@ -4649,7 +4535,7 @@ static Log_event* next_event(Relay_log_info* rli) 0, rli->ign_master_log_pos_end, Rotate_log_event::DUP_NAME); rli->ign_master_log_name_end[0]= 0; - pthread_mutex_unlock(log_lock); + mysql_mutex_unlock(log_lock); if (unlikely(!ev)) { errmsg= "Slave SQL thread failed to create a Rotate event " @@ -4664,7 +4550,7 @@ static Log_event* next_event(Relay_log_info* rli) We can, and should release data_lock while we are waiting for update. If we do not, show slave status will block */ - pthread_mutex_unlock(&rli->data_lock); + mysql_mutex_unlock(&rli->data_lock); /* Possible deadlock : @@ -4690,7 +4576,7 @@ static Log_event* next_event(Relay_log_info* rli) be stopped, and the SQL thread sets ignore_log_space_limit to 0 when it stops. */ - pthread_mutex_lock(&rli->log_space_lock); + mysql_mutex_lock(&rli->log_space_lock); // prevent the I/O thread from blocking next times rli->ignore_log_space_limit= 1; /* @@ -4699,12 +4585,12 @@ static Log_event* next_event(Relay_log_info* rli) ~Relay_log_info(), i.e. when rli is destroyed, and rli will not be destroyed before we exit the present function. */ - pthread_mutex_unlock(&rli->log_space_lock); - pthread_cond_broadcast(&rli->log_space_cond); + mysql_mutex_unlock(&rli->log_space_lock); + mysql_cond_broadcast(&rli->log_space_cond); // Note that wait_for_update_relay_log unlocks lock_log ! rli->relay_log.wait_for_update_relay_log(rli->sql_thd); // re-acquire data lock since we released it earlier - pthread_mutex_lock(&rli->data_lock); + mysql_mutex_lock(&rli->data_lock); rli->last_master_timestamp= save_timestamp; continue; } @@ -4715,7 +4601,7 @@ static Log_event* next_event(Relay_log_info* rli) */ end_io_cache(cur_log); DBUG_ASSERT(rli->cur_log_fd >= 0); - my_close(rli->cur_log_fd, MYF(MY_WME)); + mysql_file_close(rli->cur_log_fd, MYF(MY_WME)); rli->cur_log_fd = -1; if (relay_log_purge) @@ -4772,7 +4658,7 @@ static Log_event* next_event(Relay_log_info* rli) DBUG_PRINT("info",("hot_log: %d",hot_log)); if (!hot_log) /* if hot_log, we already have this mutex */ - pthread_mutex_lock(log_lock); + mysql_mutex_lock(log_lock); if (rli->relay_log.is_active(rli->linfo.log_file_name)) { #ifdef EXTRA_DEBUG @@ -4793,13 +4679,16 @@ static Log_event* next_event(Relay_log_info* rli) */ if (check_binlog_magic(cur_log,&errmsg)) { - if (!hot_log) pthread_mutex_unlock(log_lock); + if (!hot_log) + mysql_mutex_unlock(log_lock); goto err; } - if (!hot_log) pthread_mutex_unlock(log_lock); + if (!hot_log) + mysql_mutex_unlock(log_lock); continue; } - if (!hot_log) pthread_mutex_unlock(log_lock); + if (!hot_log) + mysql_mutex_unlock(log_lock); /* if we get here, the log was not hot, so we will have to open it ourselves. We are sure that the log is still not hot now (a log can get @@ -4822,7 +4711,7 @@ static Log_event* next_event(Relay_log_info* rli) TODO: come up with something better to handle this error */ if (hot_log) - pthread_mutex_unlock(log_lock); + mysql_mutex_unlock(log_lock); sql_print_error("Slave SQL thread: I/O error reading \ event(errno: %d cur_log->error: %d)", my_errno,cur_log->error); @@ -4861,9 +4750,6 @@ void rotate_relay_log(Master_info* mi) DBUG_EXECUTE_IF("crash_before_rotate_relaylog", abort();); - /* We don't lock rli->run_lock. This would lead to deadlocks. */ - pthread_mutex_lock(&mi->run_lock); - /* We need to test inited because otherwise, new_file() will attempt to lock LOCK_log, which may not be inited (if we're not a slave). @@ -4892,7 +4778,6 @@ void rotate_relay_log(Master_info* mi) */ rli->relay_log.harvest_bytes_written(&rli->log_space_total); end: - pthread_mutex_unlock(&mi->run_lock); DBUG_VOID_RETURN; } diff --git a/sql/slave.h b/sql/slave.h index eff0fa49f61..f01eccf09f4 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -115,6 +115,7 @@ extern char *master_info_file, *relay_log_info_file; extern char *opt_relay_logname, *opt_relaylog_index_name; extern my_bool opt_skip_slave_start, opt_reckless_slave; extern my_bool opt_log_slave_updates; +extern char *opt_slave_skip_errors; extern ulonglong relay_log_space_limit; /* @@ -157,15 +158,19 @@ int start_slave_threads(bool need_slave_mutex, bool wait_for_start, cond_lock is usually same as start_lock. It is needed for the case when start_lock is 0 which happens if start_slave_thread() is called already inside the start_lock section, but at the same time we want a - pthread_cond_wait() on start_cond,start_lock + mysql_cond_wait() on start_cond, start_lock */ -int start_slave_thread(pthread_handler h_func, pthread_mutex_t* start_lock, - pthread_mutex_t *cond_lock, - pthread_cond_t* start_cond, - volatile uint *slave_running, - volatile ulong *slave_run_id, - Master_info* mi, - bool high_priority); +int start_slave_thread( +#ifdef HAVE_PSI_INTERFACE + PSI_thread_key thread_key, +#endif + pthread_handler h_func, + mysql_mutex_t *start_lock, + mysql_mutex_t *cond_lock, + mysql_cond_t *start_cond, + volatile uint *slave_running, + volatile ulong *slave_run_id, + Master_info *mi); /* If fd is -1, dump to NET */ int mysql_table_dump(THD* thd, const char* db, diff --git a/sql/sp.cc b/sql/sp.cc index 0aa14625251..cbc0d003c9f 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -31,7 +31,9 @@ create_string(THD *thd, String *buf, const char *body, ulong bodylen, st_sp_chistics *chistics, const LEX_STRING *definer_user, - const LEX_STRING *definer_host); + const LEX_STRING *definer_host, + ulong sql_mode); + static int db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, ulong sql_mode, const char *params, const char *returns, @@ -39,37 +41,6 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, const char *definer, longlong created, longlong modified, Stored_program_creation_ctx *creation_ctx); -/* - * - * DB storage of Stored PROCEDUREs and FUNCTIONs - * - */ - -enum -{ - MYSQL_PROC_FIELD_DB = 0, - MYSQL_PROC_FIELD_NAME, - MYSQL_PROC_MYSQL_TYPE, - MYSQL_PROC_FIELD_SPECIFIC_NAME, - MYSQL_PROC_FIELD_LANGUAGE, - MYSQL_PROC_FIELD_ACCESS, - MYSQL_PROC_FIELD_DETERMINISTIC, - MYSQL_PROC_FIELD_SECURITY_TYPE, - MYSQL_PROC_FIELD_PARAM_LIST, - MYSQL_PROC_FIELD_RETURNS, - MYSQL_PROC_FIELD_BODY, - MYSQL_PROC_FIELD_DEFINER, - MYSQL_PROC_FIELD_CREATED, - MYSQL_PROC_FIELD_MODIFIED, - MYSQL_PROC_FIELD_SQL_MODE, - MYSQL_PROC_FIELD_COMMENT, - MYSQL_PROC_FIELD_CHARACTER_SET_CLIENT, - MYSQL_PROC_FIELD_COLLATION_CONNECTION, - MYSQL_PROC_FIELD_DB_COLLATION, - MYSQL_PROC_FIELD_BODY_UTF8, - MYSQL_PROC_FIELD_COUNT -}; - static const TABLE_FIELD_TYPE proc_table_fields[MYSQL_PROC_FIELD_COUNT] = { @@ -716,6 +687,55 @@ Silence_deprecated_warning::handle_condition( } +/** + @brief The function parses input strings and returns SP stucture. + + @param[in] thd Thread handler + @param[in] defstr CREATE... string + @param[in] sql_mode SQL mode + @param[in] creation_ctx Creation context of stored routines + + @return Pointer on sp_head struct + @retval # Pointer on sp_head struct + @retval 0 error +*/ + +static sp_head *sp_compile(THD *thd, String *defstr, ulong sql_mode, + Stored_program_creation_ctx *creation_ctx) +{ + sp_head *sp; + ulong old_sql_mode= thd->variables.sql_mode; + ha_rows old_select_limit= thd->variables.select_limit; + sp_rcontext *old_spcont= thd->spcont; + Silence_deprecated_warning warning_handler; + + thd->variables.sql_mode= sql_mode; + thd->variables.select_limit= HA_POS_ERROR; + + Parser_state parser_state(thd, defstr->c_ptr(), defstr->length()); + lex_start(thd); + thd->push_internal_handler(&warning_handler); + thd->spcont= 0; + + if (parse_sql(thd, & parser_state, creation_ctx) || thd->lex == NULL) + { + sp= thd->lex->sphead; + delete sp; + sp= 0; + } + else + { + sp= thd->lex->sphead; + } + + thd->pop_internal_handler(); + thd->spcont= old_spcont; + thd->variables.sql_mode= old_sql_mode; + thd->variables.select_limit= old_select_limit; + return sp; +} + + static int db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, ulong sql_mode, const char *params, const char *returns, @@ -729,11 +749,7 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, LEX_STRING saved_cur_db_name= { saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) }; bool cur_db_changed; - ulong old_sql_mode= thd->variables.sql_mode; - ha_rows old_select_limit= thd->variables.select_limit; - sp_rcontext *old_spcont= thd->spcont; - Silence_deprecated_warning warning_handler; - + char definer_user_name_holder[USERNAME_LENGTH + 1]; LEX_STRING definer_user_name= { definer_user_name_holder, USERNAME_LENGTH }; @@ -741,10 +757,7 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, char definer_host_name_holder[HOSTNAME_LENGTH + 1]; LEX_STRING definer_host_name= { definer_host_name_holder, HOSTNAME_LENGTH }; - int ret; - - thd->variables.sql_mode= sql_mode; - thd->variables.select_limit= HA_POS_ERROR; + int ret= 0; thd->lex= &newlex; newlex.current_select= NULL; @@ -768,7 +781,8 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, params, strlen(params), returns, strlen(returns), body, strlen(body), - &chistics, &definer_user_name, &definer_host_name)) + &chistics, &definer_user_name, &definer_host_name, + sql_mode)) { ret= SP_INTERNAL_ERROR; goto end; @@ -787,17 +801,8 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, goto end; } - thd->spcont= NULL; - { - Parser_state parser_state(thd, defstr.c_ptr(), defstr.length()); - - lex_start(thd); - - thd->push_internal_handler(&warning_handler); - ret= parse_sql(thd, & parser_state, creation_ctx) || newlex.sphead == NULL; - thd->pop_internal_handler(); - + *sphp= sp_compile(thd, &defstr, sql_mode, creation_ctx); /* Force switching back to the saved current database (if changed), because it may be NULL. In this case, mysql_change_db() would @@ -806,19 +811,16 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, if (cur_db_changed && mysql_change_db(thd, &saved_cur_db_name, TRUE)) { - delete newlex.sphead; ret= SP_INTERNAL_ERROR; goto end; } - if (ret) + if (!*sphp) { - delete newlex.sphead; ret= SP_PARSE_ERROR; goto end; } - *sphp= newlex.sphead; (*sphp)->set_definer(&definer_user_name, &definer_host_name); (*sphp)->set_info(created, modified, &chistics, sql_mode); (*sphp)->set_creation_ctx(creation_ctx); @@ -836,9 +838,6 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp, end: lex_end(thd->lex); - thd->spcont= old_spcont; - thd->variables.sql_mode= old_sql_mode; - thd->variables.select_limit= old_select_limit; thd->lex= old_lex; return ret; } @@ -861,6 +860,11 @@ sp_returns_type(THD *thd, String &result, sp_head *sp) { result.append(STRING_WITH_LEN(" CHARSET ")); result.append(field->charset()->csname); + if (!(field->charset()->state & MY_CS_PRIMARY)) + { + result.append(STRING_WITH_LEN(" COLLATE ")); + result.append(field->charset()->name); + } } delete field; @@ -923,8 +927,8 @@ sp_create_routine(THD *thd, int type, sp_head *sp) row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); + thd->clear_current_stmt_binlog_format_row(); saved_count_cuted_fields= thd->count_cuted_fields; thd->count_cuted_fields= CHECK_FIELD_WARN; @@ -1108,7 +1112,8 @@ sp_create_routine(THD *thd, int type, sp_head *sp) retstr.c_ptr(), retstr.length(), sp->m_body.str, sp->m_body.length, sp->m_chistics, &(thd->lex->definer->user), - &(thd->lex->definer->host))) + &(thd->lex->definer->host), + saved_mode)) { ret= SP_INTERNAL_ERROR; goto done; @@ -1116,9 +1121,9 @@ sp_create_routine(THD *thd, int type, sp_head *sp) /* restore sql_mode when binloging */ thd->variables.sql_mode= saved_mode; /* Such a statement can always go directly to binlog, no trans cache */ - if (thd->binlog_query(THD::MYSQL_QUERY_TYPE, + if (thd->binlog_query(THD::STMT_QUERY_TYPE, log_query.c_ptr(), log_query.length(), - FALSE, FALSE, 0)) + FALSE, FALSE, FALSE, 0)) ret= SP_INTERNAL_ERROR; thd->variables.sql_mode= 0; } @@ -1169,8 +1174,8 @@ sp_drop_routine(THD *thd, int type, sp_name *name) row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); + thd->clear_current_stmt_binlog_format_row(); if (!(table= open_proc_table_for_update(thd))) DBUG_RETURN(SP_OPEN_TABLE_FAILED); @@ -1228,8 +1233,8 @@ sp_update_routine(THD *thd, int type, sp_name *name, st_sp_chistics *chistics) row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); + thd->clear_current_stmt_binlog_format_row(); if (!(table= open_proc_table_for_update(thd))) DBUG_RETURN(SP_OPEN_TABLE_FAILED); @@ -1906,6 +1911,9 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, ret= SP_OK; break; default: + /* Query might have been killed, don't set error. */ + if (thd->killed) + break; /* Any error when loading an existing routine is either some problem with the mysql.proc table, or a parse error because the contents @@ -2030,6 +2038,8 @@ sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, { int ret= 0; + DBUG_ENTER("sp_cache_routines_and_add_tables_for_triggers"); + Sroutine_hash_entry **last_cached_routine_ptr= (Sroutine_hash_entry **)lex->sroutines_list.next; @@ -2063,7 +2073,7 @@ sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, ret= sp_cache_routines_and_add_tables_aux(thd, lex, *last_cached_routine_ptr, FALSE); - return ret; + DBUG_RETURN(ret); } @@ -2074,6 +2084,7 @@ sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, Returns TRUE on success, FALSE on (alloc) failure. */ static bool + create_string(THD *thd, String *buf, int type, const char *db, ulong dblen, @@ -2083,14 +2094,17 @@ create_string(THD *thd, String *buf, const char *body, ulong bodylen, st_sp_chistics *chistics, const LEX_STRING *definer_user, - const LEX_STRING *definer_host) + const LEX_STRING *definer_host, + ulong sql_mode) { + ulong old_sql_mode= thd->variables.sql_mode; /* Make some room to begin with */ if (buf->alloc(100 + dblen + 1 + namelen + paramslen + returnslen + bodylen + chistics->comment.length + 10 /* length of " DEFINER= "*/ + USER_HOST_BUFF_SIZE)) return FALSE; + thd->variables.sql_mode= sql_mode; buf->append(STRING_WITH_LEN("CREATE ")); append_definer(thd, buf, definer_user, definer_host); if (type == TYPE_ENUM_FUNCTION) @@ -2138,5 +2152,79 @@ create_string(THD *thd, String *buf, buf->append('\n'); } buf->append(body, bodylen); + thd->variables.sql_mode= old_sql_mode; return TRUE; } + + +/** + @brief The function loads sp_head struct for information schema purposes + (used for I_S ROUTINES & PARAMETERS tables). + + @param[in] thd thread handler + @param[in] proc_table mysql.proc table structurte + @param[in] db database name + @param[in] name sp name + @param[in] sql_mode SQL mode + @param[in] type Routine type + @param[in] returns 'returns' string + @param[in] params parameters definition string + @param[out] free_sp_head returns 1 if we need to free sp_head struct + otherwise returns 0 + + @return Pointer on sp_head struct + @retval # Pointer on sp_head struct + @retval 0 error +*/ + +sp_head * +sp_load_for_information_schema(THD *thd, TABLE *proc_table, String *db, + String *name, ulong sql_mode, int type, + const char *returns, const char *params, + bool *free_sp_head) +{ + const char *sp_body; + String defstr; + struct st_sp_chistics sp_chistics; + const LEX_STRING definer_user= {(char*)STRING_WITH_LEN("")}; + const LEX_STRING definer_host= {(char*)STRING_WITH_LEN("")}; + LEX_STRING sp_db_str; + LEX_STRING sp_name_str; + sp_head *sp; + sp_cache **spc= ((type == TYPE_ENUM_PROCEDURE) ? + &thd->sp_proc_cache : &thd->sp_func_cache); + sp_db_str.str= db->c_ptr(); + sp_db_str.length= db->length(); + sp_name_str.str= name->c_ptr(); + sp_name_str.length= name->length(); + sp_name sp_name_obj(sp_db_str, sp_name_str, true); + sp_name_obj.init_qname(thd); + *free_sp_head= 0; + if ((sp= sp_cache_lookup(spc, &sp_name_obj))) + { + return sp; + } + + LEX *old_lex= thd->lex, newlex; + Stored_program_creation_ctx *creation_ctx= + Stored_routine_creation_ctx::load_from_db(thd, &sp_name_obj, proc_table); + sp_body= (type == TYPE_ENUM_FUNCTION ? "RETURN NULL" : "BEGIN END"); + bzero((char*) &sp_chistics, sizeof(sp_chistics)); + defstr.set_charset(creation_ctx->get_client_cs()); + if (!create_string(thd, &defstr, type, + sp_db_str.str, sp_db_str.length, + sp_name_obj.m_name.str, sp_name_obj.m_name.length, + params, strlen(params), + returns, strlen(returns), + sp_body, strlen(sp_body), + &sp_chistics, &definer_user, &definer_host, sql_mode)) + return 0; + + thd->lex= &newlex; + newlex.current_select= NULL; + sp= sp_compile(thd, &defstr, sql_mode, creation_ctx); + *free_sp_head= 1; + lex_end(thd->lex); + thd->lex= old_lex; + return sp; +} @@ -34,6 +34,32 @@ #define SP_BODY_TOO_LONG -10 #define SP_FLD_STORE_FAILED -11 +/* DB storage of Stored PROCEDUREs and FUNCTIONs */ +enum +{ + MYSQL_PROC_FIELD_DB = 0, + MYSQL_PROC_FIELD_NAME, + MYSQL_PROC_MYSQL_TYPE, + MYSQL_PROC_FIELD_SPECIFIC_NAME, + MYSQL_PROC_FIELD_LANGUAGE, + MYSQL_PROC_FIELD_ACCESS, + MYSQL_PROC_FIELD_DETERMINISTIC, + MYSQL_PROC_FIELD_SECURITY_TYPE, + MYSQL_PROC_FIELD_PARAM_LIST, + MYSQL_PROC_FIELD_RETURNS, + MYSQL_PROC_FIELD_BODY, + MYSQL_PROC_FIELD_DEFINER, + MYSQL_PROC_FIELD_CREATED, + MYSQL_PROC_FIELD_MODIFIED, + MYSQL_PROC_FIELD_SQL_MODE, + MYSQL_PROC_FIELD_COMMENT, + MYSQL_PROC_FIELD_CHARACTER_SET_CLIENT, + MYSQL_PROC_FIELD_COLLATION_CONNECTION, + MYSQL_PROC_FIELD_DB_COLLATION, + MYSQL_PROC_FIELD_BODY_UTF8, + MYSQL_PROC_FIELD_COUNT +}; + /* Drop all routines in database 'db' */ int sp_drop_db_routines(THD *thd, char *db); @@ -86,4 +112,10 @@ extern "C" uchar* sp_sroutine_key(const uchar *ptr, size_t *plen, */ TABLE *open_proc_table_for_read(THD *thd, Open_tables_state *backup); +sp_head * +sp_load_for_information_schema(THD *thd, TABLE *proc_table, String *db, + String *name, ulong sql_mode, int type, + const char *returns, const char *params, + bool *free_sp_head); + #endif /* _SP_H_ */ diff --git a/sql/sp_cache.cc b/sql/sp_cache.cc index 0da5e44b846..e8604baf466 100644 --- a/sql/sp_cache.cc +++ b/sql/sp_cache.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2002 MySQL AB +/* Copyright (C) 2002 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,7 +20,7 @@ #include "sp_cache.h" #include "sp_head.h" -static pthread_mutex_t Cversion_lock; +static mysql_mutex_t Cversion_lock; static ulong volatile Cversion= 0; @@ -81,12 +81,36 @@ private: HASH m_hashtable; }; // class sp_cache +#ifdef HAVE_PSI_INTERFACE +static PSI_mutex_key key_Cversion_lock; + +static PSI_mutex_info all_sp_cache_mutexes[]= +{ + { &key_Cversion_lock, "Cversion_lock", PSI_FLAG_GLOBAL} +}; + +static void init_sp_cache_psi_keys(void) +{ + const char* category= "sql"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_sp_cache_mutexes); + PSI_server->register_mutex(category, all_sp_cache_mutexes, count); +} +#endif /* Initialize the SP caching once at startup */ void sp_cache_init() { - pthread_mutex_init(&Cversion_lock, MY_MUTEX_INIT_FAST); +#ifdef HAVE_PSI_INTERFACE + init_sp_cache_psi_keys(); +#endif + + mysql_mutex_init(key_Cversion_lock, &Cversion_lock, MY_MUTEX_INIT_FAST); } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index efe87110194..8d06003e2e4 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1,4 +1,4 @@ -/* Copyright 2002-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2002-2008 MySQL AB, 2008-2010 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ #include "sp_pcontext.h" #include "sp_rcontext.h" #include "sp_cache.h" +#include "set_var.h" /* Sufficient max length of printed destinations and frame offsets (all uints). @@ -166,7 +167,6 @@ sp_get_flags_for_command(LEX *lex) } /* fallthrough */ case SQLCOM_ANALYZE: - case SQLCOM_BACKUP_TABLE: case SQLCOM_OPTIMIZE: case SQLCOM_PRELOAD_KEYS: case SQLCOM_ASSIGN_TO_KEYCACHE: @@ -213,7 +213,6 @@ sp_get_flags_for_command(LEX *lex) case SQLCOM_SHOW_VARIABLES: case SQLCOM_SHOW_WARNS: case SQLCOM_REPAIR: - case SQLCOM_RESTORE_TABLE: flags= sp_head::MULTI_RESULTS; break; /* @@ -268,7 +267,6 @@ sp_get_flags_for_command(LEX *lex) case SQLCOM_COMMIT: case SQLCOM_ROLLBACK: case SQLCOM_LOAD: - case SQLCOM_LOAD_MASTER_DATA: case SQLCOM_LOCK_TABLES: case SQLCOM_CREATE_PROCEDURE: case SQLCOM_CREATE_SPFUNCTION: @@ -513,7 +511,7 @@ sp_head::operator delete(void *ptr, size_t size) throw() sp_head::sp_head() :Query_arena(&main_mem_root, INITIALIZED_FOR_SP), - m_flags(0), m_recursion_level(0), m_next_cached_sp(0), + m_flags(0), unsafe_flags(0), m_recursion_level(0), m_next_cached_sp(0), m_cont_level(0) { const LEX_STRING str_reset= { NULL, 0 }; @@ -1086,7 +1084,6 @@ sp_head::execute(THD *thd) Item_change_list old_change_list; String old_packet; Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer; - Object_creation_ctx *saved_creation_ctx; Warning_info *saved_warning_info, warning_info(thd->warning_info->warn_id()); @@ -1339,7 +1336,7 @@ sp_head::execute(THD *thd) /* To avoid wiping out thd->change_list on old_change_list destruction */ old_change_list.empty(); thd->lex= old_lex; - thd->query_id= old_query_id; + thd->set_query_id(old_query_id); DBUG_ASSERT(!thd->derived_tables); thd->derived_tables= old_derived_tables; thd->variables.sql_mode= save_sql_mode; @@ -1711,7 +1708,8 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, each substatement be binlogged its way. */ need_binlog_call= mysql_bin_log.is_open() && - (thd->options & OPTION_BIN_LOG) && !thd->current_stmt_binlog_row_based; + (thd->variables.option_bits & OPTION_BIN_LOG) && + !thd->is_current_stmt_binlog_format_row(); /* Remember the original arguments for unrolled replication of functions @@ -1770,12 +1768,12 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, as one select and not resetting THD::user_var_events before each invocation. */ - VOID(pthread_mutex_lock(&LOCK_thread_count)); + mysql_mutex_lock(&LOCK_thread_count); q= global_query_id; - VOID(pthread_mutex_unlock(&LOCK_thread_count)); + mysql_mutex_unlock(&LOCK_thread_count); mysql_bin_log.start_union_events(thd, q + 1); - binlog_save_options= thd->options; - thd->options&= ~OPTION_BIN_LOG; + binlog_save_options= thd->variables.option_bits; + thd->variables.option_bits&= ~OPTION_BIN_LOG; } /* @@ -1795,12 +1793,12 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, if (need_binlog_call) { mysql_bin_log.stop_union_events(thd); - thd->options= binlog_save_options; + thd->variables.option_bits= binlog_save_options; if (thd->binlog_evt_union.unioned_events) { int errcode = query_error_code(thd, thd->killed == THD::NOT_KILLED); Query_log_event qinfo(thd, binlog_buf.ptr(), binlog_buf.length(), - thd->binlog_evt_union.unioned_events_trans, FALSE, errcode); + thd->binlog_evt_union.unioned_events_trans, FALSE, FALSE, errcode); if (mysql_bin_log.write(&qinfo) && thd->binlog_evt_union.unioned_events_trans) { @@ -1988,12 +1986,12 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) save_enable_slow_log= true; thd->enable_slow_log= FALSE; } - if (!(m_flags & LOG_GENERAL_LOG) && !(thd->options & OPTION_LOG_OFF)) + if (!(m_flags & LOG_GENERAL_LOG) && !(thd->variables.option_bits & OPTION_LOG_OFF)) { DBUG_PRINT("info", ("Disabling general log for the execution")); save_log_general= true; /* disable this bit */ - thd->options |= OPTION_LOG_OFF; + thd->variables.option_bits |= OPTION_LOG_OFF; } thd->spcont= nctx; @@ -2007,7 +2005,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) err_status= execute(thd); if (save_log_general) - thd->options &= ~OPTION_LOG_OFF; + thd->variables.option_bits &= ~OPTION_LOG_OFF; if (save_enable_slow_log) thd->enable_slow_log= true; /* @@ -2148,13 +2146,10 @@ sp_head::restore_lex(THD *thd) oldlex->trg_table_fields.push_back(&sublex->trg_table_fields); - /* - If this substatement needs row-based, the entire routine does too (we - cannot switch from statement-based to row-based only for this - substatement). - */ - if (sublex->is_stmt_unsafe()) - m_flags|= BINLOG_ROW_BASED_IF_MIXED; + /* If this substatement is unsafe, the entire routine is too. */ + DBUG_PRINT("info", ("lex->get_stmt_unsafe_flags: 0x%x", + thd->lex->get_stmt_unsafe_flags())); + unsafe_flags|= sublex->get_stmt_unsafe_flags(); /* Add routines which are used by statement to respective set for @@ -2445,8 +2440,7 @@ sp_head::show_create_routine(THD *thd, int type) if (check_show_routine_access(thd, this, &full_access)) DBUG_RETURN(TRUE); - sys_var_thd_sql_mode::symbolic_mode_representation( - thd, m_sql_mode, &sql_mode); + sql_mode_string_representation(thd, m_sql_mode, &sql_mode); /* Send header. */ @@ -2749,9 +2743,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, */ thd->lex= m_lex; - VOID(pthread_mutex_lock(&LOCK_thread_count)); - thd->query_id= next_query_id(); - VOID(pthread_mutex_unlock(&LOCK_thread_count)); + thd->set_query_id(next_query_id()); if (thd->prelocked_mode == NON_PRELOCKED) { @@ -2894,7 +2886,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) (the order of query cache and subst_spvars calls is irrelevant because queries with SP vars can't be cached) */ - if (unlikely((thd->options & OPTION_LOG_OFF)==0)) + if (unlikely((thd->variables.option_bits & OPTION_LOG_OFF)==0)) general_log_write(thd, COM_QUERY, thd->query(), thd->query_length()); if (query_cache_send_result_to_client(thd, @@ -4025,7 +4017,7 @@ sp_head::add_used_tables_to_table_list(THD *thd, /** - Simple function for adding an explicetly named (systems) table to + Simple function for adding an explicitly named (systems) table to the global table list, e.g. "mysql", "proc". */ @@ -4037,10 +4029,7 @@ sp_add_to_query_tables(THD *thd, LEX *lex, TABLE_LIST *table; if (!(table= (TABLE_LIST *)thd->calloc(sizeof(TABLE_LIST)))) - { - thd->fatal_error(); return NULL; - } table->db_length= strlen(db); table->db= thd->strmake(db, table->db_length); table->table_name_length= strlen(name); diff --git a/sql/sp_head.h b/sql/sp_head.h index 00c96d44f70..fd02c799975 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -165,9 +165,8 @@ public: HAS_COMMIT_OR_ROLLBACK= 128, LOG_SLOW_STATEMENTS= 256, // Used by events LOG_GENERAL_LOG= 512, // Used by events - BINLOG_ROW_BASED_IF_MIXED= 1024, - HAS_SQLCOM_RESET= 2048, - HAS_SQLCOM_FLUSH= 4096 + HAS_SQLCOM_RESET= 1024, + HAS_SQLCOM_FLUSH= 2048 }; /** TYPE_ENUM_FUNCTION, TYPE_ENUM_PROCEDURE or TYPE_ENUM_TRIGGER */ @@ -198,6 +197,11 @@ public: private: Stored_program_creation_ctx *m_creation_ctx; + /** + Boolean combination of (1<<flag), where flag is a member of + LEX::enum_binlog_stmt_unsafe. + */ + uint32 unsafe_flags; public: inline Stored_program_creation_ctx *get_creation_ctx() @@ -453,22 +457,27 @@ public: #endif /* - This method is intended for attributes of a routine which need - to propagate upwards to the LEX of the caller (when a property of a - sp_head needs to "taint" the caller). + This method is intended for attributes of a routine which need to + propagate upwards to the LEX of the caller. */ void propagate_attributes(LEX *lex) { + DBUG_ENTER("sp_head::propagate_attributes"); /* If this routine needs row-based binary logging, the entire top statement too (we cannot switch from statement-based to row-based only for this routine, as in statement-based the top-statement may be binlogged and the substatements not). */ - if (m_flags & BINLOG_ROW_BASED_IF_MIXED) - lex->set_stmt_unsafe(); + DBUG_PRINT("info", ("lex->get_stmt_unsafe_flags(): 0x%x", + lex->get_stmt_unsafe_flags())); + DBUG_PRINT("info", ("sp_head(0x%p=%s)->unsafe_flags: 0x%x", + this, name(), unsafe_flags)); + lex->set_stmt_unsafe_flags(unsafe_flags); + DBUG_VOID_RETURN; } + sp_pcontext *get_parse_context() { return m_pcont; } private: diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc index 31c307ebe74..48ceb1371ca 100644 --- a/sql/sp_pcontext.cc +++ b/sql/sp_pcontext.cc @@ -63,21 +63,21 @@ sp_pcontext::sp_pcontext() m_context_handlers(0), m_parent(NULL), m_pboundary(0), m_label_scope(LABEL_DEFAULT_SCOPE) { - VOID(my_init_dynamic_array(&m_vars, sizeof(sp_variable_t *), + (void) my_init_dynamic_array(&m_vars, sizeof(sp_variable_t *), PCONTEXT_ARRAY_INIT_ALLOC, - PCONTEXT_ARRAY_INCREMENT_ALLOC)); - VOID(my_init_dynamic_array(&m_case_expr_id_lst, sizeof(int), + PCONTEXT_ARRAY_INCREMENT_ALLOC); + (void) my_init_dynamic_array(&m_case_expr_id_lst, sizeof(int), PCONTEXT_ARRAY_INIT_ALLOC, - PCONTEXT_ARRAY_INCREMENT_ALLOC)); - VOID(my_init_dynamic_array(&m_conds, sizeof(sp_cond_type_t *), + PCONTEXT_ARRAY_INCREMENT_ALLOC); + (void) my_init_dynamic_array(&m_conds, sizeof(sp_cond_type_t *), PCONTEXT_ARRAY_INIT_ALLOC, - PCONTEXT_ARRAY_INCREMENT_ALLOC)); - VOID(my_init_dynamic_array(&m_cursors, sizeof(LEX_STRING), + PCONTEXT_ARRAY_INCREMENT_ALLOC); + (void) my_init_dynamic_array(&m_cursors, sizeof(LEX_STRING), PCONTEXT_ARRAY_INIT_ALLOC, - PCONTEXT_ARRAY_INCREMENT_ALLOC)); - VOID(my_init_dynamic_array(&m_handlers, sizeof(sp_cond_type_t *), + PCONTEXT_ARRAY_INCREMENT_ALLOC); + (void) my_init_dynamic_array(&m_handlers, sizeof(sp_cond_type_t *), PCONTEXT_ARRAY_INIT_ALLOC, - PCONTEXT_ARRAY_INCREMENT_ALLOC)); + PCONTEXT_ARRAY_INCREMENT_ALLOC); m_label.empty(); m_children.empty(); @@ -91,21 +91,21 @@ sp_pcontext::sp_pcontext(sp_pcontext *prev, label_scope_type label_scope) m_context_handlers(0), m_parent(prev), m_pboundary(0), m_label_scope(label_scope) { - VOID(my_init_dynamic_array(&m_vars, sizeof(sp_variable_t *), + (void) my_init_dynamic_array(&m_vars, sizeof(sp_variable_t *), PCONTEXT_ARRAY_INIT_ALLOC, - PCONTEXT_ARRAY_INCREMENT_ALLOC)); - VOID(my_init_dynamic_array(&m_case_expr_id_lst, sizeof(int), + PCONTEXT_ARRAY_INCREMENT_ALLOC); + (void) my_init_dynamic_array(&m_case_expr_id_lst, sizeof(int), PCONTEXT_ARRAY_INIT_ALLOC, - PCONTEXT_ARRAY_INCREMENT_ALLOC)); - VOID(my_init_dynamic_array(&m_conds, sizeof(sp_cond_type_t *), + PCONTEXT_ARRAY_INCREMENT_ALLOC); + (void) my_init_dynamic_array(&m_conds, sizeof(sp_cond_type_t *), PCONTEXT_ARRAY_INIT_ALLOC, - PCONTEXT_ARRAY_INCREMENT_ALLOC)); - VOID(my_init_dynamic_array(&m_cursors, sizeof(LEX_STRING), + PCONTEXT_ARRAY_INCREMENT_ALLOC); + (void) my_init_dynamic_array(&m_cursors, sizeof(LEX_STRING), PCONTEXT_ARRAY_INIT_ALLOC, - PCONTEXT_ARRAY_INCREMENT_ALLOC)); - VOID(my_init_dynamic_array(&m_handlers, sizeof(sp_cond_type_t *), + PCONTEXT_ARRAY_INCREMENT_ALLOC); + (void) my_init_dynamic_array(&m_handlers, sizeof(sp_cond_type_t *), PCONTEXT_ARRAY_INIT_ALLOC, - PCONTEXT_ARRAY_INCREMENT_ALLOC)); + PCONTEXT_ARRAY_INCREMENT_ALLOC); m_label.empty(); m_children.empty(); diff --git a/sql/spatial.cc b/sql/spatial.cc index 9114c81514d..671b8544b8a 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -17,28 +17,7 @@ #ifdef HAVE_SPATIAL -/* - exponential notation : - 1 sign - 1 number before the decimal point - 1 decimal point - 14 number of significant digits (see String::qs_append(double)) - 1 'e' sign - 1 exponent sign - 3 exponent digits - == - 22 - - "f" notation : - 1 optional 0 - 1 sign - 14 number significant digits (see String::qs_append(double) ) - 1 decimal point - == - 17 -*/ - -#define MAX_DIGITS_IN_DOUBLE 22 +#define MAX_DIGITS_IN_DOUBLE MY_GCVT_MAX_FIELD_WIDTH /***************************** Gis_class_info *******************************/ diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index ea781080a38..012542a9467 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,6 +31,8 @@ #include "sp_head.h" #include "sp.h" +bool mysql_user_table_is_in_short_password_format= false; + static const TABLE_FIELD_TYPE mysql_db_table_fields[MYSQL_DB_FIELD_COUNT] = { { @@ -219,25 +221,6 @@ set_user_salt(ACL_USER *acl_user, const char *password, uint password_len) } /* - This after_update function is used when user.password is less than - SCRAMBLE_LENGTH bytes. -*/ - -static void restrict_update_of_old_passwords_var(THD *thd, - enum_var_type var_type) -{ - if (var_type == OPT_GLOBAL) - { - pthread_mutex_lock(&LOCK_global_system_variables); - global_system_variables.old_passwords= 1; - pthread_mutex_unlock(&LOCK_global_system_variables); - } - else - thd->variables.old_passwords= 1; -} - - -/* Initialize structures responsible for user/db-level privilege checking and load privilege information for them from tables in the 'mysql' database. @@ -277,7 +260,6 @@ my_bool acl_init(bool dont_read_acl_tables) DBUG_RETURN(1); /* purecov: inspected */ thd->thread_stack= (char*) &thd; thd->store_globals(); - lex_start(thd); /* It is safe to call acl_reload() since acl_* arrays and hashes which will be freed there are global static objects and thus are initialized @@ -327,7 +309,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) init_read_record(&read_record_info,thd,table= tables[0].table,NULL,1,0, FALSE); table->use_all_columns(); - VOID(my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST),20,50)); + (void) my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST),20,50); while (!(read_record_info.read_record(&read_record_info))) { ACL_HOST host; @@ -367,7 +349,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) host.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL | CREATE_TMP_ACL; } #endif - VOID(push_dynamic(&acl_hosts,(uchar*) &host)); + (void) push_dynamic(&acl_hosts,(uchar*) &host); } my_qsort((uchar*) dynamic_element(&acl_hosts,0,ACL_HOST*),acl_hosts.elements, sizeof(ACL_HOST),(qsort_cmp) acl_compare); @@ -376,7 +358,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) init_read_record(&read_record_info,thd,table=tables[1].table,NULL,1,0,FALSE); table->use_all_columns(); - VOID(my_init_dynamic_array(&acl_users,sizeof(ACL_USER),50,100)); + (void) my_init_dynamic_array(&acl_users,sizeof(ACL_USER),50,100); password_length= table->field[2]->field_length / table->field[2]->charset()->mbmaxlen; if (password_length < SCRAMBLED_PASSWORD_CHAR_LENGTH_323) @@ -389,23 +371,23 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) DBUG_PRINT("info",("user table fields: %d, password length: %d", table->s->fields, password_length)); - pthread_mutex_lock(&LOCK_global_system_variables); + mysql_mutex_lock(&LOCK_global_system_variables); if (password_length < SCRAMBLED_PASSWORD_CHAR_LENGTH) { if (opt_secure_auth) { - pthread_mutex_unlock(&LOCK_global_system_variables); + mysql_mutex_unlock(&LOCK_global_system_variables); sql_print_error("Fatal error: mysql.user table is in old format, " "but server started with --secure-auth option."); goto end; } - sys_old_passwords.after_update= restrict_update_of_old_passwords_var; + mysql_user_table_is_in_short_password_format= true; if (global_system_variables.old_passwords) - pthread_mutex_unlock(&LOCK_global_system_variables); + mysql_mutex_unlock(&LOCK_global_system_variables); else { global_system_variables.old_passwords= 1; - pthread_mutex_unlock(&LOCK_global_system_variables); + mysql_mutex_unlock(&LOCK_global_system_variables); sql_print_warning("mysql.user table is not updated to new password format; " "Disabling new password usage until " "mysql_fix_privilege_tables is run"); @@ -414,8 +396,8 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) } else { - sys_old_passwords.after_update= 0; - pthread_mutex_unlock(&LOCK_global_system_variables); + mysql_user_table_is_in_short_password_format= false; + mysql_mutex_unlock(&LOCK_global_system_variables); } allow_all_hosts=0; @@ -551,7 +533,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) user.access|= SUPER_ACL | EXECUTE_ACL; #endif } - VOID(push_dynamic(&acl_users,(uchar*) &user)); + (void) push_dynamic(&acl_users,(uchar*) &user); if (!user.host.hostname || (user.host.hostname[0] == wild_many && !user.host.hostname[1])) allow_all_hosts=1; // Anyone can connect @@ -564,7 +546,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) init_read_record(&read_record_info,thd,table=tables[2].table,NULL,1,0,FALSE); table->use_all_columns(); - VOID(my_init_dynamic_array(&acl_dbs,sizeof(ACL_DB),50,100)); + (void) my_init_dynamic_array(&acl_dbs,sizeof(ACL_DB),50,100); while (!(read_record_info.read_record(&read_record_info))) { ACL_DB db; @@ -614,7 +596,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) db.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL; } #endif - VOID(push_dynamic(&acl_dbs,(uchar*) &db)); + (void) push_dynamic(&acl_dbs,(uchar*) &db); } my_qsort((uchar*) dynamic_element(&acl_dbs,0,ACL_DB*),acl_dbs.elements, sizeof(ACL_DB),(qsort_cmp) acl_compare); @@ -712,7 +694,7 @@ my_bool acl_reload(THD *thd) } if ((old_initialized=initialized)) - VOID(pthread_mutex_lock(&acl_cache->lock)); + mysql_mutex_lock(&acl_cache->lock); old_acl_hosts=acl_hosts; old_acl_users=acl_users; @@ -739,7 +721,7 @@ my_bool acl_reload(THD *thd) delete_dynamic(&old_acl_dbs); } if (old_initialized) - VOID(pthread_mutex_unlock(&acl_cache->lock)); + mysql_mutex_unlock(&acl_cache->lock); end: close_thread_tables(thd); DBUG_RETURN(return_val); @@ -891,7 +873,7 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, DBUG_RETURN(0); } - VOID(pthread_mutex_lock(&acl_cache->lock)); + mysql_mutex_lock(&acl_cache->lock); /* Find acl entry in user database. Note, that find_acl_user is not the same, @@ -1070,7 +1052,7 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, else *sctx->priv_host= 0; } - VOID(pthread_mutex_unlock(&acl_cache->lock)); + mysql_mutex_unlock(&acl_cache->lock); DBUG_RETURN(res); } @@ -1117,7 +1099,7 @@ bool acl_getroot_no_password(Security_context *sctx, char *user, char *host, DBUG_RETURN(FALSE); } - VOID(pthread_mutex_lock(&acl_cache->lock)); + mysql_mutex_lock(&acl_cache->lock); sctx->master_access= 0; sctx->db_access= 0; @@ -1171,7 +1153,7 @@ bool acl_getroot_no_password(Security_context *sctx, char *user, char *host, else *sctx->priv_host= 0; } - VOID(pthread_mutex_unlock(&acl_cache->lock)); + mysql_mutex_unlock(&acl_cache->lock); DBUG_RETURN(res); } @@ -1192,7 +1174,7 @@ static void acl_update_user(const char *user, const char *host, USER_RESOURCES *mqh, ulong privileges) { - safe_mutex_assert_owner(&acl_cache->lock); + mysql_mutex_assert_owner(&acl_cache->lock); for (uint i=0 ; i < acl_users.elements ; i++) { @@ -1244,7 +1226,7 @@ static void acl_insert_user(const char *user, const char *host, { ACL_USER acl_user; - safe_mutex_assert_owner(&acl_cache->lock); + mysql_mutex_assert_owner(&acl_cache->lock); acl_user.user=*user ? strdup_root(&mem,user) : 0; update_hostname(&acl_user.host, *host ? strdup_root(&mem, host): 0); @@ -1260,7 +1242,7 @@ static void acl_insert_user(const char *user, const char *host, set_user_salt(&acl_user, password, password_len); - VOID(push_dynamic(&acl_users,(uchar*) &acl_user)); + (void) push_dynamic(&acl_users,(uchar*) &acl_user); if (!acl_user.host.hostname || (acl_user.host.hostname[0] == wild_many && !acl_user.host.hostname[1])) allow_all_hosts=1; // Anyone can connect /* purecov: tested */ @@ -1275,7 +1257,7 @@ static void acl_insert_user(const char *user, const char *host, static void acl_update_db(const char *user, const char *host, const char *db, ulong privileges) { - safe_mutex_assert_owner(&acl_cache->lock); + mysql_mutex_assert_owner(&acl_cache->lock); for (uint i=0 ; i < acl_dbs.elements ; i++) { @@ -1320,13 +1302,13 @@ static void acl_insert_db(const char *user, const char *host, const char *db, ulong privileges) { ACL_DB acl_db; - safe_mutex_assert_owner(&acl_cache->lock); + mysql_mutex_assert_owner(&acl_cache->lock); acl_db.user=strdup_root(&mem,user); update_hostname(&acl_db.host, *host ? strdup_root(&mem,host) : 0); acl_db.db=strdup_root(&mem,db); acl_db.access=privileges; acl_db.sort=get_sort(3,acl_db.host.hostname,acl_db.db,acl_db.user); - VOID(push_dynamic(&acl_dbs,(uchar*) &acl_db)); + (void) push_dynamic(&acl_dbs,(uchar*) &acl_db); my_qsort((uchar*) dynamic_element(&acl_dbs,0,ACL_DB*),acl_dbs.elements, sizeof(ACL_DB),(qsort_cmp) acl_compare); } @@ -1350,7 +1332,7 @@ ulong acl_get(const char *host, const char *ip, acl_entry *entry; DBUG_ENTER("acl_get"); - VOID(pthread_mutex_lock(&acl_cache->lock)); + mysql_mutex_lock(&acl_cache->lock); end=strmov((tmp_db=strmov(strmov(key, ip ? ip : "")+1,user)+1),db); if (lower_case_table_names) { @@ -1362,7 +1344,7 @@ ulong acl_get(const char *host, const char *ip, key_length))) { db_access=entry->access; - VOID(pthread_mutex_unlock(&acl_cache->lock)); + mysql_mutex_unlock(&acl_cache->lock); DBUG_PRINT("exit", ("access: 0x%lx", db_access)); DBUG_RETURN(db_access); } @@ -1416,7 +1398,7 @@ exit: memcpy((uchar*) entry->key,key,key_length); acl_cache->add(entry); } - VOID(pthread_mutex_unlock(&acl_cache->lock)); + mysql_mutex_unlock(&acl_cache->lock); DBUG_PRINT("exit", ("access: 0x%lx", db_access & host_access)); DBUG_RETURN(db_access & host_access); } @@ -1432,10 +1414,11 @@ exit: static void init_check_host(void) { DBUG_ENTER("init_check_host"); - VOID(my_init_dynamic_array(&acl_wild_hosts,sizeof(struct acl_host_and_ip), - acl_users.elements,1)); - VOID(my_hash_init(&acl_check_hosts,system_charset_info,acl_users.elements,0,0, - (my_hash_get_key) check_get_key,0,0)); + (void) my_init_dynamic_array(&acl_wild_hosts,sizeof(struct acl_host_and_ip), + acl_users.elements,1); + (void) my_hash_init(&acl_check_hosts,system_charset_info, + acl_users.elements, 0, 0, + (my_hash_get_key) check_get_key, 0, 0); if (!allow_all_hosts) { for (uint i=0 ; i < acl_users.elements ; i++) @@ -1497,12 +1480,12 @@ bool acl_check_host(const char *host, const char *ip) { if (allow_all_hosts) return 0; - VOID(pthread_mutex_lock(&acl_cache->lock)); + mysql_mutex_lock(&acl_cache->lock); if ((host && my_hash_search(&acl_check_hosts,(uchar*) host,strlen(host))) || (ip && my_hash_search(&acl_check_hosts,(uchar*) ip, strlen(ip)))) { - VOID(pthread_mutex_unlock(&acl_cache->lock)); + mysql_mutex_unlock(&acl_cache->lock); return 0; // Found host } for (uint i=0 ; i < acl_wild_hosts.elements ; i++) @@ -1510,11 +1493,11 @@ bool acl_check_host(const char *host, const char *ip) acl_host_and_ip *acl=dynamic_element(&acl_wild_hosts,i,acl_host_and_ip*); if (compare_hostname(acl, host, ip)) { - VOID(pthread_mutex_unlock(&acl_cache->lock)); + mysql_mutex_unlock(&acl_cache->lock); return 0; // Host ok } } - VOID(pthread_mutex_unlock(&acl_cache->lock)); + mysql_mutex_unlock(&acl_cache->lock); return 1; // Host is not allowed } @@ -1550,7 +1533,7 @@ int check_change_password(THD *thd, const char *host, const char *user, my_strcasecmp(system_charset_info, host, thd->security_ctx->priv_host))) { - if (check_access(thd, UPDATE_ACL, "mysql",0,1,0,0)) + if (check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 0)) return(1); } if (!thd->slave_thread && !thd->security_ctx->user[0]) @@ -1628,11 +1611,11 @@ bool change_password(THD *thd, const char *host, const char *user, if (!(table= open_ltable(thd, &tables, TL_WRITE, 0))) DBUG_RETURN(1); - VOID(pthread_mutex_lock(&acl_cache->lock)); + mysql_mutex_lock(&acl_cache->lock); ACL_USER *acl_user; if (!(acl_user= find_acl_user(host, user, TRUE))) { - VOID(pthread_mutex_unlock(&acl_cache->lock)); + mysql_mutex_unlock(&acl_cache->lock); my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH), MYF(0)); goto end; } @@ -1644,12 +1627,12 @@ bool change_password(THD *thd, const char *host, const char *user, acl_user->user ? acl_user->user : "", new_password, new_password_len)) { - VOID(pthread_mutex_unlock(&acl_cache->lock)); /* purecov: deadcode */ + mysql_mutex_unlock(&acl_cache->lock); /* purecov: deadcode */ goto end; } acl_cache->clear(1); // Clear locked hostname cache - VOID(pthread_mutex_unlock(&acl_cache->lock)); + mysql_mutex_unlock(&acl_cache->lock); result= 0; if (mysql_bin_log.is_open()) { @@ -1660,8 +1643,8 @@ bool change_password(THD *thd, const char *host, const char *user, acl_user->host.hostname ? acl_user->host.hostname : "", new_password)); thd->clear_error(); - result= thd->binlog_query(THD::MYSQL_QUERY_TYPE, buff, query_length, - FALSE, FALSE, 0); + result= thd->binlog_query(THD::STMT_QUERY_TYPE, buff, query_length, + FALSE, FALSE, FALSE, 0); } end: close_thread_tables(thd); @@ -1690,9 +1673,9 @@ bool is_acl_user(const char *host, const char *user) if (!initialized) return TRUE; - VOID(pthread_mutex_lock(&acl_cache->lock)); + mysql_mutex_lock(&acl_cache->lock); res= find_acl_user(host, user, TRUE) != NULL; - VOID(pthread_mutex_unlock(&acl_cache->lock)); + mysql_mutex_unlock(&acl_cache->lock); return res; } @@ -1707,7 +1690,7 @@ find_acl_user(const char *host, const char *user, my_bool exact) DBUG_ENTER("find_acl_user"); DBUG_PRINT("enter",("host: '%s' user: '%s'",host,user)); - safe_mutex_assert_owner(&acl_cache->lock); + mysql_mutex_assert_owner(&acl_cache->lock); for (uint i=0 ; i < acl_users.elements ; i++) { @@ -1790,24 +1773,83 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname, (ip && !wild_compare(ip, host->hostname, 0))); } +/** + Check if the given host name needs to be resolved or not. + Host name has to be resolved if it actually contains *name*. + + For example: + 192.168.1.1 --> FALSE + 192.168.1.0/255.255.255.0 --> FALSE + % --> FALSE + 192.168.1.% --> FALSE + AB% --> FALSE + + AAAAFFFF --> TRUE (Hostname) + AAAA:FFFF:1234:5678 --> FALSE + ::1 --> FALSE + + This function does not check if the given string is a valid host name or + not. It assumes that the argument is a valid host name. + + @param hostname the string to check. + + @return a flag telling if the argument needs to be resolved or not. + @retval TRUE the argument is a host name and needs to be resolved. + @retval FALSE the argument is either an IP address, or a patter and + should not be resolved. +*/ + bool hostname_requires_resolving(const char *hostname) { - char cur; if (!hostname) return FALSE; - size_t namelen= strlen(hostname); - size_t lhlen= strlen(my_localhost); - if ((namelen == lhlen) && - !my_strnncoll(system_charset_info, (const uchar *)hostname, namelen, - (const uchar *)my_localhost, strlen(my_localhost))) + + /* Check if hostname is the localhost. */ + + size_t hostname_len= strlen(hostname); + size_t localhost_len= strlen(my_localhost); + + if (hostname == my_localhost || + (hostname_len == localhost_len && + !my_strnncoll(system_charset_info, + (const uchar *) hostname, hostname_len, + (const uchar *) my_localhost, strlen(my_localhost)))) + { return FALSE; - for (; (cur=*hostname); hostname++) + } + + /* + If the string contains any of {':', '%', '_', '/'}, it is definitely + not a host name: + - ':' means that the string is an IPv6 address; + - '%' or '_' means that the string is a pattern; + - '/' means that the string is an IPv4 network address; + */ + + for (const char *p= hostname; *p; ++p) { - if ((cur != '%') && (cur != '_') && (cur != '.') && (cur != '/') && - ((cur < '0') || (cur > '9'))) - return TRUE; + switch (*p) { + case ':': + case '%': + case '_': + case '/': + return FALSE; + } } - return FALSE; + + /* + Now we have to tell a host name (ab.cd, 12.ab) from an IPv4 address + (12.34.56.78). The assumption is that if the string contains only + digits and dots, it is an IPv4 address. Otherwise -- a host name. + */ + + for (const char *p= hostname; *p; ++p) + { + if (*p != '.' && !my_isdigit(&my_charset_latin1, *p)) + return TRUE; /* a "letter" has been found. */ + } + + return FALSE; /* all characters are either dots or digits. */ } @@ -1910,7 +1952,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, LEX *lex= thd->lex; DBUG_ENTER("replace_user_table"); - safe_mutex_assert_owner(&acl_cache->lock); + mysql_mutex_assert_owner(&acl_cache->lock); if (combo.password.str && combo.password.str[0]) { @@ -3077,8 +3119,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); + thd->clear_current_stmt_binlog_format_row(); #ifdef HAVE_REPLICATION /* @@ -3118,8 +3160,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, if (!revoke_grant) create_new_users= test_if_create_new_users(thd); bool result= FALSE; - rw_wrlock(&LOCK_grant); - pthread_mutex_lock(&acl_cache->lock); + mysql_rwlock_wrlock(&LOCK_grant); + mysql_mutex_lock(&acl_cache->lock); MEM_ROOT *old_root= thd->mem_root; thd->mem_root= &memex; grant_version++; @@ -3224,14 +3266,14 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, } } thd->mem_root= old_root; - pthread_mutex_unlock(&acl_cache->lock); + mysql_mutex_unlock(&acl_cache->lock); if (!result) /* success */ { result= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); if (!result) /* success */ my_ok(thd); @@ -3304,8 +3346,8 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); + thd->clear_current_stmt_binlog_format_row(); #ifdef HAVE_REPLICATION /* @@ -3338,8 +3380,8 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, if (!revoke_grant) create_new_users= test_if_create_new_users(thd); - rw_wrlock(&LOCK_grant); - pthread_mutex_lock(&acl_cache->lock); + mysql_rwlock_wrlock(&LOCK_grant); + mysql_mutex_lock(&acl_cache->lock); MEM_ROOT *old_root= thd->mem_root; thd->mem_root= &memex; @@ -3400,7 +3442,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, } } thd->mem_root= old_root; - pthread_mutex_unlock(&acl_cache->lock); + mysql_mutex_unlock(&acl_cache->lock); if (write_to_binlog) { @@ -3408,7 +3450,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, result= TRUE; } - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); /* Restore the state of binlog format */ thd->current_stmt_binlog_row_based= save_binlog_row_based; @@ -3454,8 +3496,8 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); + thd->clear_current_stmt_binlog_format_row(); #ifdef HAVE_REPLICATION /* @@ -3490,8 +3532,8 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, create_new_users= test_if_create_new_users(thd); /* go through users in user_list */ - rw_wrlock(&LOCK_grant); - VOID(pthread_mutex_lock(&acl_cache->lock)); + mysql_rwlock_wrlock(&LOCK_grant); + mysql_mutex_lock(&acl_cache->lock); grant_version++; int result=0; @@ -3530,14 +3572,14 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, } } } - VOID(pthread_mutex_unlock(&acl_cache->lock)); + mysql_mutex_unlock(&acl_cache->lock); if (!result) { result= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); } - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); close_thread_tables(thd); if (!result) @@ -3581,7 +3623,6 @@ my_bool grant_init() DBUG_RETURN(1); /* purecov: deadcode */ thd->thread_stack= (char*) &thd; thd->store_globals(); - lex_start(thd); return_val= grant_reload(thd); delete thd; /* Remember that we don't have a THD */ @@ -3804,7 +3845,7 @@ static my_bool grant_reload_procs_priv(THD *thd) DBUG_RETURN(TRUE); } - rw_wrlock(&LOCK_grant); + mysql_rwlock_wrlock(&LOCK_grant); /* Save a copy of the current hash if we need to undo the grant load */ old_proc_priv_hash= proc_priv_hash; old_func_priv_hash= func_priv_hash; @@ -3822,7 +3863,7 @@ static my_bool grant_reload_procs_priv(THD *thd) my_hash_free(&old_proc_priv_hash); my_hash_free(&old_func_priv_hash); } - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); close_thread_tables(thd); DBUG_RETURN(return_val); @@ -3870,7 +3911,7 @@ my_bool grant_reload(THD *thd) if (simple_open_n_lock_tables(thd, tables)) goto end; - rw_wrlock(&LOCK_grant); + mysql_rwlock_wrlock(&LOCK_grant); old_column_priv_hash= column_priv_hash; /* @@ -3892,7 +3933,7 @@ my_bool grant_reload(THD *thd) my_hash_free(&old_column_priv_hash); free_root(&old_mem,MYF(0)); } - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); close_thread_tables(thd); /* @@ -3902,9 +3943,9 @@ my_bool grant_reload(THD *thd) if (grant_reload_procs_priv(thd)) return_val= 1; - rw_wrlock(&LOCK_grant); + mysql_rwlock_wrlock(&LOCK_grant); grant_version++; - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); end: DBUG_RETURN(return_val); @@ -3956,6 +3997,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, TABLE_LIST *table, *first_not_own_table= thd->lex->first_not_own_table(); Security_context *sctx= thd->security_ctx; uint i; + ulong orig_want_access= want_access; DBUG_ENTER("check_grant"); DBUG_ASSERT(number > 0); @@ -3980,7 +4022,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, table->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL); } - rw_rdlock(&LOCK_grant); + mysql_rwlock_rdlock(&LOCK_grant); for (table= tables; table && number-- && table != first_not_own_table; table= table->next_global) @@ -3989,6 +4031,33 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, sctx = test(table->security_ctx) ? table->security_ctx : thd->security_ctx; + const ACL_internal_table_access *access; + access= get_cached_table_access(&table->grant.m_internal, + table->get_db_name(), + table->get_table_name()); + + if (access) + { + switch(access->check(orig_want_access, &table->grant.privilege)) + { + case ACL_INTERNAL_ACCESS_GRANTED: + /* + Currently, + - the information_schema does not subclass ACL_internal_table_access, + there are no per table privilege checks for I_S, + - the performance schema does use per tables checks, but at most + returns 'CHECK_GRANT', and never 'ACCESS_GRANTED'. + so this branch is not used. + */ + DBUG_ASSERT(0); + case ACL_INTERNAL_ACCESS_DENIED: + goto err; + case ACL_INTERNAL_ACCESS_CHECK_GRANT: + break; + } + } + + want_access= orig_want_access; want_access&= ~sctx->master_access; if (!want_access) continue; // ok @@ -4041,11 +4110,11 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, goto err; // impossible } } - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); DBUG_RETURN(FALSE); err: - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); if (!no_errors) // Not a silent skip of table { char command[128]; @@ -4060,96 +4129,6 @@ err: } -/** - Check if all tables in the table list has any of the requested table level - privileges matching the current user. - - @param thd A pointer to the thread context. - @param required_access Set of privileges to compare against. - @param tables[in,out] A list of tables to be checked. - - @note If the table grant hash contains any grant table, this table will be - attached to the corresponding TABLE_LIST object in 'tables'. - - @return - @retval TRUE There is a privilege on the table level granted to the - current user. - @retval FALSE There are no privileges on the table level granted to the - current user. -*/ - -bool has_any_table_level_privileges(THD *thd, ulong required_access, - TABLE_LIST *tables) -{ - - Security_context *sctx; - GRANT_TABLE *grant_table; - TABLE_LIST *table; - - /* For each table in tables */ - for (table= tables; table; table= table->next_global) - { - /* - If this table is a VIEW, then it will supply its own security context. - This is because VIEWs can have a DEFINER or an INVOKER security role. - */ - sctx= table->security_ctx ? table->security_ctx : thd->security_ctx; - - /* - Get privileges from table_priv and column_priv tables by searching - the cache. - */ - rw_rdlock(&LOCK_grant); - grant_table= table_hash_search(sctx->host, sctx->ip, - table->db, sctx->priv_user, - table->table_name,0); - rw_unlock(&LOCK_grant); - - /* Stop if there are no grants for the current user */ - if (!grant_table) - return FALSE; - - /* - Save a pointer to the found grant_table in the table object. - This pointer can later be used to verify other access requirements - without having to look up the grant table in the hash. - */ - table->grant.grant_table= grant_table; - table->grant.version= grant_version; - table->grant.privilege|= grant_table->privs; - /* - Save all privileges which might be subject to column privileges - but not which aren't yet granted by table level ACLs. - This is can later be used for column privilege checks. - */ - table->grant.want_privilege= ((required_access & COL_ACLS) - & ~table->grant.privilege); - - /* - If the requested privileges share any intersection with the current - table privileges we have found at least one common privilege on the - table level. - */ - if (grant_table->privs & required_access) - continue; /* Check next table */ - - /* - There are no table level privileges which satisfies any of the - requested privileges. There might still be column privileges which - does though. - */ - return FALSE; - } - - /* - All tables in TABLE_LIST satisfy the requirement of having any - privilege on the table level. - */ - - return TRUE; -} - - /* Check column rights in given security context @@ -4181,7 +4160,7 @@ bool check_grant_column(THD *thd, GRANT_INFO *grant, if (!want_access) DBUG_RETURN(0); // Already checked - rw_rdlock(&LOCK_grant); + mysql_rwlock_rdlock(&LOCK_grant); /* reload table if someone has modified any grants */ @@ -4199,12 +4178,12 @@ bool check_grant_column(THD *thd, GRANT_INFO *grant, grant_column=column_hash_search(grant_table, name, length); if (grant_column && !(~grant_column->rights & want_access)) { - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); DBUG_RETURN(0); } err: - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); char command[128]; get_privilege_desc(command, sizeof(command), want_access); my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), @@ -4319,7 +4298,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access_arg, */ bool using_column_privileges= FALSE; - rw_rdlock(&LOCK_grant); + mysql_rwlock_rdlock(&LOCK_grant); for (; !fields->end_of_fields(); fields->next()) { @@ -4360,11 +4339,11 @@ bool check_grant_all_columns(THD *thd, ulong want_access_arg, goto err; } } - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); return 0; err: - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); char command[128]; get_privilege_desc(command, sizeof(command), want_access); @@ -4422,7 +4401,7 @@ bool check_grant_db(THD *thd,const char *db) len= (uint) (strmov(strmov(helping, sctx->priv_user) + 1, db) - helping) + 1; - rw_rdlock(&LOCK_grant); + mysql_rwlock_rdlock(&LOCK_grant); for (uint idx=0 ; idx < column_priv_hash.records ; idx++) { @@ -4442,7 +4421,7 @@ bool check_grant_db(THD *thd,const char *db) error= check_grant_db_routine(thd, db, &proc_priv_hash) && check_grant_db_routine(thd, db, &func_priv_hash); - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); return error; } @@ -4478,7 +4457,7 @@ bool check_grant_routine(THD *thd, ulong want_access, if (!want_access) DBUG_RETURN(0); // ok - rw_rdlock(&LOCK_grant); + mysql_rwlock_rdlock(&LOCK_grant); for (table= procs; table; table= table->next_global) { GRANT_NAME *grant_proc; @@ -4492,10 +4471,10 @@ bool check_grant_routine(THD *thd, ulong want_access, goto err; } } - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); DBUG_RETURN(0); err: - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); if (!no_errors) { char buff[1024]; @@ -4536,13 +4515,13 @@ bool check_routine_level_acl(THD *thd, const char *db, const char *name, bool no_routine_acl= 1; GRANT_NAME *grant_proc; Security_context *sctx= thd->security_ctx; - rw_rdlock(&LOCK_grant); + mysql_rwlock_rdlock(&LOCK_grant); if ((grant_proc= routine_hash_search(sctx->priv_host, sctx->ip, db, sctx->priv_user, name, is_proc, 0))) no_routine_acl= !(grant_proc->privs & SHOW_PROC_ACLS); - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); return no_routine_acl; } @@ -4558,7 +4537,7 @@ ulong get_table_grant(THD *thd, TABLE_LIST *table) const char *db = table->db ? table->db : thd->db; GRANT_TABLE *grant_table; - rw_rdlock(&LOCK_grant); + mysql_rwlock_rdlock(&LOCK_grant); #ifdef EMBEDDED_LIBRARY grant_table= NULL; #else @@ -4570,7 +4549,7 @@ ulong get_table_grant(THD *thd, TABLE_LIST *table) if (grant_table) table->grant.privilege|= grant_table->privs; privilege= table->grant.privilege; - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); return privilege; } @@ -4601,7 +4580,7 @@ ulong get_column_grant(THD *thd, GRANT_INFO *grant, GRANT_COLUMN *grant_column; ulong priv; - rw_rdlock(&LOCK_grant); + mysql_rwlock_rdlock(&LOCK_grant); /* reload table if someone has modified any grants */ if (grant->version != grant_version) { @@ -4624,7 +4603,7 @@ ulong get_column_grant(THD *thd, GRANT_INFO *grant, else priv= (grant->privilege | grant_table->privs | grant_column->rights); } - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); return priv; } @@ -4691,14 +4670,14 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) DBUG_RETURN(TRUE); } - rw_rdlock(&LOCK_grant); - VOID(pthread_mutex_lock(&acl_cache->lock)); + mysql_rwlock_rdlock(&LOCK_grant); + mysql_mutex_lock(&acl_cache->lock); acl_user= find_acl_user(lex_user->host.str, lex_user->user.str, TRUE); if (!acl_user) { - VOID(pthread_mutex_unlock(&acl_cache->lock)); - rw_unlock(&LOCK_grant); + mysql_mutex_unlock(&acl_cache->lock); + mysql_rwlock_unlock(&LOCK_grant); my_error(ER_NONEXISTING_GRANT, MYF(0), lex_user->user.str, lex_user->host.str); @@ -4715,8 +4694,8 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) if (protocol->send_result_set_metadata(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) { - VOID(pthread_mutex_unlock(&acl_cache->lock)); - rw_unlock(&LOCK_grant); + mysql_mutex_unlock(&acl_cache->lock); + mysql_rwlock_unlock(&LOCK_grant); DBUG_RETURN(TRUE); } @@ -5026,8 +5005,8 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) } end: - VOID(pthread_mutex_unlock(&acl_cache->lock)); - rw_unlock(&LOCK_grant); + mysql_mutex_unlock(&acl_cache->lock); + mysql_rwlock_unlock(&LOCK_grant); my_eof(thd); DBUG_RETURN(error); @@ -5151,14 +5130,14 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc) { ACL_USER *acl_user; - pthread_mutex_lock(&acl_cache->lock); + mysql_mutex_lock(&acl_cache->lock); if (initialized && (acl_user= find_acl_user(host,user, FALSE))) uc->user_resources= acl_user->user_resource; else bzero((char*) &uc->user_resources, sizeof(uc->user_resources)); - pthread_mutex_unlock(&acl_cache->lock); + mysql_mutex_unlock(&acl_cache->lock); } /* @@ -5244,7 +5223,7 @@ ACL_USER *check_acl_user(LEX_USER *user_name, ACL_USER *acl_user= 0; uint counter; - safe_mutex_assert_owner(&acl_cache->lock); + mysql_mutex_assert_owner(&acl_cache->lock); for (counter= 0 ; counter < acl_users.elements ; counter++) { @@ -5513,7 +5492,7 @@ static int handle_grant_struct(uint struct_no, bool drop, LINT_INIT(user); LINT_INIT(host); - safe_mutex_assert_owner(&acl_cache->lock); + mysql_mutex_assert_owner(&acl_cache->lock); /* Get the number of elements in the in-memory structure. */ switch (struct_no) { @@ -5818,8 +5797,8 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list) row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); + thd->clear_current_stmt_binlog_format_row(); /* CREATE USER may be skipped on replication client. */ if ((result= open_grant_tables(thd, tables))) @@ -5829,8 +5808,8 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list) DBUG_RETURN(result != 1); } - rw_wrlock(&LOCK_grant); - VOID(pthread_mutex_lock(&acl_cache->lock)); + mysql_rwlock_wrlock(&LOCK_grant); + mysql_mutex_lock(&acl_cache->lock); while ((tmp_user_name= user_list++)) { @@ -5860,7 +5839,7 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list) } } - VOID(pthread_mutex_unlock(&acl_cache->lock)); + mysql_mutex_unlock(&acl_cache->lock); if (result) my_error(ER_CANNOT_USER, MYF(0), "CREATE USER", wrong_users.c_ptr_safe()); @@ -5868,7 +5847,7 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list) if (some_users_created) result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); close_thread_tables(thd); /* Restore the state of binlog format */ thd->current_stmt_binlog_row_based= save_binlog_row_based; @@ -5906,8 +5885,8 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list) row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); + thd->clear_current_stmt_binlog_format_row(); /* DROP USER may be skipped on replication client. */ if ((result= open_grant_tables(thd, tables))) @@ -5919,8 +5898,8 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list) thd->variables.sql_mode&= ~MODE_PAD_CHAR_TO_FULL_LENGTH; - rw_wrlock(&LOCK_grant); - VOID(pthread_mutex_lock(&acl_cache->lock)); + mysql_rwlock_wrlock(&LOCK_grant); + mysql_mutex_lock(&acl_cache->lock); while ((tmp_user_name= user_list++)) { @@ -5941,7 +5920,7 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list) /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */ rebuild_check_host(); - VOID(pthread_mutex_unlock(&acl_cache->lock)); + mysql_mutex_unlock(&acl_cache->lock); if (result) my_error(ER_CANNOT_USER, MYF(0), "DROP USER", wrong_users.c_ptr_safe()); @@ -5949,7 +5928,7 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list) if (some_users_deleted) result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); close_thread_tables(thd); thd->variables.sql_mode= old_sql_mode; /* Restore the state of binlog format */ @@ -5988,8 +5967,8 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); + thd->clear_current_stmt_binlog_format_row(); /* RENAME USER may be skipped on replication client. */ if ((result= open_grant_tables(thd, tables))) @@ -5999,8 +5978,8 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) DBUG_RETURN(result != 1); } - rw_wrlock(&LOCK_grant); - VOID(pthread_mutex_lock(&acl_cache->lock)); + mysql_rwlock_wrlock(&LOCK_grant); + mysql_mutex_lock(&acl_cache->lock); while ((tmp_user_from= user_list++)) { @@ -6034,7 +6013,7 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */ rebuild_check_host(); - VOID(pthread_mutex_unlock(&acl_cache->lock)); + mysql_mutex_unlock(&acl_cache->lock); if (result) my_error(ER_CANNOT_USER, MYF(0), "RENAME USER", wrong_users.c_ptr_safe()); @@ -6042,7 +6021,7 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) if (some_users_renamed && mysql_bin_log.is_open()) result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); close_thread_tables(thd); /* Restore the state of binlog format */ thd->current_stmt_binlog_row_based= save_binlog_row_based; @@ -6078,8 +6057,8 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list) row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); + thd->clear_current_stmt_binlog_format_row(); if ((result= open_grant_tables(thd, tables))) { @@ -6088,8 +6067,8 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list) DBUG_RETURN(result != 1); } - rw_wrlock(&LOCK_grant); - VOID(pthread_mutex_lock(&acl_cache->lock)); + mysql_rwlock_wrlock(&LOCK_grant); + mysql_mutex_lock(&acl_cache->lock); LEX_USER *lex_user, *tmp_lex_user; List_iterator <LEX_USER> user_list(list); @@ -6228,12 +6207,12 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list) } while (revoked); } - VOID(pthread_mutex_unlock(&acl_cache->lock)); + mysql_mutex_unlock(&acl_cache->lock); int binlog_error= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); close_thread_tables(thd); /* error for writing binary log has already been reported */ @@ -6341,16 +6320,16 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, /* Be sure to pop this before exiting this scope! */ thd->push_internal_handler(&error_handler); - rw_wrlock(&LOCK_grant); - VOID(pthread_mutex_lock(&acl_cache->lock)); + mysql_rwlock_wrlock(&LOCK_grant); + mysql_mutex_lock(&acl_cache->lock); /* This statement will be replicated as a statement, even when using row-based replication. The flag will be reset at the end of the statement. */ - save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); + thd->clear_current_stmt_binlog_format_row(); /* Remove procedure access */ do @@ -6381,8 +6360,8 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, } } while (revoked); - VOID(pthread_mutex_unlock(&acl_cache->lock)); - rw_unlock(&LOCK_grant); + mysql_mutex_unlock(&acl_cache->lock); + mysql_rwlock_unlock(&LOCK_grant); close_thread_tables(thd); thd->pop_internal_handler(); @@ -6424,7 +6403,7 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, combo->user.str= sctx->user; - VOID(pthread_mutex_lock(&acl_cache->lock)); + mysql_mutex_lock(&acl_cache->lock); if ((au= find_acl_user(combo->host.str=(char*)sctx->host_or_ip,combo->user.str,FALSE))) goto found_acl; @@ -6435,11 +6414,11 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, if((au= find_acl_user(combo->host.str=(char*)"%", combo->user.str, FALSE))) goto found_acl; - VOID(pthread_mutex_unlock(&acl_cache->lock)); + mysql_mutex_unlock(&acl_cache->lock); DBUG_RETURN(TRUE); found_acl: - VOID(pthread_mutex_unlock(&acl_cache->lock)); + mysql_mutex_unlock(&acl_cache->lock); bzero((char*)tables, sizeof(TABLE_LIST)); user_list.empty(); @@ -6592,13 +6571,14 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond) ulong want_access; char buff[100]; TABLE *table= tables->table; - bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1,0); + bool no_global_access= check_access(thd, SELECT_ACL, "mysql", + NULL, NULL, 1, 1); char *curr_host= thd->security_ctx->priv_host_name(); DBUG_ENTER("fill_schema_user_privileges"); if (!initialized) DBUG_RETURN(0); - pthread_mutex_lock(&acl_cache->lock); + mysql_mutex_lock(&acl_cache->lock); for (counter=0 ; counter < acl_users.elements ; counter++) { @@ -6648,7 +6628,7 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond) } } err: - pthread_mutex_unlock(&acl_cache->lock); + mysql_mutex_unlock(&acl_cache->lock); DBUG_RETURN(error); #else @@ -6666,13 +6646,14 @@ int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond) ulong want_access; char buff[100]; TABLE *table= tables->table; - bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1,0); + bool no_global_access= check_access(thd, SELECT_ACL, "mysql", + NULL, NULL, 1, 1); char *curr_host= thd->security_ctx->priv_host_name(); DBUG_ENTER("fill_schema_schema_privileges"); if (!initialized) DBUG_RETURN(0); - pthread_mutex_lock(&acl_cache->lock); + mysql_mutex_lock(&acl_cache->lock); for (counter=0 ; counter < acl_dbs.elements ; counter++) { @@ -6725,7 +6706,7 @@ int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond) } } err: - pthread_mutex_unlock(&acl_cache->lock); + mysql_mutex_unlock(&acl_cache->lock); DBUG_RETURN(error); #else @@ -6741,11 +6722,12 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond) uint index; char buff[100]; TABLE *table= tables->table; - bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1,0); + bool no_global_access= check_access(thd, SELECT_ACL, "mysql", + NULL, NULL, 1, 1); char *curr_host= thd->security_ctx->priv_host_name(); DBUG_ENTER("fill_schema_table_privileges"); - rw_rdlock(&LOCK_grant); + mysql_rwlock_rdlock(&LOCK_grant); for (index=0 ; index < column_priv_hash.records ; index++) { @@ -6808,7 +6790,7 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond) } } err: - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); DBUG_RETURN(error); #else @@ -6824,11 +6806,12 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond) uint index; char buff[100]; TABLE *table= tables->table; - bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1,0); + bool no_global_access= check_access(thd, SELECT_ACL, "mysql", + NULL, NULL, 1, 1); char *curr_host= thd->security_ctx->priv_host_name(); DBUG_ENTER("fill_schema_table_privileges"); - rw_rdlock(&LOCK_grant); + mysql_rwlock_rdlock(&LOCK_grant); for (index=0 ; index < column_priv_hash.records ; index++) { @@ -6889,7 +6872,7 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond) } } err: - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); DBUG_RETURN(error); #else @@ -6941,7 +6924,7 @@ void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, grant->privilege|= acl_get(sctx->host, sctx->ip, sctx->priv_user, db, 0); /* table privileges */ - rw_rdlock(&LOCK_grant); + mysql_rwlock_rdlock(&LOCK_grant); if (grant->version != grant_version) { grant->grant_table= @@ -6954,7 +6937,7 @@ void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, { grant->privilege|= grant->grant_table->privs; } - rw_unlock(&LOCK_grant); + mysql_rwlock_unlock(&LOCK_grant); DBUG_PRINT("info", ("privilege 0x%lx", grant->privilege)); DBUG_VOID_RETURN; @@ -6973,3 +6956,104 @@ bool check_routine_level_acl(THD *thd, const char *db, const char *name, } #endif + +struct ACL_internal_schema_registry_entry +{ + const LEX_STRING *m_name; + const ACL_internal_schema_access *m_access; +}; + +/** + Internal schema registered. + Currently, this is only: + - performance_schema + - information_schema, + This can be reused later for: + - mysql +*/ +static ACL_internal_schema_registry_entry registry_array[2]; +static uint m_registry_array_size= 0; + +/** + Add an internal schema to the registry. + @param name the schema name + @param access the schema ACL specific rules +*/ +void ACL_internal_schema_registry::register_schema + (const LEX_STRING *name, const ACL_internal_schema_access *access) +{ + DBUG_ASSERT(m_registry_array_size < array_elements(registry_array)); + + /* Not thread safe, and does not need to be. */ + registry_array[m_registry_array_size].m_name= name; + registry_array[m_registry_array_size].m_access= access; + m_registry_array_size++; +} + +/** + Search per internal schema ACL by name. + @param name a schema name + @return per schema rules, or NULL +*/ +const ACL_internal_schema_access * +ACL_internal_schema_registry::lookup(const char *name) +{ + DBUG_ASSERT(name != NULL); + + uint i; + + for (i= 0; i<m_registry_array_size; i++) + { + if (my_strcasecmp(system_charset_info, registry_array[i].m_name->str, + name) == 0) + return registry_array[i].m_access; + } + return NULL; +} + +/** + Get a cached internal schema access. + @param grant_internal_info the cache + @param schema_name the name of the internal schema +*/ +const ACL_internal_schema_access * +get_cached_schema_access(GRANT_INTERNAL_INFO *grant_internal_info, + const char *schema_name) +{ + if (grant_internal_info) + { + if (! grant_internal_info->m_schema_lookup_done) + { + grant_internal_info->m_schema_access= + ACL_internal_schema_registry::lookup(schema_name); + grant_internal_info->m_schema_lookup_done= TRUE; + } + return grant_internal_info->m_schema_access; + } + return ACL_internal_schema_registry::lookup(schema_name); +} + +/** + Get a cached internal table access. + @param grant_internal_info the cache + @param schema_name the name of the internal schema + @param table_name the name of the internal table +*/ +const ACL_internal_table_access * +get_cached_table_access(GRANT_INTERNAL_INFO *grant_internal_info, + const char *schema_name, + const char *table_name) +{ + DBUG_ASSERT(grant_internal_info); + if (! grant_internal_info->m_table_lookup_done) + { + const ACL_internal_schema_access *schema_access; + schema_access= get_cached_schema_access(grant_internal_info, schema_name); + if (schema_access) + grant_internal_info->m_table_access= schema_access->lookup(table_name); + grant_internal_info->m_table_lookup_done= TRUE; + } + return grant_internal_info->m_table_access; +} + + diff --git a/sql/sql_acl.h b/sql/sql_acl.h index 25a4766e58c..8d521be2bc4 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -1,7 +1,7 @@ #ifndef SQL_ACL_INCLUDED #define SQL_ACL_INCLUDED -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright (C) 2000-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -169,6 +169,7 @@ enum mysql_db_table_field }; extern const TABLE_FIELD_DEF mysql_db_table_def; +extern bool mysql_user_table_is_in_short_password_format; /* Classes */ @@ -277,12 +278,139 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, bool check_routine_level_acl(THD *thd, const char *db, const char *name, bool is_proc); bool is_acl_user(const char *host, const char *user); -bool has_any_table_level_privileges(THD *thd, ulong required_access, - TABLE_LIST *tables); #ifdef NO_EMBEDDED_ACCESS_CHECKS #define check_grant(A,B,C,D,E,F) 0 #define check_grant_db(A,B) 0 -#define has_any_table_level_privileges(A,B,C) 0 #endif + +/** + Result of an access check for an internal schema or table. + Internal ACL checks are always performed *before* using + the grant tables. + This mechanism enforces that the server implementation has full + control on its internal tables. + Depending on the internal check result, the server implementation + can choose to: + - always allow access, + - always deny access, + - delegate the decision to the database administrator, + by using the grant tables. +*/ +enum ACL_internal_access_result +{ + /** + Access granted for all the requested privileges, + do not use the grant tables. + This flag is used only for the INFORMATION_SCHEMA privileges, + for compatibility reasons. + */ + ACL_INTERNAL_ACCESS_GRANTED, + /** Access denied, do not use the grant tables. */ + ACL_INTERNAL_ACCESS_DENIED, + /** No decision yet, use the grant tables. */ + ACL_INTERNAL_ACCESS_CHECK_GRANT +}; + +/** + Per internal table ACL access rules. + This class is an interface. + Per table(s) specific access rule should be implemented in a subclass. + @sa ACL_internal_schema_access +*/ +class ACL_internal_table_access +{ +public: + ACL_internal_table_access() + {} + + virtual ~ACL_internal_table_access() + {} + + /** + Check access to an internal table. + When a privilege is granted, this method add the requested privilege + to save_priv. + @param want_access the privileges requested + @param [in, out] save_priv the privileges granted + @return + @retval ACL_INTERNAL_ACCESS_GRANTED All the requested privileges + are granted, and saved in save_priv. + @retval ACL_INTERNAL_ACCESS_DENIED At least one of the requested + privileges was denied. + @retval ACL_INTERNAL_ACCESS_CHECK_GRANT No requested privilege + was denied, and grant should be checked for at least one + privilege. Requested privileges that are granted, if any, are saved + in save_priv. + */ + virtual ACL_internal_access_result check(ulong want_access, + ulong *save_priv) const= 0; +}; + +/** + Per internal schema ACL access rules. + This class is an interface. + Each per schema specific access rule should be implemented + in a different subclass, and registered. + Per schema access rules can control: + - every schema privileges on schema.* + - every table privileges on schema.table + @sa ACL_internal_schema_registry +*/ +class ACL_internal_schema_access +{ +public: + ACL_internal_schema_access() + {} + + virtual ~ACL_internal_schema_access() + {} + + /** + Check access to an internal schema. + @param want_access the privileges requested + @param [in, out] save_priv the privileges granted + @return + @retval ACL_INTERNAL_ACCESS_GRANTED All the requested privileges + are granted, and saved in save_priv. + @retval ACL_INTERNAL_ACCESS_DENIED At least one of the requested + privileges was denied. + @retval ACL_INTERNAL_ACCESS_CHECK_GRANT No requested privilege + was denied, and grant should be checked for at least one + privilege. Requested privileges that are granted, if any, are saved + in save_priv. + */ + virtual ACL_internal_access_result check(ulong want_access, + ulong *save_priv) const= 0; + + /** + Search for per table ACL access rules by table name. + @param name the table name + @return per table access rules, or NULL + */ + virtual const ACL_internal_table_access *lookup(const char *name) const= 0; +}; + +/** + A registry for per internal schema ACL. + An 'internal schema' is a database schema maintained by the + server implementation, such as 'performance_schema' and 'INFORMATION_SCHEMA'. +*/ +class ACL_internal_schema_registry +{ +public: + static void register_schema(const LEX_STRING *name, + const ACL_internal_schema_access *access); + static const ACL_internal_schema_access *lookup(const char *name); +}; + +const ACL_internal_schema_access * +get_cached_schema_access(GRANT_INTERNAL_INFO *grant_internal_info, + const char *schema_name); + +const ACL_internal_table_access * +get_cached_table_access(GRANT_INTERNAL_INFO *grant_internal_info, + const char *schema_name, + const char *table_name); + #endif /* SQL_ACL_INCLUDED */ diff --git a/sql/sql_audit.cc b/sql/sql_audit.cc new file mode 100644 index 00000000000..5190cba64de --- /dev/null +++ b/sql/sql_audit.cc @@ -0,0 +1,477 @@ +/* Copyright (C) 2007 MySQL AB, 2008-2009 Sun Microsystems, Inc + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "mysql_priv.h" +#include "sql_audit.h" + +extern int initialize_audit_plugin(st_plugin_int *plugin); +extern int finalize_audit_plugin(st_plugin_int *plugin); + +#ifndef EMBEDDED_LIBRARY + +unsigned long mysql_global_audit_mask[MYSQL_AUDIT_CLASS_MASK_SIZE]; + +static mysql_mutex_t LOCK_audit_mask; + +static void event_class_dispatch(THD *thd, const struct mysql_event *event); + + +static inline +void set_audit_mask(unsigned long *mask, uint event_class) +{ + mask[0]= 1; + mask[0]<<= event_class; +} + +static inline +void add_audit_mask(unsigned long *mask, const unsigned long *rhs) +{ + mask[0]|= rhs[0]; +} + +static inline +bool check_audit_mask(const unsigned long *lhs, + const unsigned long *rhs) +{ + return !(lhs[0] & rhs[0]); +} + + +typedef void (*audit_handler_t)(THD *thd, uint event_subtype, va_list ap); + +/** + MYSQL_AUDIT_GENERAL_CLASS handler + + @param[in] thd + @param[in] event_subtype + @param[in] error_code + @param[in] ap + +*/ + +static void general_class_handler(THD *thd, uint event_subtype, va_list ap) +{ + mysql_event_general event; + event.event_class= MYSQL_AUDIT_GENERAL_CLASS; + event.general_error_code= va_arg(ap, int); + event.general_thread_id= thd ? thd->thread_id : 0; + event.general_time= va_arg(ap, time_t); + event.general_user= va_arg(ap, const char *); + event.general_user_length= va_arg(ap, unsigned int); + event.general_command= va_arg(ap, const char *); + event.general_command_length= va_arg(ap, unsigned int); + event.general_query= va_arg(ap, const char *); + event.general_query_length= va_arg(ap, unsigned int); + event.general_charset= va_arg(ap, struct charset_info_st *); + event.general_rows= (unsigned long long) va_arg(ap, ha_rows); + event_class_dispatch(thd, (const mysql_event*) &event); +} + + +static audit_handler_t audit_handlers[] = +{ + general_class_handler +}; + +static const uint audit_handlers_count= + (sizeof(audit_handlers) / sizeof(audit_handler_t)); + + +/** + Acquire and lock any additional audit plugins as required + + @param[in] thd + @param[in] plugin + @param[in] arg + + @retval FALSE Always +*/ + +static my_bool acquire_plugins(THD *thd, plugin_ref plugin, void *arg) +{ + uint event_class= *(uint*) arg; + unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE]; + st_mysql_audit *data= plugin_data(plugin, struct st_mysql_audit *); + + set_audit_mask(event_class_mask, event_class); + + /* Check if this plugin is interested in the event */ + if (check_audit_mask(data->class_mask, event_class_mask)) + return 0; + + /* + Check if this plugin may already be registered. This will fail to + acquire a newly installed plugin on a specific corner case where + one or more event classes already in use by the calling thread + are an event class of which the audit plugin has interest. + */ + if (!check_audit_mask(data->class_mask, thd->audit_class_mask)) + return 0; + + /* Check if we need to initialize the array of acquired plugins */ + if (unlikely(!thd->audit_class_plugins.buffer)) + { + /* specify some reasonable initialization defaults */ + my_init_dynamic_array(&thd->audit_class_plugins, + sizeof(plugin_ref), 16, 16); + } + + /* lock the plugin and add it to the list */ + plugin= my_plugin_lock(NULL, &plugin); + insert_dynamic(&thd->audit_class_plugins, (uchar*) &plugin); + + return 0; +} + + +/** + Notify the audit system of an event + + @param[in] thd + @param[in] event_class + @param[in] event_subtype + @param[in] error_code + +*/ + +void mysql_audit_notify(THD *thd, uint event_class, uint event_subtype, ...) +{ + va_list ap; + audit_handler_t *handlers= audit_handlers + event_class; + unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE]; + + DBUG_ASSERT(event_class < audit_handlers_count); + + set_audit_mask(event_class_mask, event_class); + /* + Check to see if we have acquired the audit plugins for the + required audit event classes. + */ + if (thd && check_audit_mask(thd->audit_class_mask, event_class_mask)) + { + plugin_foreach(thd, acquire_plugins, MYSQL_AUDIT_PLUGIN, &event_class); + add_audit_mask(thd->audit_class_mask, event_class_mask); + } + + va_start(ap, event_subtype); + (*handlers)(thd, event_subtype, ap); + va_end(ap); +} + + +/** + Release any resources associated with the current thd. + + @param[in] thd + +*/ + +void mysql_audit_release(THD *thd) +{ + plugin_ref *plugins, *plugins_last; + + if (!thd || !(thd->audit_class_plugins.elements)) + return; + + plugins= (plugin_ref*) thd->audit_class_plugins.buffer; + plugins_last= plugins + thd->audit_class_plugins.elements; + for (; plugins < plugins_last; plugins++) + { + st_mysql_audit *data= plugin_data(*plugins, struct st_mysql_audit *); + + /* Check to see if the plugin has a release method */ + if (!(data->release_thd)) + continue; + + /* Tell the plugin to release its resources */ + data->release_thd(thd); + } + + /* Now we actually unlock the plugins */ + plugin_unlock_list(NULL, (plugin_ref*) thd->audit_class_plugins.buffer, + thd->audit_class_plugins.elements); + + /* Reset the state of thread values */ + reset_dynamic(&thd->audit_class_plugins); + bzero(thd->audit_class_mask, sizeof(thd->audit_class_mask)); +} + + +/** + Initialize thd variables used by Audit + + @param[in] thd + +*/ + +void mysql_audit_init_thd(THD *thd) +{ + bzero(&thd->audit_class_plugins, sizeof(thd->audit_class_plugins)); + bzero(thd->audit_class_mask, sizeof(thd->audit_class_mask)); +} + + +/** + Free thd variables used by Audit + + @param[in] thd + @param[in] plugin + @param[in] arg + + @retval FALSE Always +*/ + +void mysql_audit_free_thd(THD *thd) +{ + mysql_audit_release(thd); + DBUG_ASSERT(thd->audit_class_plugins.elements == 0); + delete_dynamic(&thd->audit_class_plugins); +} + +#ifdef HAVE_PSI_INTERFACE +static PSI_mutex_key key_LOCK_audit_mask; + +static PSI_mutex_info all_audit_mutexes[]= +{ + { &key_LOCK_audit_mask, "LOCK_audit_mask", PSI_FLAG_GLOBAL} +}; + +static void init_audit_psi_keys(void) +{ + const char* category= "sql"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_audit_mutexes); + PSI_server->register_mutex(category, all_audit_mutexes, count); +} +#endif /* HAVE_PSI_INTERFACE */ + +/** + Initialize Audit global variables +*/ + +void mysql_audit_initialize() +{ +#ifdef HAVE_PSI_INTERFACE + init_audit_psi_keys(); +#endif + + mysql_mutex_init(key_LOCK_audit_mask, &LOCK_audit_mask, MY_MUTEX_INIT_FAST); + bzero(mysql_global_audit_mask, sizeof(mysql_global_audit_mask)); +} + + +/** + Finalize Audit global variables +*/ + +void mysql_audit_finalize() +{ + mysql_mutex_destroy(&LOCK_audit_mask); +} + + +/** + Initialize an Audit plug-in + + @param[in] plugin + + @retval FALSE OK + @retval TRUE There was an error. +*/ + +int initialize_audit_plugin(st_plugin_int *plugin) +{ + st_mysql_audit *data= (st_mysql_audit*) plugin->plugin->info; + + if (!data->class_mask || !data->event_notify || + !data->class_mask[0]) + { + sql_print_error("Plugin '%s' has invalid data.", + plugin->name.str); + return 1; + } + + if (plugin->plugin->init && plugin->plugin->init(NULL)) + { + sql_print_error("Plugin '%s' init function returned error.", + plugin->name.str); + return 1; + } + + /* Make the interface info more easily accessible */ + plugin->data= plugin->plugin->info; + + /* Add the bits the plugin is interested in to the global mask */ + mysql_mutex_lock(&LOCK_audit_mask); + add_audit_mask(mysql_global_audit_mask, data->class_mask); + mysql_mutex_unlock(&LOCK_audit_mask); + + return 0; +} + + +/** + Performs a bitwise OR of the installed plugins event class masks + + @param[in] thd + @param[in] plugin + @param[in] arg + + @retval FALSE always +*/ +static my_bool calc_class_mask(THD *thd, plugin_ref plugin, void *arg) +{ + st_mysql_audit *data= plugin_data(plugin, struct st_mysql_audit *); + if ((data= plugin_data(plugin, struct st_mysql_audit *))) + add_audit_mask((unsigned long *) arg, data->class_mask); + return 0; +} + + +/** + Finalize an Audit plug-in + + @param[in] plugin + + @retval FALSE OK + @retval TRUE There was an error. +*/ +int finalize_audit_plugin(st_plugin_int *plugin) +{ + unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE]; + + if (plugin->plugin->deinit && plugin->plugin->deinit(NULL)) + { + DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.", + plugin->name.str)); + DBUG_EXECUTE("finalize_audit_plugin", return 1; ); + } + + plugin->data= NULL; + bzero(&event_class_mask, sizeof(event_class_mask)); + + /* Iterate through all the installed plugins to create new mask */ + + /* + LOCK_audit_mask/LOCK_plugin order is not fixed, but serialized with table + lock on mysql.plugin. + */ + mysql_mutex_lock(&LOCK_audit_mask); + plugin_foreach(current_thd, calc_class_mask, MYSQL_AUDIT_PLUGIN, + &event_class_mask); + + /* Set the global audit mask */ + bmove(mysql_global_audit_mask, event_class_mask, sizeof(event_class_mask)); + mysql_mutex_unlock(&LOCK_audit_mask); + + return 0; +} + + +/** + Dispatches an event by invoking the plugin's event_notify method. + + @param[in] thd + @param[in] plugin + @param[in] arg + + @retval FALSE always +*/ + +static my_bool plugins_dispatch(THD *thd, plugin_ref plugin, void *arg) +{ + const struct mysql_event *event= (const struct mysql_event *) arg; + unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE]; + st_mysql_audit *data= plugin_data(plugin, struct st_mysql_audit *); + + set_audit_mask(event_class_mask, event->event_class); + + /* Check to see if the plugin is interested in this event */ + if (check_audit_mask(data->class_mask, event_class_mask)) + return 0; + + /* Actually notify the plugin */ + data->event_notify(thd, event); + + return 0; +} + + +/** + Distributes an audit event to plug-ins + + @param[in] thd + @param[in] event +*/ + +static void event_class_dispatch(THD *thd, const struct mysql_event *event) +{ + /* + Check if we are doing a slow global dispatch. This event occurs when + thd == NULL as it is not associated with any particular thread. + */ + if (unlikely(!thd)) + { + plugin_foreach(thd, plugins_dispatch, MYSQL_AUDIT_PLUGIN, (void*) event); + } + else + { + plugin_ref *plugins, *plugins_last; + + /* Use the cached set of audit plugins */ + plugins= (plugin_ref*) thd->audit_class_plugins.buffer; + plugins_last= plugins + thd->audit_class_plugins.elements; + + for (; plugins < plugins_last; plugins++) + plugins_dispatch(thd, *plugins, (void*) event); + } +} + + +#else /* EMBEDDED_LIBRARY */ + + +void mysql_audit_initialize() +{ +} + + +void mysql_audit_finalize() +{ +} + + +int initialize_audit_plugin(st_plugin_int *plugin) +{ + return 1; +} + + +int finalize_audit_plugin(st_plugin_int *plugin) +{ + return 0; +} + + +void mysql_audit_release(THD *thd) +{ +} + + +#endif /* EMBEDDED_LIBRARY */ diff --git a/sql/sql_audit.h b/sql/sql_audit.h new file mode 100644 index 00000000000..c25011d0d59 --- /dev/null +++ b/sql/sql_audit.h @@ -0,0 +1,131 @@ +#ifndef SQL_AUDIT_INCLUDED +#define SQL_AUDIT_INCLUDED + +/* Copyright (C) 2007 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include <mysql/plugin_audit.h> + +extern unsigned long mysql_global_audit_mask[]; + + +extern void mysql_audit_initialize(); +extern void mysql_audit_finalize(); + + +extern void mysql_audit_init_thd(THD *thd); +extern void mysql_audit_free_thd(THD *thd); + + +extern void mysql_audit_notify(THD *thd, uint event_class, + uint event_subtype, ...); +extern void mysql_audit_release(THD *thd); + +#define MAX_USER_HOST_SIZE 512 +static inline uint make_user_name(THD *thd, char *buf) +{ + Security_context *sctx= thd->security_ctx; + return strxnmov(buf, MAX_USER_HOST_SIZE, + sctx->priv_user ? sctx->priv_user : "", "[", + sctx->user ? sctx->user : "", "] @ ", + sctx->host ? sctx->host : "", " [", + sctx->ip ? sctx->ip : "", "]", NullS) - buf; +} + +/** + Call audit plugins of GENERAL audit class, MYSQL_AUDIT_GENERAL_LOG subtype. + + @param[in] thd + @param[in] time time that event occurred + @param[in] user User name + @param[in] userlen User name length + @param[in] cmd Command name + @param[in] cmdlen Command name length + @param[in] query Query string + @param[in] querylen Query string length +*/ + +static inline +void mysql_audit_general_log(THD *thd, time_t time, + const char *user, uint userlen, + const char *cmd, uint cmdlen, + const char *query, uint querylen) +{ +#ifndef EMBEDDED_LIBRARY + if (mysql_global_audit_mask[0] & MYSQL_AUDIT_GENERAL_CLASSMASK) + { + CHARSET_INFO *clientcs= thd ? thd->variables.character_set_client + : global_system_variables.character_set_client; + + mysql_audit_notify(thd, MYSQL_AUDIT_GENERAL_CLASS, MYSQL_AUDIT_GENERAL_LOG, + 0, time, user, userlen, cmd, cmdlen, + query, querylen, clientcs, 0); + } +#endif +} + +/** + Call audit plugins of GENERAL audit class. + event_subtype should be set to one of: + MYSQL_AUDIT_GENERAL_ERROR + MYSQL_AUDIT_GENERAL_RESULT + + @param[in] thd + @param[in] event_subtype Type of general audit event. + @param[in] error_code Error code + @param[in] msg Message +*/ +static inline +void mysql_audit_general(THD *thd, uint event_subtype, + int error_code, const char *msg) +{ +#ifndef EMBEDDED_LIBRARY + if (mysql_global_audit_mask[0] & MYSQL_AUDIT_GENERAL_CLASSMASK) + { + time_t time= my_time(0); + uint msglen= msg ? strlen(msg) : 0; + const char *query, *user; + uint querylen, userlen; + char user_buff[MAX_USER_HOST_SIZE]; + CHARSET_INFO *clientcs; + ha_rows rows; + + if (thd) + { + query= thd->query(); + querylen= thd->query_length(); + user= user_buff; + userlen= make_user_name(thd, user_buff); + clientcs= thd->variables.character_set_client; + rows= thd->warning_info->current_row_for_warning(); + } + else + { + query= user= 0; + querylen= userlen= 0; + clientcs= global_system_variables.character_set_client; + rows= 0; + } + + mysql_audit_notify(thd, MYSQL_AUDIT_GENERAL_CLASS, event_subtype, + error_code, time, user, userlen, msg, msglen, + query, querylen, clientcs, rows); + } +#endif +} + + +#endif /* SQL_AUDIT_INCLUDED */ diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e2efb91c1a9..e7f014d39a5 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,7 +31,6 @@ #include <io.h> #endif -#define FLAGSTR(S,F) ((S) & (F) ? #F " " : "") /** This internal handler is used to trap internally @@ -100,7 +99,7 @@ TABLE *unused_tables; /* Used by mysql_test */ HASH open_cache; /* Used by mysql_test */ static HASH table_def_cache; static TABLE_SHARE *oldest_unused_share, end_of_unused_share; -static pthread_mutex_t LOCK_table_share; +static mysql_mutex_t LOCK_table_share; static bool table_def_inited= 0; static int open_unireg_entry(THD *thd, TABLE *entry, TABLE_LIST *table_list, @@ -108,10 +107,6 @@ static int open_unireg_entry(THD *thd, TABLE *entry, TABLE_LIST *table_list, char *cache_key, uint cache_key_length, MEM_ROOT *mem_root, uint flags); static void free_cache_entry(TABLE *entry); -static bool open_new_frm(THD *thd, TABLE_SHARE *share, const char *alias, - uint db_stat, uint prgflag, - uint ha_open_flags, TABLE *outparam, - TABLE_LIST *table_desc, MEM_ROOT *mem_root); static void close_old_data_files(THD *thd, TABLE *table, bool morph_locks, bool send_refresh); static bool @@ -272,10 +267,10 @@ static void table_def_free_entry(TABLE_SHARE *share) if (share->prev) { /* remove from old_unused_share list */ - pthread_mutex_lock(&LOCK_table_share); + mysql_mutex_lock(&LOCK_table_share); *share->prev= share->next; share->next->prev= share->prev; - pthread_mutex_unlock(&LOCK_table_share); + mysql_mutex_unlock(&LOCK_table_share); } free_table_share(share); DBUG_VOID_RETURN; @@ -285,7 +280,7 @@ static void table_def_free_entry(TABLE_SHARE *share) bool table_def_init(void) { table_def_inited= 1; - pthread_mutex_init(&LOCK_table_share, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_table_share, &LOCK_table_share, MY_MUTEX_INIT_FAST); oldest_unused_share= &end_of_unused_share; end_of_unused_share.prev= &oldest_unused_share; @@ -301,7 +296,7 @@ void table_def_free(void) if (table_def_inited) { table_def_inited= 0; - pthread_mutex_destroy(&LOCK_table_share); + mysql_mutex_destroy(&LOCK_table_share); my_hash_free(&table_def_cache); } DBUG_VOID_RETURN; @@ -361,7 +356,7 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key, Lock mutex to be able to read table definition from file without conflicts */ - (void) pthread_mutex_lock(&share->mutex); + mysql_mutex_lock(&share->mutex); /* We assign a new table id under the protection of the LOCK_open and @@ -392,7 +387,7 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key, share->ref_count++; // Mark in use DBUG_PRINT("exit", ("share: 0x%lx ref_count: %u", (ulong) share, share->ref_count)); - (void) pthread_mutex_unlock(&share->mutex); + mysql_mutex_unlock(&share->mutex); DBUG_RETURN(share); found: @@ -402,18 +397,18 @@ found: */ /* We must do a lock to ensure that the structure is initialized */ - (void) pthread_mutex_lock(&share->mutex); + mysql_mutex_lock(&share->mutex); if (share->error) { /* Table definition contained an error */ open_table_error(share, share->error, share->open_errno, share->errarg); - (void) pthread_mutex_unlock(&share->mutex); + mysql_mutex_unlock(&share->mutex); DBUG_RETURN(0); } if (share->is_view && !(db_flags & OPEN_VIEW)) { open_table_error(share, 1, ENOENT, 0); - (void) pthread_mutex_unlock(&share->mutex); + mysql_mutex_unlock(&share->mutex); DBUG_RETURN(0); } @@ -424,21 +419,21 @@ found: Unlink share from this list */ DBUG_PRINT("info", ("Unlinking from not used list")); - pthread_mutex_lock(&LOCK_table_share); + mysql_mutex_lock(&LOCK_table_share); *share->prev= share->next; share->next->prev= share->prev; share->next= 0; share->prev= 0; - pthread_mutex_unlock(&LOCK_table_share); + mysql_mutex_unlock(&LOCK_table_share); } - (void) pthread_mutex_unlock(&share->mutex); + mysql_mutex_unlock(&share->mutex); /* Free cache if too big */ while (table_def_cache.records > table_def_size && oldest_unused_share->next) { - pthread_mutex_lock(&oldest_unused_share->mutex); - VOID(my_hash_delete(&table_def_cache, (uchar*) oldest_unused_share)); + mysql_mutex_lock(&oldest_unused_share->mutex); + my_hash_delete(&table_def_cache, (uchar*) oldest_unused_share); } DBUG_PRINT("exit", ("share: 0x%lx ref_count: %u", @@ -566,9 +561,9 @@ void release_table_share(TABLE_SHARE *share, enum release_type type) (ulong) share, share->db.str, share->table_name.str, share->ref_count, share->version)); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); - pthread_mutex_lock(&share->mutex); + mysql_mutex_lock(&share->mutex); if (!--share->ref_count) { if (share->version != refresh_version) @@ -579,12 +574,12 @@ void release_table_share(TABLE_SHARE *share, enum release_type type) DBUG_PRINT("info",("moving share to unused list")); DBUG_ASSERT(share->next == 0); - pthread_mutex_lock(&LOCK_table_share); + mysql_mutex_lock(&LOCK_table_share); share->prev= end_of_unused_share.prev; *end_of_unused_share.prev= share; end_of_unused_share.prev= &share->next; share->next= &end_of_unused_share; - pthread_mutex_unlock(&LOCK_table_share); + mysql_mutex_unlock(&LOCK_table_share); to_be_deleted= (table_def_cache.records > table_def_size); } @@ -596,7 +591,7 @@ void release_table_share(TABLE_SHARE *share, enum release_type type) my_hash_delete(&table_def_cache, (uchar*) share); DBUG_VOID_RETURN; } - pthread_mutex_unlock(&share->mutex); + mysql_mutex_unlock(&share->mutex); DBUG_VOID_RETURN; } @@ -619,7 +614,7 @@ TABLE_SHARE *get_cached_table_share(const char *db, const char *table_name) char key[NAME_LEN*2+2]; TABLE_LIST table_list; uint key_length; - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); table_list.db= (char*) db; table_list.table_name= (char*) table_name; @@ -714,7 +709,7 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild) TABLE_LIST table_list; DBUG_ENTER("list_open_tables"); - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); bzero((char*) &table_list,sizeof(table_list)); start_list= &open_list; open_list=0; @@ -767,7 +762,7 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild) start_list= &(*start_list)->next; *start_list=0; } - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(open_list); } @@ -787,7 +782,7 @@ void intern_close_table(TABLE *table) free_io_cache(table); delete table->triggers; if (table->file) // Not true if name lock - VOID(closefrm(table, 1)); // close file + (void) closefrm(table, 1); // close file DBUG_VOID_RETURN; } @@ -864,7 +859,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, DBUG_ASSERT(thd || (!wait_for_refresh && !tables)); if (!have_lock) - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); if (!tables) { refresh_version++; // Force close of open tables @@ -874,14 +869,14 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, if (my_hash_delete(&open_cache,(uchar*) unused_tables)) printf("Warning: Couldn't delete open table from hash\n"); #else - VOID(my_hash_delete(&open_cache,(uchar*) unused_tables)); + (void) my_hash_delete(&open_cache,(uchar*) unused_tables); #endif } /* Free table shares */ while (oldest_unused_share->next) { - pthread_mutex_lock(&oldest_unused_share->mutex); - VOID(my_hash_delete(&table_def_cache, (uchar*) oldest_unused_share)); + mysql_mutex_lock(&oldest_unused_share->mutex); + (void) my_hash_delete(&table_def_cache, (uchar*) oldest_unused_share); } DBUG_PRINT("tcache", ("incremented global refresh_version to: %lu", refresh_version)); @@ -994,7 +989,7 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, { found=1; DBUG_PRINT("signal", ("Waiting for COND_refresh")); - pthread_cond_wait(&COND_refresh,&LOCK_open); + mysql_cond_wait(&COND_refresh, &LOCK_open); break; } } @@ -1019,14 +1014,14 @@ bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, } } if (!have_lock) - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); if (wait_for_refresh) { - pthread_mutex_lock(&thd->mysys_var->mutex); + mysql_mutex_lock(&thd->mysys_var->mutex); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; thd_proc_info(thd, 0); - pthread_mutex_unlock(&thd->mysys_var->mutex); + mysql_mutex_unlock(&thd->mysys_var->mutex); } DBUG_RETURN(result); } @@ -1049,7 +1044,7 @@ bool close_cached_connection_tables(THD *thd, bool if_wait_for_refresh, bzero(&tmp, sizeof(TABLE_LIST)); if (!have_lock) - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); for (idx= 0; idx < table_def_cache.records; idx++) { @@ -1082,15 +1077,15 @@ bool close_cached_connection_tables(THD *thd, bool if_wait_for_refresh, result= close_cached_tables(thd, tables, TRUE, FALSE, FALSE); if (!have_lock) - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); if (if_wait_for_refresh) { - pthread_mutex_lock(&thd->mysys_var->mutex); + mysql_mutex_lock(&thd->mysys_var->mutex); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; thd->proc_info=0; - pthread_mutex_unlock(&thd->mysys_var->mutex); + mysql_mutex_unlock(&thd->mysys_var->mutex); } DBUG_RETURN(result); @@ -1197,9 +1192,9 @@ static void close_open_tables(THD *thd) { bool found_old_table= 0; - safe_mutex_assert_not_owner(&LOCK_open); + mysql_mutex_assert_not_owner(&LOCK_open); - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); DBUG_PRINT("info", ("thd->open_tables: 0x%lx", (long) thd->open_tables)); @@ -1209,7 +1204,7 @@ static void close_open_tables(THD *thd) /* Free tables to hold down open files */ while (open_cache.records > table_cache_size && unused_tables) - VOID(my_hash_delete(&open_cache,(uchar*) unused_tables)); /* purecov: tested */ + my_hash_delete(&open_cache,(uchar*) unused_tables); /* purecov: tested */ check_unused(); if (found_old_table) { @@ -1217,7 +1212,7 @@ static void close_open_tables(THD *thd) broadcast_refresh(); } - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); } @@ -1365,7 +1360,7 @@ void close_thread_tables(THD *thd) good idea to turn off OPTION_TABLE_LOCK flag. */ DBUG_ASSERT(thd->lex->requires_prelocking()); - thd->options&= ~(OPTION_TABLE_LOCK); + thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); } DBUG_VOID_RETURN; @@ -1395,7 +1390,7 @@ bool close_thread_table(THD *thd, TABLE **table_ptr) if (table->needs_reopen_or_name_lock() || thd->version != refresh_version || !table->db_stat) { - VOID(my_hash_delete(&open_cache,(uchar*) table)); + my_hash_delete(&open_cache,(uchar*) table); found_old_table=1; } else @@ -1445,14 +1440,14 @@ void close_temporary_tables(THD *thd) TABLE *table; TABLE *next= NULL; TABLE *prev_table; - /* Assume thd->options has OPTION_QUOTE_SHOW_CREATE */ + /* Assume thd->variables.option_bits has OPTION_QUOTE_SHOW_CREATE */ bool was_quote_show= TRUE; if (!thd->temporary_tables) return; if (!mysql_bin_log.is_open() || - (thd->current_stmt_binlog_row_based && thd->variables.binlog_format == BINLOG_FORMAT_ROW)) + (thd->is_current_stmt_binlog_format_row() && thd->variables.binlog_format == BINLOG_FORMAT_ROW)) { TABLE *tmp_next; for (table= thd->temporary_tables; table; table= tmp_next) @@ -1513,9 +1508,9 @@ void close_temporary_tables(THD *thd) /* We always quote db,table names though it is slight overkill */ if (found_user_tables && - !(was_quote_show= test(thd->options & OPTION_QUOTE_SHOW_CREATE))) + !(was_quote_show= test(thd->variables.option_bits & OPTION_QUOTE_SHOW_CREATE))) { - thd->options |= OPTION_QUOTE_SHOW_CREATE; + thd->variables.option_bits |= OPTION_QUOTE_SHOW_CREATE; } /* scan sorted tmps to generate sequence of DROP */ @@ -1554,7 +1549,7 @@ void close_temporary_tables(THD *thd) thd->variables.character_set_client= system_charset_info; Query_log_event qinfo(thd, s_query.ptr(), s_query.length() - 1 /* to remove trailing ',' */, - 0, FALSE, 0); + FALSE, TRUE, FALSE, 0); qinfo.db= db.ptr(); qinfo.db_len= db.length(); thd->variables.character_set_client= cs_save; @@ -1572,7 +1567,7 @@ void close_temporary_tables(THD *thd) } } if (!was_quote_show) - thd->options&= ~OPTION_QUOTE_SHOW_CREATE; /* restore option */ + thd->variables.option_bits&= ~OPTION_QUOTE_SHOW_CREATE; /* restore option */ thd->temporary_tables=0; } @@ -1684,20 +1679,42 @@ TABLE_LIST* unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, DBUG_PRINT("info", ("real table: %s.%s", d_name, t_name)); for (;;) { - if (((! (res= find_table_in_global_list(table_list, d_name, t_name))) && - (! (res= mysql_lock_have_duplicate(thd, table, table_list)))) || - ((!res->table || res->table != table->table) && - (!check_alias || !(lower_case_table_names ? + /* + Table is unique if it is present only once in the global list + of tables and once in the list of table locks. + */ + if (! (res= find_table_in_global_list(table_list, d_name, t_name)) && + ! (res= mysql_lock_have_duplicate(thd, table, table_list))) + break; + + /* Skip if same underlying table. */ + if (res->table && (res->table == table->table)) + goto next; + + /* Skip if table alias does not match. */ + if (check_alias) + { + if (lower_case_table_names ? my_strcasecmp(files_charset_info, t_alias, res->alias) : - strcmp(t_alias, res->alias))) && - res->select_lex && !res->select_lex->exclude_from_table_unique_test && - !res->prelocking_placeholder)) + strcmp(t_alias, res->alias)) + goto next; + } + + /* + Skip if marked to be excluded (could be a derived table) or if + entry is a prelocking placeholder. + */ + if (res->select_lex && + !res->select_lex->exclude_from_table_unique_test && + !res->prelocking_placeholder) break; + /* If we found entry of this table or table of SELECT which already processed in derived table or top select of multi-update/multi-delete (exclude_from_table_unique_test) or prelocking placeholder. */ +next: table_list= res->next_global; DBUG_PRINT("info", ("found same copy of table or table which we should skip")); @@ -2076,7 +2093,7 @@ void unlink_open_table(THD *thd, TABLE *find, bool unlock) TABLE *list, **prev; DBUG_ENTER("unlink_open_table"); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); memcpy(key, find->s->table_cache_key.str, key_length); /* @@ -2103,7 +2120,7 @@ void unlink_open_table(THD *thd, TABLE *find, bool unlock) /* Remove table from open_tables list. */ *prev= list->next; /* Close table. */ - VOID(my_hash_delete(&open_cache,(uchar*) list)); // Close table + my_hash_delete(&open_cache,(uchar*) list); // Close table } else { @@ -2145,14 +2162,14 @@ void drop_open_table(THD *thd, TABLE *table, const char *db_name, else { handlerton *table_type= table->s->db_type(); - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); /* unlink_open_table() also tells threads waiting for refresh or close that something has happened. */ unlink_open_table(thd, table, FALSE); quick_rm_table(table_type, db_name, table_name, 0); - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); } } @@ -2168,7 +2185,7 @@ void drop_open_table(THD *thd, TABLE *table, const char *db_name, cond Condition to wait for */ -void wait_for_condition(THD *thd, pthread_mutex_t *mutex, pthread_cond_t *cond) +void wait_for_condition(THD *thd, mysql_mutex_t *mutex, mysql_cond_t *cond) { /* Wait until the current table is up to date */ const char *proc_info; @@ -2178,7 +2195,7 @@ void wait_for_condition(THD *thd, pthread_mutex_t *mutex, pthread_cond_t *cond) thd_proc_info(thd, "Waiting for table"); DBUG_ENTER("wait_for_condition"); if (!thd->killed) - (void) pthread_cond_wait(cond, mutex); + mysql_cond_wait(cond, mutex); /* We must unlock mutex first to avoid deadlock becasue conditions are @@ -2191,12 +2208,12 @@ void wait_for_condition(THD *thd, pthread_mutex_t *mutex, pthread_cond_t *cond) mutex is unlocked */ - pthread_mutex_unlock(mutex); - pthread_mutex_lock(&thd->mysys_var->mutex); + mysql_mutex_unlock(mutex); + mysql_mutex_lock(&thd->mysys_var->mutex); thd->mysys_var->current_mutex= 0; thd->mysys_var->current_cond= 0; thd_proc_info(thd, proc_info); - pthread_mutex_unlock(&thd->mysys_var->mutex); + mysql_mutex_unlock(&thd->mysys_var->mutex); DBUG_VOID_RETURN; } @@ -2267,7 +2284,7 @@ bool reopen_name_locked_table(THD* thd, TABLE_LIST* table_list, bool link_in) TABLE orig_table; DBUG_ENTER("reopen_name_locked_table"); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); if (thd->killed || !table) DBUG_RETURN(TRUE); @@ -2347,7 +2364,7 @@ TABLE *table_cache_insert_placeholder(THD *thd, const char *key, char *key_buff; DBUG_ENTER("table_cache_insert_placeholder"); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); /* Create a table entry with the right key and with an old refresh version @@ -2407,24 +2424,24 @@ bool lock_table_name_if_not_cached(THD *thd, const char *db, DBUG_ENTER("lock_table_name_if_not_cached"); key_length= (uint)(strmov(strmov(key, db) + 1, table_name) - key) + 1; - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); if (my_hash_search(&open_cache, (uchar *)key, key_length)) { - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); DBUG_PRINT("info", ("Table is cached, name-lock is not obtained")); *table= 0; DBUG_RETURN(FALSE); } if (!(*table= table_cache_insert_placeholder(thd, key, key_length))) { - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(TRUE); } (*table)->open_placeholder= 1; (*table)->next= thd->open_tables; thd->open_tables= *table; - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(FALSE); } @@ -2456,7 +2473,7 @@ bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists) int rc; DBUG_ENTER("check_if_table_exists"); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); *exists= TRUE; @@ -2533,12 +2550,10 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, char key[MAX_DBKEY_LENGTH]; uint key_length; char *alias= table_list->alias; + my_hash_value_type hash_value; HASH_SEARCH_STATE state; DBUG_ENTER("open_table"); - /* Parsing of partitioning information from .frm needs thd->lex set up. */ - DBUG_ASSERT(thd->lex->is_lex_started); - /* find a unused table in the open table cache */ if (refresh) *refresh=0; @@ -2681,15 +2696,15 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, */ TABLE tab; table= &tab; - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); if (!open_unireg_entry(thd, table, table_list, alias, key, key_length, mem_root, 0)) { DBUG_ASSERT(table_list->view != 0); - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(0); // VIEW } - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); } } /* @@ -2722,7 +2737,8 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, on disk. */ - VOID(pthread_mutex_lock(&LOCK_open)); + hash_value= my_calc_hash(&open_cache, (uchar*) key, key_length); + mysql_mutex_lock(&LOCK_open); /* If it's the first table from a list of tables used in a query, @@ -2740,7 +2756,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, /* Someone did a refresh while thread was opening tables */ if (refresh) *refresh=1; - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(0); } @@ -2764,8 +2780,11 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, an implicit "pending locks queue" - see wait_for_locked_table_names for details. */ - for (table= (TABLE*) my_hash_first(&open_cache, (uchar*) key, key_length, - &state); + for (table= (TABLE*) my_hash_first_from_hash_value(&open_cache, + hash_value, + (uchar*) key, + key_length, + &state); table && table->in_use ; table= (TABLE*) my_hash_next(&open_cache, (uchar*) key, key_length, &state)) @@ -2806,7 +2825,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, /* Avoid self-deadlocks by detecting self-dependencies. */ if (table->open_placeholder && table->in_use == thd) { - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); my_error(ER_UPDATE_TABLE_USED, MYF(0), table->s->table_name.str); DBUG_RETURN(0); } @@ -2842,12 +2861,12 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, */ if (table->in_use != thd) { - /* wait_for_conditionwill unlock LOCK_open for us */ + /* wait_for_condition will unlock LOCK_open for us */ wait_for_condition(thd, &LOCK_open, &COND_refresh); } else { - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); } /* There is a refresh in progress for this table. @@ -2880,7 +2899,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, DBUG_PRINT("tcache", ("opening new table")); /* Free cache if too big */ while (open_cache.records > table_cache_size && unused_tables) - VOID(my_hash_delete(&open_cache,(uchar*) unused_tables)); /* purecov: tested */ + my_hash_delete(&open_cache,(uchar*) unused_tables); /* purecov: tested */ if (table_list->create) { @@ -2888,7 +2907,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, if (check_if_table_exists(thd, table_list, &exists)) { - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(NULL); } @@ -2899,7 +2918,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, */ if (!(table= table_cache_insert_placeholder(thd, key, key_length))) { - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(NULL); } /* @@ -2910,7 +2929,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, table->open_placeholder= 1; table->next= thd->open_tables; thd->open_tables= table; - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(table); } /* Table exists. Let us try to open it. */ @@ -2919,7 +2938,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, /* make a new table */ if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME)))) { - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(NULL); } @@ -2928,7 +2947,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, if (error > 0) { my_free((uchar*)table, MYF(0)); - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(NULL); } if (table_list->view || error < 0) @@ -2941,7 +2960,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, table_list->view= (LEX*)1; my_free((uchar*)table, MYF(0)); - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(0); // VIEW } DBUG_PRINT("info", ("inserting table '%s'.'%s' 0x%lx into the cache", @@ -2950,14 +2969,14 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, if (my_hash_insert(&open_cache,(uchar*) table)) { my_free(table, MYF(0)); - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(NULL); } } check_unused(); // Debugging call - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); if (refresh) { table->next=thd->open_tables; /* Link into simple list */ @@ -3096,13 +3115,13 @@ bool reopen_table(TABLE *table) fix_merge_after_open(table->child_l, table->child_last_l, tmp.child_l, tmp.child_last_l)) { - VOID(closefrm(&tmp, 1)); // close file, free everything + (void) closefrm(&tmp, 1); // close file, free everything goto end; } delete table->triggers; if (table->file) - VOID(closefrm(table, 1)); // close file, free everything + (void) closefrm(table, 1); // close file, free everything *table= tmp; table->default_column_bitmaps(); @@ -3161,7 +3180,7 @@ void close_data_files_and_morph_locks(THD *thd, const char *db, TABLE *table; DBUG_ENTER("close_data_files_and_morph_locks"); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); if (thd->lock) { @@ -3300,7 +3319,7 @@ bool reopen_tables(THD *thd, bool get_locks, bool mark_share_as_old) if (!thd->open_tables) DBUG_RETURN(0); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); if (get_locks) { /* @@ -3343,7 +3362,7 @@ bool reopen_tables(THD *thd, bool get_locks, bool mark_share_as_old) */ if (table->child_l || table->parent) detach_merge_children(table, TRUE); - VOID(my_hash_delete(&open_cache,(uchar*) table)); + my_hash_delete(&open_cache,(uchar*) table); error=1; } else @@ -3372,7 +3391,7 @@ bool reopen_tables(THD *thd, bool get_locks, bool mark_share_as_old) { while (err_tables) { - VOID(my_hash_delete(&open_cache, (uchar*) err_tables)); + my_hash_delete(&open_cache, (uchar*) err_tables); err_tables= err_tables->next; } } @@ -3563,7 +3582,7 @@ bool wait_for_tables(THD *thd) DBUG_ENTER("wait_for_tables"); thd_proc_info(thd, "Waiting for tables"); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); while (!thd->killed) { thd->some_tables_deleted=0; @@ -3571,7 +3590,7 @@ bool wait_for_tables(THD *thd) mysql_ha_flush(thd); if (!table_is_used(thd->open_tables,1)) break; - (void) pthread_cond_wait(&COND_refresh,&LOCK_open); + mysql_cond_wait(&COND_refresh, &LOCK_open); } if (thd->killed) result= 1; // aborted @@ -3582,7 +3601,7 @@ bool wait_for_tables(THD *thd) thd->version= refresh_version; result=reopen_tables(thd,0,0); } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); thd_proc_info(thd, 0); DBUG_RETURN(result); } @@ -3654,7 +3673,7 @@ TABLE *drop_locked_tables(THD *thd,const char *db, const char *table_name) else { /* We already have a name lock, remove copy */ - VOID(my_hash_delete(&open_cache,(uchar*) table)); + my_hash_delete(&open_cache,(uchar*) table); } } else @@ -3735,7 +3754,7 @@ void assign_new_table_id(TABLE_SHARE *share) /* Preconditions */ DBUG_ASSERT(share != NULL); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); ulong tid= ++last_table_id; /* get next id */ /* @@ -3859,7 +3878,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, TABLE_LIST *table_list, uint discover_retry_count= 0; DBUG_ENTER("open_unireg_entry"); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); retry: if (!(share= get_table_share_with_create(thd, table_list, cache_key, cache_key_length, @@ -3988,7 +4007,7 @@ retry: goto err; } } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); thd->clear_error(); // Clear error message error= 0; if (open_table_from_share(thd, share, alias, @@ -4011,7 +4030,7 @@ retry: } else thd->clear_error(); // Clear error message - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); unlock_table_name(thd, table_list); if (error) @@ -4045,7 +4064,7 @@ retry: int errcode= query_error_code(thd, TRUE); if (thd->binlog_query(THD::STMT_QUERY_TYPE, query, (ulong)(end-query), - FALSE, FALSE, errcode)) + FALSE, FALSE, FALSE, errcode)) { my_free(query, MYF(0)); goto err; @@ -4265,7 +4284,7 @@ void detach_merge_children(TABLE *table, bool clear_refs) */ if ((first_detach= parent->children_attached)) { - VOID(parent->file->extra(HA_EXTRA_DETACH_CHILDREN)); + (void) parent->file->extra(HA_EXTRA_DETACH_CHILDREN); parent->children_attached= FALSE; DBUG_PRINT("myrg", ("detached parent: '%s'.'%s' 0x%lx", parent->s->db.str, parent->s->table_name.str, (long) parent)); @@ -4432,9 +4451,10 @@ bool fix_merge_after_open(TABLE_LIST *old_child_list, TABLE_LIST **old_last, thr_lock_type read_lock_type_for_table(THD *thd, TABLE *table) { - bool log_on= mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG); + bool log_on= mysql_bin_log.is_open() && (thd->variables.option_bits & OPTION_BIN_LOG); ulong binlog_format= thd->variables.binlog_format; if ((log_on == FALSE) || (binlog_format == BINLOG_FORMAT_ROW) || + (table->s->table_category == TABLE_CATEGORY_LOG) || (table->s->table_category == TABLE_CATEGORY_PERFORMANCE)) return TL_READ; else @@ -4861,7 +4881,7 @@ static bool check_lock_and_start_stmt(THD *thd, TABLE *table, There may be more differences between open_n_lock_single_table() and open_ltable(). One known difference is that open_ltable() does - neither call decide_logging_format() nor handle some other logging + neither call thd->decide_logging_format() nor handle some other logging and locking issues because it does not call lock_tables(). */ @@ -5081,165 +5101,6 @@ static void mark_real_tables_as_free_for_reuse(TABLE_LIST *table) } -/** - Decide on logging format to use for the statement. - - Compute the capabilities vector for the involved storage engines - and mask out the flags for the binary log. Right now, the binlog - flags only include the capabilities of the storage engines, so this - is safe. - - We now have three alternatives that prevent the statement from - being loggable: - - 1. If there are no capabilities left (all flags are clear) it is - not possible to log the statement at all, so we roll back the - statement and report an error. - - 2. Statement mode is set, but the capabilities indicate that - statement format is not possible. - - 3. Row mode is set, but the capabilities indicate that row - format is not possible. - - 4. Statement is unsafe, but the capabilities indicate that row - format is not possible. - - If we are in MIXED mode, we then decide what logging format to use: - - 1. If the statement is unsafe, row-based logging is used. - - 2. If statement-based logging is not possible, row-based logging is - used. - - 3. Otherwise, statement-based logging is used. - - @param thd Client thread - @param tables Tables involved in the query - */ - -int decide_logging_format(THD *thd, TABLE_LIST *tables) -{ - /* - In SBR mode, we are only proceeding if we are binlogging this - statement, ie, the filtering rules won't later filter this out. - - This check here is needed to prevent some spurious error to be - raised in some cases (See BUG#42829). - */ - if (mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG) && - (thd->variables.binlog_format != BINLOG_FORMAT_STMT || - binlog_filter->db_ok(thd->db))) - { - /* - Compute the starting vectors for the computations by creating a - set with all the capabilities bits set and one with no - capabilities bits set. - */ - handler::Table_flags flags_some_set= 0; - handler::Table_flags flags_all_set= - HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE; - - my_bool multi_engine= FALSE; - void* prev_ht= NULL; - for (TABLE_LIST *table= tables; table; table= table->next_global) - { - if (table->placeholder()) - continue; - if (table->table->s->table_category == TABLE_CATEGORY_PERFORMANCE) - thd->lex->set_stmt_unsafe(); - if (table->lock_type >= TL_WRITE_ALLOW_WRITE) - { - ulonglong const flags= table->table->file->ha_table_flags(); - DBUG_PRINT("info", ("table: %s; ha_table_flags: %s%s", - table->table_name, - FLAGSTR(flags, HA_BINLOG_STMT_CAPABLE), - FLAGSTR(flags, HA_BINLOG_ROW_CAPABLE))); - if (prev_ht && prev_ht != table->table->file->ht) - multi_engine= TRUE; - prev_ht= table->table->file->ht; - flags_all_set &= flags; - flags_some_set |= flags; - } - } - - DBUG_PRINT("info", ("flags_all_set: %s%s", - FLAGSTR(flags_all_set, HA_BINLOG_STMT_CAPABLE), - FLAGSTR(flags_all_set, HA_BINLOG_ROW_CAPABLE))); - DBUG_PRINT("info", ("flags_some_set: %s%s", - FLAGSTR(flags_some_set, HA_BINLOG_STMT_CAPABLE), - FLAGSTR(flags_some_set, HA_BINLOG_ROW_CAPABLE))); - DBUG_PRINT("info", ("thd->variables.binlog_format: %ld", - thd->variables.binlog_format)); - DBUG_PRINT("info", ("multi_engine: %s", - multi_engine ? "TRUE" : "FALSE")); - - int error= 0; - if (flags_all_set == 0) - { - my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0), - "Statement cannot be logged to the binary log in" - " row-based nor statement-based format"); - } - else if (thd->variables.binlog_format == BINLOG_FORMAT_STMT && - (flags_all_set & HA_BINLOG_STMT_CAPABLE) == 0) - { - my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0), - "Statement-based format required for this statement," - " but not allowed by this combination of engines"); - } - else if ((thd->variables.binlog_format == BINLOG_FORMAT_ROW || - thd->lex->is_stmt_unsafe()) && - (flags_all_set & HA_BINLOG_ROW_CAPABLE) == 0) - { - my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0), - "Row-based format required for this statement," - " but not allowed by this combination of engines"); - } - - /* - If more than one engine is involved in the statement and at - least one is doing it's own logging (is *self-logging*), the - statement cannot be logged atomically, so we generate an error - rather than allowing the binlog to become corrupt. - */ - if (multi_engine && - (flags_some_set & HA_HAS_OWN_BINLOGGING)) - { - error= ER_BINLOG_LOGGING_IMPOSSIBLE; - my_error(error, MYF(0), - "Statement cannot be written atomically since more" - " than one engine involved and at least one engine" - " is self-logging"); - } - - DBUG_PRINT("info", ("error: %d", error)); - - if (error) - return -1; - - /* - We switch to row-based format if we are in mixed mode and one of - the following are true: - - 1. If the statement is unsafe - 2. If statement format cannot be used - - Observe that point to cannot be decided before the tables - involved in a statement has been checked, i.e., we cannot put - this code in reset_current_stmt_binlog_row_based(), it has to be - here. - */ - if (thd->lex->is_stmt_unsafe() || - (flags_all_set & HA_BINLOG_STMT_CAPABLE) == 0) - { - thd->set_current_stmt_binlog_row_based_if_mixed(); - } - } - - return 0; -} - /* Lock all tables in list @@ -5281,7 +5142,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) *need_reopen= FALSE; if (!tables && !thd->lex->requires_prelocking()) - DBUG_RETURN(decide_logging_format(thd, tables)); + DBUG_RETURN(thd->decide_logging_format(tables)); /* We need this extra check for thd->prelocked_mode because we want to avoid @@ -5310,19 +5171,18 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) if (thd->lex->requires_prelocking()) { thd->in_lock_tables=1; - thd->options|= OPTION_TABLE_LOCK; + thd->variables.option_bits|= OPTION_TABLE_LOCK; /* A query that modifies autoinc column in sub-statement can make the master and slave inconsistent. We can solve these problems in mixed mode by switching to binlogging if at least one updated table is used by sub-statement */ - /* The BINLOG_FORMAT_MIXED judgement is saved for suppressing - warnings, but it will be removed by fixing bug#45827 */ - if (thd->variables.binlog_format == BINLOG_FORMAT_MIXED && tables && + if (thd->variables.binlog_format != BINLOG_FORMAT_ROW && tables && has_write_table_with_auto_increment(thd->lex->first_not_own_table())) { - thd->lex->set_stmt_unsafe(); + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS); + thd->set_current_stmt_binlog_format_row_if_mixed(); } } @@ -5333,7 +5193,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) { if (thd->lex->requires_prelocking()) { - thd->options&= ~(OPTION_TABLE_LOCK); + thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); thd->in_lock_tables=0; } DBUG_RETURN(-1); @@ -5376,7 +5236,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) { mysql_unlock_tables(thd, thd->locked_tables); thd->locked_tables= 0; - thd->options&= ~(OPTION_TABLE_LOCK); + thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); DBUG_RETURN(-1); } } @@ -5445,7 +5305,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) } } - DBUG_RETURN(decide_logging_format(thd, tables)); + DBUG_RETURN(thd->decide_logging_format(tables)); } @@ -5573,7 +5433,7 @@ bool rm_temporary_table(handlerton *base, char *path) DBUG_ENTER("rm_temporary_table"); strmov(ext= strend(path), reg_ext); - if (my_delete(path,MYF(0))) + if (mysql_file_delete(key_file_frm, path, MYF(0))) error=1; /* purecov: inspected */ *ext= 0; // remove extension file= get_new_handler((TABLE_SHARE*) 0, current_thd->mem_root, base); @@ -7995,7 +7855,6 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds) { SELECT_LEX *select_lex= thd->lex->current_select; - Query_arena *arena= thd->stmt_arena, backup; TABLE_LIST *table= NULL; // For HP compilers /* it_is_update set to TRUE when tables of primary SELECT_LEX (SELECT_LEX @@ -8011,10 +7870,6 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, select_lex->is_item_list_lookup= 0; DBUG_ENTER("setup_conds"); - if (select_lex->conds_processed_with_permanent_arena || - arena->is_conventional()) - arena= 0; // For easier test - thd->mark_used_columns= MARK_COLUMNS_READ; DBUG_PRINT("info", ("thd->mark_used_columns: %d", thd->mark_used_columns)); select_lex->cond_count= 0; @@ -8083,7 +7938,6 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, We do this ON -> WHERE transformation only once per PS/SP statement. */ select_lex->where= *conds; - select_lex->conds_processed_with_permanent_arena= 1; } thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup; DBUG_RETURN(test(thd->is_error())); @@ -8368,7 +8222,7 @@ my_bool mysql_rm_tmp_tables(void) So we hide error messages which happnes during deleting of these files(MYF(0)). */ - VOID(my_delete(filePath, MYF(0))); + (void) mysql_file_delete(key_file_misc, filePath, MYF(0)); } } my_dirend(dirp); @@ -8410,7 +8264,7 @@ void remove_db_from_cache(const char *db) } } while (unused_tables && !unused_tables->s->version) - VOID(my_hash_delete(&open_cache,(uchar*) unused_tables)); + my_hash_delete(&open_cache,(uchar*) unused_tables); } @@ -8424,10 +8278,10 @@ void remove_db_from_cache(const char *db) void flush_tables() { - (void) pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); while (unused_tables) my_hash_delete(&open_cache,(uchar*) unused_tables); - (void) pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } @@ -8498,15 +8352,15 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, ! in_use->killed) { in_use->killed= THD::KILL_CONNECTION; - pthread_mutex_lock(&in_use->mysys_var->mutex); + mysql_mutex_lock(&in_use->mysys_var->mutex); if (in_use->mysys_var->current_cond) { - pthread_mutex_lock(in_use->mysys_var->current_mutex); + mysql_mutex_lock(in_use->mysys_var->current_mutex); signalled= 1; - pthread_cond_broadcast(in_use->mysys_var->current_cond); - pthread_mutex_unlock(in_use->mysys_var->current_mutex); + mysql_cond_broadcast(in_use->mysys_var->current_cond); + mysql_mutex_unlock(in_use->mysys_var->current_mutex); } - pthread_mutex_unlock(&in_use->mysys_var->mutex); + mysql_mutex_unlock(&in_use->mysys_var->mutex); } /* Now we must abort all tables locks used by this thread @@ -8534,7 +8388,7 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, } } while (unused_tables && !unused_tables->s->version) - VOID(my_hash_delete(&open_cache,(uchar*) unused_tables)); + my_hash_delete(&open_cache,(uchar*) unused_tables); DBUG_PRINT("info", ("Removing table from table_def_cache")); /* Remove table from table definition cache if it's not in use */ @@ -8546,8 +8400,8 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, share->version= 0; // Mark for delete if (share->ref_count == 0) { - pthread_mutex_lock(&share->mutex); - VOID(my_hash_delete(&table_def_cache, (uchar*) share)); + mysql_mutex_lock(&share->mutex); + my_hash_delete(&table_def_cache, (uchar*) share); } } @@ -8563,7 +8417,7 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, { dropping_tables++; if (likely(signalled)) - (void) pthread_cond_wait(&COND_refresh, &LOCK_open); + mysql_cond_wait(&COND_refresh, &LOCK_open); else { struct timespec abstime; @@ -8578,7 +8432,7 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, remove_table_from_cache routine. */ set_timespec(abstime, 10); - pthread_cond_timedwait(&COND_refresh, &LOCK_open, &abstime); + mysql_cond_timedwait(&COND_refresh, &LOCK_open, &abstime); } dropping_tables--; continue; @@ -8647,7 +8501,7 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order) mem_root temporary MEM_ROOT for parsing */ -static bool +bool open_new_frm(THD *thd, TABLE_SHARE *share, const char *alias, uint db_stat, uint prgflag, uint ha_open_flags, TABLE *outparam, TABLE_LIST *table_desc, @@ -8724,12 +8578,12 @@ int abort_and_upgrade_lock(ALTER_PARTITION_PARAM_TYPE *lpt) DBUG_ENTER("abort_and_upgrade_locks"); lpt->old_lock_type= lpt->table->reginfo.lock_type; - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); /* If MERGE child, forward lock handling to parent. */ mysql_lock_abort(lpt->thd, lpt->table->parent ? lpt->table->parent : lpt->table, TRUE); - VOID(remove_table_from_cache(lpt->thd, lpt->db, lpt->table_name, flags)); - VOID(pthread_mutex_unlock(&LOCK_open)); + (void) remove_table_from_cache(lpt->thd, lpt->db, lpt->table_name, flags); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(0); } @@ -8751,10 +8605,10 @@ int abort_and_upgrade_lock(ALTER_PARTITION_PARAM_TYPE *lpt) /* purecov: begin deadcode */ void close_open_tables_and_downgrade(ALTER_PARTITION_PARAM_TYPE *lpt) { - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); remove_table_from_cache(lpt->thd, lpt->db, lpt->table_name, RTFC_WAIT_OTHER_THREAD_FLAG); - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); /* If MERGE child, forward lock handling to parent. */ mysql_lock_downgrade_write(lpt->thd, lpt->table->parent ? lpt->table->parent : lpt->table, lpt->old_lock_type); @@ -8793,7 +8647,7 @@ void mysql_wait_completed_table(ALTER_PARTITION_PARAM_TYPE *lpt, TABLE *my_table DBUG_ENTER("mysql_wait_completed_table"); key_length=(uint) (strmov(strmov(key,lpt->db)+1,lpt->table_name)-key)+1; - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); HASH_SEARCH_STATE state; for (table= (TABLE*) my_hash_first(&open_cache,(uchar*) key,key_length, &state) ; @@ -8814,14 +8668,14 @@ void mysql_wait_completed_table(ALTER_PARTITION_PARAM_TYPE *lpt, TABLE *my_table ! in_use->killed) { in_use->killed= THD::KILL_CONNECTION; - pthread_mutex_lock(&in_use->mysys_var->mutex); + mysql_mutex_lock(&in_use->mysys_var->mutex); if (in_use->mysys_var->current_cond) { - pthread_mutex_lock(in_use->mysys_var->current_mutex); - pthread_cond_broadcast(in_use->mysys_var->current_cond); - pthread_mutex_unlock(in_use->mysys_var->current_mutex); + mysql_mutex_lock(in_use->mysys_var->current_mutex); + mysql_cond_broadcast(in_use->mysys_var->current_cond); + mysql_mutex_unlock(in_use->mysys_var->current_mutex); } - pthread_mutex_unlock(&in_use->mysys_var->mutex); + mysql_mutex_unlock(&in_use->mysys_var->mutex); } /* Now we must abort all tables locks used by this thread @@ -8851,7 +8705,7 @@ void mysql_wait_completed_table(ALTER_PARTITION_PARAM_TYPE *lpt, TABLE *my_table */ mysql_lock_abort(lpt->thd, my_table->parent ? my_table->parent : my_table, FALSE); - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); DBUG_VOID_RETURN; } @@ -9005,19 +8859,18 @@ open_system_table_for_update(THD *thd, TABLE_LIST *one_table) } /** - Open a performance schema table. + Open a log table. Opening such tables is performed internally in the server implementation, and is a 'nested' open, since some tables might be already opened by the current thread. The thread context before this call is saved, and is restored - when calling close_performance_schema_table(). + when calling close_log_table(). @param thd The current thread - @param one_table Performance schema table to open + @param one_table Log table to open @param backup [out] Temporary storage used to save the thread context */ TABLE * -open_performance_schema_table(THD *thd, TABLE_LIST *one_table, - Open_tables_state *backup) +open_log_table(THD *thd, TABLE_LIST *one_table, Open_tables_state *backup) { uint flags= ( MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK | MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY | @@ -9026,13 +8879,13 @@ open_performance_schema_table(THD *thd, TABLE_LIST *one_table, TABLE *table; /* Save value that is changed in mysql_lock_tables() */ ulonglong save_utime_after_lock= thd->utime_after_lock; - DBUG_ENTER("open_performance_schema_table"); + DBUG_ENTER("open_log_table"); thd->reset_n_backup_open_tables_state(backup); if ((table= open_ltable(thd, one_table, one_table->lock_type, flags))) { - DBUG_ASSERT(table->s->table_category == TABLE_CATEGORY_PERFORMANCE); + DBUG_ASSERT(table->s->table_category == TABLE_CATEGORY_LOG); /* Make sure all columns get assigned to a default value */ table->use_all_columns(); table->no_replicate= 1; @@ -9060,18 +8913,18 @@ open_performance_schema_table(THD *thd, TABLE_LIST *one_table, } /** - Close a performance schema table. - The last table opened by open_performance_schema_table() + Close a log table. + The last table opened by open_log_table() is closed, then the thread context is restored. @param thd The current thread @param backup [in] the context to restore. */ -void close_performance_schema_table(THD *thd, Open_tables_state *backup) +void close_log_table(THD *thd, Open_tables_state *backup) { bool found_old_table; /* - If open_performance_schema_table() fails, + If open_log_table() fails, this function should not be called. */ DBUG_ASSERT(thd->lock != NULL); @@ -9090,7 +8943,7 @@ void close_performance_schema_table(THD *thd, Open_tables_state *backup) mysql_unlock_tables(thd, thd->lock); thd->lock= 0; - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); found_old_table= false; /* @@ -9106,7 +8959,7 @@ void close_performance_schema_table(THD *thd, Open_tables_state *backup) if (found_old_table) broadcast_refresh(); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); thd->restore_backup_open_tables_state(backup); } diff --git a/sql/sql_builtin.cc.in b/sql/sql_builtin.cc.in index 3becdbaccfe..f8767949fe3 100644 --- a/sql/sql_builtin.cc.in +++ b/sql/sql_builtin.cc.in @@ -18,10 +18,16 @@ typedef struct st_mysql_plugin builtin_plugin[]; extern builtin_plugin - builtin_binlog_plugin@mysql_plugin_defs@; + @mysql_mandatory_plugins@ @mysql_optional_plugins@ builtin_binlog_plugin; -struct st_mysql_plugin *mysqld_builtins[]= +struct st_mysql_plugin *mysql_optional_plugins[]= { - builtin_binlog_plugin@mysql_plugin_defs@,(struct st_mysql_plugin *)0 + @mysql_optional_plugins@ 0 }; +struct st_mysql_plugin *mysql_mandatory_plugins[]= +{ + builtin_binlog_plugin, @mysql_mandatory_plugins@ 0 +}; + + diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 5942696b86c..0fd8d6e9b0f 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -341,18 +341,14 @@ TODO list: #endif #if !defined(EXTRA_DBUG) && !defined(DBUG_OFF) -#define MUTEX_LOCK(M) { DBUG_PRINT("lock", ("mutex lock 0x%lx", (ulong)(M))); \ - pthread_mutex_lock(M);} -#define MUTEX_UNLOCK(M) {DBUG_PRINT("lock", ("mutex unlock 0x%lx",\ - (ulong)(M))); pthread_mutex_unlock(M);} #define RW_WLOCK(M) {DBUG_PRINT("lock", ("rwlock wlock 0x%lx",(ulong)(M))); \ - if (!rw_wrlock(M)) DBUG_PRINT("lock", ("rwlock wlock ok")); \ + if (!mysql_rwlock_wrlock(M)) DBUG_PRINT("lock", ("rwlock wlock ok")); \ else DBUG_PRINT("lock", ("rwlock wlock FAILED %d", errno)); } #define RW_RLOCK(M) {DBUG_PRINT("lock", ("rwlock rlock 0x%lx", (ulong)(M))); \ - if (!rw_rdlock(M)) DBUG_PRINT("lock", ("rwlock rlock ok")); \ + if (!mysql_rwlock_rdlock(M)) DBUG_PRINT("lock", ("rwlock rlock ok")); \ else DBUG_PRINT("lock", ("rwlock wlock FAILED %d", errno)); } #define RW_UNLOCK(M) {DBUG_PRINT("lock", ("rwlock unlock 0x%lx",(ulong)(M))); \ - if (!rw_unlock(M)) DBUG_PRINT("lock", ("rwlock unlock ok")); \ + if (!mysql_rwlock_unlock(M)) DBUG_PRINT("lock", ("rwlock unlock ok")); \ else DBUG_PRINT("lock", ("rwlock unlock FAILED %d", errno)); } #define BLOCK_LOCK_WR(B) {DBUG_PRINT("lock", ("%d LOCK_WR 0x%lx",\ __LINE__,(ulong)(B))); \ @@ -395,11 +391,9 @@ static void debug_wait_for_kill(const char *info) } #else -#define MUTEX_LOCK(M) pthread_mutex_lock(M) -#define MUTEX_UNLOCK(M) pthread_mutex_unlock(M) -#define RW_WLOCK(M) rw_wrlock(M) -#define RW_RLOCK(M) rw_rdlock(M) -#define RW_UNLOCK(M) rw_unlock(M) +#define RW_WLOCK(M) mysql_rwlock_wrlock(M) +#define RW_RLOCK(M) mysql_rwlock_rdlock(M) +#define RW_UNLOCK(M) mysql_rwlock_unlock(M) #define BLOCK_LOCK_WR(B) B->query()->lock_writing() #define BLOCK_LOCK_RD(B) B->query()->lock_reading() #define BLOCK_UNLOCK_WR(B) B->query()->unlock_writing() @@ -407,13 +401,6 @@ static void debug_wait_for_kill(const char *info) #define DUMP(C) #endif -const char *query_cache_type_names[]= { "OFF", "ON", "DEMAND",NullS }; -TYPELIB query_cache_type_typelib= -{ - array_elements(query_cache_type_names)-1,"", query_cache_type_names, NULL -}; - - /** Serialize access to the query cache. If the lock cannot be granted the thread hangs in a conditional wait which @@ -437,7 +424,7 @@ bool Query_cache::try_lock(bool use_timeout) bool interrupt= FALSE; DBUG_ENTER("Query_cache::try_lock"); - pthread_mutex_lock(&structure_guard_mutex); + mysql_mutex_lock(&structure_guard_mutex); while (1) { if (m_cache_lock_status == Query_cache::UNLOCKED) @@ -470,8 +457,8 @@ bool Query_cache::try_lock(bool use_timeout) { struct timespec waittime; set_timespec_nsec(waittime,(ulong)(50000000L)); /* Wait for 50 msec */ - int res= pthread_cond_timedwait(&COND_cache_status_changed, - &structure_guard_mutex,&waittime); + int res= mysql_cond_timedwait(&COND_cache_status_changed, + &structure_guard_mutex, &waittime); if (res == ETIMEDOUT) { interrupt= TRUE; @@ -480,11 +467,11 @@ bool Query_cache::try_lock(bool use_timeout) } else { - pthread_cond_wait(&COND_cache_status_changed, &structure_guard_mutex); + mysql_cond_wait(&COND_cache_status_changed, &structure_guard_mutex); } } } - pthread_mutex_unlock(&structure_guard_mutex); + mysql_mutex_unlock(&structure_guard_mutex); DBUG_RETURN(interrupt); } @@ -505,9 +492,9 @@ void Query_cache::lock_and_suspend(void) { DBUG_ENTER("Query_cache::lock_and_suspend"); - pthread_mutex_lock(&structure_guard_mutex); + mysql_mutex_lock(&structure_guard_mutex); while (m_cache_lock_status != Query_cache::UNLOCKED) - pthread_cond_wait(&COND_cache_status_changed, &structure_guard_mutex); + mysql_cond_wait(&COND_cache_status_changed, &structure_guard_mutex); m_cache_lock_status= Query_cache::LOCKED_NO_WAIT; #ifndef DBUG_OFF THD *thd= current_thd; @@ -515,8 +502,8 @@ void Query_cache::lock_and_suspend(void) m_cache_lock_thread_id= thd->thread_id; #endif /* Wake up everybody, a whole cache flush is starting! */ - pthread_cond_broadcast(&COND_cache_status_changed); - pthread_mutex_unlock(&structure_guard_mutex); + mysql_cond_broadcast(&COND_cache_status_changed); + mysql_mutex_unlock(&structure_guard_mutex); DBUG_VOID_RETURN; } @@ -533,16 +520,16 @@ void Query_cache::lock(void) { DBUG_ENTER("Query_cache::lock"); - pthread_mutex_lock(&structure_guard_mutex); + mysql_mutex_lock(&structure_guard_mutex); while (m_cache_lock_status != Query_cache::UNLOCKED) - pthread_cond_wait(&COND_cache_status_changed, &structure_guard_mutex); + mysql_cond_wait(&COND_cache_status_changed, &structure_guard_mutex); m_cache_lock_status= Query_cache::LOCKED; #ifndef DBUG_OFF THD *thd= current_thd; if (thd) m_cache_lock_thread_id= thd->thread_id; #endif - pthread_mutex_unlock(&structure_guard_mutex); + mysql_mutex_unlock(&structure_guard_mutex); DBUG_VOID_RETURN; } @@ -555,7 +542,7 @@ void Query_cache::lock(void) void Query_cache::unlock(void) { DBUG_ENTER("Query_cache::unlock"); - pthread_mutex_lock(&structure_guard_mutex); + mysql_mutex_lock(&structure_guard_mutex); #ifndef DBUG_OFF THD *thd= current_thd; if (thd) @@ -565,8 +552,8 @@ void Query_cache::unlock(void) m_cache_lock_status == Query_cache::LOCKED_NO_WAIT); m_cache_lock_status= Query_cache::UNLOCKED; DBUG_PRINT("Query_cache",("Sending signal")); - pthread_cond_signal(&COND_cache_status_changed); - pthread_mutex_unlock(&structure_guard_mutex); + mysql_cond_signal(&COND_cache_status_changed); + mysql_mutex_unlock(&structure_guard_mutex); DBUG_VOID_RETURN; } @@ -735,7 +722,7 @@ inline void Query_cache_query::lock_writing() my_bool Query_cache_query::try_lock_writing() { DBUG_ENTER("Query_cache_block::try_lock_writing"); - if (rw_trywrlock(&lock)!=0) + if (mysql_rwlock_trywrlock(&lock) != 0) { DBUG_PRINT("info", ("can't lock rwlock")); DBUG_RETURN(0); @@ -767,7 +754,7 @@ void Query_cache_query::init_n_lock() { DBUG_ENTER("Query_cache_query::init_n_lock"); res=0; wri = 0; len = 0; - my_rwlock_init(&lock, NULL); + mysql_rwlock_init(key_rwlock_query_cache_query_lock, &lock); lock_writing(); DBUG_PRINT("qcache", ("inited & locked query for block 0x%lx", (long) (((uchar*) this) - @@ -787,7 +774,7 @@ void Query_cache_query::unlock_n_destroy() active semaphore */ this->unlock_writing(); - rwlock_destroy(&lock); + mysql_rwlock_destroy(&lock); DBUG_VOID_RETURN; } @@ -1074,12 +1061,12 @@ Query_cache::Query_cache(ulong query_cache_limit_arg, :query_cache_size(0), query_cache_limit(query_cache_limit_arg), queries_in_cache(0), hits(0), inserts(0), refused(0), - total_blocks(0), lowmem_prunes(0), + total_blocks(0), lowmem_prunes(0), m_query_cache_is_disabled(FALSE), min_allocation_unit(ALIGN_SIZE(min_allocation_unit_arg)), min_result_data_size(ALIGN_SIZE(min_result_data_size_arg)), def_query_hash_size(ALIGN_SIZE(def_query_hash_size_arg)), def_table_hash_size(ALIGN_SIZE(def_table_hash_size_arg)), - initialized(0), m_query_cache_is_disabled(FALSE) + initialized(0) { ulong min_needed= (ALIGN_SIZE(sizeof(Query_cache_block)) + ALIGN_SIZE(sizeof(Query_cache_block_table)) + @@ -1360,12 +1347,12 @@ end: @param thd Pointer to the thread handler @param sql A pointer to the sql statement * @param query_length Length of the statement in characters - + @return status code - @retval 1 Query was not cached. - @retval 0 The query was cached and user was sent the result. - @retval -1 The query was cached but we didn't have rights to use it. - + @retval 0 Query was not cached. + @retval 1 The query was cached and user was sent the result. + @retval -1 The query was cached but we didn't have rights to use it. + In case of -1, no error is sent to the client. *) The buffer must be allocated memory of size: @@ -1548,7 +1535,7 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", } DBUG_PRINT("qcache", ("Query have result 0x%lx", (ulong) query)); - if ((thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && + if ((thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && (query->tables_type() & HA_CACHE_TBL_TRANSACT)) { DBUG_PRINT("qcache", @@ -1706,7 +1693,7 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used, DBUG_VOID_RETURN; using_transactions= using_transactions && - (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); + (thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); for (; tables_used; tables_used= tables_used->next_local) { DBUG_ASSERT(!using_transactions || tables_used->table!=0); @@ -1791,7 +1778,7 @@ void Query_cache::invalidate(THD *thd, TABLE *table, DBUG_VOID_RETURN; using_transactions= using_transactions && - (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); + (thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); if (using_transactions && (table->file->table_cache_type() == HA_CACHE_TBL_TRANSACT)) thd->add_changed_table(table); @@ -1810,7 +1797,7 @@ void Query_cache::invalidate(THD *thd, const char *key, uint32 key_length, DBUG_VOID_RETURN; using_transactions= using_transactions && - (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); + (thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); if (using_transactions) // used for innodb => has_transactions() is TRUE thd->add_changed_table(key, key_length); else @@ -1991,8 +1978,8 @@ void Query_cache::destroy() free_cache(); unlock(); - pthread_cond_destroy(&COND_cache_status_changed); - pthread_mutex_destroy(&structure_guard_mutex); + mysql_cond_destroy(&COND_cache_status_changed); + mysql_mutex_destroy(&structure_guard_mutex); initialized = 0; } DBUG_VOID_RETURN; @@ -2006,8 +1993,10 @@ void Query_cache::destroy() void Query_cache::init() { DBUG_ENTER("Query_cache::init"); - pthread_mutex_init(&structure_guard_mutex,MY_MUTEX_INIT_FAST); - pthread_cond_init(&COND_cache_status_changed, NULL); + mysql_mutex_init(key_structure_guard_mutex, + &structure_guard_mutex, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_cache_status_changed, + &COND_cache_status_changed, NULL); m_cache_lock_status= Query_cache::UNLOCKED; initialized = 1; /* @@ -2157,9 +2146,9 @@ ulong Query_cache::init_cache() DUMP(this); - VOID(my_hash_init(&queries, &my_charset_bin, def_query_hash_size, 0, 0, - query_cache_query_get_key, 0, 0)); -#ifndef FN_NO_CASE_SENCE + (void) my_hash_init(&queries, &my_charset_bin, def_query_hash_size, 0, 0, + query_cache_query_get_key, 0, 0); +#ifndef FN_NO_CASE_SENSE /* If lower_case_table_names!=0 then db and table names are already converted to lower case and we can use binary collation for their @@ -2168,8 +2157,8 @@ ulong Query_cache::init_cache() lower_case_table_names == 0 then we should distinguish my_table and MY_TABLE cases and so again can use binary collation. */ - VOID(my_hash_init(&tables, &my_charset_bin, def_table_hash_size, 0, 0, - query_cache_table_get_key, 0, 0)); + (void) my_hash_init(&tables, &my_charset_bin, def_table_hash_size, 0, 0, + query_cache_table_get_key, 0, 0); #else /* On windows, OS/2, MacOS X with HFS+ or any other case insensitive @@ -2179,10 +2168,11 @@ ulong Query_cache::init_cache() file system) and so should use case insensitive collation for comparison. */ - VOID(my_hash_init(&tables, - lower_case_table_names ? &my_charset_bin : - files_charset_info, - def_table_hash_size, 0, 0,query_cache_table_get_key, 0, 0)); + (void) my_hash_init(&tables, + lower_case_table_names ? &my_charset_bin : + files_charset_info, + def_table_hash_size, 0, 0,query_cache_table_get_key, + 0, 0); #endif queries_in_cache = 0; @@ -3579,7 +3569,7 @@ Query_cache::is_cacheable(THD *thd, size_t query_len, const char *query, tables_type))) DBUG_RETURN(0); - if ((thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && + if ((thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && ((*tables_type)&HA_CACHE_TBL_TRANSACT)) { DBUG_PRINT("qcache", ("not in autocommin mode")); @@ -3852,7 +3842,7 @@ my_bool Query_cache::move_by_type(uchar **border, } while ( result_block != first_result_block ); } Query_cache_query *new_query= ((Query_cache_query *) new_block->data()); - my_rwlock_init(&new_query->lock, NULL); + mysql_rwlock_init(key_rwlock_query_cache_query_lock, &new_query->lock); /* If someone is writing to this block, inform the writer that the block diff --git a/sql/sql_cache.h b/sql/sql_cache.h index 695d6fb4db3..9d1f32d6ef1 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2006 MySQL AB +/* Copyright (C) 2001-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -137,7 +137,7 @@ struct Query_cache_block struct Query_cache_query { ulonglong limit_found_rows; - rw_lock_t lock; + mysql_rwlock_t lock; Query_cache_block *res; Query_cache_tls *wri; ulong len; @@ -277,7 +277,7 @@ private: #ifndef DBUG_OFF my_thread_id m_cache_lock_thread_id; #endif - pthread_cond_t COND_cache_status_changed; + mysql_cond_t COND_cache_status_changed; enum Cache_lock_status { UNLOCKED, LOCKED_NO_WAIT, LOCKED }; Cache_lock_status m_cache_lock_status; @@ -302,7 +302,7 @@ protected: is other threads that were going to do cache flush---they'll wait till the end of a flush operation. */ - pthread_mutex_t structure_guard_mutex; + mysql_mutex_t structure_guard_mutex; uchar *cache; // cache memory Query_cache_block *first_block; // physical location block list Query_cache_block *queries_blocks; // query list (LIFO) @@ -503,5 +503,4 @@ protected: }; extern Query_cache query_cache; -extern TYPELIB query_cache_type_typelib; #endif diff --git a/sql/sql_class.cc b/sql/sql_class.cc index d37058d2167..527b84a795c 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -32,6 +32,7 @@ #include "slave.h" #include <my_bitmap.h> #include "log_event.h" +#include "sql_audit.h" #include <m_ctype.h> #include <sys/stat.h> #include <thr_alarm.h> @@ -39,6 +40,7 @@ #include <io.h> #endif #include <mysys_err.h> +#include <limits.h> #include "sp_rcontext.h" #include "sp_cache.h" @@ -268,8 +270,8 @@ const char *set_thd_proc_info(THD *thd, const char *info, } extern "C" -const char* thd_enter_cond(MYSQL_THD thd, pthread_cond_t *cond, - pthread_mutex_t *mutex, const char *msg) +const char* thd_enter_cond(MYSQL_THD thd, mysql_cond_t *cond, + mysql_mutex_t *mutex, const char *msg) { if (!thd) thd= current_thd; @@ -296,7 +298,7 @@ void **thd_ha_data(const THD *thd, const struct handlerton *hton) extern "C" long long thd_test_options(const THD *thd, long long test_options) { - return thd->options & test_options; + return thd->variables.option_bits & test_options; } extern "C" @@ -385,7 +387,7 @@ char *thd_security_context(THD *thd, char *buffer, unsigned int length, str.append(proc_info); } - pthread_mutex_lock(&thd->LOCK_thd_data); + mysql_mutex_lock(&thd->LOCK_thd_data); if (thd->query()) { @@ -397,7 +399,7 @@ char *thd_security_context(THD *thd, char *buffer, unsigned int length, str.append(thd->query(), len); } - pthread_mutex_unlock(&thd->LOCK_thd_data); + mysql_mutex_unlock(&thd->LOCK_thd_data); if (str.c_ptr_safe() == buffer) return buffer; @@ -449,7 +451,7 @@ THD::THD() lock_id(&main_lock_id), user_time(0), in_sub_stmt(0), sql_log_bin_toplevel(false), - binlog_table_maps(0), binlog_flags(0UL), + binlog_unsafe_warning_flags(0), binlog_table_maps(0), table_map_for_update(0), arg_of_last_insert_id_function(FALSE), first_successful_insert_id_in_prev_stmt(0), @@ -488,7 +490,7 @@ THD::THD() catalog= (char*)"std"; // the only catalog we have for now main_security_ctx.init(); security_ctx= &main_security_ctx; - locked=some_tables_deleted=no_errors=password= 0; + some_tables_deleted=no_errors=password= 0; query_start_used= 0; count_cuted_fields= CHECK_FIELD_IGNORE; killed= NOT_KILLED; @@ -524,6 +526,7 @@ THD::THD() dbug_sentry=THD_SENTRY_MAGIC; #endif #ifndef EMBEDDED_LIBRARY + mysql_audit_init_thd(this); net.vio=0; #endif client_capabilities= 0; // minimalistic client @@ -536,7 +539,7 @@ THD::THD() #ifdef SIGNAL_WITH_VIO_CLOSE active_vio = 0; #endif - pthread_mutex_init(&LOCK_thd_data, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_thd_data, &LOCK_thd_data, MY_MUTEX_INIT_FAST); /* Variables with default values */ proc_info="login"; @@ -684,7 +687,7 @@ void THD::raise_note(uint sql_errno) { DBUG_ENTER("THD::raise_note"); DBUG_PRINT("enter", ("code: %d", sql_errno)); - if (!(this->options & OPTION_SQL_NOTES)) + if (!(variables.option_bits & OPTION_SQL_NOTES)) DBUG_VOID_RETURN; const char* msg= ER(sql_errno); (void) raise_condition(sql_errno, @@ -700,7 +703,7 @@ void THD::raise_note_printf(uint sql_errno, ...) char ebuff[MYSQL_ERRMSG_SIZE]; DBUG_ENTER("THD::raise_note_printf"); DBUG_PRINT("enter",("code: %u", sql_errno)); - if (!(this->options & OPTION_SQL_NOTES)) + if (!(variables.option_bits & OPTION_SQL_NOTES)) DBUG_VOID_RETURN; const char* format= ER(sql_errno); va_start(args, sql_errno); @@ -721,7 +724,7 @@ MYSQL_ERROR* THD::raise_condition(uint sql_errno, MYSQL_ERROR *cond= NULL; DBUG_ENTER("THD::raise_condition"); - if (!(this->options & OPTION_SQL_NOTES) && + if (!(variables.option_bits & OPTION_SQL_NOTES) && (level == MYSQL_ERROR::WARN_LEVEL_NOTE)) DBUG_RETURN(NULL); @@ -885,41 +888,30 @@ extern "C" THD *_current_thd_noinline(void) void THD::init(void) { - pthread_mutex_lock(&LOCK_global_system_variables); + mysql_mutex_lock(&LOCK_global_system_variables); plugin_thdvar_init(this); - variables.time_format= date_time_format_copy((THD*) 0, - variables.time_format); - variables.date_format= date_time_format_copy((THD*) 0, - variables.date_format); - variables.datetime_format= date_time_format_copy((THD*) 0, - variables.datetime_format); /* variables= global_system_variables above has reset variables.pseudo_thread_id to 0. We need to correct it here to avoid temporary tables replication failure. */ variables.pseudo_thread_id= thread_id; - pthread_mutex_unlock(&LOCK_global_system_variables); + mysql_mutex_unlock(&LOCK_global_system_variables); server_status= SERVER_STATUS_AUTOCOMMIT; if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES; - options= thd_startup_options; - if (variables.max_join_size == HA_POS_ERROR) - options |= OPTION_BIG_SELECTS; - else - options &= ~OPTION_BIG_SELECTS; - - transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= FALSE; + transaction.all.modified_non_trans_table= + transaction.stmt.modified_non_trans_table= FALSE; open_options=ha_open_options; update_lock_default= (variables.low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE); session_tx_isolation= (enum_tx_isolation) variables.tx_isolation; update_charset(); - reset_current_stmt_binlog_row_based(); + reset_current_stmt_binlog_format_row(); bzero((char *) &status_var, sizeof(status_var)); - sql_log_bin_toplevel= options & OPTION_BIN_LOG; + sql_log_bin_toplevel= variables.option_bits & OPTION_BIN_LOG; #if defined(ENABLED_DEBUG_SYNC) /* Initialize the Debug Sync Facility. See debug_sync.cc. */ @@ -941,11 +933,9 @@ void THD::init_for_queries() reset_root_defaults(mem_root, variables.query_alloc_block_size, variables.query_prealloc_size); -#ifdef USING_TRANSACTIONS reset_root_defaults(&transaction.mem_root, variables.trans_alloc_block_size, variables.trans_prealloc_size); -#endif transaction.xid_state.xid.null(); transaction.xid_state.in_thd=1; } @@ -964,9 +954,9 @@ void THD::init_for_queries() void THD::change_user(void) { - pthread_mutex_lock(&LOCK_status); + mysql_mutex_lock(&LOCK_status); add_to_status(&global_status_var, &status_var); - pthread_mutex_unlock(&LOCK_status); + mysql_mutex_unlock(&LOCK_status); cleanup(); killed= NOT_KILLED; @@ -1014,10 +1004,6 @@ void THD::cleanup(void) delete_dynamic(&user_var_events); my_hash_free(&user_vars); close_temporary_tables(this); - my_free((char*) variables.time_format, MYF(MY_ALLOW_ZERO_PTR)); - my_free((char*) variables.date_format, MYF(MY_ALLOW_ZERO_PTR)); - my_free((char*) variables.datetime_format, MYF(MY_ALLOW_ZERO_PTR)); - sp_cache_clear(&sp_proc_cache); sp_cache_clear(&sp_func_cache); @@ -1025,9 +1011,9 @@ void THD::cleanup(void) unlock_global_read_lock(this); if (ull) { - pthread_mutex_lock(&LOCK_user_locks); + mysql_mutex_lock(&LOCK_user_locks); item_user_lock_release(ull); - pthread_mutex_unlock(&LOCK_user_locks); + mysql_mutex_unlock(&LOCK_user_locks); ull= NULL; } @@ -1041,8 +1027,8 @@ THD::~THD() THD_CHECK_SENTRY(this); DBUG_ENTER("~THD()"); /* Ensure that no one is using THD */ - pthread_mutex_lock(&LOCK_thd_data); - pthread_mutex_unlock(&LOCK_thd_data); + mysql_mutex_lock(&LOCK_thd_data); + mysql_mutex_unlock(&LOCK_thd_data); add_to_status(&global_status_var, &status_var); /* Close connection */ @@ -1059,16 +1045,15 @@ THD::~THD() cleanup(); ha_close_connection(this); + mysql_audit_release(this); plugin_thdvar_cleanup(this); DBUG_PRINT("info", ("freeing security context")); main_security_ctx.destroy(); safeFree(db); -#ifdef USING_TRANSACTIONS free_root(&transaction.mem_root,MYF(0)); -#endif mysys_var=0; // Safety (shouldn't be needed) - pthread_mutex_destroy(&LOCK_thd_data); + mysql_mutex_destroy(&LOCK_thd_data); #ifndef DBUG_OFF dbug_sentry= THD_SENTRY_GONE; #endif @@ -1078,6 +1063,8 @@ THD::~THD() delete rli_fake; rli_fake= NULL; } + + mysql_audit_free_thd(this); #endif free_root(&main_mem_root, MYF(0)); @@ -1141,7 +1128,7 @@ void THD::awake(THD::killed_state state_to_set) DBUG_ENTER("THD::awake"); DBUG_PRINT("enter", ("this: 0x%lx", (long) this)); THD_CHECK_SENTRY(this); - safe_mutex_assert_owner(&LOCK_thd_data); + mysql_mutex_assert_owner(&LOCK_thd_data); killed= state_to_set; if (state_to_set != THD::KILL_QUERY) @@ -1168,7 +1155,7 @@ void THD::awake(THD::killed_state state_to_set) } if (mysys_var) { - pthread_mutex_lock(&mysys_var->mutex); + mysql_mutex_lock(&mysys_var->mutex); if (!system_thread) // Don't abort locks mysys_var->abort=1; /* @@ -1192,11 +1179,11 @@ void THD::awake(THD::killed_state state_to_set) */ if (mysys_var->current_cond && mysys_var->current_mutex) { - pthread_mutex_lock(mysys_var->current_mutex); - pthread_cond_broadcast(mysys_var->current_cond); - pthread_mutex_unlock(mysys_var->current_mutex); + mysql_mutex_lock(mysys_var->current_mutex); + mysql_cond_broadcast(mysys_var->current_cond); + mysql_mutex_unlock(mysys_var->current_mutex); } - pthread_mutex_unlock(&mysys_var->mutex); + mysql_mutex_unlock(&mysys_var->mutex); } DBUG_VOID_RETURN; } @@ -1388,15 +1375,21 @@ bool THD::convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs) void THD::update_charset() { uint32 not_used; - charset_is_system_charset= !String::needs_conversion(0,charset(), - system_charset_info, - ¬_used); + charset_is_system_charset= + !String::needs_conversion(0, + variables.character_set_client, + system_charset_info, + ¬_used); charset_is_collation_connection= - !String::needs_conversion(0,charset(),variables.collation_connection, + !String::needs_conversion(0, + variables.character_set_client, + variables.collation_connection, ¬_used); charset_is_character_set_filesystem= - !String::needs_conversion(0, charset(), - variables.character_set_filesystem, ¬_used); + !String::needs_conversion(0, + variables.character_set_client, + variables.character_set_filesystem, + ¬_used); } @@ -1419,8 +1412,8 @@ void THD::add_changed_table(TABLE *table) { DBUG_ENTER("THD::add_changed_table(table)"); - DBUG_ASSERT((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && - table->file->has_transactions()); + DBUG_ASSERT(variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)); + DBUG_ASSERT(table->file->has_transactions()); add_changed_table(table->s->table_cache_key.str, (long) table->s->table_cache_key.length); DBUG_VOID_RETURN; @@ -1538,7 +1531,7 @@ int THD::send_explain_fields(select_result *result) void THD::close_active_vio() { DBUG_ENTER("close_active_vio"); - safe_mutex_assert_owner(&LOCK_thd_data); + mysql_mutex_assert_owner(&LOCK_thd_data); #ifndef EMBEDDED_LIBRARY if (active_vio) { @@ -1614,7 +1607,6 @@ void THD::rollback_item_tree_changes() select_result::select_result() { thd=current_thd; - nest_level= -1; } void select_result::send_error(uint errcode,const char *err) @@ -1771,8 +1763,9 @@ void select_to_file::send_error(uint errcode,const char *err) if (file > 0) { (void) end_io_cache(&cache); - (void) my_close(file,MYF(0)); - (void) my_delete(path,MYF(0)); // Delete file on error + mysql_file_close(file, MYF(0)); + /* Delete file on error */ + mysql_file_delete(key_select_to_file, path, MYF(0)); file= -1; } } @@ -1781,7 +1774,7 @@ void select_to_file::send_error(uint errcode,const char *err) bool select_to_file::send_eof() { int error= test(end_io_cache(&cache)); - if (my_close(file,MYF(MY_WME))) + if (mysql_file_close(file, MYF(MY_WME))) error= 1; if (!error) { @@ -1803,7 +1796,7 @@ void select_to_file::cleanup() if (file >= 0) { (void) end_io_cache(&cache); - (void) my_close(file,MYF(0)); + mysql_file_close(file, MYF(0)); file= -1; } path[0]= '\0'; @@ -1816,7 +1809,7 @@ select_to_file::~select_to_file() if (file >= 0) { // This only happens in case of error (void) end_io_cache(&cache); - (void) my_close(file,MYF(0)); + mysql_file_close(file, MYF(0)); file= -1; } } @@ -1880,7 +1873,8 @@ static File create_file(THD *thd, char *path, sql_exchange *exchange, return -1; } /* Create the file world readable */ - if ((file= my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0) + if ((file= mysql_file_create(key_select_to_file, + path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0) return file; #ifdef HAVE_FCHMOD (void) fchmod(file, 0666); // Because of umask() @@ -1889,8 +1883,9 @@ static File create_file(THD *thd, char *path, sql_exchange *exchange, #endif if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME))) { - my_close(file, MYF(0)); - my_delete(path, MYF(0)); // Delete file on error, it was just created + mysql_file_close(file, MYF(0)); + /* Delete file on error, it was just created */ + mysql_file_delete(key_select_to_file, path, MYF(0)); return -1; } return file; @@ -2683,7 +2678,7 @@ int Statement_map::insert(THD *thd, Statement *statement) my_error(ER_OUT_OF_RESOURCES, MYF(0)); goto err_names_hash; } - pthread_mutex_lock(&LOCK_prepared_stmt_count); + mysql_mutex_lock(&LOCK_prepared_stmt_count); /* We don't check that prepared_stmt_count is <= max_prepared_stmt_count because we would like to allow to lower the total limit @@ -2693,13 +2688,13 @@ int Statement_map::insert(THD *thd, Statement *statement) */ if (prepared_stmt_count >= max_prepared_stmt_count) { - pthread_mutex_unlock(&LOCK_prepared_stmt_count); + mysql_mutex_unlock(&LOCK_prepared_stmt_count); my_error(ER_MAX_PREPARED_STMT_COUNT_REACHED, MYF(0), max_prepared_stmt_count); goto err_max; } prepared_stmt_count++; - pthread_mutex_unlock(&LOCK_prepared_stmt_count); + mysql_mutex_unlock(&LOCK_prepared_stmt_count); last_found_statement= statement; return 0; @@ -2732,20 +2727,20 @@ void Statement_map::erase(Statement *statement) my_hash_delete(&names_hash, (uchar *) statement); my_hash_delete(&st_hash, (uchar *) statement); - pthread_mutex_lock(&LOCK_prepared_stmt_count); + mysql_mutex_lock(&LOCK_prepared_stmt_count); DBUG_ASSERT(prepared_stmt_count > 0); prepared_stmt_count--; - pthread_mutex_unlock(&LOCK_prepared_stmt_count); + mysql_mutex_unlock(&LOCK_prepared_stmt_count); } void Statement_map::reset() { /* Must be first, hash_free will reset st_hash.records */ - pthread_mutex_lock(&LOCK_prepared_stmt_count); + mysql_mutex_lock(&LOCK_prepared_stmt_count); DBUG_ASSERT(prepared_stmt_count >= st_hash.records); prepared_stmt_count-= st_hash.records; - pthread_mutex_unlock(&LOCK_prepared_stmt_count); + mysql_mutex_unlock(&LOCK_prepared_stmt_count); my_hash_reset(&names_hash); my_hash_reset(&st_hash); @@ -2756,10 +2751,10 @@ void Statement_map::reset() Statement_map::~Statement_map() { /* Must go first, hash_free will reset st_hash.records */ - pthread_mutex_lock(&LOCK_prepared_stmt_count); + mysql_mutex_lock(&LOCK_prepared_stmt_count); DBUG_ASSERT(prepared_stmt_count >= st_hash.records); prepared_stmt_count-= st_hash.records; - pthread_mutex_unlock(&LOCK_prepared_stmt_count); + mysql_mutex_unlock(&LOCK_prepared_stmt_count); my_hash_free(&names_hash); my_hash_free(&st_hash); @@ -3105,7 +3100,7 @@ extern "C" int thd_non_transactional_update(const MYSQL_THD thd) extern "C" int thd_binlog_format(const MYSQL_THD thd) { - if (mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG)) + if (mysql_bin_log.is_open() && (thd->variables.option_bits & OPTION_BIN_LOG)) return (int) thd->variables.binlog_format; else return BINLOG_FORMAT_UNSPEC; @@ -3166,7 +3161,7 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup, } #endif - backup->options= options; + backup->option_bits= variables.option_bits; backup->in_sub_stmt= in_sub_stmt; backup->enable_slow_log= enable_slow_log; backup->limit_found_rows= limit_found_rows; @@ -3181,13 +3176,14 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup, first_successful_insert_id_in_cur_stmt; if ((!lex->requires_prelocking() || is_update_query(lex->sql_command)) && - !current_stmt_binlog_row_based) + !is_current_stmt_binlog_format_row()) { - options&= ~OPTION_BIN_LOG; + variables.option_bits&= ~OPTION_BIN_LOG; } - if ((backup->options & OPTION_BIN_LOG) && is_update_query(lex->sql_command)&& - !current_stmt_binlog_row_based) + if ((backup->option_bits & OPTION_BIN_LOG) && + is_update_query(lex->sql_command) && + !is_current_stmt_binlog_format_row()) mysql_bin_log.start_union_events(this, this->query_id); /* Disable result sets */ @@ -3230,7 +3226,7 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup) (void)ha_release_savepoint(this, sv); } transaction.savepoints= backup->savepoints; - options= backup->options; + variables.option_bits= backup->option_bits; in_sub_stmt= backup->in_sub_stmt; enable_slow_log= backup->enable_slow_log; first_successful_insert_id_in_prev_stmt= @@ -3248,8 +3244,8 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup) if (!in_sub_stmt) is_fatal_sub_stmt_error= FALSE; - if ((options & OPTION_BIN_LOG) && is_update_query(lex->sql_command) && - !current_stmt_binlog_row_based) + if ((variables.option_bits & OPTION_BIN_LOG) && is_update_query(lex->sql_command) && + !is_current_stmt_binlog_format_row()) mysql_bin_log.stop_union_events(this); /* @@ -3263,9 +3259,9 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup) void THD::set_statement(Statement *stmt) { - pthread_mutex_lock(&LOCK_thd_data); + mysql_mutex_lock(&LOCK_thd_data); Statement::set_statement(stmt); - pthread_mutex_unlock(&LOCK_thd_data); + mysql_mutex_unlock(&LOCK_thd_data); } @@ -3273,9 +3269,29 @@ void THD::set_statement(Statement *stmt) void THD::set_query(char *query_arg, uint32 query_length_arg) { - pthread_mutex_lock(&LOCK_thd_data); + mysql_mutex_lock(&LOCK_thd_data); + set_query_inner(query_arg, query_length_arg); + mysql_mutex_unlock(&LOCK_thd_data); +} + +/** Assign a new value to thd->query and thd->query_id. */ + +void THD::set_query_and_id(char *query_arg, uint32 query_length_arg, + query_id_t new_query_id) +{ + mysql_mutex_lock(&LOCK_thd_data); set_query_inner(query_arg, query_length_arg); - pthread_mutex_unlock(&LOCK_thd_data); + query_id= new_query_id; + mysql_mutex_unlock(&LOCK_thd_data); +} + +/** Assign a new value to thd->query_id. */ + +void THD::set_query_id(query_id_t new_query_id) +{ + mysql_mutex_lock(&LOCK_thd_data); + query_id= new_query_id; + mysql_mutex_unlock(&LOCK_thd_data); } @@ -3308,7 +3324,7 @@ void mark_transaction_to_rollback(THD *thd, bool all) Handling of XA id cacheing ***************************************************************************/ -pthread_mutex_t LOCK_xid_cache; +mysql_mutex_t LOCK_xid_cache; HASH xid_cache; extern "C" uchar *xid_get_hash_key(const uchar *, size_t *, my_bool); @@ -3327,9 +3343,34 @@ void xid_free_hash(void *ptr) my_free((uchar*)ptr, MYF(0)); } +#ifdef HAVE_PSI_INTERFACE +static PSI_mutex_key key_LOCK_xid_cache; + +static PSI_mutex_info all_xid_mutexes[]= +{ + { &key_LOCK_xid_cache, "LOCK_xid_cache", PSI_FLAG_GLOBAL} +}; + +static void init_xid_psi_keys(void) +{ + const char* category= "sql"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_xid_mutexes); + PSI_server->register_mutex(category, all_xid_mutexes, count); +} +#endif /* HAVE_PSI_INTERFACE */ + bool xid_cache_init() { - pthread_mutex_init(&LOCK_xid_cache, MY_MUTEX_INIT_FAST); +#ifdef HAVE_PSI_INTERFACE + init_xid_psi_keys(); +#endif + + mysql_mutex_init(key_LOCK_xid_cache, &LOCK_xid_cache, MY_MUTEX_INIT_FAST); return my_hash_init(&xid_cache, &my_charset_bin, 100, 0, 0, xid_get_hash_key, xid_free_hash, 0) != 0; } @@ -3339,16 +3380,16 @@ void xid_cache_free() if (my_hash_inited(&xid_cache)) { my_hash_free(&xid_cache); - pthread_mutex_destroy(&LOCK_xid_cache); + mysql_mutex_destroy(&LOCK_xid_cache); } } XID_STATE *xid_cache_search(XID *xid) { - pthread_mutex_lock(&LOCK_xid_cache); + mysql_mutex_lock(&LOCK_xid_cache); XID_STATE *res=(XID_STATE *)my_hash_search(&xid_cache, xid->key(), xid->key_length()); - pthread_mutex_unlock(&LOCK_xid_cache); + mysql_mutex_unlock(&LOCK_xid_cache); return res; } @@ -3357,7 +3398,7 @@ bool xid_cache_insert(XID *xid, enum xa_states xa_state) { XID_STATE *xs; my_bool res; - pthread_mutex_lock(&LOCK_xid_cache); + mysql_mutex_lock(&LOCK_xid_cache); if (my_hash_search(&xid_cache, xid->key(), xid->key_length())) res=0; else if (!(xs=(XID_STATE *)my_malloc(sizeof(*xs), MYF(MY_WME)))) @@ -3369,29 +3410,415 @@ bool xid_cache_insert(XID *xid, enum xa_states xa_state) xs->in_thd=0; res=my_hash_insert(&xid_cache, (uchar*)xs); } - pthread_mutex_unlock(&LOCK_xid_cache); + mysql_mutex_unlock(&LOCK_xid_cache); return res; } bool xid_cache_insert(XID_STATE *xid_state) { - pthread_mutex_lock(&LOCK_xid_cache); + mysql_mutex_lock(&LOCK_xid_cache); DBUG_ASSERT(my_hash_search(&xid_cache, xid_state->xid.key(), xid_state->xid.key_length())==0); my_bool res=my_hash_insert(&xid_cache, (uchar*)xid_state); - pthread_mutex_unlock(&LOCK_xid_cache); + mysql_mutex_unlock(&LOCK_xid_cache); return res; } void xid_cache_delete(XID_STATE *xid_state) { - pthread_mutex_lock(&LOCK_xid_cache); + mysql_mutex_lock(&LOCK_xid_cache); my_hash_delete(&xid_cache, (uchar *)xid_state); - pthread_mutex_unlock(&LOCK_xid_cache); + mysql_mutex_unlock(&LOCK_xid_cache); +} + + +/** + Decide on logging format to use for the statement and issue errors + or warnings as needed. The decision depends on the following + parameters: + + - The logging mode, i.e., the value of binlog_format. Can be + statement, mixed, or row. + + - The type of statement. There are three types of statements: + "normal" safe statements; unsafe statements; and row injections. + An unsafe statement is one that, if logged in statement format, + might produce different results when replayed on the slave (e.g., + INSERT DELAYED). A row injection is either a BINLOG statement, or + a row event executed by the slave's SQL thread. + + - The capabilities of tables modified by the statement. The + *capabilities vector* for a table is a set of flags associated + with the table. Currently, it only includes two flags: *row + capability flag* and *statement capability flag*. + + The row capability flag is set if and only if the engine can + handle row-based logging. The statement capability flag is set if + and only if the table can handle statement-based logging. + + Decision table for logging format + --------------------------------- + + The following table summarizes how the format and generated + warning/error depends on the tables' capabilities, the statement + type, and the current binlog_format. + + Row capable N NNNNNNNNN YYYYYYYYY YYYYYYYYY + Statement capable N YYYYYYYYY NNNNNNNNN YYYYYYYYY + + Statement type * SSSUUUIII SSSUUUIII SSSUUUIII + + binlog_format * SMRSMRSMR SMRSMRSMR SMRSMRSMR + + Logged format - SS-S----- -RR-RR-RR SRRSRR-RR + Warning/Error 1 --2732444 5--5--6-- ---7--6-- + + Legend + ------ + + Row capable: N - Some table not row-capable, Y - All tables row-capable + Stmt capable: N - Some table not stmt-capable, Y - All tables stmt-capable + Statement type: (S)afe, (U)nsafe, or Row (I)njection + binlog_format: (S)TATEMENT, (M)IXED, or (R)OW + Logged format: (S)tatement or (R)ow + Warning/Error: Warnings and error messages are as follows: + + 1. Error: Cannot execute statement: binlogging impossible since both + row-incapable engines and statement-incapable engines are + involved. + + 2. Error: Cannot execute statement: binlogging impossible since + BINLOG_FORMAT = ROW and at least one table uses a storage engine + limited to statement-logging. + + 3. Error: Cannot execute statement: binlogging of unsafe statement + is impossible when storage engine is limited to statement-logging + and BINLOG_FORMAT = MIXED. + + 4. Error: Cannot execute row injection: binlogging impossible since + at least one table uses a storage engine limited to + statement-logging. + + 5. Error: Cannot execute statement: binlogging impossible since + BINLOG_FORMAT = STATEMENT and at least one table uses a storage + engine limited to row-logging. + + 6. Error: Cannot execute row injection: binlogging impossible since + BINLOG_FORMAT = STATEMENT. + + 7. Warning: Unsafe statement binlogged in statement format since + BINLOG_FORMAT = STATEMENT. + + In addition, we can produce the following error (not depending on + the variables of the decision diagram): + + 8. Error: Cannot execute statement: binlogging impossible since more + than one engine is involved and at least one engine is + self-logging. + + For each error case above, the statement is prevented from being + logged, we report an error, and roll back the statement. For + warnings, we set the thd->binlog_flags variable: the warning will be + printed only if the statement is successfully logged. + + @see THD::binlog_query + + @param[in] thd Client thread + @param[in] tables Tables involved in the query + + @retval 0 No error; statement can be logged. + @retval -1 One of the error conditions above applies (1, 2, 4, 5, or 6). +*/ + +int THD::decide_logging_format(TABLE_LIST *tables) +{ + DBUG_ENTER("THD::decide_logging_format"); + DBUG_PRINT("info", ("query: %s", query())); + DBUG_PRINT("info", ("variables.binlog_format: %u", + variables.binlog_format)); + DBUG_PRINT("info", ("lex->get_stmt_unsafe_flags(): 0x%x", + lex->get_stmt_unsafe_flags())); + + /* + We should not decide logging format if the binlog is closed or + binlogging is off, or if the statement is filtered out from the + binlog by filtering rules. + */ + if (mysql_bin_log.is_open() && (variables.option_bits & OPTION_BIN_LOG) && + !(variables.binlog_format == BINLOG_FORMAT_STMT && + !binlog_filter->db_ok(db))) + { + /* + Compute one bit field with the union of all the engine + capabilities, and one with the intersection of all the engine + capabilities. + */ + handler::Table_flags flags_some_set= 0; + handler::Table_flags flags_all_set= + HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE; + + my_bool multi_engine= FALSE; + my_bool mixed_engine= FALSE; + my_bool all_trans_engines= TRUE; + TABLE* prev_write_table= NULL; + TABLE* prev_access_table= NULL; + +#ifndef DBUG_OFF + { + static const char *prelocked_mode_name[] = { + "NON_PRELOCKED", + "PRELOCKED", + "PRELOCKED_UNDER_LOCK_TABLES", + }; + DBUG_PRINT("debug", ("prelocked_mode: %s", + prelocked_mode_name[prelocked_mode])); + } +#endif + + /* + Get the capabilities vector for all involved storage engines and + mask out the flags for the binary log. + */ + for (TABLE_LIST *table= tables; table; table= table->next_global) + { + if (table->placeholder()) + continue; + if (table->table->s->table_category == TABLE_CATEGORY_PERFORMANCE) + lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_TABLE); + if (table->lock_type >= TL_WRITE_ALLOW_WRITE) + { + handler::Table_flags const flags= table->table->file->ha_table_flags(); + DBUG_PRINT("info", ("table: %s; ha_table_flags: 0x%llx", + table->table_name, flags)); + if (prev_write_table && prev_write_table->file->ht != + table->table->file->ht) + multi_engine= TRUE; + all_trans_engines= all_trans_engines && + table->table->file->has_transactions(); + prev_write_table= table->table; + flags_all_set &= flags; + flags_some_set |= flags; + } + if (prev_access_table && prev_access_table->file->ht != table->table->file->ht) + mixed_engine= mixed_engine || (prev_access_table->file->has_transactions() != + table->table->file->has_transactions()); + prev_access_table= table->table; + } + + /* + Set the statement as unsafe if: + + . it is a mixed statement, i.e. access transactional and non-transactional + tables, and updates at least one; + or + . an early statement updated a transactional table; + . and, the current statement updates a non-transactional table. + + Any mixed statement is classified as unsafe to ensure that mixed mode is + completely safe. Consider the following example to understand why we + decided to do this: + + Note that mixed statements such as + + 1: INSERT INTO myisam_t SELECT * FROM innodb_t; + + 2: INSERT INTO innodb_t SELECT * FROM myisam_t; + + are classified as unsafe to ensure that in mixed mode the execution is + completely safe and equivalent to the row mode. Consider the following + statements and sessions (connections) to understand the reason: + + con1: INSERT INTO innodb_t VALUES (1); + con1: INSERT INTO innodb_t VALUES (100); + + con1: BEGIN + con2: INSERT INTO myisam_t SELECT * FROM innodb_t; + con1: INSERT INTO innodb_t VALUES (200); + con1: COMMIT; + + The point is that the concurrent statements may be written into the binary log + in a way different from the execution. For example, + + BINARY LOG: + + con2: BEGIN; + con2: INSERT INTO myisam_t SELECT * FROM innodb_t; + con2: COMMIT; + con1: BEGIN + con1: INSERT INTO innodb_t VALUES (200); + con1: COMMIT; + + .... + + or + + BINARY LOG: + + con1: BEGIN + con1: INSERT INTO innodb_t VALUES (200); + con1: COMMIT; + con2: BEGIN; + con2: INSERT INTO myisam_t SELECT * FROM innodb_t; + con2: COMMIT; + + Clearly, this may become a problem in STMT mode and setting the statement + as unsafe will make rows to be written into the binary log in MIXED mode + and as such the problem will not stand. + + In STMT mode, although such statement is classified as unsafe, i.e. + + INSERT INTO myisam_t SELECT * FROM innodb_t; + + there is no enough information to avoid writing it outside the boundaries + of a transaction. This is not a problem if we are considering snapshot + isolation level but if we have pure repeatable read or serializable the + lock history on the slave will be different from the master. + */ + if (mixed_engine || + (trans_has_updated_trans_table(this) && !all_trans_engines)) + lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_NONTRANS_AFTER_TRANS); + + DBUG_PRINT("info", ("flags_all_set: 0x%llx", flags_all_set)); + DBUG_PRINT("info", ("flags_some_set: 0x%llx", flags_some_set)); + DBUG_PRINT("info", ("multi_engine: %d", multi_engine)); + + int error= 0; + int unsafe_flags; + + /* + If more than one engine is involved in the statement and at + least one is doing it's own logging (is *self-logging*), the + statement cannot be logged atomically, so we generate an error + rather than allowing the binlog to become corrupt. + */ + if (multi_engine && + (flags_some_set & HA_HAS_OWN_BINLOGGING)) + { + my_error((error= ER_BINLOG_MULTIPLE_ENGINES_AND_SELF_LOGGING_ENGINE), + MYF(0)); + } + + /* both statement-only and row-only engines involved */ + if ((flags_all_set & (HA_BINLOG_STMT_CAPABLE | HA_BINLOG_ROW_CAPABLE)) == 0) + { + /* + 1. Error: Binary logging impossible since both row-incapable + engines and statement-incapable engines are involved + */ + my_error((error= ER_BINLOG_ROW_ENGINE_AND_STMT_ENGINE), MYF(0)); + } + /* statement-only engines involved */ + else if ((flags_all_set & HA_BINLOG_ROW_CAPABLE) == 0) + { + if (lex->is_stmt_row_injection()) + { + /* + 4. Error: Cannot execute row injection since table uses + storage engine limited to statement-logging + */ + my_error((error= ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE), MYF(0)); + } + else if (variables.binlog_format == BINLOG_FORMAT_ROW) + { + /* + 2. Error: Cannot modify table that uses a storage engine + limited to statement-logging when BINLOG_FORMAT = ROW + */ + my_error((error= ER_BINLOG_ROW_MODE_AND_STMT_ENGINE), MYF(0)); + } + else if ((unsafe_flags= lex->get_stmt_unsafe_flags()) != 0) + { + /* + 3. Error: Cannot execute statement: binlogging of unsafe + statement is impossible when storage engine is limited to + statement-logging and BINLOG_FORMAT = MIXED. + */ + for (int unsafe_type= 0; + unsafe_type < LEX::BINLOG_STMT_UNSAFE_COUNT; + unsafe_type++) + if (unsafe_flags & (1 << unsafe_type)) + my_error((error= ER_BINLOG_UNSAFE_AND_STMT_ENGINE), MYF(0), + ER(LEX::binlog_stmt_unsafe_errcode[unsafe_type])); + } + /* log in statement format! */ + } + /* no statement-only engines */ + else + { + /* binlog_format = STATEMENT */ + if (variables.binlog_format == BINLOG_FORMAT_STMT) + { + if (lex->is_stmt_row_injection()) + { + /* + 6. Error: Cannot execute row injection since + BINLOG_FORMAT = STATEMENT + */ + my_error((error= ER_BINLOG_ROW_INJECTION_AND_STMT_MODE), MYF(0)); + } + else if ((flags_all_set & HA_BINLOG_STMT_CAPABLE) == 0) + { + /* + 5. Error: Cannot modify table that uses a storage engine + limited to row-logging when binlog_format = STATEMENT + */ + my_error((error= ER_BINLOG_STMT_MODE_AND_ROW_ENGINE), MYF(0), ""); + } + else if ((unsafe_flags= lex->get_stmt_unsafe_flags()) != 0) + { + /* + 7. Warning: Unsafe statement logged as statement due to + binlog_format = STATEMENT + */ + binlog_unsafe_warning_flags|= unsafe_flags; + DBUG_PRINT("info", ("Scheduling warning to be issued by " + "binlog_query: '%s'", + ER(ER_BINLOG_UNSAFE_STATEMENT))); + DBUG_PRINT("info", ("binlog_unsafe_warning_flags: 0x%x", + binlog_unsafe_warning_flags)); + } + /* log in statement format! */ + } + /* No statement-only engines and binlog_format != STATEMENT. + I.e., nothing prevents us from row logging if needed. */ + else + { + if (lex->is_stmt_unsafe() || lex->is_stmt_row_injection() + || (flags_all_set & HA_BINLOG_STMT_CAPABLE) == 0) + { + /* log in row format! */ + set_current_stmt_binlog_format_row_if_mixed(); + } + } + } + + if (error) { + DBUG_PRINT("info", ("decision: no logging since an error was generated")); + DBUG_RETURN(-1); + } + DBUG_PRINT("info", ("decision: logging in %s format", + is_current_stmt_binlog_format_row() ? + "ROW" : "STATEMENT")); + } +#ifndef DBUG_OFF + else + DBUG_PRINT("info", ("decision: no logging since " + "mysql_bin_log.is_open() = %d " + "and (options & OPTION_BIN_LOG) = 0x%llx " + "and binlog_format = %u " + "and binlog_filter->db_ok(db) = %d", + mysql_bin_log.is_open(), + (variables.option_bits & OPTION_BIN_LOG), + variables.binlog_format, + binlog_filter->db_ok(db))); +#endif + + DBUG_RETURN(0); } + /* Implementation of interface to write rows to the binary log through the thread. The thread is responsible for writing the rows it has @@ -3443,7 +3870,7 @@ THD::binlog_prepare_pending_rows_event(TABLE* table, uint32 serv_id, if (binlog_setup_trx_data()) DBUG_RETURN(NULL); - Rows_log_event* pending= binlog_get_pending_rows_event(); + Rows_log_event* pending= binlog_get_pending_rows_event(is_transactional); if (unlikely(pending && !pending->is_valid())) DBUG_RETURN(NULL); @@ -3477,7 +3904,9 @@ THD::binlog_prepare_pending_rows_event(TABLE* table, uint32 serv_id, flush the pending event and replace it with the newly created event... */ - if (unlikely(mysql_bin_log.flush_and_set_pending_rows_event(this, ev))) + if (unlikely( + mysql_bin_log.flush_and_set_pending_rows_event(this, ev, + is_transactional))) { delete ev; DBUG_RETURN(NULL); @@ -3700,7 +4129,7 @@ int THD::binlog_write_row(TABLE* table, bool is_trans, MY_BITMAP const* cols, size_t colcnt, uchar const *record) { - DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open()); + DBUG_ASSERT(is_current_stmt_binlog_format_row() && mysql_bin_log.is_open()); /* Pack records into format for transfer. We are allocating more @@ -3730,7 +4159,7 @@ int THD::binlog_update_row(TABLE* table, bool is_trans, const uchar *before_record, const uchar *after_record) { - DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open()); + DBUG_ASSERT(is_current_stmt_binlog_format_row() && mysql_bin_log.is_open()); size_t const before_maxlen = max_row_length(table, before_record); size_t const after_maxlen = max_row_length(table, after_record); @@ -3775,7 +4204,7 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans, MY_BITMAP const* cols, size_t colcnt, uchar const *record) { - DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open()); + DBUG_ASSERT(is_current_stmt_binlog_format_row() && mysql_bin_log.is_open()); /* Pack records into format for transfer. We are allocating more @@ -3801,14 +4230,15 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans, } -int THD::binlog_remove_pending_rows_event(bool clear_maps) +int THD::binlog_remove_pending_rows_event(bool clear_maps, + bool is_transactional) { DBUG_ENTER("THD::binlog_remove_pending_rows_event"); if (!mysql_bin_log.is_open()) DBUG_RETURN(0); - mysql_bin_log.remove_pending_rows_event(this); + mysql_bin_log.remove_pending_rows_event(this, is_transactional); if (clear_maps) binlog_table_maps= 0; @@ -3816,7 +4246,7 @@ int THD::binlog_remove_pending_rows_event(bool clear_maps) DBUG_RETURN(0); } -int THD::binlog_flush_pending_rows_event(bool stmt_end) +int THD::binlog_flush_pending_rows_event(bool stmt_end, bool is_transactional) { DBUG_ENTER("THD::binlog_flush_pending_rows_event"); /* @@ -3832,7 +4262,7 @@ int THD::binlog_flush_pending_rows_event(bool stmt_end) flag is set. */ int error= 0; - if (Rows_log_event *pending= binlog_get_pending_rows_event()) + if (Rows_log_event *pending= binlog_get_pending_rows_event(is_transactional)) { if (stmt_end) { @@ -3841,7 +4271,8 @@ int THD::binlog_flush_pending_rows_event(bool stmt_end) binlog_table_maps= 0; } - error= mysql_bin_log.flush_and_set_pending_rows_event(this, 0); + error= mysql_bin_log.flush_and_set_pending_rows_event(this, 0, + is_transactional); } DBUG_RETURN(error); @@ -3857,8 +4288,6 @@ show_query_type(THD::enum_binlog_query_type qtype) return "ROW"; case THD::STMT_QUERY_TYPE: return "STMT"; - case THD::MYSQL_QUERY_TYPE: - return "MYSQL"; case THD::QUERY_TYPE_COUNT: default: DBUG_ASSERT(0 <= qtype && qtype < THD::QUERY_TYPE_COUNT); @@ -3870,32 +4299,97 @@ show_query_type(THD::enum_binlog_query_type qtype) #endif -/* - Member function that will log query, either row-based or - statement-based depending on the value of the 'current_stmt_binlog_row_based' - the value of the 'qtype' flag. +/** + Auxiliary method used by @c binlog_query() to raise warnings. - This function should be called after the all calls to ha_*_row() - functions have been issued, but before tables are unlocked and - closed. + The type of warning and the type of unsafeness is stored in + THD::binlog_unsafe_warning_flags. +*/ +void THD::issue_unsafe_warnings() +{ + DBUG_ENTER("issue_unsafe_warnings"); + /* + Ensure that binlog_unsafe_warning_flags is big enough to hold all + bits. This is actually a constant expression. + */ + DBUG_ASSERT(2 * LEX::BINLOG_STMT_UNSAFE_COUNT <= + sizeof(binlog_unsafe_warning_flags) * CHAR_BIT); - OBSERVE - There shall be no writes to any system table after calling - binlog_query(), so these writes has to be moved to before the call - of binlog_query() for correct functioning. + uint32 unsafe_type_flags= binlog_unsafe_warning_flags; - This is necessesary not only for RBR, but the master might crash - after binlogging the query but before changing the system tables. - This means that the slave and the master are not in the same state - (after the master has restarted), so therefore we have to - eliminate this problem. + /* + Clear: (1) bits above BINLOG_STMT_UNSAFE_COUNT; (2) bits for + warnings that have been printed already. + */ + unsafe_type_flags &= (LEX::BINLOG_STMT_UNSAFE_ALL_FLAGS ^ + (unsafe_type_flags >> LEX::BINLOG_STMT_UNSAFE_COUNT)); + /* If all warnings have been printed already, return. */ + if (unsafe_type_flags == 0) + DBUG_VOID_RETURN; - RETURN VALUE - Error code, or 0 if no error. + DBUG_PRINT("info", ("unsafe_type_flags: 0x%x", unsafe_type_flags)); + + /* + For each unsafe_type, check if the statement is unsafe in this way + and issue a warning. + */ + for (int unsafe_type=0; + unsafe_type < LEX::BINLOG_STMT_UNSAFE_COUNT; + unsafe_type++) + { + if ((unsafe_type_flags & (1 << unsafe_type)) != 0) + { + push_warning_printf(this, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_BINLOG_UNSAFE_STATEMENT, + ER(ER_BINLOG_UNSAFE_STATEMENT), + ER(LEX::binlog_stmt_unsafe_errcode[unsafe_type])); + if (global_system_variables.log_warnings) + { + char buf[MYSQL_ERRMSG_SIZE * 2]; + sprintf(buf, ER(ER_BINLOG_UNSAFE_STATEMENT), + ER(LEX::binlog_stmt_unsafe_errcode[unsafe_type])); + sql_print_warning(ER(ER_MESSAGE_AND_STATEMENT), buf, query()); + } + } + } + /* + Mark these unsafe types as already printed, to avoid printing + warnings for them again. + */ + binlog_unsafe_warning_flags|= + unsafe_type_flags << LEX::BINLOG_STMT_UNSAFE_COUNT; + DBUG_VOID_RETURN; +} + + +/** + Log the current query. + + The query will be logged in either row format or statement format + depending on the value of @c current_stmt_binlog_format_row field and + the value of the @c qtype parameter. + + This function must be called: + + - After the all calls to ha_*_row() functions have been issued. + + - After any writes to system tables. Rationale: if system tables + were written after a call to this function, and the master crashes + after the call to this function and before writing the system + tables, then the master and slave get out of sync. + + - Before tables are unlocked and closed. + + @see decide_logging_format + + @retval 0 Success + + @retval nonzero If there is a failure when writing the query (e.g., + write failure), then the error code is returned. */ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg, - ulong query_len, bool is_trans, bool suppress_use, - int errcode) + ulong query_len, bool is_trans, bool direct, + bool suppress_use, int errcode) { DBUG_ENTER("THD::binlog_query"); DBUG_PRINT("enter", ("qtype: %s query: '%s'", @@ -3912,59 +4406,53 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg, top-most close_thread_tables(). */ if (this->prelocked_mode == NON_PRELOCKED) - if (int error= binlog_flush_pending_rows_event(TRUE)) + if (int error= binlog_flush_pending_rows_event(TRUE, is_trans)) DBUG_RETURN(error); /* - If we are in statement mode and trying to log an unsafe statement, - we should print a warning. + Warnings for unsafe statements logged in statement format are + printed here instead of in decide_logging_format(). This is + because the warnings should be printed only if the statement is + actually logged. When executing decide_logging_format(), we cannot + know for sure if the statement will be logged. */ - if (sql_log_bin_toplevel && lex->is_stmt_unsafe() && - variables.binlog_format == BINLOG_FORMAT_STMT && - binlog_filter->db_ok(this->db)) - { - /* - A warning can be elevated a error when STRICT sql mode. - But we don't want to elevate binlog warning to error here. - */ - push_warning(this, MYSQL_ERROR::WARN_LEVEL_NOTE, - ER_BINLOG_UNSAFE_STATEMENT, - ER(ER_BINLOG_UNSAFE_STATEMENT)); - if (global_system_variables.log_warnings && - !(binlog_flags & BINLOG_FLAG_UNSAFE_STMT_PRINTED)) - { - sql_print_warning("%s Statement: %.*s", - ER(ER_BINLOG_UNSAFE_STATEMENT), - MYSQL_ERRMSG_SIZE, query_arg); - binlog_flags|= BINLOG_FLAG_UNSAFE_STMT_PRINTED; - } - } + if (sql_log_bin_toplevel) + issue_unsafe_warnings(); switch (qtype) { + /* + ROW_QUERY_TYPE means that the statement may be logged either in + row format or in statement format. If + current_stmt_binlog_format is row, it means that the + statement has already been logged in row format and hence shall + not be logged again. + */ case THD::ROW_QUERY_TYPE: DBUG_PRINT("debug", - ("current_stmt_binlog_row_based: %d", - current_stmt_binlog_row_based)); - if (current_stmt_binlog_row_based) + ("is_current_stmt_binlog_format_row: %d", + is_current_stmt_binlog_format_row())); + if (is_current_stmt_binlog_format_row()) DBUG_RETURN(0); - /* Otherwise, we fall through */ - case THD::MYSQL_QUERY_TYPE: - /* - Using this query type is a conveniece hack, since we have been - moving back and forth between using RBR for replication of - system tables and not using it. + /* Fall through */ - Make sure to change in check_table_binlog_row_based() according - to how you treat this. + /* + STMT_QUERY_TYPE means that the query must be logged in statement + format; it cannot be logged in row format. This is typically + used by DDL statements. It is an error to use this query type + if current_stmt_binlog_format_row is row. + + @todo Currently there are places that call this method with + STMT_QUERY_TYPE and current_stmt_binlog_format is row. Fix those + places and add assert to ensure correct behavior. /Sven */ case THD::STMT_QUERY_TYPE: /* The MYSQL_LOG::write() function will set the STMT_END_F flag and flush the pending rows event if necessary. - */ + */ { - Query_log_event qinfo(this, query_arg, query_len, is_trans, suppress_use, - errcode); + Query_log_event qinfo(this, query_arg, query_len, is_trans, direct, + suppress_use, errcode); qinfo.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F; /* Binlog table maps will be irrelevant after a Query_log_event diff --git a/sql/sql_class.h b/sql/sql_class.h index ab86ac6df12..7bebc639c37 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -23,6 +23,7 @@ #pragma interface /* gcc class implementation */ #endif +#include <mysql/plugin_audit.h> #include "log.h" #include "rpl_tblmap.h" @@ -46,6 +47,8 @@ enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON, enum enum_slave_exec_mode { SLAVE_EXEC_MODE_STRICT, SLAVE_EXEC_MODE_IDEMPOTENT, SLAVE_EXEC_MODE_LAST_BIT}; +enum enum_slave_type_conversions { SLAVE_TYPE_CONVERSIONS_ALL_LOSSY, + SLAVE_TYPE_CONVERSIONS_ALL_NON_LOSSY}; enum enum_mark_columns { MARK_COLUMNS_NONE, MARK_COLUMNS_READ, MARK_COLUMNS_WRITE}; enum enum_filetype { FILETYPE_CSV, FILETYPE_XML }; @@ -309,7 +312,7 @@ class Time_zone; #define THD_CHECK_SENTRY(thd) DBUG_ASSERT(thd->dbug_sentry == THD_SENTRY_MAGIC) -struct system_variables +typedef struct system_variables { /* How dynamically allocated system variables are handled: @@ -326,10 +329,12 @@ struct system_variables uint dynamic_variables_size; /* how many bytes are in use */ ulonglong myisam_max_extra_sort_file_size; - ulonglong myisam_max_sort_file_size; ulonglong max_heap_table_size; ulonglong tmp_table_size; ulonglong long_query_time; + ulonglong optimizer_switch; + ulonglong sql_mode; ///< which non-standard SQL behaviour should be enabled + ulonglong option_bits; ///< OPTION_xxx constants, e.g. OPTION_PROFILING ha_rows select_limit; ha_rows max_join_size; ulong auto_increment_increment, auto_increment_offset; @@ -343,9 +348,6 @@ struct system_variables ulong max_insert_delayed_threads; ulong min_examined_row_limit; ulong multi_range_count; - ulong myisam_repair_threads; - ulong myisam_sort_buff_size; - ulong myisam_stats_method; ulong net_buffer_length; ulong net_interactive_timeout; ulong net_read_timeout; @@ -354,23 +356,13 @@ struct system_variables ulong net_write_timeout; ulong optimizer_prune_level; ulong optimizer_search_depth; - /* A bitmap for switching optimizations on/off */ - ulong optimizer_switch; ulong preload_buff_size; ulong profiling_history_size; - ulong query_cache_type; ulong read_buff_size; ulong read_rnd_buff_size; ulong div_precincrement; ulong sortbuff_size; - ulong thread_handling; - ulong tx_isolation; - ulong completion_type; - /* Determines which non-standard SQL behaviour should be enabled */ - ulong sql_mode; ulong max_sp_recursion_depth; - /* check of key presence in updatable view */ - ulong updatable_views_with_limit; ulong default_week_format; ulong max_seeks_for_key; ulong range_alloc_block_size; @@ -380,12 +372,15 @@ struct system_variables ulong trans_prealloc_size; ulong log_warnings; ulong group_concat_max_len; - ulong ndb_autoincrement_prefetch_sz; - ulong ndb_index_stat_cache_entries; - ulong ndb_index_stat_update_freq; - ulong binlog_format; // binlog format for this thd (see enum_binlog_format) + + uint binlog_format; ///< binlog format for this thd (see enum_binlog_format) my_bool binlog_direct_non_trans_update; - /* + uint completion_type; + uint query_cache_type; + uint tx_isolation; + uint updatable_views_with_limit; + uint max_user_connections; + /** In slave thread we need to know in behalf of which thread the query is being run to replicate temp tables properly */ @@ -393,22 +388,13 @@ struct system_variables my_bool low_priority_updates; my_bool new_mode; - /* - compatibility option: - - index usage hints (USE INDEX without a FOR clause) behave as in 5.0 - */ - my_bool old_mode; my_bool query_cache_wlock_invalidate; my_bool engine_condition_pushdown; my_bool keep_files_on_create; - my_bool ndb_force_send; - my_bool ndb_use_copying_alter_table; - my_bool ndb_use_exact_count; - my_bool ndb_use_transactions; - my_bool ndb_index_stat_enable; my_bool old_alter_table; my_bool old_passwords; + my_bool big_tables; plugin_ref table_plugin; @@ -429,12 +415,10 @@ struct system_variables Time_zone *time_zone; - /* DATE, DATETIME and MYSQL_TIME formats */ - DATE_TIME_FORMAT *date_format; - DATE_TIME_FORMAT *datetime_format; - DATE_TIME_FORMAT *time_format; my_bool sysdate_is_now; -}; + + double long_query_time_double; +} SV; /* per thread status variables */ @@ -795,7 +779,7 @@ typedef struct st_xid_state { uint rm_error; } XID_STATE; -extern pthread_mutex_t LOCK_xid_cache; +extern mysql_mutex_t LOCK_xid_cache; extern HASH xid_cache; bool xid_cache_init(void); void xid_cache_free(void); @@ -1016,7 +1000,7 @@ public: class Sub_statement_state { public: - ulonglong options; + ulonglong option_bits; ulonglong first_successful_insert_id_in_prev_stmt; ulonglong first_successful_insert_id_in_cur_stmt, insert_id_for_cur_row; Discrete_interval auto_inc_interval_for_cur_row; @@ -1204,6 +1188,7 @@ public: /* Used to execute base64 coded binlog events in MySQL server */ Relay_log_info* rli_fake; + void reset_for_next_command(); /* Constant for THD::where initialization in the beginning of every query. @@ -1241,7 +1226,6 @@ public: HASH user_vars; // hash for user variables String packet; // dynamic buffer for network I/O String convert_buffer; // buffer for charset conversions - struct sockaddr_in remote; // client socket address struct rand_struct rand; // used for authentication struct system_variables variables; // Changeable local variables struct system_status_var status_var; // Per thread statistic vars @@ -1257,7 +1241,7 @@ public: - thd->mysys_var (used by KILL statement and shutdown). Is locked when THD is deleted. */ - pthread_mutex_t LOCK_thd_data; + mysql_mutex_t LOCK_thd_data; /* all prepared statements and cursors of this connection */ Statement_map stmt_map; @@ -1309,7 +1293,6 @@ public: */ const char *where; - double tmp_double_value; /* Used in set_var.cc */ ulong client_capabilities; /* What the client supports */ ulong max_client_packet_length; @@ -1380,32 +1363,81 @@ public: size_t needed, bool is_transactional, RowsEventT* hint); - Rows_log_event* binlog_get_pending_rows_event() const; - void binlog_set_pending_rows_event(Rows_log_event* ev); - int binlog_flush_pending_rows_event(bool stmt_end); - int binlog_remove_pending_rows_event(bool clear_maps); + Rows_log_event* binlog_get_pending_rows_event(bool is_transactional) const; + void binlog_set_pending_rows_event(Rows_log_event* ev, bool is_transactional); + inline int binlog_flush_pending_rows_event(bool stmt_end) + { + return (binlog_flush_pending_rows_event(stmt_end, FALSE) || + binlog_flush_pending_rows_event(stmt_end, TRUE)); + } + int binlog_flush_pending_rows_event(bool stmt_end, bool is_transactional); + int binlog_remove_pending_rows_event(bool clear_maps, bool is_transactional); + + /** + Determine the binlog format of the current statement. + + @retval 0 if the current statement will be logged in statement + format. + @retval nonzero if the current statement will be logged in row + format. + */ + int is_current_stmt_binlog_format_row() const { + DBUG_ASSERT(current_stmt_binlog_format == BINLOG_FORMAT_STMT || + current_stmt_binlog_format == BINLOG_FORMAT_ROW); + return current_stmt_binlog_format == BINLOG_FORMAT_ROW; + } private: + /** + Indicates the format in which the current statement will be + logged. This can only be set from @c decide_logging_format(). + */ + enum_binlog_format current_stmt_binlog_format; + + /** + Bit field for the state of binlog warnings. + + There are two groups of bits: + + - The first Lex::BINLOG_STMT_UNSAFE_COUNT bits list all types of + unsafeness that the current statement has. + + - The following Lex::BINLOG_STMT_UNSAFE_COUNT bits list all types + of unsafeness that the current statement has issued warnings + for. + + Hence, this variable must be big enough to hold + 2*Lex::BINLOG_STMT_UNSAFE_COUNT bits. This is asserted in @c + issue_unsafe_warnings(). + + The first and second groups of bits are set by @c + decide_logging_format() when it detects that a warning should be + issued. The third group of bits is set from @c binlog_query() + when a warning is issued. All bits are cleared at the end of the + top-level statement. + + This must be a member of THD and not of LEX, because warnings are + detected and issued in different places (@c + decide_logging_format() and @c binlog_query(), respectively). + Between these calls, the THD->lex object may change; e.g., if a + stored routine is invoked. Only THD persists between the calls. + */ + uint32 binlog_unsafe_warning_flags; + + void issue_unsafe_warnings(); + /* Number of outstanding table maps, i.e., table maps in the transaction cache. */ uint binlog_table_maps; - - enum enum_binlog_flag { - BINLOG_FLAG_UNSAFE_STMT_PRINTED, - BINLOG_FLAG_COUNT - }; - - /** - Flags with per-thread information regarding the status of the - binary log. - */ - uint32 binlog_flags; public: uint get_binlog_table_maps() const { return binlog_table_maps; } + void clear_binlog_table_maps() { + binlog_table_maps= 0; + } #endif /* MYSQL_CLIENT */ public: @@ -1437,19 +1469,13 @@ public: */ if (!xid_state.rm_error) xid_state.xid.null(); -#ifdef USING_TRANSACTIONS free_root(&mem_root,MYF(MY_KEEP_PREALLOC)); -#endif } st_transactions() { -#ifdef USING_TRANSACTIONS bzero((char*)this, sizeof(*this)); xid_state.xid.null(); init_sql_alloc(&mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0); -#else - xid_state.xa_state= XA_NOTR; -#endif } } transaction; Field *dup_field; @@ -1626,7 +1652,6 @@ public: } ulonglong limit_found_rows; - ulonglong options; /* Bitmap of states */ longlong row_count_func; /* For the ROW_COUNT() function */ ha_rows cuted_fields; @@ -1813,6 +1838,20 @@ public: partition_info *work_part_info; #endif +#ifndef EMBEDDED_LIBRARY + /** + Array of active audit plugins which have been used by this THD. + This list is later iterated to invoke release_thd() on those + plugins. + */ + DYNAMIC_ARRAY audit_class_plugins; + /** + Array of bits indicating which audit classes have already been + added to the list of audit plugins which are currently in use. + */ + unsigned long audit_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE]; +#endif + #if defined(ENABLED_DEBUG_SYNC) /* Debug Sync facility. See debug_sync.cc. */ struct st_debug_sync_control *debug_sync_control; @@ -1839,15 +1878,15 @@ public: #ifdef SIGNAL_WITH_VIO_CLOSE inline void set_active_vio(Vio* vio) { - pthread_mutex_lock(&LOCK_thd_data); + mysql_mutex_lock(&LOCK_thd_data); active_vio = vio; - pthread_mutex_unlock(&LOCK_thd_data); + mysql_mutex_unlock(&LOCK_thd_data); } inline void clear_active_vio() { - pthread_mutex_lock(&LOCK_thd_data); + mysql_mutex_lock(&LOCK_thd_data); active_vio = 0; - pthread_mutex_unlock(&LOCK_thd_data); + mysql_mutex_unlock(&LOCK_thd_data); } void close_active_vio(); #endif @@ -1855,27 +1894,18 @@ public: #ifndef MYSQL_CLIENT enum enum_binlog_query_type { - /* - The query can be logged row-based or statement-based - */ + /* The query can be logged in row format or in statement format. */ ROW_QUERY_TYPE, - /* - The query has to be logged statement-based - */ + /* The query has to be logged in statement format. */ STMT_QUERY_TYPE, - /* - The query represents a change to a table in the "mysql" - database and is currently mapped to ROW_QUERY_TYPE. - */ - MYSQL_QUERY_TYPE, QUERY_TYPE_COUNT }; int binlog_query(enum_binlog_query_type qtype, - char const *query, ulong query_len, - bool is_trans, bool suppress_use, + char const *query, ulong query_len, bool is_trans, + bool direct, bool suppress_use, int errcode); #endif @@ -1884,11 +1914,11 @@ public: enter_cond(); this mutex is then released by exit_cond(). Usage must be: lock mutex; enter_cond(); your code; exit_cond(). */ - inline const char* enter_cond(pthread_cond_t *cond, pthread_mutex_t* mutex, - const char* msg) + inline const char* enter_cond(mysql_cond_t *cond, mysql_mutex_t* mutex, + const char* msg) { const char* old_msg = proc_info; - safe_mutex_assert_owner(mutex); + mysql_mutex_assert_owner(mutex); mysys_var->current_mutex = mutex; mysys_var->current_cond = cond; proc_info = msg; @@ -1902,12 +1932,12 @@ public: locked (if that would not be the case, you'll get a deadlock if someone does a THD::awake() on you). */ - pthread_mutex_unlock(mysys_var->current_mutex); - pthread_mutex_lock(&mysys_var->mutex); + mysql_mutex_unlock(mysys_var->current_mutex); + mysql_mutex_lock(&mysys_var->mutex); mysys_var->current_mutex = 0; mysys_var->current_cond = 0; proc_info = old_msg; - pthread_mutex_unlock(&mysys_var->mutex); + mysql_mutex_unlock(&mysys_var->mutex); return; } inline time_t query_start() { query_start_used=1; return start_time; } @@ -1935,11 +1965,22 @@ public: } inline bool active_transaction() { -#ifdef USING_TRANSACTIONS return server_status & SERVER_STATUS_IN_TRANS; -#else - return 0; -#endif + } + /** + Returns TRUE if session is in a multi-statement transaction mode. + + OPTION_NOT_AUTOCOMMIT: When autocommit is off, a multi-statement + transaction is implicitly started on the first statement after a + previous transaction has been ended. + + OPTION_BEGIN: Regardless of the autocommit status, a multi-statement + transaction can be explicitly started with the statements "START + TRANSACTION", "BEGIN [WORK]", "[COMMIT | ROLLBACK] AND CHAIN", etc. + */ + inline bool in_multi_stmt_transaction() + { + return variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN); } inline bool fill_derived_tables() { @@ -1985,9 +2026,15 @@ public: DBUG_VOID_RETURN; } inline bool vio_ok() const { return net.vio != 0; } + /** Return FALSE if connection to client is broken. */ + bool is_connected() + { + return vio_ok() ? vio_is_connected(net.vio) : FALSE; + } #else void clear_error(); - inline bool vio_ok() const { return true; } + inline bool vio_ok() const { return TRUE; } + inline bool is_connected() { return TRUE; } #endif /** Mark the current error as fatal. Warning: this does not @@ -1996,6 +2043,7 @@ public: */ inline void fatal_error() { + DBUG_ASSERT(main_da.is_error()); is_fatal_error= 1; DBUG_PRINT("error",("Fatal error set")); } @@ -2078,31 +2126,51 @@ public: void set_n_backup_active_arena(Query_arena *set, Query_arena *backup); void restore_active_arena(Query_arena *set, Query_arena *backup); - inline void set_current_stmt_binlog_row_based_if_mixed() + /* + @todo Make these methods private or remove them completely. Only + decide_logging_format should call them. /Sven + */ + inline void set_current_stmt_binlog_format_row_if_mixed() { + DBUG_ENTER("set_current_stmt_binlog_format_row_if_mixed"); + /* + This should only be called from decide_logging_format. + + @todo Once we have ensured this, uncomment the following + statement, remove the big comment below that, and remove the + in_sub_stmt==0 condition from the following 'if'. + */ + /* DBUG_ASSERT(in_sub_stmt == 0); */ /* If in a stored/function trigger, the caller should already have done the change. We test in_sub_stmt to prevent introducing bugs where people wouldn't ensure that, and would switch to row-based mode in the middle of executing a stored function/trigger (which is too late, see also - reset_current_stmt_binlog_row_based()); this condition will make their + reset_current_stmt_binlog_format_row()); this condition will make their tests fail and so force them to propagate the lex->binlog_row_based_if_mixed upwards to the caller. */ if ((variables.binlog_format == BINLOG_FORMAT_MIXED) && (in_sub_stmt == 0)) - current_stmt_binlog_row_based= TRUE; + set_current_stmt_binlog_format_row(); + + DBUG_VOID_RETURN; } - inline void set_current_stmt_binlog_row_based() + inline void set_current_stmt_binlog_format_row() { - current_stmt_binlog_row_based= TRUE; + DBUG_ENTER("set_current_stmt_binlog_format_row"); + current_stmt_binlog_format= BINLOG_FORMAT_ROW; + DBUG_VOID_RETURN; } - inline void clear_current_stmt_binlog_row_based() + inline void clear_current_stmt_binlog_format_row() { - current_stmt_binlog_row_based= FALSE; + DBUG_ENTER("clear_current_stmt_binlog_format_row"); + current_stmt_binlog_format= BINLOG_FORMAT_STMT; + DBUG_VOID_RETURN; } - inline void reset_current_stmt_binlog_row_based() + inline void reset_current_stmt_binlog_format_row() { + DBUG_ENTER("reset_current_stmt_binlog_format_row"); /* If there are temporary tables, don't reset back to statement-based. Indeed it could be that: @@ -2117,19 +2185,19 @@ public: or trigger is decided when it starts executing, depending for example on the caller (for a stored function: if caller is SELECT or INSERT/UPDATE/DELETE...). - - Don't reset binlog format for NDB binlog injector thread. */ DBUG_PRINT("debug", ("temporary_tables: %s, in_sub_stmt: %s, system_thread: %s", YESNO(temporary_tables), YESNO(in_sub_stmt), show_system_thread(system_thread))); - if ((temporary_tables == NULL) && (in_sub_stmt == 0) && - (system_thread != SYSTEM_THREAD_NDBCLUSTER_BINLOG)) + if ((temporary_tables == NULL) && (in_sub_stmt == 0)) { - current_stmt_binlog_row_based= - test(variables.binlog_format == BINLOG_FORMAT_ROW); + if (variables.binlog_format == BINLOG_FORMAT_ROW) + set_current_stmt_binlog_format_row(); + else + clear_current_stmt_binlog_format_row(); } + DBUG_VOID_RETURN; } /** @@ -2161,7 +2229,10 @@ public: else { x_free(db); - db= new_db ? my_strndup(new_db, new_db_len, MYF(MY_WME)) : NULL; + if (new_db) + db= my_strndup(new_db, new_db_len, MYF(MY_WME | ME_FATALERROR)); + else + db= NULL; } db_length= db ? new_db_len : 0; return new_db && !db; @@ -2317,11 +2388,16 @@ public: virtual void set_statement(Statement *stmt); /** - Assign a new value to thd->query. + Assign a new value to thd->query and thd->query_id. Protected with LOCK_thd_data mutex. */ void set_query(char *query_arg, uint32 query_length_arg); + void set_query_and_id(char *query_arg, uint32 query_length_arg, + query_id_t new_query_id); + void set_query_id(query_id_t new_query_id); + int decide_logging_format(TABLE_LIST *tables); private: + /** The current internal error handler for this thread, or NULL. */ Internal_error_handler *m_internal_handler; /** @@ -2364,10 +2440,10 @@ my_eof(THD *thd) } #define tmp_disable_binlog(A) \ - {ulonglong tmp_disable_binlog__save_options= (A)->options; \ - (A)->options&= ~OPTION_BIN_LOG + {ulonglong tmp_disable_binlog__save_options= (A)->variables.option_bits; \ + (A)->variables.option_bits&= ~OPTION_BIN_LOG -#define reenable_binlog(A) (A)->options= tmp_disable_binlog__save_options;} +#define reenable_binlog(A) (A)->variables.option_bits= tmp_disable_binlog__save_options;} /* @@ -2403,7 +2479,6 @@ class select_result :public Sql_alloc { protected: THD *thd; SELECT_LEX_UNIT *unit; - uint nest_level; public: select_result(); virtual ~select_result() {}; @@ -2440,12 +2515,6 @@ public: */ virtual void cleanup(); void set_thd(THD *thd_arg) { thd= thd_arg; } - /** - The nest level, if supported. - @return - -1 if nest level is undefined, otherwise a positive integer. - */ - int get_nest_level() { return nest_level; } #ifdef EMBEDDED_LIBRARY virtual void begin_dataset() {} #else @@ -2540,14 +2609,6 @@ class select_export :public select_to_file { CHARSET_INFO *write_cs; // output charset public: select_export(sql_exchange *ex) :select_to_file(ex) {} - /** - Creates a select_export to represent INTO OUTFILE <filename> with a - defined level of subquery nesting. - */ - select_export(sql_exchange *ex, uint nest_level_arg) :select_to_file(ex) - { - nest_level= nest_level_arg; - } ~select_export(); int prepare(List<Item> &list, SELECT_LEX_UNIT *u); bool send_data(List<Item> &items); @@ -2557,15 +2618,6 @@ public: class select_dump :public select_to_file { public: select_dump(sql_exchange *ex) :select_to_file(ex) {} - /** - Creates a select_export to represent INTO DUMPFILE <filename> with a - defined level of subquery nesting. - */ - select_dump(sql_exchange *ex, uint nest_level_arg) : - select_to_file(ex) - { - nest_level= nest_level_arg; - } int prepare(List<Item> &list, SELECT_LEX_UNIT *u); bool send_data(List<Item> &items); }; @@ -3036,16 +3088,6 @@ class select_dumpvar :public select_result_interceptor { public: List<my_var> var_list; select_dumpvar() { var_list.empty(); row_count= 0;} - /** - Creates a select_dumpvar to represent INTO <variable> with a defined - level of subquery nesting. - */ - select_dumpvar(uint nest_level_arg) - { - var_list.empty(); - row_count= 0; - nest_level= nest_level_arg; - } ~select_dumpvar() {} int prepare(List<Item> &list, SELECT_LEX_UNIT *u); bool send_data(List<Item> &items); diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 24150aba1e0..90b255b0843 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2007 MySQL AB +/* Copyright (C) 2007 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,6 +19,7 @@ */ #include "mysql_priv.h" +#include "sql_audit.h" #include "probes_mysql.h" #ifdef HAVE_OPENSSL @@ -60,7 +61,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, user_len= strlen(user); temp_len= (strmov(strmov(temp_user, user)+1, host) - temp_user)+1; - (void) pthread_mutex_lock(&LOCK_user_conn); + mysql_mutex_lock(&LOCK_user_conn); if (!(uc = (struct user_conn *) my_hash_search(&hash_user_connections, (uchar*) temp_user, temp_len))) { @@ -91,7 +92,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, thd->user_connect=uc; uc->connections++; end: - (void) pthread_mutex_unlock(&LOCK_user_conn); + mysql_mutex_unlock(&LOCK_user_conn); return return_val; } @@ -120,9 +121,10 @@ int check_for_max_user_connections(THD *thd, USER_CONN *uc) int error=0; DBUG_ENTER("check_for_max_user_connections"); - (void) pthread_mutex_lock(&LOCK_user_conn); - if (max_user_connections && !uc->user_resources.user_conn && - max_user_connections < (uint) uc->connections) + mysql_mutex_lock(&LOCK_user_conn); + if (global_system_variables.max_user_connections && + !uc->user_resources.user_conn && + global_system_variables.max_user_connections < (uint) uc->connections) { my_error(ER_TOO_MANY_USER_CONNECTIONS, MYF(0), uc->user); error=1; @@ -160,7 +162,7 @@ end: */ thd->user_connect= NULL; } - (void) pthread_mutex_unlock(&LOCK_user_conn); + mysql_mutex_unlock(&LOCK_user_conn); DBUG_RETURN(error); } @@ -186,14 +188,14 @@ end: void decrease_user_connections(USER_CONN *uc) { DBUG_ENTER("decrease_user_connections"); - (void) pthread_mutex_lock(&LOCK_user_conn); + mysql_mutex_lock(&LOCK_user_conn); DBUG_ASSERT(uc->connections); if (!--uc->connections && !mqh_used) { /* Last connection for user; Delete it */ (void) my_hash_delete(&hash_user_connections,(uchar*) uc); } - (void) pthread_mutex_unlock(&LOCK_user_conn); + mysql_mutex_unlock(&LOCK_user_conn); DBUG_VOID_RETURN; } @@ -241,7 +243,7 @@ bool check_mqh(THD *thd, uint check_command) DBUG_ENTER("check_mqh"); DBUG_ASSERT(uc != 0); - (void) pthread_mutex_lock(&LOCK_user_conn); + mysql_mutex_lock(&LOCK_user_conn); time_out_user_resource_limits(thd, uc); @@ -268,7 +270,7 @@ bool check_mqh(THD *thd, uint check_command) } } end: - (void) pthread_mutex_unlock(&LOCK_user_conn); + mysql_mutex_unlock(&LOCK_user_conn); DBUG_RETURN(error); } @@ -329,9 +331,9 @@ check_user(THD *thd, enum enum_server_command command, #else my_bool opt_secure_auth_local; - pthread_mutex_lock(&LOCK_global_system_variables); + mysql_mutex_lock(&LOCK_global_system_variables); opt_secure_auth_local= opt_secure_auth; - pthread_mutex_unlock(&LOCK_global_system_variables); + mysql_mutex_unlock(&LOCK_global_system_variables); /* If the server is running in secure auth mode, short scrambles are @@ -377,7 +379,8 @@ check_user(THD *thd, enum enum_server_command command, if (send_old_password_request(thd) || my_net_read(net) != SCRAMBLE_LENGTH_323 + 1) { - inc_host_errors(&thd->remote.sin_addr); + inc_host_errors(thd->main_security_ctx.ip); + my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); DBUG_RETURN(1); } @@ -407,10 +410,10 @@ check_user(THD *thd, enum enum_server_command command, if (check_count) { - pthread_mutex_lock(&LOCK_connection_count); + mysql_mutex_lock(&LOCK_connection_count); bool count_ok= connection_count <= max_connections || (thd->main_security_ctx.master_access & SUPER_ACL); - VOID(pthread_mutex_unlock(&LOCK_connection_count)); + mysql_mutex_unlock(&LOCK_connection_count); if (!count_ok) { // too many connections @@ -442,7 +445,7 @@ check_user(THD *thd, enum enum_server_command command, /* Don't allow user to connect if he has done too many queries */ if ((ur.questions || ur.updates || ur.conn_per_hour || ur.user_conn || - max_user_connections) && + global_system_variables.max_user_connections) && get_or_create_user_conn(thd, (opt_old_style_user_limits ? thd->main_security_ctx.user : thd->main_security_ctx.priv_user), @@ -456,7 +459,7 @@ check_user(THD *thd, enum enum_server_command command, if (thd->user_connect && (thd->user_connect->user_resources.conn_per_hour || thd->user_connect->user_resources.user_conn || - max_user_connections) && + global_system_variables.max_user_connections) && check_for_max_user_connections(thd, thd->user_connect)) { /* The error is set in check_for_max_user_connections(). */ @@ -498,9 +501,9 @@ check_user(THD *thd, enum enum_server_command command, thd->main_security_ctx.host_or_ip, passwd_len ? ER(ER_YES) : ER(ER_NO)); /* - log access denied messages to the error log when log-warnings = 2 + Log access denied messages to the error log when log-warnings = 2 so that the overhead of the general query log is not required to track - failed connections + failed connections. */ if (global_system_variables.log_warnings > 1) { @@ -555,7 +558,7 @@ void free_max_user_conn(void) void reset_mqh(LEX_USER *lu, bool get_them= 0) { #ifndef NO_EMBEDDED_ACCESS_CHECKS - (void) pthread_mutex_lock(&LOCK_user_conn); + mysql_mutex_lock(&LOCK_user_conn); if (lu) // for GRANT { USER_CONN *uc; @@ -589,7 +592,7 @@ void reset_mqh(LEX_USER *lu, bool get_them= 0) uc->conn_per_hour=0; } } - (void) pthread_mutex_unlock(&LOCK_user_conn); + mysql_mutex_unlock(&LOCK_user_conn); #endif /* NO_EMBEDDED_ACCESS_CHECKS */ } @@ -666,9 +669,9 @@ static int check_connection(THD *thd) if (!thd->main_security_ctx.host) // If TCP/IP connection { - char ip[30]; + char ip[NI_MAXHOST]; - if (vio_peer_addr(net->vio, ip, &thd->peer_port)) + if (vio_peer_addr(net->vio, ip, &thd->peer_port, NI_MAXHOST)) { my_error(ER_BAD_HOST_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); return 1; @@ -676,12 +679,15 @@ static int check_connection(THD *thd) if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(MY_WME)))) return 1; /* The error is set by my_strdup(). */ thd->main_security_ctx.host_or_ip= thd->main_security_ctx.ip; - vio_in_addr(net->vio,&thd->remote.sin_addr); if (!(specialflag & SPECIAL_NO_RESOLVE)) { - vio_in_addr(net->vio,&thd->remote.sin_addr); - thd->main_security_ctx.host= - ip_to_hostname(&thd->remote.sin_addr, &connect_errors); + if (ip_to_hostname(&net->vio->remote, thd->main_security_ctx.ip, + &thd->main_security_ctx.host, &connect_errors)) + { + my_error(ER_BAD_HOST_ERROR, MYF(0), ip); + return 1; + } + /* Cut very long hostnames to avoid possible overflows */ if (thd->main_security_ctx.host) { @@ -714,7 +720,7 @@ static int check_connection(THD *thd) thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host; thd->main_security_ctx.ip= 0; /* Reset sin_addr */ - bzero((char*) &thd->remote, sizeof(thd->remote)); + bzero((char*) &net->vio->remote, sizeof(net->vio->remote)); } vio_keepalive(net->vio, TRUE); @@ -769,7 +775,8 @@ static int check_connection(THD *thd) (pkt_len= my_net_read(net)) == packet_error || pkt_len < MIN_HANDSHAKE_SIZE) { - inc_host_errors(&thd->remote.sin_addr); + inc_host_errors(thd->main_security_ctx.ip); + my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); return 1; @@ -779,7 +786,7 @@ static int check_connection(THD *thd) #include "_cust_sql_parse.h" #endif if (connect_errors) - reset_host_errors(&thd->remote.sin_addr); + reset_host_errors(thd->main_security_ctx.ip); if (thd->packet.alloc(thd->variables.net_buffer_length)) return 1; /* The error is set by alloc(). */ @@ -813,7 +820,7 @@ static int check_connection(THD *thd) /* Do the SSL layering. */ if (!ssl_acceptor_fd) { - inc_host_errors(&thd->remote.sin_addr); + inc_host_errors(thd->main_security_ctx.ip); my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); return 1; } @@ -821,7 +828,8 @@ static int check_connection(THD *thd) if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout)) { DBUG_PRINT("error", ("Failed to accept new SSL connection")); - inc_host_errors(&thd->remote.sin_addr); + inc_host_errors(thd->main_security_ctx.ip); + my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); return 1; } @@ -831,7 +839,8 @@ static int check_connection(THD *thd) { DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)", pkt_len)); - inc_host_errors(&thd->remote.sin_addr); + inc_host_errors(thd->main_security_ctx.ip); + my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); return 1; } @@ -840,7 +849,8 @@ static int check_connection(THD *thd) if (end >= (char*) net->read_pos+ pkt_len +2) { - inc_host_errors(&thd->remote.sin_addr); + inc_host_errors(thd->main_security_ctx.ip); + my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); return 1; } @@ -878,7 +888,8 @@ static int check_connection(THD *thd) if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len) { - inc_host_errors(&thd->remote.sin_addr); + inc_host_errors(thd->main_security_ctx.ip); + my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip); return 1; } @@ -1043,8 +1054,6 @@ static void prepare_new_connection_state(THD* thd) netware_reg_user(sctx->ip, sctx->user, "MySQL"); #endif - if (thd->variables.max_join_size == HA_POS_ERROR) - thd->options |= OPTION_BIG_SELECTS; if (thd->client_capabilities & CLIENT_COMPRESS) thd->net.compress=1; // Use compression @@ -1059,9 +1068,9 @@ static void prepare_new_connection_state(THD* thd) thd->set_time(); thd->init_for_queries(); - if (sys_init_connect.value_length && !(sctx->master_access & SUPER_ACL)) + if (opt_init_connect.length && !(sctx->master_access & SUPER_ACL)) { - execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect); + execute_init_command(thd, &opt_init_connect, &LOCK_sys_init_connect); if (thd->is_error()) { thd->killed= THD::KILL_CONNECTION; @@ -1099,6 +1108,16 @@ pthread_handler_t handle_one_connection(void *arg) { THD *thd= (THD*) arg; + mysql_thread_set_psi_id(thd->thread_id); + + do_handle_one_connection(thd); + return 0; +} + +void do_handle_one_connection(THD *thd_arg) +{ + THD *thd= thd_arg; + thd->thr_create_utime= my_micro_time(); if (thread_scheduler.init_new_connection_thread()) @@ -1106,7 +1125,7 @@ pthread_handler_t handle_one_connection(void *arg) close_connection(thd, ER_OUT_OF_RESOURCES, 1); statistic_increment(aborted_connects,&LOCK_status); thread_scheduler.end_thread(thd,0); - return 0; + return; } /* @@ -1133,7 +1152,7 @@ pthread_handler_t handle_one_connection(void *arg) */ thd->thread_stack= (char*) &thd; if (setup_connection_thread_globals(thd)) - return 0; + return; for (;;) { @@ -1151,6 +1170,7 @@ pthread_handler_t handle_one_connection(void *arg) while (!net->error && net->vio != 0 && !(thd->killed == THD::KILL_CONNECTION)) { + mysql_audit_release(thd); if (do_command(thd)) break; } @@ -1159,7 +1179,7 @@ pthread_handler_t handle_one_connection(void *arg) end_thread: close_connection(thd, 0, 1); if (thread_scheduler.end_thread(thd,1)) - return 0; // Probably no-threads + return; // Probably no-threads /* If end_thread() returns, we are either running with diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc index ffc3fafe55f..66c4460c1cd 100644 --- a/sql/sql_cursor.cc +++ b/sql/sql_cursor.cc @@ -438,7 +438,7 @@ Sensitive_cursor::fetch(ulong num_rows) thd->derived_tables= derived_tables; thd->open_tables= open_tables; thd->lock= lock; - thd->query_id= query_id; + thd->set_query_id(query_id); thd->change_list= change_list; /* save references to memory allocated during fetch */ thd->set_n_backup_active_arena(this, &backup_arena); @@ -721,7 +721,7 @@ bool Select_materialize::send_result_set_metadata(List<Item> &list, uint flags) { DBUG_ASSERT(table == 0); if (create_result_table(unit->thd, unit->get_unit_column_types(), - FALSE, thd->options | TMP_TABLE_ALL_COLUMNS, "")) + FALSE, thd->variables.option_bits | TMP_TABLE_ALL_COLUMNS, "")) return TRUE; materialized_cursor= new (&table->mem_root) diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 71054c923ca..1be84751581 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -47,7 +47,7 @@ static void mysql_change_db_impl(THD *thd, /* Database lock hash */ HASH lock_db_cache; -pthread_mutex_t LOCK_lock_db; +mysql_mutex_t LOCK_lock_db; int creating_database= 0; // how many database locks are made @@ -103,7 +103,7 @@ static my_bool lock_db_insert(const char *dbname, uint length) my_bool error= 0; DBUG_ENTER("lock_db_insert"); - safe_mutex_assert_owner(&LOCK_lock_db); + mysql_mutex_assert_owner(&LOCK_lock_db); if (!(opt= (my_dblock_t*) my_hash_search(&lock_db_cache, (uchar*) dbname, length))) @@ -138,7 +138,7 @@ end: void lock_db_delete(const char *name, uint length) { my_dblock_t *opt; - safe_mutex_assert_owner(&LOCK_lock_db); + mysql_mutex_assert_owner(&LOCK_lock_db); if ((opt= (my_dblock_t *)my_hash_search(&lock_db_cache, (const uchar*) name, length))) my_hash_delete(&lock_db_cache, (uchar*) opt); @@ -148,7 +148,7 @@ void lock_db_delete(const char *name, uint length) /* Database options hash */ static HASH dboptions; static my_bool dboptions_init= 0; -static rw_lock_t LOCK_dboptions; +static mysql_rwlock_t LOCK_dboptions; /* Structure for database options */ typedef struct my_dbopt_st @@ -181,7 +181,7 @@ uchar* dboptions_get_key(my_dbopt_t *opt, size_t *length, static inline int write_to_binlog(THD *thd, char *query, uint q_len, char *db, uint db_len) { - Query_log_event qinfo(thd, query, q_len, 0, 0, 0); + Query_log_event qinfo(thd, query, q_len, FALSE, TRUE, FALSE, 0); qinfo.db= db; qinfo.db_len= db_len; return mysql_bin_log.write(&qinfo); @@ -199,6 +199,26 @@ void free_dbopt(void *dbopt) my_free((uchar*) dbopt, MYF(0)); } +#ifdef HAVE_PSI_INTERFACE +static PSI_rwlock_key key_rwlock_LOCK_dboptions; + +static PSI_rwlock_info all_database_names_rwlocks[]= +{ + { &key_rwlock_LOCK_dboptions, "LOCK_dboptions", PSI_FLAG_GLOBAL} +}; + +static void init_database_names_psi_keys(void) +{ + const char* category= "sql"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_database_names_rwlocks); + PSI_server->register_rwlock(category, all_database_names_rwlocks, count); +} +#endif /* Initialize database option hash and locked database hash. @@ -216,8 +236,12 @@ void free_dbopt(void *dbopt) bool my_database_names_init(void) { +#ifdef HAVE_PSI_INTERFACE + init_database_names_psi_keys(); +#endif + bool error= 0; - (void) my_rwlock_init(&LOCK_dboptions, NULL); + mysql_rwlock_init(key_rwlock_LOCK_dboptions, &LOCK_dboptions); if (!dboptions_init) { dboptions_init= 1; @@ -246,7 +270,7 @@ void my_database_names_free(void) { dboptions_init= 0; my_hash_free(&dboptions); - (void) rwlock_destroy(&LOCK_dboptions); + mysql_rwlock_destroy(&LOCK_dboptions); my_hash_free(&lock_db_cache); } } @@ -258,13 +282,13 @@ void my_database_names_free(void) void my_dbopt_cleanup(void) { - rw_wrlock(&LOCK_dboptions); + mysql_rwlock_wrlock(&LOCK_dboptions); my_hash_free(&dboptions); my_hash_init(&dboptions, lower_case_table_names ? &my_charset_bin : system_charset_info, 32, 0, 0, (my_hash_get_key) dboptions_get_key, free_dbopt,0); - rw_unlock(&LOCK_dboptions); + mysql_rwlock_unlock(&LOCK_dboptions); } @@ -288,13 +312,13 @@ static my_bool get_dbopt(const char *dbname, HA_CREATE_INFO *create) length= (uint) strlen(dbname); - rw_rdlock(&LOCK_dboptions); + mysql_rwlock_rdlock(&LOCK_dboptions); if ((opt= (my_dbopt_t*) my_hash_search(&dboptions, (uchar*) dbname, length))) { create->default_table_charset= opt->charset; error= 0; } - rw_unlock(&LOCK_dboptions); + mysql_rwlock_unlock(&LOCK_dboptions); return error; } @@ -320,7 +344,7 @@ static my_bool put_dbopt(const char *dbname, HA_CREATE_INFO *create) length= (uint) strlen(dbname); - rw_wrlock(&LOCK_dboptions); + mysql_rwlock_wrlock(&LOCK_dboptions); if (!(opt= (my_dbopt_t*) my_hash_search(&dboptions, (uchar*) dbname, length))) { @@ -349,7 +373,7 @@ static my_bool put_dbopt(const char *dbname, HA_CREATE_INFO *create) opt->charset= create->default_table_charset; end: - rw_unlock(&LOCK_dboptions); + mysql_rwlock_unlock(&LOCK_dboptions); DBUG_RETURN(error); } @@ -361,11 +385,11 @@ end: void del_dbopt(const char *path) { my_dbopt_t *opt; - rw_wrlock(&LOCK_dboptions); + mysql_rwlock_wrlock(&LOCK_dboptions); if ((opt= (my_dbopt_t *)my_hash_search(&dboptions, (const uchar*) path, strlen(path)))) my_hash_delete(&dboptions, (uchar*) opt); - rw_unlock(&LOCK_dboptions); + mysql_rwlock_unlock(&LOCK_dboptions); } @@ -392,7 +416,8 @@ static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) if (put_dbopt(path, create)) return 1; - if ((file=my_create(path, CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0) + if ((file= mysql_file_create(key_file_dbopt, path, CREATE_MODE, + O_RDWR | O_TRUNC, MYF(MY_WME))) >= 0) { ulong length; length= (ulong) (strxnmov(buf, sizeof(buf)-1, "default-character-set=", @@ -401,10 +426,10 @@ static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) create->default_table_charset->name, "\n", NullS) - buf); - /* Error is written by my_write */ - if (!my_write(file,(uchar*) buf, length, MYF(MY_NABP+MY_WME))) + /* Error is written by mysql_file_write */ + if (!mysql_file_write(file, (uchar*) buf, length, MYF(MY_NABP+MY_WME))) error=0; - my_close(file,MYF(0)); + mysql_file_close(file, MYF(0)); } return error; } @@ -441,7 +466,8 @@ bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) DBUG_RETURN(0); /* Otherwise, load options from the .opt file */ - if ((file=my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0) + if ((file= mysql_file_open(key_file_dbopt, + path, O_RDONLY | O_SHARE, MYF(0))) < 0) goto err1; IO_CACHE cache; @@ -499,7 +525,7 @@ bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create) end_io_cache(&cache); err2: - my_close(file,MYF(0)); + mysql_file_close(file, MYF(0)); err1: DBUG_RETURN(error); } @@ -619,7 +645,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, DBUG_ENTER("mysql_create_db"); /* do not create 'information_schema' db */ - if (is_schema_db(db)) + if (is_infoschema_db(db)) { my_error(ER_DB_CREATE_EXISTS, MYF(0), db); DBUG_RETURN(-1); @@ -643,13 +669,13 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, goto exit2; } - VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); + mysql_mutex_lock(&LOCK_mysql_create_db); /* Check directory */ path_len= build_table_filename(path, sizeof(path) - 1, db, "", "", 0); path[path_len-1]= 0; // Remove last '/' from path - if (my_stat(path,&stat_info,MYF(0))) + if (mysql_file_stat(key_file_misc, path, &stat_info, MYF(0))) { if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS)) { @@ -724,7 +750,7 @@ not_silent: if (mysql_bin_log.is_open()) { int errcode= query_error_code(thd, TRUE); - Query_log_event qinfo(thd, query, query_length, 0, + Query_log_event qinfo(thd, query, query_length, FALSE, TRUE, /* suppress_use */ TRUE, errcode); /* @@ -758,7 +784,7 @@ not_silent: } exit: - VOID(pthread_mutex_unlock(&LOCK_mysql_create_db)); + mysql_mutex_unlock(&LOCK_mysql_create_db); start_waiting_global_read_lock(thd); exit2: DBUG_RETURN(error); @@ -789,7 +815,7 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) if ((error=wait_if_global_read_lock(thd,0,1))) goto exit2; - VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); + mysql_mutex_lock(&LOCK_mysql_create_db); /* Recreate db options file: /dbpath/.db.opt @@ -816,10 +842,9 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) if (mysql_bin_log.is_open()) { - thd->clear_error(); - Query_log_event qinfo(thd, thd->query(), thd->query_length(), 0, - /* suppress_use */ TRUE, 0); - + int errcode= query_error_code(thd, TRUE); + Query_log_event qinfo(thd, thd->query(), thd->query_length(), FALSE, TRUE, + /* suppress_use */ TRUE, errcode); /* Write should use the database being created as the "current database" and not the threads current database, which is the @@ -835,7 +860,7 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info) my_ok(thd, result); exit: - VOID(pthread_mutex_unlock(&LOCK_mysql_create_db)); + mysql_mutex_unlock(&LOCK_mysql_create_db); start_waiting_global_read_lock(thd); exit2: DBUG_RETURN(error); @@ -887,7 +912,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) goto exit2; } - VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); + mysql_mutex_lock(&LOCK_mysql_create_db); length= build_table_filename(path, sizeof(path) - 1, db, "", "", 0); strmov(path+length, MY_DB_OPT_FILE); // Append db option file name @@ -909,9 +934,9 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) } else { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); remove_db_from_cache(db); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); Drop_table_error_handler err_handler(thd->get_internal_handler()); thd->push_internal_handler(&err_handler); @@ -968,9 +993,9 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) } if (mysql_bin_log.is_open()) { - thd->clear_error(); - Query_log_event qinfo(thd, query, query_length, 0, - /* suppress_use */ TRUE, 0); + int errcode= query_error_code(thd, TRUE); + Query_log_event qinfo(thd, query, query_length, FALSE, TRUE, + /* suppress_use */ TRUE, errcode); /* Write should use the database being created as the "current database" and not the threads current database, which is the @@ -1046,7 +1071,7 @@ exit: */ if (thd->db && !strcmp(thd->db, db) && error == 0) mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server); - VOID(pthread_mutex_unlock(&LOCK_mysql_create_db)); + mysql_mutex_unlock(&LOCK_mysql_create_db); start_waiting_global_read_lock(thd); exit2: DBUG_RETURN(error); @@ -1159,9 +1184,9 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, goto err; table_list->db= (char*) (table_list+1); table_list->table_name= strmov(table_list->db, db) + 1; - VOID(filename_to_tablename(file->name, table_list->table_name, + (void) filename_to_tablename(file->name, table_list->table_name, MYSQL50_TABLE_NAME_PREFIX_LENGTH + - strlen(file->name) + 1)); + strlen(file->name) + 1); table_list->alias= table_list->table_name; // If lower_case_table_names=2 table_list->internal_tmp_table= is_prefix(file->name, tmp_file_prefix); /* Link into list */ @@ -1172,7 +1197,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db, else { strxmov(filePath, org_path, "/", file->name, NullS); - if (my_delete_with_symlink(filePath,MYF(MY_WME))) + if (mysql_file_delete_with_symlink(key_file_misc, filePath, MYF(MY_WME))) { goto err; } @@ -1250,7 +1275,7 @@ static my_bool rm_dir_w_symlink(const char *org_path, my_bool send_error) DBUG_RETURN(1); if (!error) { - if (my_delete(path, MYF(send_error ? MY_WME : 0))) + if (mysql_file_delete(key_file_misc, path, MYF(send_error ? MY_WME : 0))) { DBUG_RETURN(send_error); } @@ -1327,7 +1352,7 @@ long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, const char *org_path) continue; } strxmov(filePath, org_path, "/", file->name, NullS); - if (my_delete_with_symlink(filePath,MYF(MY_WME))) + if (mysql_file_delete_with_symlink(key_file_misc, filePath, MYF(MY_WME))) { goto err; } @@ -1575,7 +1600,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch) } } - if (is_schema_db(new_db_name->str, new_db_name->length)) + if (is_infoschema_db(new_db_name->str, new_db_name->length)) { /* Switch the current database to INFORMATION_SCHEMA. */ @@ -1733,18 +1758,18 @@ static int lock_databases(THD *thd, const char *db1, uint length1, const char *db2, uint length2) { - pthread_mutex_lock(&LOCK_lock_db); + mysql_mutex_lock(&LOCK_lock_db); while (!thd->killed && (my_hash_search(&lock_db_cache,(uchar*) db1, length1) || my_hash_search(&lock_db_cache,(uchar*) db2, length2))) { wait_for_condition(thd, &LOCK_lock_db, &COND_refresh); - pthread_mutex_lock(&LOCK_lock_db); + mysql_mutex_lock(&LOCK_lock_db); } if (thd->killed) { - pthread_mutex_unlock(&LOCK_lock_db); + mysql_mutex_unlock(&LOCK_lock_db); return 1; } @@ -1761,7 +1786,7 @@ lock_databases(THD *thd, const char *db1, uint length1, while (!thd->killed && creating_table) { wait_for_condition(thd, &LOCK_lock_db, &COND_refresh); - pthread_mutex_lock(&LOCK_lock_db); + mysql_mutex_lock(&LOCK_lock_db); } if (thd->killed) @@ -1769,8 +1794,8 @@ lock_databases(THD *thd, const char *db1, uint length1, lock_db_delete(db1, length1); lock_db_delete(db2, length2); creating_database--; - pthread_mutex_unlock(&LOCK_lock_db); - pthread_cond_signal(&COND_refresh); + mysql_mutex_unlock(&LOCK_lock_db); + mysql_cond_signal(&COND_refresh); return(1); } @@ -1778,7 +1803,7 @@ lock_databases(THD *thd, const char *db1, uint length1, We can unlock now as the hash will protect against anyone creating a table in the databases we are using */ - pthread_mutex_unlock(&LOCK_lock_db); + mysql_mutex_unlock(&LOCK_lock_db); return 0; } @@ -1907,7 +1932,7 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db) */ build_table_filename(path, sizeof(path)-1, new_db.str,"",MY_DB_OPT_FILE, 0); - my_delete(path, MYF(MY_WME)); + mysql_file_delete(key_file_dbopt, path, MYF(MY_WME)); length= build_table_filename(path, sizeof(path)-1, new_db.str, "", "", 0); if (length && path[length-1] == FN_LIBCHAR) path[length-1]=0; // remove ending '\' @@ -1963,7 +1988,7 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db) old_db->str, "", file->name, 0); build_table_filename(newname, sizeof(newname)-1, new_db.str, "", file->name, 0); - my_rename(oldname, newname, MYF(MY_WME)); + mysql_file_rename(key_file_misc, oldname, newname, MYF(MY_WME)); } my_dirend(dirp); } @@ -1981,7 +2006,7 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db) { int errcode= query_error_code(thd, TRUE); Query_log_event qinfo(thd, thd->query(), thd->query_length(), - 0, TRUE, errcode); + FALSE, TRUE, TRUE, errcode); thd->clear_error(); error|= mysql_bin_log.write(&qinfo); } @@ -1991,14 +2016,14 @@ bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db) error|= mysql_change_db(thd, & new_db, FALSE); exit: - pthread_mutex_lock(&LOCK_lock_db); + mysql_mutex_lock(&LOCK_lock_db); /* Remove the databases from db lock cache */ lock_db_delete(old_db->str, old_db->length); lock_db_delete(new_db.str, new_db.length); creating_database--; /* Signal waiting CREATE TABLE's to continue */ - pthread_cond_signal(&COND_refresh); - pthread_mutex_unlock(&LOCK_lock_db); + mysql_cond_signal(&COND_refresh); + mysql_mutex_unlock(&LOCK_lock_db); DBUG_RETURN(error); } diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index c78a4dc705e..1d1f673d126 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -92,7 +92,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, } const_cond= (!conds || conds->const_item()); - safe_update=test(thd->options & OPTION_SAFE_UPDATES); + safe_update=test(thd->variables.option_bits & OPTION_SAFE_UPDATES); if (safe_update && const_cond) { my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE, @@ -131,7 +131,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, if (!using_limit && const_cond_result && !(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) && (thd->lex->sql_command == SQLCOM_TRUNCATE || - (!thd->current_stmt_binlog_row_based && + (!thd->is_current_stmt_binlog_format_row() && !(table->triggers && table->triggers->has_delete_triggers())))) { /* Update the table->file->stats.records number */ @@ -385,7 +385,8 @@ cleanup: transactional_table= table->file->has_transactions(); if (!transactional_table && deleted > 0) - thd->transaction.stmt.modified_non_trans_table= TRUE; + thd->transaction.stmt.modified_non_trans_table= + thd->transaction.all.modified_non_trans_table= TRUE; /* See similar binlogging code in sql_update.cc, for comments */ if ((error < 0) || thd->transaction.stmt.modified_non_trans_table) @@ -414,15 +415,13 @@ cleanup: */ int log_result= thd->binlog_query(query_type, thd->query(), thd->query_length(), - is_trans, FALSE, errcode); + is_trans, FALSE, FALSE, errcode); if (log_result) { error=1; } } - if (thd->transaction.stmt.modified_non_trans_table) - thd->transaction.all.modified_non_trans_table= TRUE; } DBUG_ASSERT(transactional_table || !deleted || thd->transaction.stmt.modified_non_trans_table); free_underlaid_joins(thd, select_lex); @@ -461,19 +460,6 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) DBUG_ENTER("mysql_prepare_delete"); List<Item> all_fields; - /* - Statement-based replication of DELETE ... LIMIT is not safe as order of - rows is not defined, so in mixed mode we go to row-based. - - Note that we may consider a statement as safe if ORDER BY primary_key - is present. However it may confuse users to see very similiar statements - replicated differently. - */ - if (thd->lex->current_select->select_limit) - { - thd->lex->set_stmt_unsafe(); - thd->set_current_stmt_binlog_row_based_if_mixed(); - } thd->lex->allow_sum_func= 0; if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context, &thd->lex->select_lex.top_join_list, @@ -631,7 +617,7 @@ multi_delete::initialize_tables(JOIN *join) Unique **tempfiles_ptr; DBUG_ENTER("initialize_tables"); - if ((thd->options & OPTION_SAFE_UPDATES) && error_if_full_join(join)) + if ((thd->variables.option_bits & OPTION_SAFE_UPDATES) && error_if_full_join(join)) DBUG_RETURN(1); table_map tables_to_delete_from=0; @@ -822,6 +808,9 @@ void multi_delete::abort() if (deleted) query_cache_invalidate3(thd, delete_tables, 1); + if (thd->transaction.stmt.modified_non_trans_table) + thd->transaction.all.modified_non_trans_table= TRUE; + /* If rows from the first table only has been deleted and it is transactional, just do rollback. @@ -852,10 +841,9 @@ void multi_delete::abort() int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); /* possible error of writing binary log is ignored deliberately */ (void) thd->binlog_query(THD::ROW_QUERY_TYPE, - thd->query(), thd->query_length(), - transactional_tables, FALSE, errcode); + thd->query(), thd->query_length(), + transactional_tables, FALSE, FALSE, errcode); } - thd->transaction.all.modified_non_trans_table= true; } DBUG_VOID_RETURN; } @@ -1008,6 +996,9 @@ bool multi_delete::send_eof() /* reset used flags */ thd_proc_info(thd, "end"); + if (thd->transaction.stmt.modified_non_trans_table) + thd->transaction.all.modified_non_trans_table= TRUE; + /* We must invalidate the query cache before binlog writing and ha_autocommit_... @@ -1027,14 +1018,12 @@ bool multi_delete::send_eof() errcode= query_error_code(thd, killed_status == THD::NOT_KILLED); if (thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query(), thd->query_length(), - transactional_tables, FALSE, errcode) && + transactional_tables, FALSE, FALSE, errcode) && !normal_tables) { local_error=1; // Log write failed: roll back the SQL statement } } - if (thd->transaction.stmt.modified_non_trans_table) - thd->transaction.all.modified_non_trans_table= TRUE; } if (local_error != 0) error_handled= TRUE; // to force early leave from ::send_error() @@ -1059,15 +1048,16 @@ bool multi_delete::send_eof() static bool mysql_truncate_by_delete(THD *thd, TABLE_LIST *table_list) { - bool error, save_binlog_row_based= thd->current_stmt_binlog_row_based; + bool error, save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); DBUG_ENTER("mysql_truncate_by_delete"); table_list->lock_type= TL_WRITE; mysql_init_select(thd->lex); - thd->clear_current_stmt_binlog_row_based(); + thd->clear_current_stmt_binlog_format_row(); error= mysql_delete(thd, table_list, NULL, NULL, HA_POS_ERROR, LL(0), TRUE); ha_autocommit_or_rollback(thd, error); end_trans(thd, error ? ROLLBACK : COMMIT); - thd->current_stmt_binlog_row_based= save_binlog_row_based; + if (save_binlog_row_based) + thd->set_current_stmt_binlog_format_row(); DBUG_RETURN(error); } @@ -1170,10 +1160,10 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) // crashes, replacement works. *(path + path_length - reg_ext_length)= // '\0'; path[path_length - reg_ext_length] = 0; - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); error= ha_create_table(thd, path, table_list->db, table_list->table_name, &create_info, 1); - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); query_cache_invalidate3(thd, table_list, 0); end: @@ -1182,20 +1172,20 @@ end: if (!error) { /* In RBR, the statement is not binlogged if the table is temporary. */ - if (!is_temporary_table || !thd->current_stmt_binlog_row_based) + if (!is_temporary_table || !thd->is_current_stmt_binlog_format_row()) error= write_bin_log(thd, TRUE, thd->query(), thd->query_length()); if (!error) - my_ok(thd); // This should return record count + my_ok(thd); // This should return record count } - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); unlock_table_name(thd, table_list); - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); } else if (error) { - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); unlock_table_name(thd, table_list); - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); } DBUG_RETURN(error); diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 9b747759ece..24088872471 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -154,7 +154,7 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list) if ((res= check_duplicate_names(unit->types, 0))) goto exit; - create_options= (first_select->options | thd->options | + create_options= (first_select->options | thd->variables.option_bits | TMP_TABLE_ALL_COLUMNS); /* Temp table is created so that it hounours if UNION without ALL is to be @@ -289,7 +289,7 @@ bool mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *orig_table_list) (ORDER *) first_select->order_list.first, (ORDER *) first_select->group_list.first, first_select->having, (ORDER*) NULL, - (first_select->options | thd->options | + (first_select->options | thd->variables.option_bits | SELECT_NO_UNLOCK), derived_result, unit, first_select); } diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index ab3f2797405..5b45c35dd22 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -1,4 +1,5 @@ -/* Copyright (C) 2000-2004 MySQL AB +/* Copyright (C) 2000-2004 MySQL AB, 2008-2009 Sun Microsystems, Inc + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. @@ -143,14 +144,14 @@ static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables, { (*table_ptr)->file->ha_index_or_rnd_end(); if (! is_locked) - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); if (close_thread_table(thd, table_ptr)) { /* Tell threads waiting for refresh that something has happened */ broadcast_refresh(); } if (! is_locked) - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); } else if (tables->table) { @@ -775,7 +776,7 @@ void mysql_ha_flush(THD *thd) TABLE_LIST *hash_tables; DBUG_ENTER("mysql_ha_flush"); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); for (uint i= 0; i < thd->handler_tables_hash.records; i++) { diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 66e32f65f8c..6d8af8fbd40 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -61,6 +61,7 @@ #include "sql_show.h" #include "slave.h" #include "rpl_mi.h" +#include "sql_audit.h" #ifndef EMBEDDED_LIBRARY static bool delayed_get_table(THD *thd, TABLE_LIST *table_list); @@ -455,7 +456,7 @@ void upgrade_lock_type(THD *thd, thr_lock_type *lock_type, return; } - bool log_on= (thd->options & OPTION_BIN_LOG || + bool log_on= (thd->variables.option_bits & OPTION_BIN_LOG || ! (thd->security_ctx->master_access & SUPER_ACL)); if (global_system_variables.binlog_format == BINLOG_FORMAT_STMT && log_on && mysql_bin_log.is_open() && is_multi_insert) @@ -607,7 +608,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, By default, both logs are enabled (this won't cause problems if the server runs without --log-update or --log-bin). */ - bool log_on= ((thd->options & OPTION_BIN_LOG) || + bool log_on= ((thd->variables.option_bits & OPTION_BIN_LOG) || (!(thd->security_ctx->master_access & SUPER_ACL))); #endif thr_lock_type lock_type; @@ -899,6 +900,10 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, */ query_cache_invalidate3(thd, table_list, 1); } + + if (thd->transaction.stmt.modified_non_trans_table) + thd->transaction.all.modified_non_trans_table= TRUE; + if ((changed && error <= 0) || thd->transaction.stmt.modified_non_trans_table || was_insert_delayed) @@ -913,7 +918,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, thd->net.last_error/errno. For example if there has been a disk full error when writing the row, and it was MyISAM, then thd->net.last_error/errno will be set to - "disk full"... and the my_pwrite() will wait until free + "disk full"... and the mysql_file_pwrite() will wait until free space appears, and so when it finishes then the write_row() was entirely successful */ @@ -937,15 +942,13 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, */ DBUG_ASSERT(thd->killed != THD::KILL_BAD_DATA || error > 0); if (thd->binlog_query(THD::ROW_QUERY_TYPE, - thd->query(), thd->query_length(), - transactional_table, FALSE, - errcode)) + thd->query(), thd->query_length(), + transactional_table, FALSE, FALSE, + errcode)) { - error=1; + error= 1; } } - if (thd->transaction.stmt.modified_non_trans_table) - thd->transaction.all.modified_non_trans_table= TRUE; } DBUG_ASSERT(transactional_table || !changed || thd->transaction.stmt.modified_non_trans_table); @@ -976,7 +979,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, if (error) goto abort; - if (values_list.elements == 1 && (!(thd->options & OPTION_WARNINGS) || + if (values_list.elements == 1 && (!(thd->variables.option_bits & OPTION_WARNINGS) || !thd->cuted_fields)) { thd->row_count_func= info.copied + info.deleted + @@ -1058,7 +1061,7 @@ static bool check_view_insertability(THD * thd, TABLE_LIST *view) DBUG_ASSERT(view->table != 0 && view->field_translation != 0); - VOID(bitmap_init(&used_fields, used_fields_buff, table->s->fields, 0)); + (void) bitmap_init(&used_fields, used_fields_buff, table->s->fields, 0); bitmap_clear_all(&used_fields); view->contain_auto_increment= 0; @@ -1347,6 +1350,23 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, static int last_uniq_key(TABLE *table,uint keynr) { + /* + When an underlying storage engine informs that the unique key + conflicts are not reported in the ascending order by setting + the HA_DUPLICATE_KEY_NOT_IN_ORDER flag, we cannot rely on this + information to determine the last key conflict. + + The information about the last key conflict will be used to + do a replace of the new row on the conflicting row, rather + than doing a delete (of old row) + insert (of new row). + + Hence check for this flag and disable replacing the last row + by returning 0 always. Returning 0 will result in doing + a delete + insert always. + */ + if (table->file->ha_table_flags() & HA_DUPLICATE_KEY_NOT_IN_ORDER) + return 0; + while (++keynr < table->s->keys) if (table->key_info[keynr].flags & HA_NOSAME) return 0; @@ -1755,8 +1775,8 @@ class Delayed_insert :public ilink { public: THD thd; TABLE *table; - pthread_mutex_t mutex; - pthread_cond_t cond,cond_client; + mysql_mutex_t mutex; + mysql_cond_t cond, cond_client; volatile uint tables_in_use,stacked_inserts; volatile bool status,dead; COPY_INFO info; @@ -1769,6 +1789,7 @@ public: table(0),tables_in_use(0),stacked_inserts(0), status(0), dead(0), group_count(0) { + DBUG_ENTER("Delayed_insert constructor"); thd.security_ctx->user=thd.security_ctx->priv_user=(char*) delayed_user; thd.security_ctx->host=(char*) my_localhost; thd.current_tablenr=0; @@ -1777,25 +1798,36 @@ public: thd.lex->current_select= 0; // for my_message_sql thd.lex->sql_command= SQLCOM_INSERT; // For innodb::store_lock() /* - Statement-based replication of INSERT DELAYED has problems with RAND() - and user vars, so in mixed mode we go to row-based. + Statement-based replication of INSERT DELAYED has problems with + RAND() and user variables, so in mixed mode we go to row-based. + For normal commands, the unsafe flag is set at parse time. + However, since the flag is a member of the THD object, of which + the delayed_insert thread has its own copy, we must set the + statement to unsafe here and explicitly set row logging mode. + + @todo set_current_stmt_binlog_format_row_if_mixed should not be + called by anything else than thd->decide_logging_format(). When + we call set_current_blah here, none of the checks in + decide_logging_format is made. We should probably call + thd->decide_logging_format() directly instead. /Sven */ - thd.lex->set_stmt_unsafe(); - thd.set_current_stmt_binlog_row_based_if_mixed(); + thd.lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_DELAYED); + thd.set_current_stmt_binlog_format_row_if_mixed(); bzero((char*) &thd.net, sizeof(thd.net)); // Safety bzero((char*) &table_list, sizeof(table_list)); // Safety thd.system_thread= SYSTEM_THREAD_DELAYED_INSERT; thd.security_ctx->host_or_ip= ""; bzero((char*) &info,sizeof(info)); - pthread_mutex_init(&mutex,MY_MUTEX_INIT_FAST); - pthread_cond_init(&cond,NULL); - pthread_cond_init(&cond_client,NULL); - VOID(pthread_mutex_lock(&LOCK_thread_count)); + mysql_mutex_init(key_delayed_insert_mutex, &mutex, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_delayed_insert_cond, &cond, NULL); + mysql_cond_init(key_delayed_insert_cond_client, &cond_client, NULL); + mysql_mutex_lock(&LOCK_thread_count); delayed_insert_threads++; delayed_lock= global_system_variables.low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE; - VOID(pthread_mutex_unlock(&LOCK_thread_count)); + mysql_mutex_unlock(&LOCK_thread_count); + DBUG_VOID_RETURN; } ~Delayed_insert() { @@ -1805,17 +1837,17 @@ public: delete row; if (table) close_thread_tables(&thd); - VOID(pthread_mutex_lock(&LOCK_thread_count)); - pthread_mutex_destroy(&mutex); - pthread_cond_destroy(&cond); - pthread_cond_destroy(&cond_client); + mysql_mutex_lock(&LOCK_thread_count); + mysql_mutex_destroy(&mutex); + mysql_cond_destroy(&cond); + mysql_cond_destroy(&cond_client); thd.unlink(); // Must be unlinked under lock x_free(thd.query()); thd.security_ctx->user= thd.security_ctx->host=0; thread_count--; delayed_insert_threads--; - VOID(pthread_mutex_unlock(&LOCK_thread_count)); - VOID(pthread_cond_broadcast(&COND_thread_count)); /* Tell main we are ready */ + mysql_mutex_unlock(&LOCK_thread_count); + mysql_cond_broadcast(&COND_thread_count); /* Tell main we are ready */ } /* The following is for checking when we can delete ourselves */ @@ -1825,18 +1857,18 @@ public: } void unlock() { - pthread_mutex_lock(&LOCK_delayed_insert); + mysql_mutex_lock(&LOCK_delayed_insert); if (!--locks_in_memory) { - pthread_mutex_lock(&mutex); + mysql_mutex_lock(&mutex); if (thd.killed && ! stacked_inserts && ! tables_in_use) { - pthread_cond_signal(&cond); + mysql_cond_signal(&cond); status=1; } - pthread_mutex_unlock(&mutex); + mysql_mutex_unlock(&mutex); } - pthread_mutex_unlock(&LOCK_delayed_insert); + mysql_mutex_unlock(&LOCK_delayed_insert); } inline uint lock_count() { return locks_in_memory; } @@ -1857,7 +1889,7 @@ static Delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list) { thd_proc_info(thd, "waiting for delay_list"); - pthread_mutex_lock(&LOCK_delayed_insert); // Protect master list + mysql_mutex_lock(&LOCK_delayed_insert); // Protect master list I_List_iterator<Delayed_insert> it(delayed_threads); Delayed_insert *di; while ((di= it++)) @@ -1869,7 +1901,7 @@ Delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list) break; } } - pthread_mutex_unlock(&LOCK_delayed_insert); // For unlink from list + mysql_mutex_unlock(&LOCK_delayed_insert); // For unlink from list return di; } @@ -1939,7 +1971,7 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) if (delayed_insert_threads >= thd->variables.max_insert_delayed_threads) DBUG_RETURN(0); thd_proc_info(thd, "Creating delayed handler"); - pthread_mutex_lock(&LOCK_delayed_create); + mysql_mutex_lock(&LOCK_delayed_create); /* The first search above was done without LOCK_delayed_create. Another thread might have created the handler in between. Search again. @@ -1947,20 +1979,17 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) if (! (di= find_handler(thd, table_list))) { if (!(di= new Delayed_insert())) - { - thd->fatal_error(); goto end_create; - } - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thread_count++; - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); di->thd.set_db(table_list->db, (uint) strlen(table_list->db)); - di->thd.set_query(my_strdup(table_list->table_name, MYF(MY_WME)), 0); + di->thd.set_query(my_strdup(table_list->table_name, + MYF(MY_WME | ME_FATALERROR)), 0); if (di->thd.db == NULL || di->thd.query() == NULL) { /* The error is reported */ delete di; - thd->fatal_error(); goto end_create; } di->table_list= *table_list; // Needed to open table @@ -1968,18 +1997,18 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) di->table_list.alias= di->table_list.table_name= di->thd.query(); di->table_list.db= di->thd.db; di->lock(); - pthread_mutex_lock(&di->mutex); - if ((error= pthread_create(&di->thd.real_id, &connection_attrib, - handle_delayed_insert, (void*) di))) + mysql_mutex_lock(&di->mutex); + if ((error= mysql_thread_create(key_thread_delayed_insert, + &di->thd.real_id, &connection_attrib, + handle_delayed_insert, (void*) di))) { DBUG_PRINT("error", ("Can't create thread to handle delayed insert (error %d)", error)); - pthread_mutex_unlock(&di->mutex); + mysql_mutex_unlock(&di->mutex); di->unlock(); delete di; - my_error(ER_CANT_CREATE_THREAD, MYF(0), error); - thd->fatal_error(); + my_error(ER_CANT_CREATE_THREAD, MYF(ME_FATALERROR), error); goto end_create; } @@ -1987,9 +2016,9 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) thd_proc_info(thd, "waiting for handler open"); while (!di->thd.killed && !di->table && !thd->killed) { - pthread_cond_wait(&di->cond_client, &di->mutex); + mysql_cond_wait(&di->cond_client, &di->mutex); } - pthread_mutex_unlock(&di->mutex); + mysql_mutex_unlock(&di->mutex); thd_proc_info(thd, "got old table"); if (di->thd.killed) { @@ -2012,16 +2041,16 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) di->unlock(); goto end_create; } - pthread_mutex_lock(&LOCK_delayed_insert); + mysql_mutex_lock(&LOCK_delayed_insert); delayed_threads.append(di); - pthread_mutex_unlock(&LOCK_delayed_insert); + mysql_mutex_unlock(&LOCK_delayed_insert); } - pthread_mutex_unlock(&LOCK_delayed_create); + mysql_mutex_unlock(&LOCK_delayed_create); } - pthread_mutex_lock(&di->mutex); + mysql_mutex_lock(&di->mutex); table_list->table= di->get_local_table(thd); - pthread_mutex_unlock(&di->mutex); + mysql_mutex_unlock(&di->mutex); if (table_list->table) { DBUG_ASSERT(! thd->is_error()); @@ -2032,7 +2061,7 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) DBUG_RETURN((table_list->table == NULL)); end_create: - pthread_mutex_unlock(&LOCK_delayed_create); + mysql_mutex_unlock(&LOCK_delayed_create); DBUG_RETURN(thd->is_error()); } @@ -2068,10 +2097,10 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) if (!thd.lock) // Table is not locked { thd_proc_info(client_thd, "waiting for handler lock"); - pthread_cond_signal(&cond); // Tell handler to lock table + mysql_cond_signal(&cond); // Tell handler to lock table while (!dead && !thd.lock && ! client_thd->killed) { - pthread_cond_wait(&cond_client,&mutex); + mysql_cond_wait(&cond_client, &mutex); } thd_proc_info(client_thd, "got handler lock"); if (client_thd->killed) @@ -2158,7 +2187,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) error: tables_in_use--; status=1; - pthread_cond_signal(&cond); // Inform thread about abort + mysql_cond_signal(&cond); // Inform thread about abort DBUG_RETURN(0); } @@ -2177,9 +2206,9 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, (ulong) query.length)); thd_proc_info(thd, "waiting for handler insert"); - pthread_mutex_lock(&di->mutex); + mysql_mutex_lock(&di->mutex); while (di->stacked_inserts >= delayed_queue_size && !thd->killed) - pthread_cond_wait(&di->cond_client,&di->mutex); + mysql_cond_wait(&di->cond_client, &di->mutex); thd_proc_info(thd, "storing row into queue"); if (thd->killed) @@ -2254,15 +2283,15 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, di->status=1; if (table->s->blob_fields) unlink_blobs(table); - pthread_cond_signal(&di->cond); + mysql_cond_signal(&di->cond); thread_safe_increment(delayed_rows_in_use,&LOCK_delayed_status); - pthread_mutex_unlock(&di->mutex); + mysql_mutex_unlock(&di->mutex); DBUG_RETURN(0); err: delete row; - pthread_mutex_unlock(&di->mutex); + mysql_mutex_unlock(&di->mutex); DBUG_RETURN(1); } @@ -2275,14 +2304,14 @@ static void end_delayed_insert(THD *thd) { DBUG_ENTER("end_delayed_insert"); Delayed_insert *di=thd->di; - pthread_mutex_lock(&di->mutex); + mysql_mutex_lock(&di->mutex); DBUG_PRINT("info",("tables in use: %d",di->tables_in_use)); if (!--di->tables_in_use || di->thd.killed) { // Unlock table di->status=1; - pthread_cond_signal(&di->cond); + mysql_cond_signal(&di->cond); } - pthread_mutex_unlock(&di->mutex); + mysql_mutex_unlock(&di->mutex); DBUG_VOID_RETURN; } @@ -2291,7 +2320,7 @@ static void end_delayed_insert(THD *thd) void kill_delayed_threads(void) { - VOID(pthread_mutex_lock(&LOCK_delayed_insert)); // For unlink from list + mysql_mutex_lock(&LOCK_delayed_insert); // For unlink from list I_List_iterator<Delayed_insert> it(delayed_threads); Delayed_insert *di; @@ -2300,7 +2329,7 @@ void kill_delayed_threads(void) di->thd.killed= THD::KILL_CONNECTION; if (di->thd.mysys_var) { - pthread_mutex_lock(&di->thd.mysys_var->mutex); + mysql_mutex_lock(&di->thd.mysys_var->mutex); if (di->thd.mysys_var->current_cond) { /* @@ -2308,250 +2337,249 @@ void kill_delayed_threads(void) in handle_delayed_insert() */ if (&di->mutex != di->thd.mysys_var->current_mutex) - pthread_mutex_lock(di->thd.mysys_var->current_mutex); - pthread_cond_broadcast(di->thd.mysys_var->current_cond); + mysql_mutex_lock(di->thd.mysys_var->current_mutex); + mysql_cond_broadcast(di->thd.mysys_var->current_cond); if (&di->mutex != di->thd.mysys_var->current_mutex) - pthread_mutex_unlock(di->thd.mysys_var->current_mutex); + mysql_mutex_unlock(di->thd.mysys_var->current_mutex); } - pthread_mutex_unlock(&di->thd.mysys_var->mutex); + mysql_mutex_unlock(&di->thd.mysys_var->mutex); } } - VOID(pthread_mutex_unlock(&LOCK_delayed_insert)); // For unlink from list + mysql_mutex_unlock(&LOCK_delayed_insert); // For unlink from list } -static void handle_delayed_insert_impl(THD *thd, Delayed_insert *di) +/* + * Create a new delayed insert thread +*/ + +pthread_handler_t handle_delayed_insert(void *arg) { - DBUG_ENTER("handle_delayed_insert_impl"); - thd->thread_stack= (char*) &thd; - if (init_thr_lock() || thd->store_globals()) - { - /* Can't use my_error since store_globals has perhaps failed */ - thd->stmt_da->set_error_status(thd, ER_OUT_OF_RESOURCES, - ER(ER_OUT_OF_RESOURCES), NULL); - thd->fatal_error(); - goto err; - } + Delayed_insert *di=(Delayed_insert*) arg; + THD *thd= &di->thd; + + pthread_detach_this_thread(); + /* Add thread to THD list so that's it's visible in 'show processlist' */ + mysql_mutex_lock(&LOCK_thread_count); + thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; + thd->set_current_time(); + threads.append(thd); + thd->killed=abort_loop ? THD::KILL_CONNECTION : THD::NOT_KILLED; + mysql_mutex_unlock(&LOCK_thread_count); + + mysql_thread_set_psi_id(thd->thread_id); /* - Open table requires an initialized lex in case the table is - partitioned. The .frm file contains a partial SQL string which is - parsed using a lex, that depends on initialized thd->lex. - */ - lex_start(thd); - thd->lex->sql_command= SQLCOM_INSERT; // For innodb::store_lock() - /* - Statement-based replication of INSERT DELAYED has problems with RAND() - and user vars, so in mixed mode we go to row-based. + Wait until the client runs into mysql_cond_wait(), + where we free it after the table is opened and di linked in the list. + If we did not wait here, the client might detect the opened table + before it is linked to the list. It would release LOCK_delayed_create + and allow another thread to create another handler for the same table, + since it does not find one in the list. */ - thd->lex->set_stmt_unsafe(); - thd->set_current_stmt_binlog_row_based_if_mixed(); - - /* Open table */ - if (!(di->table= open_n_lock_single_table(thd, &di->table_list, - TL_WRITE_DELAYED))) - { - thd->fatal_error(); // Abort waiting inserts - goto err; - } - if (!(di->table->file->ha_table_flags() & HA_CAN_INSERT_DELAYED)) + mysql_mutex_lock(&di->mutex); + if (my_thread_init()) { - thd->fatal_error(); - my_error(ER_DELAYED_NOT_SUPPORTED, MYF(0), di->table_list.table_name); - goto err; + /* Can't use my_error since store_globals has not yet been called */ + thd->stmt_da->set_error_status(thd, ER_OUT_OF_RESOURCES, + ER(ER_OUT_OF_RESOURCES), NULL); } - if (di->table->triggers) + else { + DBUG_ENTER("handle_delayed_insert"); + thd->thread_stack= (char*) &thd; + if (init_thr_lock() || thd->store_globals()) + { + /* Can't use my_error since store_globals has perhaps failed */ + thd->stmt_da->set_error_status(thd, ER_OUT_OF_RESOURCES, + ER(ER_OUT_OF_RESOURCES), NULL); + thd->fatal_error(); + goto err; + } + /* - Table has triggers. This is not an error, but we do - not support triggers with delayed insert. Terminate the delayed - thread without an error and thus request lock upgrade. + Open table requires an initialized lex in case the table is + partitioned. The .frm file contains a partial SQL string which is + parsed using a lex, that depends on initialized thd->lex. */ - goto err; - } - di->table->copy_blobs=1; - - /* Tell client that the thread is initialized */ - pthread_cond_signal(&di->cond_client); - - /* Now wait until we get an insert or lock to handle */ - /* We will not abort as long as a client thread uses this thread */ + lex_start(thd); + thd->lex->sql_command= SQLCOM_INSERT; // For innodb::store_lock() + /* + Statement-based replication of INSERT DELAYED has problems with RAND() + and user vars, so in mixed mode we go to row-based. + */ + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_DELAYED); + thd->set_current_stmt_binlog_format_row_if_mixed(); - for (;;) - { - if (thd->killed == THD::KILL_CONNECTION) + /* Open table */ + if (!(di->table= open_n_lock_single_table(thd, &di->table_list, + TL_WRITE_DELAYED))) + { + thd->fatal_error(); // Abort waiting inserts + goto err; + } + if (!(di->table->file->ha_table_flags() & HA_CAN_INSERT_DELAYED)) + { + my_error(ER_DELAYED_NOT_SUPPORTED, MYF(ME_FATALERROR), + di->table_list.table_name); + goto err; + } + if (di->table->triggers) { - uint lock_count; /* - Remove this from delay insert list so that no one can request a - table from this + Table has triggers. This is not an error, but we do + not support triggers with delayed insert. Terminate the delayed + thread without an error and thus request lock upgrade. */ - pthread_mutex_unlock(&di->mutex); - pthread_mutex_lock(&LOCK_delayed_insert); - di->unlink(); - lock_count=di->lock_count(); - pthread_mutex_unlock(&LOCK_delayed_insert); - pthread_mutex_lock(&di->mutex); - if (!lock_count && !di->tables_in_use && !di->stacked_inserts) - break; // Time to die + goto err; } + di->table->copy_blobs=1; - if (!di->status && !di->stacked_inserts) - { - struct timespec abstime; - set_timespec(abstime, delayed_insert_timeout); + /* Tell client that the thread is initialized */ + mysql_cond_signal(&di->cond_client); + + /* Now wait until we get an insert or lock to handle */ + /* We will not abort as long as a client thread uses this thread */ - /* Information for pthread_kill */ - di->thd.mysys_var->current_mutex= &di->mutex; - di->thd.mysys_var->current_cond= &di->cond; - thd_proc_info(&(di->thd), "Waiting for INSERT"); + for (;;) + { + if (thd->killed == THD::KILL_CONNECTION) + { + uint lock_count; + /* + Remove this from delay insert list so that no one can request a + table from this + */ + mysql_mutex_unlock(&di->mutex); + mysql_mutex_lock(&LOCK_delayed_insert); + di->unlink(); + lock_count=di->lock_count(); + mysql_mutex_unlock(&LOCK_delayed_insert); + mysql_mutex_lock(&di->mutex); + if (!lock_count && !di->tables_in_use && !di->stacked_inserts) + break; // Time to die + } - DBUG_PRINT("info",("Waiting for someone to insert rows")); - while (!thd->killed) + if (!di->status && !di->stacked_inserts) { - int error; + struct timespec abstime; + set_timespec(abstime, delayed_insert_timeout); + + /* Information for pthread_kill */ + di->thd.mysys_var->current_mutex= &di->mutex; + di->thd.mysys_var->current_cond= &di->cond; + thd_proc_info(&(di->thd), "Waiting for INSERT"); + + DBUG_PRINT("info",("Waiting for someone to insert rows")); + while (!thd->killed) + { + int error; + mysql_audit_release(thd); #if defined(HAVE_BROKEN_COND_TIMEDWAIT) - error=pthread_cond_wait(&di->cond,&di->mutex); + error= mysql_cond_wait(&di->cond, &di->mutex); #else - error=pthread_cond_timedwait(&di->cond,&di->mutex,&abstime); + error= mysql_cond_timedwait(&di->cond, &di->mutex, &abstime); #ifdef EXTRA_DEBUG - if (error && error != EINTR && error != ETIMEDOUT) - { - fprintf(stderr, "Got error %d from pthread_cond_timedwait\n",error); - DBUG_PRINT("error",("Got error %d from pthread_cond_timedwait", - error)); - } + if (error && error != EINTR && error != ETIMEDOUT) + { + fprintf(stderr, "Got error %d from mysql_cond_timedwait\n", error); + DBUG_PRINT("error", ("Got error %d from mysql_cond_timedwait", + error)); + } #endif #endif - if (thd->killed || di->status) - break; - if (error == ETIMEDOUT || error == ETIME) - { - thd->killed= THD::KILL_CONNECTION; - break; - } + if (thd->killed || di->status) + break; + if (error == ETIMEDOUT || error == ETIME) + { + thd->killed= THD::KILL_CONNECTION; + break; + } + } + /* We can't lock di->mutex and mysys_var->mutex at the same time */ + mysql_mutex_unlock(&di->mutex); + mysql_mutex_lock(&di->thd.mysys_var->mutex); + di->thd.mysys_var->current_mutex= 0; + di->thd.mysys_var->current_cond= 0; + mysql_mutex_unlock(&di->thd.mysys_var->mutex); + mysql_mutex_lock(&di->mutex); } - /* We can't lock di->mutex and mysys_var->mutex at the same time */ - pthread_mutex_unlock(&di->mutex); - pthread_mutex_lock(&di->thd.mysys_var->mutex); - di->thd.mysys_var->current_mutex= 0; - di->thd.mysys_var->current_cond= 0; - pthread_mutex_unlock(&di->thd.mysys_var->mutex); - pthread_mutex_lock(&di->mutex); - } - thd_proc_info(&(di->thd), 0); + thd_proc_info(&(di->thd), 0); - if (di->tables_in_use && ! thd->lock) - { - bool not_used; - /* - Request for new delayed insert. - Lock the table, but avoid to be blocked by a global read lock. - If we got here while a global read lock exists, then one or more - inserts started before the lock was requested. These are allowed - to complete their work before the server returns control to the - client which requested the global read lock. The delayed insert - handler will close the table and finish when the outstanding - inserts are done. - */ - if (! (thd->lock= mysql_lock_tables(thd, &di->table, 1, - MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK, - ¬_used))) + if (di->tables_in_use && ! thd->lock) { - /* Fatal error */ - di->dead= 1; - thd->killed= THD::KILL_CONNECTION; + bool not_used; + /* + Request for new delayed insert. + Lock the table, but avoid to be blocked by a global read lock. + If we got here while a global read lock exists, then one or more + inserts started before the lock was requested. These are allowed + to complete their work before the server returns control to the + client which requested the global read lock. The delayed insert + handler will close the table and finish when the outstanding + inserts are done. + */ + if (! (thd->lock= mysql_lock_tables(thd, &di->table, 1, + MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK, + ¬_used))) + { + /* Fatal error */ + di->dead= 1; + thd->killed= THD::KILL_CONNECTION; + } + mysql_cond_broadcast(&di->cond_client); } - pthread_cond_broadcast(&di->cond_client); - } - if (di->stacked_inserts) - { - if (di->handle_inserts()) + if (di->stacked_inserts) { - /* Some fatal error */ - di->dead= 1; - thd->killed= THD::KILL_CONNECTION; + if (di->handle_inserts()) + { + /* Some fatal error */ + di->dead= 1; + thd->killed= THD::KILL_CONNECTION; + } } + di->status=0; + if (!di->stacked_inserts && !di->tables_in_use && thd->lock) + { + /* + No one is doing a insert delayed + Unlock table so that other threads can use it + */ + MYSQL_LOCK *lock=thd->lock; + thd->lock=0; + mysql_mutex_unlock(&di->mutex); + /* + We need to release next_insert_id before unlocking. This is + enforced by handler::ha_external_lock(). + */ + di->table->file->ha_release_auto_increment(); + mysql_unlock_tables(thd, lock); + ha_autocommit_or_rollback(thd, 0); + di->group_count=0; + mysql_audit_release(thd); + mysql_mutex_lock(&di->mutex); + } + if (di->tables_in_use) + mysql_cond_broadcast(&di->cond_client); // If waiting clients } - di->status=0; - if (!di->stacked_inserts && !di->tables_in_use && thd->lock) - { - /* - No one is doing a insert delayed - Unlock table so that other threads can use it - */ - MYSQL_LOCK *lock=thd->lock; - thd->lock=0; - pthread_mutex_unlock(&di->mutex); - /* - We need to release next_insert_id before unlocking. This is - enforced by handler::ha_external_lock(). - */ - di->table->file->ha_release_auto_increment(); - mysql_unlock_tables(thd, lock); - ha_autocommit_or_rollback(thd, 0); - di->group_count=0; - pthread_mutex_lock(&di->mutex); - } - if (di->tables_in_use) - pthread_cond_broadcast(&di->cond_client); // If waiting clients - } - -err: - /* - mysql_lock_tables() can potentially start a transaction and write - a table map. In the event of an error, that transaction has to be - rolled back. We only need to roll back a potential statement - transaction, since real transactions are rolled back in - close_thread_tables(). - - TODO: This is not true any more, table maps are generated on the - first call to ha_*_row() instead. Remove code that are used to - cover for the case outlined above. - */ - ha_autocommit_or_rollback(thd, 1); - - DBUG_VOID_RETURN; -} - - -/* - * Create a new delayed insert thread -*/ -pthread_handler_t handle_delayed_insert(void *arg) -{ - Delayed_insert *di=(Delayed_insert*) arg; - THD *thd= &di->thd; - - pthread_detach_this_thread(); - /* Add thread to THD list so that's it's visible in 'show processlist' */ - pthread_mutex_lock(&LOCK_thread_count); - thd->thread_id= thd->variables.pseudo_thread_id= thread_id++; - thd->set_current_time(); - threads.append(thd); - thd->killed=abort_loop ? THD::KILL_CONNECTION : THD::NOT_KILLED; - pthread_mutex_unlock(&LOCK_thread_count); + err: + /* + mysql_lock_tables() can potentially start a transaction and write + a table map. In the event of an error, that transaction has to be + rolled back. We only need to roll back a potential statement + transaction, since real transactions are rolled back in + close_thread_tables(). + + TODO: This is not true any more, table maps are generated on the + first call to ha_*_row() instead. Remove code that are used to + cover for the case outlined above. + */ + ha_autocommit_or_rollback(thd, 1); - /* - Wait until the client runs into pthread_cond_wait(), - where we free it after the table is opened and di linked in the list. - If we did not wait here, the client might detect the opened table - before it is linked to the list. It would release LOCK_delayed_create - and allow another thread to create another handler for the same table, - since it does not find one in the list. - */ - pthread_mutex_lock(&di->mutex); - if (my_thread_init()) - { - /* Can't use my_error since store_globals has not yet been called */ - thd->stmt_da->set_error_status(thd, ER_OUT_OF_RESOURCES, - ER(ER_OUT_OF_RESOURCES), NULL); - goto end; + DBUG_LEAVE; } - handle_delayed_insert_impl(thd, di); -end: /* di should be unlinked from the thread handler list and have no active clients @@ -2561,14 +2589,14 @@ end: di->table=0; di->dead= 1; // If error thd->killed= THD::KILL_CONNECTION; // If error - pthread_cond_broadcast(&di->cond_client); // Safety - pthread_mutex_unlock(&di->mutex); + mysql_cond_broadcast(&di->cond_client); // Safety + mysql_mutex_unlock(&di->mutex); - pthread_mutex_lock(&LOCK_delayed_create); // Because of delayed_get_table - pthread_mutex_lock(&LOCK_delayed_insert); + mysql_mutex_lock(&LOCK_delayed_create); // Because of delayed_get_table + mysql_mutex_lock(&LOCK_delayed_insert); delete di; - pthread_mutex_unlock(&LOCK_delayed_insert); - pthread_mutex_unlock(&LOCK_delayed_create); + mysql_mutex_unlock(&LOCK_delayed_insert); + mysql_mutex_unlock(&LOCK_delayed_create); my_thread_end(); pthread_exit(0); @@ -2609,13 +2637,14 @@ bool Delayed_insert::handle_inserts(void) { int error; ulong max_rows; + bool has_trans = TRUE; bool using_ignore= 0, using_opt_replace= 0, using_bin_log= mysql_bin_log.is_open(); delayed_row *row; DBUG_ENTER("handle_inserts"); /* Allow client to insert new rows */ - pthread_mutex_unlock(&mutex); + mysql_mutex_unlock(&mutex); table->next_number_field=table->found_next_number_field; table->use_all_columns(); @@ -2648,12 +2677,12 @@ bool Delayed_insert::handle_inserts(void) */ if (!using_bin_log) table->file->extra(HA_EXTRA_WRITE_CACHE); - pthread_mutex_lock(&mutex); + mysql_mutex_lock(&mutex); while ((row=rows.get())) { stacked_inserts--; - pthread_mutex_unlock(&mutex); + mysql_mutex_unlock(&mutex); memcpy(table->record[0],row->record,table->s->reclength); thd.start_time=row->start_time; @@ -2761,9 +2790,9 @@ bool Delayed_insert::handle_inserts(void) */ if (thd.binlog_query(THD::ROW_QUERY_TYPE, row->query.str, row->query.length, - FALSE, FALSE, errcode)) + FALSE, FALSE, FALSE, errcode)) goto err; - + thd.time_zone_used = backup_time_zone_used; thd.variables.time_zone = backup_time_zone; } @@ -2772,7 +2801,7 @@ bool Delayed_insert::handle_inserts(void) free_delayed_insert_blobs(table); thread_safe_decrement(delayed_rows_in_use,&LOCK_delayed_status); thread_safe_increment(delayed_insert_writes,&LOCK_delayed_status); - pthread_mutex_lock(&mutex); + mysql_mutex_lock(&mutex); /* Reset the table->auto_increment_field_not_null as it is valid for @@ -2794,9 +2823,9 @@ bool Delayed_insert::handle_inserts(void) if (stacked_inserts || tables_in_use) // Let these wait a while { if (tables_in_use) - pthread_cond_broadcast(&cond_client); // If waiting clients + mysql_cond_broadcast(&cond_client); // If waiting clients thd_proc_info(&thd, "reschedule"); - pthread_mutex_unlock(&mutex); + mysql_mutex_unlock(&mutex); if ((error=table->file->extra(HA_EXTRA_NO_CACHE))) { /* This should never happen */ @@ -2815,15 +2844,15 @@ bool Delayed_insert::handle_inserts(void) } if (!using_bin_log) table->file->extra(HA_EXTRA_WRITE_CACHE); - pthread_mutex_lock(&mutex); + mysql_mutex_lock(&mutex); thd_proc_info(&thd, "insert"); } if (tables_in_use) - pthread_cond_broadcast(&cond_client); // If waiting clients + mysql_cond_broadcast(&cond_client); // If waiting clients } } thd_proc_info(&thd, 0); - pthread_mutex_unlock(&mutex); + mysql_mutex_unlock(&mutex); /* We need to flush the pending event when using row-based @@ -2836,9 +2865,11 @@ bool Delayed_insert::handle_inserts(void) or trigger. TODO: Move the logging to last in the sequence of rows. - */ - if (thd.current_stmt_binlog_row_based && - thd.binlog_flush_pending_rows_event(TRUE)) + */ + has_trans= thd.lex->sql_command == SQLCOM_CREATE_TABLE || + table->file->has_transactions(); + if (thd.is_current_stmt_binlog_format_row() && + thd.binlog_flush_pending_rows_event(TRUE, has_trans)) goto err; if ((error=table->file->extra(HA_EXTRA_NO_CACHE))) @@ -2849,7 +2880,7 @@ bool Delayed_insert::handle_inserts(void) goto err; } query_cache_invalidate3(&thd, table, 1); - pthread_mutex_lock(&mutex); + mysql_mutex_lock(&mutex); DBUG_RETURN(0); err: @@ -2873,7 +2904,7 @@ bool Delayed_insert::handle_inserts(void) } DBUG_PRINT("error", ("dropped %lu rows after an error", max_rows)); thread_safe_increment(delayed_insert_errors, &LOCK_delayed_status); - pthread_mutex_lock(&mutex); + mysql_mutex_lock(&mutex); DBUG_RETURN(1); } #endif /* EMBEDDED_LIBRARY */ @@ -2903,19 +2934,6 @@ bool mysql_insert_select_prepare(THD *thd) DBUG_ENTER("mysql_insert_select_prepare"); /* - Statement-based replication of INSERT ... SELECT ... LIMIT is not safe - as order of rows is not defined, so in mixed mode we go to row-based. - - Note that we may consider a statement as safe if ORDER BY primary_key - is present or we SELECT a constant. However it may confuse users to - see very similiar statements replicated differently. - */ - if (lex->current_select->select_limit) - { - lex->set_stmt_unsafe(); - thd->set_current_stmt_binlog_row_based_if_mixed(); - } - /* SELECT_LEX do not belong to INSERT statement, so we can't add WHERE clause if table is VIEW */ @@ -3280,9 +3298,11 @@ bool select_insert::send_eof() and ha_autocommit_or_rollback. */ query_cache_invalidate3(thd, table, 1); - if (thd->transaction.stmt.modified_non_trans_table) - thd->transaction.all.modified_non_trans_table= TRUE; } + + if (thd->transaction.stmt.modified_non_trans_table) + thd->transaction.all.modified_non_trans_table= TRUE; + DBUG_ASSERT(trans_table || !changed || thd->transaction.stmt.modified_non_trans_table); @@ -3302,7 +3322,7 @@ bool select_insert::send_eof() errcode= query_error_code(thd, killed_status == THD::NOT_KILLED); if (thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query(), thd->query_length(), - trans_table, FALSE, errcode)) + trans_table, FALSE, FALSE, errcode)) { table->file->ha_release_auto_increment(); DBUG_RETURN(1); @@ -3374,16 +3394,17 @@ void select_insert::abort() { transactional_table= table->file->has_transactions(); if (thd->transaction.stmt.modified_non_trans_table) { + if (!can_rollback_data()) + thd->transaction.all.modified_non_trans_table= TRUE; + if (mysql_bin_log.is_open()) { int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); /* error of writing binary log is ignored */ (void) thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query(), thd->query_length(), - transactional_table, FALSE, errcode); + transactional_table, FALSE, FALSE, errcode); } - if (!thd->current_stmt_binlog_row_based && !can_rollback_data()) - thd->transaction.all.modified_non_trans_table= TRUE; if (changed) query_cache_invalidate3(thd, table, 1); } @@ -3536,7 +3557,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) { - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); if (reopen_name_locked_table(thd, create_table, FALSE)) { quick_rm_table(create_info->db_type, create_table->db, @@ -3545,7 +3566,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, } else table= create_table->table; - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); } else { @@ -3627,11 +3648,11 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) virtual int do_postlock(TABLE **tables, uint count) { THD *thd= const_cast<THD*>(ptr->get_thd()); - if (int error= decide_logging_format(thd, &all_tables)) + if (int error= thd->decide_logging_format(&all_tables)) return error; TABLE const *const table = *tables; - if (thd->current_stmt_binlog_row_based && + if (thd->is_current_stmt_binlog_format_row() && !table->s->tmp_table && !ptr->get_create_info()->table_existed) { @@ -3656,7 +3677,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) temporary table, we need to start a statement transaction. */ if ((thd->lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) == 0 && - thd->current_stmt_binlog_row_based && + thd->is_current_stmt_binlog_format_row() && mysql_bin_log.is_open()) { thd->binlog_start_trans_and_stmt(); @@ -3675,7 +3696,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR), create_table->table_name); - if (thd->current_stmt_binlog_row_based) + if (thd->is_current_stmt_binlog_format_row()) binlog_show_create_table(&(create_table->table), 1); table= create_table->table; } @@ -3763,7 +3784,7 @@ select_create::binlog_show_create_table(TABLE **tables, uint count) schema that will do a close_thread_tables(), destroying the statement transaction cache. */ - DBUG_ASSERT(thd->current_stmt_binlog_row_based); + DBUG_ASSERT(thd->is_current_stmt_binlog_format_row()); DBUG_ASSERT(tables && *tables && count > 0); char buf[2048]; @@ -3785,6 +3806,7 @@ select_create::binlog_show_create_table(TABLE **tables, uint count) result= thd->binlog_query(THD::STMT_QUERY_TYPE, query.ptr(), query.length(), /* is_trans */ TRUE, + /* direct */ FALSE, /* suppress_use */ FALSE, errcode); } @@ -3804,7 +3826,7 @@ void select_create::send_error(uint errcode,const char *err) DBUG_PRINT("info", ("Current statement %s row-based", - thd->current_stmt_binlog_row_based ? "is" : "is NOT")); + thd->is_current_stmt_binlog_format_row() ? "is" : "is NOT")); DBUG_PRINT("info", ("Current table (at 0x%lu) %s a temporary (or non-existant) table", (ulong) table, @@ -3887,7 +3909,7 @@ void select_create::abort() thd->transaction.stmt.modified_non_trans_table= FALSE; reenable_binlog(thd); /* possible error of writing binary log is ignored deliberately */ - (void)thd->binlog_flush_pending_rows_event(TRUE); + (void) thd->binlog_flush_pending_rows_event(TRUE, TRUE); if (m_plock) { diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index f6dd1fae90a..6da734592dc 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -24,6 +24,8 @@ #include "sp.h" #include "sp_head.h" +static int lex_one_token(void *arg, void *yythd); + /* We are using pointer to this variable for distinguishing between assignment to NEW row field (when parsing trigger definition) and structured variable. @@ -36,6 +38,23 @@ sys_var *trg_new_row_fake_var= (sys_var*) 0x01; */ const LEX_STRING null_lex_str= {NULL, 0}; const LEX_STRING empty_lex_str= { (char*) "", 0 }; +/** + @note The order of the elements of this array must correspond to + the order of elements in enum_binlog_stmt_unsafe. +*/ +const int +Query_tables_list::binlog_stmt_unsafe_errcode[BINLOG_STMT_UNSAFE_COUNT] = +{ + ER_BINLOG_UNSAFE_LIMIT, + ER_BINLOG_UNSAFE_INSERT_DELAYED, + ER_BINLOG_UNSAFE_SYSTEM_TABLE, + ER_BINLOG_UNSAFE_AUTOINC_COLUMNS, + ER_BINLOG_UNSAFE_UDF, + ER_BINLOG_UNSAFE_SYSTEM_VARIABLE, + ER_BINLOG_UNSAFE_SYSTEM_FUNCTION, + ER_BINLOG_UNSAFE_NONTRANS_AFTER_TRANS +}; + /* Longest standard keyword name */ @@ -124,6 +143,8 @@ Lex_input_stream::Lex_input_stream(THD *thd, yylineno(1), yytoklen(0), yylval(NULL), + lookahead_token(-1), + lookahead_yylval(NULL), m_ptr(buffer), m_tok_start(NULL), m_tok_end(NULL), @@ -788,6 +809,60 @@ bool consume_comment(Lex_input_stream *lip, int remaining_recursions_permitted) int MYSQLlex(void *arg, void *yythd) { + THD *thd= (THD *)yythd; + Lex_input_stream *lip= & thd->m_parser_state->m_lip; + YYSTYPE *yylval=(YYSTYPE*) arg; + int token; + + if (lip->lookahead_token >= 0) + { + /* + The next token was already parsed in advance, + return it. + */ + token= lip->lookahead_token; + lip->lookahead_token= -1; + *yylval= *(lip->lookahead_yylval); + lip->lookahead_yylval= NULL; + return token; + } + + token= lex_one_token(arg, yythd); + + switch(token) { + case WITH: + /* + Parsing 'WITH' 'ROLLUP' or 'WITH' 'CUBE' requires 2 look ups, + which makes the grammar LALR(2). + Replace by a single 'WITH_ROLLUP' or 'WITH_CUBE' token, + to transform the grammar into a LALR(1) grammar, + which sql_yacc.yy can process. + */ + token= lex_one_token(arg, yythd); + switch(token) { + case CUBE_SYM: + return WITH_CUBE_SYM; + case ROLLUP_SYM: + return WITH_ROLLUP_SYM; + default: + /* + Save the token following 'WITH' + */ + lip->lookahead_yylval= lip->yylval; + lip->yylval= NULL; + lip->lookahead_token= token; + return WITH; + } + break; + default: + break; + } + + return token; +} + +int lex_one_token(void *arg, void *yythd) +{ reg1 uchar c= 0; bool comment_closed; int tokval, result_state; @@ -1614,7 +1689,6 @@ void st_select_lex::init_query() parent_lex->push_context(&context); cond_count= between_count= with_wild= 0; max_equal_elems= 0; - conds_processed_with_permanent_arena= 0; ref_pointer_array= 0; select_n_where_fields= 0; select_n_having_items= 0; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 4bf8cd41aee..80cb1e0f210 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -33,15 +33,23 @@ class sp_pcontext; class st_alter_tablespace; class partition_info; class Event_parse_data; +class set_var_base; +class sys_var; + +/** + used by the parser to store internal variable name +*/ +struct sys_var_with_base +{ + sys_var *var; + LEX_STRING base_name; +}; #ifdef MYSQL_SERVER /* The following hack is needed because mysql_yacc.cc does not define YYSTYPE before including this file */ - -#include "set_var.h" - #ifdef MYSQL_YACC #define LEX_YYSTYPE void * #else @@ -89,10 +97,10 @@ enum enum_sql_command { SQLCOM_ROLLBACK, SQLCOM_ROLLBACK_TO_SAVEPOINT, SQLCOM_COMMIT, SQLCOM_SAVEPOINT, SQLCOM_RELEASE_SAVEPOINT, SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP, - SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_CHANGE_MASTER, - SQLCOM_RENAME_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_RESTORE_TABLE, + SQLCOM_BEGIN, SQLCOM_CHANGE_MASTER, + SQLCOM_RENAME_TABLE, SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_PURGE_BEFORE, SQLCOM_SHOW_BINLOGS, - SQLCOM_SHOW_OPEN_TABLES, SQLCOM_LOAD_MASTER_DATA, + SQLCOM_SHOW_OPEN_TABLES, SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ, SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_UPDATE_MULTI, SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO, @@ -403,6 +411,8 @@ public: struct LEX; class st_select_lex; class st_select_lex_unit; + + class st_select_lex_node { protected: st_select_lex_node *next, **prev, /* neighbor list */ @@ -440,8 +450,17 @@ public: { return (void*) alloc_root(mem_root, (uint) size); } static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) {} - st_select_lex_node(): linkage(UNSPECIFIED_TYPE) {} + + // Ensures that at least all members used during cleanup() are initialized. + st_select_lex_node() + : next(NULL), prev(NULL), + master(NULL), slave(NULL), + link_next(NULL), link_prev(NULL), + linkage(UNSPECIFIED_TYPE) + { + } virtual ~st_select_lex_node() {} + inline st_select_lex_node* get_master() { return master; } virtual void init_query(); virtual void init_select(); @@ -487,6 +506,8 @@ class select_result; class JOIN; class select_union; class Procedure; + + class st_select_lex_unit: public st_select_lex_node { protected: TABLE_LIST result_table_list; @@ -498,6 +519,14 @@ protected: bool saved_error; public: + // Ensures that at least all members used during cleanup() are initialized. + st_select_lex_unit() + : union_result(NULL), table(NULL), result(NULL), + cleaned(false), + fake_select_lex(NULL) + { + } + bool prepared, // prepare phase already performed for UNION (unit) optimized, // optimize phase already performed for UNION (unit) executed, // already executed @@ -638,11 +667,6 @@ public: uint select_n_where_fields; enum_parsing_place parsing_place; /* where we are parsing expression */ bool with_sum_func; /* sum function indicator */ - /* - PS or SP cond natural joins was alredy processed with permanent - arena and all additional items which we need alredy stored in it - */ - bool conds_processed_with_permanent_arena; ulong table_join_options; uint in_sum_expr; @@ -1052,25 +1076,158 @@ public: } } + /** - Has the parser/scanner detected that this statement is unsafe? - */ + Enumeration listing of all types of unsafe statement. + + @note The order of elements of this enumeration type must + correspond to the order of the elements of the @c explanations + array defined in the body of @c THD::issue_unsafe_warnings. + */ + enum enum_binlog_stmt_unsafe { + /** + SELECT..LIMIT is unsafe because the set of rows returned cannot + be predicted. + */ + BINLOG_STMT_UNSAFE_LIMIT= 0, + /** + INSERT DELAYED is unsafe because the time when rows are inserted + cannot be predicted. + */ + BINLOG_STMT_UNSAFE_INSERT_DELAYED, + /** + Access to log tables is unsafe because slave and master probably + log different things. + */ + BINLOG_STMT_UNSAFE_SYSTEM_TABLE, + /** + Inserting into an autoincrement column in a stored routine is unsafe. + Even with just one autoincrement column, if the routine is invoked more than + once slave is not guaranteed to execute the statement graph same way as + the master. + And since it's impossible to estimate how many times a routine can be invoked at + the query pre-execution phase (see lock_tables), the statement is marked + pessimistically unsafe. + */ + BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS, + /** + Using a UDF (user-defined function) is unsafe. + */ + BINLOG_STMT_UNSAFE_UDF, + /** + Using most system variables is unsafe, because slave may run + with different options than master. + */ + BINLOG_STMT_UNSAFE_SYSTEM_VARIABLE, + /** + Using some functions is unsafe (e.g., UUID). + */ + BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION, + + /** + Mixing transactional and non-transactional statements are unsafe if + non-transactional reads or writes are occur after transactional + reads or writes inside a transaction. + */ + BINLOG_STMT_UNSAFE_NONTRANS_AFTER_TRANS, + + /* The last element of this enumeration type. */ + BINLOG_STMT_UNSAFE_COUNT + }; + /** + This has all flags from 0 (inclusive) to BINLOG_STMT_FLAG_COUNT + (exclusive) set. + */ + static const int BINLOG_STMT_UNSAFE_ALL_FLAGS= + ((1 << BINLOG_STMT_UNSAFE_COUNT) - 1); + + /** + Maps elements of enum_binlog_stmt_unsafe to error codes. + */ + static const int binlog_stmt_unsafe_errcode[BINLOG_STMT_UNSAFE_COUNT]; + + /** + Determine if this statement is marked as unsafe. + + @retval 0 if the statement is not marked as unsafe. + @retval nonzero if the statement is marked as unsafe. + */ inline bool is_stmt_unsafe() const { - return binlog_stmt_flags & (1U << BINLOG_STMT_FLAG_UNSAFE); + return get_stmt_unsafe_flags() != 0; } /** - Flag the current (top-level) statement as unsafe. + Flag the current (top-level) statement as unsafe. + The flag will be reset after the statement has finished. - The flag will be reset after the statement has finished. + @param unsafe_type The type of unsafety: one of the @c + BINLOG_STMT_FLAG_UNSAFE_* flags in @c enum_binlog_stmt_flag. + */ + inline void set_stmt_unsafe(enum_binlog_stmt_unsafe unsafe_type) { + DBUG_ENTER("set_stmt_unsafe"); + DBUG_ASSERT(unsafe_type >= 0 && unsafe_type < BINLOG_STMT_UNSAFE_COUNT); + binlog_stmt_flags|= (1U << unsafe_type); + DBUG_VOID_RETURN; + } - */ - inline void set_stmt_unsafe() { - binlog_stmt_flags|= (1U << BINLOG_STMT_FLAG_UNSAFE); + /** + Set the bits of binlog_stmt_flags determining the type of + unsafeness of the current statement. No existing bits will be + cleared, but new bits may be set. + + @param flags A binary combination of zero or more bits, (1<<flag) + where flag is a member of enum_binlog_stmt_unsafe. + */ + inline void set_stmt_unsafe_flags(uint32 flags) { + DBUG_ENTER("set_stmt_unsafe_flags"); + DBUG_ASSERT((flags & ~BINLOG_STMT_UNSAFE_ALL_FLAGS) == 0); + binlog_stmt_flags|= flags; + DBUG_VOID_RETURN; } + /** + Return a binary combination of all unsafe warnings for the + statement. If the statement has been marked as unsafe by the + 'flag' member of enum_binlog_stmt_unsafe, then the return value + from this function has bit (1<<flag) set to 1. + */ + inline uint32 get_stmt_unsafe_flags() const { + DBUG_ENTER("get_stmt_unsafe_flags"); + DBUG_RETURN(binlog_stmt_flags & BINLOG_STMT_UNSAFE_ALL_FLAGS); + } + + /** + Mark the current statement as safe; i.e., clear all bits in + binlog_stmt_flags that correspond to elements of + enum_binlog_stmt_unsafe. + */ inline void clear_stmt_unsafe() { - binlog_stmt_flags&= ~(1U << BINLOG_STMT_FLAG_UNSAFE); + DBUG_ENTER("clear_stmt_unsafe"); + binlog_stmt_flags&= ~BINLOG_STMT_UNSAFE_ALL_FLAGS; + DBUG_VOID_RETURN; + } + + /** + Determine if this statement is a row injection. + + @retval 0 if the statement is not a row injection + @retval nonzero if the statement is a row injection + */ + inline bool is_stmt_row_injection() const { + return binlog_stmt_flags & + (1U << (BINLOG_STMT_UNSAFE_COUNT + BINLOG_STMT_TYPE_ROW_INJECTION)); + } + + /** + Flag the statement as a row injection. A row injection is either + a BINLOG statement, or a row event in the relay log executed by + the slave SQL thread. + */ + inline void set_stmt_row_injection() { + DBUG_ENTER("set_stmt_row_injection"); + binlog_stmt_flags|= + (1U << (BINLOG_STMT_UNSAFE_COUNT + BINLOG_STMT_TYPE_ROW_INJECTION)); + DBUG_VOID_RETURN; } /** @@ -1081,16 +1238,37 @@ public: { return sroutines_list.elements != 0; } private: - enum enum_binlog_stmt_flag { - BINLOG_STMT_FLAG_UNSAFE, - BINLOG_STMT_FLAG_COUNT + + /** + Enumeration listing special types of statements. + + Currently, the only possible type is ROW_INJECTION. + */ + enum enum_binlog_stmt_type { + /** + The statement is a row injection (i.e., either a BINLOG + statement or a row event executed by the slave SQL thread). + */ + BINLOG_STMT_TYPE_ROW_INJECTION = 0, + + /** The last element of this enumeration type. */ + BINLOG_STMT_TYPE_COUNT }; - /* - Tells if the parsing stage detected properties of the statement, - for example: that some items require row-based binlogging to give - a reliable binlog/replication, or if we will use stored functions - or triggers which themselves need require row-based binlogging. + /** + Bit field indicating the type of statement. + + There are two groups of bits: + + - The low BINLOG_STMT_UNSAFE_COUNT bits indicate the types of + unsafeness that the current statement has. + + - The next BINLOG_STMT_TYPE_COUNT bits indicate if the statement + is of some special type. + + This must be a member of LEX, not of THD: each stored procedure + needs to remember its unsafeness state between calls and each + stored procedure has its own LEX object (but no own THD object). */ uint32 binlog_stmt_flags; }; @@ -1414,6 +1592,17 @@ public: /** Interface with bison, value of the last token parsed. */ LEX_YYSTYPE yylval; + /** + LALR(2) resolution, look ahead token. + Value of the next token to return, if any, + or -1, if no token was parsed in advance. + Note: 0 is a legal token, and represents YYEOF. + */ + int lookahead_token; + + /** LALR(2) resolution, value of the look ahead token.*/ + LEX_YYSTYPE lookahead_yylval; + private: /** Pointer to the current position in the raw input stream. */ const char *m_ptr; @@ -1716,7 +1905,9 @@ struct LEX: public Query_tables_list uint profile_options; uint uint_geom_type; uint grant, grant_tot_col, which_columns; - uint fk_delete_opt, fk_update_opt, fk_match_option; + enum Foreign_key::fk_match_opt fk_match_option; + enum Foreign_key::fk_option fk_update_opt; + enum Foreign_key::fk_option fk_delete_opt; uint slave_thd_opt, start_transaction_opt; int nest_level; /* diff --git a/sql/sql_list.h b/sql/sql_list.h index 74f4cc0ec0d..e1bf05fff23 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -458,7 +458,7 @@ struct ilink struct ilink **prev,*next; static void *operator new(size_t size) throw () { - return (void*)my_malloc((uint)size, MYF(MY_WME | MY_FAE)); + return (void*)my_malloc((uint)size, MYF(MY_WME | MY_FAE | ME_FATALERROR)); } static void operator delete(void* ptr_arg, size_t size) { diff --git a/sql/sql_load.cc b/sql/sql_load.cc index b5fb92110ec..b8ba16f2fb1 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright (C) 2000-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -341,7 +341,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, MY_RETURN_REAL_PATH); #if !defined(__WIN__) && ! defined(__NETWARE__) MY_STAT stat_info; - if (!my_stat(name,&stat_info,MYF(MY_WME))) + if (!mysql_file_stat(key_file_load, name, &stat_info, MYF(MY_WME))) DBUG_RETURN(TRUE); // if we are not in slave thread, the file must be: @@ -394,7 +394,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, } } - if ((file=my_open(name,O_RDONLY,MYF(MY_WME))) < 0) + if ((file= mysql_file_open(key_file_load, + name, O_RDONLY, MYF(MY_WME))) < 0) DBUG_RETURN(TRUE); } @@ -412,8 +413,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, info.escape_char, read_file_from_client, is_fifo); if (read_info.error) { - if (file >= 0) - my_close(file,MYF(0)); // no files in net reading + if (file >= 0) + mysql_file_close(file, MYF(0)); // no files in net reading DBUG_RETURN(TRUE); // Can't allocate buffers } @@ -484,7 +485,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table->next_number_field=0; } if (file >= 0) - my_close(file,MYF(0)); + mysql_file_close(file, MYF(0)); free_blobs(table); /* if pack_blob was used */ table->copy_blobs=0; thd->count_cuted_fields= CHECK_FIELD_IGNORE; @@ -580,8 +581,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, version for the binary log to mark that table maps are invalid after this point. */ - if (thd->current_stmt_binlog_row_based) - error= thd->binlog_flush_pending_rows_event(true); + if (thd->is_current_stmt_binlog_format_row()) + error= thd->binlog_flush_pending_rows_event(TRUE, transactional_table); else { /* @@ -735,7 +736,7 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex, (uint) ((char*) fname_end - (char*) thd->query()), (duplicates == DUP_REPLACE) ? LOAD_DUP_REPLACE : (ignore ? LOAD_DUP_IGNORE : LOAD_DUP_ERROR), - transactional_table, FALSE, errcode); + transactional_table, FALSE, FALSE, errcode); e.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F; return mysql_bin_log.write(&e); } diff --git a/sql/sql_manager.cc b/sql/sql_manager.cc index b082f65bfb9..4f3e4e1c6d1 100644 --- a/sql/sql_manager.cc +++ b/sql/sql_manager.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000, 2002, 2005 MySQL AB +/* Copyright (C) 2000, 2002, 2005 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,8 +28,8 @@ static bool volatile manager_thread_in_use; static bool abort_manager; pthread_t manager_thread; -pthread_mutex_t LOCK_manager; -pthread_cond_t COND_manager; +mysql_mutex_t LOCK_manager; +mysql_cond_t COND_manager; struct handler_cb { struct handler_cb *next; @@ -42,7 +42,7 @@ bool mysql_manager_submit(void (*action)()) { bool result= FALSE; struct handler_cb * volatile *cb; - pthread_mutex_lock(&LOCK_manager); + mysql_mutex_lock(&LOCK_manager); cb= &cb_list; while (*cb && (*cb)->action != action) cb= &(*cb)->next; @@ -57,7 +57,7 @@ bool mysql_manager_submit(void (*action)()) (*cb)->action= action; } } - pthread_mutex_unlock(&LOCK_manager); + mysql_mutex_unlock(&LOCK_manager); return result; } @@ -76,7 +76,7 @@ pthread_handler_t handle_manager(void *arg __attribute__((unused))) for (;;) { - pthread_mutex_lock(&LOCK_manager); + mysql_mutex_lock(&LOCK_manager); /* XXX: This will need to be made more general to handle different * polling needs. */ if (flush_time) @@ -87,19 +87,19 @@ pthread_handler_t handle_manager(void *arg __attribute__((unused))) reset_flush_time = FALSE; } while ((!error || error == EINTR) && !abort_manager) - error= pthread_cond_timedwait(&COND_manager, &LOCK_manager, &abstime); + error= mysql_cond_timedwait(&COND_manager, &LOCK_manager, &abstime); } else { while ((!error || error == EINTR) && !abort_manager) - error= pthread_cond_wait(&COND_manager, &LOCK_manager); + error= mysql_cond_wait(&COND_manager, &LOCK_manager); } if (cb == NULL) { cb= cb_list; cb_list= NULL; } - pthread_mutex_unlock(&LOCK_manager); + mysql_mutex_unlock(&LOCK_manager); if (abort_manager) break; @@ -134,7 +134,8 @@ void start_handle_manager() if (flush_time && flush_time != ~(ulong) 0L) { pthread_t hThread; - if (pthread_create(&hThread,&connection_attrib,handle_manager,0)) + if (mysql_thread_create(key_thread_handle_manager, + &hThread, &connection_attrib, handle_manager, 0)) sql_print_warning("Can't create handle_manager thread"); } DBUG_VOID_RETURN; @@ -146,14 +147,14 @@ void stop_handle_manager() { DBUG_ENTER("stop_handle_manager"); abort_manager = true; - pthread_mutex_lock(&LOCK_manager); + mysql_mutex_lock(&LOCK_manager); if (manager_thread_in_use) { DBUG_PRINT("quit", ("initiate shutdown of handle manager thread: 0x%lx", (ulong)manager_thread)); - pthread_cond_signal(&COND_manager); + mysql_cond_signal(&COND_manager); } - pthread_mutex_unlock(&LOCK_manager); + mysql_mutex_unlock(&LOCK_manager); DBUG_VOID_RETURN; } diff --git a/sql/sql_map.cc b/sql/sql_map.cc index 55f9b08d3fe..e4e85c51d17 100644 --- a/sql/sql_map.cc +++ b/sql/sql_map.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2001, 2004-2005 MySQL AB +/* Copyright (C) 2000-2001, 2004-2005 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -32,10 +32,10 @@ mapped_files::mapped_files(const char * filename,uchar *magic,uint magic_length) error=0; map=0; size=0; - if ((file=my_open(name,O_RDONLY,MYF(MY_WME))) >= 0) + if ((file= mysql_file_open(key_file_map, name, O_RDONLY, MYF(MY_WME))) >= 0) { struct stat stat_buf; - if (!fstat(file,&stat_buf)) + if (!fstat(file, &stat_buf)) { if (!(map=(uchar*) my_mmap(0,(size_t)(size= stat_buf.st_size),PROT_READ, MAP_SHARED | MAP_NORESERVE,file, @@ -48,12 +48,12 @@ mapped_files::mapped_files(const char * filename,uchar *magic,uint magic_length) if (map && memcmp(map,magic,magic_length)) { my_error(ER_WRONG_MAGIC, MYF(0), name); - VOID(my_munmap((char*) map,(size_t)size)); + (void) my_munmap((char*) map,(size_t)size); map=0; } if (!map) { - VOID(my_close(file,MYF(0))); + (void) mysql_file_close(file, MYF(0)); file= -1; } } @@ -66,8 +66,8 @@ mapped_files::~mapped_files() #ifdef HAVE_MMAP if (file >= 0) { - VOID(my_munmap((char*) map,(size_t)size)); - VOID(my_close(file,MYF(0))); + (void) my_munmap((char*) map,(size_t)size); + (void) mysql_file_close(file, MYF(0)); file= -1; map=0; } my_free(name,MYF(0)); @@ -85,7 +85,7 @@ static I_List<mapped_files> maps_in_use; mapped_files *map_file(const char * name,uchar *magic,uint magic_length) { #ifdef HAVE_MMAP - VOID(pthread_mutex_lock(&LOCK_mapped_file)); + mysql_mutex_lock(&LOCK_mapped_file); I_List_iterator<mapped_files> list(maps_in_use); mapped_files *map; char path[FN_REFLEN]; @@ -108,7 +108,7 @@ mapped_files *map_file(const char * name,uchar *magic,uint magic_length) if (!map->map) my_error(ER_NO_FILE_MAPPING, MYF(0), path, map->error); } - VOID(pthread_mutex_unlock(&LOCK_mapped_file)); + mysql_mutex_unlock(&LOCK_mapped_file); return map; #else return NULL; @@ -122,10 +122,10 @@ mapped_files *map_file(const char * name,uchar *magic,uint magic_length) void unmap_file(mapped_files *map) { #ifdef HAVE_MMAP - VOID(pthread_mutex_lock(&LOCK_mapped_file)); + mysql_mutex_lock(&LOCK_mapped_file); if (!map->use_count--) delete map; - VOID(pthread_mutex_unlock(&LOCK_mapped_file)); + mysql_mutex_unlock(&LOCK_mapped_file); #endif } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 96e4fb05988..73ed2e3f017 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,8 +28,10 @@ #include "sp_cache.h" #include "events.h" #include "sql_trigger.h" +#include "sql_audit.h" #include "sql_prepare.h" #include "probes_mysql.h" +#include "set_var.h" /** @defgroup Runtime_Environment Runtime Environment @@ -134,7 +136,7 @@ static bool xa_trans_rollback(THD *thd) bool status= test(ha_rollback(thd)); - thd->options&= ~(ulong) OPTION_BEGIN; + thd->variables.option_bits&= ~(ulong) OPTION_BEGIN; thd->transaction.all.modified_non_trans_table= FALSE; thd->server_status&= ~SERVER_STATUS_IN_TRANS; xid_cache_delete(&thd->transaction.xid_state); @@ -169,18 +171,18 @@ bool end_active_trans(THD *thd) xa_state_names[thd->transaction.xid_state.xa_state]); DBUG_RETURN(1); } - if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN | + if (thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN | OPTION_TABLE_LOCK)) { - DBUG_PRINT("info",("options: 0x%llx", thd->options)); + DBUG_PRINT("info",("options: 0x%llx", thd->variables.option_bits)); /* Safety if one did "drop table" on locked tables */ if (!thd->locked_tables) - thd->options&= ~OPTION_TABLE_LOCK; + thd->variables.option_bits&= ~OPTION_TABLE_LOCK; thd->server_status&= ~SERVER_STATUS_IN_TRANS; if (ha_commit(thd)) error=1; } - thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); + thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); thd->transaction.all.modified_non_trans_table= FALSE; DBUG_RETURN(error); } @@ -204,7 +206,7 @@ bool begin_trans(THD *thd) error= -1; else { - thd->options|= OPTION_BEGIN; + thd->variables.option_bits|= OPTION_BEGIN; thd->server_status|= SERVER_STATUS_IN_TRANS; } return error; @@ -263,8 +265,6 @@ void init_update_queries(void) sql_command_flags[SQLCOM_CREATE_DB]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_DROP_DB]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_RENAME_TABLE]= CF_CHANGES_DATA; - sql_command_flags[SQLCOM_BACKUP_TABLE]= CF_CHANGES_DATA; - sql_command_flags[SQLCOM_RESTORE_TABLE]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_DROP_INDEX]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_CREATE_VIEW]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE; sql_command_flags[SQLCOM_DROP_VIEW]= CF_CHANGES_DATA; @@ -376,25 +376,34 @@ bool is_log_table_write_query(enum enum_sql_command command) return (sql_command_flags[command] & CF_WRITE_LOGS_COMMAND) != 0; } -void execute_init_command(THD *thd, sys_var_str *init_command_var, - rw_lock_t *var_mutex) +void execute_init_command(THD *thd, LEX_STRING *init_command, + mysql_rwlock_t *var_lock) { Vio* save_vio; ulong save_client_capabilities; + mysql_rwlock_rdlock(var_lock); + if (!init_command->length) + { + mysql_rwlock_unlock(var_lock); + return; + } + + /* + copy the value under a lock, and release the lock. + init_command has to be executed without a lock held, + as it may try to change itself + */ + size_t len= init_command->length; + char *buf= thd->strmake(init_command->str, len); + mysql_rwlock_unlock(var_lock); + #if defined(ENABLED_PROFILING) thd->profiling.start_new_query(); - thd->profiling.set_query_source(init_command_var->value, - init_command_var->value_length); + thd->profiling.set_query_source(buf, len); #endif thd_proc_info(thd, "Execution of init_command"); - /* - We need to lock init_command_var because - during execution of init_command_var query - values of init_command_var can't be changed - */ - rw_rdlock(var_mutex); save_client_capabilities= thd->client_capabilities; thd->client_capabilities|= CLIENT_MULTI_QUERIES; /* @@ -403,10 +412,7 @@ void execute_init_command(THD *thd, sys_var_str *init_command_var, */ save_vio= thd->net.vio; thd->net.vio= 0; - dispatch_command(COM_QUERY, thd, - init_command_var->value, - init_command_var->value_length); - rw_unlock(var_mutex); + dispatch_command(COM_QUERY, thd, buf, len); thd->client_capabilities= save_client_capabilities; thd->net.vio= save_vio; @@ -418,7 +424,7 @@ void execute_init_command(THD *thd, sys_var_str *init_command_var, static void handle_bootstrap_impl(THD *thd) { - FILE *file=bootstrap_file; + MYSQL_FILE *file= bootstrap_file; char *buff; const char* found_semicolon= NULL; @@ -429,9 +435,6 @@ static void handle_bootstrap_impl(THD *thd) thd->thread_stack= (char*) &thd; #endif /* EMBEDDED_LIBRARY */ - if (thd->variables.max_join_size == HA_POS_ERROR) - thd->options |= OPTION_BIG_SELECTS; - thd_proc_info(thd, 0); thd->version=refresh_version; thd->security_ctx->priv_user= @@ -446,12 +449,12 @@ static void handle_bootstrap_impl(THD *thd) buff= (char*) thd->net.buff; thd->init_for_queries(); - while (fgets(buff, thd->net.max_packet, file)) + while (mysql_file_fgets(buff, thd->net.max_packet, file)) { - char *query, *res; - /* strlen() can't be deleted because fgets() doesn't return length */ + char *query; + /* strlen() can't be deleted because mysql_file_fgets() doesn't return length */ ulong length= (ulong) strlen(buff); - while (buff[length-1] != '\n' && !feof(file)) + while (buff[length-1] != '\n' && !mysql_file_feof(file)) { /* We got only a part of the current string. Will try to increase @@ -465,7 +468,7 @@ static void handle_bootstrap_impl(THD *thd) break; } buff= (char*) thd->net.buff; - res= fgets(buff + length, thd->net.max_packet - length, file); + mysql_file_fgets(buff + length, thd->net.max_packet - length, file); length+= (ulong) strlen(buff + length); /* purecov: end */ } @@ -484,7 +487,7 @@ static void handle_bootstrap_impl(THD *thd) query= (char *) thd->memdup_w_gap(buff, length + 1, thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE); - thd->set_query(query, length); + thd->set_query_and_id(query, length, next_query_id()); DBUG_PRINT("query",("%-.4096s",thd->query())); #if defined(ENABLED_PROFILING) thd->profiling.start_new_query(); @@ -495,7 +498,6 @@ static void handle_bootstrap_impl(THD *thd) We don't need to obtain LOCK_thread_count here because in bootstrap mode we have only one thread. */ - thd->query_id=next_query_id(); thd->set_time(); mysql_parse(thd, thd->query(), length, & found_semicolon); close_thread_tables(thd); // Free tables @@ -511,9 +513,7 @@ static void handle_bootstrap_impl(THD *thd) break; free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); -#ifdef USING_TRANSACTIONS free_root(&thd->transaction.mem_root,MYF(MY_KEEP_PREALLOC)); -#endif } DBUG_VOID_RETURN; @@ -530,6 +530,14 @@ pthread_handler_t handle_bootstrap(void *arg) { THD *thd=(THD*) arg; + mysql_thread_set_psi_id(thd->thread_id); + + do_handle_bootstrap(thd); + return 0; +} + +void do_handle_bootstrap(THD *thd) +{ /* The following must be called before DBUG_ENTER */ thd->thread_stack= (char*) &thd; if (my_thread_init() || thd->store_globals()) @@ -549,16 +557,16 @@ end: delete thd; #ifndef EMBEDDED_LIBRARY - (void) pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thread_count--; in_bootstrap= FALSE; - (void) pthread_cond_broadcast(&COND_thread_count); - (void) pthread_mutex_unlock(&LOCK_thread_count); + mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); my_thread_end(); pthread_exit(0); #endif - return 0; + return; } @@ -629,72 +637,6 @@ void cleanup_items(Item *item) } /** - Handle COM_TABLE_DUMP command. - - @param thd thread handle - @param db database name or an empty string. If empty, - the current database of the connection is used - @param tbl_name name of the table to dump - - @note - This function is written to handle one specific command only. - - @retval - 0 success - @retval - 1 error, the error message is set in THD -*/ - -static -int mysql_table_dump(THD *thd, LEX_STRING *db, char *tbl_name) -{ - TABLE* table; - TABLE_LIST* table_list; - int error = 0; - DBUG_ENTER("mysql_table_dump"); - if (db->length == 0) - { - db->str= thd->db; /* purecov: inspected */ - db->length= thd->db_length; /* purecov: inspected */ - } - if (!(table_list = (TABLE_LIST*) thd->calloc(sizeof(TABLE_LIST)))) - DBUG_RETURN(1); // out of memory - table_list->db= db->str; - table_list->table_name= table_list->alias= tbl_name; - table_list->lock_type= TL_READ_NO_INSERT; - table_list->prev_global= &table_list; // can be removed after merge with 4.1 - - if (check_db_name(db)) - { - /* purecov: begin inspected */ - my_error(ER_WRONG_DB_NAME ,MYF(0), db->str ? db->str : "NULL"); - goto err; - /* purecov: end */ - } - if (lower_case_table_names) - my_casedn_str(files_charset_info, tbl_name); - - if (!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT, 0))) - DBUG_RETURN(1); - - if (check_one_table_access(thd, SELECT_ACL, table_list)) - goto err; - thd->free_list = 0; - thd->set_query(tbl_name, (uint) strlen(tbl_name)); - if ((error = mysqld_dump_create_info(thd, table_list, -1))) - { - my_error(ER_GET_ERRNO, MYF(0), my_errno); - goto err; - } - net_flush(&thd->net); - if ((error= table->file->dump(thd,-1))) - my_error(ER_GET_ERRNO, MYF(0), error); - -err: - DBUG_RETURN(error); -} - -/** Ends the current transaction and (maybe) begin the next. @param thd Current thread @@ -730,7 +672,7 @@ int end_trans(THD *thd, enum enum_mysql_completiontype completion) */ thd->server_status&= ~SERVER_STATUS_IN_TRANS; res= ha_commit(thd); - thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); + thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); thd->transaction.all.modified_non_trans_table= FALSE; break; case COMMIT_RELEASE: @@ -748,7 +690,7 @@ int end_trans(THD *thd, enum enum_mysql_completiontype completion) thd->server_status&= ~SERVER_STATUS_IN_TRANS; if (ha_rollback(thd)) res= -1; - thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); + thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); thd->transaction.all.modified_non_trans_table= FALSE; if (!res && (completion == ROLLBACK_AND_CHAIN)) res= begin_trans(thd); @@ -801,7 +743,7 @@ bool do_command(THD *thd) This thread will do a blocking read from the client which will be interrupted when the next command is received from the client, the connection is closed or "net_wait_timeout" - number of seconds has passed + number of seconds has passed. */ my_net_set_read_timeout(net, thd->variables.net_wait_timeout); @@ -814,11 +756,7 @@ bool do_command(THD *thd) net_new_transaction(net); - packet_length= my_net_read(net); -#if defined(ENABLED_PROFILING) - thd->profiling.start_new_query(); -#endif - if (packet_length == packet_error) + if ((packet_length= my_net_read(net)) == packet_error) { DBUG_PRINT("info",("Got error %d reading command from socket %s", net->error, @@ -875,9 +813,6 @@ bool do_command(THD *thd) return_value= dispatch_command(command, thd, packet+1, (uint) (packet_length-1)); out: -#if defined(ENABLED_PROFILING) - thd->profiling.finish_current_query(); -#endif DBUG_RETURN(return_value); } #endif /* EMBEDDED_LIBRARY */ @@ -979,6 +914,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, DBUG_ENTER("dispatch_command"); DBUG_PRINT("info",("packet: '%*.s'; command: %d", packet_length, packet, command)); +#if defined(ENABLED_PROFILING) + thd->profiling.start_new_query(); +#endif MYSQL_COMMAND_START(thd->thread_id, command, thd->security_ctx->priv_user, (char *) thd->security_ctx->host_or_ip); @@ -991,29 +929,29 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->enable_slow_log= TRUE; thd->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */ thd->set_time(); - VOID(pthread_mutex_lock(&LOCK_thread_count)); - thd->query_id= global_query_id; - - switch( command ) { - /* Ignore these statements. */ - case COM_STATISTICS: - case COM_PING: - break; - /* Only increase id on these statements but don't count them. */ - case COM_STMT_PREPARE: - case COM_STMT_CLOSE: - case COM_STMT_RESET: - next_query_id(); - break; - /* Increase id and count all other statements. */ - default: - statistic_increment(thd->status_var.questions, &LOCK_status); - next_query_id(); + { + query_id_t query_id; + switch( command ) { + /* Ignore these statements. */ + case COM_STATISTICS: + case COM_PING: + query_id= get_query_id(); + break; + /* Only increase id on these statements but don't count them. */ + case COM_STMT_PREPARE: + case COM_STMT_CLOSE: + case COM_STMT_RESET: + query_id= next_query_id() - 1; + break; + /* Increase id and count all other statements. */ + default: + statistic_increment(thd->status_var.questions, &LOCK_status); + query_id= next_query_id() - 1; + } + thd->set_query_id(query_id); } - - thread_running++; + inc_thread_running(); /* TODO: set thd->lex->sql_command to SQLCOM_END here */ - VOID(pthread_mutex_unlock(&LOCK_thread_count)); /** Clear the set of flags that are expected to be cleared at the @@ -1042,40 +980,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; } #endif - case COM_TABLE_DUMP: - { - char *tbl_name; - LEX_STRING db; - /* Safe because there is always a trailing \0 at the end of the packet */ - uint db_len= *(uchar*) packet; - if (db_len + 1 > packet_length || db_len > NAME_LEN) - { - my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); - break; - } - /* Safe because there is always a trailing \0 at the end of the packet */ - uint tbl_len= *(uchar*) (packet + db_len + 1); - if (db_len + tbl_len + 2 > packet_length || tbl_len > NAME_LEN) - { - my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); - break; - } - - status_var_increment(thd->status_var.com_other); - thd->enable_slow_log= opt_log_slow_admin_statements; - db.str= (char*) thd->alloc(db_len + tbl_len + 2); - if (!db.str) - { - my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); - break; - } - db.length= db_len; - tbl_name= strmake(db.str, packet + 1, db_len)+1; - strmake(tbl_name, packet + db_len + 2, tbl_len); - if (mysql_table_dump(thd, &db, tbl_name) == 0) - thd->stmt_da->disable_status(); - break; - } case COM_CHANGE_USER: { status_var_increment(thd->status_var.com_other); @@ -1236,9 +1140,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->profiling.set_query_source(thd->query(), thd->query_length()); #endif - if (!(specialflag & SPECIAL_NO_PRIOR)) - my_pthread_setprio(pthread_self(),QUERY_PRIOR); - mysql_parse(thd, thd->query(), thd->query_length(), &end_of_stmt); while (!thd->killed && (end_of_stmt != NULL) && ! thd->is_error()) @@ -1278,21 +1179,16 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->security_ctx->priv_user, (char *) thd->security_ctx->host_or_ip); - thd->set_query(beginning_of_next_stmt, length); - VOID(pthread_mutex_lock(&LOCK_thread_count)); + thd->set_query_and_id(beginning_of_next_stmt, length, next_query_id()); /* Count each statement from the client. */ statistic_increment(thd->status_var.questions, &LOCK_status); - thd->query_id= next_query_id(); thd->set_time(); /* Reset the query start time. */ /* TODO: set thd->lex->sql_command to SQLCOM_END here */ - VOID(pthread_mutex_unlock(&LOCK_thread_count)); mysql_parse(thd, beginning_of_next_stmt, length, &end_of_stmt); } - if (!(specialflag & SPECIAL_NO_PRIOR)) - my_pthread_setprio(pthread_self(),WAIT_PRIOR); DBUG_PRINT("info",("query ready")); break; } @@ -1324,7 +1220,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, table_list.alias= table_list.table_name= conv_name.str; packet= arg_end + 1; - if (is_schema_db(table_list.db, table_list.db_length)) + if (is_infoschema_db(table_list.db, table_list.db_length)) { ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, table_list.alias); if (schema_table) @@ -1339,8 +1235,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (lower_case_table_names) my_casedn_str(files_charset_info, table_list.table_name); - if (check_access(thd,SELECT_ACL,table_list.db,&table_list.grant.privilege, - 0, 0, test(table_list.schema_table))) + if (check_access(thd, SELECT_ACL, table_list.db, + &table_list.grant.privilege, + &table_list.grant.m_internal, + 0, 0)) break; if (check_grant(thd, SELECT_ACL, &table_list, TRUE, UINT_MAX, FALSE)) break; @@ -1370,55 +1268,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->stmt_da->disable_status(); // Don't send anything back error=TRUE; // End server break; - -#ifdef REMOVED - case COM_CREATE_DB: // QQ: To be removed - { - LEX_STRING db, alias; - HA_CREATE_INFO create_info; - - status_var_increment(thd->status_var.com_stat[SQLCOM_CREATE_DB]); - if (thd->make_lex_string(&db, packet, packet_length, FALSE) || - thd->make_lex_string(&alias, db.str, db.length, FALSE) || - check_db_name(&db)) - { - my_error(ER_WRONG_DB_NAME, MYF(0), db.str ? db.str : "NULL"); - break; - } - if (check_access(thd, CREATE_ACL, db.str , 0, 1, 0, - is_schema_db(db.str, db.length))) - break; - general_log_print(thd, command, "%.*s", db.length, db.str); - bzero(&create_info, sizeof(create_info)); - mysql_create_db(thd, (lower_case_table_names == 2 ? alias.str : db.str), - &create_info, 0); - break; - } - case COM_DROP_DB: // QQ: To be removed - { - status_var_increment(thd->status_var.com_stat[SQLCOM_DROP_DB]); - LEX_STRING db; - - if (thd->make_lex_string(&db, packet, packet_length, FALSE) || - check_db_name(&db)) - { - my_error(ER_WRONG_DB_NAME, MYF(0), db.str ? db.str : "NULL"); - break; - } - if (check_access(thd, DROP_ACL, db.str, 0, 1, 0, - is_schema_db(db.str, db.length))) - break; - if (thd->locked_tables || thd->active_transaction()) - { - my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, - ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); - break; - } - general_log_write(thd, command, "%.*s", db.length, db.str); - mysql_rm_db(thd, db.str, 0, 0); - break; - } -#endif #ifndef EMBEDDED_LIBRARY case COM_BINLOG_DUMP: { @@ -1555,8 +1404,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd, } #endif #ifndef EMBEDDED_LIBRARY - VOID(my_net_write(net, (uchar*) buff, length)); - VOID(net_flush(net)); + (void) my_net_write(net, (uchar*) buff, length); + (void) net_flush(net); thd->stmt_da->disable_status(); #endif break; @@ -1646,18 +1495,22 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* Free tables */ close_thread_tables(thd); + if (!thd->is_error() && !thd->killed_errno()) + mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_RESULT, 0, 0); + log_slow_statement(thd); thd_proc_info(thd, "cleaning up"); thd->set_query(NULL, 0); thd->command=COM_SLEEP; - VOID(pthread_mutex_lock(&LOCK_thread_count)); // For process list - thread_running--; - VOID(pthread_mutex_unlock(&LOCK_thread_count)); + dec_thread_running(); thd_proc_info(thd, 0); thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); +#if defined(ENABLED_PROFILING) + thd->profiling.finish_current_query(); +#endif if (MYSQL_QUERY_DONE_ENABLED() || MYSQL_COMMAND_DONE_ENABLED()) { int res; @@ -2013,8 +1866,6 @@ bool sp_process_definer(THD *thd) TODO: this is workaround. right way will be move invalidating in the unlock procedure. - TODO: use check_change_password() - - JOIN is not supported yet. TODO - - SUSPEND and FOR MIGRATE are not supported yet. TODO @retval FALSE OK @@ -2075,7 +1926,6 @@ mysql_execute_command(THD *thd) A better approach would be to reset this for any commands that is not a SHOW command or a select that only access local variables, but for now this is probably good enough. - Don't reset warnings when executing a stored routine. */ if ((sql_command_flags[lex->sql_command] & CF_DIAGNOSTIC_STMT) != 0) thd->warning_info->set_read_only(TRUE); @@ -2242,11 +2092,11 @@ mysql_execute_command(THD *thd) restore status variables, as we don't want 'show status' to cause changes */ - pthread_mutex_lock(&LOCK_status); + mysql_mutex_lock(&LOCK_status); add_diff_to_status(&global_status_var, &thd->status_var, &old_status_var); thd->status_var= old_status_var; - pthread_mutex_unlock(&LOCK_status); + mysql_mutex_unlock(&LOCK_status); break; } case SQLCOM_SHOW_DATABASES: @@ -2278,7 +2128,7 @@ mysql_execute_command(THD *thd) privileges_requested, all_tables, FALSE, UINT_MAX, FALSE); else - res= check_access(thd, privileges_requested, any_db, 0, 0, 0, UINT_MAX); + res= check_access(thd, privileges_requested, any_db, NULL, NULL, 0, 0); if (res) break; @@ -2414,36 +2264,13 @@ case SQLCOM_PREPARE: } #endif - case SQLCOM_BACKUP_TABLE: - { - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE) - || check_global_access(thd, FILE_ACL)) - goto error; /* purecov: inspected */ - thd->enable_slow_log= opt_log_slow_admin_statements; - res = mysql_backup_table(thd, first_table); - select_lex->table_list.first= (uchar*) first_table; - lex->query_tables=all_tables; - break; - } - case SQLCOM_RESTORE_TABLE: - { - DBUG_ASSERT(first_table == all_tables && first_table != 0); - if (check_table_access(thd, INSERT_ACL, all_tables, FALSE, UINT_MAX, FALSE) - || check_global_access(thd, FILE_ACL)) - goto error; /* purecov: inspected */ - thd->enable_slow_log= opt_log_slow_admin_statements; - res = mysql_restore_table(thd, first_table); - select_lex->table_list.first= (uchar*) first_table; - lex->query_tables=all_tables; - break; - } case SQLCOM_ASSIGN_TO_KEYCACHE: { DBUG_ASSERT(first_table == all_tables && first_table != 0); if (check_access(thd, INDEX_ACL, first_table->db, - &first_table->grant.privilege, 0, 0, - test(first_table->schema_table))) + &first_table->grant.privilege, + &first_table->grant.m_internal, + 0, 0)) goto error; res= mysql_assign_to_keycache(thd, first_table, &lex->ident); break; @@ -2452,8 +2279,9 @@ case SQLCOM_PREPARE: { DBUG_ASSERT(first_table == all_tables && first_table != 0); if (check_access(thd, INDEX_ACL, first_table->db, - &first_table->grant.privilege, 0, 0, - test(first_table->schema_table))) + &first_table->grant.privilege, + &first_table->grant.m_internal, + 0, 0)) goto error; res = mysql_preload_keys(thd, first_table); break; @@ -2463,9 +2291,9 @@ case SQLCOM_PREPARE: { if (check_global_access(thd, SUPER_ACL)) goto error; - pthread_mutex_lock(&LOCK_active_mi); + mysql_mutex_lock(&LOCK_active_mi); res = change_master(thd,active_mi); - pthread_mutex_unlock(&LOCK_active_mi); + mysql_mutex_unlock(&LOCK_active_mi); break; } case SQLCOM_SHOW_SLAVE_STAT: @@ -2473,7 +2301,7 @@ case SQLCOM_PREPARE: /* Accept one of two privileges */ if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL)) goto error; - pthread_mutex_lock(&LOCK_active_mi); + mysql_mutex_lock(&LOCK_active_mi); if (active_mi != NULL) { res = show_master_info(thd, active_mi); @@ -2484,7 +2312,7 @@ case SQLCOM_PREPARE: WARN_NO_MASTER_INFO, ER(WARN_NO_MASTER_INFO)); my_ok(thd); } - pthread_mutex_unlock(&LOCK_active_mi); + mysql_mutex_unlock(&LOCK_active_mi); break; } case SQLCOM_SHOW_MASTER_STAT: @@ -2496,13 +2324,6 @@ case SQLCOM_PREPARE: break; } - case SQLCOM_LOAD_MASTER_DATA: // sync with master - if (check_global_access(thd, SUPER_ACL)) - goto error; - if (end_active_trans(thd)) - goto error; - res = load_master_data(thd); - break; #endif /* HAVE_REPLICATION */ case SQLCOM_SHOW_ENGINE_STATUS: { @@ -2518,35 +2339,6 @@ case SQLCOM_PREPARE: res = ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_MUTEX); break; } -#ifdef HAVE_REPLICATION - case SQLCOM_LOAD_MASTER_TABLE: - { - DBUG_ASSERT(first_table == all_tables && first_table != 0); - DBUG_ASSERT(first_table->db); /* Must be set in the parser */ - - if (check_access(thd, CREATE_ACL, first_table->db, - &first_table->grant.privilege, 0, 0, - test(first_table->schema_table))) - goto error; /* purecov: inspected */ - /* Check that the first table has CREATE privilege */ - if (check_grant(thd, CREATE_ACL, all_tables, FALSE, 1, FALSE)) - goto error; - - pthread_mutex_lock(&LOCK_active_mi); - /* - fetch_master_table will send the error to the client on failure. - Give error if the table already exists. - */ - if (!fetch_master_table(thd, first_table->db, first_table->table_name, - active_mi, 0, 0)) - { - my_ok(thd); - } - pthread_mutex_unlock(&LOCK_active_mi); - break; - } -#endif /* HAVE_REPLICATION */ - case SQLCOM_CREATE_TABLE: { /* If CREATE TABLE of non-temporary table, do implicit commit */ @@ -2770,7 +2562,7 @@ case SQLCOM_PREPARE: { /* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */ if (create_info.options & HA_LEX_CREATE_TMP_TABLE) - thd->options|= OPTION_KEEP_LOG; + thd->variables.option_bits|= OPTION_KEEP_LOG; /* regular create */ if (create_info.options & HA_LEX_CREATE_TABLE_LIKE) res= mysql_create_like_table(thd, create_table, select_tables, @@ -2834,9 +2626,9 @@ end_with_restore_list: #ifdef HAVE_REPLICATION case SQLCOM_SLAVE_START: { - pthread_mutex_lock(&LOCK_active_mi); + mysql_mutex_lock(&LOCK_active_mi); start_slave(thd,active_mi,1 /* net report*/); - pthread_mutex_unlock(&LOCK_active_mi); + mysql_mutex_unlock(&LOCK_active_mi); break; } case SQLCOM_SLAVE_STOP: @@ -2860,9 +2652,9 @@ end_with_restore_list: goto error; } { - pthread_mutex_lock(&LOCK_active_mi); + mysql_mutex_lock(&LOCK_active_mi); stop_slave(thd,active_mi,1/* net report*/); - pthread_mutex_unlock(&LOCK_active_mi); + mysql_mutex_unlock(&LOCK_active_mi); break; } #endif /* HAVE_REPLICATION */ @@ -2893,10 +2685,13 @@ end_with_restore_list: /* Must be set in the parser */ DBUG_ASSERT(select_lex->db); if (check_access(thd, priv_needed, first_table->db, - &first_table->grant.privilege, 0, 0, - test(first_table->schema_table)) || - check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0, - is_schema_db(select_lex->db))|| + &first_table->grant.privilege, + &first_table->grant.m_internal, + 0, 0) || + check_access(thd, INSERT_ACL | CREATE_ACL, select_lex->db, + &priv, + NULL, /* Do not use first_table->grant with select_lex->db */ + 0, 0) || check_merge_table_access(thd, first_table->db, (TABLE_LIST *) create_info.merge_list.first)) @@ -2953,10 +2748,13 @@ end_with_restore_list: for (table= first_table; table; table= table->next_local->next_local) { if (check_access(thd, ALTER_ACL | DROP_ACL, table->db, - &table->grant.privilege,0,0, test(table->schema_table)) || - check_access(thd, INSERT_ACL | CREATE_ACL, table->next_local->db, - &table->next_local->grant.privilege, 0, 0, - test(table->next_local->schema_table))) + &table->grant.privilege, + &table->grant.m_internal, + 0, 0) || + check_access(thd, INSERT_ACL | CREATE_ACL, table->next_local->db, + &table->next_local->grant.privilege, + &table->next_local->grant.m_internal, + 0, 0)) goto error; TABLE_LIST old_list, new_list; /* @@ -3024,42 +2822,13 @@ end_with_restore_list: } else { - ulong save_priv; - /* - If it is an INFORMATION_SCHEMA table, SELECT_ACL privilege is the - only privilege allowed. For any other privilege check_access() - reports an error. That's how internal implementation protects - INFORMATION_SCHEMA from updates. - - For ordinary tables any privilege from the SHOW_CREATE_TABLE_ACLS - set is sufficient. + The fact that check_some_access() returned FALSE does not mean that + access is granted. We need to check if first_table->grant.privilege + contains any table-specific privilege. */ - - ulong check_privs= test(first_table->schema_table) ? - SELECT_ACL : SHOW_CREATE_TABLE_ACLS; - - if (check_access(thd, check_privs, first_table->db, - &save_priv, FALSE, FALSE, - test(first_table->schema_table))) - goto error; - - /* - save_priv contains any privileges actually granted by check_access - (i.e. save_priv contains global (user- and database-level) - privileges). - - The fact that check_access() returned FALSE does not mean that - access is granted. We need to check if save_priv contains any - table-specific privilege. If not, we need to check table-level - privileges. - - If there are no global privileges and no table-level privileges, - access is denied. - */ - - if (!(save_priv & (SHOW_CREATE_TABLE_ACLS)) && - !has_any_table_level_privileges(thd, SHOW_CREATE_TABLE_ACLS, first_table)) + if (check_some_access(thd, SHOW_CREATE_TABLE_ACLS, first_table) || + (first_table->grant.privilege & SHOW_CREATE_TABLE_ACLS) == 0) { my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), "SHOW", thd->security_ctx->priv_user, @@ -3079,6 +2848,7 @@ end_with_restore_list: if (check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE)) goto error; /* purecov: inspected */ + res = mysql_checksum_table(thd, first_table, &lex->check_opt); break; } @@ -3490,7 +3260,7 @@ end_with_restore_list: select_lex->where, 0, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL, (ORDER *)NULL, - (select_lex->options | thd->options | + (select_lex->options | thd->variables.option_bits | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | OPTION_SETUP_TABLES_DONE) & ~OPTION_BUFFER_RESULT, del_result, unit, select_lex); @@ -3520,7 +3290,7 @@ end_with_restore_list: else { /* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */ - thd->options|= OPTION_KEEP_LOG; + thd->variables.option_bits|= OPTION_KEEP_LOG; } /* DDL and binlog write order protected by LOCK_open */ res= mysql_rm_table(thd, first_table, lex->drop_if_exists, @@ -3553,7 +3323,7 @@ end_with_restore_list: goto error; #else { - if (check_access(thd, FILE_ACL, any_db,0,0,0,0)) + if (check_access(thd, FILE_ACL, any_db, NULL, NULL, 0, 0)) goto error; res= ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_LOGS); break; @@ -3609,11 +3379,6 @@ end_with_restore_list: if ((check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE) || open_and_lock_tables(thd, all_tables))) goto error; - if (lex->one_shot_set && not_all_support_one_shot(lex_var_list)) - { - my_error(ER_RESERVED_SYNTAX, MYF(0), "SET ONE_SHOT"); - goto error; - } if (!(res= sql_set_variables(thd, lex_var_list))) { /* @@ -3646,10 +3411,10 @@ end_with_restore_list: false, mysqldump will not work. */ unlock_locked_tables(thd); - if (thd->options & OPTION_TABLE_LOCK) + if (thd->variables.option_bits & OPTION_TABLE_LOCK) { end_active_trans(thd); - thd->options&= ~(OPTION_TABLE_LOCK); + thd->variables.option_bits&= ~OPTION_TABLE_LOCK; } if (thd->global_read_lock) unlock_global_read_lock(thd); @@ -3667,7 +3432,7 @@ end_with_restore_list: !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) goto error; thd->in_lock_tables=1; - thd->options|= OPTION_TABLE_LOCK; + thd->variables.option_bits |= OPTION_TABLE_LOCK; if (!(res= simple_open_n_lock_tables(thd, all_tables))) { @@ -3688,7 +3453,6 @@ end_with_restore_list: */ ha_autocommit_or_rollback(thd, 1); end_active_trans(thd); - thd->options&= ~(OPTION_TABLE_LOCK); } thd->in_lock_tables=0; break; @@ -3728,8 +3492,7 @@ end_with_restore_list: break; } #endif - if (check_access(thd,CREATE_ACL,lex->name.str, 0, 1, 0, - is_schema_db(lex->name.str, lex->name.length))) + if (check_access(thd, CREATE_ACL, lex->name.str, NULL, NULL, 1, 0)) break; res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name.str), &create_info, 0); @@ -3763,8 +3526,7 @@ end_with_restore_list: break; } #endif - if (check_access(thd,DROP_ACL,lex->name.str,0,1,0, - is_schema_db(lex->name.str, lex->name.length))) + if (check_access(thd, DROP_ACL, lex->name.str, NULL, NULL, 1, 0)) break; if (thd->locked_tables || thd->active_transaction()) { @@ -3798,12 +3560,9 @@ end_with_restore_list: my_error(ER_WRONG_DB_NAME, MYF(0), db->str); break; } - if (check_access(thd, ALTER_ACL, db->str, 0, 1, 0, - is_schema_db(db->str, db->length)) || - check_access(thd, DROP_ACL, db->str, 0, 1, 0, - is_schema_db(db->str, db->length)) || - check_access(thd, CREATE_ACL, db->str, 0, 1, 0, - is_schema_db(db->str, db->length))) + if (check_access(thd, ALTER_ACL, db->str, NULL, NULL, 1, 0) || + check_access(thd, DROP_ACL, db->str, NULL, NULL, 1, 0) || + check_access(thd, CREATE_ACL, db->str, NULL, NULL, 1, 0)) { res= 1; break; @@ -3846,8 +3605,7 @@ end_with_restore_list: break; } #endif - if (check_access(thd, ALTER_ACL, db->str, 0, 1, 0, - is_schema_db(db->str, db->length))) + if (check_access(thd, ALTER_ACL, db->str, NULL, NULL, 1, 0)) break; if (thd->locked_tables || thd->active_transaction()) { @@ -3932,7 +3690,7 @@ end_with_restore_list: #endif case SQLCOM_CREATE_FUNCTION: // UDF function { - if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0)) + if (check_access(thd, INSERT_ACL, "mysql", NULL, NULL, 1, 0)) break; #ifdef HAVE_DLOPEN if (!(res = mysql_create_function(thd, &lex->udf))) @@ -3946,7 +3704,7 @@ end_with_restore_list: #ifndef NO_EMBEDDED_ACCESS_CHECKS case SQLCOM_CREATE_USER: { - if (check_access(thd, INSERT_ACL, "mysql", 0, 1, 1, 0) && + if (check_access(thd, INSERT_ACL, "mysql", NULL, NULL, 1, 1) && check_global_access(thd,CREATE_USER_ACL)) break; if (end_active_trans(thd)) @@ -3958,7 +3716,7 @@ end_with_restore_list: } case SQLCOM_DROP_USER: { - if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 1, 0) && + if (check_access(thd, DELETE_ACL, "mysql", NULL, NULL, 1, 1) && check_global_access(thd,CREATE_USER_ACL)) break; if (end_active_trans(thd)) @@ -3970,7 +3728,7 @@ end_with_restore_list: } case SQLCOM_RENAME_USER: { - if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) && + if (check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 1) && check_global_access(thd,CREATE_USER_ACL)) break; if (end_active_trans(thd)) @@ -3984,7 +3742,7 @@ end_with_restore_list: { if (end_active_trans(thd)) goto error; - if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) && + if (check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 1) && check_global_access(thd,CREATE_USER_ACL)) break; /* Conditionally writes to binlog */ @@ -3999,12 +3757,10 @@ end_with_restore_list: goto error; if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL, - first_table ? first_table->db : select_lex->db, - first_table ? &first_table->grant.privilege : 0, - first_table ? 0 : 1, 0, - first_table ? (bool) first_table->schema_table : - select_lex->db ? - is_schema_db(select_lex->db) : 0)) + first_table ? first_table->db : select_lex->db, + first_table ? &first_table->grant.privilege : NULL, + first_table ? &first_table->grant.m_internal : NULL, + first_table ? 0 : 1, 0)) goto error; if (thd->security_ctx->user) // If not replication @@ -4031,7 +3787,7 @@ end_with_restore_list: // TODO: use check_change_password() if (is_acl_user(user->host.str, user->user.str) && user->password.str && - check_access(thd, UPDATE_ACL,"mysql",0,1,1,0)) + check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 1)) { my_message(ER_PASSWORD_NOT_ALLOWED, ER(ER_PASSWORD_NOT_ALLOWED), MYF(0)); @@ -4163,7 +3919,7 @@ end_with_restore_list: goto error; if ((thd->security_ctx->priv_user && !strcmp(thd->security_ctx->priv_user, grant_user->user.str)) || - !check_access(thd, SELECT_ACL, "mysql",0,1,0,0)) + !check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 0)) { res = mysql_show_grants(thd, grant_user); } @@ -4259,7 +4015,7 @@ end_with_restore_list: res= TRUE; // cannot happen else { - if (((thd->options & OPTION_KEEP_LOG) || + if (((thd->variables.option_bits & OPTION_KEEP_LOG) || thd->transaction.all.modified_non_trans_table) && !thd->slave_thread) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, @@ -4274,7 +4030,7 @@ end_with_restore_list: break; } case SQLCOM_SAVEPOINT: - if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) || + if (!(thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) || thd->in_sub_stmt) || !opt_using_transactions) my_ok(thd); else @@ -4347,9 +4103,8 @@ end_with_restore_list: goto create_sp_error; } - if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0, - is_schema_db(lex->sphead->m_db.str, - lex->sphead->m_db.length))) + if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, + NULL, NULL, 0, 0)) goto create_sp_error; if (end_active_trans(thd)) @@ -4674,7 +4429,7 @@ create_sp_error: lex->spname->m_name.length); if (udf) { - if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0, 0)) + if (check_access(thd, DELETE_ACL, "mysql", NULL, NULL, 1, 0)) goto error; if (!(res = mysql_drop_function(thd, &lex->spname->m_name))) @@ -4832,7 +4587,7 @@ create_sp_error: break; } if (thd->lex->xa_opt != XA_NONE) - { // JOIN is not supported yet. TODO + { /// @todo JOIN is not supported yet. my_error(ER_XAER_INVAL, MYF(0)); break; } @@ -4858,14 +4613,14 @@ create_sp_error: thd->transaction.xid_state.xid.set(thd->lex->xid); xid_cache_insert(&thd->transaction.xid_state); thd->transaction.all.modified_non_trans_table= FALSE; - thd->options= ((thd->options & ~(OPTION_KEEP_LOG)) | OPTION_BEGIN); + thd->variables.option_bits= ((thd->variables.option_bits & ~(OPTION_KEEP_LOG)) | OPTION_BEGIN); thd->server_status|= SERVER_STATUS_IN_TRANS; my_ok(thd); break; case SQLCOM_XA_END: /* fake it */ if (thd->lex->xa_opt != XA_NONE) - { // SUSPEND and FOR MIGRATE are not supported yet. TODO + { /// @todo SUSPEND and FOR MIGRATE are not supported yet. my_error(ER_XAER_INVAL, MYF(0)); break; } @@ -4964,7 +4719,7 @@ create_sp_error: xa_state_names[thd->transaction.xid_state.xa_state]); break; } - thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); + thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); thd->transaction.all.modified_non_trans_table= FALSE; thd->server_status&= ~SERVER_STATUS_IN_TRANS; xid_cache_delete(&thd->transaction.xid_state); @@ -5233,8 +4988,9 @@ bool check_single_table_access(THD *thd, ulong privilege, db_name= all_tables->db; if (check_access(thd, privilege, db_name, - &all_tables->grant.privilege, 0, no_errors, - test(all_tables->schema_table))) + &all_tables->grant.privilege, + &all_tables->grant.m_internal, + 0, no_errors)) goto deny; /* Show only 1 table for check_grant */ @@ -5300,17 +5056,17 @@ bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables) @param want_access The requested access privileges. @param db A pointer to the Db name. @param[out] save_priv A pointer to the granted privileges will be stored. + @param grant_internal_info A pointer to the internal grant cache. @param dont_check_global_grants True if no global grants are checked. @param no_error True if no errors should be sent to the client. - @param schema_db True if the db specified belongs to the meta data tables. 'save_priv' is used to save the User-table (global) and Db-table grants for the supplied db name. Note that we don't store db level grants if the global grants is enough to satisfy the request AND the global grants contains a SELECT grant. - A meta data table (from INFORMATION_SCHEMA) can always be accessed with - a SELECT_ACL. + For internal databases (INFORMATION_SCHEMA, PERFORMANCE_SCHEMA), + additional rules apply, see ACL_internal_schema_access. @see check_grant @@ -5322,7 +5078,8 @@ bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables) bool check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, - bool dont_check_global_grants, bool no_errors, bool schema_db) + GRANT_INTERNAL_INFO *grant_internal_info, + bool dont_check_global_grants, bool no_errors) { Security_context *sctx= thd->security_ctx; ulong db_access; @@ -5345,7 +5102,10 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, if (save_priv) *save_priv=0; else + { save_priv= &dummy; + dummy= 0; + } thd_proc_info(thd, "checking permissions"); if ((!db || !db[0]) && !thd->db && !dont_check_global_grants) @@ -5357,55 +5117,65 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, DBUG_RETURN(TRUE); /* purecov: tested */ } - if (schema_db) + if ((db != NULL) && (db != any_db)) { - /* - We don't allow any simple privileges but SELECT_ACL or CREATE_VIEW_ACL - on the information_schema database. - */ - want_access &= ~SELECT_ACL; - if (want_access & DB_ACLS) + const ACL_internal_schema_access *access; + access= get_cached_schema_access(grant_internal_info, db); + if (access) { - if (!no_errors) + switch (access->check(want_access, save_priv)) { - const char *db_name= db ? db : thd->db; - my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), - sctx->priv_user, sctx->priv_host, db_name); + case ACL_INTERNAL_ACCESS_GRANTED: + /* + All the privileges requested have been granted internally. + [out] *save_privileges= Internal privileges. + */ + DBUG_RETURN(FALSE); + case ACL_INTERNAL_ACCESS_DENIED: + if (! no_errors) + { + my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), + sctx->priv_user, sctx->priv_host, db); + } + DBUG_RETURN(TRUE); + case ACL_INTERNAL_ACCESS_CHECK_GRANT: + /* + Only some of the privilege requested have been granted internally, + proceed with the remaining bits of the request (want_access). + */ + want_access&= ~(*save_priv); + break; } - /* - Access denied; - [out] *save_privileges= 0 - */ - DBUG_RETURN(TRUE); - } - else - { - /* Access granted */ - *save_priv= SELECT_ACL; - DBUG_RETURN(FALSE); } } if ((sctx->master_access & want_access) == want_access) { - /* get access for current db */ - db_access= sctx->db_access; /* 1. If we don't have a global SELECT privilege, we have to get the database specific access rights to be able to handle queries of type UPDATE t1 SET a=1 WHERE b > 0 2. Change db access if it isn't current db which is being addressed */ - if (!(sctx->master_access & SELECT_ACL) && - (db && (!thd->db || db_is_pattern || strcmp(db,thd->db)))) - db_access=acl_get(sctx->host, sctx->ip, sctx->priv_user, db, - db_is_pattern); - - /* - The effective privileges are the union of the global privileges - and the the intersection of db- and host-privileges. - */ - *save_priv=sctx->master_access | db_access; + if (!(sctx->master_access & SELECT_ACL)) + { + if (db && (!thd->db || db_is_pattern || strcmp(db, thd->db))) + db_access= acl_get(sctx->host, sctx->ip, sctx->priv_user, db, + db_is_pattern); + else + { + /* get access for current db */ + db_access= sctx->db_access; + } + /* + The effective privileges are the union of the global privileges + and the intersection of db- and host-privileges, + plus the internal privileges. + */ + *save_priv|= sctx->master_access | db_access; + } + else + *save_priv|= sctx->master_access; DBUG_RETURN(FALSE); } if (((want_access & ~sctx->master_access) & ~DB_ACLS) || @@ -5441,10 +5211,10 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, /* Save the union of User-table and the intersection between Db-table and - Host-table privileges. + Host-table privileges, with the already saved internal privileges. */ db_access= (db_access | sctx->master_access); - *save_priv= db_access; + *save_priv|= db_access; /* We need to investigate column- and table access if all requested privileges @@ -5465,14 +5235,14 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, { /* Ok; but need to check table- and column privileges. - [out] *save_privileges is (User-priv | (Db-priv & Host-priv)) + [out] *save_privileges is (User-priv | (Db-priv & Host-priv) | Internal-priv) */ DBUG_RETURN(FALSE); } /* Access is denied; - [out] *save_privileges is (User-priv | (Db-priv & Host-priv)) + [out] *save_privileges is (User-priv | (Db-priv & Host-priv) | Internal-priv) */ DBUG_PRINT("error",("Access denied")); if (!no_errors) @@ -5488,6 +5258,18 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, static bool check_show_access(THD *thd, TABLE_LIST *table) { + /* + This is a SHOW command using an INFORMATION_SCHEMA table. + check_access() has not been called for 'table', + and SELECT is currently always granted on the I_S, so we automatically + grant SELECT on table here, to bypass a call to check_access(). + Note that not calling check_access(table) is an optimization, + which needs to be revisited if the INFORMATION_SCHEMA does + not always automatically grant SELECT but use the grant tables. + See Bug#38837 need a way to disable information_schema for security + */ + table->grant.privilege= SELECT_ACL; + switch (get_schema_table_idx(table->schema_table)) { case SCH_SCHEMATA: return (specialflag & SPECIAL_SKIP_SHOW_DB) && @@ -5504,8 +5286,7 @@ static bool check_show_access(THD *thd, TABLE_LIST *table) DBUG_ASSERT(dst_db_name); if (check_access(thd, SELECT_ACL, dst_db_name, - &thd->col_access, FALSE, FALSE, - is_schema_db(dst_db_name))) + &thd->col_access, NULL, FALSE, FALSE)) return TRUE; if (!thd->col_access && check_grant_db(thd, dst_db_name)) @@ -5529,8 +5310,9 @@ static bool check_show_access(THD *thd, TABLE_LIST *table) DBUG_ASSERT(dst_table); if (check_access(thd, SELECT_ACL, dst_table->db, - &dst_table->grant.privilege, FALSE, FALSE, - test(dst_table->schema_table))) + &dst_table->grant.privilege, + &dst_table->grant.m_internal, + FALSE, FALSE)) return TRUE; /* Access denied */ /* @@ -5611,23 +5393,6 @@ check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables, sctx= backup_ctx; /* - Always allow SELECT on schema tables. This is done by removing the - required SELECT_ACL privilege in the want_access parameter. - Disallow any other DDL or DML operation on any schema table. - */ - if (tables->schema_table) - { - want_access &= ~SELECT_ACL; - if (want_access & DB_ACLS) - { - if (!no_errors) - my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), - sctx->priv_user, sctx->priv_host, - INFORMATION_SCHEMA_NAME.str); - goto deny; - } - } - /* Register access for view underlying table. Remove SHOW_VIEW_ACL, because it will be checked during making view */ @@ -5647,18 +5412,11 @@ check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables, (int)tables->table->s->tmp_table)) continue; thd->security_ctx= sctx; - if ((sctx->master_access & want_access) == want_access && - thd->db) - tables->grant.privilege= want_access; - else if (tables->db && thd->db && strcmp(tables->db, thd->db) == 0) - { - if (check_access(thd, want_access, tables->get_db_name(), - &tables->grant.privilege, 0, no_errors, - test(tables->schema_table))) - goto deny; // Access denied - } - else if (check_access(thd, want_access, tables->get_db_name(), - &tables->grant.privilege, 0, no_errors, 0)) + + if (check_access(thd, want_access, tables->get_db_name(), + &tables->grant.privilege, + &tables->grant.m_internal, + 0, no_errors)) goto deny; } thd->security_ctx= backup_ctx; @@ -5686,14 +5444,23 @@ check_routine_access(THD *thd, ulong want_access,char *db, char *name, calculating db_access) under the assumption that it's common to give persons global right to execute all stored SP (but not necessary to create them). + Note that this effectively bypasses the ACL_internal_schema_access checks + that are implemented for the INFORMATION_SCHEMA and PERFORMANCE_SCHEMA, + which are located in check_access(). + Since the I_S and P_S do not contain routines, this bypass is ok, + as long as this code path is not abused to create routines. + The assert enforce that. */ + DBUG_ASSERT((want_access & CREATE_PROC_ACL) == 0); if ((thd->security_ctx->master_access & want_access) == want_access) tables->grant.privilege= want_access; - else if (check_access(thd,want_access,db,&tables->grant.privilege, - 0, no_errors, 0)) + else if (check_access(thd, want_access, db, + &tables->grant.privilege, + &tables->grant.m_internal, + 0, no_errors)) return TRUE; - return check_grant_routine(thd, want_access, tables, is_proc, no_errors); + return check_grant_routine(thd, want_access, tables, is_proc, no_errors); } @@ -5714,13 +5481,18 @@ bool check_some_routine_access(THD *thd, const char *db, const char *name, bool is_proc) { ulong save_priv; - if (thd->security_ctx->master_access & SHOW_PROC_ACLS) - return FALSE; /* - There are no routines in information_schema db. So we can safely - pass zero to last paramter of check_access function + The following test is just a shortcut for check_access() (to avoid + calculating db_access) + Note that this effectively bypasses the ACL_internal_schema_access checks + that are implemented for the INFORMATION_SCHEMA and PERFORMANCE_SCHEMA, + which are located in check_access(). + Since the I_S and P_S do not contain routines, this bypass is ok, + as it only opens SHOW_PROC_ACLS. */ - if (!check_access(thd, SHOW_PROC_ACLS, db, &save_priv, 0, 1, 0) || + if (thd->security_ctx->master_access & SHOW_PROC_ACLS) + return FALSE; + if (!check_access(thd, SHOW_PROC_ACLS, db, &save_priv, NULL, 0, 1) || (save_priv & SHOW_PROC_ACLS)) return FALSE; return check_routine_level_acl(thd, db, name, is_proc); @@ -5750,8 +5522,9 @@ bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table) if (access & want_access) { if (!check_access(thd, access, table->db, - &table->grant.privilege, 0, 1, - test(table->schema_table)) && + &table->grant.privilege, + &table->grant.m_internal, + 0, 1) && !check_grant(thd, access, table, FALSE, 1, TRUE)) DBUG_RETURN(0); } @@ -5830,7 +5603,6 @@ bool check_stack_overrun(THD *thd, long margin, my_snprintf(ebuff, sizeof(ebuff), ER(ER_STACK_OVERRUN_NEED_MORE), stack_used, my_thread_stack_size, margin); my_message(ER_STACK_OVERRUN_NEED_MORE, ebuff, MYF(ME_FATALERROR)); - thd->fatal_error(); return 1; } #ifndef DBUG_OFF @@ -5879,21 +5651,26 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize) /** - Reset THD part responsible for command processing state. + Reset the part of THD responsible for the state of command + processing. - This needs to be called before execution of every statement - (prepared or conventional). - It is not called by substatements of routines. + This needs to be called before execution of every statement + (prepared or conventional). It is not called by substatements of + routines. - @todo - Make it a method of THD and align its name with the rest of - reset/end/start/init methods. - @todo - Call it after we use THD for queries, not before. -*/ + @todo Remove mysql_reset_thd_for_next_command and only use the + member function. + @todo Call it after we use THD for queries, not before. +*/ void mysql_reset_thd_for_next_command(THD *thd) { + thd->reset_for_next_command(); +} + +void THD::reset_for_next_command() +{ + THD *thd= this; DBUG_ENTER("mysql_reset_thd_for_next_command"); DBUG_ASSERT(!thd->spcont); /* not for substatements of routines */ DBUG_ASSERT(! thd->in_sub_stmt); @@ -5918,9 +5695,9 @@ void mysql_reset_thd_for_next_command(THD *thd) OPTION_STATUS_NO_TRANS_UPDATE | OPTION_KEEP_LOG to not get warnings in ha_rollback_trans() about some tables couldn't be rolled back. */ - if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) + if (!(thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) { - thd->options&= ~OPTION_KEEP_LOG; + thd->variables.option_bits&= ~OPTION_KEEP_LOG; thd->transaction.all.modified_non_trans_table= FALSE; } DBUG_ASSERT(thd->security_ctx== &thd->main_security_ctx); @@ -5937,15 +5714,12 @@ void mysql_reset_thd_for_next_command(THD *thd) thd->rand_used= 0; thd->sent_row_count= thd->examined_row_count= 0; - /* - Because we come here only for start of top-statements, binlog format is - constant inside a complex statement (using stored functions) etc. - */ - thd->reset_current_stmt_binlog_row_based(); + thd->reset_current_stmt_binlog_format_row(); + thd->binlog_unsafe_warning_flags= 0; DBUG_PRINT("debug", - ("current_stmt_binlog_row_based: %d", - thd->current_stmt_binlog_row_based)); + ("is_current_stmt_binlog_format_row(): %d", + thd->is_current_stmt_binlog_format_row())); DBUG_VOID_RETURN; } @@ -6360,17 +6134,6 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type, DBUG_RETURN(1); } - if (type == MYSQL_TYPE_TIMESTAMP && length) - { - /* Display widths are no longer supported for TIMSTAMP as of MySQL 4.1. - In other words, for declarations such as TIMESTAMP(2), TIMESTAMP(4), - and so on, the display width is ignored. - */ - char buf[32]; - my_snprintf(buf, sizeof(buf), "TIMESTAMP(%s)", length); - WARN_DEPRECATED(thd, "6.0", buf, "'TIMESTAMP'"); - } - if (!(new_field= new Create_field()) || new_field->init(thd, field_name->str, type, length, decimals, type_modifier, default_value, on_update_value, comment, change, @@ -6494,13 +6257,17 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, DBUG_RETURN(0); /* purecov: inspected */ if (table->db.str) { + ptr->is_fqtn= TRUE; ptr->db= table->db.str; ptr->db_length= table->db.length; } else if (lex->copy_db_to(&ptr->db, &ptr->db_length)) DBUG_RETURN(0); + else + ptr->is_fqtn= FALSE; ptr->alias= alias_str; + ptr->is_alias= alias ? TRUE : FALSE; if (lower_case_table_names && table->table.length) table->table.length= my_casedn_str(files_charset_info, table->table.str); ptr->table_name=table->table.str; @@ -6511,7 +6278,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX); ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES); ptr->derived= table->sel; - if (!ptr->derived && is_schema_db(ptr->db, ptr->db_length)) + if (!ptr->derived && is_infoschema_db(ptr->db, ptr->db_length)) { ST_SCHEMA_TABLE *schema_table; if (ptr->updating && @@ -7049,7 +6816,6 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, { thd->thread_stack= (char*) &tmp_thd; thd->store_globals(); - lex_start(thd); } if (thd) @@ -7087,6 +6853,30 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, tables. */ + options|= REFRESH_BINARY_LOG; + options|= REFRESH_RELAY_LOG; + options|= REFRESH_SLOW_LOG; + options|= REFRESH_GENERAL_LOG; + options|= REFRESH_ENGINE_LOG; + options|= REFRESH_ERROR_LOG; + } + + if (options & REFRESH_ERROR_LOG) + if (flush_error_log()) + result= 1; + + if ((options & REFRESH_SLOW_LOG) && opt_slow_log) + logger.flush_slow_log(); + + if ((options & REFRESH_GENERAL_LOG) && opt_log) + logger.flush_general_log(); + + if (options & REFRESH_ENGINE_LOG) + if (ha_flush_logs(NULL)) + result= 1; + + if (options & REFRESH_BINARY_LOG) + { /* Writing this command to the binlog may result in infinite loops when doing mysqlbinlog|mysql, and anyway it does not really make @@ -7094,23 +6884,16 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, than it would help them) */ tmp_write_to_binlog= 0; - if( mysql_bin_log.is_open() ) - { + if (mysql_bin_log.is_open()) mysql_bin_log.rotate_and_purge(RP_FORCE_ROTATE); - } + } + if (options & REFRESH_RELAY_LOG) + { #ifdef HAVE_REPLICATION - pthread_mutex_lock(&LOCK_active_mi); + mysql_mutex_lock(&LOCK_active_mi); rotate_relay_log(active_mi); - pthread_mutex_unlock(&LOCK_active_mi); + mysql_mutex_unlock(&LOCK_active_mi); #endif - - /* flush slow and general logs */ - logger.flush_logs(thd); - - if (ha_flush_logs(NULL)) - result=1; - if (flush_error_log()) - result=1; } #ifdef HAVE_QUERY_CACHE if (options & REFRESH_QUERY_CACHE_FREE) @@ -7204,10 +6987,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables, if (options & REFRESH_SLAVE) { tmp_write_to_binlog= 0; - pthread_mutex_lock(&LOCK_active_mi); + mysql_mutex_lock(&LOCK_active_mi); if (reset_slave(thd, active_mi)) result=1; - pthread_mutex_unlock(&LOCK_active_mi); + mysql_mutex_unlock(&LOCK_active_mi); } #endif if (options & REFRESH_USER_RESOURCES) @@ -7237,7 +7020,7 @@ uint kill_one_thread(THD *thd, ulong id, bool only_kill_query) uint error=ER_NO_SUCH_THREAD; DBUG_ENTER("kill_one_thread"); DBUG_PRINT("enter", ("id=%lu only_kill=%d", id, only_kill_query)); - VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list + mysql_mutex_lock(&LOCK_thread_count); // For unlink from list I_List_iterator<THD> it(threads); while ((tmp=it++)) { @@ -7245,11 +7028,11 @@ uint kill_one_thread(THD *thd, ulong id, bool only_kill_query) continue; if (tmp->thread_id == id) { - pthread_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete + mysql_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete break; } } - VOID(pthread_mutex_unlock(&LOCK_thread_count)); + mysql_mutex_unlock(&LOCK_thread_count); if (tmp) { @@ -7278,7 +7061,7 @@ uint kill_one_thread(THD *thd, ulong id, bool only_kill_query) } else error=ER_KILL_DENIED_ERROR; - pthread_mutex_unlock(&tmp->LOCK_thd_data); + mysql_mutex_unlock(&tmp->LOCK_thd_data); } DBUG_PRINT("exit", ("%d", error)); DBUG_RETURN(error); @@ -7459,12 +7242,14 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables) if (table->derived) table->grant.privilege= SELECT_ACL; else if ((check_access(thd, UPDATE_ACL, table->db, - &table->grant.privilege, 0, 1, - test(table->schema_table)) || + &table->grant.privilege, + &table->grant.m_internal, + 0, 1) || check_grant(thd, UPDATE_ACL, table, FALSE, 1, TRUE)) && (check_access(thd, SELECT_ACL, table->db, - &table->grant.privilege, 0, 0, - test(table->schema_table)) || + &table->grant.privilege, + &table->grant.m_internal, + 0, 0) || check_grant(thd, SELECT_ACL, table, FALSE, 1, FALSE))) DBUG_RETURN(TRUE); @@ -7481,8 +7266,9 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables) if (!table->table_in_first_from_clause) { if (check_access(thd, SELECT_ACL, table->db, - &table->grant.privilege, 0, 0, - test(table->schema_table)) || + &table->grant.privilege, + &table->grant.m_internal, + 0, 0) || check_grant(thd, SELECT_ACL, table, FALSE, 1, FALSE)) DBUG_RETURN(TRUE); } @@ -7539,7 +7325,7 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables) } thd->lex->query_tables_own_last= save_query_tables_own_last; - if ((thd->options & OPTION_SAFE_UPDATES) && !select_lex->where) + if ((thd->variables.option_bits & OPTION_SAFE_UPDATES) && !select_lex->where) { my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE, ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0)); @@ -7549,6 +7335,63 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables) } +/* + Given a table in the source list, find a correspondent table in the + table references list. + + @param lex Pointer to LEX representing multi-delete. + @param src Source table to match. + @param ref Table references list. + + @remark The source table list (tables listed before the FROM clause + or tables listed in the FROM clause before the USING clause) may + contain table names or aliases that must match unambiguously one, + and only one, table in the target table list (table references list, + after FROM/USING clause). + + @return Matching table, NULL otherwise. +*/ + +static TABLE_LIST *multi_delete_table_match(LEX *lex, TABLE_LIST *tbl, + TABLE_LIST *tables) +{ + TABLE_LIST *match= NULL; + DBUG_ENTER("multi_delete_table_match"); + + for (TABLE_LIST *elem= tables; elem; elem= elem->next_local) + { + int cmp; + + if (tbl->is_fqtn && elem->is_alias) + continue; /* no match */ + if (tbl->is_fqtn && elem->is_fqtn) + cmp= my_strcasecmp(table_alias_charset, tbl->table_name, elem->table_name) || + strcmp(tbl->db, elem->db); + else if (elem->is_alias) + cmp= my_strcasecmp(table_alias_charset, tbl->alias, elem->alias); + else + cmp= my_strcasecmp(table_alias_charset, tbl->table_name, elem->table_name) || + strcmp(tbl->db, elem->db); + + if (cmp) + continue; + + if (match) + { + my_error(ER_NONUNIQ_TABLE, MYF(0), elem->alias); + DBUG_RETURN(NULL); + } + + match= elem; + } + + if (!match) + my_error(ER_UNKNOWN_TABLE, MYF(0), tbl->table_name, "MULTI DELETE"); + + DBUG_RETURN(match); +} + + /** Link tables in auxilary table list of multi-delete with corresponding elements in main table list, and set proper locks for them. @@ -7574,20 +7417,9 @@ bool multi_delete_set_locks_and_link_aux_tables(LEX *lex) { lex->table_count++; /* All tables in aux_tables must be found in FROM PART */ - TABLE_LIST *walk; - for (walk= tables; walk; walk= walk->next_local) - { - if (!my_strcasecmp(table_alias_charset, - target_tbl->alias, walk->alias) && - !strcmp(walk->db, target_tbl->db)) - break; - } + TABLE_LIST *walk= multi_delete_table_match(lex, target_tbl, tables); if (!walk) - { - my_error(ER_UNKNOWN_TABLE, MYF(0), - target_tbl->table_name, "MULTI DELETE"); DBUG_RETURN(TRUE); - } if (!walk->derived) { target_tbl->table_name= walk->table_name; @@ -7717,8 +7549,9 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, (select_lex->item_list.elements ? INSERT_ACL : 0); if (check_access(thd, want_priv, create_table->db, - &create_table->grant.privilege, 0, 0, - test(create_table->schema_table)) || + &create_table->grant.privilege, + &create_table->grant.m_internal, + 0, 0) || check_merge_table_access(thd, create_table->db, (TABLE_LIST *) lex->create_info.merge_list.first)) @@ -8110,3 +7943,37 @@ bool parse_sql(THD *thd, /** @} (end of group Runtime_Environment) */ + + + +/** + Check and merge "CHARACTER SET cs [ COLLATE cl ]" clause + + @param cs character set pointer. + @param cl collation pointer. + + Check if collation "cl" is applicable to character set "cs". + + If "cl" is NULL (e.g. when COLLATE clause is not specified), + then simply "cs" is returned. + + @return Error status. + @retval NULL, if "cl" is not applicable to "cs". + @retval pointer to merged CHARSET_INFO on success. +*/ + + +CHARSET_INFO* +merge_charset_and_collation(CHARSET_INFO *cs, CHARSET_INFO *cl) +{ + if (cl) + { + if (!my_charset_same(cs, cl)) + { + my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0), cl->name, cs->csname); + return NULL; + } + return cl; + } + return cs; +} diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 534a6162d87..90d5c553cdf 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -933,6 +933,85 @@ int check_signed_flag(partition_info *part_info) return error; } +/** + Initialize lex object for use in fix_fields and parsing. + + SYNOPSIS + init_lex_with_single_table() + @param thd The thread object + @param table The table object + @return Operation status + @retval TRUE An error occurred, memory allocation error + @retval FALSE Ok + + DESCRIPTION + This function is used to initialize a lex object on the + stack for use by fix_fields and for parsing. In order to + work properly it also needs to initialize the + Name_resolution_context object of the lexer. + Finally it needs to set a couple of variables to ensure + proper functioning of fix_fields. +*/ + +static int +init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex) +{ + TABLE_LIST *table_list; + Table_ident *table_ident; + SELECT_LEX *select_lex= &lex->select_lex; + Name_resolution_context *context= &select_lex->context; + /* + We will call the parser to create a part_info struct based on the + partition string stored in the frm file. + We will use a local lex object for this purpose. However we also + need to set the Name_resolution_object for this lex object. We + do this by using add_table_to_list where we add the table that + we're working with to the Name_resolution_context. + */ + thd->lex= lex; + lex_start(thd); + context->init(); + if ((!(table_ident= new Table_ident(thd, + table->s->table_name, + table->s->db, TRUE))) || + (!(table_list= select_lex->add_table_to_list(thd, + table_ident, + NULL, + 0)))) + return TRUE; + context->resolve_in_table_list_only(table_list); + lex->use_only_table_context= TRUE; + select_lex->cur_pos_in_select_list= UNDEF_POS; + table->map= 1; //To ensure correct calculation of const item + table->get_fields_in_item_tree= TRUE; + table_list->table= table; + return FALSE; +} + +/** + End use of local lex with single table + + SYNOPSIS + end_lex_with_single_table() + @param thd The thread object + @param table The table object + @param old_lex The real lex object connected to THD + + DESCRIPTION + This function restores the real lex object after calling + init_lex_with_single_table and also restores some table + variables temporarily set. +*/ + +static void +end_lex_with_single_table(THD *thd, TABLE *table, LEX *old_lex) +{ + LEX *lex= thd->lex; + table->map= 0; + table->get_fields_in_item_tree= FALSE; + lex_end(lex); + thd->lex= old_lex; +} /* The function uses a new feature in fix_fields where the flag @@ -975,57 +1054,20 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, bool is_sub_part, bool is_create_table_ind) { partition_info *part_info= table->part_info; - uint dir_length, home_dir_length; bool result= TRUE; - TABLE_LIST tables; - TABLE_LIST *save_table_list, *save_first_table, *save_last_table; int error; - Name_resolution_context *context; const char *save_where; - char* db_name; - char db_name_string[FN_REFLEN]; - bool save_use_only_table_context; + LEX *old_lex= thd->lex; + LEX lex; uint8 saved_full_group_by_flag; nesting_map saved_allow_sum_func; DBUG_ENTER("fix_fields_part_func"); - /* - Set-up the TABLE_LIST object to be a list with a single table - Set the object to zero to create NULL pointers and set alias - and real name to table name and get database name from file name. - TODO: Consider generalizing or refactoring Lex::add_table_to_list() so - it can be used in all places where we create TABLE_LIST objects. - Also consider creating appropriate constructors for TABLE_LIST. - */ - - bzero((void*)&tables, sizeof(TABLE_LIST)); - tables.alias= tables.table_name= (char*) table->s->table_name.str; - tables.table= table; - tables.next_local= 0; - tables.next_name_resolution_table= 0; - /* - Cache the table in Item_fields. All the tables can be cached except - the trigger pseudo table. - */ - tables.cacheable_table= TRUE; - context= thd->lex->current_context(); - tables.select_lex= context->select_lex; - strmov(db_name_string, table->s->normalized_path.str); - dir_length= dirname_length(db_name_string); - db_name_string[dir_length - 1]= 0; - home_dir_length= dirname_length(db_name_string); - db_name= &db_name_string[home_dir_length]; - tables.db= db_name; + if (init_lex_with_single_table(thd, table, &lex)) + goto end; - table->map= 1; //To ensure correct calculation of const item - table->get_fields_in_item_tree= TRUE; - save_table_list= context->table_list; - save_first_table= context->first_name_resolution_table; - save_last_table= context->last_name_resolution_table; - context->table_list= &tables; - context->first_name_resolution_table= &tables; - context->last_name_resolution_table= NULL; - func_expr->walk(&Item::change_context_processor, 0, (uchar*) context); + func_expr->walk(&Item::change_context_processor, 0, + (uchar*) &lex.select_lex.context); save_where= thd->where; thd->where= "partition function"; /* @@ -1040,19 +1082,14 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, that does this during val_int must be disallowed as partition function. SEE Bug #21658 - */ - /* + This is a tricky call to prepare for since it can have a large number of interesting side effects, both desirable and undesirable. */ - - save_use_only_table_context= thd->lex->use_only_table_context; - thd->lex->use_only_table_context= TRUE; - thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS; saved_full_group_by_flag= thd->lex->current_select->full_group_by_flag; saved_allow_sum_func= thd->lex->allow_sum_func; thd->lex->allow_sum_func= 0; - + error= func_expr->fix_fields(thd, (Item**)&func_expr); /* @@ -1062,18 +1099,12 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, thd->lex->current_select->full_group_by_flag= saved_full_group_by_flag; thd->lex->allow_sum_func= saved_allow_sum_func; - thd->lex->use_only_table_context= save_use_only_table_context; - - context->table_list= save_table_list; - context->first_name_resolution_table= save_first_table; - context->last_name_resolution_table= save_last_table; if (unlikely(error)) { DBUG_PRINT("info", ("Field in partition function not part of table")); clear_field_flag(table); goto end; } - thd->where= save_where; if (unlikely(func_expr->const_item())) { my_error(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR, MYF(0)); @@ -1105,8 +1136,11 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, goto end; result= set_up_field_array(table, is_sub_part); end: - table->get_fields_in_item_tree= FALSE; - table->map= 0; //Restore old value + end_lex_with_single_table(thd, table, old_lex); +#if !defined(DBUG_OFF) + func_expr->walk(&Item::change_context_processor, 0, + (uchar*) 0); +#endif DBUG_RETURN(result); } @@ -1846,7 +1880,7 @@ end: static int add_write(File fptr, const char *buf, uint len) { - uint ret_code= my_write(fptr, (const uchar*)buf, len, MYF(MY_FNABP)); + uint ret_code= mysql_file_write(fptr, (const uchar*)buf, len, MYF(MY_FNABP)); if (likely(ret_code == 0)) return 0; @@ -1943,11 +1977,11 @@ static int add_part_field_list(File fptr, List<char> field_list) const char *field_str= part_it++; String field_string("", 0, system_charset_info); THD *thd= current_thd; - ulonglong save_options= thd->options; - thd->options= 0; + ulonglong save_options= thd->variables.option_bits; + thd->variables.option_bits= 0; append_identifier(thd, &field_string, field_str, strlen(field_str)); - thd->options= save_options; + thd->variables.option_bits= save_options; err+= add_string_object(fptr, &field_string); if (i != (num_fields-1)) err+= add_comma(fptr); @@ -1962,12 +1996,12 @@ static int add_name_string(File fptr, const char *name) int err; String name_string("", 0, system_charset_info); THD *thd= current_thd; - ulonglong save_options= thd->options; + ulonglong save_options= thd->variables.option_bits; - thd->options= 0; + thd->variables.option_bits= 0; append_identifier(thd, &name_string, name, strlen(name)); - thd->options= save_options; + thd->variables.option_bits= save_options; err= add_string_object(fptr, &name_string); return err; } @@ -2443,8 +2477,7 @@ char *generate_partition_syntax(partition_info *part_info, default: DBUG_ASSERT(0); /* We really shouldn't get here, no use in continuing from here */ - my_error(ER_OUT_OF_RESOURCES, MYF(0)); - current_thd->fatal_error(); + my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); DBUG_RETURN(NULL); } if (part_info->part_expr) @@ -2559,10 +2592,11 @@ char *generate_partition_syntax(partition_info *part_info, } if (err) goto close_file; - buffer_length= my_seek(fptr, 0L,MY_SEEK_END,MYF(0)); + buffer_length= mysql_file_seek(fptr, 0L, MY_SEEK_END, MYF(0)); if (unlikely(buffer_length == MY_FILEPOS_ERROR)) goto close_file; - if (unlikely(my_seek(fptr, 0L, MY_SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR)) + if (unlikely(mysql_file_seek(fptr, 0L, MY_SEEK_SET, MYF(0)) + == MY_FILEPOS_ERROR)) goto close_file; *buf_length= (uint)buffer_length; if (use_sql_alloc) @@ -2572,7 +2606,7 @@ char *generate_partition_syntax(partition_info *part_info, if (!buf) goto close_file; - if (unlikely(my_read(fptr, (uchar*)buf, *buf_length, MYF(MY_FNABP)))) + if (unlikely(mysql_file_read(fptr, (uchar*)buf, *buf_length, MYF(MY_FNABP)))) { if (!use_sql_alloc) my_free(buf, MYF(0)); @@ -2583,7 +2617,7 @@ char *generate_partition_syntax(partition_info *part_info, buf[*buf_length]= 0; close_file: - my_close(fptr, MYF(0)); + mysql_file_close(fptr, MYF(0)); DBUG_RETURN(buf); } @@ -4142,26 +4176,13 @@ bool mysql_unpack_partition(THD *thd, LEX lex; DBUG_ENTER("mysql_unpack_partition"); - thd->lex= &lex; thd->variables.character_set_client= system_charset_info; Parser_state parser_state(thd, part_buf, part_info_len); - lex_start(thd); - *work_part_info_used= false; - /* - We need to use the current SELECT_LEX since I need to keep the - Name_resolution_context object which is referenced from the - Item_field objects. - This is not a nice solution since if the parser uses current_select - for anything else it will corrupt the current LEX object. - Also, we need to make sure there even is a select -- if the statement - was a "USE ...", current_select will be NULL, but we may still end up - here if we try to log to a partitioned table. This is currently - unsupported, but should still fail rather than crash! - */ - if (!(thd->lex->current_select= old_lex->current_select)) + if (init_lex_with_single_table(thd, table, &lex)) goto end; + /* All Items created is put into a free list on the THD object. This list is used to free all Item objects after completing a query. We don't @@ -4171,6 +4192,7 @@ bool mysql_unpack_partition(THD *thd, Thus we move away the current list temporarily and start a new list that we then save in the partition info structure. */ + *work_part_info_used= FALSE; lex.part_info= new partition_info();/* Indicates MYSQLparse from this place */ if (!lex.part_info) { @@ -4284,8 +4306,7 @@ bool mysql_unpack_partition(THD *thd, result= FALSE; end: - lex_end(thd->lex); - thd->lex= old_lex; + end_lex_with_single_table(thd, table, old_lex); thd->variables.character_set_client= old_character_set_client; DBUG_RETURN(result); } @@ -5517,10 +5538,7 @@ static bool mysql_change_partitions(ALTER_PARTITION_PARAM_TYPE *lpt) &lpt->deleted, lpt->pack_frm_data, lpt->pack_frm_len))) { - if (error != ER_OUTOFMEMORY) - file->print_error(error, MYF(0)); - else - lpt->thd->fatal_error(); + file->print_error(error, MYF(error != ER_OUTOFMEMORY ? 0 : ME_FATALERROR)); DBUG_RETURN(TRUE); } DBUG_RETURN(FALSE); @@ -5942,7 +5960,7 @@ static bool write_log_drop_shadow_frm(ALTER_PARTITION_PARAM_TYPE *lpt) DBUG_ENTER("write_log_drop_shadow_frm"); build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1, lpt); - pthread_mutex_lock(&LOCK_gdl); + mysql_mutex_lock(&LOCK_gdl); if (write_log_replace_delete_frm(lpt, 0UL, NULL, (const char*)shadow_path, FALSE)) goto error; @@ -5950,13 +5968,13 @@ static bool write_log_drop_shadow_frm(ALTER_PARTITION_PARAM_TYPE *lpt) if (write_execute_ddl_log_entry(log_entry->entry_pos, FALSE, &exec_log_entry)) goto error; - pthread_mutex_unlock(&LOCK_gdl); + mysql_mutex_unlock(&LOCK_gdl); set_part_info_exec_log_entry(part_info, exec_log_entry); DBUG_RETURN(FALSE); error: release_part_info_log_entries(part_info->first_log_entry); - pthread_mutex_unlock(&LOCK_gdl); + mysql_mutex_unlock(&LOCK_gdl); part_info->first_log_entry= NULL; my_error(ER_DDL_LOG_ERROR, MYF(0)); DBUG_RETURN(TRUE); @@ -5990,7 +6008,7 @@ static bool write_log_rename_frm(ALTER_PARTITION_PARAM_TYPE *lpt) build_table_filename(path, sizeof(path) - 1, lpt->db, lpt->table_name, "", 0); build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1, lpt); - pthread_mutex_lock(&LOCK_gdl); + mysql_mutex_lock(&LOCK_gdl); if (write_log_replace_delete_frm(lpt, 0UL, shadow_path, path, TRUE)) goto error; log_entry= part_info->first_log_entry; @@ -5999,12 +6017,12 @@ static bool write_log_rename_frm(ALTER_PARTITION_PARAM_TYPE *lpt) FALSE, &exec_log_entry)) goto error; release_part_info_log_entries(old_first_log_entry); - pthread_mutex_unlock(&LOCK_gdl); + mysql_mutex_unlock(&LOCK_gdl); DBUG_RETURN(FALSE); error: release_part_info_log_entries(part_info->first_log_entry); - pthread_mutex_unlock(&LOCK_gdl); + mysql_mutex_unlock(&LOCK_gdl); part_info->first_log_entry= old_first_log_entry; part_info->frm_log_entry= NULL; my_error(ER_DDL_LOG_ERROR, MYF(0)); @@ -6042,7 +6060,7 @@ static bool write_log_drop_partition(ALTER_PARTITION_PARAM_TYPE *lpt) build_table_filename(path, sizeof(path) - 1, lpt->db, lpt->table_name, "", 0); build_table_shadow_filename(tmp_path, sizeof(tmp_path) - 1, lpt); - pthread_mutex_lock(&LOCK_gdl); + mysql_mutex_lock(&LOCK_gdl); if (write_log_dropped_partitions(lpt, &next_entry, (const char*)path, FALSE)) goto error; @@ -6055,12 +6073,12 @@ static bool write_log_drop_partition(ALTER_PARTITION_PARAM_TYPE *lpt) FALSE, &exec_log_entry)) goto error; release_part_info_log_entries(old_first_log_entry); - pthread_mutex_unlock(&LOCK_gdl); + mysql_mutex_unlock(&LOCK_gdl); DBUG_RETURN(FALSE); error: release_part_info_log_entries(part_info->first_log_entry); - pthread_mutex_unlock(&LOCK_gdl); + mysql_mutex_unlock(&LOCK_gdl); part_info->first_log_entry= old_first_log_entry; part_info->frm_log_entry= NULL; my_error(ER_DDL_LOG_ERROR, MYF(0)); @@ -6098,7 +6116,7 @@ static bool write_log_add_change_partition(ALTER_PARTITION_PARAM_TYPE *lpt) build_table_filename(path, sizeof(path) - 1, lpt->db, lpt->table_name, "", 0); build_table_shadow_filename(tmp_path, sizeof(tmp_path) - 1, lpt); - pthread_mutex_lock(&LOCK_gdl); + mysql_mutex_lock(&LOCK_gdl); if (write_log_dropped_partitions(lpt, &next_entry, (const char*)path, FALSE)) goto error; @@ -6109,13 +6127,13 @@ static bool write_log_add_change_partition(ALTER_PARTITION_PARAM_TYPE *lpt) if (write_execute_ddl_log_entry(log_entry->entry_pos, FALSE, &exec_log_entry)) goto error; - pthread_mutex_unlock(&LOCK_gdl); + mysql_mutex_unlock(&LOCK_gdl); set_part_info_exec_log_entry(part_info, exec_log_entry); DBUG_RETURN(FALSE); error: release_part_info_log_entries(part_info->first_log_entry); - pthread_mutex_unlock(&LOCK_gdl); + mysql_mutex_unlock(&LOCK_gdl); part_info->first_log_entry= NULL; my_error(ER_DDL_LOG_ERROR, MYF(0)); DBUG_RETURN(TRUE); @@ -6153,7 +6171,7 @@ static bool write_log_final_change_partition(ALTER_PARTITION_PARAM_TYPE *lpt) build_table_filename(path, sizeof(path) - 1, lpt->db, lpt->table_name, "", 0); build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1, lpt); - pthread_mutex_lock(&LOCK_gdl); + mysql_mutex_lock(&LOCK_gdl); if (write_log_dropped_partitions(lpt, &next_entry, (const char*)path, lpt->alter_info->flags & ALTER_REORGANIZE_PARTITION)) goto error; @@ -6167,12 +6185,12 @@ static bool write_log_final_change_partition(ALTER_PARTITION_PARAM_TYPE *lpt) FALSE, &exec_log_entry)) goto error; release_part_info_log_entries(old_first_log_entry); - pthread_mutex_unlock(&LOCK_gdl); + mysql_mutex_unlock(&LOCK_gdl); DBUG_RETURN(FALSE); error: release_part_info_log_entries(part_info->first_log_entry); - pthread_mutex_unlock(&LOCK_gdl); + mysql_mutex_unlock(&LOCK_gdl); part_info->first_log_entry= old_first_log_entry; part_info->frm_log_entry= NULL; my_error(ER_DDL_LOG_ERROR, MYF(0)); @@ -6199,7 +6217,7 @@ static void write_log_completed(ALTER_PARTITION_PARAM_TYPE *lpt, DBUG_ENTER("write_log_completed"); DBUG_ASSERT(log_entry); - pthread_mutex_lock(&LOCK_gdl); + mysql_mutex_lock(&LOCK_gdl); if (write_execute_ddl_log_entry(0UL, TRUE, &log_entry)) { /* @@ -6213,7 +6231,7 @@ static void write_log_completed(ALTER_PARTITION_PARAM_TYPE *lpt, } release_part_info_log_entries(part_info->first_log_entry); release_part_info_log_entries(part_info->exec_log_entry); - pthread_mutex_unlock(&LOCK_gdl); + mysql_mutex_unlock(&LOCK_gdl); part_info->exec_log_entry= NULL; part_info->first_log_entry= NULL; DBUG_VOID_RETURN; @@ -6231,10 +6249,10 @@ static void write_log_completed(ALTER_PARTITION_PARAM_TYPE *lpt, static void release_log_entries(partition_info *part_info) { - pthread_mutex_lock(&LOCK_gdl); + mysql_mutex_lock(&LOCK_gdl); release_part_info_log_entries(part_info->first_log_entry); release_part_info_log_entries(part_info->exec_log_entry); - pthread_mutex_unlock(&LOCK_gdl); + mysql_mutex_unlock(&LOCK_gdl); part_info->first_log_entry= NULL; part_info->exec_log_entry= NULL; } @@ -6259,7 +6277,7 @@ static void alter_partition_lock_handling(ALTER_PARTITION_PARAM_TYPE *lpt) since all table objects were closed and removed as part of the ALTER TABLE of partitioning structure. */ - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); lpt->thd->in_lock_tables= 1; err= reopen_tables(lpt->thd, 1, 1); lpt->thd->in_lock_tables= 0; @@ -6273,7 +6291,7 @@ static void alter_partition_lock_handling(ALTER_PARTITION_PARAM_TYPE *lpt) unlink_open_table(lpt->thd, lpt->table, FALSE); sql_print_warning("We failed to reacquire LOCKs in ALTER TABLE"); } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } } @@ -6297,9 +6315,9 @@ static int alter_close_tables(ALTER_PARTITION_PARAM_TYPE *lpt) We set lock to zero to ensure we don't do this twice and we set db_stat to zero to ensure we don't close twice. */ - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); close_data_files_and_morph_locks(thd, db, table_name); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(0); } diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 2382fc8ab5e..442c342fd31 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -13,13 +13,15 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "mysql_priv.h" +#include "sys_vars_shared.h" #include <my_pthread.h> #include <my_getopt.h> +#include <mysql/plugin_audit.h> #define REPORT_TO_LOG 1 #define REPORT_TO_USER 2 -extern struct st_mysql_plugin *mysqld_builtins[]; +extern struct st_mysql_plugin *mysql_optional_plugins[]; +extern struct st_mysql_plugin *mysql_mandatory_plugins[]; /** @note The order of the enumeration is critical. @@ -54,6 +56,9 @@ const LEX_STRING plugin_type_names[MYSQL_MAX_PLUGIN_TYPE_NUM]= extern int initialize_schema_table(st_plugin_int *plugin); extern int finalize_schema_table(st_plugin_int *plugin); +extern int initialize_audit_plugin(st_plugin_int *plugin); +extern int finalize_audit_plugin(st_plugin_int *plugin); + /* The number of elements in both plugin_type_initialize and plugin_type_deinitialize should equal to the number of plugins @@ -61,12 +66,14 @@ extern int finalize_schema_table(st_plugin_int *plugin); */ plugin_type_init plugin_type_initialize[MYSQL_MAX_PLUGIN_TYPE_NUM]= { - 0,ha_initialize_handlerton,0,0,initialize_schema_table + 0,ha_initialize_handlerton,0,0,initialize_schema_table, + initialize_audit_plugin }; plugin_type_init plugin_type_deinitialize[MYSQL_MAX_PLUGIN_TYPE_NUM]= { - 0,ha_finalize_handlerton,0,0,finalize_schema_table + 0,ha_finalize_handlerton,0,0,finalize_schema_table, + finalize_audit_plugin }; #ifdef HAVE_DLOPEN @@ -88,8 +95,8 @@ static int min_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]= MYSQL_FTPARSER_INTERFACE_VERSION, MYSQL_DAEMON_INTERFACE_VERSION, MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION, - 0x0000, /* place holder for audit plugin */ - MYSQL_REPLICATION_INTERFACE_VERSION, + MYSQL_AUDIT_INTERFACE_VERSION, + MYSQL_REPLICATION_INTERFACE_VERSION }; static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]= { @@ -98,8 +105,8 @@ static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]= MYSQL_FTPARSER_INTERFACE_VERSION, MYSQL_DAEMON_INTERFACE_VERSION, MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION, - 0x0000, /* place holder for audit plugin */ - MYSQL_REPLICATION_INTERFACE_VERSION, + MYSQL_AUDIT_INTERFACE_VERSION, + MYSQL_REPLICATION_INTERFACE_VERSION }; /* support for Services */ @@ -111,7 +118,7 @@ static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]= following variables/structures. We are always manipulating ref count, so a rwlock here is unneccessary. */ -pthread_mutex_t LOCK_plugin; +mysql_mutex_t LOCK_plugin; static DYNAMIC_ARRAY plugin_dl_array; static DYNAMIC_ARRAY plugin_array; static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM]; @@ -167,6 +174,8 @@ struct st_mysql_sys_var MYSQL_PLUGIN_VAR_HEADER; }; +static SHOW_TYPE pluginvar_show_type(st_mysql_sys_var *plugin_var); + /* sys_var class for access to all plugin variables visible to the user @@ -176,28 +185,44 @@ class sys_var_pluginvar: public sys_var public: struct st_plugin_int *plugin; struct st_mysql_sys_var *plugin_var; + /** + variable name from whatever is hard-coded in the plugin source + and doesn't have pluginname- prefix is replaced by an allocated name + with a plugin prefix. When plugin is uninstalled we need to restore the + pointer to point to the hard-coded value, because plugin may be + installed/uninstalled many times without reloading the shared object. + */ + const char *orig_pluginvar_name; static void *operator new(size_t size, MEM_ROOT *mem_root) - { return (void*) alloc_root(mem_root, (uint) size); } + { return (void*) alloc_root(mem_root, size); } static void operator delete(void *ptr_arg,size_t size) { TRASH(ptr_arg, size); } - sys_var_pluginvar(const char *name_arg, + sys_var_pluginvar(sys_var_chain *chain, const char *name_arg, struct st_mysql_sys_var *plugin_var_arg) - :sys_var(name_arg), plugin_var(plugin_var_arg) {} + :sys_var(chain, name_arg, plugin_var_arg->comment, + (plugin_var_arg->flags & PLUGIN_VAR_THDLOCAL ? SESSION : GLOBAL) | + (plugin_var_arg->flags & PLUGIN_VAR_READONLY ? READONLY : 0), + 0, -1, NO_ARG, pluginvar_show_type(plugin_var_arg), 0, 0, + VARIABLE_NOT_IN_BINLOG, 0, 0, 0, 0, PARSE_NORMAL), + plugin_var(plugin_var_arg), orig_pluginvar_name(plugin_var_arg->name) + { plugin_var->name= name_arg; } sys_var_pluginvar *cast_pluginvar() { return this; } - bool is_readonly() const { return plugin_var->flags & PLUGIN_VAR_READONLY; } - bool check_type(enum_var_type type) - { return !(plugin_var->flags & PLUGIN_VAR_THDLOCAL) && type != OPT_GLOBAL; } bool check_update_type(Item_result type); SHOW_TYPE show_type(); uchar* real_value_ptr(THD *thd, enum_var_type type); TYPELIB* plugin_var_typelib(void); - uchar* value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); - bool check(THD *thd, set_var *var); - bool check_default(enum_var_type type) { return is_readonly(); } - void set_default(THD *thd, enum_var_type type); - bool update(THD *thd, set_var *var); + uchar* do_value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); + uchar* session_value_ptr(THD *thd, LEX_STRING *base) + { return do_value_ptr(thd, OPT_SESSION, base); } + uchar* global_value_ptr(THD *thd, LEX_STRING *base) + { return do_value_ptr(thd, OPT_GLOBAL, base); } + bool do_check(THD *thd, set_var *var); + virtual void session_save_default(THD *thd, set_var *var) {} + virtual void global_save_default(THD *thd, set_var *var) {} + bool session_update(THD *thd, set_var *var); + bool global_update(THD *thd, set_var *var); }; @@ -212,8 +237,9 @@ static bool register_builtin(struct st_mysql_plugin *, struct st_plugin_int *, static void unlock_variables(THD *thd, struct system_variables *vars); static void cleanup_variables(THD *thd, struct system_variables *vars); static void plugin_vars_free_values(sys_var *vars); -static void plugin_opt_set_limits(struct my_option *options, - const struct st_mysql_sys_var *opt); +static void restore_pluginvar_names(sys_var *first); +static void plugin_opt_set_limits(struct my_option *, + const struct st_mysql_sys_var *); #define my_intern_plugin_lock(A,B) intern_plugin_lock(A,B CALLER_INFO) #define my_intern_plugin_lock_ci(A,B) intern_plugin_lock(A,B ORIG_CALLER_INFO) static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin @@ -221,12 +247,6 @@ static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin static void intern_plugin_unlock(LEX *lex, plugin_ref plugin); static void reap_plugins(void); - -/* declared in set_var.cc */ -extern sys_var *intern_find_sys_var(const char *str, uint length, bool no_error); -extern bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd, - const char *name, longlong val); - #ifdef EMBEDDED_LIBRARY /* declared in sql_base.cc */ extern bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists); @@ -292,6 +312,11 @@ static int item_val_int(struct st_mysql_value *value, long long *buf) return 0; } +static int item_is_unsigned(struct st_mysql_value *value) +{ + Item *item= ((st_item_value_holder*)value)->item; + return item->unsigned_flag; +} static int item_val_real(struct st_mysql_value *value, double *buf) { @@ -424,7 +449,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report) (plugin_dl.version >> 8) > (MYSQL_PLUGIN_INTERFACE_VERSION >> 8)) { free_plugin_mem(&plugin_dl); - report_error(report, ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, 0, + report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0, "plugin interface version mismatch"); DBUG_RETURN(0); } @@ -453,8 +478,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report) if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym))) { free_plugin_mem(&plugin_dl); - report_error(report, ER_CANT_FIND_DL_ENTRY, MYF(0), - plugin_declarations_sym); + report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_declarations_sym); DBUG_RETURN(0); } @@ -542,7 +566,7 @@ static void plugin_dl_del(const LEX_STRING *dl) uint i; DBUG_ENTER("plugin_dl_del"); - safe_mutex_assert_owner(&LOCK_plugin); + mysql_mutex_assert_owner(&LOCK_plugin); for (i= 0; i < plugin_dl_array.elements; i++) { @@ -574,7 +598,7 @@ static struct st_plugin_int *plugin_find_internal(const LEX_STRING *name, int ty if (! initialized) DBUG_RETURN(0); - safe_mutex_assert_owner(&LOCK_plugin); + mysql_mutex_assert_owner(&LOCK_plugin); if (type == MYSQL_ANY_PLUGIN) { @@ -599,14 +623,14 @@ static SHOW_COMP_OPTION plugin_status(const LEX_STRING *name, int type) SHOW_COMP_OPTION rc= SHOW_OPTION_NO; struct st_plugin_int *plugin; DBUG_ENTER("plugin_is_ready"); - pthread_mutex_lock(&LOCK_plugin); + mysql_mutex_lock(&LOCK_plugin); if ((plugin= plugin_find_internal(name, type))) { rc= SHOW_OPTION_DISABLED; if (plugin->state == PLUGIN_IS_READY) rc= SHOW_OPTION_YES; } - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); DBUG_RETURN(rc); } @@ -620,10 +644,10 @@ bool plugin_is_ready(const LEX_STRING *name, int type) } -SHOW_COMP_OPTION sys_var_have_plugin::get_option() +SHOW_COMP_OPTION plugin_status(const char *name, int len, size_t type) { - LEX_STRING plugin_name= { (char *) plugin_name_str, plugin_name_len }; - return plugin_status(&plugin_name, plugin_type); + LEX_STRING plugin_name= { (char *) name, len }; + return plugin_status(&plugin_name, type); } @@ -632,7 +656,7 @@ static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc CALLER_INFO_PROTO) st_plugin_int *pi= plugin_ref_to_int(rc); DBUG_ENTER("intern_plugin_lock"); - safe_mutex_assert_owner(&LOCK_plugin); + mysql_mutex_assert_owner(&LOCK_plugin); if (pi->state & (PLUGIN_IS_READY | PLUGIN_IS_UNINITIALIZED)) { @@ -671,9 +695,9 @@ plugin_ref plugin_lock(THD *thd, plugin_ref *ptr CALLER_INFO_PROTO) LEX *lex= thd ? thd->lex : 0; plugin_ref rc; DBUG_ENTER("plugin_lock"); - pthread_mutex_lock(&LOCK_plugin); + mysql_mutex_lock(&LOCK_plugin); rc= my_intern_plugin_lock_ci(lex, *ptr); - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); DBUG_RETURN(rc); } @@ -685,10 +709,10 @@ plugin_ref plugin_lock_by_name(THD *thd, const LEX_STRING *name, int type plugin_ref rc= NULL; st_plugin_int *plugin; DBUG_ENTER("plugin_lock_by_name"); - pthread_mutex_lock(&LOCK_plugin); + mysql_mutex_lock(&LOCK_plugin); if ((plugin= plugin_find_internal(name, type))) rc= my_intern_plugin_lock_ci(lex, plugin_int_to_ref(plugin)); - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); DBUG_RETURN(rc); } @@ -748,14 +772,6 @@ static bool plugin_add(MEM_ROOT *tmp_root, name_len)) { struct st_plugin_int *tmp_plugin_ptr; - - if (plugin->type == MYSQL_AUDIT_PLUGIN) - { - /* Bug#49894 */ - sql_print_error("Plugin type 'AUDIT' not supported by this server."); - goto err; - } - if (*(int*)plugin->info < min_plugin_info_interface_version[plugin->type] || ((*(int*)plugin->info) >> 8) > @@ -787,6 +803,7 @@ static bool plugin_add(MEM_ROOT *tmp_root, tmp_plugin_ptr->state= PLUGIN_IS_FREED; } mysql_del_sys_var_chain(tmp.system_vars); + restore_pluginvar_names(tmp.system_vars); goto err; /* plugin was disabled */ @@ -808,17 +825,17 @@ static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check) deinitialization to deadlock if plugins have worker threads with plugin locks */ - safe_mutex_assert_not_owner(&LOCK_plugin); + mysql_mutex_assert_not_owner(&LOCK_plugin); if (plugin->plugin->status_vars) { #ifdef FIX_LATER - /* - We have a problem right now where we can not prepend without - breaking backwards compatibility. We will fix this shortly so - that engines have "use names" and we wil use those for - CREATE TABLE, and use the plugin name then for adding automatic - variable names. + /** + @todo + unfortunately, status variables were introduced without a + pluginname_ namespace, that is pluginname_ was not added automatically + to status variable names. It should be fixed together with the next + incompatible API change. */ SHOW_VAR array[2]= { {plugin->plugin->name, (char*)plugin->plugin->status_vars, SHOW_ARRAY}, @@ -858,21 +875,21 @@ static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check) plugin->name.str, plugin->ref_count); } - static void plugin_del(struct st_plugin_int *plugin) { DBUG_ENTER("plugin_del(plugin)"); - safe_mutex_assert_owner(&LOCK_plugin); + mysql_mutex_assert_owner(&LOCK_plugin); /* Free allocated strings before deleting the plugin. */ + mysql_rwlock_wrlock(&LOCK_system_variables_hash); + mysql_del_sys_var_chain(plugin->system_vars); + mysql_rwlock_unlock(&LOCK_system_variables_hash); + restore_pluginvar_names(plugin->system_vars); plugin_vars_free_values(plugin->system_vars); my_hash_delete(&plugin_hash[plugin->plugin->type], (uchar*)plugin); if (plugin->plugin_dl) plugin_dl_del(&plugin->plugin_dl->dl); plugin->state= PLUGIN_IS_FREED; plugin_array_version++; - rw_wrlock(&LOCK_system_variables_hash); - mysql_del_sys_var_chain(plugin->system_vars); - rw_unlock(&LOCK_system_variables_hash); free_root(&plugin->mem_root, MYF(0)); DBUG_VOID_RETURN; } @@ -895,7 +912,7 @@ static void reap_plugins(void) uint count, idx; struct st_plugin_int *plugin, **reap, **list; - safe_mutex_assert_owner(&LOCK_plugin); + mysql_mutex_assert_owner(&LOCK_plugin); if (!reap_needed) return; @@ -916,13 +933,13 @@ static void reap_plugins(void) } } - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); list= reap; while ((plugin= *(--list))) plugin_deinitialize(plugin, true); - pthread_mutex_lock(&LOCK_plugin); + mysql_mutex_lock(&LOCK_plugin); while ((plugin= *(--reap))) plugin_del(plugin); @@ -936,7 +953,7 @@ static void intern_plugin_unlock(LEX *lex, plugin_ref plugin) st_plugin_int *pi; DBUG_ENTER("intern_plugin_unlock"); - safe_mutex_assert_owner(&LOCK_plugin); + mysql_mutex_assert_owner(&LOCK_plugin); if (!plugin) DBUG_VOID_RETURN; @@ -989,10 +1006,10 @@ void plugin_unlock(THD *thd, plugin_ref plugin) if (!plugin_dlib(plugin)) DBUG_VOID_RETURN; #endif - pthread_mutex_lock(&LOCK_plugin); + mysql_mutex_lock(&LOCK_plugin); intern_plugin_unlock(lex, plugin); reap_plugins(); - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); DBUG_VOID_RETURN; } @@ -1002,20 +1019,25 @@ void plugin_unlock_list(THD *thd, plugin_ref *list, uint count) LEX *lex= thd ? thd->lex : 0; DBUG_ENTER("plugin_unlock_list"); DBUG_ASSERT(list); - pthread_mutex_lock(&LOCK_plugin); + mysql_mutex_lock(&LOCK_plugin); while (count--) intern_plugin_unlock(lex, *list++); reap_plugins(); - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); DBUG_VOID_RETURN; } static int plugin_initialize(struct st_plugin_int *plugin) { + int ret= 1; DBUG_ENTER("plugin_initialize"); - safe_mutex_assert_owner(&LOCK_plugin); + mysql_mutex_assert_owner(&LOCK_plugin); + uint state= plugin->state; + DBUG_ASSERT(state == PLUGIN_IS_UNINITIALIZED); + + mysql_mutex_unlock(&LOCK_plugin); if (plugin_type_initialize[plugin->plugin->type]) { if ((*plugin_type_initialize[plugin->plugin->type])(plugin)) @@ -1034,8 +1056,7 @@ static int plugin_initialize(struct st_plugin_int *plugin) goto err; } } - - plugin->state= PLUGIN_IS_READY; + state= PLUGIN_IS_READY; // plugin->init() succeeded if (plugin->plugin->status_vars) { @@ -1054,7 +1075,8 @@ static int plugin_initialize(struct st_plugin_int *plugin) if (add_status_vars(array)) // add_status_vars makes a copy goto err; #else - add_status_vars(plugin->plugin->status_vars); // add_status_vars makes a copy + if (add_status_vars(plugin->plugin->status_vars)) + goto err; #endif /* FIX_LATER */ } @@ -1074,9 +1096,18 @@ static int plugin_initialize(struct st_plugin_int *plugin) } } - DBUG_RETURN(0); + ret= 0; + err: - DBUG_RETURN(1); + mysql_mutex_lock(&LOCK_plugin); + plugin->state= state; + + /* maintain the obsolete @@have_innodb variable */ + if (!my_strcasecmp(&my_charset_latin1, plugin->name.str, "InnoDB")) + have_innodb= state & PLUGIN_IS_READY ? SHOW_OPTION_YES + : SHOW_OPTION_DISABLED; + + DBUG_RETURN(ret); } @@ -1115,6 +1146,26 @@ static inline void convert_underscore_to_dash(char *str, int len) *p= '-'; } +#ifdef HAVE_PSI_INTERFACE +static PSI_mutex_key key_LOCK_plugin; + +static PSI_mutex_info all_plugin_mutexes[]= +{ + { &key_LOCK_plugin, "LOCK_plugin", PSI_FLAG_GLOBAL} +}; + +static void init_plugin_psi_keys(void) +{ + const char* category= "sql"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_plugin_mutexes); + PSI_server->register_mutex(category, all_plugin_mutexes, count); +} +#endif /* HAVE_PSI_INTERFACE */ /* The logic is that we first load and initialize all compiled in plugins. @@ -1131,12 +1182,17 @@ int plugin_init(int *argc, char **argv, int flags) struct st_mysql_plugin *plugin; struct st_plugin_int tmp, *plugin_ptr, **reap; MEM_ROOT tmp_root; - bool reaped_mandatory_plugin= FALSE; + bool reaped_mandatory_plugin= false; + bool mandatory= true; DBUG_ENTER("plugin_init"); if (initialized) DBUG_RETURN(0); +#ifdef HAVE_PSI_INTERFACE + init_plugin_psi_keys(); +#endif + init_alloc_root(&plugin_mem_root, 4096, 4096); init_alloc_root(&tmp_root, 4096, 4096); @@ -1145,7 +1201,7 @@ int plugin_init(int *argc, char **argv, int flags) goto err; - pthread_mutex_init(&LOCK_plugin, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_plugin, &LOCK_plugin, MY_MUTEX_INIT_FAST); if (my_init_dynamic_array(&plugin_dl_array, sizeof(struct st_plugin_dl *),16,16) || @@ -1160,15 +1216,22 @@ int plugin_init(int *argc, char **argv, int flags) goto err; } - pthread_mutex_lock(&LOCK_plugin); + mysql_mutex_lock(&LOCK_plugin); initialized= 1; /* First we register builtin plugins */ - for (builtins= mysqld_builtins; *builtins; builtins++) + for (builtins= mysql_mandatory_plugins; *builtins || mandatory; builtins++) { + if (!*builtins) + { + builtins= mysql_optional_plugins; + mandatory= false; + if (!*builtins) + break; + } for (plugin= *builtins; plugin->info; plugin++) { if (opt_ignore_builtin_innodb && @@ -1180,6 +1243,27 @@ int plugin_init(int *argc, char **argv, int flags) tmp.name.str= (char *)plugin->name; tmp.name.length= strlen(plugin->name); tmp.state= 0; + tmp.is_mandatory= mandatory; + + /* + If the performance schema is compiled in, + treat the storage engine plugin as 'mandatory', + to suppress any plugin-level options such as '--performance-schema'. + This is specific to the performance schema, and is done on purpose: + the server-level option '--performance-schema' controls the overall + performance schema initialization, which consists of much more that + the underlying storage engine initialization. + See mysqld.cc, set_vars.cc. + Suppressing ways to interfere directly with the storage engine alone + prevents awkward situations where: + - the user wants the performance schema functionality, by using + '--enable-performance-schema' (the server option), + - yet disable explicitly a component needed for the functionality + to work, by using '--skip-performance-schema' (the plugin) + */ + if (!my_strcasecmp(&my_charset_latin1, plugin->name, "PERFORMANCE_SCHEMA")) + tmp.is_mandatory= true; + free_root(&tmp_root, MYF(MY_MARK_BLOCKS_FREE)); if (test_plugin_options(&tmp_root, &tmp, argc, argv)) tmp.state= PLUGIN_IS_DISABLED; @@ -1194,7 +1278,7 @@ int plugin_init(int *argc, char **argv, int flags) my_strcasecmp(&my_charset_latin1, plugin->name, "CSV")) continue; - if (plugin_ptr->state == PLUGIN_IS_UNINITIALIZED && + if (plugin_ptr->state != PLUGIN_IS_UNINITIALIZED || plugin_initialize(plugin_ptr)) goto err_unlock; @@ -1215,7 +1299,7 @@ int plugin_init(int *argc, char **argv, int flags) /* should now be set to MyISAM storage engine */ DBUG_ASSERT(global_system_variables.table_plugin); - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); /* Register all dynamic plugins */ if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING)) @@ -1233,7 +1317,7 @@ int plugin_init(int *argc, char **argv, int flags) Now we initialize all remaining plugins */ - pthread_mutex_lock(&LOCK_plugin); + mysql_mutex_lock(&LOCK_plugin); reap= (st_plugin_int **) my_alloca((plugin_array.elements+1) * sizeof(void*)); *(reap++)= NULL; @@ -1255,15 +1339,15 @@ int plugin_init(int *argc, char **argv, int flags) */ while ((plugin_ptr= *(--reap))) { - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); if (plugin_ptr->is_mandatory) reaped_mandatory_plugin= TRUE; plugin_deinitialize(plugin_ptr, true); - pthread_mutex_lock(&LOCK_plugin); + mysql_mutex_lock(&LOCK_plugin); plugin_del(plugin_ptr); } - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); my_afree(reap); if (reaped_mandatory_plugin) goto err; @@ -1274,7 +1358,7 @@ end: DBUG_RETURN(0); err_unlock: - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); err: free_root(&tmp_root, MYF(0)); DBUG_RETURN(1); @@ -1303,7 +1387,6 @@ static bool register_builtin(struct st_mysql_plugin *plugin, DBUG_RETURN(0); } - #ifdef NOT_USED_YET /* Register a plugin at run time. (note, this doesn't initialize a plugin) @@ -1329,18 +1412,21 @@ bool plugin_register_builtin(THD *thd, struct st_mysql_plugin *plugin) tmp.name.str= (char *)plugin->name; tmp.name.length= strlen(plugin->name); - pthread_mutex_lock(&LOCK_plugin); - rw_wrlock(&LOCK_system_variables_hash); + mysql_mutex_lock(&LOCK_plugin); + mysql_rwlock_wrlock(&LOCK_system_variables_hash); if (test_plugin_options(thd->mem_root, &tmp, &dummy_argc, NULL)) goto end; tmp.state= PLUGIN_IS_UNINITIALIZED; if ((result= register_builtin(plugin, &tmp, &ptr))) + { mysql_del_sys_var_chain(tmp.system_vars); + restore_pluginvar_names(tmp.system_vars); + } end: - rw_unlock(&LOCK_system_variables_hash); - pthread_mutex_unlock(&LOCK_plugin); + mysql_rwlock_unlock(&LOCK_system_variables_hash); + mysql_mutex_unlock(&LOCK_plugin); DBUG_RETURN(result);; } @@ -1352,27 +1438,22 @@ end: */ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv) { + THD thd; TABLE_LIST tables; TABLE *table; READ_RECORD read_record_info; int error; - THD *new_thd; + THD *new_thd= &thd; #ifdef EMBEDDED_LIBRARY bool table_exists; #endif /* EMBEDDED_LIBRARY */ DBUG_ENTER("plugin_load"); - if (!(new_thd= new THD)) - { - sql_print_error("Can't allocate memory for plugin structures"); - delete new_thd; - DBUG_VOID_RETURN; - } new_thd->thread_stack= (char*) &tables; new_thd->store_globals(); - lex_start(new_thd); new_thd->db= my_strdup("mysql", MYF(0)); new_thd->db_length= 5; + bzero((char*) &thd.net, sizeof(thd.net)); bzero((uchar*)&tables, sizeof(tables)); tables.alias= tables.table_name= (char*)"plugin"; tables.lock_type= TL_READ; @@ -1383,10 +1464,10 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv) When building an embedded library, if the mysql.plugin table does not exist, we silently ignore the missing table */ - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (check_if_table_exists(new_thd, &tables, &table_exists)) table_exists= FALSE; - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); if (!table_exists) goto end; #endif /* EMBEDDED_LIBRARY */ @@ -1404,10 +1485,10 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv) /* there're no other threads running yet, so we don't need a mutex. but plugin_add() before is designed to work in multi-threaded - environment, and it uses safe_mutex_assert_owner(), so we lock + environment, and it uses mysql_mutex_assert_owner(), so we lock the mutex here to satisfy the assert */ - pthread_mutex_lock(&LOCK_plugin); + mysql_mutex_lock(&LOCK_plugin); while (!(error= read_record_info.read_record(&read_record_info))) { DBUG_PRINT("info", ("init plugin record")); @@ -1423,14 +1504,13 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv) str_name.c_ptr(), str_dl.c_ptr()); free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE)); } - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); if (error > 0) sql_print_error(ER(ER_GET_ERRNO), my_errno); end_read_record(&read_record_info); new_thd->version--; // Force close to free memory end: close_thread_tables(new_thd); - delete new_thd; /* Remember that we don't have a THD */ my_pthread_setspecific_ptr(THR_THD, 0); DBUG_VOID_RETURN; @@ -1475,7 +1555,7 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv, } dl= name; - pthread_mutex_lock(&LOCK_plugin); + mysql_mutex_lock(&LOCK_plugin); if ((plugin_dl= plugin_dl_add(&dl, REPORT_TO_LOG))) { for (plugin= plugin_dl->plugins; plugin->info; plugin++) @@ -1493,11 +1573,11 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv, else { free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE)); - pthread_mutex_lock(&LOCK_plugin); + mysql_mutex_lock(&LOCK_plugin); if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG)) goto error; } - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); name.length= dl.length= 0; dl.str= NULL; name.str= p= buffer; str= &name; @@ -1518,7 +1598,7 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv, } DBUG_RETURN(FALSE); error: - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); sql_print_error("Couldn't load plugin named '%s' with soname '%s'.", name.str, dl.str); DBUG_RETURN(TRUE); @@ -1534,7 +1614,7 @@ void plugin_shutdown(void) if (initialized) { - pthread_mutex_lock(&LOCK_plugin); + mysql_mutex_lock(&LOCK_plugin); reap_needed= true; @@ -1579,7 +1659,7 @@ void plugin_shutdown(void) if (plugins[i]->state == PLUGIN_IS_DELETED) plugins[i]->state= PLUGIN_IS_DYING; } - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); /* We loop through all plugins and call deinit() if they have one. @@ -1600,9 +1680,9 @@ void plugin_shutdown(void) /* It's perfectly safe not to lock LOCK_plugin, as there're no concurrent threads anymore. But some functions called from here - use safe_mutex_assert_owner(), so we lock the mutex to satisfy it + use mysql_mutex_assert_owner(), so we lock the mutex to satisfy it */ - pthread_mutex_lock(&LOCK_plugin); + mysql_mutex_lock(&LOCK_plugin); /* We defer checking ref_counts until after all plugins are deinitialized @@ -1623,10 +1703,10 @@ void plugin_shutdown(void) cleanup_variables(NULL, &global_system_variables); cleanup_variables(NULL, &max_system_variables); - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); initialized= 0; - pthread_mutex_destroy(&LOCK_plugin); + mysql_mutex_destroy(&LOCK_plugin); my_afree(plugins); } @@ -1674,14 +1754,14 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl if (! (table = open_ltable(thd, &tables, TL_WRITE, 0))) DBUG_RETURN(TRUE); - pthread_mutex_lock(&LOCK_plugin); - rw_wrlock(&LOCK_system_variables_hash); + mysql_mutex_lock(&LOCK_plugin); + mysql_rwlock_wrlock(&LOCK_system_variables_hash); my_load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv, NULL); error= plugin_add(thd->mem_root, name, dl, &argc, argv, REPORT_TO_USER); if (argv) free_defaults(argv); - rw_unlock(&LOCK_system_variables_hash); + mysql_rwlock_unlock(&LOCK_system_variables_hash); if (error || !(tmp= plugin_find_internal(name, MYSQL_ANY_PLUGIN))) goto err; @@ -1694,7 +1774,6 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl } else { - DBUG_ASSERT(tmp->state == PLUGIN_IS_UNINITIALIZED); if (plugin_initialize(tmp)) { my_error(ER_CANT_INITIALIZE_UDF, MYF(0), name->str, @@ -1721,14 +1800,14 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl goto deinit; } - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); DBUG_RETURN(FALSE); deinit: tmp->state= PLUGIN_IS_DELETED; reap_needed= true; reap_plugins(); err: - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); DBUG_RETURN(TRUE); } @@ -1748,7 +1827,7 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name) if (! (table= open_ltable(thd, &tables, TL_WRITE, 0))) DBUG_RETURN(TRUE); - pthread_mutex_lock(&LOCK_plugin); + mysql_mutex_lock(&LOCK_plugin); if (!(plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN))) { my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PLUGIN", name->str); @@ -1769,7 +1848,7 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name) else reap_needed= true; reap_plugins(); - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); uchar user_key[MAX_KEY_LENGTH]; table->use_all_columns(); @@ -1796,7 +1875,7 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name) } DBUG_RETURN(FALSE); err: - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); DBUG_RETURN(TRUE); } @@ -1814,7 +1893,7 @@ bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func, state_mask= ~state_mask; // do it only once - pthread_mutex_lock(&LOCK_plugin); + mysql_mutex_lock(&LOCK_plugin); total= type == MYSQL_ANY_PLUGIN ? plugin_array.elements : plugin_hash[type].records; /* @@ -1839,17 +1918,17 @@ bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func, plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL; } } - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); for (idx= 0; idx < total; idx++) { if (unlikely(version != plugin_array_version)) { - pthread_mutex_lock(&LOCK_plugin); + mysql_mutex_lock(&LOCK_plugin); for (uint i=idx; i < total; i++) if (plugins[i] && plugins[i]->state & state_mask) plugins[i]=0; - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); } plugin= plugins[idx]; /* It will stop iterating on first engine error when "func" returns TRUE */ @@ -1912,7 +1991,7 @@ static int check_func_bool(THD *thd, struct st_mysql_sys_var *var, void *save, st_mysql_value *value) { char buff[STRING_BUFFER_USUAL_SIZE]; - const char *strvalue= "NULL", *str; + const char *str; int result, length; long long tmp; @@ -1921,28 +2000,19 @@ static int check_func_bool(THD *thd, struct st_mysql_sys_var *var, length= sizeof(buff); if (!(str= value->val_str(value, buff, &length)) || (result= find_type(&bool_typelib, str, length, 1)-1) < 0) - { - if (str) - strvalue= str; goto err; - } } else { if (value->val_int(value, &tmp) < 0) goto err; if (tmp > 1) - { - llstr(tmp, buff); - strvalue= buff; goto err; - } result= (int) tmp; } *(my_bool *) save= -result; return 0; err: - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue); return 1; } @@ -1950,60 +2020,87 @@ err: static int check_func_int(THD *thd, struct st_mysql_sys_var *var, void *save, st_mysql_value *value) { - my_bool fixed; - long long tmp; + my_bool fixed1, fixed2; + long long orig, val; struct my_option options; - value->val_int(value, &tmp); + value->val_int(value, &orig); + val= orig; plugin_opt_set_limits(&options, var); if (var->flags & PLUGIN_VAR_UNSIGNED) - *(uint *)save= (uint) getopt_ull_limit_value((ulonglong) tmp, &options, - &fixed); + { + if ((fixed1= (!value->is_unsigned(value) && val < 0))) + val=0; + *(uint *)save= (uint) getopt_ull_limit_value((ulonglong) val, &options, + &fixed2); + } else - *(int *)save= (int) getopt_ll_limit_value(tmp, &options, &fixed); + { + if ((fixed1= (value->is_unsigned(value) && val < 0))) + val=LONGLONG_MAX; + *(int *)save= (int) getopt_ll_limit_value(val, &options, &fixed2); + } - return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED, - var->name, (longlong) tmp); + return throw_bounds_warning(thd, var->name, fixed1 || fixed2, + value->is_unsigned(value), (longlong) orig); } static int check_func_long(THD *thd, struct st_mysql_sys_var *var, void *save, st_mysql_value *value) { - my_bool fixed; - long long tmp; + my_bool fixed1, fixed2; + long long orig, val; struct my_option options; - value->val_int(value, &tmp); + value->val_int(value, &orig); + val= orig; plugin_opt_set_limits(&options, var); if (var->flags & PLUGIN_VAR_UNSIGNED) - *(ulong *)save= (ulong) getopt_ull_limit_value((ulonglong) tmp, &options, - &fixed); + { + if ((fixed1= (!value->is_unsigned(value) && val < 0))) + val=0; + *(ulong *)save= (ulong) getopt_ull_limit_value((ulonglong) val, &options, + &fixed2); + } else - *(long *)save= (long) getopt_ll_limit_value(tmp, &options, &fixed); + { + if ((fixed1= (value->is_unsigned(value) && val < 0))) + val=LONGLONG_MAX; + *(long *)save= (long) getopt_ll_limit_value(val, &options, &fixed2); + } - return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED, - var->name, (longlong) tmp); + return throw_bounds_warning(thd, var->name, fixed1 || fixed2, + value->is_unsigned(value), (longlong) orig); } static int check_func_longlong(THD *thd, struct st_mysql_sys_var *var, void *save, st_mysql_value *value) { - my_bool fixed; - long long tmp; + my_bool fixed1, fixed2; + long long orig, val; struct my_option options; - value->val_int(value, &tmp); + value->val_int(value, &orig); + val= orig; plugin_opt_set_limits(&options, var); if (var->flags & PLUGIN_VAR_UNSIGNED) - *(ulonglong *)save= getopt_ull_limit_value((ulonglong) tmp, &options, - &fixed); + { + if ((fixed1= (!value->is_unsigned(value) && val < 0))) + val=0; + *(ulonglong *)save= getopt_ull_limit_value((ulonglong) val, &options, + &fixed2); + } else - *(longlong *)save= getopt_ll_limit_value(tmp, &options, &fixed); + { + if ((fixed1= (value->is_unsigned(value) && val < 0))) + val=LONGLONG_MAX; + *(longlong *)save= getopt_ll_limit_value(val, &options, &fixed2); + } - return throw_bounds_warning(thd, fixed, var->flags & PLUGIN_VAR_UNSIGNED, - var->name, (longlong) tmp); + return throw_bounds_warning(thd, var->name, fixed1 || fixed2, + value->is_unsigned(value), (longlong) orig); } static int check_func_str(THD *thd, struct st_mysql_sys_var *var, @@ -2025,7 +2122,7 @@ static int check_func_enum(THD *thd, struct st_mysql_sys_var *var, void *save, st_mysql_value *value) { char buff[STRING_BUFFER_USUAL_SIZE]; - const char *strvalue= "NULL", *str; + const char *str; TYPELIB *typelib; long long tmp; long result; @@ -2041,28 +2138,20 @@ static int check_func_enum(THD *thd, struct st_mysql_sys_var *var, length= sizeof(buff); if (!(str= value->val_str(value, buff, &length))) goto err; - if ((result= (long)find_type(typelib, str, length, 1)-1) < 0) - { - strvalue= str; + if ((result= (long)find_type(typelib, str, length, 0) - 1) < 0) goto err; - } } else { if (value->val_int(value, &tmp)) goto err; - if (tmp >= typelib->count) - { - llstr(tmp, buff); - strvalue= buff; + if (tmp < 0 || tmp >= typelib->count) goto err; - } result= (long) tmp; } *(long*)save= result; return 0; err: - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue); return 1; } @@ -2071,7 +2160,7 @@ static int check_func_set(THD *thd, struct st_mysql_sys_var *var, void *save, st_mysql_value *value) { char buff[STRING_BUFFER_USUAL_SIZE], *error= 0; - const char *strvalue= "NULL", *str; + const char *str; TYPELIB *typelib; ulonglong result; uint error_len= 0; // init as only set on error @@ -2091,28 +2180,19 @@ static int check_func_set(THD *thd, struct st_mysql_sys_var *var, result= find_set(typelib, str, length, NULL, &error, &error_len, ¬_used); if (error_len) - { - strmake(buff, error, min(sizeof(buff) - 1, error_len)); - strvalue= buff; goto err; - } } else { if (value->val_int(value, (long long *)&result)) goto err; - if (unlikely((result >= (ULL(1) << typelib->count)) && + if (unlikely((result >= (1ULL << typelib->count)) && (typelib->count < sizeof(long)*8))) - { - llstr(result, buff); - strvalue= buff; goto err; - } } *(ulonglong*)save= result; return 0; err: - my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->name, strvalue); return 1; } @@ -2170,12 +2250,12 @@ sys_var *find_sys_var(THD *thd, const char *str, uint length) plugin_ref plugin; DBUG_ENTER("find_sys_var"); - pthread_mutex_lock(&LOCK_plugin); - rw_rdlock(&LOCK_system_variables_hash); - if ((var= intern_find_sys_var(str, length, false)) && + mysql_mutex_lock(&LOCK_plugin); + mysql_rwlock_rdlock(&LOCK_system_variables_hash); + if ((var= intern_find_sys_var(str, length)) && (pi= var->cast_pluginvar())) { - rw_unlock(&LOCK_system_variables_hash); + mysql_rwlock_unlock(&LOCK_system_variables_hash); LEX *lex= thd ? thd->lex : 0; if (!(plugin= my_intern_plugin_lock(lex, plugin_int_to_ref(pi->plugin)))) var= NULL; /* failed to lock it, it must be uninstalling */ @@ -2188,14 +2268,10 @@ sys_var *find_sys_var(THD *thd, const char *str, uint length) } } else - rw_unlock(&LOCK_system_variables_hash); - pthread_mutex_unlock(&LOCK_plugin); + mysql_rwlock_unlock(&LOCK_system_variables_hash); + mysql_mutex_unlock(&LOCK_plugin); - /* - If the variable exists but the plugin it is associated with is not ready - then the intern_plugin_lock did not raise an error, so we do it here. - */ - if (pi && !var) + if (!var) my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str); DBUG_RETURN(var); } @@ -2345,6 +2421,15 @@ static st_bookmark *register_var(const char *plugin, const char *name, return result; } +static void restore_pluginvar_names(sys_var *first) +{ + for (sys_var *var= first; var; var= var->next) + { + sys_var_pluginvar *pv= var->cast_pluginvar(); + pv->plugin_var->name= pv->orig_pluginvar_name; + } +} + /* returns a pointer to the memory which holds the thd-local variable or @@ -2368,7 +2453,7 @@ static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock) { uint idx; - rw_rdlock(&LOCK_system_variables_hash); + mysql_rwlock_rdlock(&LOCK_system_variables_hash); thd->variables.dynamic_variables_ptr= (char*) my_realloc(thd->variables.dynamic_variables_ptr, @@ -2376,9 +2461,9 @@ static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock) MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); if (global_lock) - pthread_mutex_lock(&LOCK_global_system_variables); + mysql_mutex_lock(&LOCK_global_system_variables); - safe_mutex_assert_owner(&LOCK_global_system_variables); + mysql_mutex_assert_owner(&LOCK_global_system_variables); memcpy(thd->variables.dynamic_variables_ptr + thd->variables.dynamic_variables_size, @@ -2398,7 +2483,7 @@ static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock) st_bookmark *v= (st_bookmark*) my_hash_element(&bookmark_hash,idx); if (v->version <= thd->variables.dynamic_variables_version || - !(var= intern_find_sys_var(v->key + 1, v->name_len, true)) || + !(var= intern_find_sys_var(v->key + 1, v->name_len)) || !(pi= var->cast_pluginvar()) || v->key[0] != (pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK)) continue; @@ -2417,7 +2502,7 @@ static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock) } if (global_lock) - pthread_mutex_unlock(&LOCK_global_system_variables); + mysql_mutex_unlock(&LOCK_global_system_variables); thd->variables.dynamic_variables_version= global_system_variables.dynamic_variables_version; @@ -2426,7 +2511,7 @@ static uchar *intern_sys_var_ptr(THD* thd, int offset, bool global_lock) thd->variables.dynamic_variables_size= global_system_variables.dynamic_variables_size; - rw_unlock(&LOCK_system_variables_hash); + mysql_rwlock_unlock(&LOCK_system_variables_hash); } return (uchar*)thd->variables.dynamic_variables_ptr + offset; } @@ -2453,11 +2538,11 @@ void plugin_thdvar_init(THD *thd) thd->variables.dynamic_variables_size= 0; thd->variables.dynamic_variables_ptr= 0; - pthread_mutex_lock(&LOCK_plugin); + mysql_mutex_lock(&LOCK_plugin); thd->variables.table_plugin= my_intern_plugin_lock(NULL, global_system_variables.table_plugin); intern_plugin_unlock(NULL, old_table_plugin); - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); DBUG_VOID_RETURN; } @@ -2486,12 +2571,12 @@ static void cleanup_variables(THD *thd, struct system_variables *vars) int flags; uint idx; - rw_rdlock(&LOCK_system_variables_hash); + mysql_rwlock_rdlock(&LOCK_system_variables_hash); for (idx= 0; idx < bookmark_hash.records; idx++) { v= (st_bookmark*) my_hash_element(&bookmark_hash, idx); if (v->version > vars->dynamic_variables_version || - !(var= intern_find_sys_var(v->key + 1, v->name_len, true)) || + !(var= intern_find_sys_var(v->key + 1, v->name_len)) || !(pivar= var->cast_pluginvar()) || v->key[0] != (pivar->plugin_var->flags & PLUGIN_VAR_TYPEMASK)) continue; @@ -2506,7 +2591,7 @@ static void cleanup_variables(THD *thd, struct system_variables *vars) *ptr= NULL; } } - rw_unlock(&LOCK_system_variables_hash); + mysql_rwlock_unlock(&LOCK_system_variables_hash); DBUG_ASSERT(vars->table_plugin == NULL); @@ -2523,7 +2608,7 @@ void plugin_thdvar_cleanup(THD *thd) plugin_ref *list; DBUG_ENTER("plugin_thdvar_cleanup"); - pthread_mutex_lock(&LOCK_plugin); + mysql_mutex_lock(&LOCK_plugin); unlock_variables(thd, &thd->variables); cleanup_variables(thd, &thd->variables); @@ -2537,7 +2622,7 @@ void plugin_thdvar_cleanup(THD *thd) } reap_plugins(); - pthread_mutex_unlock(&LOCK_plugin); + mysql_mutex_unlock(&LOCK_plugin); reset_dynamic(&thd->lex->plugins); @@ -2570,7 +2655,7 @@ static void plugin_vars_free_values(sys_var *vars) /* Free the string from global_system_variables. */ char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL); DBUG_PRINT("plugin", ("freeing value for: '%s' addr: 0x%lx", - var->name, (long) valptr)); + var->name.str, (long) valptr)); my_free(*valptr, MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR)); *valptr= NULL; } @@ -2578,43 +2663,44 @@ static void plugin_vars_free_values(sys_var *vars) DBUG_VOID_RETURN; } - -bool sys_var_pluginvar::check_update_type(Item_result type) +static SHOW_TYPE pluginvar_show_type(st_mysql_sys_var *plugin_var) { - if (is_readonly()) - return 1; switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) { + case PLUGIN_VAR_BOOL: + return SHOW_MY_BOOL; case PLUGIN_VAR_INT: + return SHOW_INT; case PLUGIN_VAR_LONG: + return SHOW_LONG; case PLUGIN_VAR_LONGLONG: - return type != INT_RESULT; + return SHOW_LONGLONG; case PLUGIN_VAR_STR: - return type != STRING_RESULT; + return SHOW_CHAR_PTR; + case PLUGIN_VAR_ENUM: + case PLUGIN_VAR_SET: + return SHOW_CHAR; default: - return 0; + DBUG_ASSERT(0); + return SHOW_UNDEF; } } -SHOW_TYPE sys_var_pluginvar::show_type() +bool sys_var_pluginvar::check_update_type(Item_result type) { switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) { - case PLUGIN_VAR_BOOL: - return SHOW_MY_BOOL; case PLUGIN_VAR_INT: - return SHOW_INT; case PLUGIN_VAR_LONG: - return SHOW_LONG; case PLUGIN_VAR_LONGLONG: - return SHOW_LONGLONG; + return type != INT_RESULT; case PLUGIN_VAR_STR: - return SHOW_CHAR_PTR; + return type != STRING_RESULT; case PLUGIN_VAR_ENUM: + case PLUGIN_VAR_BOOL: case PLUGIN_VAR_SET: - return SHOW_CHAR; + return type != STRING_RESULT && type != INT_RESULT; default: - DBUG_ASSERT(0); - return SHOW_UNDEF; + return true; } } @@ -2647,12 +2733,12 @@ TYPELIB* sys_var_pluginvar::plugin_var_typelib(void) default: return NULL; } - return NULL; + return NULL; /* Keep compiler happy */ } -uchar* sys_var_pluginvar::value_ptr(THD *thd, enum_var_type type, - LEX_STRING *base) +uchar* sys_var_pluginvar::do_value_ptr(THD *thd, enum_var_type type, + LEX_STRING *base) { uchar* result; @@ -2661,139 +2747,104 @@ uchar* sys_var_pluginvar::value_ptr(THD *thd, enum_var_type type, if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_ENUM) result= (uchar*) get_type(plugin_var_typelib(), *(ulong*)result); else if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_SET) - { - char buffer[STRING_BUFFER_USUAL_SIZE]; - String str(buffer, sizeof(buffer), system_charset_info); - TYPELIB *typelib= plugin_var_typelib(); - ulonglong mask= 1, value= *(ulonglong*) result; - uint i; - - str.length(0); - for (i= 0; i < typelib->count; i++, mask<<=1) - { - if (!(value & mask)) - continue; - str.append(typelib->type_names[i], typelib->type_lengths - ? typelib->type_lengths[i] - : strlen(typelib->type_names[i])); - str.append(','); - } - - result= (uchar*) ""; - if (str.length()) - result= (uchar*) thd->strmake(str.ptr(), str.length()-1); - } + result= (uchar*) set_to_string(thd, 0, *(ulonglong*) result, + plugin_var_typelib()->type_names); return result; } - -bool sys_var_pluginvar::check(THD *thd, set_var *var) +bool sys_var_pluginvar::do_check(THD *thd, set_var *var) { st_item_value_holder value; - DBUG_ASSERT(is_readonly() || plugin_var->check); + DBUG_ASSERT(!is_readonly()); + DBUG_ASSERT(plugin_var->check); value.value_type= item_value_type; value.val_str= item_val_str; value.val_int= item_val_int; value.val_real= item_val_real; + value.is_unsigned= item_is_unsigned; value.item= var->value; - return is_readonly() || - plugin_var->check(thd, plugin_var, &var->save_result, &value); + return plugin_var->check(thd, plugin_var, &var->save_result, &value); } - -void sys_var_pluginvar::set_default(THD *thd, enum_var_type type) +bool sys_var_pluginvar::session_update(THD *thd, set_var *var) { - const void *src; - void *tgt; - - DBUG_ASSERT(is_readonly() || plugin_var->update); + DBUG_ASSERT(!is_readonly()); + DBUG_ASSERT(plugin_var->flags & PLUGIN_VAR_THDLOCAL); + DBUG_ASSERT(thd == current_thd); - if (is_readonly()) - return; - - pthread_mutex_lock(&LOCK_global_system_variables); - tgt= real_value_ptr(thd, type); - src= ((void **) (plugin_var + 1) + 1); + mysql_mutex_lock(&LOCK_global_system_variables); + void *tgt= real_value_ptr(thd, var->type); + const void *src= var->value ? (void*)&var->save_result + : (void*)real_value_ptr(thd, OPT_GLOBAL); + mysql_mutex_unlock(&LOCK_global_system_variables); + plugin_var->update(thd, plugin_var, tgt, src); - if (plugin_var->flags & PLUGIN_VAR_THDLOCAL) - { - if (type != OPT_GLOBAL) - src= real_value_ptr(thd, OPT_GLOBAL); - else - switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) { - case PLUGIN_VAR_INT: - src= &((thdvar_uint_t*) plugin_var)->def_val; - break; - case PLUGIN_VAR_LONG: - src= &((thdvar_ulong_t*) plugin_var)->def_val; - break; - case PLUGIN_VAR_LONGLONG: - src= &((thdvar_ulonglong_t*) plugin_var)->def_val; - break; - case PLUGIN_VAR_ENUM: - src= &((thdvar_enum_t*) plugin_var)->def_val; - break; - case PLUGIN_VAR_SET: - src= &((thdvar_set_t*) plugin_var)->def_val; - break; - case PLUGIN_VAR_BOOL: - src= &((thdvar_bool_t*) plugin_var)->def_val; - break; - case PLUGIN_VAR_STR: - src= &((thdvar_str_t*) plugin_var)->def_val; - break; - default: - DBUG_ASSERT(0); - } - } - - /* thd must equal current_thd if PLUGIN_VAR_THDLOCAL flag is set */ - DBUG_ASSERT(!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || - thd == current_thd); - - if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || type == OPT_GLOBAL) - { - plugin_var->update(thd, plugin_var, tgt, src); - pthread_mutex_unlock(&LOCK_global_system_variables); - } - else - { - pthread_mutex_unlock(&LOCK_global_system_variables); - plugin_var->update(thd, plugin_var, tgt, src); - } + return false; } - -bool sys_var_pluginvar::update(THD *thd, set_var *var) +bool sys_var_pluginvar::global_update(THD *thd, set_var *var) { - void *tgt; + DBUG_ASSERT(!is_readonly()); + mysql_mutex_assert_owner(&LOCK_global_system_variables); - DBUG_ASSERT(is_readonly() || plugin_var->update); + void *tgt= real_value_ptr(thd, var->type); + const void *src= &var->save_result; - /* thd must equal current_thd if PLUGIN_VAR_THDLOCAL flag is set */ - DBUG_ASSERT(!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || - thd == current_thd); - - if (is_readonly()) - return 1; - - pthread_mutex_lock(&LOCK_global_system_variables); - tgt= real_value_ptr(thd, var->type); - - if (!(plugin_var->flags & PLUGIN_VAR_THDLOCAL) || var->type == OPT_GLOBAL) - { - /* variable we are updating has global scope, so we unlock after updating */ - plugin_var->update(thd, plugin_var, tgt, &var->save_result); - pthread_mutex_unlock(&LOCK_global_system_variables); - } - else + if (!var->value) { - pthread_mutex_unlock(&LOCK_global_system_variables); - plugin_var->update(thd, plugin_var, tgt, &var->save_result); + switch (plugin_var->flags & (PLUGIN_VAR_TYPEMASK | PLUGIN_VAR_THDLOCAL)) { + case PLUGIN_VAR_INT: + src= &((sysvar_uint_t*) plugin_var)->def_val; + break; + case PLUGIN_VAR_LONG: + src= &((sysvar_ulong_t*) plugin_var)->def_val; + break; + case PLUGIN_VAR_LONGLONG: + src= &((sysvar_ulonglong_t*) plugin_var)->def_val; + break; + case PLUGIN_VAR_ENUM: + src= &((sysvar_enum_t*) plugin_var)->def_val; + break; + case PLUGIN_VAR_SET: + src= &((sysvar_set_t*) plugin_var)->def_val; + break; + case PLUGIN_VAR_BOOL: + src= &((sysvar_bool_t*) plugin_var)->def_val; + break; + case PLUGIN_VAR_STR: + src= &((sysvar_str_t*) plugin_var)->def_val; + break; + case PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL: + src= &((thdvar_uint_t*) plugin_var)->def_val; + break; + case PLUGIN_VAR_LONG | PLUGIN_VAR_THDLOCAL: + src= &((thdvar_ulong_t*) plugin_var)->def_val; + break; + case PLUGIN_VAR_LONGLONG | PLUGIN_VAR_THDLOCAL: + src= &((thdvar_ulonglong_t*) plugin_var)->def_val; + break; + case PLUGIN_VAR_ENUM | PLUGIN_VAR_THDLOCAL: + src= &((thdvar_enum_t*) plugin_var)->def_val; + break; + case PLUGIN_VAR_SET | PLUGIN_VAR_THDLOCAL: + src= &((thdvar_set_t*) plugin_var)->def_val; + break; + case PLUGIN_VAR_BOOL | PLUGIN_VAR_THDLOCAL: + src= &((thdvar_bool_t*) plugin_var)->def_val; + break; + case PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL: + src= &((thdvar_str_t*) plugin_var)->def_val; + break; + default: + DBUG_ASSERT(0); + } } - return 0; + + plugin_var->update(thd, plugin_var, tgt, src); + + return false; } @@ -2843,7 +2894,7 @@ static void plugin_opt_set_limits(struct my_option *options, options->typelib= ((sysvar_set_t*) opt)->typelib; options->def_value= ((sysvar_set_t*) opt)->def_val; options->min_value= options->block_size= 0; - options->max_value= (ULL(1) << options->typelib->count) - 1; + options->max_value= (1ULL << options->typelib->count) - 1; break; case PLUGIN_VAR_BOOL: options->var_type= GET_BOOL; @@ -2885,7 +2936,7 @@ static void plugin_opt_set_limits(struct my_option *options, options->typelib= ((thdvar_set_t*) opt)->typelib; options->def_value= ((thdvar_set_t*) opt)->def_val; options->min_value= options->block_size= 0; - options->max_value= (ULL(1) << options->typelib->count) - 1; + options->max_value= (1ULL << options->typelib->count) - 1; break; case PLUGIN_VAR_BOOL | PLUGIN_VAR_THDLOCAL: options->var_type= GET_BOOL; @@ -2956,40 +3007,48 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, DBUG_ENTER("construct_options"); - options[0].name= plugin_name_ptr= (char*) alloc_root(mem_root, - plugin_name_len + 1); + plugin_name_ptr= (char*) alloc_root(mem_root, plugin_name_len + 1); strcpy(plugin_name_ptr, plugin_name); my_casedn_str(&my_charset_latin1, plugin_name_ptr); convert_underscore_to_dash(plugin_name_ptr, plugin_name_len); - /* support --skip-plugin-foo syntax */ - options[1].name= plugin_name_with_prefix_ptr= (char*) alloc_root(mem_root, - plugin_name_len + - plugin_dash.length + 1); - strxmov(plugin_name_with_prefix_ptr, plugin_dash.str, options[0].name, NullS); - - options[0].id= options[1].id= 256; /* must be >255. dup id ok */ - options[0].var_type= options[1].var_type= GET_ENUM; - options[0].arg_type= options[1].arg_type= OPT_ARG; - options[0].def_value= options[1].def_value= 1; /* ON */ - options[0].typelib= options[1].typelib= &global_plugin_typelib; - - strxnmov(comment, max_comment_len, "Enable or disable ", plugin_name, - " plugin. Possible values are ON, OFF, FORCE (don't start " - "if the plugin fails to load).", NullS); - options[0].comment= comment; + plugin_name_with_prefix_ptr= (char*) alloc_root(mem_root, + plugin_name_len + + plugin_dash.length + 1); + strxmov(plugin_name_with_prefix_ptr, plugin_dash.str, plugin_name_ptr, NullS); + + if (!tmp->is_mandatory) + { + /* support --skip-plugin-foo syntax */ + options[0].name= plugin_name_ptr; + options[1].name= plugin_name_with_prefix_ptr; + options[0].id= options[1].id= 0; + options[0].var_type= options[1].var_type= GET_ENUM; + options[0].arg_type= options[1].arg_type= OPT_ARG; + options[0].def_value= options[1].def_value= 1; /* ON */ + options[0].typelib= options[1].typelib= &global_plugin_typelib; + + strxnmov(comment, max_comment_len, "Enable or disable ", plugin_name, + " plugin. Possible values are ON, OFF, FORCE (don't start " + "if the plugin fails to load).", NullS); + options[0].comment= comment; + /* + Allocate temporary space for the value of the tristate. + This option will have a limited lifetime and is not used beyond + server initialization. + GET_ENUM value is an unsigned integer. + */ + options[0].value= options[1].value= + (uchar **)alloc_root(mem_root, sizeof(uint)); + *((uint*) options[0].value)= (uint) options[0].def_value; - /* - Allocate temporary space for the value of the tristate. - This option will have a limited lifetime and is not used beyond - server initialization. - GET_ENUM value is an integer. - */ - options[0].value= options[1].value= (uchar **)alloc_root(mem_root, - sizeof(int)); - *((uint*) options[0].value)= *((uint*) options[1].value)= - (uint) options[0].def_value; + options+= 2; + } - options+= 2; + if (!my_strcasecmp(&my_charset_latin1, plugin_name_ptr, "NDBCLUSTER")) + { + plugin_name_ptr= const_cast<char*>("ndb"); // Use legacy "ndb" prefix + plugin_name_len= 3; + } /* Two passes as the 2nd pass will take pointer addresses for use @@ -3137,7 +3196,7 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, options->name= optname; options->comment= opt->comment; options->app_type= opt; - options->id= (options-1)->id + 1; + options->id= 0; plugin_opt_set_limits(options, opt); @@ -3178,13 +3237,20 @@ static my_option *construct_help_options(MEM_ROOT *mem_root, bzero(opts, sizeof(my_option) * count); + /** + some plugin variables (those that don't have PLUGIN_VAR_NOSYSVAR flag) + have their names prefixed with the plugin name. Restore the names here + to get the correct (not double-prefixed) help text. + We won't need @@sysvars anymore and don't care about their proper names. + */ + restore_pluginvar_names(p->system_vars); + if (construct_options(mem_root, p, opts)) DBUG_RETURN(NULL); DBUG_RETURN(opts); } - /** Create and register system variables supplied from the plugin and assigns initial values from corresponding command line arguments. @@ -3209,18 +3275,17 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, int *argc, char **argv) { struct sys_var_chain chain= { NULL, NULL }; - my_bool can_disable; bool disable_plugin; - enum_plugin_load_policy plugin_load_policy= PLUGIN_ON; + enum_plugin_load_policy plugin_load_policy= tmp->is_mandatory ? PLUGIN_FORCE : PLUGIN_ON; MEM_ROOT *mem_root= alloc_root_inited(&tmp->mem_root) ? &tmp->mem_root : &plugin_mem_root; st_mysql_sys_var **opt; my_option *opts= NULL; + LEX_STRING plugin_name; char *varname; int error; - st_mysql_sys_var *o; - sys_var *v; + sys_var *v __attribute__((unused)); struct st_bookmark *var; uint len, count= EXTRA_OPTIONS; DBUG_ENTER("test_plugin_options"); @@ -3256,9 +3321,10 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, We adjust the default value to account for the hardcoded exceptions we have set for the federated and ndbcluster storage engines. */ - opts[0].def_value= opts[1].def_value= (int)plugin_load_policy; + if (!tmp->is_mandatory) + opts[0].def_value= opts[1].def_value= plugin_load_policy; - error= handle_options(argc, &argv, opts, get_one_plugin_option); + error= handle_options(argc, &argv, opts, NULL); (*argc)++; /* add back one for the program name */ if (error) @@ -3271,24 +3337,12 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, Set plugin loading policy from option value. First element in the option list is always the <plugin name> option value. */ - plugin_load_policy= (enum_plugin_load_policy)*(uint*)opts[0].value; + if (!tmp->is_mandatory) + plugin_load_policy= (enum_plugin_load_policy)*(uint*)opts[0].value; } disable_plugin= (plugin_load_policy == PLUGIN_OFF); - /* - The 'MyISAM' and 'Memory' storage engines currently can't be disabled. - */ - can_disable= - my_strcasecmp(&my_charset_latin1, tmp->name.str, "MyISAM") && - my_strcasecmp(&my_charset_latin1, tmp->name.str, "MEMORY"); - - tmp->is_mandatory= (plugin_load_policy == PLUGIN_FORCE) || !can_disable; - - if (disable_plugin && !can_disable) - { - sql_print_warning("Plugin '%s' cannot be disabled", tmp->name.str); - disable_plugin= FALSE; - } + tmp->is_mandatory= (plugin_load_policy == PLUGIN_FORCE); /* If the plugin is disabled it should not be initialized. @@ -3303,34 +3357,37 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, DBUG_RETURN(1); } + if (!my_strcasecmp(&my_charset_latin1, tmp->name.str, "NDBCLUSTER")) + { + plugin_name.str= const_cast<char*>("ndb"); // Use legacy "ndb" prefix + plugin_name.length= 3; + } + else + plugin_name= tmp->name; + error= 1; for (opt= tmp->plugin->system_vars; opt && *opt; opt++) { + st_mysql_sys_var *o; if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR)) continue; - if ((var= find_bookmark(tmp->name.str, o->name, o->flags))) - v= new (mem_root) sys_var_pluginvar(var->key + 1, o); + if ((var= find_bookmark(plugin_name.str, o->name, o->flags))) + v= new (mem_root) sys_var_pluginvar(&chain, var->key + 1, o); else { - len= tmp->name.length + strlen(o->name) + 2; + len= plugin_name.length + strlen(o->name) + 2; varname= (char*) alloc_root(mem_root, len); - strxmov(varname, tmp->name.str, "-", o->name, NullS); + strxmov(varname, plugin_name.str, "-", o->name, NullS); my_casedn_str(&my_charset_latin1, varname); convert_dash_to_underscore(varname, len-1); - v= new (mem_root) sys_var_pluginvar(varname, o); + v= new (mem_root) sys_var_pluginvar(&chain, varname, o); } DBUG_ASSERT(v); /* check that an object was actually constructed */ - /* - Add to the chain of variables. - Done like this for easier debugging so that the - pointer to v is not lost on optimized builds. - */ - v->chain_sys_var(&chain); } /* end for */ if (chain.first) { chain.last->next = NULL; - if (mysql_add_sys_var_chain(chain.first, NULL)) + if (mysql_add_sys_var_chain(chain.first)) { sql_print_error("Plugin '%s' has conflicting system variables", tmp->name.str); @@ -3351,49 +3408,26 @@ err: Help Verbose text with Plugin System Variables ****************************************************************************/ -static int option_cmp(my_option *a, my_option *b) -{ - return my_strcasecmp(&my_charset_latin1, a->name, b->name); -} - -void my_print_help_inc_plugins(my_option *main_options, uint size) +void add_plugin_options(DYNAMIC_ARRAY *options, MEM_ROOT *mem_root) { - DYNAMIC_ARRAY all_options; struct st_plugin_int *p; - MEM_ROOT mem_root; my_option *opt; - init_alloc_root(&mem_root, 4096, 4096); - my_init_dynamic_array(&all_options, sizeof(my_option), size, size/4); - - if (initialized) - for (uint idx= 0; idx < plugin_array.elements; idx++) - { - p= *dynamic_element(&plugin_array, idx, struct st_plugin_int **); - - if (!p->plugin->system_vars || - !(opt= construct_help_options(&mem_root, p))) - continue; - - /* Only options with a non-NULL comment are displayed in help text */ - for (;opt->id; opt++) - if (opt->comment) - insert_dynamic(&all_options, (uchar*) opt); - } - - for (;main_options->id; main_options++) - insert_dynamic(&all_options, (uchar*) main_options); - - sort_dynamic(&all_options, (qsort_cmp) option_cmp); + if (!initialized) + return; - /* main_options now points to the empty option terminator */ - insert_dynamic(&all_options, (uchar*) main_options); + for (uint idx= 0; idx < plugin_array.elements; idx++) + { + p= *dynamic_element(&plugin_array, idx, struct st_plugin_int **); - my_print_help((my_option*) all_options.buffer); - my_print_variables((my_option*) all_options.buffer); + if (!(opt= construct_help_options(mem_root, p))) + continue; - delete_dynamic(&all_options); - free_root(&mem_root, MYF(0)); + /* Only options with a non-NULL comment are displayed in help text */ + for (;opt->name; opt++) + if (opt->comment) + insert_dynamic(options, (uchar*) opt); + } } diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h index 23ce85c994b..1a870ec260e 100644 --- a/sql/sql_plugin.h +++ b/sql/sql_plugin.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 MySQL AB +/* Copyright (C) 2005 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,6 +17,9 @@ #define _sql_plugin_h class sys_var; +enum SHOW_COMP_OPTION { SHOW_OPTION_YES, SHOW_OPTION_NO, SHOW_OPTION_DISABLED}; + +#include <my_sys.h> #ifdef DBUG_OFF #define plugin_ref_to_int(A) A @@ -37,6 +40,7 @@ class sys_var; typedef enum enum_mysql_show_type SHOW_TYPE; typedef struct st_mysql_show_var SHOW_VAR; +typedef struct st_mysql_lex_string LEX_STRING; #define MYSQL_ANY_PLUGIN -1 @@ -112,7 +116,7 @@ extern const LEX_STRING plugin_type_names[]; extern int plugin_init(int *argc, char **argv, int init_flags); extern void plugin_shutdown(void); -extern void my_print_help_inc_plugins(struct my_option *options, uint size); +void add_plugin_options(DYNAMIC_ARRAY *options, MEM_ROOT *mem_root); extern bool plugin_is_ready(const LEX_STRING *name, int type); #define my_plugin_lock_by_name(A,B,C) plugin_lock_by_name(A,B,C CALLER_INFO) #define my_plugin_lock_by_name_ci(A,B,C) plugin_lock_by_name(A,B,C ORIG_CALLER_INFO) @@ -129,6 +133,7 @@ extern bool mysql_uninstall_plugin(THD *thd, const LEX_STRING *name); extern bool plugin_register_builtin(struct st_mysql_plugin *plugin); extern void plugin_thdvar_init(THD *thd); extern void plugin_thdvar_cleanup(THD *thd); +extern SHOW_COMP_OPTION plugin_status(const char *name, int len, size_t type); typedef my_bool (plugin_foreach_func)(THD *thd, plugin_ref plugin, diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 934b87a938f..12de2bbcecc 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 1995-2002 MySQL AB +/* Copyright (C) 1995-2002 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -84,6 +84,7 @@ When one supplies long data for a placeholder: */ #include "mysql_priv.h" +#include "set_var.h" #include "sql_prepare.h" #include "sql_select.h" // for JOIN #include "sql_cursor.h" @@ -1413,7 +1414,7 @@ static int mysql_test_select(Prepared_statement *stmt, if (check_table_access(thd, privilege, tables, FALSE, UINT_MAX, FALSE)) goto error; } - else if (check_access(thd, privilege, any_db,0,0,0,0)) + else if (check_access(thd, privilege, any_db, NULL, NULL, 0, 0)) goto error; if (!lex->result && !(lex->result= new (stmt->mem_root) select_send)) @@ -2617,14 +2618,8 @@ void mysqld_stmt_fetch(THD *thd, char *packet, uint packet_length) thd->stmt_arena= stmt; thd->set_n_backup_statement(stmt, &stmt_backup); - if (!(specialflag & SPECIAL_NO_PRIOR)) - my_pthread_setprio(pthread_self(), QUERY_PRIOR); - cursor->fetch(num_rows); - if (!(specialflag & SPECIAL_NO_PRIOR)) - my_pthread_setprio(pthread_self(), WAIT_PRIOR); - if (!cursor->is_open()) { stmt->close_cursor(); @@ -3388,14 +3383,8 @@ reexecute: thd->m_reprepare_observer = &reprepare_observer; } - if (!(specialflag & SPECIAL_NO_PRIOR)) - my_pthread_setprio(pthread_self(),QUERY_PRIOR); - error= execute(expanded_query, open_cursor) || thd->is_error(); - if (!(specialflag & SPECIAL_NO_PRIOR)) - my_pthread_setprio(pthread_self(), WAIT_PRIOR); - thd->m_reprepare_observer= NULL; if (error && !thd->is_fatal_error && !thd->killed && diff --git a/sql/sql_profile.cc b/sql/sql_profile.cc index 69e5bc3cbb4..f8c11cb71b9 100644 --- a/sql/sql_profile.cc +++ b/sql/sql_profile.cc @@ -134,6 +134,26 @@ int make_profile_table_for_show(THD *thd, ST_SCHEMA_TABLE *schema_table) #define RUSAGE_USEC(tv) ((tv).tv_sec*1000*1000 + (tv).tv_usec) #define RUSAGE_DIFF_USEC(tv1, tv2) (RUSAGE_USEC((tv1))-RUSAGE_USEC((tv2))) +#ifdef _WIN32 +static ULONGLONG FileTimeToQuadWord(FILETIME *ft) +{ + // Overlay FILETIME onto a ULONGLONG. + union { + ULONGLONG qwTime; + FILETIME ft; + } u; + + u.ft = *ft; + return u.qwTime; +} + + +// Get time difference between to FILETIME objects in seconds. +static double GetTimeDiffInSeconds(FILETIME *a, FILETIME *b) +{ + return ((FileTimeToQuadWord(a) - FileTimeToQuadWord(b)) / 1e7); +} +#endif PROF_MEASUREMENT::PROF_MEASUREMENT(QUERY_PROFILE *profile_arg, const char *status_arg) @@ -224,6 +244,12 @@ void PROF_MEASUREMENT::collect() time_usecs= (double) my_getsystime() / 10.0; /* 1 sec was 1e7, now is 1e6 */ #ifdef HAVE_GETRUSAGE getrusage(RUSAGE_SELF, &rusage); +#elif defined(_WIN32) + FILETIME ftDummy; + // NOTE: Get{Process|Thread}Times has a granularity of the clock interval, + // which is typically ~15ms. So intervals shorter than that will not be + // measurable by this function. + GetProcessTimes(GetCurrentProcess(), &ftDummy, &ftDummy, &ftKernel, &ftUser); #endif } @@ -341,7 +367,7 @@ void PROFILING::start_new_query(const char *initial_state) finish_current_query(); } - enabled= (((thd)->options & OPTION_PROFILING) != 0); + enabled= ((thd->variables.option_bits & OPTION_PROFILING) != 0); if (! enabled) DBUG_VOID_RETURN; @@ -379,7 +405,7 @@ void PROFILING::finish_current_query() status_change("ending", NULL, NULL, 0); if ((enabled) && /* ON at start? */ - ((thd->options & OPTION_PROFILING) != 0) && /* and ON at end? */ + ((thd->variables.option_bits & OPTION_PROFILING) != 0) && /* and ON at end? */ (current->query_source != NULL) && (! current->entries.is_empty())) { @@ -593,6 +619,23 @@ int PROFILING::fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond) table->field[5]->store_decimal(&cpu_stime_decimal); table->field[4]->set_notnull(); table->field[5]->set_notnull(); +#elif defined(_WIN32) + my_decimal cpu_utime_decimal, cpu_stime_decimal; + + double2my_decimal(E_DEC_FATAL_ERROR, + GetTimeDiffInSeconds(&entry->ftUser, + &previous->ftUser), + &cpu_utime_decimal); + double2my_decimal(E_DEC_FATAL_ERROR, + GetTimeDiffInSeconds(&entry->ftKernel, + &previous->ftKernel), + &cpu_stime_decimal); + + // Store the result. + table->field[4]->store_decimal(&cpu_utime_decimal); + table->field[5]->store_decimal(&cpu_stime_decimal); + table->field[4]->set_notnull(); + table->field[5]->set_notnull(); #else /* TODO: Add CPU-usage info for non-BSD systems */ #endif diff --git a/sql/sql_profile.h b/sql/sql_profile.h index bffe1cb576b..31e2f1a7c50 100644 --- a/sql/sql_profile.h +++ b/sql/sql_profile.h @@ -173,6 +173,8 @@ private: char *status; #ifdef HAVE_GETRUSAGE struct rusage rusage; +#elif defined(_WIN32) + FILETIME ftKernel, ftUser; #endif char *function; diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index e85e730db5b..7c52a12c072 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright (C) 2000-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -134,10 +134,10 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) } } - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (lock_table_names_exclusively(thd, table_list)) { - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); goto err; } @@ -173,7 +173,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) higher concurrency - query_cache_invalidate can take minutes to complete. */ - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); if (!silent && !error) { @@ -185,9 +185,9 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) if (!error) query_cache_invalidate3(thd, table_list, 0); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); unlock_table_names(thd, table_list, (TABLE_LIST*) 0); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); err: start_waiting_global_read_lock(thd); diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 6d1b93ea9ea..510f9d8dc01 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB & Sasha +/* Copyright (C) 2000-2006 MySQL AB & Sasha, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,6 +29,14 @@ my_bool opt_sporadic_binlog_dump_fail = 0; static int binlog_dump_count = 0; #endif +/** + a copy of active_mi->rli->slave_skip_counter, for showing in SHOW VARIABLES, + INFORMATION_SCHEMA.GLOBAL_VARIABLES and @@sql_slave_skip_counter without + taking all the mutexes needed to access active_mi->rli->slave_skip_counter + properly. +*/ +uint sql_slave_skip_counter; + /* fake_rotate_event() builds a fake (=which does not exist physically in any binlog) Rotate event, which contains the name of the binlog we are going to @@ -143,13 +151,14 @@ static int send_file(THD *thd) if (!strcmp(fname,"/dev/null")) goto end; - if ((fd = my_open(fname, O_RDONLY, MYF(0))) < 0) + if ((fd= mysql_file_open(key_file_send_file, + fname, O_RDONLY, MYF(0))) < 0) { errmsg = "on open of file"; goto err; } - while ((long) (bytes= my_read(fd, buf, IO_SIZE, MYF(0))) > 0) + while ((long) (bytes= mysql_file_read(fd, buf, IO_SIZE, MYF(0))) > 0) { if (my_net_write(net, buf, bytes)) { @@ -170,7 +179,7 @@ static int send_file(THD *thd) err: my_net_set_read_timeout(net, old_timeout); if (fd >= 0) - (void) my_close(fd, MYF(0)); + mysql_file_close(fd, MYF(0)); if (errmsg) { sql_print_error("Failed in send_file() %s", errmsg); @@ -205,7 +214,7 @@ void adjust_linfo_offsets(my_off_t purge_offset) { THD *tmp; - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); I_List_iterator<THD> it(threads); while ((tmp=it++)) @@ -213,7 +222,7 @@ void adjust_linfo_offsets(my_off_t purge_offset) LOG_INFO* linfo; if ((linfo = tmp->current_linfo)) { - pthread_mutex_lock(&linfo->lock); + mysql_mutex_lock(&linfo->lock); /* Index file offset can be less that purge offset only if we just started reading the index file. In that case @@ -223,10 +232,10 @@ void adjust_linfo_offsets(my_off_t purge_offset) linfo->fatal = (linfo->index_file_offset != 0); else linfo->index_file_offset -= purge_offset; - pthread_mutex_unlock(&linfo->lock); + mysql_mutex_unlock(&linfo->lock); } } - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); } @@ -236,7 +245,7 @@ bool log_in_use(const char* log_name) THD *tmp; bool result = 0; - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); I_List_iterator<THD> it(threads); while ((tmp=it++)) @@ -244,39 +253,26 @@ bool log_in_use(const char* log_name) LOG_INFO* linfo; if ((linfo = tmp->current_linfo)) { - pthread_mutex_lock(&linfo->lock); + mysql_mutex_lock(&linfo->lock); result = !bcmp((uchar*) log_name, (uchar*) linfo->log_file_name, log_name_len); - pthread_mutex_unlock(&linfo->lock); + mysql_mutex_unlock(&linfo->lock); if (result) break; } } - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); return result; } bool purge_error_message(THD* thd, int res) { - uint errmsg= 0; - - switch (res) { - case 0: break; - case LOG_INFO_EOF: errmsg= ER_UNKNOWN_TARGET_BINLOG; break; - case LOG_INFO_IO: errmsg= ER_IO_ERR_LOG_INDEX_READ; break; - case LOG_INFO_INVALID:errmsg= ER_BINLOG_PURGE_PROHIBITED; break; - case LOG_INFO_SEEK: errmsg= ER_FSEEK_FAIL; break; - case LOG_INFO_MEM: errmsg= ER_OUT_OF_RESOURCES; break; - case LOG_INFO_FATAL: errmsg= ER_BINLOG_PURGE_FATAL_ERR; break; - case LOG_INFO_IN_USE: errmsg= ER_LOG_IN_USE; break; - case LOG_INFO_EMFILE: errmsg= ER_BINLOG_PURGE_EMFILE; break; - default: errmsg= ER_LOG_PURGE_UNKNOWN_ERR; break; - } + uint errcode; - if (errmsg) + if ((errcode= purge_log_get_error_code(res)) != 0) { - my_message(errmsg, ER(errmsg), MYF(0)); + my_message(errcode, ER(errcode), MYF(0)); return TRUE; } my_ok(thd); @@ -449,7 +445,7 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, int error; const char *errmsg = "Unknown error"; NET* net = &thd->net; - pthread_mutex_t *log_lock; + mysql_mutex_t *log_lock; bool binlog_can_be_corrupted= FALSE; #ifndef DBUG_OFF int left_events = max_binlog_dump_events; @@ -520,9 +516,9 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, goto err; } - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thd->current_linfo = &linfo; - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0) { @@ -802,11 +798,11 @@ impossible position"; has not been updated since last read. */ - pthread_mutex_lock(log_lock); - switch (error= Log_event::read_log_event(&log, packet, (pthread_mutex_t*) 0)) { + mysql_mutex_lock(log_lock); + switch (error= Log_event::read_log_event(&log, packet, (mysql_mutex_t*) 0)) { case 0: /* we read successfully, so we'll need to send it to the slave */ - pthread_mutex_unlock(log_lock); + mysql_mutex_unlock(log_lock); read_packet = 1; if (coord) coord->pos= uint4korr(packet->ptr() + ev_offset + LOG_POS_OFFSET); @@ -820,7 +816,7 @@ impossible position"; DBUG_PRINT("wait",("waiting for data in binary log")); if (thd->server_id==0) // for mysqlbinlog (mysqlbinlog.server_id==0) { - pthread_mutex_unlock(log_lock); + mysql_mutex_unlock(log_lock); goto end; } @@ -832,11 +828,11 @@ impossible position"; { if (coord) { - DBUG_ASSERT(heartbeat_ts && heartbeat_period != LL(0)); + DBUG_ASSERT(heartbeat_ts && heartbeat_period != 0); set_timespec_nsec(*heartbeat_ts, heartbeat_period); } ret= mysql_bin_log.wait_for_update_bin_log(thd, heartbeat_ts); - DBUG_ASSERT(ret == 0 || heartbeat_period != LL(0) && coord != NULL); + DBUG_ASSERT(ret == 0 || (heartbeat_period != 0 && coord != NULL)); if (ret == ETIMEDOUT || ret == ETIME) { #ifndef DBUG_OFF @@ -855,23 +851,21 @@ impossible position"; { errmsg = "Failed on my_net_write()"; my_errno= ER_UNKNOWN_ERROR; - pthread_mutex_unlock(log_lock); + mysql_mutex_unlock(log_lock); goto err; } } else { - DBUG_ASSERT(ret == 0 && signal_cnt != mysql_bin_log.signal_cnt || - thd->killed); - DBUG_PRINT("wait",("binary log received update")); + DBUG_PRINT("wait",("binary log received update or a broadcast signal caught")); } } while (signal_cnt == mysql_bin_log.signal_cnt && !thd->killed); - pthread_mutex_unlock(log_lock); + mysql_mutex_unlock(log_lock); } break; default: - pthread_mutex_unlock(log_lock); + mysql_mutex_unlock(log_lock); test_for_non_eof_log_read_errors(error, &errmsg); goto err; } @@ -941,7 +935,7 @@ impossible position"; break; end_io_cache(&log); - (void) my_close(file, MYF(MY_WME)); + mysql_file_close(file, MYF(MY_WME)); /* reset transmit packet for the possible fake rotate event */ if (reset_transmit_packet(thd, flags, &ev_offset, &errmsg)) @@ -971,14 +965,14 @@ impossible position"; end: end_io_cache(&log); - (void)my_close(file, MYF(MY_WME)); + mysql_file_close(file, MYF(MY_WME)); RUN_HOOK(binlog_transmit, transmit_stop, (thd, flags)); my_eof(thd); thd_proc_info(thd, "Waiting to finalize termination"); - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thd->current_linfo = 0; - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); DBUG_VOID_RETURN; err: @@ -992,11 +986,11 @@ err: this mutex will make sure that it never tried to update our linfo after we return from this stack frame */ - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thd->current_linfo = 0; - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); if (file >= 0) - (void) my_close(file, MYF(MY_WME)); + mysql_file_close(file, MYF(MY_WME)); my_message(my_errno, errmsg, MYF(0)); DBUG_VOID_RETURN; @@ -1022,7 +1016,7 @@ int start_slave(THD* thd , Master_info* mi, bool net_report) int thread_mask; DBUG_ENTER("start_slave"); - if (check_access(thd, SUPER_ACL, any_db,0,0,0,0)) + if (check_access(thd, SUPER_ACL, any_db, NULL, NULL, 0, 0)) DBUG_RETURN(1); lock_slave_threads(mi); // this allows us to cleanly read slave_running // Get a mask of _stopped_ threads @@ -1049,7 +1043,7 @@ int start_slave(THD* thd , Master_info* mi, bool net_report) */ if (thread_mask & SLAVE_SQL) { - pthread_mutex_lock(&mi->rli.data_lock); + mysql_mutex_lock(&mi->rli.data_lock); if (thd->lex->mi.pos) { @@ -1103,7 +1097,7 @@ int start_slave(THD* thd , Master_info* mi, bool net_report) ER(ER_MISSING_SKIP_SLAVE)); } - pthread_mutex_unlock(&mi->rli.data_lock); + mysql_mutex_unlock(&mi->rli.data_lock); } else if (thd->lex->mi.pos || thd->lex->mi.relay_log_pos) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_UNTIL_COND_IGNORED, @@ -1162,7 +1156,7 @@ int stop_slave(THD* thd, Master_info* mi, bool net_report ) if (!thd) thd = current_thd; - if (check_access(thd, SUPER_ACL, any_db,0,0,0,0)) + if (check_access(thd, SUPER_ACL, any_db, NULL, NULL, 0, 0)) DBUG_RETURN(1); thd_proc_info(thd, "Killing slave"); int thread_mask; @@ -1246,14 +1240,8 @@ int reset_slave(THD *thd, Master_info* mi) goto err; } - /* - Clear master's log coordinates and reset host/user/etc to the values - specified in mysqld's options (only for good display of SHOW SLAVE STATUS; - next init_master_info() (in start_slave() for example) would have set them - the same way; but here this is for the case where the user does SHOW SLAVE - STATUS; before doing START SLAVE; - */ - init_master_info_with_options(mi); + /* Clear master's log coordinates */ + init_master_log_pos(mi); /* Reset errors (the idea is that we forget about the old master). @@ -1266,14 +1254,16 @@ int reset_slave(THD *thd, Master_info* mi) end_master_info(mi); // and delete these two files fn_format(fname, master_info_file, mysql_data_home, "", 4+32); - if (my_stat(fname, &stat_area, MYF(0)) && my_delete(fname, MYF(MY_WME))) + if (mysql_file_stat(key_file_master_info, fname, &stat_area, MYF(0)) && + mysql_file_delete(key_file_master_info, fname, MYF(MY_WME))) { error=1; goto err; } // delete relay_log_info_file fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32); - if (my_stat(fname, &stat_area, MYF(0)) && my_delete(fname, MYF(MY_WME))) + if (mysql_file_stat(key_file_relay_log_info, fname, &stat_area, MYF(0)) && + mysql_file_delete(key_file_relay_log_info, fname, MYF(MY_WME))) { error=1; goto err; @@ -1291,7 +1281,7 @@ err: Kill all Binlog_dump threads which previously talked to the same slave ("same" means with the same server id). Indeed, if the slave stops, if the - Binlog_dump thread is waiting (pthread_cond_wait) for binlog update, then it + Binlog_dump thread is waiting (mysql_cond_wait) for binlog update, then it will keep existing until a query is written to the binlog. If the master is idle, then this could last long, and if the slave reconnects, we could have 2 Binlog_dump threads in SHOW PROCESSLIST, until a query is written to the @@ -1309,7 +1299,7 @@ err: void kill_zombie_dump_threads(uint32 slave_server_id) { - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); I_List_iterator<THD> it(threads); THD *tmp; @@ -1318,11 +1308,11 @@ void kill_zombie_dump_threads(uint32 slave_server_id) if (tmp->command == COM_BINLOG_DUMP && tmp->server_id == slave_server_id) { - pthread_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete + mysql_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete break; } } - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); if (tmp) { /* @@ -1331,7 +1321,7 @@ void kill_zombie_dump_threads(uint32 slave_server_id) again. We just to do kill the thread ourselves. */ tmp->awake(THD::KILL_QUERY); - pthread_mutex_unlock(&tmp->LOCK_thd_data); + mysql_mutex_unlock(&tmp->LOCK_thd_data); } } @@ -1588,7 +1578,7 @@ bool change_master(THD* thd, Master_info* mi) if (!mi->rli.group_master_log_name[0]) // uninitialized case mi->rli.group_master_log_pos=0; - pthread_mutex_lock(&mi->rli.data_lock); + mysql_mutex_lock(&mi->rli.data_lock); mi->rli.abort_pos_wait++; /* for MASTER_POS_WAIT() to abort */ /* Clear the errors, for a clean start */ mi->rli.clear_error(); @@ -1601,8 +1591,8 @@ bool change_master(THD* thd, Master_info* mi) not exist anymore). */ flush_relay_log_info(&mi->rli); - pthread_cond_broadcast(&mi->data_cond); - pthread_mutex_unlock(&mi->rli.data_lock); + mysql_cond_broadcast(&mi->data_cond); + mysql_mutex_unlock(&mi->rli.data_lock); err: unlock_slave_threads(mi); @@ -1715,7 +1705,7 @@ bool mysql_show_binlog_events(THD* thd) my_off_t pos = max(BIN_LOG_HEADER_SIZE, lex_mi->pos); // user-friendly char search_file_name[FN_REFLEN], *name; const char *log_file_name = lex_mi->log_file_name; - pthread_mutex_t *log_lock = binary_log->get_log_lock(); + mysql_mutex_t *log_lock = binary_log->get_log_lock(); LOG_INFO linfo; Log_event* ev; @@ -1737,9 +1727,9 @@ bool mysql_show_binlog_events(THD* thd) goto err; } - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thd->current_linfo = &linfo; - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); if ((file=open_binlog(&log, linfo.log_file_name, &errmsg)) < 0) goto err; @@ -1749,7 +1739,7 @@ bool mysql_show_binlog_events(THD* thd) */ thd->variables.max_allowed_packet += MAX_LOG_EVENT_HEADER; - pthread_mutex_lock(log_lock); + mysql_mutex_lock(log_lock); /* open_binlog() sought to position 4. @@ -1759,7 +1749,7 @@ bool mysql_show_binlog_events(THD* thd) This code will fail on a mixed relay log (one which has Format_desc then Rotate then Format_desc). */ - ev = Log_event::read_log_event(&log,(pthread_mutex_t*)0,description_event); + ev= Log_event::read_log_event(&log, (mysql_mutex_t*)0, description_event); if (ev) { if (ev->get_type_code() == FORMAT_DESCRIPTION_EVENT) @@ -1780,7 +1770,7 @@ bool mysql_show_binlog_events(THD* thd) } for (event_count = 0; - (ev = Log_event::read_log_event(&log,(pthread_mutex_t*) 0, + (ev = Log_event::read_log_event(&log, (mysql_mutex_t*) 0, description_event)); ) { if (event_count >= limit_start && @@ -1788,7 +1778,7 @@ bool mysql_show_binlog_events(THD* thd) { errmsg = "Net error"; delete ev; - pthread_mutex_unlock(log_lock); + mysql_mutex_unlock(log_lock); goto err; } @@ -1802,11 +1792,11 @@ bool mysql_show_binlog_events(THD* thd) if (event_count < limit_end && log.error) { errmsg = "Wrong offset or I/O error"; - pthread_mutex_unlock(log_lock); + mysql_mutex_unlock(log_lock); goto err; } - pthread_mutex_unlock(log_lock); + mysql_mutex_unlock(log_lock); } ret= FALSE; @@ -1816,7 +1806,7 @@ err: if (file >= 0) { end_io_cache(&log); - (void) my_close(file, MYF(MY_WME)); + mysql_file_close(file, MYF(MY_WME)); } if (errmsg) @@ -1825,9 +1815,9 @@ err: else my_eof(thd); - pthread_mutex_lock(&LOCK_thread_count); + mysql_mutex_lock(&LOCK_thread_count); thd->current_linfo = 0; - pthread_mutex_unlock(&LOCK_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); DBUG_RETURN(ret); } @@ -1908,12 +1898,12 @@ bool show_binlogs(THD* thd) Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_RETURN(TRUE); - pthread_mutex_lock(mysql_bin_log.get_log_lock()); + mysql_mutex_lock(mysql_bin_log.get_log_lock()); mysql_bin_log.lock_index(); index_file=mysql_bin_log.get_index_file(); mysql_bin_log.raw_get_current_log(&cur); // dont take mutex - pthread_mutex_unlock(mysql_bin_log.get_log_lock()); // lockdep, OK + mysql_mutex_unlock(mysql_bin_log.get_log_lock()); // lockdep, OK cur_dir_len= dirname_length(cur.log_file_name); @@ -1936,11 +1926,12 @@ bool show_binlogs(THD* thd) else { /* this is an old log, open it and find the size */ - if ((file= my_open(fname, O_RDONLY | O_SHARE | O_BINARY, - MYF(0))) >= 0) + if ((file= mysql_file_open(key_file_binlog, + fname, O_RDONLY | O_SHARE | O_BINARY, + MYF(0))) >= 0) { - file_length= (ulonglong) my_seek(file, 0L, MY_SEEK_END, MYF(0)); - my_close(file, MYF(0)); + file_length= (ulonglong) mysql_file_seek(file, 0L, MY_SEEK_END, MYF(0)); + mysql_file_close(file, MYF(0)); } } protocol->store(file_length); @@ -1975,7 +1966,7 @@ int log_loaded_block(IO_CACHE* file) uchar* buffer= (uchar*) my_b_get_buffer_start(file); uint max_event_size= current_thd->variables.max_allowed_packet; lf_info= (LOAD_FILE_INFO*) file->arg; - if (lf_info->thd->current_stmt_binlog_row_based) + if (lf_info->thd->is_current_stmt_binlog_format_row()) DBUG_RETURN(0); if (lf_info->last_pos_in_file != HA_POS_ERROR && lf_info->last_pos_in_file >= my_b_get_pos_in_file(file)) @@ -2009,147 +2000,4 @@ int log_loaded_block(IO_CACHE* file) DBUG_RETURN(0); } -/* - Replication System Variables -*/ - -class sys_var_slave_skip_counter :public sys_var -{ -public: - sys_var_slave_skip_counter(sys_var_chain *chain, const char *name_arg) - :sys_var(name_arg) - { chain_sys_var(chain); } - bool check(THD *thd, set_var *var); - bool update(THD *thd, set_var *var); - bool check_type(enum_var_type type) { return type != OPT_GLOBAL; } - /* - We can't retrieve the value of this, so we don't have to define - type() or value_ptr() - */ -}; - -class sys_var_sync_binlog_period :public sys_var_long_ptr -{ -public: - sys_var_sync_binlog_period(sys_var_chain *chain, const char *name_arg, - ulong *value_ptr) - :sys_var_long_ptr(chain, name_arg,value_ptr) {} - bool update(THD *thd, set_var *var); -}; - -static void fix_slave_net_timeout(THD *thd, enum_var_type type) -{ - DBUG_ENTER("fix_slave_net_timeout"); -#ifdef HAVE_REPLICATION - pthread_mutex_lock(&LOCK_active_mi); - DBUG_PRINT("info",("slave_net_timeout=%lu mi->heartbeat_period=%.3f", - slave_net_timeout, - (active_mi? active_mi->heartbeat_period : 0.0))); - if (active_mi && slave_net_timeout < active_mi->heartbeat_period) - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE, - "The currect value for master_heartbeat_period" - " exceeds the new value of `slave_net_timeout' sec." - " A sensible value for the period should be" - " less than the timeout."); - pthread_mutex_unlock(&LOCK_active_mi); -#endif - DBUG_VOID_RETURN; -} - -static sys_var_chain vars = { NULL, NULL }; - -static sys_var_const sys_log_slave_updates(&vars, "log_slave_updates", - OPT_GLOBAL, SHOW_MY_BOOL, - (uchar*) &opt_log_slave_updates); -static sys_var_const sys_relay_log(&vars, "relay_log", - OPT_GLOBAL, SHOW_CHAR_PTR, - (uchar*) &opt_relay_logname); -static sys_var_const sys_relay_log_index(&vars, "relay_log_index", - OPT_GLOBAL, SHOW_CHAR_PTR, - (uchar*) &opt_relaylog_index_name); -static sys_var_const sys_relay_log_info_file(&vars, "relay_log_info_file", - OPT_GLOBAL, SHOW_CHAR_PTR, - (uchar*) &relay_log_info_file); -static sys_var_bool_ptr sys_relay_log_purge(&vars, "relay_log_purge", - &relay_log_purge); -static sys_var_bool_ptr sys_relay_log_recovery(&vars, "relay_log_recovery", - &relay_log_recovery); -static sys_var_uint_ptr sys_sync_binlog_period(&vars, "sync_binlog", - &sync_binlog_period); -static sys_var_uint_ptr sys_sync_relaylog_period(&vars, "sync_relay_log", - &sync_relaylog_period); -static sys_var_uint_ptr sys_sync_relayloginfo_period(&vars, "sync_relay_log_info", - &sync_relayloginfo_period); -static sys_var_uint_ptr sys_sync_masterinfo_period(&vars, "sync_master_info", - &sync_masterinfo_period); -static sys_var_const sys_relay_log_space_limit(&vars, - "relay_log_space_limit", - OPT_GLOBAL, SHOW_LONGLONG, - (uchar*) - &relay_log_space_limit); -static sys_var_const sys_slave_load_tmpdir(&vars, "slave_load_tmpdir", - OPT_GLOBAL, SHOW_CHAR_PTR, - (uchar*) &slave_load_tmpdir); -static sys_var_long_ptr sys_slave_net_timeout(&vars, "slave_net_timeout", - &slave_net_timeout, - fix_slave_net_timeout); -static sys_var_const sys_slave_skip_errors(&vars, "slave_skip_errors", - OPT_GLOBAL, SHOW_CHAR, - (uchar*) slave_skip_error_names); -static sys_var_long_ptr sys_slave_trans_retries(&vars, "slave_transaction_retries", - &slave_trans_retries); -static sys_var_slave_skip_counter sys_slave_skip_counter(&vars, "sql_slave_skip_counter"); - - -bool sys_var_slave_skip_counter::check(THD *thd, set_var *var) -{ - int result= 0; - pthread_mutex_lock(&LOCK_active_mi); - pthread_mutex_lock(&active_mi->rli.run_lock); - if (active_mi->rli.slave_running) - { - my_message(ER_SLAVE_MUST_STOP, ER(ER_SLAVE_MUST_STOP), MYF(0)); - result=1; - } - pthread_mutex_unlock(&active_mi->rli.run_lock); - pthread_mutex_unlock(&LOCK_active_mi); - var->save_result.ulong_value= (ulong) var->value->val_int(); - return result; -} - - -bool sys_var_slave_skip_counter::update(THD *thd, set_var *var) -{ - pthread_mutex_lock(&LOCK_active_mi); - pthread_mutex_lock(&active_mi->rli.run_lock); - /* - The following test should normally never be true as we test this - in the check function; To be safe against multiple - SQL_SLAVE_SKIP_COUNTER request, we do the check anyway - */ - if (!active_mi->rli.slave_running) - { - pthread_mutex_lock(&active_mi->rli.data_lock); - active_mi->rli.slave_skip_counter= var->save_result.ulong_value; - pthread_mutex_unlock(&active_mi->rli.data_lock); - } - pthread_mutex_unlock(&active_mi->rli.run_lock); - pthread_mutex_unlock(&LOCK_active_mi); - return 0; -} - - -int init_replication_sys_vars() -{ - if (mysql_add_sys_var_chain(vars.first, my_long_options)) - { - /* should not happen */ - fprintf(stderr, "failed to initialize replication system variables"); - unireg_abort(1); - } - return 0; -} - - #endif /* HAVE_REPLICATION */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7119650a7a6..18954e0cf23 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -120,8 +120,7 @@ static COND *optimize_cond(JOIN *join, COND *conds, Item::cond_result *cond_value); static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item); static bool open_tmp_table(TABLE *table); -static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, - ulonglong options); +static bool create_myisam_tmp_table(TABLE *,TMP_TABLE_PARAM *, ulonglong, my_bool); static int do_select(JOIN *join,List<Item> *fields,TABLE *tmp_table, Procedure *proc); @@ -267,7 +266,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result, (ORDER*) select_lex->group_list.first, select_lex->having, (ORDER*) lex->proc_list.first, - select_lex->options | thd->options | + select_lex->options | thd->variables.option_bits | setup_tables_done_option, result, unit, select_lex); } @@ -1031,7 +1030,7 @@ JOIN::optimize() error= 0; DBUG_RETURN(0); } - if (!(thd->options & OPTION_BIG_SELECTS) && + if (!(thd->variables.option_bits & OPTION_BIG_SELECTS) && best_read > (double) thd->variables.max_join_size && !(select_options & SELECT_DESCRIBE)) { /* purecov: inspected */ @@ -1096,6 +1095,10 @@ JOIN::optimize() { conds=new Item_int((longlong) 0,1); // Always false } + + /* Cache constant expressions in WHERE, HAVING, ON clauses. */ + cache_const_exprs(); + if (make_join_select(this, select, conds)) { zero_result_cause= @@ -1515,15 +1518,10 @@ JOIN::optimize() if (!(exec_tmp_table1= create_tmp_table(thd, &tmp_table_param, all_fields, - tmp_group, - group_list ? 0 : select_distinct, + tmp_group, group_list ? 0 : select_distinct, group_list && simple_group, - select_options, - tmp_rows_limit, - (char *) ""))) - { + select_options, tmp_rows_limit, ""))) DBUG_RETURN(1); - } /* We don't have to store rows in temp table that doesn't match HAVING if: @@ -1997,8 +1995,7 @@ JOIN::exec() curr_join->select_distinct && !curr_join->group_list, 1, curr_join->select_options, - HA_POS_ERROR, - (char *) ""))) + HA_POS_ERROR, ""))) DBUG_VOID_RETURN; curr_join->exec_tmp_table2= exec_tmp_table2; } @@ -2844,8 +2841,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds, !table->fulltext_searched && !table->pos_in_table_list->embedding) { - if ((table->key_info[key].flags & (HA_NOSAME | HA_END_SPACE_KEY)) - == HA_NOSAME) + if (table->key_info[key].flags & HA_NOSAME) { if (const_ref == eq_part) { // Found everything for ref. @@ -3978,7 +3974,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab, save_pos++; } i=(uint) (save_pos-(KEYUSE*) keyuse->buffer); - VOID(set_dynamic(keyuse,(uchar*) &key_end,i)); + (void) set_dynamic(keyuse,(uchar*) &key_end,i); keyuse->elements=i; } return FALSE; @@ -4396,7 +4392,7 @@ best_access_path(JOIN *join, */ if (table->quick_keys.is_set(key) && (const_part & ((1 << table->quick_key_parts[key])-1)) == - ((1 << table->quick_key_parts[key])-1) && + (((key_part_map)1 << table->quick_key_parts[key])-1) && table->quick_n_ranges[key] == 1 && records > (double) table->quick_rows[key]) { @@ -5825,8 +5821,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse, DBUG_RETURN(0); if (j->type == JT_CONST) j->table->const_table= 1; - else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY | - HA_END_SPACE_KEY)) != HA_NOSAME) || + else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) != HA_NOSAME) || keyparts != keyinfo->key_parts || null_ref_key) { /* Must read with repeat */ @@ -6366,7 +6361,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) /* Push condition to storage engine if this is enabled and the condition is not guarded */ tab->table->file->pushed_cond= NULL; - if (thd->variables.engine_condition_pushdown) + if (thd->variables.optimizer_switch & + OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN) { COND *push_cond= make_cond_for_table(tmp, current_map, current_map); @@ -9206,18 +9202,26 @@ optimize_cond(JOIN *join, COND *conds, List<TABLE_LIST> *join_list, /** - Remove const and eq items. + Handles the reqursive job for remove_eq_conds() - @return - Return new item, or NULL if no condition @n - cond_value is set to according: - - COND_OK : query is possible (field = constant) - - COND_TRUE : always true ( 1 = 1 ) - - COND_FALSE : always false ( 1 = 2 ) + Remove const and eq items. Return new item, or NULL if no condition + cond_value is set to according: + COND_OK query is possible (field = constant) + COND_TRUE always true ( 1 = 1 ) + COND_FALSE always false ( 1 = 2 ) + + SYNPOSIS + remove_eq_conds() + thd THD environment + cond the condition to handle + cond_value the resulting value of the condition + + RETURN + *COND with the simplified condition */ -COND * -remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) +static COND * +internal_remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) { if (cond->type() == Item::COND_ITEM) { @@ -9231,12 +9235,12 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) Item *item; while ((item=li++)) { - Item *new_item=remove_eq_conds(thd, item, &tmp_cond_value); + Item *new_item=internal_remove_eq_conds(thd, item, &tmp_cond_value); if (!new_item) li.remove(); else if (item != new_item) { - VOID(li.replace(new_item)); + (void) li.replace(new_item); should_fix_fields=1; } if (*cond_value == Item::COND_UNDEF) @@ -9280,54 +9284,19 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) else if (cond->type() == Item::FUNC_ITEM && ((Item_func*) cond)->functype() == Item_func::ISNULL_FUNC) { - /* - Handles this special case for some ODBC applications: - The are requesting the row that was just updated with a auto_increment - value with this construct: - - SELECT * from table_name where auto_increment_column IS NULL - This will be changed to: - SELECT * from table_name where auto_increment_column = LAST_INSERT_ID - */ - Item_func_isnull *func=(Item_func_isnull*) cond; Item **args= func->arguments(); if (args[0]->type() == Item::FIELD_ITEM) { Field *field=((Item_field*) args[0])->field; - if (field->flags & AUTO_INCREMENT_FLAG && !field->table->maybe_null && - (thd->options & OPTION_AUTO_IS_NULL) && - (thd->first_successful_insert_id_in_prev_stmt > 0 && - thd->substitute_null_with_insert_id)) - { -#ifdef HAVE_QUERY_CACHE - query_cache_abort(&thd->query_cache_tls); -#endif - COND *new_cond; - if ((new_cond= new Item_func_eq(args[0], - new Item_int("last_insert_id()", - thd->read_first_successful_insert_id_in_prev_stmt(), - MY_INT64_NUM_DECIMAL_DIGITS)))) - { - cond=new_cond; - /* - Item_func_eq can't be fixed after creation so we do not check - cond->fixed, also it do not need tables so we use 0 as second - argument. - */ - cond->fix_fields(thd, &cond); - } - /* - IS NULL should be mapped to LAST_INSERT_ID only for first row, so - clear for next row - */ - thd->substitute_null_with_insert_id= FALSE; - } /* fix to replace 'NULL' dates with '0' (shreeve@uci.edu) */ - else if (((field->type() == MYSQL_TYPE_DATE) || - (field->type() == MYSQL_TYPE_DATETIME)) && - (field->flags & NOT_NULL_FLAG) && - !field->table->maybe_null) + /* + datetime_field IS NULL has to be modified to + datetime_field == 0 + */ + if (((field->type() == MYSQL_TYPE_DATE) || + (field->type() == MYSQL_TYPE_DATETIME)) && + (field->flags & NOT_NULL_FLAG) && !field->table->maybe_null) { COND *new_cond; if ((new_cond= new Item_func_eq(args[0],new Item_int("0", 0, 2)))) @@ -9368,6 +9337,85 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) return cond; // Point at next and level } + +/** + Remove const and eq items. Return new item, or NULL if no condition + cond_value is set to according: + COND_OK query is possible (field = constant) + COND_TRUE always true ( 1 = 1 ) + COND_FALSE always false ( 1 = 2 ) + + SYNPOSIS + remove_eq_conds() + thd THD environment + cond the condition to handle + cond_value the resulting value of the condition + + NOTES + calls the inner_remove_eq_conds to check all the tree reqursively + + RETURN + *COND with the simplified condition +*/ + +COND * +remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) +{ + if (cond->type() == Item::FUNC_ITEM && + ((Item_func*) cond)->functype() == Item_func::ISNULL_FUNC) + { + /* + Handles this special case for some ODBC applications: + The are requesting the row that was just updated with a auto_increment + value with this construct: + + SELECT * from table_name where auto_increment_column IS NULL + This will be changed to: + SELECT * from table_name where auto_increment_column = LAST_INSERT_ID + */ + + Item_func_isnull *func=(Item_func_isnull*) cond; + Item **args= func->arguments(); + if (args[0]->type() == Item::FIELD_ITEM) + { + Field *field=((Item_field*) args[0])->field; + if (field->flags & AUTO_INCREMENT_FLAG && !field->table->maybe_null && + (thd->variables.option_bits & OPTION_AUTO_IS_NULL) && + (thd->first_successful_insert_id_in_prev_stmt > 0 && + thd->substitute_null_with_insert_id)) + { +#ifdef HAVE_QUERY_CACHE + query_cache_abort(&thd->query_cache_tls); +#endif + COND *new_cond; + if ((new_cond= new Item_func_eq(args[0], + new Item_int("last_insert_id()", + thd->read_first_successful_insert_id_in_prev_stmt(), + MY_INT64_NUM_DECIMAL_DIGITS)))) + { + cond=new_cond; + /* + Item_func_eq can't be fixed after creation so we do not check + cond->fixed, also it do not need tables so we use 0 as second + argument. + */ + cond->fix_fields(thd, &cond); + } + /* + IS NULL should be mapped to LAST_INSERT_ID only for first row, so + clear for next row + */ + thd->substitute_null_with_insert_id= FALSE; + + *cond_value= Item::COND_OK; + return cond; + } + } + } + return internal_remove_eq_conds(thd, cond, cond_value); // Scan all the condition +} + + /* Check if equality can be used in removing components of GROUP BY/DISTINCT @@ -9716,7 +9764,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Item_sum *item_sum=(Item_sum*) item; result= item_sum->create_tmp_field(group, table, convert_blob_length); if (!result) - thd->fatal_error(); + my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); return result; } case Item::FIELD_ITEM: @@ -9882,7 +9930,7 @@ TABLE * create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ORDER *group, bool distinct, bool save_sum_fields, ulonglong select_options, ha_rows rows_limit, - char *table_alias) + const char *table_alias) { MEM_ROOT *mem_root_save, own_root; TABLE *table; @@ -10197,9 +10245,9 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, /* If result table is small; use a heap */ /* future: storage engine selection can be made dynamic? */ - if (blob_count || using_unique_constraint || - (select_options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) == - OPTION_BIG_TABLES || (select_options & TMP_TABLE_FORCE_MYISAM)) + if (blob_count || using_unique_constraint + || (thd->variables.big_tables && !(select_options & SELECT_SMALL_RESULT)) + || (select_options & TMP_TABLE_FORCE_MYISAM)) { share->db_plugin= ha_lock_engine(0, myisam_hton); table->file= get_new_handler(share, &table->mem_root, @@ -10526,7 +10574,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, share->db_record_offset= 1; if (share->db_type() == myisam_hton) { - if (create_myisam_tmp_table(table,param,select_options)) + if (create_myisam_tmp_table(table, param, select_options, + thd->variables.big_tables)) goto err; } if (open_tmp_table(table)) @@ -10597,6 +10646,7 @@ TABLE *create_virtual_tmp_table(THD *thd, List<Create_field> &field_list) share->blob_field= blob_field; share->fields= field_count; share->blob_ptr_size= portable_sizeof_char_ptr; + share->db_low_byte_first=1; // True for HEAP and MyISAM setup_tmp_table_column_bitmaps(table, bitmaps); /* Create all fields and calculate the total length of record */ @@ -10661,6 +10711,18 @@ TABLE *create_virtual_tmp_table(THD *thd, List<Create_field> &field_list) null_bit= 1; } } + if (cur_field->type() == MYSQL_TYPE_BIT && + cur_field->key_type() == HA_KEYTYPE_BIT) + { + /* This is a Field_bit since key_type is HA_KEYTYPE_BIT */ + static_cast<Field_bit*>(cur_field)->set_bit_ptr(null_pos, null_bit); + null_bit+= cur_field->field_length & 7; + if (null_bit > 7) + { + null_pos++; + null_bit-= 8; + } + } cur_field->reset(); field_pos+= cur_field->pack_length(); @@ -10690,7 +10752,7 @@ static bool open_tmp_table(TABLE *table) static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, - ulonglong options) + ulonglong options, my_bool big_tables) { int error; MI_KEYDEF keydef; @@ -10777,8 +10839,7 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param, MI_CREATE_INFO create_info; bzero((char*) &create_info,sizeof(create_info)); - if ((options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) == - OPTION_BIG_TABLES) + if (big_tables && !(options & SELECT_SMALL_RESULT)) create_info.data_file_length= ~(ulonglong) 0; if ((error=mi_create(share->table_name.str, share->keys, &keydef, @@ -10860,8 +10921,7 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, We don't want this error to be converted to a warning, e.g. in case of INSERT IGNORE ... SELECT. */ - thd->fatal_error(); - table->file->print_error(error,MYF(0)); + table->file->print_error(error, MYF(ME_FATALERROR)); DBUG_RETURN(1); } @@ -10880,7 +10940,8 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, thd_proc_info(thd, "converting HEAP to MyISAM"); if (create_myisam_tmp_table(&new_table, param, - thd->lex->select_lex.options | thd->options)) + thd->lex->select_lex.options | thd->variables.option_bits, + thd->variables.big_tables)) goto err2; if (open_tmp_table(&new_table)) goto err1; @@ -11064,7 +11125,7 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure) if (table) { - VOID(table->file->extra(HA_EXTRA_WRITE_CACHE)); + (void) table->file->extra(HA_EXTRA_WRITE_CACHE); empty_record(table); if (table->group && join->tmp_table_param.sum_func_count && table->s->keys && !table->file->inited) @@ -12410,7 +12471,7 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), if (end_of_records) DBUG_RETURN(NESTED_LOOP_OK); join->first_record=1; - VOID(test_if_group_changed(join->group_fields)); + (void) test_if_group_changed(join->group_fields); } if (idx < (int) join->send_group_parts) { @@ -12673,7 +12734,7 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), if (end_of_records) DBUG_RETURN(NESTED_LOOP_OK); join->first_record=1; - VOID(test_if_group_changed(join->group_fields)); + (void) test_if_group_changed(join->group_fields); } if (idx < (int) join->send_group_parts) { @@ -15072,8 +15133,7 @@ calc_group_buffer(JOIN *join,ORDER *group) default: /* This case should never be choosen */ DBUG_ASSERT(0); - my_error(ER_OUT_OF_RESOURCES, MYF(0)); - join->thd->fatal_error(); + my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); } } parts++; @@ -16599,7 +16659,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, { const COND *pushed_cond= tab->table->file->pushed_cond; - if (thd->variables.engine_condition_pushdown && pushed_cond) + if ((thd->variables.optimizer_switch & + OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN) && pushed_cond) { extra.append(STRING_WITH_LEN("; Using where with pushed " "condition")); @@ -16747,7 +16808,7 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) (ORDER*) first->group_list.first, first->having, (ORDER*) thd->lex->proc_list.first, - first->options | thd->options | SELECT_DESCRIBE, + first->options | thd->variables.option_bits | SELECT_DESCRIBE, result, unit, first); } DBUG_RETURN(res || thd->is_error()); @@ -17105,5 +17166,40 @@ bool JOIN::change_result(select_result *res) } /** + Cache constant expressions in WHERE, HAVING, ON conditions. +*/ + +void JOIN::cache_const_exprs() +{ + bool cache_flag= FALSE; + bool *analyzer_arg= &cache_flag; + + /* No need in cache if all tables are constant. */ + if (const_tables == tables) + return; + + if (conds) + conds->compile(&Item::cache_const_expr_analyzer, (uchar **)&analyzer_arg, + &Item::cache_const_expr_transformer, (uchar *)&cache_flag); + cache_flag= FALSE; + if (having) + having->compile(&Item::cache_const_expr_analyzer, (uchar **)&analyzer_arg, + &Item::cache_const_expr_transformer, (uchar *)&cache_flag); + + for (JOIN_TAB *tab= join_tab + const_tables; tab < join_tab + tables ; tab++) + { + if (*tab->on_expr_ref) + { + cache_flag= FALSE; + (*tab->on_expr_ref)->compile(&Item::cache_const_expr_analyzer, + (uchar **)&analyzer_arg, + &Item::cache_const_expr_transformer, + (uchar *)&cache_flag); + } + } +} + + +/** @} (end of group Query_Optimizer) */ diff --git a/sql/sql_select.h b/sql/sql_select.h index a84fa65a548..c30aae4fbf9 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -555,6 +555,7 @@ public: return (unit == &thd->lex->unit && (unit->fake_select_lex == 0 || select_lex == unit->fake_select_lex)); } + void cache_const_exprs(); private: /** TRUE if the query contains an aggregate function but has no GROUP @@ -577,7 +578,7 @@ bool store_val_in_field(Field *field, Item *val, enum_check_fields check_flag); TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ORDER *group, bool distinct, bool save_sum_fields, ulonglong select_options, ha_rows rows_limit, - char* alias); + const char* alias); void free_tmp_table(THD *thd, TABLE *entry); void count_field_types(SELECT_LEX *select_lex, TMP_TABLE_PARAM *param, List<Item> &fields, bool reset_with_sum_func); @@ -643,7 +644,7 @@ public: enum store_key_result result; THD *thd= to_field->table->in_use; enum_check_fields saved_count_cuted_fields= thd->count_cuted_fields; - ulong sql_mode= thd->variables.sql_mode; + ulonglong sql_mode= thd->variables.sql_mode; thd->variables.sql_mode&= ~(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE); thd->count_cuted_fields= CHECK_FIELD_IGNORE; diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc index 3dfe8436124..a7109af9f64 100644 --- a/sql/sql_servers.cc +++ b/sql/sql_servers.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2003 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -47,7 +47,7 @@ static HASH servers_cache; static MEM_ROOT mem; -static rw_lock_t THR_LOCK_servers; +static mysql_rwlock_t THR_LOCK_servers; static bool get_server_from_table_to_cache(TABLE *table); @@ -89,6 +89,26 @@ static uchar *servers_cache_get_key(FOREIGN_SERVER *server, size_t *length, DBUG_RETURN((uchar*) server->server_name); } +#ifdef HAVE_PSI_INTERFACE +static PSI_rwlock_key key_rwlock_THR_LOCK_servers; + +static PSI_rwlock_info all_servers_cache_rwlocks[]= +{ + { &key_rwlock_THR_LOCK_servers, "THR_LOCK_servers", PSI_FLAG_GLOBAL} +}; + +static void init_servers_cache_psi_keys(void) +{ + const char* category= "sql"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_servers_cache_rwlocks); + PSI_server->register_rwlock(category, all_servers_cache_rwlocks, count); +} +#endif /* HAVE_PSI_INTERFACE */ /* Initialize structures responsible for servers used in federated @@ -115,8 +135,12 @@ bool servers_init(bool dont_read_servers_table) bool return_val= FALSE; DBUG_ENTER("servers_init"); +#ifdef HAVE_PSI_INTERFACE + init_servers_cache_psi_keys(); +#endif + /* init the mutex */ - if (my_rwlock_init(&THR_LOCK_servers, NULL)) + if (mysql_rwlock_init(key_rwlock_THR_LOCK_servers, &THR_LOCK_servers)) DBUG_RETURN(TRUE); /* initialise our servers cache */ @@ -128,7 +152,7 @@ bool servers_init(bool dont_read_servers_table) } /* Initialize the mem root for data */ - init_alloc_root(&mem, ACL_ALLOC_BLOCK_SIZE, 0); + init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0); if (dont_read_servers_table) goto end; @@ -140,7 +164,6 @@ bool servers_init(bool dont_read_servers_table) DBUG_RETURN(TRUE); thd->thread_stack= (char*) &thd; thd->store_globals(); - lex_start(thd); /* It is safe to call servers_reload() since servers_* arrays and hashes which will be freed there are global static objects and thus are initialized @@ -180,7 +203,7 @@ static bool servers_load(THD *thd, TABLE_LIST *tables) my_hash_reset(&servers_cache); free_root(&mem, MYF(0)); - init_alloc_root(&mem, ACL_ALLOC_BLOCK_SIZE, 0); + init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0); init_read_record(&read_record_info,thd,table=tables[0].table,NULL,1,0, FALSE); @@ -232,7 +255,7 @@ bool servers_reload(THD *thd) } DBUG_PRINT("info", ("locking servers_cache")); - rw_wrlock(&THR_LOCK_servers); + mysql_rwlock_wrlock(&THR_LOCK_servers); bzero((char*) tables, sizeof(tables)); tables[0].alias= tables[0].table_name= (char*) "servers"; @@ -263,7 +286,7 @@ bool servers_reload(THD *thd) end: close_thread_tables(thd); DBUG_PRINT("info", ("unlocking servers_cache")); - rw_unlock(&THR_LOCK_servers); + mysql_rwlock_unlock(&THR_LOCK_servers); DBUG_RETURN(return_val); } @@ -593,7 +616,7 @@ int drop_server(THD *thd, LEX_SERVER_OPTIONS *server_options) tables.db= (char*) "mysql"; tables.alias= tables.table_name= (char*) "servers"; - rw_wrlock(&THR_LOCK_servers); + mysql_rwlock_wrlock(&THR_LOCK_servers); /* hit the memory hit first */ if ((error= delete_server_record_in_cache(server_options))) @@ -617,7 +640,7 @@ int drop_server(THD *thd, LEX_SERVER_OPTIONS *server_options) } end: - rw_unlock(&THR_LOCK_servers); + mysql_rwlock_unlock(&THR_LOCK_servers); DBUG_RETURN(error); } @@ -670,8 +693,8 @@ delete_server_record_in_cache(LEX_SERVER_OPTIONS *server_options) server->server_name, server->server_name_length)); - VOID(my_hash_delete(&servers_cache, (uchar*) server)); - + my_hash_delete(&servers_cache, (uchar*) server); + error= 0; end: @@ -777,7 +800,7 @@ int update_server_record_in_cache(FOREIGN_SERVER *existing, /* delete the existing server struct from the server cache */ - VOID(my_hash_delete(&servers_cache, (uchar*)existing)); + my_hash_delete(&servers_cache, (uchar*)existing); /* Insert the altered server struct into the server cache @@ -969,7 +992,7 @@ int create_server(THD *thd, LEX_SERVER_OPTIONS *server_options) DBUG_PRINT("info", ("server_options->server_name %s", server_options->server_name)); - rw_wrlock(&THR_LOCK_servers); + mysql_rwlock_wrlock(&THR_LOCK_servers); /* hit the memory first */ if (my_hash_search(&servers_cache, (uchar*) server_options->server_name, @@ -990,7 +1013,7 @@ int create_server(THD *thd, LEX_SERVER_OPTIONS *server_options) DBUG_PRINT("info", ("error returned %d", error)); end: - rw_unlock(&THR_LOCK_servers); + mysql_rwlock_unlock(&THR_LOCK_servers); DBUG_RETURN(error); } @@ -1019,7 +1042,7 @@ int alter_server(THD *thd, LEX_SERVER_OPTIONS *server_options) DBUG_PRINT("info", ("server_options->server_name %s", server_options->server_name)); - rw_wrlock(&THR_LOCK_servers); + mysql_rwlock_wrlock(&THR_LOCK_servers); if (!(existing= (FOREIGN_SERVER *) my_hash_search(&servers_cache, (uchar*) name.str, @@ -1044,7 +1067,7 @@ int alter_server(THD *thd, LEX_SERVER_OPTIONS *server_options) end: DBUG_PRINT("info", ("error returned %d", error)); - rw_unlock(&THR_LOCK_servers); + mysql_rwlock_unlock(&THR_LOCK_servers); DBUG_RETURN(error); } @@ -1210,7 +1233,7 @@ void servers_free(bool end) my_hash_reset(&servers_cache); DBUG_VOID_RETURN; } - rwlock_destroy(&THR_LOCK_servers); + mysql_rwlock_destroy(&THR_LOCK_servers); free_root(&mem,MYF(0)); my_hash_free(&servers_cache); DBUG_VOID_RETURN; @@ -1292,7 +1315,7 @@ FOREIGN_SERVER *get_server_by_name(MEM_ROOT *mem, const char *server_name, } DBUG_PRINT("info", ("locking servers_cache")); - rw_rdlock(&THR_LOCK_servers); + mysql_rwlock_rdlock(&THR_LOCK_servers); if (!(server= (FOREIGN_SERVER *) my_hash_search(&servers_cache, (uchar*) server_name, server_name_length))) @@ -1306,7 +1329,7 @@ FOREIGN_SERVER *get_server_by_name(MEM_ROOT *mem, const char *server_name, server= clone_server(mem, server, buff); DBUG_PRINT("info", ("unlocking servers_cache")); - rw_unlock(&THR_LOCK_servers); + mysql_rwlock_unlock(&THR_LOCK_servers); DBUG_RETURN(server); } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 389aae87977..bb7fa61f39b 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,6 +22,8 @@ #include "repl_failsafe.h" #include "sp.h" #include "sp_head.h" +#include "sp_pcontext.h" +#include "set_var.h" #include "sql_trigger.h" #include "authors.h" #include "contributors.h" @@ -432,7 +434,7 @@ find_files(THD *thd, List<LEX_STRING> *files, const char *db, end= strend(buff); if (end != buff && end[-1] == FN_LIBCHAR) end[-1]= 0; // Remove end FN_LIBCHAR - if (!my_stat(buff, file->mystat, MYF(0))) + if (!mysql_file_stat(key_file_misc, buff, file->mystat, MYF(0))) continue; } #endif @@ -495,7 +497,7 @@ find_files(THD *thd, List<LEX_STRING> *files, const char *db, DBUG_PRINT("info",("found: %d files", files->elements)); my_dirend(dirp); - VOID(ha_find_files(thd, db, path, wild, dir, files)); + (void) ha_find_files(thd, db, path, wild, dir, files); DBUG_RETURN(FIND_FILES_OK); } @@ -748,7 +750,7 @@ bool mysqld_show_create_db(THD *thd, char *dbname, DBUG_RETURN(TRUE); } #endif - if (is_schema_db(dbname)) + if (is_infoschema_db(dbname)) { dbname= INFORMATION_SCHEMA_NAME.str; create.default_table_charset= system_charset_info; @@ -841,35 +843,6 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) DBUG_VOID_RETURN; } - -int -mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd) -{ - Protocol *protocol= thd->protocol; - String *packet= protocol->storage_packet(); - DBUG_ENTER("mysqld_dump_create_info"); - DBUG_PRINT("enter",("table: %s",table_list->table->s->table_name.str)); - - protocol->prepare_for_resend(); - if (store_create_info(thd, table_list, packet, NULL, - FALSE /* show_database */)) - DBUG_RETURN(-1); - - if (fd < 0) - { - if (protocol->write()) - DBUG_RETURN(-1); - protocol->flush(); - } - else - { - if (my_write(fd, (const uchar*) packet->ptr(), packet->length(), - MYF(MY_WME))) - DBUG_RETURN(-1); - } - DBUG_RETURN(0); -} - /* Go through all character combinations and ensure that sql_lex.cc can parse it as an identifier. @@ -935,7 +908,7 @@ append_identifier(THD *thd, String *packet, const char *name, uint length) it's a keyword */ - VOID(packet->reserve(length*2 + 2)); + (void) packet->reserve(length*2 + 2); quote_char= (char) q; packet->append("e_char, 1, system_charset_info); @@ -988,7 +961,7 @@ int get_quote_char_for_identifier(THD *thd, const char *name, uint length) if (length && !is_keyword(name,length) && !require_quotes(name, length) && - !(thd->options & OPTION_QUOTE_SHOW_CREATE)) + !(thd->variables.option_bits & OPTION_QUOTE_SHOW_CREATE)) return EOF; if (thd->variables.sql_mode & MODE_ANSI_QUOTES) return '"'; @@ -1026,20 +999,21 @@ static void append_directory(THD *thd, String *packet, const char *dir_type, #define LIST_PROCESS_HOST_LEN 64 -static bool get_field_default_value(THD *thd, TABLE *table, +static bool get_field_default_value(THD *thd, Field *timestamp_field, Field *field, String *def_value, bool quoted) { bool has_default; bool has_now_default; enum enum_field_types field_type= field->type(); - /* + + /* We are using CURRENT_TIMESTAMP instead of NOW because it is more standard */ - has_now_default= table->timestamp_field == field && - field->unireg_check != Field::TIMESTAMP_UN_FIELD; - + has_now_default= (timestamp_field == field && + field->unireg_check != Field::TIMESTAMP_UN_FIELD); + has_default= (field_type != FIELD_TYPE_BLOB && !(field->flags & NO_DEFAULT_VALUE_FLAG) && field->unireg_check != Field::NEXT_NUMBER && @@ -1092,6 +1066,7 @@ static bool get_field_default_value(THD *thd, TABLE *table, return has_default; } + /* Build a CREATE TABLE statement for a table. @@ -1241,7 +1216,8 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet, packet->append(STRING_WITH_LEN(" NULL")); } - if (get_field_default_value(thd, table, field, &def_value, 1)) + if (get_field_default_value(thd, table->timestamp_field, + field, &def_value, 1)) { packet->append(STRING_WITH_LEN(" DEFAULT ")); packet->append(def_value.ptr(), def_value.length(), system_charset_info); @@ -1704,6 +1680,30 @@ public: template class I_List<thread_info>; #endif +static const char *thread_state_info(THD *tmp) +{ +#ifndef EMBEDDED_LIBRARY + if (tmp->net.reading_or_writing) + { + if (tmp->net.reading_or_writing == 2) + return "Writing to net"; + else if (tmp->command == COM_SLEEP) + return ""; + else + return "Reading from net"; + } + else +#endif + { + if (tmp->proc_info) + return tmp->proc_info; + else if (tmp->mysys_var && tmp->mysys_var->current_cond) + return "Waiting on cond"; + else + return NULL; + } +} + void mysqld_list_processes(THD *thd,const char *user, bool verbose) { Item *field; @@ -1730,7 +1730,7 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) DBUG_VOID_RETURN; - VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list + mysql_mutex_lock(&LOCK_thread_count); // For unlink from list if (!thd->killed) { I_List_iterator<THD> it(threads); @@ -1763,40 +1763,27 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) thd_info->db=thd->strdup(thd_info->db); thd_info->command=(int) tmp->command; if ((mysys_var= tmp->mysys_var)) - pthread_mutex_lock(&mysys_var->mutex); + mysql_mutex_lock(&mysys_var->mutex); thd_info->proc_info= (char*) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0); -#ifndef EMBEDDED_LIBRARY - thd_info->state_info= (char*) (tmp->locked ? "Locked" : - tmp->net.reading_or_writing ? - (tmp->net.reading_or_writing == 2 ? - "Writing to net" : - thd_info->command == COM_SLEEP ? "" : - "Reading from net") : - tmp->proc_info ? tmp->proc_info : - tmp->mysys_var && - tmp->mysys_var->current_cond ? - "Waiting on cond" : NullS); -#else - thd_info->state_info= (char*)"Writing to net"; -#endif + thd_info->state_info= thread_state_info(tmp); if (mysys_var) - pthread_mutex_unlock(&mysys_var->mutex); + mysql_mutex_unlock(&mysys_var->mutex); thd_info->start_time= tmp->start_time; thd_info->query=0; /* Lock THD mutex that protects its data when looking at it. */ - pthread_mutex_lock(&tmp->LOCK_thd_data); + mysql_mutex_lock(&tmp->LOCK_thd_data); if (tmp->query()) { uint length= min(max_query_length, tmp->query_length()); thd_info->query= (char*) thd->strmake(tmp->query(),length); } - pthread_mutex_unlock(&tmp->LOCK_thd_data); + mysql_mutex_unlock(&tmp->LOCK_thd_data); thread_infos.append(thd_info); } } } - VOID(pthread_mutex_unlock(&LOCK_thread_count)); + mysql_mutex_unlock(&LOCK_thread_count); thread_info *thd_info; time_t now= my_time(0); @@ -1835,7 +1822,7 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) user= thd->security_ctx->master_access & PROCESS_ACL ? NullS : thd->security_ctx->priv_user; - VOID(pthread_mutex_lock(&LOCK_thread_count)); + mysql_mutex_lock(&LOCK_thread_count); if (!thd->killed) { @@ -1879,7 +1866,7 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) } if ((mysys_var= tmp->mysys_var)) - pthread_mutex_lock(&mysys_var->mutex); + mysql_mutex_lock(&mysys_var->mutex); /* COMMAND */ if ((val= (char *) (tmp->killed == THD::KILL_CONNECTION? "Killed" : 0))) table->field[4]->store(val, strlen(val), cs); @@ -1890,28 +1877,14 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) table->field[5]->store((longlong)(tmp->start_time ? now - tmp->start_time : 0), FALSE); /* STATE */ -#ifndef EMBEDDED_LIBRARY - val= (char*) (tmp->locked ? "Locked" : - tmp->net.reading_or_writing ? - (tmp->net.reading_or_writing == 2 ? - "Writing to net" : - tmp->command == COM_SLEEP ? "" : - "Reading from net") : - tmp->proc_info ? tmp->proc_info : - tmp->mysys_var && - tmp->mysys_var->current_cond ? - "Waiting on cond" : NullS); -#else - val= (char *) (tmp->proc_info ? tmp->proc_info : NullS); -#endif - if (val) + if ((val= thread_state_info(tmp))) { table->field[6]->store(val, strlen(val), cs); table->field[6]->set_notnull(); } if (mysys_var) - pthread_mutex_unlock(&mysys_var->mutex); + mysql_mutex_unlock(&mysys_var->mutex); /* INFO */ if (tmp->query()) @@ -1924,13 +1897,13 @@ int fill_schema_processlist(THD* thd, TABLE_LIST* tables, COND* cond) if (schema_table_store_record(thd, table)) { - VOID(pthread_mutex_unlock(&LOCK_thread_count)); + mysql_mutex_unlock(&LOCK_thread_count); DBUG_RETURN(1); } } } - VOID(pthread_mutex_unlock(&LOCK_thread_count)); + mysql_mutex_unlock(&LOCK_thread_count); DBUG_RETURN(0); } @@ -1989,7 +1962,7 @@ int add_status_vars(SHOW_VAR *list) { int res= 0; if (status_vars_inited) - pthread_mutex_lock(&LOCK_status); + mysql_mutex_lock(&LOCK_status); if (!all_status_vars.buffer && // array is not allocated yet - do it now my_init_dynamic_array(&all_status_vars, sizeof(SHOW_VAR), 200, 20)) { @@ -2004,7 +1977,7 @@ int add_status_vars(SHOW_VAR *list) sort_dynamic(&all_status_vars, show_var_cmp); err: if (status_vars_inited) - pthread_mutex_unlock(&LOCK_status); + mysql_mutex_unlock(&LOCK_status); return res; } @@ -2066,7 +2039,7 @@ void remove_status_vars(SHOW_VAR *list) { if (status_vars_inited) { - pthread_mutex_lock(&LOCK_status); + mysql_mutex_lock(&LOCK_status); SHOW_VAR *all= dynamic_element(&all_status_vars, 0, SHOW_VAR *); int a= 0, b= all_status_vars.elements, c= (a+b)/2; @@ -2087,7 +2060,7 @@ void remove_status_vars(SHOW_VAR *list) all[c].type= SHOW_UNDEF; } shrink_var_array(&all_status_vars); - pthread_mutex_unlock(&LOCK_status); + mysql_mutex_unlock(&LOCK_status); } else { @@ -2177,7 +2150,7 @@ static bool show_status_array(THD *thd, const char *wild, char *value=var->value; const char *pos, *end; // We assign a lot of const's - pthread_mutex_lock(&LOCK_global_system_variables); + mysql_mutex_lock(&LOCK_global_system_variables); if (show_type == SHOW_SYS) { @@ -2197,7 +2170,8 @@ static bool show_status_array(THD *thd, const char *wild, value= ((char *) status_var + (ulong) value); /* fall through */ case SHOW_DOUBLE: - end= buff + my_sprintf(buff, (buff, "%f", *(double*) value)); + /* 6 is the default precision for '%f' in sprintf() */ + end= buff + my_fcvt(*(double *) value, 6, buff, NULL); break; case SHOW_LONG_STATUS: value= ((char *) status_var + (ulong) value); @@ -2245,6 +2219,15 @@ static bool show_status_array(THD *thd, const char *wild, end= strend(pos); break; } + case SHOW_LEX_STRING: + { + LEX_STRING *ls=(LEX_STRING*)value; + if (!(pos= ls->str)) + end= pos= ""; + else + end= pos + ls->length; + break; + } case SHOW_KEY_CACHE_LONG: value= (char*) dflt_key_cache + (ulong)value; end= int10_to_str(*(long*) value, buff, 10); @@ -2264,7 +2247,7 @@ static bool show_status_array(THD *thd, const char *wild, thd->count_cuted_fields= CHECK_FIELD_IGNORE; table->field[1]->set_notnull(); - pthread_mutex_unlock(&LOCK_global_system_variables); + mysql_mutex_unlock(&LOCK_global_system_variables); if (schema_table_store_record(thd, table)) { @@ -2287,7 +2270,7 @@ void calc_sum_of_all_status(STATUS_VAR *to) DBUG_ENTER("calc_sum_of_all_status"); /* Ensure that thread id not killed during loop */ - VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list + mysql_mutex_lock(&LOCK_thread_count); // For unlink from list I_List_iterator<THD> it(threads); THD *tmp; @@ -2299,7 +2282,7 @@ void calc_sum_of_all_status(STATUS_VAR *to) while ((tmp= it++)) add_to_status(to, &tmp->status_var); - VOID(pthread_mutex_unlock(&LOCK_thread_count)); + mysql_mutex_unlock(&LOCK_thread_count); DBUG_VOID_RETURN; } @@ -2702,8 +2685,8 @@ int make_db_list(THD *thd, List<LEX_STRING> *files, */ if (lookup_field_vals->db_value.str) { - if (is_schema_db(lookup_field_vals->db_value.str, - lookup_field_vals->db_value.length)) + if (is_infoschema_db(lookup_field_vals->db_value.str, + lookup_field_vals->db_value.length)) { *with_i_schema= 1; if (files->push_back(i_s_name_copy)) @@ -2854,9 +2837,9 @@ make_table_name_list(THD *thd, List<LEX_STRING> *table_names, LEX *lex, Check that table is relevant in current transaction. (used for ndb engine, see ndbcluster_find_files(), ha_ndbcluster.cc) */ - VOID(ha_find_files(thd, db_name->str, path, + (void) ha_find_files(thd, db_name->str, path, lookup_field_vals->table_value.str, 0, - table_names)); + table_names); } return 0; } @@ -3094,17 +3077,18 @@ uint get_table_open_method(TABLE_LIST *tables, open_tables function for this table */ -static int fill_schema_table_from_frm(THD *thd,TABLE *table, - ST_SCHEMA_TABLE *schema_table, +static int fill_schema_table_from_frm(THD *thd, TABLE_LIST *tables, + ST_SCHEMA_TABLE *schema_table, LEX_STRING *db_name, LEX_STRING *table_name, enum enum_schema_tables schema_table_idx) { + TABLE *table= tables->table; TABLE_SHARE *share; TABLE tbl; TABLE_LIST table_list; uint res= 0; - int error; + int not_used; char key[MAX_DBKEY_LENGTH]; uint key_length; char db_name_buff[NAME_LEN + 1], table_name_buff[NAME_LEN + 1]; @@ -3132,61 +3116,85 @@ static int fill_schema_table_from_frm(THD *thd,TABLE *table, table_list.db= db_name->str; } + if (schema_table->i_s_requested_object & OPEN_TRIGGER_ONLY) + { + init_sql_alloc(&tbl.mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); + if (!Table_triggers_list::check_n_load(thd, db_name->str, + table_name->str, &tbl, 1)) + { + table_list.table= &tbl; + res= schema_table->process_table(thd, &table_list, table, + res, db_name, table_name); + delete tbl.triggers; + } + free_root(&tbl.mem_root, MYF(0)); + goto end; + } + key_length= create_table_def_key(thd, key, &table_list, 0); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); share= get_table_share(thd, &table_list, key, - key_length, OPEN_VIEW, &error); + key_length, OPEN_VIEW, ¬_used); if (!share) { res= 0; - goto err; + goto end_unlock; } - + if (share->is_view) { if (schema_table->i_s_requested_object & OPEN_TABLE_ONLY) { /* skip view processing */ res= 0; - goto err1; + goto end_share; } else if (schema_table->i_s_requested_object & OPEN_VIEW_FULL) { /* - tell get_all_tables() to fall back to + tell get_all_tables() to fall back to open_normal_and_derived_tables() */ res= 1; - goto err1; + goto end_share; } } - if (share->is_view || - !open_table_from_share(thd, share, table_name->str, 0, - (READ_KEYINFO | COMPUTE_TYPES | - EXTRA_RECORD | OPEN_FRM_FILE_ONLY), - thd->open_options, &tbl, FALSE)) + if (share->is_view) + { + if (open_new_frm(thd, share, table_name->str, + (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | + HA_GET_INDEX | HA_TRY_READ_ONLY), + READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD | + OPEN_VIEW_NO_PARSE, + thd->open_options, &tbl, &table_list, thd->mem_root)) + goto end_share; + table_list.view= (LEX*) share->is_view; + res= schema_table->process_table(thd, &table_list, table, + res, db_name, table_name); + goto end_share; + } + { tbl.s= share; table_list.table= &tbl; table_list.view= (LEX*) share->is_view; res= schema_table->process_table(thd, &table_list, table, res, db_name, table_name); - closefrm(&tbl, true); - goto err; } -err1: +end_share: release_table_share(share, RELEASE_NORMAL); -err: - pthread_mutex_unlock(&LOCK_open); +end_unlock: + mysql_mutex_unlock(&LOCK_open); + +end: thd->clear_error(); return res; } - /** @brief Fill I_S tables whose data are retrieved from frm files and storage engine @@ -3243,6 +3251,10 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) */ thd->reset_n_backup_open_tables_state(&open_tables_state_backup); + schema_table_idx= get_schema_table_idx(schema_table); + tables->table_open_method= table_open_method= + get_table_open_method(tables, schema_table, schema_table_idx); + DBUG_PRINT("open_method", ("%d", tables->table_open_method)); /* this branch processes SHOW FIELDS, SHOW INDEXES commands. see sql_parse.cc, prepare_schema_table() function where @@ -3255,7 +3267,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) goto err; } - schema_table_idx= get_schema_table_idx(schema_table); if (get_lookup_field_values(thd, cond, tables, &lookup_field_vals)) { error= 0; @@ -3293,9 +3304,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) else partial_cond= make_cond_for_info_schema(cond, tables); - tables->table_open_method= table_open_method= - get_table_open_method(tables, schema_table, schema_table_idx); - if (lex->describe) { /* EXPLAIN SELECT */ @@ -3309,8 +3317,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) while ((db_name= it++)) { #ifndef NO_EMBEDDED_ACCESS_CHECKS - if (!(check_access(thd,SELECT_ACL, db_name->str, - &thd->col_access, 0, 1, with_i_schema) || + if (!(check_access(thd, SELECT_ACL, db_name->str, + &thd->col_access, NULL, 0, 1) || (!thd->col_access && check_grant_db(thd, db_name->str))) || sctx->master_access & (DB_ACLS | SHOW_DB_ACL) || acl_get(sctx->host, sctx->ip, sctx->priv_user, db_name->str, 0)) @@ -3362,10 +3370,10 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) } else { - if (!(table_open_method & ~OPEN_FRM_ONLY) && + if (!(table_open_method & ~OPEN_FRM_ONLY) && !with_i_schema) { - if (!fill_schema_table_from_frm(thd, table, schema_table, db_name, + if (!fill_schema_table_from_frm(thd, tables, schema_table, db_name, table_name, schema_table_idx)) continue; } @@ -3508,7 +3516,7 @@ int fill_schema_schemata(THD *thd, TABLE_LIST *tables, COND *cond) path_len= build_table_filename(path, sizeof(path) - 1, lookup_field_vals.db_value.str, "", "", 0); path[path_len-1]= 0; - if (!my_stat(path,&stat_info,MYF(0))) + if (!mysql_file_stat(key_file_misc, path, &stat_info, MYF(0))) DBUG_RETURN(0); } @@ -3741,6 +3749,128 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables, } +/** + @brief Store field characteristics into appropriate I_S table columns + + @param[in] table I_S table + @param[in] field processed field + @param[in] cs I_S table charset + @param[in] offset offset from beginning of table + to DATE_TYPE column in I_S table + + @return void +*/ + +void store_column_type(TABLE *table, Field *field, CHARSET_INFO *cs, + uint offset) +{ + bool is_blob; + int decimals, field_length; + const char *tmp_buff; + char column_type_buff[MAX_FIELD_WIDTH]; + String column_type(column_type_buff, sizeof(column_type_buff), cs); + + field->sql_type(column_type); + /* DTD_IDENTIFIER column */ + table->field[offset + 7]->store(column_type.ptr(), column_type.length(), cs); + table->field[offset + 7]->set_notnull(); + /* + DATA_TYPE column: + MySQL column type has the following format: + base_type [(dimension)] [unsigned] [zerofill]. + For DATA_TYPE column we extract only base type. + */ + tmp_buff= strchr(column_type.ptr(), '('); + if (!tmp_buff) + /* + if there is no dimention part then check the presence of + [unsigned] [zerofill] attributes and cut them of if exist. + */ + tmp_buff= strchr(column_type.ptr(), ' '); + table->field[offset]->store(column_type.ptr(), + (tmp_buff ? tmp_buff - column_type.ptr() : + column_type.length()), cs); + + is_blob= (field->type() == MYSQL_TYPE_BLOB); + if (field->has_charset() || is_blob || + field->real_type() == MYSQL_TYPE_VARCHAR || // For varbinary type + field->real_type() == MYSQL_TYPE_STRING) // For binary type + { + uint32 octet_max_length= field->max_display_length(); + if (is_blob && octet_max_length != (uint32) 4294967295U) + octet_max_length /= field->charset()->mbmaxlen; + longlong char_max_len= is_blob ? + (longlong) octet_max_length / field->charset()->mbminlen : + (longlong) octet_max_length / field->charset()->mbmaxlen; + /* CHARACTER_MAXIMUM_LENGTH column*/ + table->field[offset + 1]->store(char_max_len, TRUE); + table->field[offset + 1]->set_notnull(); + /* CHARACTER_OCTET_LENGTH column */ + table->field[offset + 2]->store((longlong) octet_max_length, TRUE); + table->field[offset + 2]->set_notnull(); + } + + /* + Calculate field_length and decimals. + They are set to -1 if they should not be set (we should return NULL) + */ + + decimals= field->decimals(); + switch (field->type()) { + case MYSQL_TYPE_NEWDECIMAL: + field_length= ((Field_new_decimal*) field)->precision; + break; + case MYSQL_TYPE_DECIMAL: + field_length= field->field_length - (decimals ? 2 : 1); + break; + case MYSQL_TYPE_TINY: + case MYSQL_TYPE_SHORT: + case MYSQL_TYPE_LONG: + case MYSQL_TYPE_LONGLONG: + case MYSQL_TYPE_INT24: + field_length= field->max_display_length() - 1; + break; + case MYSQL_TYPE_BIT: + field_length= field->max_display_length(); + decimals= -1; // return NULL + break; + case MYSQL_TYPE_FLOAT: + case MYSQL_TYPE_DOUBLE: + field_length= field->field_length; + if (decimals == NOT_FIXED_DEC) + decimals= -1; // return NULL + break; + default: + field_length= decimals= -1; + break; + } + + /* NUMERIC_PRECISION column */ + if (field_length >= 0) + { + table->field[offset + 3]->store((longlong) field_length, TRUE); + table->field[offset + 3]->set_notnull(); + } + /* NUMERIC_SCALE column */ + if (decimals >= 0) + { + table->field[offset + 4]->store((longlong) decimals, TRUE); + table->field[offset + 4]->set_notnull(); + } + if (field->has_charset()) + { + /* CHARACTER_SET_NAME column*/ + tmp_buff= field->charset()->csname; + table->field[offset + 5]->store(tmp_buff, strlen(tmp_buff), cs); + table->field[offset + 5]->set_notnull(); + /* COLLATION_NAME column */ + tmp_buff= field->charset()->name; + table->field[offset + 6]->store(tmp_buff, strlen(tmp_buff), cs); + table->field[offset + 6]->set_notnull(); + } +} + + static int get_schema_column_record(THD *thd, TABLE_LIST *tables, TABLE *table, bool res, LEX_STRING *db_name, @@ -3750,7 +3880,8 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, const char *wild= lex->wild ? lex->wild->ptr() : NullS; CHARSET_INFO *cs= system_charset_info; TABLE *show_table; - Field **ptr,*field; + TABLE_SHARE *show_table_share; + Field **ptr, *field, *timestamp_field; int count; DBUG_ENTER("get_schema_column_record"); @@ -3761,7 +3892,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, /* I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS rather than in SHOW COLUMNS - */ + */ if (thd->is_error()) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, thd->stmt_da->sql_errno(), thd->stmt_da->message()); @@ -3772,26 +3903,53 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, } show_table= tables->table; + show_table_share= show_table->s; count= 0; - restore_record(show_table, s->default_values); - show_table->use_all_columns(); // Required for default - for (ptr= show_table->field; (field= *ptr) ; ptr++) + if (tables->view || tables->schema_table) + { + ptr= show_table->field; + timestamp_field= show_table->timestamp_field; + show_table->use_all_columns(); // Required for default + } + else + { + ptr= show_table_share->field; + timestamp_field= show_table_share->timestamp_field; + /* + read_set may be inited in case of + temporary table + */ + if (!show_table->read_set) + { + /* to satisfy 'field->val_str' ASSERTs */ + uchar *bitmaps; + uint bitmap_size= show_table_share->column_bitmap_size; + if (!(bitmaps= (uchar*) alloc_root(thd->mem_root, bitmap_size))) + DBUG_RETURN(0); + bitmap_init(&show_table->def_read_set, + (my_bitmap_map*) bitmaps, show_table_share->fields, FALSE); + bitmap_set_all(&show_table->def_read_set); + show_table->read_set= &show_table->def_read_set; + } + bitmap_set_all(show_table->read_set); + } + + for (; (field= *ptr) ; ptr++) { - const char *tmp_buff; uchar *pos; - bool is_blob; - uint flags=field->flags; char tmp[MAX_FIELD_WIDTH]; String type(tmp,sizeof(tmp), system_charset_info); char *end; - int decimals, field_length; + + /* to satisfy 'field->val_str' ASSERTs */ + field->table= show_table; + show_table->in_use= thd; if (wild && wild[0] && wild_case_compare(system_charset_info, field->field_name,wild)) continue; - flags= field->flags; count++; /* Get default row, with all NULL fields set to NULL */ restore_record(table, s->default_values); @@ -3799,9 +3957,8 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, #ifndef NO_EMBEDDED_ACCESS_CHECKS uint col_access; check_access(thd,SELECT_ACL, db_name->str, - &tables->grant.privilege, FALSE, FALSE, - test(tables->schema_table)); - col_access= get_column_grant(thd, &tables->grant, + &tables->grant.privilege, 0, 0, test(tables->schema_table)); + col_access= get_column_grant(thd, &tables->grant, db_name->str, table_name->str, field->field_name) & COL_ACLS; if (!tables->schema_table && !col_access) @@ -3826,104 +3983,16 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, table->field[4]->store((longlong) count, TRUE); field->sql_type(type); table->field[14]->store(type.ptr(), type.length(), cs); - /* - MySQL column type has the following format: - base_type [(dimension)] [unsigned] [zerofill]. - For DATA_TYPE column we extract only base type. - */ - tmp_buff= strchr(type.ptr(), '('); - if (!tmp_buff) - /* - if there is no dimention part then check the presence of - [unsigned] [zerofill] attributes and cut them of if exist. - */ - tmp_buff= strchr(type.ptr(), ' '); - table->field[7]->store(type.ptr(), - (tmp_buff ? tmp_buff - type.ptr() : - type.length()), cs); - if (get_field_default_value(thd, show_table, field, &type, 0)) + if (get_field_default_value(thd, timestamp_field, field, &type, 0)) { table->field[5]->store(type.ptr(), type.length(), cs); table->field[5]->set_notnull(); } - pos=(uchar*) ((flags & NOT_NULL_FLAG) ? "NO" : "YES"); + pos=(uchar*) ((field->flags & NOT_NULL_FLAG) ? "NO" : "YES"); table->field[6]->store((const char*) pos, strlen((const char*) pos), cs); - is_blob= (field->type() == MYSQL_TYPE_BLOB); - if (field->has_charset() || is_blob || - field->real_type() == MYSQL_TYPE_VARCHAR || // For varbinary type - field->real_type() == MYSQL_TYPE_STRING) // For binary type - { - uint32 octet_max_length= field->max_display_length(); - if (is_blob && octet_max_length != (uint32) 4294967295U) - octet_max_length /= field->charset()->mbmaxlen; - longlong char_max_len= is_blob ? - (longlong) octet_max_length / field->charset()->mbminlen : - (longlong) octet_max_length / field->charset()->mbmaxlen; - table->field[8]->store(char_max_len, TRUE); - table->field[8]->set_notnull(); - table->field[9]->store((longlong) octet_max_length, TRUE); - table->field[9]->set_notnull(); - } - - /* - Calculate field_length and decimals. - They are set to -1 if they should not be set (we should return NULL) - */ - - decimals= field->decimals(); - switch (field->type()) { - case MYSQL_TYPE_NEWDECIMAL: - field_length= ((Field_new_decimal*) field)->precision; - break; - case MYSQL_TYPE_DECIMAL: - field_length= field->field_length - (decimals ? 2 : 1); - break; - case MYSQL_TYPE_TINY: - case MYSQL_TYPE_SHORT: - case MYSQL_TYPE_LONG: - case MYSQL_TYPE_LONGLONG: - case MYSQL_TYPE_INT24: - field_length= field->max_display_length() - 1; - break; - case MYSQL_TYPE_BIT: - field_length= field->max_display_length(); - decimals= -1; // return NULL - break; - case MYSQL_TYPE_FLOAT: - case MYSQL_TYPE_DOUBLE: - field_length= field->field_length; - if (decimals == NOT_FIXED_DEC) - decimals= -1; // return NULL - break; - default: - field_length= decimals= -1; - break; - } - - if (field_length >= 0) - { - table->field[10]->store((longlong) field_length, TRUE); - table->field[10]->set_notnull(); - } - if (decimals >= 0) - { - table->field[11]->store((longlong) decimals, TRUE); - table->field[11]->set_notnull(); - } - - if (field->has_charset()) - { - pos=(uchar*) field->charset()->csname; - table->field[12]->store((const char*) pos, - strlen((const char*) pos), cs); - table->field[12]->set_notnull(); - pos=(uchar*) field->charset()->name; - table->field[13]->store((const char*) pos, - strlen((const char*) pos), cs); - table->field[13]->set_notnull(); - } + store_column_type(table, field, cs, 7); pos=(uchar*) ((field->flags & PRI_KEY_FLAG) ? "PRI" : (field->flags & UNIQUE_KEY_FLAG) ? "UNI" : (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":""); @@ -3933,7 +4002,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, end= tmp; if (field->unireg_check == Field::NEXT_NUMBER) table->field[16]->store(STRING_WITH_LEN("auto_increment"), cs); - if (show_table->timestamp_field == field && + if (timestamp_field == field && field->unireg_check != Field::TIMESTAMP_DN_FIELD) table->field[16]->store(STRING_WITH_LEN("on update CURRENT_TIMESTAMP"), cs); @@ -3946,7 +4015,6 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, } - int fill_schema_charsets(THD *thd, TABLE_LIST *tables, COND *cond) { CHARSET_INFO **cs; @@ -4135,6 +4203,169 @@ int fill_schema_coll_charset_app(THD *thd, TABLE_LIST *tables, COND *cond) } +/** + @brief Store record into I_S.PARAMETERS table + + @param[in] thd thread handler + @param[in] table I_S table + @param[in] proc_table 'mysql.proc' table + @param[in] wild wild string, not used for now, + will be useful + if we add 'SHOW PARAMETERs' + @param[in] full_access if 1 user has privileges on the routine + @param[in] sp_user user in 'user@host' format + + @return Operation status + @retval 0 ok + @retval 1 error +*/ + +bool store_schema_params(THD *thd, TABLE *table, TABLE *proc_table, + const char *wild, bool full_access, + const char *sp_user) +{ + TABLE_SHARE share; + TABLE tbl; + CHARSET_INFO *cs= system_charset_info; + char params_buff[MAX_FIELD_WIDTH], returns_buff[MAX_FIELD_WIDTH], + sp_db_buff[NAME_LEN], sp_name_buff[NAME_LEN], path[FN_REFLEN], + definer_buff[USERNAME_LENGTH + HOSTNAME_LENGTH + 1]; + String params(params_buff, sizeof(params_buff), cs); + String returns(returns_buff, sizeof(returns_buff), cs); + String sp_db(sp_db_buff, sizeof(sp_db_buff), cs); + String sp_name(sp_name_buff, sizeof(sp_name_buff), cs); + String definer(definer_buff, sizeof(definer_buff), cs); + sp_head *sp; + uint routine_type; + bool free_sp_head; + DBUG_ENTER("store_schema_params"); + + bzero((char*) &tbl, sizeof(TABLE)); + (void) build_table_filename(path, sizeof(path), "", "", "", 0); + init_tmp_table_share(thd, &share, "", 0, "", path); + + get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_DB], &sp_db); + get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_NAME], &sp_name); + get_field(thd->mem_root,proc_table->field[MYSQL_PROC_FIELD_DEFINER],&definer); + routine_type= (uint) proc_table->field[MYSQL_PROC_MYSQL_TYPE]->val_int(); + + if (!full_access) + full_access= !strcmp(sp_user, definer.ptr()); + if (!full_access && + check_some_routine_access(thd, sp_db.ptr(),sp_name.ptr(), + routine_type == TYPE_ENUM_PROCEDURE)) + DBUG_RETURN(0); + + params.length(0); + get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_PARAM_LIST], + ¶ms); + returns.length(0); + if (routine_type == TYPE_ENUM_FUNCTION) + get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_RETURNS], + &returns); + + sp= sp_load_for_information_schema(thd, proc_table, &sp_db, &sp_name, + (ulong) proc_table-> + field[MYSQL_PROC_FIELD_SQL_MODE]->val_int(), + routine_type, + returns.c_ptr_safe(), + params.c_ptr_safe(), + &free_sp_head); + + if (sp) + { + Field *field; + Create_field *field_def; + String tmp_string; + if (routine_type == TYPE_ENUM_FUNCTION) + { + restore_record(table, s->default_values); + table->field[0]->store(STRING_WITH_LEN("def"), cs); + table->field[1]->store(sp_db.ptr(), sp_db.length(), cs); + table->field[2]->store(sp_name.ptr(), sp_name.length(), cs); + table->field[3]->store((longlong) 0, TRUE); + get_field(thd->mem_root, proc_table->field[MYSQL_PROC_MYSQL_TYPE], + &tmp_string); + table->field[14]->store(tmp_string.ptr(), tmp_string.length(), cs); + field_def= &sp->m_return_field_def; + field= make_field(&share, (uchar*) 0, field_def->length, + (uchar*) "", 0, field_def->pack_flag, + field_def->sql_type, field_def->charset, + field_def->geom_type, Field::NONE, + field_def->interval, ""); + + field->table= &tbl; + tbl.in_use= thd; + store_column_type(table, field, cs, 6); + if (schema_table_store_record(thd, table)) + { + free_table_share(&share); + if (free_sp_head) + delete sp; + DBUG_RETURN(1); + } + } + + sp_pcontext *spcont= sp->get_parse_context(); + uint params= spcont->context_var_count(); + for (uint i= 0 ; i < params ; i++) + { + const char *tmp_buff; + sp_variable_t *spvar= spcont->find_variable(i); + field_def= &spvar->field_def; + switch (spvar->mode) { + case sp_param_in: + tmp_buff= "IN"; + break; + case sp_param_out: + tmp_buff= "OUT"; + break; + case sp_param_inout: + tmp_buff= "INOUT"; + break; + default: + tmp_buff= ""; + break; + } + + restore_record(table, s->default_values); + table->field[0]->store(STRING_WITH_LEN("def"), cs); + table->field[1]->store(sp_db.ptr(), sp_db.length(), cs); + table->field[2]->store(sp_name.ptr(), sp_name.length(), cs); + table->field[3]->store((longlong) i + 1, TRUE); + table->field[4]->store(tmp_buff, strlen(tmp_buff), cs); + table->field[4]->set_notnull(); + table->field[5]->store(spvar->name.str, spvar->name.length, cs); + table->field[5]->set_notnull(); + get_field(thd->mem_root, proc_table->field[MYSQL_PROC_MYSQL_TYPE], + &tmp_string); + table->field[14]->store(tmp_string.ptr(), tmp_string.length(), cs); + + field= make_field(&share, (uchar*) 0, field_def->length, + (uchar*) "", 0, field_def->pack_flag, + field_def->sql_type, field_def->charset, + field_def->geom_type, Field::NONE, + field_def->interval, spvar->name.str); + + field->table= &tbl; + tbl.in_use= thd; + store_column_type(table, field, cs, 6); + if (schema_table_store_record(thd, table)) + { + free_table_share(&share); + if (free_sp_head) + delete sp; + DBUG_RETURN(1); + } + } + if (free_sp_head) + delete sp; + } + free_table_share(&share); + DBUG_RETURN(0); +} + + bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, const char *wild, bool full_access, const char *sp_user) { @@ -4143,75 +4374,131 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, MYSQL_TIME time; LEX *lex= thd->lex; CHARSET_INFO *cs= system_charset_info; - get_field(thd->mem_root, proc_table->field[0], &sp_db); - get_field(thd->mem_root, proc_table->field[1], &sp_name); - get_field(thd->mem_root, proc_table->field[11], &definer); + get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_DB], &sp_db); + get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_NAME], &sp_name); + get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_DEFINER],&definer); if (!full_access) full_access= !strcmp(sp_user, definer.ptr()); - if (!full_access && check_some_routine_access(thd, sp_db.ptr(), - sp_name.ptr(), - proc_table->field[2]-> - val_int() == - TYPE_ENUM_PROCEDURE)) + if (!full_access && + check_some_routine_access(thd, sp_db.ptr(), sp_name.ptr(), + proc_table->field[MYSQL_PROC_MYSQL_TYPE]-> + val_int() == TYPE_ENUM_PROCEDURE)) return 0; if ((lex->sql_command == SQLCOM_SHOW_STATUS_PROC && - proc_table->field[2]->val_int() == TYPE_ENUM_PROCEDURE) || + proc_table->field[MYSQL_PROC_MYSQL_TYPE]->val_int() == + TYPE_ENUM_PROCEDURE) || (lex->sql_command == SQLCOM_SHOW_STATUS_FUNC && - proc_table->field[2]->val_int() == TYPE_ENUM_FUNCTION) || + proc_table->field[MYSQL_PROC_MYSQL_TYPE]->val_int() == + TYPE_ENUM_FUNCTION) || (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0) { restore_record(table, s->default_values); if (!wild || !wild[0] || !wild_compare(sp_name.ptr(), wild, 0)) { - int enum_idx= (int) proc_table->field[5]->val_int(); + int enum_idx= (int) proc_table->field[MYSQL_PROC_FIELD_ACCESS]->val_int(); table->field[3]->store(sp_name.ptr(), sp_name.length(), cs); - get_field(thd->mem_root, proc_table->field[3], &tmp_string); + get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_SPECIFIC_NAME], + &tmp_string); table->field[0]->store(tmp_string.ptr(), tmp_string.length(), cs); table->field[1]->store(STRING_WITH_LEN("def"), cs); table->field[2]->store(sp_db.ptr(), sp_db.length(), cs); - get_field(thd->mem_root, proc_table->field[2], &tmp_string); + get_field(thd->mem_root, proc_table->field[MYSQL_PROC_MYSQL_TYPE], + &tmp_string); table->field[4]->store(tmp_string.ptr(), tmp_string.length(), cs); - if (proc_table->field[2]->val_int() == TYPE_ENUM_FUNCTION) + if (proc_table->field[MYSQL_PROC_MYSQL_TYPE]->val_int() == + TYPE_ENUM_FUNCTION) { - get_field(thd->mem_root, proc_table->field[9], &tmp_string); - table->field[5]->store(tmp_string.ptr(), tmp_string.length(), cs); - table->field[5]->set_notnull(); + sp_head *sp; + bool free_sp_head; + get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_RETURNS], + &tmp_string); + + sp= sp_load_for_information_schema(thd, proc_table, &sp_db, &sp_name, + (ulong) proc_table-> + field[MYSQL_PROC_FIELD_SQL_MODE]-> + val_int(), + TYPE_ENUM_FUNCTION, + tmp_string.c_ptr_safe(), + "", &free_sp_head); + + if (sp) + { + char path[FN_REFLEN]; + TABLE_SHARE share; + TABLE tbl; + Field *field; + Create_field *field_def= &sp->m_return_field_def; + + bzero((char*) &tbl, sizeof(TABLE)); + (void) build_table_filename(path, sizeof(path), "", "", "", 0); + init_tmp_table_share(thd, &share, "", 0, "", path); + field= make_field(&share, (uchar*) 0, field_def->length, + (uchar*) "", 0, field_def->pack_flag, + field_def->sql_type, field_def->charset, + field_def->geom_type, Field::NONE, + field_def->interval, ""); + + field->table= &tbl; + tbl.in_use= thd; + store_column_type(table, field, cs, 5); + free_table_share(&share); + if (free_sp_head) + delete sp; + } } + if (full_access) { - get_field(thd->mem_root, proc_table->field[19], &tmp_string); - table->field[7]->store(tmp_string.ptr(), tmp_string.length(), cs); - table->field[7]->set_notnull(); + get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_BODY_UTF8], + &tmp_string); + table->field[14]->store(tmp_string.ptr(), tmp_string.length(), cs); + table->field[14]->set_notnull(); } - table->field[6]->store(STRING_WITH_LEN("SQL"), cs); - table->field[10]->store(STRING_WITH_LEN("SQL"), cs); - get_field(thd->mem_root, proc_table->field[6], &tmp_string); - table->field[11]->store(tmp_string.ptr(), tmp_string.length(), cs); - table->field[12]->store(sp_data_access_name[enum_idx].str, + table->field[13]->store(STRING_WITH_LEN("SQL"), cs); + table->field[17]->store(STRING_WITH_LEN("SQL"), cs); + + + get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_DETERMINISTIC], + &tmp_string); + table->field[18]->store(tmp_string.ptr(), tmp_string.length(), cs); + table->field[19]->store(sp_data_access_name[enum_idx].str, sp_data_access_name[enum_idx].length , cs); - get_field(thd->mem_root, proc_table->field[7], &tmp_string); - table->field[14]->store(tmp_string.ptr(), tmp_string.length(), cs); + + get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_SECURITY_TYPE], + &tmp_string); + table->field[21]->store(tmp_string.ptr(), tmp_string.length(), cs); bzero((char *)&time, sizeof(time)); - ((Field_timestamp *) proc_table->field[12])->get_time(&time); - table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); + ((Field_timestamp *) proc_table->field[MYSQL_PROC_FIELD_CREATED])-> + get_time(&time); + table->field[22]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); bzero((char *)&time, sizeof(time)); - ((Field_timestamp *) proc_table->field[13])->get_time(&time); - table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); - get_field(thd->mem_root, proc_table->field[14], &tmp_string); - table->field[17]->store(tmp_string.ptr(), tmp_string.length(), cs); - get_field(thd->mem_root, proc_table->field[15], &tmp_string); - table->field[18]->store(tmp_string.ptr(), tmp_string.length(), cs); - table->field[19]->store(definer.ptr(), definer.length(), cs); + ((Field_timestamp *) proc_table->field[MYSQL_PROC_FIELD_MODIFIED])-> + get_time(&time); + table->field[23]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); - get_field(thd->mem_root, proc_table->field[16], &tmp_string); - table->field[20]->store(tmp_string.ptr(), tmp_string.length(), cs); + get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_SQL_MODE], + &tmp_string); + table->field[24]->store(tmp_string.ptr(), tmp_string.length(), cs); - get_field(thd->mem_root, proc_table->field[17], &tmp_string); - table->field[21]->store(tmp_string.ptr(), tmp_string.length(), cs); + get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_COMMENT], + &tmp_string); + table->field[25]->store(tmp_string.ptr(), tmp_string.length(), cs); + table->field[26]->store(definer.ptr(), definer.length(), cs); - get_field(thd->mem_root, proc_table->field[18], &tmp_string); - table->field[22]->store(tmp_string.ptr(), tmp_string.length(), cs); + get_field(thd->mem_root, + proc_table->field[MYSQL_PROC_FIELD_CHARACTER_SET_CLIENT], + &tmp_string); + table->field[27]->store(tmp_string.ptr(), tmp_string.length(), cs); + + get_field(thd->mem_root, + proc_table->field[ MYSQL_PROC_FIELD_COLLATION_CONNECTION], + &tmp_string); + table->field[28]->store(tmp_string.ptr(), tmp_string.length(), cs); + + get_field(thd->mem_root, proc_table->field[MYSQL_PROC_FIELD_DB_COLLATION], + &tmp_string); + table->field[29]->store(tmp_string.ptr(), tmp_string.length(), cs); return schema_table_store_record(thd, table); } @@ -4230,6 +4517,8 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond) bool full_access; char definer[USER_HOST_BUFF_SIZE]; Open_tables_state open_tables_state_backup; + enum enum_schema_tables schema_table_idx= + get_schema_table_idx(tables->schema_table); DBUG_ENTER("fill_schema_proc"); strxmov(definer, thd->security_ctx->priv_user, "@", @@ -4253,14 +4542,19 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond) res= (res == HA_ERR_END_OF_FILE) ? 0 : 1; goto err; } - if (store_schema_proc(thd, table, proc_table, wild, full_access, definer)) + + if (schema_table_idx == SCH_PROCEDURES ? + store_schema_proc(thd, table, proc_table, wild, full_access, definer) : + store_schema_params(thd, table, proc_table, wild, full_access, definer)) { res= 1; goto err; } while (!proc_table->file->index_next(proc_table->record[0])) { - if (store_schema_proc(thd, table, proc_table, wild, full_access, definer)) + if (schema_table_idx == SCH_PROCEDURES ? + store_schema_proc(thd, table, proc_table, wild, full_access, definer): + store_schema_params(thd, table, proc_table, wild, full_access, definer)) { res= 1; goto err; @@ -4375,24 +4669,15 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables, LEX_STRING *table_name) { CHARSET_INFO *cs= system_charset_info; - DBUG_ENTER("get_schema_views_record"); - LEX_STRING *tmp_db_name, *tmp_table_name; char definer[USER_HOST_BUFF_SIZE]; uint definer_len; bool updatable_view; - /* - if SELECT FROM I_S.VIEWS uses only fields - which have OPEN_FRM_ONLY flag then 'tables' - structure is zeroed and only tables->view is set. - (see fill_schema_table_from_frm() function). - So we should disable other fields filling. - */ - bool only_share= !tables->definer.user.str; + DBUG_ENTER("get_schema_views_record"); if (tables->view) { Security_context *sctx= thd->security_ctx; - if (!only_share && !tables->allowed_show) + if (!tables->allowed_show) { if (!my_strcasecmp(system_charset_info, tables->definer.user.str, sctx->priv_user) && @@ -4410,47 +4695,42 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables, TABLE_LIST table_list; uint view_access; memset(&table_list, 0, sizeof(table_list)); - table_list.db= tables->view_db.str; - table_list.table_name= tables->view_name.str; + table_list.db= tables->db; + table_list.table_name= tables->table_name; table_list.grant.privilege= thd->col_access; view_access= get_table_grant(thd, &table_list); - if ((view_access & (SHOW_VIEW_ACL|SELECT_ACL)) == - (SHOW_VIEW_ACL|SELECT_ACL)) - tables->allowed_show= TRUE; + if ((view_access & (SHOW_VIEW_ACL|SELECT_ACL)) == + (SHOW_VIEW_ACL|SELECT_ACL)) + tables->allowed_show= TRUE; } } #endif } restore_record(table, s->default_values); - tmp_db_name= &tables->view_db; - tmp_table_name= &tables->view_name; - if (only_share) - { - tmp_db_name= db_name; - tmp_table_name= table_name; - } table->field[0]->store(STRING_WITH_LEN("def"), cs); - table->field[1]->store(tmp_db_name->str, tmp_db_name->length, cs); - table->field[2]->store(tmp_table_name->str, tmp_table_name->length, cs); - if (!only_share) + table->field[1]->store(db_name->str, db_name->length, cs); + table->field[2]->store(table_name->str, table_name->length, cs); + + if (tables->allowed_show) { - if (tables->allowed_show) - { - table->field[3]->store(tables->view_body_utf8.str, - tables->view_body_utf8.length, - cs); - } + table->field[3]->store(tables->view_body_utf8.str, + tables->view_body_utf8.length, + cs); + } - if (tables->with_check != VIEW_CHECK_NONE) - { - if (tables->with_check == VIEW_CHECK_LOCAL) - table->field[4]->store(STRING_WITH_LEN("LOCAL"), cs); - else - table->field[4]->store(STRING_WITH_LEN("CASCADED"), cs); - } + if (tables->with_check != VIEW_CHECK_NONE) + { + if (tables->with_check == VIEW_CHECK_LOCAL) + table->field[4]->store(STRING_WITH_LEN("LOCAL"), cs); else - table->field[4]->store(STRING_WITH_LEN("NONE"), cs); + table->field[4]->store(STRING_WITH_LEN("CASCADED"), cs); + } + else + table->field[4]->store(STRING_WITH_LEN("NONE"), cs); + if (table->pos_in_table_list->table_open_method & + OPEN_FULL_TABLE) + { updatable_view= 0; if (tables->algorithm != VIEW_ALGORITHM_TMPTABLE) { @@ -4484,31 +4764,33 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables, table->field[5]->store(STRING_WITH_LEN("YES"), cs); else table->field[5]->store(STRING_WITH_LEN("NO"), cs); - definer_len= (strxmov(definer, tables->definer.user.str, "@", - tables->definer.host.str, NullS) - definer); - table->field[6]->store(definer, definer_len, cs); - if (tables->view_suid) - table->field[7]->store(STRING_WITH_LEN("DEFINER"), cs); - else - table->field[7]->store(STRING_WITH_LEN("INVOKER"), cs); + } - table->field[8]->store(tables->view_creation_ctx->get_client_cs()->csname, - strlen(tables->view_creation_ctx-> - get_client_cs()->csname), cs); + definer_len= (strxmov(definer, tables->definer.user.str, "@", + tables->definer.host.str, NullS) - definer); + table->field[6]->store(definer, definer_len, cs); + if (tables->view_suid) + table->field[7]->store(STRING_WITH_LEN("DEFINER"), cs); + else + table->field[7]->store(STRING_WITH_LEN("INVOKER"), cs); + + table->field[8]->store(tables->view_creation_ctx->get_client_cs()->csname, + strlen(tables->view_creation_ctx-> + get_client_cs()->csname), cs); + + table->field[9]->store(tables->view_creation_ctx-> + get_connection_cl()->name, + strlen(tables->view_creation_ctx-> + get_connection_cl()->name), cs); - table->field[9]->store(tables->view_creation_ctx-> - get_connection_cl()->name, - strlen(tables->view_creation_ctx-> - get_connection_cl()->name), cs); - } if (schema_table_store_record(thd, table)) DBUG_RETURN(1); if (res && thd->is_error()) - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, thd->stmt_da->sql_errno(), thd->stmt_da->message()); } - if (res) + if (res) thd->clear_error(); DBUG_RETURN(0); } @@ -4620,8 +4902,7 @@ static bool store_trigger(THD *thd, TABLE *table, LEX_STRING *db_name, table->field[14]->store(STRING_WITH_LEN("OLD"), cs); table->field[15]->store(STRING_WITH_LEN("NEW"), cs); - sys_var_thd_sql_mode::symbolic_mode_representation(thd, sql_mode, - &sql_mode_rep); + sql_mode_string_representation(thd, sql_mode, &sql_mode_rep); table->field[17]->store(sql_mode_rep.str, sql_mode_rep.length, cs); table->field[18]->store(definer_buffer->str, definer_buffer->length, cs); table->field[19]->store(client_cs_name->str, client_cs_name->length, cs); @@ -5070,8 +5351,7 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables, break; default: DBUG_ASSERT(0); - my_error(ER_OUT_OF_RESOURCES, MYF(0)); - current_thd->fatal_error(); + my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR)); DBUG_RETURN(1); } table->field[7]->set_notnull(); @@ -5331,8 +5611,7 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) has access. */ if (thd->lex->sql_command != SQLCOM_SHOW_EVENTS && - check_access(thd, EVENT_ACL, et.dbname.str, 0, 0, 1, - is_schema_db(et.dbname.str, et.dbname.length))) + check_access(thd, EVENT_ACL, et.dbname.str, NULL, NULL, 0, 1)) DBUG_RETURN(0); sch_table->field[ISE_EVENT_CATALOG]->store(STRING_WITH_LEN("def"), scs); @@ -5353,8 +5632,7 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) /* SQL_MODE */ { LEX_STRING sql_mode; - sys_var_thd_sql_mode::symbolic_mode_representation(thd, et.sql_mode, - &sql_mode); + sql_mode_string_representation(thd, et.sql_mode, &sql_mode); sch_table->field[ISE_SQL_MODE]-> store(sql_mode.str, sql_mode.length, scs); } @@ -5517,10 +5795,10 @@ int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond) schema_table_idx == SCH_GLOBAL_VARIABLES) option_type= OPT_GLOBAL; - rw_rdlock(&LOCK_system_variables_hash); - res= show_status_array(thd, wild, enumerate_sys_vars(thd, sorted_vars), + mysql_rwlock_rdlock(&LOCK_system_variables_hash); + res= show_status_array(thd, wild, enumerate_sys_vars(thd, sorted_vars, option_type), option_type, NULL, "", tables->table, upper_case_names, cond); - rw_unlock(&LOCK_system_variables_hash); + mysql_rwlock_unlock(&LOCK_system_variables_hash); DBUG_RETURN(res); } @@ -5556,14 +5834,14 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond) tmp1= &thd->status_var; } - pthread_mutex_lock(&LOCK_status); + mysql_mutex_lock(&LOCK_status); if (option_type == OPT_GLOBAL) calc_sum_of_all_status(&tmp); res= show_status_array(thd, wild, (SHOW_VAR *)all_status_vars.buffer, option_type, tmp1, "", tables->table, upper_case_names, cond); - pthread_mutex_unlock(&LOCK_status); + mysql_mutex_unlock(&LOCK_status); DBUG_RETURN(res); } @@ -5843,7 +6121,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) SELECT_LEX *select_lex= thd->lex->current_select; if (!(table= create_tmp_table(thd, tmp_table_param, field_list, (ORDER*) 0, 0, 0, - (select_lex->options | thd->options | + (select_lex->options | thd->variables.option_bits | TMP_TABLE_ALL_COLUMNS), HA_POS_ERROR, table_list->alias))) DBUG_RETURN(0); @@ -6018,7 +6296,7 @@ int make_character_sets_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) int make_proc_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table) { - int fields_arr[]= {2, 3, 4, 19, 16, 15, 14, 18, 20, 21, 22, -1}; + int fields_arr[]= {2, 3, 4, 26, 23, 22, 21, 25, 27, 28, 29, -1}; int *field_num= fields_arr; ST_FIELD_INFO *field_info; Name_resolution_context *context= &thd->lex->select_lex.context; @@ -6253,32 +6531,33 @@ bool get_schema_tables_result(JOIN *join, DBUG_RETURN(result); } -struct run_hton_fill_schema_files_args +struct run_hton_fill_schema_table_args { TABLE_LIST *tables; COND *cond; }; -static my_bool run_hton_fill_schema_files(THD *thd, plugin_ref plugin, +static my_bool run_hton_fill_schema_table(THD *thd, plugin_ref plugin, void *arg) { - struct run_hton_fill_schema_files_args *args= - (run_hton_fill_schema_files_args *) arg; + struct run_hton_fill_schema_table_args *args= + (run_hton_fill_schema_table_args *) arg; handlerton *hton= plugin_data(plugin, handlerton *); - if(hton->fill_files_table && hton->state == SHOW_OPTION_YES) - hton->fill_files_table(hton, thd, args->tables, args->cond); + if (hton->fill_is_table && hton->state == SHOW_OPTION_YES) + hton->fill_is_table(hton, thd, args->tables, args->cond, + get_schema_table_idx(args->tables->schema_table)); return false; } -int fill_schema_files(THD *thd, TABLE_LIST *tables, COND *cond) +int hton_fill_schema_table(THD *thd, TABLE_LIST *tables, COND *cond) { - DBUG_ENTER("fill_schema_files"); + DBUG_ENTER("hton_fill_schema_table"); - struct run_hton_fill_schema_files_args args; + struct run_hton_fill_schema_table_args args; args.tables= tables; args.cond= cond; - plugin_foreach(thd, run_hton_fill_schema_files, + plugin_foreach(thd, run_hton_fill_schema_table, MYSQL_STORAGE_ENGINE_PLUGIN, &args); DBUG_RETURN(0); @@ -6469,7 +6748,14 @@ ST_FIELD_INFO proc_fields_info[]= {"ROUTINE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Name", SKIP_OPEN_TABLE}, {"ROUTINE_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type", SKIP_OPEN_TABLE}, - {"DTD_IDENTIFIER", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE}, + {"DATA_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}, + {"CHARACTER_MAXIMUM_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0, SKIP_OPEN_TABLE}, + {"CHARACTER_OCTET_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0, SKIP_OPEN_TABLE}, + {"NUMERIC_PRECISION", 21 , MYSQL_TYPE_LONG, 0, 1, 0, SKIP_OPEN_TABLE}, + {"NUMERIC_SCALE", 21 , MYSQL_TYPE_LONG, 0, 1, 0, SKIP_OPEN_TABLE}, + {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE}, + {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE}, + {"DTD_IDENTIFIER", 65535, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE}, {"ROUTINE_BODY", 8, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}, {"ROUTINE_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE}, {"EXTERNAL_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, SKIP_OPEN_TABLE}, @@ -6527,15 +6813,15 @@ ST_FIELD_INFO view_fields_info[]= {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY}, {"TABLE_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY}, {"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY}, - {"VIEW_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, - {"CHECK_OPTION", 8, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, + {"VIEW_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY}, + {"CHECK_OPTION", 8, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY}, {"IS_UPDATABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, - {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, - {"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, + {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY}, + {"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY}, {"CHARACTER_SET_CLIENT", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, 0, - OPEN_FULL_TABLE}, + OPEN_FRM_ONLY}, {"COLLATION_CONNECTION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, 0, - OPEN_FULL_TABLE}, + OPEN_FRM_ONLY}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} }; @@ -6650,38 +6936,38 @@ ST_FIELD_INFO open_tables_fields_info[]= ST_FIELD_INFO triggers_fields_info[]= { - {"TRIGGER_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, - {"TRIGGER_SCHEMA",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, + {"TRIGGER_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY}, + {"TRIGGER_SCHEMA",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY}, {"TRIGGER_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Trigger", - OPEN_FULL_TABLE}, - {"EVENT_MANIPULATION", 6, MYSQL_TYPE_STRING, 0, 0, "Event", OPEN_FULL_TABLE}, + OPEN_FRM_ONLY}, + {"EVENT_MANIPULATION", 6, MYSQL_TYPE_STRING, 0, 0, "Event", OPEN_FRM_ONLY}, {"EVENT_OBJECT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, - OPEN_FULL_TABLE}, + OPEN_FRM_ONLY}, {"EVENT_OBJECT_SCHEMA",NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, - OPEN_FULL_TABLE}, + OPEN_FRM_ONLY}, {"EVENT_OBJECT_TABLE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, "Table", - OPEN_FULL_TABLE}, - {"ACTION_ORDER", 4, MYSQL_TYPE_LONGLONG, 0, 0, 0, OPEN_FULL_TABLE}, - {"ACTION_CONDITION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE}, + OPEN_FRM_ONLY}, + {"ACTION_ORDER", 4, MYSQL_TYPE_LONGLONG, 0, 0, 0, OPEN_FRM_ONLY}, + {"ACTION_CONDITION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FRM_ONLY}, {"ACTION_STATEMENT", 65535, MYSQL_TYPE_STRING, 0, 0, "Statement", - OPEN_FULL_TABLE}, - {"ACTION_ORIENTATION", 9, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, - {"ACTION_TIMING", 6, MYSQL_TYPE_STRING, 0, 0, "Timing", OPEN_FULL_TABLE}, + OPEN_FRM_ONLY}, + {"ACTION_ORIENTATION", 9, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY}, + {"ACTION_TIMING", 6, MYSQL_TYPE_STRING, 0, 0, "Timing", OPEN_FRM_ONLY}, {"ACTION_REFERENCE_OLD_TABLE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, - OPEN_FULL_TABLE}, + OPEN_FRM_ONLY}, {"ACTION_REFERENCE_NEW_TABLE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, - OPEN_FULL_TABLE}, - {"ACTION_REFERENCE_OLD_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, - {"ACTION_REFERENCE_NEW_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, - {"CREATED", 0, MYSQL_TYPE_DATETIME, 0, 1, "Created", OPEN_FULL_TABLE}, - {"SQL_MODE", 32*256, MYSQL_TYPE_STRING, 0, 0, "sql_mode", OPEN_FULL_TABLE}, - {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer", OPEN_FULL_TABLE}, + OPEN_FRM_ONLY}, + {"ACTION_REFERENCE_OLD_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY}, + {"ACTION_REFERENCE_NEW_ROW", 3, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FRM_ONLY}, + {"CREATED", 0, MYSQL_TYPE_DATETIME, 0, 1, "Created", OPEN_FRM_ONLY}, + {"SQL_MODE", 32*256, MYSQL_TYPE_STRING, 0, 0, "sql_mode", OPEN_FRM_ONLY}, + {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer", OPEN_FRM_ONLY}, {"CHARACTER_SET_CLIENT", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, - "character_set_client", OPEN_FULL_TABLE}, + "character_set_client", OPEN_FRM_ONLY}, {"COLLATION_CONNECTION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, - "collation_connection", OPEN_FULL_TABLE}, + "collation_connection", OPEN_FRM_ONLY}, {"DATABASE_COLLATION", MY_CS_NAME_SIZE, MYSQL_TYPE_STRING, 0, 0, - "Database Collation", OPEN_FULL_TABLE}, + "Database Collation", OPEN_FRM_ONLY}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} }; @@ -6860,6 +7146,51 @@ ST_FIELD_INFO referential_constraints_fields_info[]= }; +ST_FIELD_INFO parameters_fields_info[]= +{ + {"SPECIFIC_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, + {"SPECIFIC_SCHEMA", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, + OPEN_FULL_TABLE}, + {"SPECIFIC_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, + {"ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 0, 0, OPEN_FULL_TABLE}, + {"PARAMETER_MODE", 5, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE}, + {"PARAMETER_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE}, + {"DATA_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, + {"CHARACTER_MAXIMUM_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0, OPEN_FULL_TABLE}, + {"CHARACTER_OCTET_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, 0, OPEN_FULL_TABLE}, + {"NUMERIC_PRECISION", 21 , MYSQL_TYPE_LONG, 0, 1, 0, OPEN_FULL_TABLE}, + {"NUMERIC_SCALE", 21 , MYSQL_TYPE_LONG, 0, 1, 0, OPEN_FULL_TABLE}, + {"CHARACTER_SET_NAME", 64, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE}, + {"COLLATION_NAME", 64, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE}, + {"DTD_IDENTIFIER", 65535, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, + {"ROUTINE_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE} +}; + + +ST_FIELD_INFO tablespaces_fields_info[]= +{ + {"TABLESPACE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, + SKIP_OPEN_TABLE}, + {"ENGINE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}, + {"TABLESPACE_TYPE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, MY_I_S_MAYBE_NULL, + 0, SKIP_OPEN_TABLE}, + {"LOGFILE_GROUP_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, MY_I_S_MAYBE_NULL, + 0, SKIP_OPEN_TABLE}, + {"EXTENT_SIZE", 21, MYSQL_TYPE_LONGLONG, 0, + MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED, 0, SKIP_OPEN_TABLE}, + {"AUTOEXTEND_SIZE", 21, MYSQL_TYPE_LONGLONG, 0, + MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED, 0, SKIP_OPEN_TABLE}, + {"MAXIMUM_SIZE", 21, MYSQL_TYPE_LONGLONG, 0, + MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED, 0, SKIP_OPEN_TABLE}, + {"NODEGROUP_ID", 21, MYSQL_TYPE_LONGLONG, 0, + MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED, 0, SKIP_OPEN_TABLE}, + {"TABLESPACE_COMMENT", 2048, MYSQL_TYPE_STRING, 0, MY_I_S_MAYBE_NULL, 0, + SKIP_OPEN_TABLE}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} +}; + + /* Description of ST_FIELD_INFO in table.h @@ -6890,7 +7221,7 @@ ST_SCHEMA_TABLE schema_tables[]= 0, make_old_format, 0, -1, -1, 0, 0}, #endif {"FILES", files_fields_info, create_schema_table, - fill_schema_files, 0, 0, -1, -1, 0, 0}, + hton_fill_schema_table, 0, 0, -1, -1, 0, 0}, {"GLOBAL_STATUS", variables_fields_info, create_schema_table, fill_status, make_old_format, 0, 0, -1, 0, 0}, {"GLOBAL_VARIABLES", variables_fields_info, create_schema_table, @@ -6900,6 +7231,8 @@ ST_SCHEMA_TABLE schema_tables[]= OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY}, {"OPEN_TABLES", open_tables_fields_info, create_schema_table, fill_open_tables, make_old_format, 0, -1, -1, 1, 0}, + {"PARAMETERS", parameters_fields_info, create_schema_table, + fill_schema_proc, 0, 0, -1, -1, 0, 0}, {"PARTITIONS", partitions_fields_info, create_schema_table, get_all_tables, 0, get_schema_partitions_record, 1, 2, 0, OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY}, @@ -6931,6 +7264,8 @@ ST_SCHEMA_TABLE schema_tables[]= {"TABLES", tables_fields_info, create_schema_table, get_all_tables, make_old_format, get_schema_tables_record, 1, 2, 0, OPTIMIZE_I_S_TABLE}, + {"TABLESPACES", tablespaces_fields_info, create_schema_table, + hton_fill_schema_table, 0, 0, -1, -1, 0, 0}, {"TABLE_CONSTRAINTS", table_constraints_fields_info, create_schema_table, get_all_tables, 0, get_schema_constraints_record, 3, 4, 0, OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY}, @@ -6940,7 +7275,7 @@ ST_SCHEMA_TABLE schema_tables[]= fill_schema_table_privileges, 0, 0, -1, -1, 0, 0}, {"TRIGGERS", triggers_fields_info, create_schema_table, get_all_tables, make_old_format, get_schema_triggers_record, 5, 6, 0, - OPTIMIZE_I_S_TABLE|OPEN_TABLE_ONLY}, + OPEN_TRIGGER_ONLY|OPTIMIZE_I_S_TABLE}, {"USER_PRIVILEGES", user_privileges_fields_info, create_schema_table, fill_schema_user_privileges, 0, 0, -1, -1, 0, 0}, {"VARIABLES", variables_fields_info, create_schema_table, fill_variables, @@ -7063,9 +7398,7 @@ static bool show_create_trigger_impl(THD *thd, &trg_connection_cl_name, &trg_db_cl_name); - sys_var_thd_sql_mode::symbolic_mode_representation(thd, - trg_sql_mode, - &trg_sql_mode_str); + sql_mode_string_representation(thd, trg_sql_mode, &trg_sql_mode_str); /* Resolve trigger client character set. */ @@ -7224,7 +7557,7 @@ static TABLE_LIST *get_trigger_table(THD *thd, const sp_name *trg_name) { /* Acquire LOCK_open (stop the server). */ - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); /* Load base table name from the TRN-file and create TABLE_LIST object. @@ -7234,7 +7567,7 @@ static TABLE_LIST *get_trigger_table(THD *thd, const sp_name *trg_name) /* Release LOCK_open (continue the server). */ - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); /* That's it. */ @@ -7315,6 +7648,56 @@ bool show_create_trigger(THD *thd, const sp_name *trg_name) */ } +class IS_internal_schema_access : public ACL_internal_schema_access +{ +public: + IS_internal_schema_access() + {} + + ~IS_internal_schema_access() + {} + + ACL_internal_access_result check(ulong want_access, + ulong *save_priv) const; + + const ACL_internal_table_access *lookup(const char *name) const; +}; + +ACL_internal_access_result +IS_internal_schema_access::check(ulong want_access, + ulong *save_priv) const +{ + want_access &= ~SELECT_ACL; + + /* + We don't allow any simple privileges but SELECT_ACL on + the information_schema database. + */ + if (unlikely(want_access & DB_ACLS)) + return ACL_INTERNAL_ACCESS_DENIED; + + /* Always grant SELECT for the information schema. */ + *save_priv|= SELECT_ACL; + + return want_access ? ACL_INTERNAL_ACCESS_CHECK_GRANT : + ACL_INTERNAL_ACCESS_GRANTED; +} + +const ACL_internal_table_access * +IS_internal_schema_access::lookup(const char *name) const +{ + /* There are no per table rules for the information schema. */ + return NULL; +} + +static IS_internal_schema_access is_internal_schema_access; + +void initialize_information_schema_acl() +{ + ACL_internal_schema_registry::register_schema(&INFORMATION_SCHEMA_NAME, + &is_internal_schema_access); +} + /* Convert a string in character set in column character set format to utf8 character set if possible, the utf8 character set string diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 593450cacd5..e4e51aba622 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -23,10 +23,7 @@ #include <my_sys.h> #include <m_string.h> #include <m_ctype.h> -#ifdef HAVE_FCONVERT -#include <floatingpoint.h> -#endif - +#include <mysql_com.h> /* The following extern declarations are ok as these are interface functions required by the string function @@ -106,82 +103,19 @@ bool String::set_int(longlong num, bool unsigned_flag, CHARSET_INFO *cs) bool String::set_real(double num,uint decimals, CHARSET_INFO *cs) { - char buff[331]; + char buff[FLOATING_POINT_BUFFER]; uint dummy_errors; + size_t len; str_charset=cs; if (decimals >= NOT_FIXED_DEC) { - uint32 len= my_sprintf(buff,(buff, "%.15g",num));// Enough for a DATETIME + len= my_gcvt(num, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL); return copy(buff, len, &my_charset_latin1, cs, &dummy_errors); } -#ifdef HAVE_FCONVERT - int decpt,sign; - char *pos,*to; - - VOID(fconvert(num,(int) decimals,&decpt,&sign,buff+1)); - if (!my_isdigit(&my_charset_latin1, buff[1])) - { // Nan or Inf - pos=buff+1; - if (sign) - { - buff[0]='-'; - pos=buff; - } - uint dummy_errors; - return copy(pos,(uint32) strlen(pos), &my_charset_latin1, cs, &dummy_errors); - } - if (alloc((uint32) ((uint32) decpt+3+decimals))) - return TRUE; - to=Ptr; - if (sign) - *to++='-'; - - pos=buff+1; - if (decpt < 0) - { /* value is < 0 */ - *to++='0'; - if (!decimals) - goto end; - *to++='.'; - if ((uint32) -decpt > decimals) - decpt= - (int) decimals; - decimals=(uint32) ((int) decimals+decpt); - while (decpt++ < 0) - *to++='0'; - } - else if (decpt == 0) - { - *to++= '0'; - if (!decimals) - goto end; - *to++='.'; - } - else - { - while (decpt-- > 0) - *to++= *pos++; - if (!decimals) - goto end; - *to++='.'; - } - while (decimals--) - *to++= *pos++; - -end: - *to=0; - str_length=(uint32) (to-Ptr); - return FALSE; -#else -#ifdef HAVE_SNPRINTF - buff[sizeof(buff)-1]=0; // Safety - snprintf(buff,sizeof(buff)-1, "%.*f",(int) decimals,num); -#else - sprintf(buff,"%.*f",(int) decimals,num); -#endif - return copy(buff,(uint32) strlen(buff), &my_charset_latin1, cs, + len= my_fcvt(num, decimals, buff, NULL); + return copy(buff, (uint32) len, &my_charset_latin1, cs, &dummy_errors); -#endif } @@ -499,22 +433,6 @@ bool String::append(const char *s,uint32 arg_length, CHARSET_INFO *cs) return FALSE; } - -#ifdef TO_BE_REMOVED -bool String::append(FILE* file, uint32 arg_length, myf my_flags) -{ - if (realloc(str_length+arg_length)) - return TRUE; - if (my_fread(file, (uchar*) Ptr + str_length, arg_length, my_flags)) - { - shrink(str_length); - return TRUE; - } - str_length+=arg_length; - return FALSE; -} -#endif - bool String::append(IO_CACHE* file, uint32 arg_length) { if (realloc(str_length+arg_length)) @@ -676,7 +594,8 @@ void String::qs_append(const char *str, uint32 len) void String::qs_append(double d) { char *buff = Ptr + str_length; - str_length+= my_sprintf(buff, (buff, "%.15g", d)); + str_length+= my_gcvt(d, MY_GCVT_ARG_DOUBLE, FLOATING_POINT_BUFFER - 1, buff, + NULL); } void String::qs_append(double *d) diff --git a/sql/sql_string.h b/sql/sql_string.h index 75dc1163eec..38f843e7e8f 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -22,10 +22,6 @@ #pragma interface /* gcc class implementation */ #endif -#ifndef NOT_FIXED_DEC -#define NOT_FIXED_DEC 31 -#endif - class String; int sortcmp(const String *a,const String *b, CHARSET_INFO *cs); String *copy_if_not_alloced(String *a,String *b,uint32 arg_length); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6006c818725..4f962de0a12 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,6 +22,7 @@ #include "sp_head.h" #include "sql_trigger.h" #include "sql_show.h" +#include "keycaches.h" #ifdef __WIN__ #include <io.h> @@ -498,9 +499,9 @@ uint build_table_filename(char *buff, size_t bufflen, const char *db, if (flags & FN_IS_TMP) // FN_FROM_IS_TMP | FN_TO_IS_TMP strnmov(tbbuff, table_name, sizeof(tbbuff)); else - VOID(tablename_to_filename(table_name, tbbuff, sizeof(tbbuff))); + (void) tablename_to_filename(table_name, tbbuff, sizeof(tbbuff)); - VOID(tablename_to_filename(db, dbbuff, sizeof(dbbuff))); + (void) tablename_to_filename(db, dbbuff, sizeof(dbbuff)); char *end = buff + bufflen; /* Don't add FN_ROOTDIR if mysql_data_home already includes it */ @@ -611,7 +612,7 @@ struct st_global_ddl_log st_global_ddl_log global_ddl_log; -pthread_mutex_t LOCK_gdl; +mysql_mutex_t LOCK_gdl; #define DDL_LOG_ENTRY_TYPE_POS 0 #define DDL_LOG_ACTION_TYPE_POS 1 @@ -641,8 +642,8 @@ static bool read_ddl_log_file_entry(uint entry_no) uint io_size= global_ddl_log.io_size; DBUG_ENTER("read_ddl_log_file_entry"); - if (my_pread(file_id, file_entry_buf, io_size, io_size * entry_no, - MYF(MY_WME)) != io_size) + if (mysql_file_pread(file_id, file_entry_buf, io_size, io_size * entry_no, + MYF(MY_WME)) != io_size) error= TRUE; DBUG_RETURN(error); } @@ -665,8 +666,8 @@ static bool write_ddl_log_file_entry(uint entry_no) char *file_entry_buf= (char*)global_ddl_log.file_entry_buf; DBUG_ENTER("write_ddl_log_file_entry"); - if (my_pwrite(file_id, (uchar*)file_entry_buf, - IO_SIZE, IO_SIZE * entry_no, MYF(MY_WME)) != IO_SIZE) + if (mysql_file_pwrite(file_id, (uchar*)file_entry_buf, + IO_SIZE, IO_SIZE * entry_no, MYF(MY_WME)) != IO_SIZE) error= TRUE; DBUG_RETURN(error); } @@ -700,7 +701,7 @@ static bool write_ddl_log_header() sql_print_error("Error writing ddl log header"); DBUG_RETURN(TRUE); } - VOID(sync_ddl_log()); + (void) sync_ddl_log(); DBUG_RETURN(error); } @@ -742,8 +743,9 @@ static uint read_ddl_log_header() DBUG_ENTER("read_ddl_log_header"); create_ddl_log_file_name(file_name); - if ((global_ddl_log.file_id= my_open(file_name, - O_RDWR | O_BINARY, MYF(0))) >= 0) + if ((global_ddl_log.file_id= mysql_file_open(key_file_global_ddl_log, + file_name, + O_RDWR | O_BINARY, MYF(0))) >= 0) { if (read_ddl_log_file_entry(0UL)) { @@ -768,7 +770,7 @@ static uint read_ddl_log_header() global_ddl_log.first_free= NULL; global_ddl_log.first_used= NULL; global_ddl_log.num_entries= 0; - VOID(pthread_mutex_init(&LOCK_gdl, MY_MUTEX_INIT_FAST)); + mysql_mutex_init(key_LOCK_gdl, &LOCK_gdl, MY_MUTEX_INIT_FAST); global_ddl_log.do_release= true; DBUG_RETURN(entry_no); } @@ -839,10 +841,10 @@ static bool init_ddl_log() global_ddl_log.io_size= IO_SIZE; global_ddl_log.name_len= FN_LEN; create_ddl_log_file_name(file_name); - if ((global_ddl_log.file_id= my_create(file_name, - CREATE_MODE, - O_RDWR | O_TRUNC | O_BINARY, - MYF(MY_WME))) < 0) + if ((global_ddl_log.file_id= mysql_file_create(key_file_global_ddl_log, + file_name, CREATE_MODE, + O_RDWR | O_TRUNC | O_BINARY, + MYF(MY_WME))) < 0) { /* Couldn't create ddl log file, this is serious error */ sql_print_error("Failed to open ddl log file"); @@ -851,7 +853,7 @@ static bool init_ddl_log() global_ddl_log.inited= TRUE; if (write_ddl_log_header()) { - VOID(my_close(global_ddl_log.file_id, MYF(MY_WME))); + (void) mysql_file_close(global_ddl_log.file_id, MYF(MY_WME)); global_ddl_log.inited= FALSE; DBUG_RETURN(TRUE); } @@ -928,14 +930,14 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry) if (frm_action) { strxmov(to_path, ddl_log_entry->name, reg_ext, NullS); - if ((error= my_delete(to_path, MYF(MY_WME)))) + if ((error= mysql_file_delete(key_file_frm, to_path, MYF(MY_WME)))) { if (my_errno != ENOENT) break; } #ifdef WITH_PARTITION_STORAGE_ENGINE strxmov(to_path, ddl_log_entry->name, par_ext, NullS); - VOID(my_delete(to_path, MYF(MY_WME))); + (void) mysql_file_delete(key_file_partition, to_path, MYF(MY_WME)); #endif } else @@ -948,7 +950,7 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry) } if ((deactivate_ddl_log_entry(ddl_log_entry->entry_pos))) break; - VOID(sync_ddl_log()); + (void) sync_ddl_log(); error= FALSE; if (ddl_log_entry->action_type == DDL_LOG_DELETE_ACTION) break; @@ -967,12 +969,12 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry) { strxmov(to_path, ddl_log_entry->name, reg_ext, NullS); strxmov(from_path, ddl_log_entry->from_name, reg_ext, NullS); - if (my_rename(from_path, to_path, MYF(MY_WME))) + if (mysql_file_rename(key_file_frm, from_path, to_path, MYF(MY_WME))) break; #ifdef WITH_PARTITION_STORAGE_ENGINE strxmov(to_path, ddl_log_entry->name, par_ext, NullS); strxmov(from_path, ddl_log_entry->from_name, par_ext, NullS); - VOID(my_rename(from_path, to_path, MYF(MY_WME))); + (void) mysql_file_rename(key_file_partition, from_path, to_path, MYF(MY_WME)); #endif } else @@ -983,7 +985,7 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry) } if ((deactivate_ddl_log_entry(ddl_log_entry->entry_pos))) break; - VOID(sync_ddl_log()); + (void) sync_ddl_log(); error= FALSE; break; } @@ -1121,7 +1123,7 @@ bool write_ddl_log_entry(DDL_LOG_ENTRY *ddl_log_entry, } if (write_header && !error) { - VOID(sync_ddl_log()); + (void) sync_ddl_log(); if (write_ddl_log_header()) error= TRUE; } @@ -1178,7 +1180,7 @@ bool write_execute_ddl_log_entry(uint first_entry, any log entries before, we are only here to write the execute entry to indicate it is done. */ - VOID(sync_ddl_log()); + (void) sync_ddl_log(); file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (char)DDL_LOG_EXECUTE_CODE; } else @@ -1202,7 +1204,7 @@ bool write_execute_ddl_log_entry(uint first_entry, release_ddl_log_memory_entry(*active_entry); DBUG_RETURN(TRUE); } - VOID(sync_ddl_log()); + (void) sync_ddl_log(); if (write_header) { if (write_ddl_log_header()) @@ -1298,7 +1300,7 @@ bool sync_ddl_log() { DBUG_RETURN(TRUE); } - if (my_sync(global_ddl_log.file_id, MYF(0))) + if (mysql_file_sync(global_ddl_log.file_id, MYF(0))) { /* Write to error log */ sql_print_error("Failed to sync ddl log"); @@ -1354,7 +1356,7 @@ bool execute_ddl_log_entry(THD *thd, uint first_entry) uint read_entry= first_entry; DBUG_ENTER("execute_ddl_log_entry"); - pthread_mutex_lock(&LOCK_gdl); + mysql_mutex_lock(&LOCK_gdl); do { if (read_ddl_log_entry(read_entry, &ddl_log_entry)) @@ -1376,7 +1378,7 @@ bool execute_ddl_log_entry(THD *thd, uint first_entry) } read_entry= ddl_log_entry.next_entry; } while (read_entry); - pthread_mutex_unlock(&LOCK_gdl); + mysql_mutex_unlock(&LOCK_gdl); DBUG_RETURN(FALSE); } @@ -1394,7 +1396,7 @@ static void close_ddl_log() DBUG_ENTER("close_ddl_log"); if (global_ddl_log.file_id >= 0) { - VOID(my_close(global_ddl_log.file_id, MYF(MY_WME))); + (void) mysql_file_close(global_ddl_log.file_id, MYF(MY_WME)); global_ddl_log.file_id= (File) -1; } DBUG_VOID_RETURN; @@ -1454,7 +1456,7 @@ void execute_ddl_log_recovery() } close_ddl_log(); create_ddl_log_file_name(file_name); - VOID(my_delete(file_name, MYF(0))); + (void) mysql_file_delete(key_file_global_ddl_log, file_name, MYF(0)); global_ddl_log.recovery_phase= FALSE; delete thd; /* Remember that we don't have a THD */ @@ -1480,7 +1482,7 @@ void release_ddl_log() if (!global_ddl_log.do_release) DBUG_VOID_RETURN; - pthread_mutex_lock(&LOCK_gdl); + mysql_mutex_lock(&LOCK_gdl); while (used_list) { DDL_LOG_MEMORY_ENTRY *tmp= used_list->next_log_entry; @@ -1495,8 +1497,8 @@ void release_ddl_log() } close_ddl_log(); global_ddl_log.inited= 0; - pthread_mutex_unlock(&LOCK_gdl); - VOID(pthread_mutex_destroy(&LOCK_gdl)); + mysql_mutex_unlock(&LOCK_gdl); + mysql_mutex_destroy(&LOCK_gdl); global_ddl_log.do_release= false; DBUG_VOID_RETURN; } @@ -1628,7 +1630,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) CHF_CREATE_FLAG, lpt->create_info)) { - my_delete(shadow_frm_name, MYF(0)); + mysql_file_delete(key_file_frm, shadow_frm_name, MYF(0)); error= 1; goto end; } @@ -1652,7 +1654,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) error= 1; goto end; } - error= my_delete(shadow_frm_name, MYF(MY_WME)); + error= mysql_file_delete(key_file_frm, shadow_frm_name, MYF(MY_WME)); } if (flags & WFRM_INSTALL_SHADOW) { @@ -1675,8 +1677,8 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) completing this we write a new phase to the log entry that will deactivate it. */ - VOID(pthread_mutex_lock(&LOCK_open)); - if (my_delete(frm_name, MYF(MY_WME)) || + mysql_mutex_lock(&LOCK_open); + if (mysql_file_delete(key_file_frm, frm_name, MYF(MY_WME)) || #ifdef WITH_PARTITION_STORAGE_ENGINE lpt->table->file->ha_create_handler_files(path, shadow_path, CHF_DELETE_FLAG, NULL) || @@ -1684,11 +1686,13 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) (sync_ddl_log(), FALSE) || #endif #ifdef WITH_PARTITION_STORAGE_ENGINE - my_rename(shadow_frm_name, frm_name, MYF(MY_WME)) || + mysql_file_rename(key_file_frm, + shadow_frm_name, frm_name, MYF(MY_WME)) || lpt->table->file->ha_create_handler_files(path, shadow_path, CHF_RENAME_FLAG, NULL)) #else - my_rename(shadow_frm_name, frm_name, MYF(MY_WME))) + mysql_file_rename(key_file_frm, + shadow_frm_name, frm_name, MYF(MY_WME))) #endif { error= 1; @@ -1728,11 +1732,11 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) #endif err: - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); #ifdef WITH_PARTITION_STORAGE_ENGINE deactivate_ddl_log_entry(part_info->frm_log_entry->entry_pos); part_info->frm_log_entry= NULL; - VOID(sync_ddl_log()); + (void) sync_ddl_log(); #endif } @@ -1758,7 +1762,7 @@ end: */ int write_bin_log(THD *thd, bool clear_error, - char const *query, ulong query_length) + char const *query, ulong query_length, bool is_trans) { int error= 0; if (mysql_bin_log.is_open()) @@ -1769,7 +1773,8 @@ int write_bin_log(THD *thd, bool clear_error, else errcode= query_error_code(thd, TRUE); error= thd->binlog_query(THD::STMT_QUERY_TYPE, - query, query_length, FALSE, FALSE, errcode); + query, query_length, is_trans, FALSE, FALSE, + errcode); } return error; } @@ -1790,7 +1795,8 @@ int write_bin_log(THD *thd, bool clear_error, If a table is in use, we will wait for all users to free the table before dropping it - Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set. + Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set, but + not if under LOCK TABLES. RETURN FALSE OK. In this case ok packet is sent to user @@ -1801,7 +1807,7 @@ int write_bin_log(THD *thd, bool clear_error, bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, my_bool drop_temporary) { - bool error= FALSE, need_start_waiters= FALSE; + bool error= FALSE, need_start_waiting= FALSE; Drop_table_error_handler err_handler(thd->get_internal_handler()); DBUG_ENTER("mysql_rm_table"); @@ -1809,13 +1815,9 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, if (!drop_temporary) { - if ((error= wait_if_global_read_lock(thd, 0, 1))) - { - my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), tables->table_name); + if (!thd->locked_tables && + !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) DBUG_RETURN(TRUE); - } - else - need_start_waiters= TRUE; } /* @@ -1828,7 +1830,7 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, thd->pop_internal_handler(); - if (need_start_waiters) + if (need_start_waiting) start_waiting_global_read_lock(thd); if (error) @@ -1885,7 +1887,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, LINT_INIT(alias); LINT_INIT(path_length); - if (thd->current_stmt_binlog_row_based && !dont_log_query) + if (thd->is_current_stmt_binlog_format_row() && !dont_log_query) { built_query.set_charset(system_charset_info); if (if_exists) @@ -1896,7 +1898,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, mysql_ha_rm_tables(thd, tables, FALSE); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); /* If we have the table in the definition cache, we don't have to check the @@ -1912,19 +1914,19 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, table->db_type= share->db_type(); /* Disable drop of enabled log tables */ - if (share && (share->table_category == TABLE_CATEGORY_PERFORMANCE) && + if (share && (share->table_category == TABLE_CATEGORY_LOG) && check_if_log_table(table->db_length, table->db, table->table_name_length, table->table_name, 1)) { my_error(ER_BAD_LOG_STATEMENT, MYF(0), "DROP"); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(1); } } if (!drop_temporary && lock_table_names_exclusively(thd, tables)) { - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(1); } @@ -1945,7 +1947,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, // removed temporary table tmp_table_deleted= 1; if (thd->variables.binlog_format == BINLOG_FORMAT_MIXED && - thd->current_stmt_binlog_row_based) + thd->is_current_stmt_binlog_format_row()) { if (built_tmp_query.is_empty()) { @@ -1979,7 +1981,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, being built. The string always end in a comma and the comma will be chopped off before being written to the binary log. */ - if (!drop_temporary && thd->current_stmt_binlog_row_based && !dont_log_query) + if (!drop_temporary && thd->is_current_stmt_binlog_format_row() && !dont_log_query) { non_temp_tables_count++; /* @@ -2067,7 +2069,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, int new_error; /* Delete the table definition file */ strmov(end,reg_ext); - if (!(new_error=my_delete(path,MYF(MY_WME)))) + if (!(new_error= mysql_file_delete(key_file_frm, path, MYF(MY_WME)))) { some_tables_deleted=1; new_error= Table_triggers_list::drop_all_triggers(thd, db, @@ -2095,7 +2097,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, It's safe to unlock LOCK_open: we have an exclusive lock on the table name. */ - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); thd->thread_specific_used|= tmp_table_deleted; error= 0; if (wrong_tables.length()) @@ -2113,7 +2115,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, query_cache_invalidate3(thd, tables, 0); if (!dont_log_query) { - if (!thd->current_stmt_binlog_row_based || + if (!thd->is_current_stmt_binlog_format_row() || (non_temp_tables_count > 0 && !tmp_table_deleted)) { /* @@ -2125,7 +2127,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, */ error |= write_bin_log(thd, !error, thd->query(), thd->query_length()); } - else if (thd->current_stmt_binlog_row_based && + else if (thd->is_current_stmt_binlog_format_row() && tmp_table_deleted) { if (non_temp_tables_count > 0) @@ -2164,7 +2166,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, */ built_tmp_query.chop(); // Chop of the last comma built_tmp_query.append(" /* generated by server */"); - error|= write_bin_log(thd, !error, built_tmp_query.ptr(), built_tmp_query.length()); + error|= write_bin_log(thd, !error, built_tmp_query.ptr(), built_tmp_query.length(), + thd->in_multi_stmt_transaction()); } } @@ -2178,10 +2181,10 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, */ } } - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); err_with_placeholders: unlock_table_names(thd, tables, (TABLE_LIST*) 0); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(error); } @@ -2210,7 +2213,7 @@ bool quick_rm_table(handlerton *base,const char *db, uint path_length= build_table_filename(path, sizeof(path) - 1, db, table_name, reg_ext, flags); - if (my_delete(path,MYF(0))) + if (mysql_file_delete(key_file_frm, path, MYF(0))) error= 1; /* purecov: inspected */ path[path_length - reg_ext_length]= '\0'; // Remove reg_ext if (!(flags & FRM_ONLY)) @@ -2239,10 +2242,10 @@ static int sort_keys(KEY *a, KEY *b) { if (!(b_flags & HA_NOSAME)) return -1; - if ((a_flags ^ b_flags) & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) + if ((a_flags ^ b_flags) & HA_NULL_PART_KEY) { /* Sort NOT NULL keys before other keys */ - return (a_flags & (HA_NULL_PART_KEY | HA_END_SPACE_KEY)) ? 1 : -1; + return (a_flags & HA_NULL_PART_KEY) ? 1 : -1; } if (a->name == primary_key_name) return -1; @@ -3617,8 +3620,8 @@ static inline int write_create_table_bin_log(THD *thd, Otherwise, the statement shall be binlogged. */ if (!internal_tmp_table && - (!thd->current_stmt_binlog_row_based || - (thd->current_stmt_binlog_row_based && + (!thd->is_current_stmt_binlog_format_row() || + (thd->is_current_stmt_binlog_format_row() && !(create_info->options & HA_LEX_CREATE_TMP_TABLE)))) return write_bin_log(thd, TRUE, thd->query(), thd->query_length()); return 0; @@ -3897,7 +3900,7 @@ bool mysql_create_table_no_lock(THD *thd, goto err; } - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE)) { if (!access(path,F_OK)) @@ -3961,15 +3964,43 @@ bool mysql_create_table_no_lock(THD *thd, create_info->table_existed= 0; // Mark that table is created #ifdef HAVE_READLINK - if (test_if_data_home_dir(create_info->data_file_name)) - { - my_error(ER_WRONG_ARGUMENTS, MYF(0), "DATA DIRECTORY"); - goto unlock_and_end; - } - if (test_if_data_home_dir(create_info->index_file_name)) { - my_error(ER_WRONG_ARGUMENTS, MYF(0), "INDEX DIRECTORY"); - goto unlock_and_end; + size_t dirlen; + char dirpath[FN_REFLEN]; + + /* + data_file_name and index_file_name include the table name without + extension. Mostly this does not refer to an existing file. When + comparing data_file_name or index_file_name against the data + directory, we try to resolve all symbolic links. On some systems, + we use realpath(3) for the resolution. This returns ENOENT if the + resolved path does not refer to an existing file. my_realpath() + does then copy the requested path verbatim, without symlink + resolution. Thereafter the comparison can fail even if the + requested path is within the data directory. E.g. if symlinks to + another file system are used. To make realpath(3) return the + resolved path, we strip the table name and compare the directory + path only. If the directory doesn't exist either, table creation + will fail anyway. + */ + if (create_info->data_file_name) + { + dirname_part(dirpath, create_info->data_file_name, &dirlen); + if (test_if_data_home_dir(dirpath)) + { + my_error(ER_WRONG_ARGUMENTS, MYF(0), "DATA DIRECTORY"); + goto unlock_and_end; + } + } + if (create_info->index_file_name) + { + dirname_part(dirpath, create_info->index_file_name, &dirlen); + if (test_if_data_home_dir(dirpath)) + { + my_error(ER_WRONG_ARGUMENTS, MYF(0), "INDEX DIRECTORY"); + goto unlock_and_end; + } + } } #ifdef WITH_PARTITION_STORAGE_ENGINE @@ -4013,7 +4044,7 @@ bool mysql_create_table_no_lock(THD *thd, error= write_create_table_bin_log(thd, create_info, internal_tmp_table); unlock_and_end: - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); err: thd_proc_info(thd, "After create"); @@ -4046,21 +4077,21 @@ bool mysql_create_table(THD *thd, const char *db, const char *table_name, DBUG_ENTER("mysql_create_table"); /* Wait for any database locks */ - pthread_mutex_lock(&LOCK_lock_db); + mysql_mutex_lock(&LOCK_lock_db); while (!thd->killed && my_hash_search(&lock_db_cache,(uchar*) db, strlen(db))) { wait_for_condition(thd, &LOCK_lock_db, &COND_refresh); - pthread_mutex_lock(&LOCK_lock_db); + mysql_mutex_lock(&LOCK_lock_db); } if (thd->killed) { - pthread_mutex_unlock(&LOCK_lock_db); + mysql_mutex_unlock(&LOCK_lock_db); DBUG_RETURN(TRUE); } creating_table++; - pthread_mutex_unlock(&LOCK_lock_db); + mysql_mutex_unlock(&LOCK_lock_db); if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE)) { @@ -4097,14 +4128,14 @@ bool mysql_create_table(THD *thd, const char *db, const char *table_name, unlock: if (name_lock) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); unlink_open_table(thd, name_lock, FALSE); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } - pthread_mutex_lock(&LOCK_lock_db); + mysql_mutex_lock(&LOCK_lock_db); if (!--creating_table && creating_database) - pthread_cond_signal(&COND_refresh); - pthread_mutex_unlock(&LOCK_lock_db); + mysql_cond_signal(&COND_refresh); + mysql_mutex_unlock(&LOCK_lock_db); DBUG_RETURN(result); } @@ -4265,9 +4296,9 @@ void wait_while_table_is_used(THD *thd, TABLE *table, table->s->table_name.str, (ulong) table->s, table->db_stat, table->s->version)); - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); - VOID(table->file->extra(function)); + (void) table->file->extra(function); /* Mark all tables that are in use as 'old' */ mysql_lock_abort(thd, table, TRUE); /* end threads waiting on lock */ @@ -4330,73 +4361,6 @@ static int send_check_errmsg(THD *thd, TABLE_LIST* table, return 1; } - -static int prepare_for_restore(THD* thd, TABLE_LIST* table, - HA_CHECK_OPT *check_opt) -{ - DBUG_ENTER("prepare_for_restore"); - - if (table->table) // do not overwrite existing tables on restore - { - DBUG_RETURN(send_check_errmsg(thd, table, "restore", - "table exists, will not overwrite on restore" - )); - } - else - { - char* backup_dir= thd->lex->backup_dir; - char src_path[FN_REFLEN], dst_path[FN_REFLEN + 1], uname[FN_REFLEN]; - char* table_name= table->table_name; - char* db= table->db; - - VOID(tablename_to_filename(table->table_name, uname, sizeof(uname) - 1)); - - if (fn_format_relative_to_data_home(src_path, uname, backup_dir, reg_ext)) - DBUG_RETURN(-1); // protect buffer overflow - - build_table_filename(dst_path, sizeof(dst_path) - 1, - db, table_name, reg_ext, 0); - - if (lock_and_wait_for_table_name(thd,table)) - DBUG_RETURN(-1); - - if (my_copy(src_path, dst_path, MYF(MY_WME))) - { - pthread_mutex_lock(&LOCK_open); - unlock_table_name(thd, table); - pthread_mutex_unlock(&LOCK_open); - DBUG_RETURN(send_check_errmsg(thd, table, "restore", - "Failed copying .frm file")); - } - if (mysql_truncate(thd, table, 1)) - { - pthread_mutex_lock(&LOCK_open); - unlock_table_name(thd, table); - pthread_mutex_unlock(&LOCK_open); - DBUG_RETURN(send_check_errmsg(thd, table, "restore", - "Failed generating table from .frm file")); - } - } - - /* - Now we should be able to open the partially restored table - to finish the restore in the handler later on - */ - pthread_mutex_lock(&LOCK_open); - if (reopen_name_locked_table(thd, table, TRUE)) - { - unlock_table_name(thd, table); - pthread_mutex_unlock(&LOCK_open); - DBUG_RETURN(send_check_errmsg(thd, table, "restore", - "Failed to open partially restored table")); - } - /* A MERGE table must not come here. */ - DBUG_ASSERT(!table->table || !table->table->child_l); - pthread_mutex_unlock(&LOCK_open); - DBUG_RETURN(0); -} - - static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, HA_CHECK_OPT *check_opt) { @@ -4417,22 +4381,22 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, uint key_length; key_length= create_table_def_key(thd, key, table_list, 0); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (!(share= (get_table_share(thd, table_list, key, key_length, 0, &error)))) { - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(0); // Can't open frm file } if (open_table_from_share(thd, share, "", 0, 0, 0, &tmp_table, FALSE)) { release_table_share(share, RELEASE_NORMAL); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(0); // Out of memory } table= &tmp_table; - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } /* A MERGE table must not come here. */ @@ -4477,7 +4441,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, // Name of data file strxmov(from, table->s->normalized_path.str, ext[1], NullS); - if (!my_stat(from, &stat_info, MYF(0))) + if (!mysql_file_stat(key_file_misc, from, &stat_info, MYF(0))) goto end; // Can't use USE_FRM flag my_snprintf(tmp, sizeof(tmp), "%s-%lx_%lx", @@ -4486,38 +4450,38 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, /* If we could open the table, close it */ if (table_list->table) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); close_cached_table(thd, table); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } if (lock_and_wait_for_table_name(thd,table_list)) { error= -1; goto end; } - if (my_rename(from, tmp, MYF(MY_WME))) + if (mysql_file_rename(key_file_misc, from, tmp, MYF(MY_WME))) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); unlock_table_name(thd, table_list); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); error= send_check_errmsg(thd, table_list, "repair", "Failed renaming data file"); goto end; } if (mysql_truncate(thd, table_list, 1)) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); unlock_table_name(thd, table_list); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); error= send_check_errmsg(thd, table_list, "repair", "Failed generating table from .frm file"); goto end; } - if (my_rename(tmp, from, MYF(MY_WME))) + if (mysql_file_rename(key_file_misc, tmp, from, MYF(MY_WME))) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); unlock_table_name(thd, table_list); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); error= send_check_errmsg(thd, table_list, "repair", "Failed restoring .MYD file"); goto end; @@ -4527,23 +4491,23 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, Now we should be able to open the partially repaired table to finish the repair in the handler later on. */ - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); if (reopen_name_locked_table(thd, table_list, TRUE)) { unlock_table_name(thd, table_list); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); error= send_check_errmsg(thd, table_list, "repair", "Failed to open partially repaired table"); goto end; } - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); end: if (table == &tmp_table) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); closefrm(table, 1); // Free allocated memory - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } DBUG_RETURN(error); } @@ -4770,7 +4734,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, if (lock_type == TL_WRITE && table->table->s->version) { DBUG_PRINT("admin", ("removing table from cache")); - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open, "Waiting to get writelock"); mysql_lock_abort(thd,table->table, TRUE); @@ -5033,10 +4997,10 @@ send_result_message: table->table->file->info(HA_STATUS_CONST); else { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); remove_table_from_cache(thd, table->table->s->db.str, table->table->s->table_name.str, RTFC_NO_FLAG); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } /* May be something modified consequently we have to invalidate cache */ query_cache_invalidate3(thd, table->table, 0); @@ -5063,29 +5027,6 @@ err: } -bool mysql_backup_table(THD* thd, TABLE_LIST* table_list) -{ - DBUG_ENTER("mysql_backup_table"); - WARN_DEPRECATED(thd, "6.0", "BACKUP TABLE", - "MySQL Administrator (mysqldump, mysql)"); - DBUG_RETURN(mysql_admin_table(thd, table_list, 0, - "backup", TL_READ, 0, 0, 0, 0, - &handler::ha_backup, 0)); -} - - -bool mysql_restore_table(THD* thd, TABLE_LIST* table_list) -{ - DBUG_ENTER("mysql_restore_table"); - WARN_DEPRECATED(thd, "6.0", "RESTORE TABLE", - "MySQL Administrator (mysqldump, mysql)"); - DBUG_RETURN(mysql_admin_table(thd, table_list, 0, - "restore", TL_WRITE, 1, 1, 0, - &prepare_for_restore, - &handler::ha_restore, 0)); -} - - bool mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt) { DBUG_ENTER("mysql_repair_table"); @@ -5128,14 +5069,14 @@ bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables, DBUG_ENTER("mysql_assign_to_keycache"); check_opt.init(); - pthread_mutex_lock(&LOCK_global_system_variables); + mysql_mutex_lock(&LOCK_global_system_variables); if (!(key_cache= get_key_cache(key_cache_name))) { - pthread_mutex_unlock(&LOCK_global_system_variables); + mysql_mutex_unlock(&LOCK_global_system_variables); my_error(ER_UNKNOWN_KEY_CACHE, MYF(0), key_cache_name->str); DBUG_RETURN(TRUE); } - pthread_mutex_unlock(&LOCK_global_system_variables); + mysql_mutex_unlock(&LOCK_global_system_variables); check_opt.key_cache= key_cache; DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt, "assign_to_keycache", TL_READ_NO_INSERT, 0, 0, @@ -5144,45 +5085,6 @@ bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables, /* - Reassign all tables assigned to a key cache to another key cache - - SYNOPSIS - reassign_keycache_tables() - thd Thread object - src_cache Reference to the key cache to clean up - dest_cache New key cache - - NOTES - This is called when one sets a key cache size to zero, in which - case we have to move the tables associated to this key cache to - the "default" one. - - One has to ensure that one never calls this function while - some other thread is changing the key cache. This is assured by - the caller setting src_cache->in_init before calling this function. - - We don't delete the old key cache as there may still be pointers pointing - to it for a while after this function returns. - - RETURN VALUES - 0 ok -*/ - -int reassign_keycache_tables(THD *thd, KEY_CACHE *src_cache, - KEY_CACHE *dst_cache) -{ - DBUG_ENTER("reassign_keycache_tables"); - - DBUG_ASSERT(src_cache != dst_cache); - DBUG_ASSERT(src_cache->in_init); - src_cache->param_buff_size= 0; // Free key cache - ha_resize_key_cache(src_cache); - ha_change_key_cache(src_cache, dst_cache); - DBUG_RETURN(0); -} - - -/* Preload specified indexes for a table into key cache SYNOPSIS @@ -5362,12 +5264,12 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, Also some engines (e.g. NDB cluster) require that LOCK_open should be held during the call to ha_create_table(). See bug #28614 for more info. */ - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); if (src_table->schema_table) { if (mysql_create_like_schema_frm(thd, src_table, dst_path, create_info)) { - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); goto err; } } @@ -5377,7 +5279,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, my_error(ER_BAD_DB_ERROR,MYF(0),db); else my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno); - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); goto err; } @@ -5406,7 +5308,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, if (thd->variables.keep_files_on_create) create_info->options|= HA_CREATE_KEEP_FILES; err= ha_create_table(thd, dst_path, db, table_name, create_info, 1); - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); if (create_info->options & HA_LEX_CREATE_TMP_TABLE) { @@ -5448,7 +5350,7 @@ binlog: /* We have to write the query before we unlock the tables. */ - if (thd->current_stmt_binlog_row_based) + if (thd->is_current_stmt_binlog_format_row()) { /* Since temporary tables are not replicated under row-based @@ -5480,13 +5382,13 @@ binlog: of this function. */ table->table= name_lock; - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); if (reopen_name_locked_table(thd, table, FALSE)) { - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); goto err; } - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); /* The condition avoids a crash as described in BUG#48506. Other @@ -5520,9 +5422,9 @@ binlog: err: if (name_lock) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); unlink_open_table(thd, name_lock, FALSE); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } DBUG_RETURN(res); } @@ -6009,6 +5911,35 @@ bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled, /** + maximum possible length for certain blob types. + + @param[in] type Blob type (e.g. MYSQL_TYPE_TINY_BLOB) + + @return + length +*/ + +static uint +blob_length_by_type(enum_field_types type) +{ + switch (type) + { + case MYSQL_TYPE_TINY_BLOB: + return 255; + case MYSQL_TYPE_BLOB: + return 65535; + case MYSQL_TYPE_MEDIUM_BLOB: + return 16777215; + case MYSQL_TYPE_LONG_BLOB: + return 4294967295U; + default: + DBUG_ASSERT(0); // we should never go here + return 0; + } +} + + +/** Prepare column and key definitions for CREATE TABLE in ALTER TABLE. This function transforms parse output of ALTER TABLE - lists of @@ -6303,6 +6234,14 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, BLOBs may have cfield->length == 0, which is why we test it before checking whether cfield->length < key_part_length (in chars). + + In case of TEXTs we check the data type maximum length *in bytes* + to key part length measured *in characters* (i.e. key_part_length + devided to mbmaxlen). This is because it's OK to have: + CREATE TABLE t1 (a tinytext, key(a(254)) character set utf8); + In case of this example: + - data type maximum length is 255. + - key_part_length is 1016 (=254*4, where 4 is mbmaxlen) */ if (!Field::type_can_have_key_part(cfield->field->type()) || !Field::type_can_have_key_part(cfield->sql_type) || @@ -6310,8 +6249,11 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, (key_info->flags & HA_SPATIAL) || (cfield->field->field_length == key_part_length && !f_is_blob(key_part->key_type)) || - (cfield->length && (cfield->length < key_part_length / - key_part->field->charset()->mbmaxlen))) + (cfield->length && (((cfield->sql_type >= MYSQL_TYPE_TINY_BLOB && + cfield->sql_type <= MYSQL_TYPE_BLOB) ? + blob_length_by_type(cfield->sql_type) : + cfield->length) < + key_part_length / key_part->field->charset()->mbmaxlen))) key_part_length= 0; // Use whole field } key_part_length /= key_part->field->charset()->mbmaxlen; @@ -6599,7 +6541,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, if (wait_if_global_read_lock(thd,0,1)) DBUG_RETURN(TRUE); - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); if (lock_table_names(thd, table_list)) { error= 1; @@ -6612,7 +6554,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, { thd->clear_error(); Query_log_event qinfo(thd, thd->query(), thd->query_length(), - 0, FALSE, 0); + FALSE, TRUE, FALSE, 0); if ((error= mysql_bin_log.write(&qinfo))) goto view_err_unlock; } @@ -6623,7 +6565,7 @@ view_err_unlock: unlock_table_names(thd, table_list, (TABLE_LIST*) 0); view_err: - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); start_waiting_global_read_lock(thd); DBUG_RETURN(error); } @@ -6784,17 +6726,17 @@ view_err: while the fact that the table is still open gives us protection from concurrent DDL statements. */ - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); DBUG_EXECUTE_IF("sleep_alter_enable_indexes", my_sleep(6000000);); error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); /* COND_refresh will be signaled in close_thread_tables() */ break; case DISABLE: - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); /* COND_refresh will be signaled in close_thread_tables() */ break; @@ -6811,7 +6753,7 @@ view_err: table->alias); } - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); /* Unlike to the above case close_cached_table() below will remove ALL instances of TABLE from table cache (it will also remove table lock @@ -6850,8 +6792,8 @@ view_err: else if (Table_triggers_list::change_table_name(thd, db, table_name, new_db, new_alias)) { - VOID(mysql_rename_table(old_db_type, new_db, new_alias, db, - table_name, 0)); + (void) mysql_rename_table(old_db_type, new_db, new_alias, db, + table_name, 0); error= -1; } } @@ -6878,7 +6820,7 @@ view_err: } if (name_lock) unlink_open_table(thd, name_lock, FALSE); - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); table_list->table= NULL; // For query cache query_cache_invalidate3(thd, table_list, 0); DBUG_RETURN(error); @@ -7239,9 +7181,9 @@ view_err: } else { - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); thd_proc_info(thd, "manage keys"); alter_table_manage_keys(table, table->file->indexes_are_disabled(), alter_info->keys_onoff); @@ -7356,8 +7298,8 @@ view_err: /* Should pass the 'new_name' as we store table name in the cache */ if (rename_temporary_table(thd, new_table, new_db, new_name)) goto err1; - /* We don't replicate alter table statement on temporary tables */ - if (!thd->current_stmt_binlog_row_based && + + if (!thd->is_current_stmt_binlog_format_row() && write_bin_log(thd, TRUE, thd->query(), thd->query_length())) DBUG_RETURN(TRUE); goto end_temporary; @@ -7372,11 +7314,11 @@ view_err: intern_close_table(new_table); my_free(new_table,MYF(0)); } - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); if (error) { - VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP)); - VOID(pthread_mutex_unlock(&LOCK_open)); + (void) quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP); + mysql_mutex_unlock(&LOCK_open); goto err; } @@ -7431,7 +7373,7 @@ view_err: FN_TO_IS_TMP)) { error=1; - VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP)); + (void) quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP); } else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db, new_alias, FN_FROM_IS_TMP) || @@ -7444,10 +7386,10 @@ view_err: { /* Try to get everything back. */ error=1; - VOID(quick_rm_table(new_db_type,new_db,new_alias, 0)); - VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP)); - VOID(mysql_rename_table(old_db_type, db, old_name, db, alias, - FN_FROM_IS_TMP)); + (void) quick_rm_table(new_db_type,new_db,new_alias, 0); + (void) quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP); + (void) mysql_rename_table(old_db_type, db, old_name, db, alias, + FN_FROM_IS_TMP); } if (error) @@ -7499,7 +7441,7 @@ view_err: } } - VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP)); + (void) quick_rm_table(old_db_type, db, old_name, FN_IS_TMP); if (thd->locked_tables && new_name == table_name && new_db == db) { @@ -7509,7 +7451,7 @@ view_err: if (error) goto err_with_placeholders; } - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); thd_proc_info(thd, "end"); @@ -7520,7 +7462,7 @@ view_err: db, table_name); DBUG_ASSERT(!(mysql_bin_log.is_open() && - thd->current_stmt_binlog_row_based && + thd->is_current_stmt_binlog_format_row() && (create_info->options & HA_LEX_CREATE_TMP_TABLE))); if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) DBUG_RETURN(TRUE); @@ -7557,10 +7499,10 @@ view_err: from the list of open tables and table cache. If we are not under LOCK TABLES we can rely on close_thread_tables() doing this job. */ - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); unlink_open_table(thd, table, FALSE); unlink_open_table(thd, name_lock, FALSE); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } end_temporary: @@ -7578,10 +7520,8 @@ err1: close_temporary_table(thd, new_table, 1, 1); } else - VOID(quick_rm_table(new_db_type, new_db, tmp_name, - create_info->frm_only - ? FN_IS_TMP | FRM_ONLY - : FN_IS_TMP)); + (void) quick_rm_table(new_db_type, new_db, tmp_name, + create_info->frm_only ? FN_IS_TMP | FRM_ONLY : FN_IS_TMP); err: /* @@ -7619,9 +7559,9 @@ err: } if (name_lock) { - pthread_mutex_lock(&LOCK_open); + mysql_mutex_lock(&LOCK_open); unlink_open_table(thd, name_lock, FALSE); - pthread_mutex_unlock(&LOCK_open); + mysql_mutex_unlock(&LOCK_open); } DBUG_RETURN(TRUE); @@ -7634,7 +7574,7 @@ err_with_placeholders: unlink_open_table(thd, table, FALSE); if (name_lock) unlink_open_table(thd, name_lock, FALSE); - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(TRUE); } /* mysql_alter_table */ diff --git a/sql/sql_test.cc b/sql/sql_test.cc index 845a6792801..fe56d6acf3e 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright (C) 2000-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,6 +19,7 @@ #include "mysql_priv.h" #include "sql_select.h" +#include "keycaches.h" #include <hash.h> #include <thr_alarm.h> #if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_H) @@ -55,19 +56,18 @@ static const char *lock_descriptions[] = void print_where(COND *cond,const char *info, enum_query_type query_type) { + char buff[256]; + String str(buff,(uint32) sizeof(buff), system_charset_info); + str.length(0); if (cond) - { - char buff[256]; - String str(buff,(uint32) sizeof(buff), system_charset_info); - str.length(0); cond->print(&str, query_type); - str.append('\0'); - DBUG_LOCK_FILE; - (void) fprintf(DBUG_FILE,"\nWHERE:(%s) ",info); - (void) fputs(str.ptr(),DBUG_FILE); - (void) fputc('\n',DBUG_FILE); - DBUG_UNLOCK_FILE; - } + str.append('\0'); + + DBUG_LOCK_FILE; + (void) fprintf(DBUG_FILE,"\nWHERE:(%s) %p ", info, cond); + (void) fputs(str.ptr(),DBUG_FILE); + (void) fputc('\n',DBUG_FILE); + DBUG_UNLOCK_FILE; } /* This is for debugging purposes */ @@ -80,7 +80,7 @@ void print_cached_tables(void) compile_time_assert(TL_WRITE_ONLY+1 == array_elements(lock_descriptions)); /* purecov: begin tested */ - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); puts("DB Table Version Thread Open Lock"); for (idx=unused=0 ; idx < open_cache.records ; idx++) @@ -116,7 +116,7 @@ void print_cached_tables(void) if (my_hash_check(&open_cache)) printf("Error: File hash table is corrupted\n"); fflush(stdout); - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); /* purecov: end */ return; } @@ -155,7 +155,7 @@ void TEST_filesort(SORT_FIELD *sortorder,uint s_length) } out.append('\0'); // Purify doesn't like c_ptr() DBUG_LOCK_FILE; - VOID(fputs("\nInfo about FILESORT\n",DBUG_FILE)); + (void) fputs("\nInfo about FILESORT\n",DBUG_FILE); fprintf(DBUG_FILE,"Sortorder: %s\n",out.ptr()); DBUG_UNLOCK_FILE; DBUG_VOID_RETURN; @@ -184,7 +184,7 @@ TEST_join(JOIN *join) } DBUG_LOCK_FILE; - VOID(fputs("\nInfo about JOIN\n",DBUG_FILE)); + (void) fputs("\nInfo about JOIN\n",DBUG_FILE); for (i=0 ; i < join->tables ; i++) { JOIN_TAB *tab=join->join_tab+i; @@ -210,7 +210,7 @@ TEST_join(JOIN *join) tab->select->quick->dbug_dump(18, FALSE); } else - VOID(fputs(" select used\n",DBUG_FILE)); + (void) fputs(" select used\n",DBUG_FILE); } if (tab->ref.key_parts) { @@ -365,7 +365,7 @@ static void push_locks_into_array(DYNAMIC_ARRAY *ar, THR_LOCK_DATA *data, table_lock_info.lock_text=text; // lock_type is also obtainable from THR_LOCK_DATA table_lock_info.type=table->reginfo.lock_type; - VOID(push_dynamic(ar,(uchar*) &table_lock_info)); + (void) push_dynamic(ar,(uchar*) &table_lock_info); } } } @@ -390,13 +390,13 @@ static void display_table_locks(void) LIST *list; DYNAMIC_ARRAY saved_table_locks; - VOID(my_init_dynamic_array(&saved_table_locks,sizeof(TABLE_LOCK_INFO),open_cache.records + 20,50)); - VOID(pthread_mutex_lock(&THR_LOCK_lock)); + (void) my_init_dynamic_array(&saved_table_locks,sizeof(TABLE_LOCK_INFO),open_cache.records + 20,50); + mysql_mutex_lock(&THR_LOCK_lock); for (list= thr_lock_thread_list; list; list= list_rest(list)) { THR_LOCK *lock=(THR_LOCK*) list->data; - VOID(pthread_mutex_lock(&lock->mutex)); + mysql_mutex_lock(&lock->mutex); push_locks_into_array(&saved_table_locks, lock->write.data, FALSE, "Locked - write"); push_locks_into_array(&saved_table_locks, lock->write_wait.data, TRUE, @@ -405,9 +405,9 @@ static void display_table_locks(void) "Locked - read"); push_locks_into_array(&saved_table_locks, lock->read_wait.data, TRUE, "Waiting - read"); - VOID(pthread_mutex_unlock(&lock->mutex)); + mysql_mutex_unlock(&lock->mutex); } - VOID(pthread_mutex_unlock(&THR_LOCK_lock)); + mysql_mutex_unlock(&THR_LOCK_lock); if (!saved_table_locks.elements) goto end; qsort((uchar*) dynamic_element(&saved_table_locks,0,TABLE_LOCK_INFO *),saved_table_locks.elements,sizeof(TABLE_LOCK_INFO),(qsort_cmp) dl_compare); @@ -453,8 +453,10 @@ writes: %10s\n\ r_requests: %10s\n\ reads: %10s\n\n", name, - (ulong) key_cache->param_buff_size, key_cache->param_block_size, - key_cache->param_division_limit, key_cache->param_age_threshold, + (ulong) key_cache->param_buff_size, + (ulong)key_cache->param_block_size, + (ulong)key_cache->param_division_limit, + (ulong)key_cache->param_age_threshold, key_cache->blocks_used,key_cache->global_blocks_changed, llstr(key_cache->global_cache_w_requests,llbuff1), llstr(key_cache->global_cache_write,llbuff2), @@ -472,7 +474,7 @@ void mysql_print_status() calc_sum_of_all_status(&tmp); printf("\nStatus information:\n\n"); - VOID(my_getwd(current_dir, sizeof(current_dir),MYF(0))); + (void) my_getwd(current_dir, sizeof(current_dir),MYF(0)); printf("Current dir: %s\n", current_dir); printf("Running threads: %d Stack size: %ld\n", thread_count, (long) my_thread_stack_size); @@ -483,7 +485,7 @@ void mysql_print_status() /* Print key cache status */ puts("\nKey caches:"); process_key_caches(print_key_cache_status); - pthread_mutex_lock(&LOCK_status); + mysql_mutex_lock(&LOCK_status); printf("\nhandler status:\n\ read_key: %10lu\n\ read_next: %10lu\n\ @@ -499,7 +501,7 @@ update: %10lu\n", tmp.ha_write_count, tmp.ha_delete_count, tmp.ha_update_count); - pthread_mutex_unlock(&LOCK_status); + mysql_mutex_unlock(&LOCK_status); printf("\nTable status:\n\ Opened tables: %10lu\n\ Open tables: %10lu\n\ diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index aa2ed498de1..ee530a74b50 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2004-2005 MySQL AB +/* Copyright (C) 2004-2005 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -387,7 +387,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) DBUG_RETURN(TRUE); - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); if (!create) { @@ -510,7 +510,7 @@ end: result= write_bin_log(thd, TRUE, stmt_query.ptr(), stmt_query.length()); } - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); if (need_start_waiting) start_waiting_global_read_lock(thd); @@ -804,7 +804,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, return 0; err_with_cleanup: - my_delete(trigname_buff, MYF(MY_WME)); + mysql_file_delete(key_file_trn, trigname_buff, MYF(MY_WME)); return 1; } @@ -827,7 +827,7 @@ static bool rm_trigger_file(char *path, const char *db, const char *table_name) { build_table_filename(path, FN_REFLEN-1, db, table_name, TRG_EXT, 0); - return my_delete(path, MYF(MY_WME)); + return mysql_file_delete(key_file_trg, path, MYF(MY_WME)); } @@ -849,7 +849,7 @@ static bool rm_trigname_file(char *path, const char *db, const char *trigger_name) { build_table_filename(path, FN_REFLEN - 1, db, trigger_name, TRN_EXT, 0); - return my_delete(path, MYF(MY_WME)); + return mysql_file_delete(key_file_trn, path, MYF(MY_WME)); } @@ -1198,12 +1198,13 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, DBUG_RETURN(1); // EOM } - - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_TRG_NO_CREATION_CTX, - ER(ER_TRG_NO_CREATION_CTX), - (const char*) db, - (const char*) table_name); + + if (!thd->no_warnings_for_error) + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRG_NO_CREATION_CTX, + ER(ER_TRG_NO_CREATION_CTX), + (const char*) db, + (const char*) table_name); if (!(trg_client_cs_name= alloc_lex_string(&table->mem_root)) || !(trg_connection_cl_name= alloc_lex_string(&table->mem_root)) || @@ -1332,12 +1333,12 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, MySQL, which does not support triggers definers. We should emit warning here. */ - - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, - ER_TRG_NO_DEFINER, ER(ER_TRG_NO_DEFINER), - (const char*) db, - (const char*) lex.sphead->m_name.str); - + if (!thd->no_warnings_for_error) + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_TRG_NO_DEFINER, ER(ER_TRG_NO_DEFINER), + (const char*) db, + (const char*) lex.sphead->m_name.str); + /* Set definer to the '' to correct displaying in the information schema. @@ -1660,7 +1661,7 @@ bool Table_triggers_list::drop_all_triggers(THD *thd, char *db, char *name) DBUG_ENTER("drop_all_triggers"); bzero(&table, sizeof(table)); - init_alloc_root(&table.mem_root, 8192, 0); + init_sql_alloc(&table.mem_root, 8192, 0); if (Table_triggers_list::check_n_load(thd, db, name, &table, 1)) { @@ -1871,7 +1872,7 @@ bool Table_triggers_list::change_table_name(THD *thd, const char *db, DBUG_ENTER("change_table_name"); bzero(&table, sizeof(table)); - init_alloc_root(&table.mem_root, 8192, 0); + init_sql_alloc(&table.mem_root, 8192, 0); /* This method interfaces the mysql server code protected by @@ -1884,7 +1885,7 @@ bool Table_triggers_list::change_table_name(THD *thd, const char *db, old_table)-(char*)&key[0])+1; if (!is_table_name_exclusively_locked_by_this_thread(thd, key, key_length)) - safe_mutex_assert_owner(&LOCK_open); + mysql_mutex_assert_owner(&LOCK_open); #endif DBUG_ASSERT(my_strcasecmp(table_alias_charset, db, new_db) || diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index b2e35c84854..d0e446fb157 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -44,7 +44,7 @@ extern "C" static bool initialized = 0; static MEM_ROOT mem; static HASH udf_hash; -static rw_lock_t THR_LOCK_udf; +static mysql_rwlock_t THR_LOCK_udf; static udf_func *add_udf(LEX_STRING *name, Item_result ret, @@ -100,6 +100,26 @@ extern "C" uchar* get_hash_key(const uchar *buff, size_t *length, return (uchar*) udf->name.str; } +#ifdef HAVE_PSI_INTERFACE +static PSI_rwlock_key key_rwlock_THR_LOCK_udf; + +static PSI_rwlock_info all_udf_rwlocks[]= +{ + { &key_rwlock_THR_LOCK_udf, "THR_LOCK_udf", PSI_FLAG_GLOBAL} +}; + +static void init_udf_psi_keys(void) +{ + const char* category= "sql"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_udf_rwlocks); + PSI_server->register_rwlock(category, all_udf_rwlocks, count); +} +#endif /* Read all predeclared functions from mysql.func and accept all that @@ -119,8 +139,12 @@ void udf_init() if (initialized) DBUG_VOID_RETURN; - my_rwlock_init(&THR_LOCK_udf,NULL); - +#ifdef HAVE_PSI_INTERFACE + init_udf_psi_keys(); +#endif + + mysql_rwlock_init(key_rwlock_THR_LOCK_udf, &THR_LOCK_udf); + init_sql_alloc(&mem, UDF_ALLOC_BLOCK_SIZE, 0); THD *new_thd = new THD; if (!new_thd || @@ -135,7 +159,6 @@ void udf_init() initialized = 1; new_thd->thread_stack= (char*) &new_thd; new_thd->store_globals(); - lex_start(new_thd); new_thd->set_db(db, sizeof(db)-1); bzero((uchar*) &tables,sizeof(tables)); @@ -257,7 +280,7 @@ void udf_free() if (initialized) { initialized= 0; - rwlock_destroy(&THR_LOCK_udf); + mysql_rwlock_destroy(&THR_LOCK_udf); } DBUG_VOID_RETURN; } @@ -295,7 +318,7 @@ void free_udf(udf_func *udf) if (!initialized) DBUG_VOID_RETURN; - rw_wrlock(&THR_LOCK_udf); + mysql_rwlock_wrlock(&THR_LOCK_udf); if (!--udf->usage_count) { /* @@ -307,7 +330,7 @@ void free_udf(udf_func *udf) if (!find_udf_dl(udf->dl)) dlclose(udf->dlhandle); } - rw_unlock(&THR_LOCK_udf); + mysql_rwlock_unlock(&THR_LOCK_udf); DBUG_VOID_RETURN; } @@ -324,9 +347,9 @@ udf_func *find_udf(const char *name,uint length,bool mark_used) /* TODO: This should be changed to reader locks someday! */ if (mark_used) - rw_wrlock(&THR_LOCK_udf); /* Called during fix_fields */ + mysql_rwlock_wrlock(&THR_LOCK_udf); /* Called during fix_fields */ else - rw_rdlock(&THR_LOCK_udf); /* Called during parsing */ + mysql_rwlock_rdlock(&THR_LOCK_udf); /* Called during parsing */ if ((udf=(udf_func*) my_hash_search(&udf_hash,(uchar*) name, length ? length : (uint) strlen(name)))) @@ -336,7 +359,7 @@ udf_func *find_udf(const char *name,uint length,bool mark_used) else if (mark_used) udf->usage_count++; } - rw_unlock(&THR_LOCK_udf); + mysql_rwlock_unlock(&THR_LOCK_udf); DBUG_RETURN(udf); } @@ -438,10 +461,10 @@ int mysql_create_function(THD *thd,udf_func *udf) Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for CREATE FUNCTION command. */ - save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); + thd->clear_current_stmt_binlog_format_row(); - rw_wrlock(&THR_LOCK_udf); + mysql_rwlock_wrlock(&THR_LOCK_udf); if ((my_hash_search(&udf_hash,(uchar*) udf->name.str, udf->name.length))) { my_error(ER_UDF_EXISTS, MYF(0), udf->name.str); @@ -504,7 +527,7 @@ int mysql_create_function(THD *thd,udf_func *udf) del_udf(u_d); goto err; } - rw_unlock(&THR_LOCK_udf); + mysql_rwlock_unlock(&THR_LOCK_udf); /* Binlog the create function. */ if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) @@ -520,7 +543,7 @@ int mysql_create_function(THD *thd,udf_func *udf) err: if (new_dl) dlclose(dl); - rw_unlock(&THR_LOCK_udf); + mysql_rwlock_unlock(&THR_LOCK_udf); /* Restore the state of binlog format */ thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(1); @@ -550,10 +573,10 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name) Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for DROP FUNCTION command. */ - save_binlog_row_based= thd->current_stmt_binlog_row_based; - thd->clear_current_stmt_binlog_row_based(); + save_binlog_row_based= thd->is_current_stmt_binlog_format_row(); + thd->clear_current_stmt_binlog_format_row(); - rw_wrlock(&THR_LOCK_udf); + mysql_rwlock_wrlock(&THR_LOCK_udf); if (!(udf=(udf_func*) my_hash_search(&udf_hash,(uchar*) udf_name->str, (uint) udf_name->length))) { @@ -588,7 +611,7 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name) } close_thread_tables(thd); - rw_unlock(&THR_LOCK_udf); + mysql_rwlock_unlock(&THR_LOCK_udf); /* Binlog the drop function. */ if (write_bin_log(thd, TRUE, thd->query(), thd->query_length())) @@ -601,7 +624,7 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name) thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(0); err: - rw_unlock(&THR_LOCK_udf); + mysql_rwlock_unlock(&THR_LOCK_udf); /* Restore the state of binlog format */ thd->current_stmt_binlog_row_based= save_binlog_row_based; DBUG_RETURN(1); diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 1760670f9c8..ad14d2e4ecd 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -121,7 +121,7 @@ select_union::create_result_table(THD *thd_arg, List<Item> *column_types, if (! (table= create_tmp_table(thd_arg, &tmp_table_param, *column_types, (ORDER*) 0, is_union_distinct, 1, - options, HA_POS_ERROR, (char*) alias))) + options, HA_POS_ERROR, alias))) return TRUE; table->file->extra(HA_EXTRA_WRITE_CACHE); table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); @@ -232,7 +232,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, bool can_skip_order_by; sl->options|= SELECT_NO_UNLOCK; JOIN *join= new JOIN(thd_arg, sl->item_list, - sl->options | thd_arg->options | additional_options, + sl->options | thd_arg->variables.option_bits | additional_options, tmp_result); /* setup_tables_done_option should be set only for very first SELECT, @@ -364,7 +364,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, } - create_options= (first_sl->options | thd_arg->options | + create_options= (first_sl->options | thd_arg->variables.option_bits | TMP_TABLE_ALL_COLUMNS); /* Force the temporary table to be a MyISAM table if we're going to use @@ -405,7 +405,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, init_prepare_fake_select_lex(thd); /* Should be done only once (the only item_list per statement) */ DBUG_ASSERT(fake_select_lex->join == 0); - if (!(fake_select_lex->join= new JOIN(thd, item_list, thd->options, + if (!(fake_select_lex->join= new JOIN(thd, item_list, thd->variables.option_bits, result))) { fake_select_lex->table_list.empty(); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index c9c4501f072..97abf2cd89b 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -186,7 +186,7 @@ int mysql_update(THD *thd, ha_rows *found_return, ha_rows *updated_return) { bool using_limit= limit != HA_POS_ERROR; - bool safe_update= test(thd->options & OPTION_SAFE_UPDATES); + bool safe_update= test(thd->variables.option_bits & OPTION_SAFE_UPDATES); bool used_key_is_modified, transactional_table, will_batch; bool can_compare_record; int res; @@ -663,11 +663,13 @@ int mysql_update(THD *thd, If (ignore && error is ignorable) we don't have to do anything; otherwise... */ + myf flags= 0; + if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) - thd->fatal_error(); /* Other handler errors are fatal */ + flags|= ME_FATALERROR; /* Other handler errors are fatal */ prepare_record_for_error_message(error, table); - table->file->print_error(error,MYF(0)); + table->file->print_error(error,MYF(flags)); error= 1; break; } @@ -764,9 +766,8 @@ int mysql_update(THD *thd, */ { /* purecov: begin inspected */ - thd->fatal_error(); prepare_record_for_error_message(loc_error, table); - table->file->print_error(loc_error,MYF(0)); + table->file->print_error(loc_error,MYF(ME_FATALERROR)); error= 1; /* purecov: end */ } @@ -782,7 +783,7 @@ int mysql_update(THD *thd, end_read_record(&info); delete select; thd_proc_info(thd, "end"); - VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY)); + (void) table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); /* Invalidate the table in the query cache if something changed. @@ -792,6 +793,9 @@ int mysql_update(THD *thd, { query_cache_invalidate3(thd, table_list, 1); } + + if (thd->transaction.stmt.modified_non_trans_table) + thd->transaction.all.modified_non_trans_table= TRUE; /* error < 0 means really no error at all: we processed all rows until the @@ -814,13 +818,11 @@ int mysql_update(THD *thd, if (thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query(), thd->query_length(), - transactional_table, FALSE, errcode)) + transactional_table, FALSE, FALSE, errcode)) { error=1; // Rollback update } } - if (thd->transaction.stmt.modified_non_trans_table) - thd->transaction.all.modified_non_trans_table= TRUE; } DBUG_ASSERT(transactional_table || !updated || thd->transaction.stmt.modified_non_trans_table); free_underlaid_joins(thd, select_lex); @@ -884,19 +886,6 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, SELECT_LEX *select_lex= &thd->lex->select_lex; DBUG_ENTER("mysql_prepare_update"); - /* - Statement-based replication of UPDATE ... LIMIT is not safe as order of - rows is not defined, so in mixed mode we go to row-based. - - Note that we may consider a statement as safe if ORDER BY primary_key - is present. However it may confuse users to see very similiar statements - replicated differently. - */ - if (thd->lex->current_select->select_limit) - { - thd->lex->set_stmt_unsafe(); - thd->set_current_stmt_binlog_row_based_if_mixed(); - } #ifndef NO_EMBEDDED_ACCESS_CHECKS table_list->grant.want_privilege= table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege); @@ -1074,9 +1063,10 @@ reopen_tables: if (!tl->derived) { uint want_privilege= tl->updating ? UPDATE_ACL : SELECT_ACL; - if (check_access(thd, want_privilege, - tl->db, &tl->grant.privilege, 0, 0, - test(tl->schema_table)) || + if (check_access(thd, want_privilege, tl->db, + &tl->grant.privilege, + &tl->grant.m_internal, + 0, 0) || check_grant(thd, want_privilege, tl, FALSE, 1, FALSE)) DBUG_RETURN(TRUE); } @@ -1496,7 +1486,7 @@ multi_update::initialize_tables(JOIN *join) TABLE_LIST *table_ref; DBUG_ENTER("initialize_tables"); - if ((thd->options & OPTION_SAFE_UPDATES) && error_if_full_join(join)) + if ((thd->variables.option_bits & OPTION_SAFE_UPDATES) && error_if_full_join(join)) DBUG_RETURN(1); main_table=join->join_tab->table; table_to_update= 0; @@ -1620,13 +1610,14 @@ loop_end: tmp_param->field_count=temp_fields.elements; tmp_param->group_parts=1; tmp_param->group_length= table->file->ref_length; - if (!(tmp_tables[cnt]=create_tmp_table(thd, - tmp_param, - temp_fields, - (ORDER*) &group, 0, 0, - TMP_TABLE_ALL_COLUMNS, - HA_POS_ERROR, - (char *) ""))) + /* small table, ignore SQL_BIG_TABLES */ + my_bool save_big_tables= thd->variables.big_tables; + thd->variables.big_tables= FALSE; + tmp_tables[cnt]=create_tmp_table(thd, tmp_param, temp_fields, + (ORDER*) &group, 0, 0, + TMP_TABLE_ALL_COLUMNS, HA_POS_ERROR, ""); + thd->variables.big_tables= save_big_tables; + if (!tmp_tables[cnt]) DBUG_RETURN(1); tmp_tables[cnt]->file->extra(HA_EXTRA_WRITE_CACHE); } @@ -1746,11 +1737,13 @@ bool multi_update::send_data(List<Item> ¬_used_values) If (ignore && error == is ignorable) we don't have to do anything; otherwise... */ + myf flags= 0; + if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) - thd->fatal_error(); /* Other handler errors are fatal */ + flags|= ME_FATALERROR; /* Other handler errors are fatal */ prepare_record_for_error_message(error, table); - table->file->print_error(error,MYF(0)); + table->file->print_error(error,MYF(flags)); DBUG_RETURN(1); } } @@ -1764,10 +1757,10 @@ bool multi_update::send_data(List<Item> ¬_used_values) /* non-transactional or transactional table got modified */ /* either multi_update class' flag is raised in its branch */ if (table->file->has_transactions()) - transactional_tables= 1; + transactional_tables= TRUE; else { - trans_safe= 0; + trans_safe= FALSE; thd->transaction.stmt.modified_non_trans_table= TRUE; } } @@ -1858,7 +1851,7 @@ void multi_update::abort() todo/fixme: do_update() is never called with the arg 1. should it change the signature to become argless? */ - VOID(do_updates()); + (void) do_updates(); } } if (thd->transaction.stmt.modified_non_trans_table) @@ -1877,8 +1870,8 @@ void multi_update::abort() int errcode= query_error_code(thd, thd->killed == THD::NOT_KILLED); /* the error of binary logging is ignored */ (void)thd->binlog_query(THD::ROW_QUERY_TYPE, - thd->query(), thd->query_length(), - transactional_tables, FALSE, errcode); + thd->query(), thd->query_length(), + transactional_tables, FALSE, FALSE, errcode); } thd->transaction.all.modified_non_trans_table= TRUE; } @@ -2016,10 +2009,10 @@ int multi_update::do_updates() if (updated != org_updated) { if (table->file->has_transactions()) - transactional_tables= 1; + transactional_tables= TRUE; else { - trans_safe= 0; // Can't do safe rollback + trans_safe= FALSE; // Can't do safe rollback thd->transaction.stmt.modified_non_trans_table= TRUE; } } @@ -2034,9 +2027,8 @@ int multi_update::do_updates() err: { - thd->fatal_error(); prepare_record_for_error_message(local_error, table); - table->file->print_error(local_error,MYF(0)); + table->file->print_error(local_error,MYF(ME_FATALERROR)); } err2: @@ -2049,10 +2041,10 @@ err2: if (updated != org_updated) { if (table->file->has_transactions()) - transactional_tables= 1; + transactional_tables= TRUE; else { - trans_safe= 0; + trans_safe= FALSE; thd->transaction.stmt.modified_non_trans_table= TRUE; } } @@ -2098,8 +2090,9 @@ bool multi_update::send_eof() either from the query's list or via a stored routine: bug#13270,23333 */ - DBUG_ASSERT(trans_safe || !updated || - thd->transaction.stmt.modified_non_trans_table); + if (thd->transaction.stmt.modified_non_trans_table) + thd->transaction.all.modified_non_trans_table= TRUE; + if (local_error == 0 || thd->transaction.stmt.modified_non_trans_table) { if (mysql_bin_log.is_open()) @@ -2111,14 +2104,15 @@ bool multi_update::send_eof() errcode= query_error_code(thd, killed_status == THD::NOT_KILLED); if (thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query(), thd->query_length(), - transactional_tables, FALSE, errcode)) + transactional_tables, FALSE, FALSE, errcode)) { local_error= 1; // Rollback update } } - if (thd->transaction.stmt.modified_non_trans_table) - thd->transaction.all.modified_non_trans_table= TRUE; } + DBUG_ASSERT(trans_safe || !updated || + thd->transaction.stmt.modified_non_trans_table); + if (local_error != 0) error_handled= TRUE; // to force early leave from ::send_error() diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 858b6ba43d7..31e4a45ce4f 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2004 MySQL AB +/* Copyright (C) 2004 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,15 +29,6 @@ const LEX_STRING view_type= { C_STRING_WITH_LEN("VIEW") }; static int mysql_register_view(THD *thd, TABLE_LIST *view, enum_view_create_mode mode); -const char *updatable_views_with_limit_names[]= { "NO", "YES", NullS }; -TYPELIB updatable_views_with_limit_typelib= -{ - array_elements(updatable_views_with_limit_names)-1, "", - updatable_views_with_limit_names, - 0 -}; - - /* Make a unique name for an anonymous view column SYNOPSIS @@ -267,12 +258,16 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, checked that we have not more privileges on correspondent column of view table (i.e. user will not get some privileges by view creation) */ - if ((check_access(thd, CREATE_VIEW_ACL, view->db, &view->grant.privilege, - 0, 0, is_schema_db(view->db, view->db_length)) || + if ((check_access(thd, CREATE_VIEW_ACL, view->db, + &view->grant.privilege, + &view->grant.m_internal, + 0, 0) || check_grant(thd, CREATE_VIEW_ACL, view, FALSE, 1, FALSE)) || (mode != VIEW_CREATE_NEW && - (check_access(thd, DROP_ACL, view->db, &view->grant.privilege, - 0, 0, is_schema_db(view->db, view->db_length)) || + (check_access(thd, DROP_ACL, view->db, + &view->grant.privilege, + &view->grant.m_internal, + 0, 0) || check_grant(thd, DROP_ACL, view, FALSE, 1, FALSE)))) goto err; @@ -322,7 +317,9 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view, if (!tbl->table_in_first_from_clause) { if (check_access(thd, SELECT_ACL, tbl->db, - &tbl->grant.privilege, 0, 0, test(tbl->schema_table)) || + &tbl->grant.privilege, + &tbl->grant.m_internal, + 0, 0) || check_grant(thd, SELECT_ACL, tbl, FALSE, 1, FALSE)) goto err; } @@ -620,7 +617,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, res= TRUE; goto err; } - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); res= mysql_register_view(thd, view, mode); if (mysql_bin_log.is_open()) @@ -663,11 +660,11 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, int errcode= query_error_code(thd, TRUE); if (thd->binlog_query(THD::STMT_QUERY_TYPE, - buff.ptr(), buff.length(), FALSE, FALSE, errcode)) + buff.ptr(), buff.length(), FALSE, FALSE, FALSE, errcode)) res= TRUE; } - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); if (mode != VIEW_CREATE_NEW) query_cache_invalidate3(thd, view, 0); start_waiting_global_read_lock(thd); @@ -819,7 +816,8 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, thd->variables.sql_mode|= sql_mode; } - DBUG_PRINT("info", ("View: %s", view_query.ptr())); + DBUG_PRINT("info", + ("View: %*.s", (int) view_query.length(), view_query.ptr())); /* fill structure */ view->source= thd->lex->create_view_select; @@ -1125,8 +1123,18 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, table->db, table->table_name); get_default_definer(thd, &table->definer); } + + /* + Initialize view definition context by character set names loaded from + the view definition file. Use UTF8 character set if view definition + file is of old version and does not contain the character set names. + */ + table->view_creation_ctx= View_creation_ctx::create(thd, table); + if (flags & OPEN_VIEW_NO_PARSE) { + if (arena) + thd->restore_active_arena(arena, &backup); DBUG_RETURN(FALSE); } @@ -1141,13 +1149,6 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, /*TODO: md5 test here and warning if it is differ */ - /* - Initialize view definition context by character set names loaded from - the view definition file. Use UTF8 character set if view definition - file is of old version and does not contain the character set names. - */ - - table->view_creation_ctx= View_creation_ctx::create(thd, table); /* TODO: TABLE mem root should be used here when VIEW will be stored in @@ -1308,8 +1309,8 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, If the view's body needs row-based binlogging (e.g. the VIEW is created from SELECT UUID()), the top statement also needs it. */ - if (lex->is_stmt_unsafe()) - old_lex->set_stmt_unsafe(); + old_lex->set_stmt_unsafe_flags(lex->get_stmt_unsafe_flags()); + view_is_mergeable= (table->algorithm != VIEW_ALGORITHM_TMPTABLE && lex->can_be_merged()); @@ -1580,7 +1581,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) bool something_wrong= FALSE; DBUG_ENTER("mysql_drop_view"); - VOID(pthread_mutex_lock(&LOCK_open)); + mysql_mutex_lock(&LOCK_open); for (view= views; view; view= view->next_local) { TABLE_SHARE *share; @@ -1616,7 +1617,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) } continue; } - if (my_delete(path, MYF(MY_WME))) + if (mysql_file_delete(key_file_frm, path, MYF(MY_WME))) error= TRUE; some_views_deleted= TRUE; @@ -1628,10 +1629,10 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) if ((share= get_cached_table_share(view->db, view->table_name))) { DBUG_ASSERT(share->ref_count == 0); - pthread_mutex_lock(&share->mutex); + mysql_mutex_lock(&share->mutex); share->ref_count++; share->version= 0; - pthread_mutex_unlock(&share->mutex); + mysql_mutex_unlock(&share->mutex); release_table_share(share, RELEASE_WAIT_FOR_DROP); } query_cache_invalidate3(thd, view, 0); @@ -1658,7 +1659,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) something_wrong= 1; } - VOID(pthread_mutex_unlock(&LOCK_open)); + mysql_mutex_unlock(&LOCK_open); if (something_wrong) { @@ -1691,10 +1692,11 @@ frm_type_enum mysql_frm_type(THD *thd, char *path, enum legacy_db_type *dbt) *dbt= DB_TYPE_UNKNOWN; - if ((file= my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0) + if ((file= mysql_file_open(key_file_frm, + path, O_RDONLY | O_SHARE, MYF(0))) < 0) DBUG_RETURN(FRMTYPE_ERROR); - error= my_read(file, (uchar*) header, sizeof(header), MYF(MY_NABP)); - my_close(file, MYF(MY_WME)); + error= mysql_file_read(file, (uchar*) header, sizeof(header), MYF(MY_NABP)); + mysql_file_close(file, MYF(MY_WME)); if (error) DBUG_RETURN(FRMTYPE_ERROR); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 36a910b7a99..0b0ca2e6215 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -47,6 +47,8 @@ #include "event_parse_data.h" #include <myisam.h> #include <myisammrg.h> +#include "keycaches.h" +#include "set_var.h" /* this is to get the bison compilation windows warnings out */ #ifdef _MSC_VER @@ -426,7 +428,7 @@ set_system_variable(THD *thd, struct sys_var_with_base *tmp, LEX *lex= thd->lex; /* No AUTOCOMMIT from a stored function or trigger. */ - if (lex->spcont && tmp->var == &sys_autocommit) + if (lex->spcont && tmp->var == Sys_autocommit_ptr) lex->sphead->m_flags|= sp_head::HAS_SET_AUTOCOMMIT_STMT; if (! (var= new set_var(var_type, tmp->var, &tmp->base_name, val))) @@ -598,6 +600,89 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal, DBUG_RETURN(result); } +/** + @brief Creates a new SELECT_LEX for a UNION branch. + + Sets up and initializes a SELECT_LEX structure for a query once the parser + discovers a UNION token. The current SELECT_LEX is pushed on the stack and + the new SELECT_LEX becomes the current one. + + @param lex The parser state. + + @param is_union_distinct True if the union preceding the new select statement + uses UNION DISTINCT. + + @param is_top_level This should be @c TRUE if the newly created SELECT_LEX + is a non-nested statement. + + @return <code>false</code> if successful, <code>true</code> if an error was + reported. In the latter case parsing should stop. + */ +bool add_select_to_union_list(LEX *lex, bool is_union_distinct, + bool is_top_level) +{ + /* + Only the last SELECT can have INTO. Since the grammar won't allow INTO in + a nested SELECT, we make this check only when creating a top-level SELECT. + */ + if (is_top_level && lex->result) + { + my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO"); + return TRUE; + } + if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE) + { + my_parse_error(ER(ER_SYNTAX_ERROR)); + return TRUE; + } + /* This counter shouldn't be incremented for UNION parts */ + lex->nest_level--; + if (mysql_new_select(lex, 0)) + return TRUE; + mysql_init_select(lex); + lex->current_select->linkage=UNION_TYPE; + if (is_union_distinct) /* UNION DISTINCT - remember position */ + lex->current_select->master_unit()->union_distinct= + lex->current_select; + return FALSE; +} + +/** + @brief Initializes a SELECT_LEX for a query within parentheses (aka + braces). + + @return false if successful, true if an error was reported. In the latter + case parsing should stop. + */ +bool setup_select_in_parentheses(LEX *lex) +{ + SELECT_LEX * sel= lex->current_select; + if (sel->set_braces(1)) + { + my_parse_error(ER(ER_SYNTAX_ERROR)); + return TRUE; + } + if (sel->linkage == UNION_TYPE && + !sel->master_unit()->first_select()->braces && + sel->master_unit()->first_select()->linkage == + UNION_TYPE) + { + my_parse_error(ER(ER_SYNTAX_ERROR)); + return TRUE; + } + if (sel->linkage == UNION_TYPE && + sel->olap != UNSPECIFIED_OLAP_TYPE && + sel->master_unit()->fake_select_lex) + { + my_error(ER_WRONG_USAGE, MYF(0), "CUBE/ROLLUP", "ORDER BY"); + return TRUE; + } + /* select in braces, can't contain global parameters */ + if (sel->master_unit()->fake_select_lex) + sel->master_unit()->global_parameters= + sel->master_unit()->fake_select_lex; + return FALSE; +} static bool add_create_index_prepare (LEX *lex, Table_ident *table) { @@ -612,7 +697,6 @@ static bool add_create_index_prepare (LEX *lex, Table_ident *table) return FALSE; } - static bool add_create_index (LEX *lex, Key::Keytype type, const LEX_STRING &name, KEY_CREATE_INFO *info= NULL, bool generated= 0) @@ -672,6 +756,7 @@ static bool add_create_index (LEX *lex, Key::Keytype type, struct p_elem_val *p_elem_value; enum index_hint_type index_hint; enum enum_filetype filetype; + enum Foreign_key::fk_option m_fk_option; Diag_condition_item_name diag_condition_item_name; } @@ -854,6 +939,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token ENUM %token EQ /* OPERATOR */ %token EQUAL_SYM /* OPERATOR */ +%token ERROR_SYM %token ERRORS %token ESCAPED %token ESCAPE_SYM /* SQL-2003-R */ @@ -887,6 +973,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token FULLTEXT_SYM %token FUNCTION_SYM /* SQL-2003-R */ %token GE +%token GENERAL %token GEOMETRYCOLLECTION %token GEOMETRY_SYM %token GET_FORMAT /* MYSQL-FUNC */ @@ -920,7 +1007,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token INFILE %token INITIAL_SIZE_SYM %token INNER_SYM /* SQL-2003-R */ -%token INNOBASE_SYM %token INOUT_SYM /* SQL-2003-R */ %token INSENSITIVE_SYM /* SQL-2003-R */ %token INSERT /* SQL-2003-R */ @@ -1107,6 +1193,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token REDUNDANT_SYM %token REFERENCES /* SQL-2003-R */ %token REGEXP +%token RELAY %token RELAYLOG_SYM %token RELAY_LOG_FILE_SYM %token RELAY_LOG_POS_SYM @@ -1164,6 +1251,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token SIGNED_SYM %token SIMPLE_SYM /* SQL-2003-N */ %token SLAVE +%token SLOW %token SMALLINT /* SQL-2003-R */ %token SNAPSHOT_SYM %token SOCKET_SYM @@ -1278,6 +1366,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token WHERE /* SQL-2003-R */ %token WHILE_SYM %token WITH /* SQL-2003-R */ +%token WITH_CUBE_SYM /* INTERNAL */ +%token WITH_ROLLUP_SYM /* INTERNAL */ %token WORK_SYM /* SQL-2003-N */ %token WRAPPER_SYM %token WRITE_SYM /* SQL-2003-N */ @@ -1330,10 +1420,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); text_string opt_gconcat_separator %type <num> - type int_type real_type order_dir lock_option + type type_with_opt_collate int_type real_type order_dir lock_option udf_type if_exists opt_local opt_table_options table_options table_option opt_if_not_exists opt_no_write_to_binlog - delete_option opt_temporary all_or_any opt_distinct + opt_temporary all_or_any opt_distinct opt_ignore_leaves fulltext_options spatial_type union_option start_transaction_opts opt_chain opt_release union_opt select_derived_init option_type2 @@ -1341,6 +1431,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt +%type <m_fk_option> + delete_option + %type <ulong_num> ulong_num real_ulong_num merge_insert_types @@ -1352,7 +1445,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type <item> literal text_literal insert_ident order_ident - simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr + simple_ident expr opt_expr opt_else sum_expr in_sum_expr variable variable_aux bool_pri predicate bit_expr table_wild simple_expr udf_expr @@ -1395,6 +1488,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); join_table_list join_table table_factor table_ref esc_table_ref select_derived derived_table_list + select_derived_union %type <date_time_type> date_time_type; %type <interval> interval @@ -1430,8 +1524,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type <variable> internal_variable_name -%type <select_lex> subselect take_first_select - get_select_lex +%type <select_lex> subselect + get_select_lex query_specification + query_expression_body %type <boolfunc2creator> comp_op @@ -1441,7 +1536,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); show describe load alter optimize keycache preload flush reset purge begin commit rollback savepoint release slave master_def master_defs master_file_def slave_until_opts - repair restore backup analyze check start checksum + repair analyze check start checksum field_list field_list_item field_spec kill column_def key_def keycache_list keycache_list_or_parts assign_to_keycache assign_to_keycache_parts @@ -1452,8 +1547,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); handler opt_precision opt_ignore opt_column opt_restrict grant revoke set lock unlock string_list field_options field_option - field_opt_list opt_binary table_lock_list table_lock - ref_list opt_on_delete opt_on_delete_list opt_on_delete_item use + field_opt_list opt_binary ascii unicode table_lock_list table_lock + ref_list opt_match_clause opt_on_update_delete use opt_delete_options opt_delete_option varchar nchar nvarchar opt_outer table_list table_name table_alias_ref_list table_alias_ref opt_option opt_place @@ -1515,7 +1610,7 @@ END_OF_INPUT %type <NONE> '-' '+' '*' '/' '%' '(' ')' ',' '!' '{' '}' '&' '|' AND_SYM OR_SYM OR_OR_SYM BETWEEN_SYM CASE_SYM - THEN_SYM WHEN_SYM DIV_SYM MOD_SYM OR2_SYM AND_AND_SYM + THEN_SYM WHEN_SYM DIV_SYM MOD_SYM OR2_SYM AND_AND_SYM DELETE_SYM %% /* @@ -1598,7 +1693,6 @@ verb_clause: statement: alter | analyze - | backup | binlog_base64_event | call | change @@ -1633,7 +1727,6 @@ statement: | replace | reset | resignal_stmt - | restore | revoke | rollback | savepoint @@ -2420,7 +2513,7 @@ sp_init_param: ; sp_fdparam: - ident sp_init_param type + ident sp_init_param type_with_opt_collate { LEX *lex= Lex; sp_pcontext *spc= lex->spcont; @@ -2457,7 +2550,7 @@ sp_pdparams: ; sp_pdparam: - sp_opt_inout sp_init_param ident type + sp_opt_inout sp_init_param ident type_with_opt_collate { LEX *lex= Lex; sp_pcontext *spc= lex->spcont; @@ -2537,7 +2630,7 @@ sp_decl: lex->sphead->reset_lex(YYTHD); lex->spcont->declare_var_boundary($2); } - type + type_with_opt_collate sp_opt_default { THD *thd= YYTHD; @@ -4212,8 +4305,8 @@ have_partitioning: MYSQL_YYABORT; } #else - my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), - "--skip-partition"); + my_error(ER_FEATURE_DISABLED, MYF(0), "partitioning", + "--with-plugin-partition"); MYSQL_YYABORT; #endif } @@ -4636,7 +4729,6 @@ part_value_item: part_value_item_list {} ')' { - LEX *lex= Lex; partition_info *part_info= Lex->part_info; part_info->print_debug(") part_value_item", NULL); if (part_info->num_columns == 0) @@ -4667,7 +4759,6 @@ part_value_expr_item: MAX_VALUE_SYM { partition_info *part_info= Lex->part_info; - part_column_list_val *col_val; if (part_info->part_type == LIST_PARTITION) { my_parse_error(ER(ER_MAXVALUE_IN_VALUES_IN)); @@ -4911,14 +5002,8 @@ create_table_option: ENGINE_SYM opt_equal storage_engines { Lex->create_info.db_type= $3; - Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE; - } - | TYPE_SYM opt_equal storage_engines - { - Lex->create_info.db_type= $3; - WARN_DEPRECATED(yythd, "6.0", "TYPE=storage_engine", - "'ENGINE=storage_engine'"); - Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE; + if ($3) + Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE; } | MAX_ROWS opt_equal ulonglong_num { @@ -5066,14 +5151,14 @@ default_collation: HA_CREATE_INFO *cinfo= &Lex->create_info; if ((cinfo->used_fields & HA_CREATE_USED_DEFAULT_CHARSET) && cinfo->default_table_charset && $4 && - !my_charset_same(cinfo->default_table_charset,$4)) - { - my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0), - $4->name, cinfo->default_table_charset->csname); - MYSQL_YYABORT; - } - Lex->create_info.default_table_charset= $4; - Lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET; + !($4= merge_charset_and_collation(cinfo->default_table_charset, + $4))) + { + MYSQL_YYABORT; + } + + Lex->create_info.default_table_charset= $4; + Lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET; } ; @@ -5201,10 +5286,6 @@ key_def: /* Only used for ALTER TABLE. Ignored otherwise. */ lex->alter_info.flags|= ALTER_FOREIGN_KEY; } - | constraint opt_check_constraint - { - Lex->col_list.empty(); /* Alloced by sql_alloc */ - } | opt_constraint check_constraint { Lex->col_list.empty(); /* Alloced by sql_alloc */ @@ -5217,7 +5298,7 @@ opt_check_constraint: ; check_constraint: - CHECK_SYM expr + CHECK_SYM '(' expr ')' ; opt_constraint: @@ -5326,7 +5407,7 @@ type: { $$=MYSQL_TYPE_DATE; } | TIME_SYM { $$=MYSQL_TYPE_TIME; } - | TIMESTAMP opt_field_length + | TIMESTAMP { if (YYTHD->variables.sql_mode & MODE_MAXDB) $$=MYSQL_TYPE_DATETIME; @@ -5581,6 +5662,28 @@ attribute: } ; + +type_with_opt_collate: + type opt_collate + { + $$= $1; + + if (Lex->charset) /* Lex->charset is scanned in "type" */ + { + if (!(Lex->charset= merge_charset_and_collation(Lex->charset, $2))) + MYSQL_YYABORT; + } + else if ($2) + { + my_error(ER_NOT_SUPPORTED_YET, MYF(0), + "COLLATE with no CHARACTER SET " + "in SP parameters, RETURNS, DECLARE"); + MYSQL_YYABORT; + } + } + ; + + now_or_signed_literal: NOW_SYM optional_braces { @@ -5663,11 +5766,21 @@ opt_default: | DEFAULT {} ; -opt_binary: - /* empty */ { Lex->charset=NULL; } - | ASCII_SYM opt_bin_mod { Lex->charset=&my_charset_latin1; } - | BYTE_SYM { Lex->charset=&my_charset_bin; } - | UNICODE_SYM opt_bin_mod + +ascii: + ASCII_SYM { Lex->charset= &my_charset_latin1; } + | BINARY ASCII_SYM + { + Lex->charset= &my_charset_latin1_bin; + } + | ASCII_SYM BINARY + { + Lex->charset= &my_charset_latin1_bin; + } + ; + +unicode: + UNICODE_SYM { if (!(Lex->charset=get_charset_by_csname("ucs2", MY_CS_PRIMARY,MYF(0)))) @@ -5676,8 +5789,40 @@ opt_binary: MYSQL_YYABORT; } } + | UNICODE_SYM BINARY + { + if (!(Lex->charset=get_charset_by_name("ucs2_bin", MYF(0)))) + { + my_error(ER_UNKNOWN_COLLATION, MYF(0), "ucs2_bin"); + MYSQL_YYABORT; + } + } + | BINARY UNICODE_SYM + { + if (!(Lex->charset=get_charset_by_name("ucs2_bin", MYF(0)))) + { + my_error(ER_UNKNOWN_COLLATION, MYF(0), "ucs2_bin"); + MYSQL_YYABORT; + } + } + ; + +opt_binary: + /* empty */ { Lex->charset=NULL; } + | ascii + | unicode + | BYTE_SYM { Lex->charset=&my_charset_bin; } | charset charset_name opt_bin_mod { Lex->charset=$2; } - | BINARY opt_bin_charset { Lex->type|= BINCMP_FLAG; } + | BINARY + { + Lex->charset= NULL; + Lex->type|= BINCMP_FLAG; + } + | BINARY charset charset_name + { + Lex->charset= $3; + Lex->type|= BINCMP_FLAG; + } ; opt_bin_mod: @@ -5685,20 +5830,6 @@ opt_bin_mod: | BINARY { Lex->type|= BINCMP_FLAG; } ; -opt_bin_charset: - /* empty */ { Lex->charset= NULL; } - | ASCII_SYM { Lex->charset=&my_charset_latin1; } - | UNICODE_SYM - { - if (!(Lex->charset=get_charset_by_csname("ucs2", - MY_CS_PRIMARY,MYF(0)))) - { - my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), "ucs2"); - MYSQL_YYABORT; - } - } - | charset charset_name { Lex->charset=$2; } - ; opt_primary: /* empty */ @@ -5706,21 +5837,20 @@ opt_primary: ; references: - REFERENCES table_ident - { - LEX *lex=Lex; - lex->fk_delete_opt= lex->fk_update_opt= lex->fk_match_option= 0; - lex->ref_list.empty(); - } + REFERENCES + table_ident opt_ref_list + opt_match_clause + opt_on_update_delete { $$=$2; } ; opt_ref_list: - /* empty */ opt_on_delete {} - | '(' ref_list ')' opt_on_delete {} + /* empty */ + { Lex->ref_list.empty(); } + | '(' ref_list ')' ; ref_list: @@ -5736,34 +5866,64 @@ ref_list: Key_part_spec *key= new Key_part_spec($1, 0); if (key == NULL) MYSQL_YYABORT; - Lex->ref_list.push_back(key); + LEX *lex= Lex; + lex->ref_list.empty(); + lex->ref_list.push_back(key); } ; -opt_on_delete: - /* empty */ {} - | opt_on_delete_list {} - ; - -opt_on_delete_list: - opt_on_delete_list opt_on_delete_item {} - | opt_on_delete_item {} +opt_match_clause: + /* empty */ + { Lex->fk_match_option= Foreign_key::FK_MATCH_UNDEF; } + | MATCH FULL + { Lex->fk_match_option= Foreign_key::FK_MATCH_FULL; } + | MATCH PARTIAL + { Lex->fk_match_option= Foreign_key::FK_MATCH_PARTIAL; } + | MATCH SIMPLE_SYM + { Lex->fk_match_option= Foreign_key::FK_MATCH_SIMPLE; } ; -opt_on_delete_item: - ON DELETE_SYM delete_option { Lex->fk_delete_opt= $3; } - | ON UPDATE_SYM delete_option { Lex->fk_update_opt= $3; } - | MATCH FULL { Lex->fk_match_option= Foreign_key::FK_MATCH_FULL; } - | MATCH PARTIAL { Lex->fk_match_option= Foreign_key::FK_MATCH_PARTIAL; } - | MATCH SIMPLE_SYM { Lex->fk_match_option= Foreign_key::FK_MATCH_SIMPLE; } +opt_on_update_delete: + /* empty */ + { + LEX *lex= Lex; + lex->fk_update_opt= Foreign_key::FK_OPTION_UNDEF; + lex->fk_delete_opt= Foreign_key::FK_OPTION_UNDEF; + } + | ON UPDATE_SYM delete_option + { + LEX *lex= Lex; + lex->fk_update_opt= $3; + lex->fk_delete_opt= Foreign_key::FK_OPTION_UNDEF; + } + | ON DELETE_SYM delete_option + { + LEX *lex= Lex; + lex->fk_update_opt= Foreign_key::FK_OPTION_UNDEF; + lex->fk_delete_opt= $3; + } + | ON UPDATE_SYM delete_option + ON DELETE_SYM delete_option + { + LEX *lex= Lex; + lex->fk_update_opt= $3; + lex->fk_delete_opt= $6; + } + | ON DELETE_SYM delete_option + ON UPDATE_SYM delete_option + { + LEX *lex= Lex; + lex->fk_update_opt= $6; + lex->fk_delete_opt= $3; + } ; delete_option: - RESTRICT { $$= (int) Foreign_key::FK_OPTION_RESTRICT; } - | CASCADE { $$= (int) Foreign_key::FK_OPTION_CASCADE; } - | SET NULL_SYM { $$= (int) Foreign_key::FK_OPTION_SET_NULL; } - | NO_SYM ACTION { $$= (int) Foreign_key::FK_OPTION_NO_ACTION; } - | SET DEFAULT { $$= (int) Foreign_key::FK_OPTION_DEFAULT; } + RESTRICT { $$= Foreign_key::FK_OPTION_RESTRICT; } + | CASCADE { $$= Foreign_key::FK_OPTION_CASCADE; } + | SET NULL_SYM { $$= Foreign_key::FK_OPTION_SET_NULL; } + | NO_SYM ACTION { $$= Foreign_key::FK_OPTION_NO_ACTION; } + | SET DEFAULT { $$= Foreign_key::FK_OPTION_DEFAULT; } ; normal_key_type: @@ -6629,28 +6789,6 @@ slave_until_opts: | slave_until_opts ',' master_file_def ; -restore: - RESTORE_SYM table_or_tables - { - Lex->sql_command = SQLCOM_RESTORE_TABLE; - } - table_list FROM TEXT_STRING_sys - { - Lex->backup_dir = $6.str; - } - ; - -backup: - BACKUP_SYM table_or_tables - { - Lex->sql_command = SQLCOM_BACKUP_TABLE; - } - table_list TO_SYM TEXT_STRING_sys - { - Lex->backup_dir = $6.str; - } - ; - checksum: CHECKSUM_SYM table_or_tables { @@ -6914,7 +7052,7 @@ cache_keys_spec: { Lex->select_lex.alloc_index_hints(YYTHD); Select->set_index_hint_type(INDEX_HINT_USE, - global_system_variables.old_mode ? + old_mode ? INDEX_HINT_MASK_JOIN : INDEX_HINT_MASK_ALL); } @@ -6954,37 +7092,22 @@ select_init: select_paren: SELECT_SYM select_part2 { - LEX *lex= Lex; - SELECT_LEX * sel= lex->current_select; - if (sel->set_braces(1)) - { - my_parse_error(ER(ER_SYNTAX_ERROR)); + if (setup_select_in_parentheses(Lex)) MYSQL_YYABORT; - } - if (sel->linkage == UNION_TYPE && - !sel->master_unit()->first_select()->braces && - sel->master_unit()->first_select()->linkage == - UNION_TYPE) - { - my_parse_error(ER(ER_SYNTAX_ERROR)); - MYSQL_YYABORT; - } - if (sel->linkage == UNION_TYPE && - sel->olap != UNSPECIFIED_OLAP_TYPE && - sel->master_unit()->fake_select_lex) - { - my_error(ER_WRONG_USAGE, MYF(0), - "CUBE/ROLLUP", "ORDER BY"); - MYSQL_YYABORT; - } - /* select in braces, can't contain global parameters */ - if (sel->master_unit()->fake_select_lex) - sel->master_unit()->global_parameters= - sel->master_unit()->fake_select_lex; } | '(' select_paren ')' ; +/* The equivalent of select_paren for nested queries. */ +select_paren_derived: + SELECT_SYM select_part2_derived + { + if (setup_select_in_parentheses(Lex)) + MYSQL_YYABORT; + } + | '(' select_paren_derived ')' + ; + select_init2: select_part2 { @@ -7061,50 +7184,63 @@ select_option_list: ; select_option: - STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; } - | HIGH_PRIORITY + query_expression_option + | SQL_NO_CACHE_SYM { - if (check_simple_select()) + /* + Allow this flag only on the first top-level SELECT statement, if + SQL_CACHE wasn't specified, and only once per query. + */ + if (Lex->current_select != &Lex->select_lex) + { + my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE"); MYSQL_YYABORT; - Lex->lock_option= TL_READ_HIGH_PRIORITY; - Lex->current_select->lock_option= TL_READ_HIGH_PRIORITY; - } - | DISTINCT { Select->options|= SELECT_DISTINCT; } - | SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; } - | SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; } - | SQL_BUFFER_RESULT - { - if (check_simple_select()) + } + else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE) + { + my_error(ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE"); MYSQL_YYABORT; - Select->options|= OPTION_BUFFER_RESULT; - } - | SQL_CALC_FOUND_ROWS - { - if (check_simple_select()) + } + else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE) + { + my_error(ER_DUP_ARGUMENT, MYF(0), "SQL_NO_CACHE"); MYSQL_YYABORT; - Select->options|= OPTION_FOUND_ROWS; - } - | SQL_NO_CACHE_SYM - { - Lex->safe_to_cache_query=0; - Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE; - Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE; + } + else + { + Lex->safe_to_cache_query=0; + Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE; + Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE; + } } | SQL_CACHE_SYM { - /* - Honor this flag only if SQL_NO_CACHE wasn't specified AND - we are parsing the outermost SELECT in the query. - */ - if (Lex->select_lex.sql_cache != SELECT_LEX::SQL_NO_CACHE && - Lex->current_select == &Lex->select_lex) + /* + Allow this flag only on the first top-level SELECT statement, if + SQL_NO_CACHE wasn't specified, and only once per query. + */ + if (Lex->current_select != &Lex->select_lex) + { + my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE"); + MYSQL_YYABORT; + } + else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE) + { + my_error(ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE"); + MYSQL_YYABORT; + } + else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE) + { + my_error(ER_DUP_ARGUMENT, MYF(0), "SQL_CACHE"); + MYSQL_YYABORT; + } + else { Lex->safe_to_cache_query=1; Lex->select_lex.options|= OPTION_TO_QUERY_CACHE; Lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE; } } - | ALL { Select->options|= SELECT_ALL; } ; select_lock_type: @@ -7145,7 +7281,14 @@ select_item_list: ; select_item: - remember_name select_item2 remember_end select_alias + remember_name table_wild remember_end + { + THD *thd= YYTHD; + + if (add_item_to_list(thd, $2)) + MYSQL_YYABORT; + } + | remember_name expr remember_end select_alias { THD *thd= YYTHD; DBUG_ASSERT($1 < $3); @@ -7182,11 +7325,6 @@ remember_end: } ; -select_item2: - table_wild { $$=$1; /* table.* */ } - | expr { $$=$1; } - ; - select_alias: /* empty */ { $$=null_lex_str;} | AS ident { $$=$2; } @@ -7787,7 +7925,7 @@ function_call_keyword: $$= new (YYTHD->mem_root) Item_func_current_user(Lex->current_context()); if ($$ == NULL) MYSQL_YYABORT; - Lex->set_stmt_unsafe(); + Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); Lex->safe_to_cache_query= 0; } | DATE_SYM '(' expr ')' @@ -7942,7 +8080,7 @@ function_call_keyword: $$= new (YYTHD->mem_root) Item_func_user(); if ($$ == NULL) MYSQL_YYABORT; - Lex->set_stmt_unsafe(); + Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); Lex->safe_to_cache_query=0; } | YEAR_SYM '(' expr ')' @@ -8092,7 +8230,7 @@ function_call_nonkeyword: sysdate_is_now=1, because the slave may have sysdate_is_now=0. */ - Lex->set_stmt_unsafe(); + Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION); if (global_system_variables.sysdate_is_now == 0) $$= new (YYTHD->mem_root) Item_func_sysdate_local(); else @@ -8686,7 +8824,7 @@ variable_aux: if (!($$= get_system_var(YYTHD, $2, $3, $4))) MYSQL_YYABORT; if (!((Item_func_get_system_var*) $$)->is_written_to_binlog()) - Lex->set_stmt_unsafe(); + Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_VARIABLE); } ; @@ -8831,6 +8969,7 @@ when_list: } ; +/* Equivalent to <table reference> in the SQL:2003 standard. */ /* Warning - may return NULL in case of incomplete SELECT */ table_ref: table_factor { $$=$1; } @@ -8858,6 +8997,7 @@ esc_table_ref: | '{' ident table_ref '}' { $$=$3; } ; +/* Equivalent to <table reference list> in the SQL:2003 standard. */ /* Warning - may return NULL in case of incomplete SELECT */ derived_table_list: esc_table_ref { $$=$1; } @@ -9011,6 +9151,13 @@ normal_join: | CROSS JOIN_SYM {} ; +/* + This is a flattening of the rules <table factor> and <table primary> + in the SQL:2003 standard, since we don't have <sample clause> + + I.e. + <table factor> ::= <table primary> [ <sample clause> ] +*/ /* Warning - may return NULL in case of incomplete SELECT */ table_factor: { @@ -9048,12 +9195,29 @@ table_factor: /* incomplete derived tables return NULL, we must be nested in select_derived rule to be here. */ } - | '(' get_select_lex select_derived union_opt ')' opt_table_alias + /* + Represents a flattening of the following rules from the SQL:2003 + standard. This sub-rule corresponds to the sub-rule + <table primary> ::= ... | <derived table> [ AS ] <correlation name> + + The following rules have been flattened into query_expression_body + (since we have no <with clause>). + + <derived table> ::= <table subquery> + <table subquery> ::= <subquery> + <subquery> ::= <left paren> <query expression> <right paren> + <query expression> ::= [ <with clause> ] <query expression body> + + For the time being we use the non-standard rule + select_derived_union which is a compromise between the standard + and our parser. Possibly this rule could be replaced by our + query_expression_body. + */ + | '(' get_select_lex select_derived_union ')' opt_table_alias { /* Use $2 instead of Lex->current_select as derived table will alter value of Lex->current_select. */ - - if (!($3 || $6) && $2->embedding && + if (!($3 || $5) && $2->embedding && !$2->embedding->nested_join->join_list.elements) { /* we have a derived table ($3 == NULL) but no alias, @@ -9075,7 +9239,7 @@ table_factor: if (ti == NULL) MYSQL_YYABORT; if (!($$= sel->add_table_to_list(lex->thd, - ti, $6, 0, + new Table_ident(unit), $5, 0, TL_READ))) MYSQL_YYABORT; @@ -9083,7 +9247,8 @@ table_factor: lex->pop_context(); lex->nest_level--; } - else if ($4 || $6) + else if (($3->select_lex && + $3->select_lex->master_unit()->is_union()) || $5) { /* simple nested joins cannot have aliases or unions */ my_parse_error(ER(ER_SYNTAX_ERROR)); @@ -9098,6 +9263,62 @@ table_factor: } ; +select_derived_union: + select_derived opt_order_clause opt_limit_clause + | select_derived_union + UNION_SYM + union_option + { + if (add_select_to_union_list(Lex, (bool)$3, FALSE)) + MYSQL_YYABORT; + } + query_specification + { + /* + Remove from the name resolution context stack the context of the + last select in the union. + */ + Lex->pop_context(); + } + opt_order_clause opt_limit_clause + ; + +/* The equivalent of select_init2 for nested queries. */ +select_init2_derived: + select_part2_derived + { + LEX *lex= Lex; + SELECT_LEX * sel= lex->current_select; + if (lex->current_select->set_braces(0)) + { + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; + } + if (sel->linkage == UNION_TYPE && + sel->master_unit()->first_select()->braces) + { + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; + } + } + ; + +/* The equivalent of select_part2 for nested queries. */ +select_part2_derived: + { + LEX *lex= Lex; + SELECT_LEX *sel= lex->current_select; + if (sel->linkage != UNION_TYPE) + mysql_init_select(lex); + lex->current_select->parsing_place= SELECT_LIST; + } + opt_query_expression_options select_item_list + { + Select->parsing_place= NO_MATTER; + } + opt_select_from select_lock_type + ; + /* handle contents of parentheses in join expression */ select_derived: get_select_lex @@ -9184,8 +9405,7 @@ opt_outer: index_hint_clause: /* empty */ { - $$= global_system_variables.old_mode ? - INDEX_HINT_MASK_JOIN : INDEX_HINT_MASK_ALL; + $$= old_mode ? INDEX_HINT_MASK_JOIN : INDEX_HINT_MASK_ALL; } | FOR_SYM JOIN_SYM { $$= INDEX_HINT_MASK_JOIN; } | FOR_SYM ORDER_SYM BY { $$= INDEX_HINT_MASK_ORDER; } @@ -9282,24 +9502,25 @@ interval: ; interval_time_stamp: - interval_time_st {} - | FRAC_SECOND_SYM { - $$=INTERVAL_MICROSECOND; - /* - FRAC_SECOND was mistakenly implemented with - a wrong resolution. According to the ODBC - standard it should be nanoseconds, not - microseconds. Changing it to nanoseconds - in MySQL would mean making TIMESTAMPDIFF - and TIMESTAMPADD to return DECIMAL, since - the return value would be too big for BIGINT - Hence we just deprecate the incorrect - implementation without changing its - resolution. - */ - WARN_DEPRECATED(yythd, VER_CELOSIA, "FRAC_SECOND", "MICROSECOND"); - } - ; + interval_time_st {} + | FRAC_SECOND_SYM + { + $$=INTERVAL_MICROSECOND; + /* + FRAC_SECOND was mistakenly implemented with + a wrong resolution. According to the ODBC + standard it should be nanoseconds, not + microseconds. Changing it to nanoseconds + in MySQL would mean making TIMESTAMPDIFF + and TIMESTAMPADD to return DECIMAL, since + the return value would be too big for BIGINT + Hence we just deprecate the incorrect + implementation without changing its + resolution. + */ + WARN_DEPRECATED(yythd, 6, 2, "FRAC_SECOND", "MICROSECOND"); + } + ; interval_time_st: DAY_SYM { $$=INTERVAL_DAY; } @@ -9409,8 +9630,15 @@ group_list: olap_opt: /* empty */ {} - | WITH CUBE_SYM + | WITH_CUBE_SYM { + /* + 'WITH CUBE' is reserved in the MySQL syntax, but not implemented, + and cause LALR(2) conflicts. + This syntax is not standard. + MySQL syntax: GROUP BY col1, col2, col3 WITH CUBE + SQL-2003: GROUP BY ... CUBE(col1, col2, col3) + */ LEX *lex=Lex; if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE) { @@ -9420,10 +9648,17 @@ olap_opt: } lex->current_select->olap= CUBE_TYPE; my_error(ER_NOT_SUPPORTED_YET, MYF(0), "CUBE"); - MYSQL_YYABORT; /* To be deleted in 5.1 */ + MYSQL_YYABORT; } - | WITH ROLLUP_SYM + | WITH_ROLLUP_SYM { + /* + 'WITH ROLLUP' is needed for backward compatibility, + and cause LALR(2) conflicts. + This syntax is not standard. + MySQL syntax: GROUP BY col1, col2, col3 WITH ROLLUP + SQL-2003: GROUP BY ... ROLLUP(col1, col2, col3) + */ LEX *lex= Lex; if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE) { @@ -9532,7 +9767,10 @@ opt_limit_clause: ; limit_clause: - LIMIT limit_options {} + LIMIT limit_options + { + Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT); + } ; limit_options: @@ -9594,6 +9832,7 @@ delete_limit_clause: { SELECT_LEX *sel= Select; sel->select_limit= $2; + Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_LIMIT); sel->explicit_limit= 1; } ; @@ -9697,8 +9936,7 @@ procedure_item: select_var_list_init: { LEX *lex=Lex; - if (!lex->describe && - (!(lex->result= new select_dumpvar(lex->nest_level)))) + if (!lex->describe && (!(lex->result= new select_dumpvar()))) MYSQL_YYABORT; } select_var_list @@ -9779,7 +10017,7 @@ into_destination: LEX *lex= Lex; lex->uncacheable(UNCACHEABLE_SIDEEFFECT); if (!(lex->exchange= new sql_exchange($2.str, 0)) || - !(lex->result= new select_export(lex->exchange, lex->nest_level))) + !(lex->result= new select_export(lex->exchange))) MYSQL_YYABORT; } opt_load_data_charset @@ -9793,7 +10031,7 @@ into_destination: lex->uncacheable(UNCACHEABLE_SIDEEFFECT); if (!(lex->exchange= new sql_exchange($2.str,1))) MYSQL_YYABORT; - if (!(lex->result= new select_dump(lex->exchange, lex->nest_level))) + if (!(lex->result= new select_dump(lex->exchange))) MYSQL_YYABORT; } } @@ -10044,13 +10282,21 @@ insert_lock_option: #endif } | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; } - | DELAYED_SYM { $$= TL_WRITE_DELAYED; } + | DELAYED_SYM + { + $$= TL_WRITE_DELAYED; + Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_DELAYED); + } | HIGH_PRIORITY { $$= TL_WRITE; } ; replace_lock_option: opt_low_priority { $$= $1; } - | DELAYED_SYM { $$= TL_WRITE_DELAYED; } + | DELAYED_SYM + { + $$= TL_WRITE_DELAYED; + Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_DELAYED); + } ; insert2: @@ -10254,7 +10500,7 @@ delete: lex->ignore= 0; lex->select_lex.init_order(); } - opt_delete_options single_multi {} + opt_delete_options single_multi ; single_multi: @@ -10269,45 +10515,45 @@ single_multi: | table_wild_list { mysql_init_multi_delete(Lex); } FROM join_table_list where_clause - { + { if (multi_delete_set_locks_and_link_aux_tables(Lex)) MYSQL_YYABORT; } | FROM table_alias_ref_list { mysql_init_multi_delete(Lex); } USING join_table_list where_clause - { + { if (multi_delete_set_locks_and_link_aux_tables(Lex)) MYSQL_YYABORT; } ; table_wild_list: - table_wild_one {} - | table_wild_list ',' table_wild_one {} + table_wild_one + | table_wild_list ',' table_wild_one ; table_wild_one: - ident opt_wild opt_table_alias + ident opt_wild { Table_ident *ti= new Table_ident($1); if (ti == NULL) MYSQL_YYABORT; if (!Select->add_table_to_list(YYTHD, ti, - $3, + NULL, TL_OPTION_UPDATING | TL_OPTION_ALIAS, Lex->lock_option)) MYSQL_YYABORT; } - | ident '.' ident opt_wild opt_table_alias + | ident '.' ident opt_wild { Table_ident *ti= new Table_ident(YYTHD, $1, $3, 0); if (ti == NULL) MYSQL_YYABORT; if (!Select->add_table_to_list(YYTHD, ti, - $5, + NULL, TL_OPTION_UPDATING | TL_OPTION_ALIAS, Lex->lock_option)) MYSQL_YYABORT; @@ -10469,14 +10715,6 @@ show_param: if (prepare_schema_table(YYTHD, lex, 0, SCH_OPEN_TABLES)) MYSQL_YYABORT; } - | opt_full PLUGIN_SYM - { - LEX *lex= Lex; - WARN_DEPRECATED(yythd, "6.0", "SHOW PLUGIN", "'SHOW PLUGINS'"); - lex->sql_command= SQLCOM_SHOW_PLUGINS; - if (prepare_schema_table(YYTHD, lex, 0, SCH_PLUGINS)) - MYSQL_YYABORT; - } | PLUGINS_SYM { LEX *lex= Lex; @@ -10537,14 +10775,6 @@ show_param: if (prepare_schema_table(YYTHD, lex, $3, SCH_STATISTICS)) MYSQL_YYABORT; } - | TABLE_SYM TYPES_SYM - { - LEX *lex=Lex; - lex->sql_command= SQLCOM_SHOW_STORAGE_ENGINES; - WARN_DEPRECATED(yythd, "6.0", "SHOW TABLE TYPES", "'SHOW [STORAGE] ENGINES'"); - if (prepare_schema_table(YYTHD, lex, 0, SCH_ENGINES)) - MYSQL_YYABORT; - } | opt_storage ENGINES_SYM { LEX *lex=Lex; @@ -10592,30 +10822,6 @@ show_param: if (prepare_schema_table(YYTHD, lex, 0, SCH_STATUS)) MYSQL_YYABORT; } - | INNOBASE_SYM STATUS_SYM - { - LEX *lex= Lex; - lex->sql_command = SQLCOM_SHOW_ENGINE_STATUS; - if (!(lex->create_info.db_type= - ha_resolve_by_legacy_type(YYTHD, DB_TYPE_INNODB))) - { - my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), "InnoDB"); - MYSQL_YYABORT; - } - WARN_DEPRECATED(yythd, "6.0", "SHOW INNODB STATUS", "'SHOW ENGINE INNODB STATUS'"); - } - | MUTEX_SYM STATUS_SYM - { - LEX *lex= Lex; - lex->sql_command = SQLCOM_SHOW_ENGINE_MUTEX; - if (!(lex->create_info.db_type= - ha_resolve_by_legacy_type(YYTHD, DB_TYPE_INNODB))) - { - my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), "InnoDB"); - MYSQL_YYABORT; - } - WARN_DEPRECATED(yythd, "6.0", "SHOW MUTEX STATUS", "'SHOW ENGINE INNODB MUTEX'"); - } | opt_full PROCESSLIST_SYM { Lex->sql_command= SQLCOM_SHOW_PROCESSLIST;} | opt_var_type VARIABLES wild_and_where @@ -10874,6 +11080,18 @@ flush_option: opt_table_list {} | TABLES WITH READ_SYM LOCK_SYM { Lex->type|= REFRESH_TABLES | REFRESH_READ_LOCK; } + | ERROR_SYM LOGS_SYM + { Lex->type|= REFRESH_ERROR_LOG; } + | ENGINE_SYM LOGS_SYM + { Lex->type|= REFRESH_ENGINE_LOG; } + | GENERAL LOGS_SYM + { Lex->type|= REFRESH_GENERAL_LOG; } + | SLOW LOGS_SYM + { Lex->type|= REFRESH_SLOW_LOG; } + | BINARY LOGS_SYM + { Lex->type|= REFRESH_BINARY_LOG; } + | RELAY LOGS_SYM + { Lex->type|= REFRESH_RELAY_LOG; } | QUERY_SYM CACHE_SYM { Lex->type|= REFRESH_QUERY_CACHE_FREE; } | HOSTS_SYM @@ -11020,36 +11238,7 @@ load: opt_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec opt_load_data_set_spec {} - | LOAD TABLE_SYM table_ident FROM MASTER_SYM - { - LEX *lex=Lex; - WARN_DEPRECATED(yythd, "6.0", "LOAD TABLE FROM MASTER", - "MySQL Administrator (mysqldump, mysql)"); - if (lex->sphead) - { - my_error(ER_SP_BADSTATEMENT, MYF(0), "LOAD TABLE"); - MYSQL_YYABORT; - } - lex->sql_command = SQLCOM_LOAD_MASTER_TABLE; - if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING)) - MYSQL_YYABORT; - } - | LOAD DATA_SYM FROM MASTER_SYM - { - THD *thd= YYTHD; - LEX *lex= thd->lex; - - if (lex->sphead) - { - my_error(ER_SP_BADSTATEMENT, MYF(0), "LOAD DATA"); - MYSQL_YYABORT; - } - Lex->sql_command = SQLCOM_LOAD_MASTER_DATA; - WARN_DEPRECATED(yythd, "6.0", "LOAD DATA FROM MASTER", - "mysqldump or future " - "BACKUP/RESTORE DATABASE facility"); - } - ; + ; data_or_xml: DATA_SYM { $$= FILETYPE_CSV; } @@ -12052,6 +12241,7 @@ keyword_sp: | ENUM {} | ENGINE_SYM {} | ENGINES_SYM {} + | ERROR_SYM {} | ERRORS {} | ESCAPE_SYM {} | EVENT_SYM {} @@ -12086,7 +12276,6 @@ keyword_sp: | IPC_SYM {} | ISOLATION {} | ISSUER_SYM {} - | INNOBASE_SYM {} | INSERT_METHOD {} | KEY_BLOCK_SIZE {} | LAST_SYM {} @@ -12178,6 +12367,7 @@ keyword_sp: | REDO_BUFFER_SIZE_SYM {} | REDOFILE_SYM {} | REDUNDANT_SYM {} + | RELAY {} | RELAYLOG_SYM {} | RELAY_LOG_FILE_SYM {} | RELAY_LOG_POS_SYM {} @@ -13357,33 +13547,8 @@ union_clause: union_list: UNION_SYM union_option { - LEX *lex=Lex; - if (lex->result && - (lex->result->get_nest_level() == -1 || - lex->result->get_nest_level() == lex->nest_level)) - { - /* - Only the last SELECT can have INTO unless the INTO and UNION - are at different nest levels. In version 5.1 and above, INTO - will onle be allowed at top level. - */ - my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO"); - MYSQL_YYABORT; - } - if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE) - { - my_parse_error(ER(ER_SYNTAX_ERROR)); - MYSQL_YYABORT; - } - /* This counter shouldn't be incremented for UNION parts */ - Lex->nest_level--; - if (mysql_new_select(lex, 0)) + if (add_select_to_union_list(Lex, (bool)$2, TRUE)) MYSQL_YYABORT; - mysql_init_select(lex); - lex->current_select->linkage=UNION_TYPE; - if ($2) /* UNION DISTINCT - remember position */ - lex->current_select->master_unit()->union_distinct= - lex->current_select; } select_init { @@ -13436,22 +13601,39 @@ union_option: | ALL { $$=0; } ; -take_first_select: /* empty */ - { - $$= Lex->current_select->master_unit()->first_select(); - }; +query_specification: + SELECT_SYM select_init2_derived + { + $$= Lex->current_select->master_unit()->first_select(); + } + | '(' select_paren_derived ')' + { + $$= Lex->current_select->master_unit()->first_select(); + } + ; + +query_expression_body: + query_specification + | query_expression_body + UNION_SYM union_option + { + if (add_select_to_union_list(Lex, (bool)$3, FALSE)) + MYSQL_YYABORT; + } + query_specification + { + Lex->pop_context(); + $$= $1; + } + ; +/* Corresponds to <query expression> in the SQL:2003 standard. */ subselect: - SELECT_SYM subselect_start select_init2 take_first_select - subselect_end - { - $$= $4; - } - | '(' subselect_start select_paren take_first_select - subselect_end ')' - { - $$= $4; - }; + subselect_start query_expression_body subselect_end + { + $$= $2; + } + ; subselect_start: { @@ -13503,6 +13685,43 @@ subselect_end: } ; +opt_query_expression_options: + /* empty */ + | query_expression_option_list + ; + +query_expression_option_list: + query_expression_option_list query_expression_option + | query_expression_option + ; + +query_expression_option: + STRAIGHT_JOIN { Select->options|= SELECT_STRAIGHT_JOIN; } + | HIGH_PRIORITY + { + if (check_simple_select()) + MYSQL_YYABORT; + Lex->lock_option= TL_READ_HIGH_PRIORITY; + Lex->current_select->lock_option= TL_READ_HIGH_PRIORITY; + } + | DISTINCT { Select->options|= SELECT_DISTINCT; } + | SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; } + | SQL_BIG_RESULT { Select->options|= SELECT_BIG_RESULT; } + | SQL_BUFFER_RESULT + { + if (check_simple_select()) + MYSQL_YYABORT; + Select->options|= OPTION_BUFFER_RESULT; + } + | SQL_CALC_FOUND_ROWS + { + if (check_simple_select()) + MYSQL_YYABORT; + Select->options|= OPTION_FOUND_ROWS; + } + | ALL { Select->options|= SELECT_ALL; } + ; + /************************************************************************** CREATE VIEW | TRIGGER | PROCEDURE statements. @@ -13850,7 +14069,7 @@ sf_tail: lex->interval_list.empty(); lex->type= 0; } - type /* $11 */ + type_with_opt_collate /* $11 */ { /* $12 */ LEX *lex= Lex; sp_head *sp= lex->sphead; diff --git a/sql/strfunc.cc b/sql/strfunc.cc index 56fa4a380ea..d7ab102b225 100644 --- a/sql/strfunc.cc +++ b/sql/strfunc.cc @@ -45,6 +45,7 @@ ulonglong find_set(TYPELIB *lib, const char *str, uint length, CHARSET_INFO *cs, const char *end= str + strip->cset->lengthsp(strip, str, length); ulonglong found= 0; *err_pos= 0; // No error yet + *err_len= 0; if (str != end) { const char *start= str; @@ -71,7 +72,7 @@ ulonglong find_set(TYPELIB *lib, const char *str, uint length, CHARSET_INFO *cs, var_len= (uint) (pos - start); uint find= cs ? find_type2(lib, start, var_len, cs) : find_type(lib, start, var_len, (bool) 0); - if (!find) + if (!find && *err_len == 0) // report the first error with length > 0 { *err_pos= (char*) start; *err_len= var_len; @@ -87,209 +88,6 @@ ulonglong find_set(TYPELIB *lib, const char *str, uint length, CHARSET_INFO *cs, return found; } - -static const char *on_off_default_names[]= -{ - "off","on","default", NullS -}; - -static const unsigned int on_off_default_names_len[]= -{ - sizeof("off") - 1, - sizeof("on") - 1, - sizeof("default") - 1 -}; - -static TYPELIB on_off_default_typelib= {array_elements(on_off_default_names)-1, - "", on_off_default_names, - (unsigned int *)on_off_default_names_len}; - - -/* - Parse a TYPELIB name from the buffer - - SYNOPSIS - parse_name() - lib Set of names to scan for. - strpos INOUT Start of the buffer (updated to point to the next - character after the name) - end End of the buffer - cs Charset used in the buffer - - DESCRIPTION - Parse a TYPELIB name from the buffer. The buffer is assumed to contain - one of the names specified in the TYPELIB, followed by comma, '=', or - end of the buffer. - - RETURN - 0 No matching name - >0 Offset+1 in typelib for matched name -*/ - -static uint parse_name(TYPELIB *lib, const char **strpos, const char *end, - CHARSET_INFO *cs) -{ - const char *pos= *strpos; - const char *start= pos; - - /* Find the length */ - if (cs && cs->mbminlen > 1) - { - int mblen= 0; - for ( ; pos < end; pos+= mblen) - { - my_wc_t wc; - if ((mblen= cs->cset->mb_wc(cs, &wc, (const uchar *) pos, - (const uchar *) end)) < 1) - mblen= 1; // Not to hang on a wrong multibyte sequence - if (wc == (my_wc_t) '=' || wc == (my_wc_t) ',') - break; - } - } - else - for (; pos != end && *pos != '=' && *pos !=',' ; pos++) ; - - uint var_len= (uint) (pos - start); - /* Determine which flag it is */ - uint find= cs ? find_type2(lib, start, var_len, cs) : - find_type(lib, start, var_len, (bool) 0); - *strpos= pos; - return find; -} - - -/* Read next character from the buffer in a charset-aware way */ - -static my_wc_t get_next_char(const char **pos, const char *end, CHARSET_INFO *cs) -{ - my_wc_t wc; - if (*pos == end) - return (my_wc_t)-1; - - if (cs && cs->mbminlen > 1) - { - int mblen; - if ((mblen= cs->cset->mb_wc(cs, &wc, (const uchar *) *pos, - (const uchar *) end)) < 1) - mblen= 1; // Not to hang on a wrong multibyte sequence - *pos += mblen; - return wc; - } - else - return *((*pos)++); -} - - -/* - Parse and apply a set of flag assingments - - SYNOPSIS - find_set_from_flags() - lib Flag names - default_name Number of "default" in the typelib - cur_set Current set of flags (start from this state) - default_set Default set of flags (use this for assign-default - keyword and flag=default assignments) - str String to be parsed - length Length of the string - cs String charset - err_pos OUT If error, set to point to start of wrong set string - NULL on success - err_len OUT If error, set to the length of wrong set string - set_warning OUT TRUE <=> Some string in set couldn't be used - - DESCRIPTION - Parse a set of flag assignments, that is, parse a string in form: - - param_name1=value1,param_name2=value2,... - - where the names are specified in the TYPELIB, and each value can be - either 'on','off', or 'default'. Setting the same name twice is not - allowed. - - Besides param=val assignments, we support the "default" keyword (keyword - #default_name in the typelib). It can be used one time, if specified it - causes us to build the new set over the default_set rather than cur_set - value. - - RETURN - Parsed set value if (*errpos == NULL) - Otherwise undefined -*/ - -ulonglong find_set_from_flags(TYPELIB *lib, uint default_name, - ulonglong cur_set, ulonglong default_set, - const char *str, uint length, CHARSET_INFO *cs, - char **err_pos, uint *err_len, bool *set_warning) -{ - CHARSET_INFO *strip= cs ? cs : &my_charset_latin1; - const char *end= str + strip->cset->lengthsp(strip, str, length); - ulonglong flags_to_set= 0, flags_to_clear= 0; - bool set_defaults= 0; - *err_pos= 0; // No error yet - if (str != end) - { - const char *start= str; - for (;;) - { - const char *pos= start; - uint flag_no, value; - - if (!(flag_no= parse_name(lib, &pos, end, cs))) - goto err; - - if (flag_no == default_name) - { - /* Using 'default' twice isn't allowed. */ - if (set_defaults) - goto err; - set_defaults= TRUE; - } - else - { - ulonglong bit= ((longlong) 1 << (flag_no - 1)); - /* parse the '=on|off|default' */ - if ((flags_to_clear | flags_to_set) & bit || - get_next_char(&pos, end, cs) != '=' || - !(value= parse_name(&on_off_default_typelib, &pos, end, cs))) - { - goto err; - } - - if (value == 1) // this is '=off' - flags_to_clear|= bit; - else if (value == 2) // this is '=on' - flags_to_set|= bit; - else // this is '=default' - { - if (default_set & bit) - flags_to_set|= bit; - else - flags_to_clear|= bit; - } - } - if (pos >= end) - break; - - if (get_next_char(&pos, end, cs) != ',') - goto err; - - start=pos; - continue; - err: - *err_pos= (char*)start; - *err_len= end - start; - *set_warning= TRUE; - break; - } - } - ulonglong res= set_defaults? default_set : cur_set; - res|= flags_to_set; - res&= ~flags_to_clear; - return res; -} - - /* Function to find a string in a TYPELIB (Same format as mysys/typelib.c) @@ -543,3 +341,60 @@ int find_string_in_array(LEX_STRING * const haystack, LEX_STRING * const needle, } return -1; } + + +char *set_to_string(THD *thd, LEX_STRING *result, ulonglong set, + const char *lib[]) +{ + char buff[STRING_BUFFER_USUAL_SIZE*8]; + String tmp(buff, sizeof(buff), &my_charset_latin1); + LEX_STRING unused; + + if (!result) + result= &unused; + + tmp.length(0); + + for (uint i= 0; set; i++, set >>= 1) + if (set & 1) { + tmp.append(lib[i]); + tmp.append(','); + } + + if (tmp.length()) + { + result->str= thd->strmake(tmp.ptr(), tmp.length()-1); + result->length= tmp.length()-1; + } + else + { + result->str= const_cast<char*>(""); + result->length= 0; + } + return result->str; +} + +char *flagset_to_string(THD *thd, LEX_STRING *result, ulonglong set, + const char *lib[]) +{ + char buff[STRING_BUFFER_USUAL_SIZE*8]; + String tmp(buff, sizeof(buff), &my_charset_latin1); + LEX_STRING unused; + + if (!result) result= &unused; + + tmp.length(0); + + // note that the last element is always "default", and it's ignored below + for (uint i= 0; lib[i+1]; i++, set >>= 1) + { + tmp.append(lib[i]); + tmp.append(set & 1 ? "=on," : "=off,"); + } + + result->str= thd->strmake(tmp.ptr(), tmp.length()-1); + result->length= tmp.length()-1; + + return result->str; +} + diff --git a/sql/structs.h b/sql/structs.h index 33b7148c4b3..041a6809804 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -142,8 +142,6 @@ typedef struct st_known_date_time_format { const char *time_format; } KNOWN_DATE_TIME_FORMAT; -enum SHOW_COMP_OPTION { SHOW_OPTION_YES, SHOW_OPTION_NO, SHOW_OPTION_DISABLED}; - extern const char *show_comp_option_name[]; typedef int *(*update_var)(THD *, struct st_mysql_show_var *); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc new file mode 100644 index 00000000000..54e6fdb1d74 --- /dev/null +++ b/sql/sys_vars.cc @@ -0,0 +1,2973 @@ +/* Copyright (C) 2002-2006 MySQL AB, 2009-2010 Sun Microsystems, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + How to add new variables: + + 1. copy one of the existing variables, and edit the declaration. + 2. if you need special behavior on assignment or additional checks + use ON_CHECK and ON_UPDATE callbacks. + 3. *Don't* add new Sys_var classes or uncle Occam will come + with his razor to haunt you at nights + + Note - all storage engine variables (for example myisam_whatever) + should go into the corresponding storage engine sources + (for example in storage/myisam/ha_myisam.cc) ! +*/ + +#include "sys_vars.h" + +#include "events.h" +#include <thr_alarm.h> +#include "slave.h" +#include "rpl_mi.h" + +#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE +#include "../storage/perfschema/pfs_server.h" +#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */ + +/* + The rule for this file: everything should be 'static'. When a sys_var + variable or a function from this file is - in very rare cases - needed + elsewhere it should be explicitly declared 'export' here to show that it's + not a mistakenly forgotten 'static' keyword. +*/ +#define export /* not static */ + +#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE + +#define PFS_TRAILING_PROPERTIES \ + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(NULL), ON_UPDATE(NULL), \ + 0, NULL, sys_var::PARSE_EARLY + +static Sys_var_mybool Sys_pfs_enabled( + "performance_schema", + "Enable the performance schema.", + READ_ONLY GLOBAL_VAR(pfs_param.m_enabled), + CMD_LINE(OPT_ARG), DEFAULT(FALSE), + PFS_TRAILING_PROPERTIES); + +static Sys_var_ulong Sys_pfs_events_waits_history_long_size( + "performance_schema_events_waits_history_long_size", + "Number of rows in EVENTS_WAITS_HISTORY_LONG.", + READ_ONLY GLOBAL_VAR(pfs_param.m_events_waits_history_long_sizing), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024*1024), + DEFAULT(PFS_WAITS_HISTORY_LONG_SIZE), + BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES); + +static Sys_var_ulong Sys_pfs_events_waits_history_size( + "performance_schema_events_waits_history_size", + "Number of rows per thread in EVENTS_WAITS_HISTORY.", + READ_ONLY GLOBAL_VAR(pfs_param.m_events_waits_history_sizing), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024), + DEFAULT(PFS_WAITS_HISTORY_SIZE), + BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES); + +static Sys_var_ulong Sys_pfs_max_cond_classes( + "performance_schema_max_cond_classes", + "Maximum number of condition instruments.", + READ_ONLY GLOBAL_VAR(pfs_param.m_cond_class_sizing), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 256), + DEFAULT(PFS_MAX_COND_CLASS), + BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES); + +static Sys_var_ulong Sys_pfs_max_cond_instances( + "performance_schema_max_cond_instances", + "Maximum number of instrumented condition objects.", + READ_ONLY GLOBAL_VAR(pfs_param.m_cond_sizing), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024*1024), + DEFAULT(PFS_MAX_COND), + BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES); + +static Sys_var_ulong Sys_pfs_max_file_classes( + "performance_schema_max_file_classes", + "Maximum number of file instruments.", + READ_ONLY GLOBAL_VAR(pfs_param.m_file_class_sizing), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 256), + DEFAULT(PFS_MAX_FILE_CLASS), + BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES); + +static Sys_var_ulong Sys_pfs_max_file_handles( + "performance_schema_max_file_handles", + "Maximum number of opened instrumented files.", + READ_ONLY GLOBAL_VAR(pfs_param.m_file_handle_sizing), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024*1024), + DEFAULT(PFS_MAX_FILE_HANDLE), + BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES); + +static Sys_var_ulong Sys_pfs_max_file_instances( + "performance_schema_max_file_instances", + "Maximum number of instrumented files.", + READ_ONLY GLOBAL_VAR(pfs_param.m_file_sizing), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024*1024), + DEFAULT(PFS_MAX_FILE), + BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES); + +static Sys_var_ulong Sys_pfs_max_mutex_classes( + "performance_schema_max_mutex_classes", + "Maximum number of mutex instruments.", + READ_ONLY GLOBAL_VAR(pfs_param.m_mutex_class_sizing), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 256), + DEFAULT(PFS_MAX_MUTEX_CLASS), + BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES); + +static Sys_var_ulong Sys_pfs_max_mutex_instances( + "performance_schema_max_mutex_instances", + "Maximum number of instrumented MUTEX objects.", + READ_ONLY GLOBAL_VAR(pfs_param.m_mutex_sizing), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024*1024), + DEFAULT(PFS_MAX_MUTEX), + BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES); + +static Sys_var_ulong Sys_pfs_max_rwlock_classes( + "performance_schema_max_rwlock_classes", + "Maximum number of rwlock instruments.", + READ_ONLY GLOBAL_VAR(pfs_param.m_rwlock_class_sizing), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 256), + DEFAULT(PFS_MAX_RWLOCK_CLASS), + BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES); + +static Sys_var_ulong Sys_pfs_max_rwlock_instances( + "performance_schema_max_rwlock_instances", + "Maximum number of instrumented RWLOCK objects.", + READ_ONLY GLOBAL_VAR(pfs_param.m_rwlock_sizing), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024*1024), + DEFAULT(PFS_MAX_RWLOCK), + BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES); + +static Sys_var_ulong Sys_pfs_max_table_handles( + "performance_schema_max_table_handles", + "Maximum number of opened instrumented tables.", + READ_ONLY GLOBAL_VAR(pfs_param.m_table_sizing), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024*1024), + DEFAULT(PFS_MAX_TABLE), + BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES); + +static Sys_var_ulong Sys_pfs_max_table_instances( + "performance_schema_max_table_instances", + "Maximum number of instrumented tables.", + READ_ONLY GLOBAL_VAR(pfs_param.m_table_share_sizing), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024*1024), + DEFAULT(PFS_MAX_TABLE_SHARE), + BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES); + +static Sys_var_ulong Sys_pfs_max_thread_classes( + "performance_schema_max_thread_classes", + "Maximum number of thread instruments.", + READ_ONLY GLOBAL_VAR(pfs_param.m_thread_class_sizing), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 256), + DEFAULT(PFS_MAX_THREAD_CLASS), + BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES); + +static Sys_var_ulong Sys_pfs_max_thread_instances( + "performance_schema_max_thread_instances", + "Maximum number of instrumented threads.", + READ_ONLY GLOBAL_VAR(pfs_param.m_thread_sizing), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024*1024), + DEFAULT(PFS_MAX_THREAD), + BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES); + +#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */ + +static Sys_var_ulong Sys_auto_increment_increment( + "auto_increment_increment", + "Auto-increment columns are incremented by this", + SESSION_VAR(auto_increment_increment), + CMD_LINE(OPT_ARG), + VALID_RANGE(1, 65535), DEFAULT(1), BLOCK_SIZE(1), + NO_MUTEX_GUARD, IN_BINLOG); + +static Sys_var_ulong Sys_auto_increment_offset( + "auto_increment_offset", + "Offset added to Auto-increment columns. Used when " + "auto-increment-increment != 1", + SESSION_VAR(auto_increment_offset), + CMD_LINE(OPT_ARG), + VALID_RANGE(1, 65535), DEFAULT(1), BLOCK_SIZE(1), + NO_MUTEX_GUARD, IN_BINLOG); + +static Sys_var_mybool Sys_automatic_sp_privileges( + "automatic_sp_privileges", + "Creating and dropping stored procedures alters ACLs", + GLOBAL_VAR(sp_automatic_privileges), + CMD_LINE(OPT_ARG), DEFAULT(TRUE)); + +static Sys_var_ulong Sys_back_log( + "back_log", "The number of outstanding connection requests " + "MySQL can have. This comes into play when the main MySQL thread " + "gets very many connection requests in a very short time", + READ_ONLY GLOBAL_VAR(back_log), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, 65535), DEFAULT(50), BLOCK_SIZE(1)); + +static Sys_var_charptr Sys_basedir( + "basedir", "Path to installation directory. All paths are " + "usually resolved relative to this", + READ_ONLY GLOBAL_VAR(mysql_home_ptr), CMD_LINE(REQUIRED_ARG, 'b'), + IN_FS_CHARSET, DEFAULT(0)); + +static Sys_var_ulong Sys_binlog_cache_size( + "binlog_cache_size", "The size of the cache to " + "hold the SQL statements for the binary log during a " + "transaction. If you often use big, multi-statement " + "transactions you can increase this to get more performance", + GLOBAL_VAR(binlog_cache_size), + CMD_LINE(REQUIRED_ARG), + VALID_RANGE(IO_SIZE, ULONG_MAX), DEFAULT(32768), BLOCK_SIZE(IO_SIZE)); + +static bool check_has_super(sys_var *self, THD *thd, set_var *var) +{ + DBUG_ASSERT(self->scope() != sys_var::GLOBAL);// don't abuse check_has_super() +#ifndef NO_EMBEDDED_ACCESS_CHECKS + if (!(thd->security_ctx->master_access & SUPER_ACL)) + { + my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); + return true; + } +#endif + return false; +} +static bool binlog_format_check(sys_var *self, THD *thd, set_var *var) +{ + /* + If RBR and open temporary tables, their CREATE TABLE may not be in the + binlog, so we can't toggle to SBR in this connection. + */ + if ((thd->variables.binlog_format == BINLOG_FORMAT_ROW) && + thd->temporary_tables) + { + my_error(ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR, MYF(0)); + return true; + } + /* + if in a stored function/trigger, it's too late to change mode + */ + if (thd->in_sub_stmt) + { + my_error(ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT, MYF(0)); + return true; + } + /* + Make the session variable 'binlog_format' read-only inside a transaction. + */ + if (thd->active_transaction() && (var->type == OPT_SESSION)) + { + my_error(ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT, MYF(0)); + return true; + } + + if (check_has_super(self, thd, var)) + return true; + if (var->type == OPT_GLOBAL || + (thd->variables.binlog_format == var->save_result.ulonglong_value)) + return false; + + return false; +} + +static bool fix_binlog_format_after_update(sys_var *self, THD *thd, + enum_var_type type) +{ + if (type == OPT_SESSION) + thd->reset_current_stmt_binlog_format_row(); + return false; +} + +static Sys_var_enum Sys_binlog_format( + "binlog_format", "What form of binary logging the master will " + "use: either ROW for row-based binary logging, STATEMENT " + "for statement-based binary logging, or MIXED. MIXED is statement-" + "based binary logging except for those statements where only row-" + "based is correct: those which involve user-defined functions (i.e. " + "UDFs) or the UUID() function; for those, row-based binary logging is " + "automatically used. If NDBCLUSTER is enabled and binlog-format is " + "MIXED, the format switches to row-based and back implicitly per each " + "query accessing an NDBCLUSTER table", + SESSION_VAR(binlog_format), CMD_LINE(REQUIRED_ARG, OPT_BINLOG_FORMAT), + binlog_format_names, DEFAULT(BINLOG_FORMAT_STMT), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(binlog_format_check), + ON_UPDATE(fix_binlog_format_after_update)); + +static bool binlog_direct_check(sys_var *self, THD *thd, set_var *var) +{ + /* + Makes the session variable 'binlog_direct_non_transactional_updates' + read-only inside a transaction. + */ + if (thd->active_transaction() && (var->type == OPT_SESSION)) + { + my_error(ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT, MYF(0)); + return 1; + } + /* + Makes the session variable 'binlog_direct_non_transactional_updates' + read-only if within a procedure, trigger or function. + */ + if (thd->in_sub_stmt) + { + my_error(ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_DIRECT, MYF(0)); + return 1; + } + + if (check_has_super(self, thd, var)) + return true; + if (var->type == OPT_GLOBAL || + (thd->variables.binlog_direct_non_trans_update == + static_cast<my_bool>(var->save_result.ulonglong_value))) + return false; + + return false; +} + +static Sys_var_mybool Sys_binlog_direct( + "binlog_direct_non_transactional_updates", + "Causes updates to non-transactional engines using statement format to " + "be written directly to binary log. Before using this option make sure " + "that there are no dependencies between transactional and " + "non-transactional tables such as in the statement INSERT INTO t_myisam " + "SELECT * FROM t_innodb; otherwise, slaves may diverge from the master.", + SESSION_VAR(binlog_direct_non_trans_update), + CMD_LINE(OPT_ARG), DEFAULT(FALSE), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(binlog_direct_check)); + +static Sys_var_ulong Sys_bulk_insert_buff_size( + "bulk_insert_buffer_size", "Size of tree cache used in bulk " + "insert optimisation. Note that this is a limit per thread!", + SESSION_VAR(bulk_insert_buff_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, ULONG_MAX), DEFAULT(8192*1024), BLOCK_SIZE(1)); + +static Sys_var_charptr Sys_character_sets_dir( + "character_sets_dir", "Directory where character sets are", + READ_ONLY GLOBAL_VAR(charsets_dir), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(0)); + +static bool check_not_null(sys_var *self, THD *thd, set_var *var) +{ + return var->value && var->value->is_null(); +} +static bool check_charset(sys_var *self, THD *thd, set_var *var) +{ + if (!var->value) + return false; + + char buff[STRING_BUFFER_USUAL_SIZE]; + if (var->value->result_type() == STRING_RESULT) + { + String str(buff, sizeof(buff), system_charset_info), *res; + if (!(res=var->value->val_str(&str))) + var->save_result.ptr= NULL; + else if (!(var->save_result.ptr= get_charset_by_csname(res->c_ptr(), + MY_CS_PRIMARY, + MYF(0))) && + !(var->save_result.ptr= get_old_charset_by_name(res->c_ptr()))) + { + ErrConvString err(res); + my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), err.ptr()); + return true; + } + } + else // INT_RESULT + { + int csno= (int)var->value->val_int(); + if (!(var->save_result.ptr= get_charset(csno, MYF(0)))) + { + my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), llstr(csno, buff)); + return true; + } + } + return false; +} +static bool check_charset_not_null(sys_var *self, THD *thd, set_var *var) +{ + return check_charset(self, thd, var) || check_not_null(self, thd, var); +} +static Sys_var_struct Sys_character_set_system( + "character_set_system", "The character set used by the server " + "for storing identifiers", + READ_ONLY GLOBAL_VAR(system_charset_info), NO_CMD_LINE, + offsetof(CHARSET_INFO, csname), DEFAULT(0)); + +static Sys_var_struct Sys_character_set_server( + "character_set_server", "The default character set", + SESSION_VAR(collation_server), NO_CMD_LINE, + offsetof(CHARSET_INFO, csname), DEFAULT(&default_charset_info), + NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_charset_not_null)); + +static bool check_charset_db(sys_var *self, THD *thd, set_var *var) +{ + if (check_charset_not_null(self, thd, var)) + return true; + if (!var->value) // = DEFAULT + var->save_result.ptr= thd->db_charset; + return false; +} +static Sys_var_struct Sys_character_set_database( + "character_set_database", + " The character set used by the default database", + SESSION_VAR(collation_database), NO_CMD_LINE, + offsetof(CHARSET_INFO, csname), DEFAULT(&default_charset_info), + NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_charset_db)); + +static bool check_cs_client(sys_var *self, THD *thd, set_var *var) +{ + if (check_charset_not_null(self, thd, var)) + return true; + + // Currently, UCS-2 cannot be used as a client character set + if (((CHARSET_INFO *)(var->save_result.ptr))->mbminlen > 1) + return true; + + return false; +} +static bool fix_thd_charset(sys_var *self, THD *thd, enum_var_type type) +{ + if (type == OPT_SESSION) + thd->update_charset(); + return false; +} +static Sys_var_struct Sys_character_set_client( + "character_set_client", "The character set for statements " + "that arrive from the client", + SESSION_VAR(character_set_client), NO_CMD_LINE, + offsetof(CHARSET_INFO, csname), DEFAULT(&default_charset_info), + NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_cs_client), + ON_UPDATE(fix_thd_charset)); + +static Sys_var_struct Sys_character_set_connection( + "character_set_connection", "The character set used for " + "literals that do not have a character set introducer and for " + "number-to-string conversion", + SESSION_VAR(collation_connection), NO_CMD_LINE, + offsetof(CHARSET_INFO, csname), DEFAULT(&default_charset_info), + NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_charset_not_null), + ON_UPDATE(fix_thd_charset)); + +static Sys_var_struct Sys_character_set_results( + "character_set_results", "The character set used for returning " + "query results to the client", + SESSION_VAR(character_set_results), NO_CMD_LINE, + offsetof(CHARSET_INFO, csname), DEFAULT(&default_charset_info), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_charset)); + +static Sys_var_struct Sys_character_set_filesystem( + "character_set_filesystem", "The filesystem character set", + SESSION_VAR(character_set_filesystem), NO_CMD_LINE, + offsetof(CHARSET_INFO, csname), DEFAULT(&character_set_filesystem), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_charset_not_null), + ON_UPDATE(fix_thd_charset)); + +static const char *completion_type_names[]= {"NO_CHAIN", "CHAIN", "RELEASE", 0}; +static Sys_var_enum Sys_completion_type( + "completion_type", "The transaction completion type, one of " + "NO_CHAIN, CHAIN, RELEASE", + SESSION_VAR(completion_type), CMD_LINE(REQUIRED_ARG), + completion_type_names, DEFAULT(0)); + +static bool check_collation_not_null(sys_var *self, THD *thd, set_var *var) +{ + if (!var->value) + return false; + + char buff[STRING_BUFFER_USUAL_SIZE]; + if (var->value->result_type() == STRING_RESULT) + { + String str(buff, sizeof(buff), system_charset_info), *res; + if (!(res= var->value->val_str(&str))) + var->save_result.ptr= NULL; + else if (!(var->save_result.ptr= get_charset_by_name(res->c_ptr(), MYF(0)))) + { + ErrConvString err(res); + my_error(ER_UNKNOWN_COLLATION, MYF(0), err.ptr()); + return true; + } + } + else // INT_RESULT + { + int csno= (int)var->value->val_int(); + if (!(var->save_result.ptr= get_charset(csno, MYF(0)))) + { + my_error(ER_UNKNOWN_COLLATION, MYF(0), llstr(csno, buff)); + return true; + } + } + return check_not_null(self, thd, var); +} +static Sys_var_struct Sys_collation_connection( + "collation_connection", "The collation of the connection " + "character set", + SESSION_VAR(collation_connection), NO_CMD_LINE, + offsetof(CHARSET_INFO, name), DEFAULT(&default_charset_info), + NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_collation_not_null), + ON_UPDATE(fix_thd_charset)); + +static bool check_collation_db(sys_var *self, THD *thd, set_var *var) +{ + if (check_collation_not_null(self, thd, var)) + return true; + if (!var->value) // = DEFAULT + var->save_result.ptr= thd->db_charset; + return false; +} +static Sys_var_struct Sys_collation_database( + "collation_database", "The collation of the database " + "character set", + SESSION_VAR(collation_database), NO_CMD_LINE, + offsetof(CHARSET_INFO, name), DEFAULT(&default_charset_info), + NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_collation_db)); + +static Sys_var_struct Sys_collation_server( + "collation_server", "The server default collation", + SESSION_VAR(collation_server), NO_CMD_LINE, + offsetof(CHARSET_INFO, name), DEFAULT(&default_charset_info), + NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_collation_not_null)); + +static const char *concurrent_insert_names[]= {"NEVER", "AUTO", "ALWAYS", 0}; +static Sys_var_enum Sys_concurrent_insert( + "concurrent_insert", "Use concurrent insert with MyISAM. Possible " + "values are NEVER, AUTO, ALWAYS", + GLOBAL_VAR(myisam_concurrent_insert), CMD_LINE(OPT_ARG), + concurrent_insert_names, DEFAULT(1)); + +static Sys_var_ulong Sys_connect_timeout( + "connect_timeout", + "The number of seconds the mysqld server is waiting for a connect " + "packet before responding with 'Bad handshake'", + GLOBAL_VAR(connect_timeout), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(2, LONG_TIMEOUT), DEFAULT(CONNECT_TIMEOUT), BLOCK_SIZE(1)); + +static Sys_var_charptr Sys_datadir( + "datadir", "Path to the database root directory", + READ_ONLY GLOBAL_VAR(mysql_real_data_home_ptr), + CMD_LINE(REQUIRED_ARG, 'h'), IN_FS_CHARSET, DEFAULT(0)); + +#ifndef DBUG_OFF +static Sys_var_dbug Sys_dbug( + "debug", "Debug log", sys_var::SESSION, + CMD_LINE(OPT_ARG, '#'), DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(check_has_super)); +#endif + +/** + @todo + When updating myisam_delay_key_write, we should do a 'flush tables' + of all MyISAM tables to ensure that they are reopen with the + new attribute. +*/ +export bool fix_delay_key_write(sys_var *self, THD *thd, enum_var_type type) +{ + switch (delay_key_write_options) { + case DELAY_KEY_WRITE_NONE: + myisam_delay_key_write=0; + break; + case DELAY_KEY_WRITE_ON: + myisam_delay_key_write=1; + break; + case DELAY_KEY_WRITE_ALL: + myisam_delay_key_write=1; + ha_open_options|= HA_OPEN_DELAY_KEY_WRITE; + break; + } + return false; +} +static const char *delay_key_write_names[]= { "OFF", "ON", "ALL", NullS }; +static Sys_var_enum Sys_delay_key_write( + "delay_key_write", "Type of DELAY_KEY_WRITE", + GLOBAL_VAR(delay_key_write_options), CMD_LINE(OPT_ARG), + delay_key_write_names, DEFAULT(DELAY_KEY_WRITE_ON), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_delay_key_write)); + +static Sys_var_ulong Sys_delayed_insert_limit( + "delayed_insert_limit", + "After inserting delayed_insert_limit rows, the INSERT DELAYED " + "handler will check if there are any SELECT statements pending. " + "If so, it allows these to execute before continuing", + GLOBAL_VAR(delayed_insert_limit), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, ULONG_MAX), DEFAULT(DELAYED_LIMIT), BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_delayed_insert_timeout( + "delayed_insert_timeout", + "How long a INSERT DELAYED thread should wait for INSERT statements " + "before terminating", + GLOBAL_VAR(delayed_insert_timeout), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, LONG_TIMEOUT), DEFAULT(DELAYED_WAIT_TIMEOUT), + BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_delayed_queue_size( + "delayed_queue_size", + "What size queue (in rows) should be allocated for handling INSERT " + "DELAYED. If the queue becomes full, any client that does INSERT " + "DELAYED will wait until there is room in the queue again", + GLOBAL_VAR(delayed_queue_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, ULONG_MAX), DEFAULT(DELAYED_QUEUE_SIZE), BLOCK_SIZE(1)); + +#ifdef HAVE_EVENT_SCHEDULER +static const char *event_scheduler_names[]= { "OFF", "ON", "DISABLED", NullS }; +static bool event_scheduler_check(sys_var *self, THD *thd, set_var *var) +{ + /* DISABLED is only accepted on the command line */ + if (var->save_result.ulonglong_value == Events::EVENTS_DISABLED) + return true; + /* + If the scheduler was disabled because there are no/bad + system tables, produce a more meaningful error message + than ER_OPTION_PREVENTS_STATEMENT + */ + if (Events::check_if_system_tables_error()) + return true; + if (Events::opt_event_scheduler == Events::EVENTS_DISABLED) + { + my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), + "--event-scheduler=DISABLED or --skip-grant-tables"); + return true; + } + return false; +} +static bool event_scheduler_update(sys_var *self, THD *thd, enum_var_type type) +{ + mysql_mutex_unlock(&LOCK_global_system_variables); + /* + Events::start() is heavyweight. In particular it creates a new THD, + which takes LOCK_global_system_variables internally. + Thus we have to release it here. + We need to re-take it before returning, though. + And we need to take it *without* holding Events::LOCK_event_metadata. + */ + bool ret= Events::opt_event_scheduler == Events::EVENTS_ON + ? Events::start() + : Events::stop(); + mysql_mutex_unlock(&Events::LOCK_event_metadata); + mysql_mutex_lock(&LOCK_global_system_variables); + mysql_mutex_lock(&Events::LOCK_event_metadata); + if (ret) + my_error(ER_EVENT_SET_VAR_ERROR, MYF(0)); + return ret; +} +static PolyLock_mutex PLock_event_metadata(&Events::LOCK_event_metadata); +static Sys_var_enum Sys_event_scheduler( + "event_scheduler", "Enable the event scheduler. Possible values are " + "ON, OFF, and DISABLED (keep the event scheduler completely " + "deactivated, it cannot be activated run-time)", + GLOBAL_VAR(Events::opt_event_scheduler), CMD_LINE(OPT_ARG), + event_scheduler_names, DEFAULT(Events::EVENTS_OFF), + &PLock_event_metadata, NOT_IN_BINLOG, + ON_CHECK(event_scheduler_check), ON_UPDATE(event_scheduler_update)); +#endif + +static Sys_var_ulong Sys_expire_logs_days( + "expire_logs_days", + "If non-zero, binary logs will be purged after expire_logs_days " + "days; possible purges happen at startup and at binary log rotation", + GLOBAL_VAR(expire_logs_days), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 99), DEFAULT(0), BLOCK_SIZE(1)); + +static Sys_var_mybool Sys_flush( + "flush", "Flush MyISAM tables to disk between SQL commands", + GLOBAL_VAR(myisam_flush), + CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static Sys_var_ulong Sys_flush_time( + "flush_time", + "A dedicated thread is created to flush all tables at the " + "given interval", + GLOBAL_VAR(flush_time), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, LONG_TIMEOUT), + DEFAULT(FLUSH_TIME), BLOCK_SIZE(1)); + +static bool check_ftb_syntax(sys_var *self, THD *thd, set_var *var) +{ + return ft_boolean_check_syntax_string((uchar*) + (var->save_result.string_value.str)); +} +static bool query_cache_flush(sys_var *self, THD *thd, enum_var_type type) +{ +#ifdef HAVE_QUERY_CACHE + query_cache.flush(); +#endif /* HAVE_QUERY_CACHE */ + return false; +} +/// @todo make SESSION_VAR (usability enhancement and a fix for a race condition) +static Sys_var_charptr Sys_ft_boolean_syntax( + "ft_boolean_syntax", "List of operators for " + "MATCH ... AGAINST ( ... IN BOOLEAN MODE)", + GLOBAL_VAR(ft_boolean_syntax), + CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET, + DEFAULT(DEFAULT_FTB_SYNTAX), NO_MUTEX_GUARD, + NOT_IN_BINLOG, ON_CHECK(check_ftb_syntax), ON_UPDATE(query_cache_flush)); + +static Sys_var_ulong Sys_ft_max_word_len( + "ft_max_word_len", + "The maximum length of the word to be included in a FULLTEXT index. " + "Note: FULLTEXT indexes must be rebuilt after changing this variable", + READ_ONLY GLOBAL_VAR(ft_max_word_len), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(10, HA_FT_MAXCHARLEN), DEFAULT(HA_FT_MAXCHARLEN), + BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_ft_min_word_len( + "ft_min_word_len", + "The minimum length of the word to be included in a FULLTEXT index. " + "Note: FULLTEXT indexes must be rebuilt after changing this variable", + READ_ONLY GLOBAL_VAR(ft_min_word_len), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, HA_FT_MAXCHARLEN), DEFAULT(4), BLOCK_SIZE(1)); + +/// @todo make it an updatable SESSION_VAR +static Sys_var_ulong Sys_ft_query_expansion_limit( + "ft_query_expansion_limit", + "Number of best matches to use for query expansion", + READ_ONLY GLOBAL_VAR(ft_query_expansion_limit), + CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, 1000), DEFAULT(20), BLOCK_SIZE(1)); + +static Sys_var_charptr Sys_ft_stopword_file( + "ft_stopword_file", + "Use stopwords from this file instead of built-in list", + READ_ONLY GLOBAL_VAR(ft_stopword_file), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(0)); + +static Sys_var_mybool Sys_ignore_builtin_innodb( + "ignore_builtin_innodb", + "Disable initialization of builtin InnoDB plugin", + READ_ONLY GLOBAL_VAR(opt_ignore_builtin_innodb), + CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static bool check_init_string(sys_var *self, THD *thd, set_var *var) +{ + if (var->save_result.string_value.str == 0) + { + var->save_result.string_value.str= const_cast<char*>(""); + var->save_result.string_value.length= 0; + } + return false; +} +static PolyLock_rwlock PLock_sys_init_connect(&LOCK_sys_init_connect); +static Sys_var_lexstring Sys_init_connect( + "init_connect", "Command(s) that are executed for each " + "new connection", GLOBAL_VAR(opt_init_connect), + CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET, + DEFAULT(""), &PLock_sys_init_connect, NOT_IN_BINLOG, + ON_CHECK(check_init_string)); + +static Sys_var_charptr Sys_init_file( + "init_file", "Read SQL commands from this file at startup", + READ_ONLY GLOBAL_VAR(opt_init_file), + IF_DISABLE_GRANT_OPTIONS(NO_CMD_LINE, CMD_LINE(REQUIRED_ARG)), + IN_FS_CHARSET, DEFAULT(0)); + +static PolyLock_rwlock PLock_sys_init_slave(&LOCK_sys_init_slave); +static Sys_var_lexstring Sys_init_slave( + "init_slave", "Command(s) that are executed by a slave server " + "each time the SQL thread starts", GLOBAL_VAR(opt_init_slave), + CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET, + DEFAULT(""), &PLock_sys_init_slave, + NOT_IN_BINLOG, ON_CHECK(check_init_string)); + +static Sys_var_ulong Sys_interactive_timeout( + "interactive_timeout", + "The number of seconds the server waits for activity on an interactive " + "connection before closing it", + SESSION_VAR(net_interactive_timeout), + CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, LONG_TIMEOUT), DEFAULT(NET_WAIT_TIMEOUT), BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_join_buffer_size( + "join_buffer_size", + "The size of the buffer that is used for full joins", + SESSION_VAR(join_buff_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(128, ULONG_MAX), DEFAULT(128*1024), BLOCK_SIZE(128)); + +static Sys_var_keycache Sys_key_buffer_size( + "key_buffer_size", "The size of the buffer used for " + "index blocks for MyISAM tables. Increase this to get better index " + "handling (for all reads and multiple writes) to as much as you can " + "afford", + KEYCACHE_VAR(param_buff_size), + CMD_LINE(REQUIRED_ARG, OPT_KEY_BUFFER_SIZE), + VALID_RANGE(0, SIZE_T_MAX), DEFAULT(KEY_CACHE_SIZE), + BLOCK_SIZE(IO_SIZE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(update_buffer_size)); + +static Sys_var_keycache Sys_key_cache_block_size( + "key_cache_block_size", "The default size of key cache blocks", + KEYCACHE_VAR(param_block_size), + CMD_LINE(REQUIRED_ARG, OPT_KEY_CACHE_BLOCK_SIZE), + VALID_RANGE(512, 1024*16), DEFAULT(KEY_CACHE_BLOCK_SIZE), + BLOCK_SIZE(512), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(update_keycache_param)); + +static Sys_var_keycache Sys_key_cache_division_limit( + "key_cache_division_limit", + "The minimum percentage of warm blocks in key cache", + KEYCACHE_VAR(param_division_limit), + CMD_LINE(REQUIRED_ARG, OPT_KEY_CACHE_DIVISION_LIMIT), + VALID_RANGE(1, 100), DEFAULT(100), + BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(update_keycache_param)); + +static Sys_var_keycache Sys_key_cache_age_threshold( + "key_cache_age_threshold", "This characterizes the number of " + "hits a hot block has to be untouched until it is considered aged " + "enough to be downgraded to a warm block. This specifies the " + "percentage ratio of that number of hits to the total number of " + "blocks in key cache", + KEYCACHE_VAR(param_age_threshold), + CMD_LINE(REQUIRED_ARG, OPT_KEY_CACHE_AGE_THRESHOLD), + VALID_RANGE(100, ULONG_MAX), DEFAULT(300), + BLOCK_SIZE(100), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(update_keycache_param)); + +static Sys_var_mybool Sys_large_files_support( + "large_files_support", + "Whether mysqld was compiled with options for large file support", + READ_ONLY GLOBAL_VAR(opt_large_files), + NO_CMD_LINE, DEFAULT(sizeof(my_off_t) > 4)); + +static Sys_var_uint Sys_large_page_size( + "large_page_size", + "If large page support is enabled, this shows the size of memory pages", + READ_ONLY GLOBAL_VAR(opt_large_page_size), NO_CMD_LINE, + VALID_RANGE(0, UINT_MAX), DEFAULT(0), BLOCK_SIZE(1)); + +static Sys_var_mybool Sys_large_pages( + "large_pages", "Enable support for large pages", + READ_ONLY GLOBAL_VAR(opt_large_files), + IF_WIN(NO_CMD_LINE, CMD_LINE(OPT_ARG)), DEFAULT(FALSE)); + +static Sys_var_charptr Sys_language( + "lc_messages_dir", "Directory where error messages are", + READ_ONLY GLOBAL_VAR(lc_messages_dir_ptr), CMD_LINE(REQUIRED_ARG, 'L'), + IN_FS_CHARSET, DEFAULT(0)); + +static Sys_var_mybool Sys_local_infile( + "local_infile", "Enable LOAD DATA LOCAL INFILE", + GLOBAL_VAR(opt_local_infile), CMD_LINE(OPT_ARG), DEFAULT(TRUE)); + +#ifdef HAVE_MLOCKALL +static Sys_var_mybool Sys_locked_in_memory( + "locked_in_memory", + "Whether mysqld was locked in memory with --memlock", + READ_ONLY GLOBAL_VAR(locked_in_memory), NO_CMD_LINE, DEFAULT(FALSE)); +#endif + +/* this says NO_CMD_LINE, as command-line option takes a string, not a bool */ +static Sys_var_mybool Sys_log_bin( + "log_bin", "Whether the binary log is enabled", + READ_ONLY GLOBAL_VAR(opt_bin_log), NO_CMD_LINE, DEFAULT(FALSE)); + +static Sys_var_mybool Sys_trust_function_creators( + "log_bin_trust_function_creators", + "If set to FALSE (the default), then when --log-bin is used, creation " + "of a stored function (or trigger) is allowed only to users having the " + "SUPER privilege and only if this stored function (trigger) may not " + "break binary logging. Note that if ALL connections to this server " + "ALWAYS use row-based binary logging, the security issues do not " + "exist and the binary logging cannot break, so you can safely set " + "this to TRUE", + GLOBAL_VAR(trust_function_creators), + CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static Sys_var_charptr Sys_log_error( + "log_error", "Error log file", + READ_ONLY GLOBAL_VAR(log_error_file_ptr), CMD_LINE(OPT_ARG), + IN_FS_CHARSET, DEFAULT(disabled_my_option)); + +static Sys_var_mybool Sys_log_queries_not_using_indexes( + "log_queries_not_using_indexes", + "Log queries that are executed without benefit of any index to the " + "slow log if it is open", + GLOBAL_VAR(opt_log_queries_not_using_indexes), + CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static Sys_var_ulong Sys_log_warnings( + "log_warnings", + "Log some not critical warnings to the log file", + SESSION_VAR(log_warnings), + CMD_LINE(OPT_ARG, 'W'), + VALID_RANGE(0, ULONG_MAX), DEFAULT(1), BLOCK_SIZE(1)); + +static bool update_cached_long_query_time(sys_var *self, THD *thd, + enum_var_type type) +{ + if (type == OPT_SESSION) + thd->variables.long_query_time= + thd->variables.long_query_time_double * 1e6; + else + global_system_variables.long_query_time= + global_system_variables.long_query_time_double * 1e6; + return false; +} + +static Sys_var_double Sys_long_query_time( + "long_query_time", + "Log all queries that have taken more than long_query_time seconds " + "to execute to file. The argument will be treated as a decimal value " + "with microsecond precision", + SESSION_VAR(long_query_time_double), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, LONG_TIMEOUT), DEFAULT(10), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(update_cached_long_query_time)); + +static bool fix_low_prio_updates(sys_var *self, THD *thd, enum_var_type type) +{ + if (type == OPT_SESSION) + thd->update_lock_default= (thd->variables.low_priority_updates ? + TL_WRITE_LOW_PRIORITY : TL_WRITE); + else + thr_upgraded_concurrent_insert_lock= + (global_system_variables.low_priority_updates ? + TL_WRITE_LOW_PRIORITY : TL_WRITE); + return false; +} +static Sys_var_mybool Sys_low_priority_updates( + "low_priority_updates", + "INSERT/DELETE/UPDATE has lower priority than selects", + SESSION_VAR(low_priority_updates), + CMD_LINE(OPT_ARG), + DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_low_prio_updates)); + +#ifndef TO_BE_DELETED /* Alias for the low_priority_updates */ +static Sys_var_mybool Sys_sql_low_priority_updates( + "sql_low_priority_updates", + "INSERT/DELETE/UPDATE has lower priority than selects", + SESSION_VAR(low_priority_updates), NO_CMD_LINE, + DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_low_prio_updates)); +#endif + +static Sys_var_mybool Sys_lower_case_file_system( + "lower_case_file_system", + "Case sensitivity of file names on the file system where the " + "data directory is located", + READ_ONLY GLOBAL_VAR(lower_case_file_system), NO_CMD_LINE, + DEFAULT(FALSE)); + +static Sys_var_uint Sys_lower_case_table_names( + "lower_case_table_names", + "If set to 1 table names are stored in lowercase on disk and table " + "names will be case-insensitive. Should be set to 2 if you are using " + "a case insensitive file system", + READ_ONLY GLOBAL_VAR(lower_case_table_names), + CMD_LINE(OPT_ARG, OPT_LOWER_CASE_TABLE_NAMES), + VALID_RANGE(0, 2), +#ifdef FN_NO_CASE_SENSE + DEFAULT(1), +#else + DEFAULT(0), +#endif + BLOCK_SIZE(1)); + +static bool session_readonly(sys_var *self, THD *thd, set_var *var) +{ + if (var->type == OPT_GLOBAL) + return false; + my_error(ER_VARIABLE_IS_READONLY, MYF(0), "SESSION", + self->name.str, "GLOBAL"); + return true; +} +static Sys_var_ulong Sys_max_allowed_packet( + "max_allowed_packet", + "Max packet length to send to or receive from the server", + SESSION_VAR(max_allowed_packet), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1024, 1024*1024*1024), DEFAULT(1024*1024), + BLOCK_SIZE(1024), NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(session_readonly)); + +static Sys_var_ulonglong Sys_max_binlog_cache_size( + "max_binlog_cache_size", + "Can be used to restrict the total size used to cache a " + "multi-transaction query", + GLOBAL_VAR(max_binlog_cache_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(IO_SIZE, ULONGLONG_MAX), + DEFAULT((ULONGLONG_MAX/IO_SIZE)*IO_SIZE), + BLOCK_SIZE(IO_SIZE)); + +static bool fix_max_binlog_size(sys_var *self, THD *thd, enum_var_type type) +{ + mysql_bin_log.set_max_size(max_binlog_size); +#ifdef HAVE_REPLICATION + if (!max_relay_log_size) + active_mi->rli.relay_log.set_max_size(max_binlog_size); +#endif + return false; +} +static Sys_var_ulong Sys_max_binlog_size( + "max_binlog_size", + "Binary log will be rotated automatically when the size exceeds this " + "value. Will also apply to relay logs if max_relay_log_size is 0", + GLOBAL_VAR(max_binlog_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(IO_SIZE, 1024*1024L*1024L), DEFAULT(1024*1024L*1024L), + BLOCK_SIZE(IO_SIZE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_max_binlog_size)); + +static bool fix_max_connections(sys_var *self, THD *thd, enum_var_type type) +{ +#ifndef EMBEDDED_LIBRARY + resize_thr_alarm(max_connections + + global_system_variables.max_insert_delayed_threads + 10); +#endif + return false; +} + +// Default max_connections of 151 is larger than Apache's default max +// children, to avoid "too many connections" error in a common setup +static Sys_var_ulong Sys_max_connections( + "max_connections", "The number of simultaneous clients allowed", + GLOBAL_VAR(max_connections), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, 100000), DEFAULT(151), BLOCK_SIZE(1), NO_MUTEX_GUARD, + NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(fix_max_connections)); + +static Sys_var_ulong Sys_max_connect_errors( + "max_connect_errors", + "If there is more than this number of interrupted connections from " + "a host this host will be blocked from further connections", + GLOBAL_VAR(max_connect_errors), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, ULONG_MAX), DEFAULT(MAX_CONNECT_ERRORS), + BLOCK_SIZE(1)); + +static bool check_max_delayed_threads(sys_var *self, THD *thd, set_var *var) +{ + return var->type != OPT_GLOBAL && + var->save_result.ulonglong_value != 0 && + var->save_result.ulonglong_value != + global_system_variables.max_insert_delayed_threads; +} + +// Alias for max_delayed_threads +static Sys_var_ulong Sys_max_insert_delayed_threads( + "max_insert_delayed_threads", + "Don't start more than this number of threads to handle INSERT " + "DELAYED statements. If set to zero INSERT DELAYED will be not used", + SESSION_VAR(max_insert_delayed_threads), + NO_CMD_LINE, VALID_RANGE(0, 16384), DEFAULT(20), + BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(check_max_delayed_threads), ON_UPDATE(fix_max_connections)); + +static Sys_var_ulong Sys_max_delayed_threads( + "max_delayed_threads", + "Don't start more than this number of threads to handle INSERT " + "DELAYED statements. If set to zero INSERT DELAYED will be not used", + SESSION_VAR(max_insert_delayed_threads), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 16384), DEFAULT(20), + BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(check_max_delayed_threads), ON_UPDATE(fix_max_connections)); + +static Sys_var_ulong Sys_max_error_count( + "max_error_count", + "Max number of errors/warnings to store for a statement", + SESSION_VAR(max_error_count), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, 65535), DEFAULT(DEFAULT_ERROR_COUNT), BLOCK_SIZE(1)); + +static Sys_var_ulonglong Sys_max_heap_table_size( + "max_heap_table_size", + "Don't allow creation of heap tables bigger than this", + SESSION_VAR(max_heap_table_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(16384, (ulonglong)~(intptr)0), DEFAULT(16*1024*1024), + BLOCK_SIZE(1024)); + +static Sys_var_ulong Sys_pseudo_thread_id( + "pseudo_thread_id", + "This variable is for internal server use", + SESSION_ONLY(pseudo_thread_id), + NO_CMD_LINE, VALID_RANGE(0, ULONG_MAX), DEFAULT(0), + BLOCK_SIZE(1), NO_MUTEX_GUARD, IN_BINLOG, + ON_CHECK(check_has_super)); + +static bool fix_max_join_size(sys_var *self, THD *thd, enum_var_type type) +{ + SV *sv= type == OPT_GLOBAL ? &global_system_variables : &thd->variables; + if (sv->max_join_size == HA_POS_ERROR) + sv->option_bits|= OPTION_BIG_SELECTS; + else + sv->option_bits&= ~OPTION_BIG_SELECTS; + return false; +} +static Sys_var_harows Sys_max_join_size( + "max_join_size", + "Joins that are probably going to read more than max_join_size " + "records return an error", + SESSION_VAR(max_join_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, HA_POS_ERROR), DEFAULT(HA_POS_ERROR), BLOCK_SIZE(1), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_max_join_size)); + +static Sys_var_ulong Sys_max_seeks_for_key( + "max_seeks_for_key", + "Limit assumed max number of seeks when looking up rows based on a key", + SESSION_VAR(max_seeks_for_key), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, ULONG_MAX), DEFAULT(ULONG_MAX), BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_max_length_for_sort_data( + "max_length_for_sort_data", + "Max number of bytes in sorted records", + SESSION_VAR(max_length_for_sort_data), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(4, 8192*1024L), DEFAULT(1024), BLOCK_SIZE(1)); + +static Sys_var_harows Sys_sql_max_join_size( + "sql_max_join_size", "Alias for max_join_size", + SESSION_VAR(max_join_size), NO_CMD_LINE, + VALID_RANGE(1, HA_POS_ERROR), DEFAULT(HA_POS_ERROR), BLOCK_SIZE(1), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_max_join_size), DEPRECATED(70000, 0)); + +static PolyLock_mutex PLock_prepared_stmt_count(&LOCK_prepared_stmt_count); +static Sys_var_ulong Sys_max_prepared_stmt_count( + "max_prepared_stmt_count", + "Maximum number of prepared statements in the server", + GLOBAL_VAR(max_prepared_stmt_count), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, 1024*1024), DEFAULT(16382), BLOCK_SIZE(1), + &PLock_prepared_stmt_count); + +static bool fix_max_relay_log_size(sys_var *self, THD *thd, enum_var_type type) +{ +#ifdef HAVE_REPLICATION + active_mi->rli.relay_log.set_max_size(max_relay_log_size ? + max_relay_log_size: max_binlog_size); +#endif + return false; +} +static Sys_var_ulong Sys_max_relay_log_size( + "max_relay_log_size", + "If non-zero: relay log will be rotated automatically when the " + "size exceeds this value; if zero: when the size " + "exceeds max_binlog_size", + GLOBAL_VAR(max_relay_log_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, 1024L*1024*1024), DEFAULT(0), BLOCK_SIZE(IO_SIZE), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_max_relay_log_size)); + +static Sys_var_ulong Sys_max_sort_length( + "max_sort_length", + "The number of bytes to use when sorting BLOB or TEXT values (only " + "the first max_sort_length bytes of each value are used; the rest " + "are ignored)", + SESSION_VAR(max_sort_length), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(4, 8192*1024L), DEFAULT(1024), BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_max_sp_recursion_depth( + "max_sp_recursion_depth", + "Maximum stored procedure recursion depth", + SESSION_VAR(max_sp_recursion_depth), CMD_LINE(OPT_ARG), + VALID_RANGE(0, 255), DEFAULT(0), BLOCK_SIZE(1)); + +// non-standard session_value_ptr() here +static Sys_var_max_user_conn Sys_max_user_connections( + "max_user_connections", + "The maximum number of active connections for a single user " + "(0 = no limit)", + SESSION_VAR(max_user_connections), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, UINT_MAX), DEFAULT(0), BLOCK_SIZE(1), NO_MUTEX_GUARD, + NOT_IN_BINLOG, ON_CHECK(session_readonly)); + +static Sys_var_ulong Sys_max_tmp_tables( + "max_tmp_tables", + "Maximum number of temporary tables a client can keep open at a time", + SESSION_VAR(max_tmp_tables), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, ULONG_MAX), DEFAULT(32), BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_max_write_lock_count( + "max_write_lock_count", + "After this many write locks, allow some read locks to run in between", + GLOBAL_VAR(max_write_lock_count), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, ULONG_MAX), DEFAULT(ULONG_MAX), BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_min_examined_row_limit( + "min_examined_row_limit", + "Don't write queries to slow log that examine fewer rows " + "than that", + SESSION_VAR(min_examined_row_limit), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, ULONG_MAX), DEFAULT(0), BLOCK_SIZE(1)); + +#ifdef _WIN32 +static Sys_var_mybool Sys_named_pipe( + "named_pipe", "Enable the named pipe (NT)", + READ_ONLY GLOBAL_VAR(opt_enable_named_pipe), CMD_LINE(OPT_ARG), + DEFAULT(FALSE)); +#endif + +static Sys_var_ulong Sys_net_buffer_length( + "net_buffer_length", + "Buffer length for TCP/IP and socket communication", + SESSION_VAR(net_buffer_length), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1024, 1024*1024), DEFAULT(16384), BLOCK_SIZE(1024), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(session_readonly)); + +static bool fix_net_read_timeout(sys_var *self, THD *thd, enum_var_type type) +{ + if (type != OPT_GLOBAL) + my_net_set_read_timeout(&thd->net, thd->variables.net_read_timeout); + return false; +} +static Sys_var_ulong Sys_net_read_timeout( + "net_read_timeout", + "Number of seconds to wait for more data from a connection before " + "aborting the read", + SESSION_VAR(net_read_timeout), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, LONG_TIMEOUT), DEFAULT(NET_READ_TIMEOUT), BLOCK_SIZE(1), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_net_read_timeout)); + +static bool fix_net_write_timeout(sys_var *self, THD *thd, enum_var_type type) +{ + if (type != OPT_GLOBAL) + my_net_set_write_timeout(&thd->net, thd->variables.net_write_timeout); + return false; +} +static Sys_var_ulong Sys_net_write_timeout( + "net_write_timeout", + "Number of seconds to wait for a block to be written to a connection " + "before aborting the write", + SESSION_VAR(net_write_timeout), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, LONG_TIMEOUT), DEFAULT(NET_WRITE_TIMEOUT), BLOCK_SIZE(1), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_net_write_timeout)); + +static bool fix_net_retry_count(sys_var *self, THD *thd, enum_var_type type) +{ + if (type != OPT_GLOBAL) + thd->net.retry_count=thd->variables.net_retry_count; + return false; +} +static Sys_var_ulong Sys_net_retry_count( + "net_retry_count", + "If a read on a communication port is interrupted, retry this " + "many times before giving up", + SESSION_VAR(net_retry_count), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, ULONG_MAX), DEFAULT(MYSQLD_NET_RETRY_COUNT), + BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_net_retry_count)); + +static Sys_var_mybool Sys_new_mode( + "new", "Use very new possible \"unsafe\" functions", + SESSION_VAR(new_mode), CMD_LINE(OPT_ARG, 'n'), DEFAULT(FALSE)); + +static Sys_var_mybool Sys_old_mode( + "old", "Use compatible behavior", + READ_ONLY GLOBAL_VAR(old_mode), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static Sys_var_mybool Sys_old_alter_table( + "old_alter_table", "Use old, non-optimized alter table", + SESSION_VAR(old_alter_table), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static bool check_old_passwords(sys_var *self, THD *thd, set_var *var) +{ + return mysql_user_table_is_in_short_password_format; +} +static Sys_var_mybool Sys_old_passwords( + "old_passwords", + "Use old password encryption method (needed for 4.0 and older clients)", + SESSION_VAR(old_passwords), CMD_LINE(OPT_ARG), DEFAULT(FALSE), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_old_passwords)); + +static Sys_var_ulong Sys_open_files_limit( + "open_files_limit", + "If this is not 0, then mysqld will use this value to reserve file " + "descriptors to use with setrlimit(). If this value is 0 then mysqld " + "will reserve max_connections*5 or max_connections + table_cache*2 " + "(whichever is larger) number of file descriptors", + READ_ONLY GLOBAL_VAR(open_files_limit), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, OS_FILE_LIMIT), DEFAULT(0), BLOCK_SIZE(1)); + +/// @todo change to enum +static Sys_var_ulong Sys_optimizer_prune_level( + "optimizer_prune_level", + "Controls the heuristic(s) applied during query optimization to prune " + "less-promising partial plans from the optimizer search space. " + "Meaning: 0 - do not apply any heuristic, thus perform exhaustive " + "search; 1 - prune plans based on number of retrieved rows", + SESSION_VAR(optimizer_prune_level), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, 1), DEFAULT(1), BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_optimizer_search_depth( + "optimizer_search_depth", + "Maximum depth of search performed by the query optimizer. Values " + "larger than the number of relations in a query result in better " + "query plans, but take longer to compile a query. Values smaller " + "than the number of tables in a relation result in faster " + "optimization, but may produce very bad query plans. If set to 0, " + "the system will automatically pick a reasonable value; if set to " + "63, the optimizer will switch to the original find_best search" + "(used for testing/comparison)", + SESSION_VAR(optimizer_search_depth), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, MAX_TABLES+2), DEFAULT(MAX_TABLES+1), BLOCK_SIZE(1)); + +static const char *optimizer_switch_names[]= +{ + "index_merge", "index_merge_union", "index_merge_sort_union", + "index_merge_intersection", "engine_condition_pushdown", + "default", NullS +}; +/** propagates changes to @@engine_condition_pushdown */ +static bool fix_optimizer_switch(sys_var *self, THD *thd, + enum_var_type type) +{ + SV *sv= (type == OPT_GLOBAL) ? &global_system_variables : &thd->variables; + sv->engine_condition_pushdown= + test(sv->optimizer_switch & OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN); + return false; +} +static Sys_var_flagset Sys_optimizer_switch( + "optimizer_switch", + "optimizer_switch=option=val[,option=val...], where option is one of " + "{index_merge, index_merge_union, index_merge_sort_union, " + "index_merge_intersection, engine_condition_pushdown}" + " and val is one of {on, off, default}", + SESSION_VAR(optimizer_switch), CMD_LINE(REQUIRED_ARG), + optimizer_switch_names, DEFAULT(OPTIMIZER_SWITCH_DEFAULT), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(NULL), + ON_UPDATE(fix_optimizer_switch)); + +static Sys_var_charptr Sys_pid_file( + "pid_file", "Pid file used by safe_mysqld", + READ_ONLY GLOBAL_VAR(pidfile_name_ptr), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(0)); + +static Sys_var_charptr Sys_plugin_dir( + "plugin_dir", "Directory for plugins", + READ_ONLY GLOBAL_VAR(opt_plugin_dir_ptr), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(0)); + +static Sys_var_uint Sys_port( + "port", + "Port number to use for connection or 0 to default to, " + "my.cnf, $MYSQL_TCP_PORT, " +#if MYSQL_PORT_DEFAULT == 0 + "/etc/services, " +#endif + "built-in default (" STRINGIFY_ARG(MYSQL_PORT) "), whatever comes first", + READ_ONLY GLOBAL_VAR(mysqld_port), CMD_LINE(REQUIRED_ARG, 'P'), + VALID_RANGE(0, UINT_MAX32), DEFAULT(0), BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_preload_buff_size( + "preload_buffer_size", + "The size of the buffer that is allocated when preloading indexes", + SESSION_VAR(preload_buff_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1024, 1024*1024*1024), DEFAULT(32768), BLOCK_SIZE(1)); + +static Sys_var_uint Sys_protocol_version( + "protocol_version", + "The version of the client/server protocol used by the MySQL server", + READ_ONLY GLOBAL_VAR(protocol_version), NO_CMD_LINE, + VALID_RANGE(0, ~0), DEFAULT(PROTOCOL_VERSION), BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_read_buff_size( + "read_buffer_size", + "Each thread that does a sequential scan allocates a buffer of " + "this size for each table it scans. If you do many sequential scans, " + "you may want to increase this value", + SESSION_VAR(read_buff_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(IO_SIZE*2, INT_MAX32), DEFAULT(128*1024), + BLOCK_SIZE(IO_SIZE)); + +static my_bool read_only; +static bool check_read_only(sys_var *self, THD *thd, set_var *var) +{ + /* Prevent self dead-lock */ + if (thd->locked_tables || thd->active_transaction()) + { + my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0)); + return true; + } + return false; +} +static bool fix_read_only(sys_var *self, THD *thd, enum_var_type type) +{ + bool result= true; + my_bool new_read_only= read_only; // make a copy before releasing a mutex + DBUG_ENTER("sys_var_opt_readonly::update"); + + if (read_only == FALSE || read_only == opt_readonly) + { + opt_readonly= read_only; + DBUG_RETURN(false); + } + + if (check_read_only(self, thd, 0)) // just in case + goto end; + + if (thd->global_read_lock) + { + /* + This connection already holds the global read lock. + This can be the case with: + - FLUSH TABLES WITH READ LOCK + - SET GLOBAL READ_ONLY = 1 + */ + opt_readonly= read_only; + DBUG_RETURN(false); + } + + /* + Perform a 'FLUSH TABLES WITH READ LOCK'. + This is a 3 step process: + - [1] lock_global_read_lock() + - [2] close_cached_tables() + - [3] make_global_read_lock_block_commit() + [1] prevents new connections from obtaining tables locked for write. + [2] waits until all existing connections close their tables. + [3] prevents transactions from being committed. + */ + + read_only= opt_readonly; + mysql_mutex_unlock(&LOCK_global_system_variables); + + if (lock_global_read_lock(thd)) + goto end_with_mutex_unlock; + + /* + This call will be blocked by any connection holding a READ or WRITE lock. + Ideally, we want to wait only for pending WRITE locks, but since: + con 1> LOCK TABLE T FOR READ; + con 2> LOCK TABLE T FOR WRITE; (blocked by con 1) + con 3> SET GLOBAL READ ONLY=1; (blocked by con 2) + can cause to wait on a read lock, it's required for the client application + to unlock everything, and acceptable for the server to wait on all locks. + */ + if ((result= close_cached_tables(thd, NULL, FALSE, TRUE, TRUE))) + goto end_with_read_lock; + + if ((result= make_global_read_lock_block_commit(thd))) + goto end_with_read_lock; + + /* Change the opt_readonly system variable, safe because the lock is held */ + opt_readonly= new_read_only; + result= false; + + end_with_read_lock: + /* Release the lock */ + unlock_global_read_lock(thd); + end_with_mutex_unlock: + mysql_mutex_lock(&LOCK_global_system_variables); + end: + read_only= opt_readonly; + DBUG_RETURN(result); +} +static Sys_var_mybool Sys_readonly( + "read_only", + "Make all non-temporary tables read-only, with the exception for " + "replication (slave) threads and users with the SUPER privilege", + GLOBAL_VAR(read_only), CMD_LINE(OPT_ARG), DEFAULT(FALSE), + NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(check_read_only), ON_UPDATE(fix_read_only)); + +// Small lower limit to be able to test MRR +static Sys_var_ulong Sys_read_rnd_buff_size( + "read_rnd_buffer_size", + "When reading rows in sorted order after a sort, the rows are read " + "through this buffer to avoid a disk seeks. If not set, then it's " + "set to the value of record_buffer", + SESSION_VAR(read_rnd_buff_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, INT_MAX32), DEFAULT(256*1024), BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_div_precincrement( + "div_precision_increment", "Precision of the result of '/' " + "operator will be increased on that value", + SESSION_VAR(div_precincrement), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, DECIMAL_MAX_SCALE), DEFAULT(4), BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_rpl_recovery_rank( + "rpl_recovery_rank", "Unused, will be removed", + GLOBAL_VAR(rpl_recovery_rank), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, ULONG_MAX), DEFAULT(0), BLOCK_SIZE(1), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(0), + DEPRECATED(70000, 0)); + +static Sys_var_ulong Sys_range_alloc_block_size( + "range_alloc_block_size", + "Allocation block size for storing ranges during optimization", + SESSION_VAR(range_alloc_block_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(RANGE_ALLOC_BLOCK_SIZE, ULONG_MAX), + DEFAULT(RANGE_ALLOC_BLOCK_SIZE), BLOCK_SIZE(1024)); + +static Sys_var_ulong Sys_multi_range_count( + "multi_range_count", "Number of key ranges to request at once", + SESSION_VAR(multi_range_count), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, ULONG_MAX), DEFAULT(256), BLOCK_SIZE(1)); + +static bool fix_thd_mem_root(sys_var *self, THD *thd, enum_var_type type) +{ + if (type != OPT_GLOBAL) + reset_root_defaults(thd->mem_root, + thd->variables.query_alloc_block_size, + thd->variables.query_prealloc_size); + return false; +} +static Sys_var_ulong Sys_query_alloc_block_size( + "query_alloc_block_size", + "Allocation block size for query parsing and execution", + SESSION_VAR(query_alloc_block_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1024, ULONG_MAX), DEFAULT(QUERY_ALLOC_BLOCK_SIZE), + BLOCK_SIZE(1024), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_thd_mem_root)); + +static Sys_var_ulong Sys_query_prealloc_size( + "query_prealloc_size", + "Persistent buffer for query parsing and execution", + SESSION_VAR(query_prealloc_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(QUERY_ALLOC_PREALLOC_SIZE, ULONG_MAX), + DEFAULT(QUERY_ALLOC_PREALLOC_SIZE), + BLOCK_SIZE(1024), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_thd_mem_root)); + +#ifdef HAVE_SMEM +static Sys_var_mybool Sys_shared_memory( + "shared_memory", "Enable the shared memory", + READ_ONLY GLOBAL_VAR(opt_enable_shared_memory), CMD_LINE(OPT_ARG), + DEFAULT(FALSE)); + +static Sys_var_charptr Sys_shared_memory_base_name( + "shared_memory_base_name", "Base name of shared memory", + READ_ONLY GLOBAL_VAR(shared_memory_base_name), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(0)); +#endif + +// this has to be NO_CMD_LINE as the command-line option has a different name +static Sys_var_mybool Sys_skip_external_locking( + "skip_external_locking", "Don't use system (external) locking", + READ_ONLY GLOBAL_VAR(my_disable_locking), NO_CMD_LINE, DEFAULT(TRUE)); + +static Sys_var_mybool Sys_skip_networking( + "skip_networking", "Don't allow connection with TCP/IP", + READ_ONLY GLOBAL_VAR(opt_disable_networking), CMD_LINE(OPT_ARG), + DEFAULT(FALSE)); + +static Sys_var_mybool Sys_skip_show_database( + "skip_show_database", "Don't allow 'SHOW DATABASE' commands", + READ_ONLY GLOBAL_VAR(opt_skip_show_db), CMD_LINE(OPT_ARG), + DEFAULT(FALSE)); + +static Sys_var_charptr Sys_socket( + "socket", "Socket file to use for connection", + READ_ONLY GLOBAL_VAR(mysqld_unix_port), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(0)); + +#ifdef HAVE_THR_SETCONCURRENCY +static Sys_var_ulong Sys_thread_concurrency( + "thread_concurrency", + "Permits the application to give the threads system a hint for " + "the desired number of threads that should be run at the same time", + READ_ONLY GLOBAL_VAR(concurrency), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, 512), DEFAULT(DEFAULT_CONCURRENCY), BLOCK_SIZE(1)); +#endif + +static Sys_var_ulong Sys_thread_stack( + "thread_stack", "The stack size for each thread", + READ_ONLY GLOBAL_VAR(my_thread_stack_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(128*1024, ULONG_MAX), DEFAULT(DEFAULT_THREAD_STACK), + BLOCK_SIZE(1024)); + +static Sys_var_charptr Sys_tmpdir( + "tmpdir", "Path for temporary files. Several paths may " + "be specified, separated by a " +#if defined(__WIN__) || defined(__NETWARE__) + "semicolon (;)" +#else + "colon (:)" +#endif + ", in this case they are used in a round-robin fashion", + READ_ONLY GLOBAL_VAR(opt_mysql_tmpdir), CMD_LINE(REQUIRED_ARG, 't'), + IN_FS_CHARSET, DEFAULT(0)); + +static bool fix_trans_mem_root(sys_var *self, THD *thd, enum_var_type type) +{ + if (type != OPT_GLOBAL) + reset_root_defaults(&thd->transaction.mem_root, + thd->variables.trans_alloc_block_size, + thd->variables.trans_prealloc_size); + return false; +} +static Sys_var_ulong Sys_trans_alloc_block_size( + "transaction_alloc_block_size", + "Allocation block size for transactions to be stored in binary log", + SESSION_VAR(trans_alloc_block_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1024, ULONG_MAX), DEFAULT(QUERY_ALLOC_BLOCK_SIZE), + BLOCK_SIZE(1024), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_trans_mem_root)); + +static Sys_var_ulong Sys_trans_prealloc_size( + "transaction_prealloc_size", + "Persistent buffer for transactions to be stored in binary log", + SESSION_VAR(trans_prealloc_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1024, ULONG_MAX), DEFAULT(TRANS_ALLOC_PREALLOC_SIZE), + BLOCK_SIZE(1024), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_trans_mem_root)); + +static const char *thread_handling_names[]= +{ + "one-thread-per-connection", "no-threads", +#if HAVE_POOL_OF_THREADS == 1 + "pool-of-threads", +#endif + 0 +}; +static Sys_var_enum Sys_thread_handling( + "thread_handling", + "Define threads usage for handling queries, one of " + "one-thread-per-connection, no-threads" +#if HAVE_POOL_OF_THREADS == 1 + ", pool-of-threads" +#endif + , READ_ONLY GLOBAL_VAR(thread_handling), CMD_LINE(REQUIRED_ARG), + thread_handling_names, DEFAULT(0)); + +#ifdef HAVE_QUERY_CACHE +static bool fix_query_cache_size(sys_var *self, THD *thd, enum_var_type type) +{ + ulong new_cache_size= query_cache.resize(query_cache_size); + /* + Note: query_cache_size is a global variable reflecting the + requested cache size. See also query_cache_size_arg + */ + if (query_cache_size != new_cache_size) + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARN_QC_RESIZE, ER(ER_WARN_QC_RESIZE), + query_cache_size, new_cache_size); + + query_cache_size= new_cache_size; + return false; +} +static Sys_var_ulong Sys_query_cache_size( + "query_cache_size", + "The memory allocated to store results from old queries", + GLOBAL_VAR(query_cache_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, ULONG_MAX), DEFAULT(0), BLOCK_SIZE(1024), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_query_cache_size)); + +static Sys_var_ulong Sys_query_cache_limit( + "query_cache_limit", + "Don't cache results that are bigger than this", + GLOBAL_VAR(query_cache.query_cache_limit), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, ULONG_MAX), DEFAULT(1024*1024), BLOCK_SIZE(1)); + +static bool fix_qcache_min_res_unit(sys_var *self, THD *thd, enum_var_type type) +{ + query_cache_min_res_unit= + query_cache.set_min_res_unit(query_cache_min_res_unit); + return false; +} +static Sys_var_ulong Sys_query_cache_min_res_unit( + "query_cache_min_res_unit", + "The minimum size for blocks allocated by the query cache", + GLOBAL_VAR(query_cache_min_res_unit), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, ULONG_MAX), DEFAULT(QUERY_CACHE_MIN_RESULT_DATA_SIZE), + BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_qcache_min_res_unit)); + +static const char *query_cache_type_names[]= { "OFF", "ON", "DEMAND", 0 }; +static bool check_query_cache_type(sys_var *self, THD *thd, set_var *var) +{ + if (query_cache.is_disabled()) + { + my_error(ER_QUERY_CACHE_DISABLED, MYF(0)); + return true; + } + return false; +} +static Sys_var_enum Sys_query_cache_type( + "query_cache_type", + "OFF = Don't cache or retrieve results. ON = Cache all results " + "except SELECT SQL_NO_CACHE ... queries. DEMAND = Cache only " + "SELECT SQL_CACHE ... queries", + SESSION_VAR(query_cache_type), CMD_LINE(REQUIRED_ARG), + query_cache_type_names, DEFAULT(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(check_query_cache_type)); + +static Sys_var_mybool Sys_query_cache_wlock_invalidate( + "query_cache_wlock_invalidate", + "Invalidate queries in query cache on LOCK for write", + SESSION_VAR(query_cache_wlock_invalidate), CMD_LINE(OPT_ARG), + DEFAULT(FALSE)); +#endif /* HAVE_QUERY_CACHE */ + +static Sys_var_mybool Sys_secure_auth( + "secure_auth", + "Disallow authentication for accounts that have old (pre-4.1) " + "passwords", + GLOBAL_VAR(opt_secure_auth), CMD_LINE(OPT_ARG), + DEFAULT(FALSE)); + +static Sys_var_charptr Sys_secure_file_priv( + "secure_file_priv", + "Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files " + "within specified directory", + PREALLOCATED READ_ONLY GLOBAL_VAR(opt_secure_file_priv), + CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET, DEFAULT(0)); + +static bool fix_server_id(sys_var *self, THD *thd, enum_var_type type) +{ + server_id_supplied = 1; + thd->server_id= server_id; + return false; +} +static Sys_var_ulong Sys_server_id( + "server_id", + "Uniquely identifies the server instance in the community of " + "replication partners", + GLOBAL_VAR(server_id), CMD_LINE(REQUIRED_ARG, OPT_SERVER_ID), + VALID_RANGE(0, UINT_MAX32), DEFAULT(0), BLOCK_SIZE(1), NO_MUTEX_GUARD, + NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(fix_server_id)); + +static Sys_var_mybool Sys_slave_compressed_protocol( + "slave_compressed_protocol", + "Use compression on master/slave protocol", + GLOBAL_VAR(opt_slave_compressed_protocol), CMD_LINE(OPT_ARG), + DEFAULT(FALSE)); + +#ifdef HAVE_REPLICATION +static const char *slave_exec_mode_names[]= {"STRICT", "IDEMPOTENT", 0}; +static Sys_var_enum Slave_exec_mode( + "slave_exec_mode", + "Modes for how replication events should be executed. Legal values " + "are STRICT (default) and IDEMPOTENT. In IDEMPOTENT mode, " + "replication will not stop for operations that are idempotent. " + "In STRICT mode, replication will stop on any unexpected difference " + "between the master and the slave", + GLOBAL_VAR(slave_exec_mode_options), CMD_LINE(REQUIRED_ARG), + slave_exec_mode_names, DEFAULT(SLAVE_EXEC_MODE_STRICT)); +const char *slave_type_conversions_name[]= {"ALL_LOSSY", "ALL_NON_LOSSY", 0}; +static Sys_var_set Slave_type_conversions( + "slave_type_conversions", + "Set of slave type conversions that are enabled. Legal values are:" + " ALL_LOSSY to enable lossy conversions and" + " ALL_NON_LOSSY to enable non-lossy conversions." + " If the variable is assigned the empty set, no conversions are" + " allowed and it is expected that the types match exactly.", + GLOBAL_VAR(slave_type_conversions_options), CMD_LINE(REQUIRED_ARG), + slave_type_conversions_name, + DEFAULT(0)); +#endif + + +static Sys_var_ulong Sys_slow_launch_time( + "slow_launch_time", + "If creating the thread takes longer than this value (in seconds), " + "the Slow_launch_threads counter will be incremented", + GLOBAL_VAR(slow_launch_time), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, LONG_TIMEOUT), DEFAULT(2), BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_sort_buffer( + "sort_buffer_size", + "Each thread that needs to do a sort allocates a buffer of this size", + SESSION_VAR(sortbuff_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(MIN_SORT_MEMORY, ULONG_MAX), DEFAULT(MAX_SORT_MEMORY), + BLOCK_SIZE(1)); + +export ulong expand_sql_mode(ulonglong sql_mode) +{ + if (sql_mode & MODE_ANSI) + { + /* + Note that we dont set + MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | MODE_NO_FIELD_OPTIONS + to allow one to get full use of MySQL in this mode. + + MODE_ONLY_FULL_GROUP_BY was removed from ANSI mode because it is + currently overly restrictive (see BUG#8510). + */ + sql_mode|= (MODE_REAL_AS_FLOAT | MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | + MODE_IGNORE_SPACE); + } + if (sql_mode & MODE_ORACLE) + sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | + MODE_IGNORE_SPACE | + MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | + MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER); + if (sql_mode & MODE_MSSQL) + sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | + MODE_IGNORE_SPACE | + MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | + MODE_NO_FIELD_OPTIONS); + if (sql_mode & MODE_POSTGRESQL) + sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | + MODE_IGNORE_SPACE | + MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | + MODE_NO_FIELD_OPTIONS); + if (sql_mode & MODE_DB2) + sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | + MODE_IGNORE_SPACE | + MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | + MODE_NO_FIELD_OPTIONS); + if (sql_mode & MODE_MAXDB) + sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | + MODE_IGNORE_SPACE | + MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | + MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER); + if (sql_mode & MODE_MYSQL40) + sql_mode|= MODE_HIGH_NOT_PRECEDENCE; + if (sql_mode & MODE_MYSQL323) + sql_mode|= MODE_HIGH_NOT_PRECEDENCE; + if (sql_mode & MODE_TRADITIONAL) + sql_mode|= (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES | + MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | + MODE_ERROR_FOR_DIVISION_BY_ZERO | MODE_NO_AUTO_CREATE_USER | + MODE_NO_ENGINE_SUBSTITUTION); + return sql_mode; +} +static bool check_sql_mode(sys_var *self, THD *thd, set_var *var) +{ + var->save_result.ulonglong_value= + expand_sql_mode(var->save_result.ulonglong_value); + return false; +} +static bool fix_sql_mode(sys_var *self, THD *thd, enum_var_type type) +{ + if (type != OPT_GLOBAL) + { + /* Update thd->server_status */ + if (thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) + thd->server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES; + else + thd->server_status&= ~SERVER_STATUS_NO_BACKSLASH_ESCAPES; + } + return false; +} +/* + WARNING: When adding new SQL modes don't forget to update the + tables definitions that stores it's value (ie: mysql.event, mysql.proc) +*/ +static const char *sql_mode_names[]= +{ + "REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE", ",", + "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION", "NO_DIR_IN_CREATE", + "POSTGRESQL", "ORACLE", "MSSQL", "DB2", "MAXDB", "NO_KEY_OPTIONS", + "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI", + "NO_AUTO_VALUE_ON_ZERO", "NO_BACKSLASH_ESCAPES", "STRICT_TRANS_TABLES", + "STRICT_ALL_TABLES", "NO_ZERO_IN_DATE", "NO_ZERO_DATE", + "ALLOW_INVALID_DATES", "ERROR_FOR_DIVISION_BY_ZERO", "TRADITIONAL", + "NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE", "NO_ENGINE_SUBSTITUTION", + "PAD_CHAR_TO_FULL_LENGTH", + 0 +}; +export bool sql_mode_string_representation(THD *thd, ulong sql_mode, + LEX_STRING *ls) +{ + set_to_string(thd, ls, sql_mode, sql_mode_names); + return ls->str == 0; +} +/* + sql_mode should *not* be IN_BINLOG: even though it is written to the binlog, + the slave ignores the MODE_NO_DIR_IN_CREATE variable, so slave's value + differs from master's (see log_event.cc: Query_log_event::do_apply_event()). +*/ +static Sys_var_set Sys_sql_mode( + "sql_mode", + "Syntax: sql-mode=mode[,mode[,mode...]]. See the manual for the " + "complete list of valid sql modes", + SESSION_VAR(sql_mode), CMD_LINE(REQUIRED_ARG), + sql_mode_names, DEFAULT(0), NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(check_sql_mode), ON_UPDATE(fix_sql_mode)); + +#ifdef HAVE_OPENSSL +#define SSL_OPT(X) CMD_LINE(REQUIRED_ARG,X) +#else +#define SSL_OPT(X) NO_CMD_LINE +#endif + +static Sys_var_charptr Sys_ssl_ca( + "ssl_ca", + "CA file in PEM format (check OpenSSL docs, implies --ssl)", + READ_ONLY GLOBAL_VAR(opt_ssl_ca), SSL_OPT(OPT_SSL_CA), + IN_FS_CHARSET, DEFAULT(0)); + +static Sys_var_charptr Sys_ssl_capath( + "ssl_capath", + "CA directory (check OpenSSL docs, implies --ssl)", + READ_ONLY GLOBAL_VAR(opt_ssl_capath), SSL_OPT(OPT_SSL_CAPATH), + IN_FS_CHARSET, DEFAULT(0)); + +static Sys_var_charptr Sys_ssl_cert( + "ssl_cert", "X509 cert in PEM format (implies --ssl)", + READ_ONLY GLOBAL_VAR(opt_ssl_cert), SSL_OPT(OPT_SSL_CERT), + IN_FS_CHARSET, DEFAULT(0)); + +static Sys_var_charptr Sys_ssl_cipher( + "ssl_cipher", "SSL cipher to use (implies --ssl)", + READ_ONLY GLOBAL_VAR(opt_ssl_cipher), SSL_OPT(OPT_SSL_CIPHER), + IN_FS_CHARSET, DEFAULT(0)); + +static Sys_var_charptr Sys_ssl_key( + "ssl_key", "X509 key in PEM format (implies --ssl)", + READ_ONLY GLOBAL_VAR(opt_ssl_key), SSL_OPT(OPT_SSL_KEY), + IN_FS_CHARSET, DEFAULT(0)); + +// why ENUM and not BOOL ? +static const char *updatable_views_with_limit_names[]= {"NO", "YES", 0}; +static Sys_var_enum Sys_updatable_views_with_limit( + "updatable_views_with_limit", + "YES = Don't issue an error message (warning only) if a VIEW without " + "presence of a key of the underlying table is used in queries with a " + "LIMIT clause for updating. NO = Prohibit update of a VIEW, which " + "does not contain a key of the underlying table and the query uses " + "a LIMIT clause (usually get from GUI tools)", + SESSION_VAR(updatable_views_with_limit), CMD_LINE(REQUIRED_ARG), + updatable_views_with_limit_names, DEFAULT(TRUE)); + +static Sys_var_mybool Sys_sync_frm( + "sync_frm", "Sync .frm files to disk on creation", + GLOBAL_VAR(opt_sync_frm), CMD_LINE(OPT_ARG), + DEFAULT(TRUE)); + +static char *system_time_zone_ptr; +static Sys_var_charptr Sys_system_time_zone( + "system_time_zone", "The server system time zone", + READ_ONLY GLOBAL_VAR(system_time_zone_ptr), NO_CMD_LINE, + IN_FS_CHARSET, DEFAULT(system_time_zone)); + +static Sys_var_ulong Sys_table_def_size( + "table_definition_cache", + "The number of cached table definitions", + GLOBAL_VAR(table_def_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(TABLE_DEF_CACHE_MIN, 512*1024), + DEFAULT(TABLE_DEF_CACHE_DEFAULT), BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_table_cache_size( + "table_open_cache", "The number of cached open tables", + GLOBAL_VAR(table_cache_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, 512*1024), DEFAULT(TABLE_OPEN_CACHE_DEFAULT), + BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_table_lock_wait_timeout( + "table_lock_wait_timeout", + "Timeout in seconds to wait for a table level lock before returning an " + "error. Used only if the connection has active cursors", + GLOBAL_VAR(table_lock_wait_timeout), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, 1024*1024*1024), DEFAULT(50), BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_thread_cache_size( + "thread_cache_size", + "How many threads we should keep in a cache for reuse", + GLOBAL_VAR(thread_cache_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, 16384), DEFAULT(0), BLOCK_SIZE(1)); + +#if HAVE_POOL_OF_THREADS == 1 +static Sys_var_ulong Sys_thread_pool_size( + "thread_pool_size", + "How many threads we should create to handle query requests in " + "case of 'thread_handling=pool-of-threads'", + GLOBAL_VAR(thread_pool_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, 16384), DEFAULT(20), BLOCK_SIZE(0)); +#endif + +// Can't change the 'next' tx_isolation if we are already in a transaction +static bool check_tx_isolation(sys_var *self, THD *thd, set_var *var) +{ + if (var->type == OPT_DEFAULT && (thd->server_status & SERVER_STATUS_IN_TRANS)) + { + my_error(ER_CANT_CHANGE_TX_ISOLATION, MYF(0)); + return true; + } + return false; +} + +/* + If one doesn't use the SESSION modifier, the isolation level + is only active for the next command. +*/ +static bool fix_tx_isolation(sys_var *self, THD *thd, enum_var_type type) +{ + if (type == OPT_SESSION) + thd->session_tx_isolation= (enum_tx_isolation)thd->variables.tx_isolation; + return false; +} +// NO_CMD_LINE - different name of the option +static Sys_var_enum Sys_tx_isolation( + "tx_isolation", "Default transaction isolation level", + SESSION_VAR(tx_isolation), NO_CMD_LINE, + tx_isolation_names, DEFAULT(ISO_REPEATABLE_READ), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_tx_isolation), + ON_UPDATE(fix_tx_isolation)); + +static Sys_var_ulonglong Sys_tmp_table_size( + "tmp_table_size", + "If an internal in-memory temporary table exceeds this size, MySQL " + "will automatically convert it to an on-disk MyISAM table", + SESSION_VAR(tmp_table_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1024, (ulonglong)~(intptr)0), DEFAULT(16*1024*1024), + BLOCK_SIZE(1)); + +static Sys_var_mybool Sys_timed_mutexes( + "timed_mutexes", + "Specify whether to time mutexes (only InnoDB mutexes are currently " + "supported)", + GLOBAL_VAR(timed_mutexes), CMD_LINE(OPT_ARG), DEFAULT(0)); + +static char *server_version_ptr; +static Sys_var_charptr Sys_version( + "version", "Server version", + READ_ONLY GLOBAL_VAR(server_version_ptr), NO_CMD_LINE, + IN_SYSTEM_CHARSET, DEFAULT(server_version)); + +static char *server_version_comment_ptr; +static Sys_var_charptr Sys_version_comment( + "version_comment", "version_comment", + READ_ONLY GLOBAL_VAR(server_version_comment_ptr), NO_CMD_LINE, + IN_SYSTEM_CHARSET, DEFAULT(MYSQL_COMPILATION_COMMENT)); + +static char *server_version_compile_machine_ptr; +static Sys_var_charptr Sys_version_compile_machine( + "version_compile_machine", "version_compile_machine", + READ_ONLY GLOBAL_VAR(server_version_compile_machine_ptr), NO_CMD_LINE, + IN_SYSTEM_CHARSET, DEFAULT(MACHINE_TYPE)); + +static char *server_version_compile_os_ptr; +static Sys_var_charptr Sys_version_compile_os( + "version_compile_os", "version_compile_os", + READ_ONLY GLOBAL_VAR(server_version_compile_os_ptr), NO_CMD_LINE, + IN_SYSTEM_CHARSET, DEFAULT(SYSTEM_TYPE)); + +static Sys_var_ulong Sys_net_wait_timeout( + "wait_timeout", + "The number of seconds the server waits for activity on a " + "connection before closing it", + SESSION_VAR(net_wait_timeout), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT)), + DEFAULT(NET_WAIT_TIMEOUT), BLOCK_SIZE(1)); + +/** propagates changes to the relevant flag of @@optimizer_switch */ +static bool fix_engine_condition_pushdown(sys_var *self, THD *thd, + enum_var_type type) +{ + SV *sv= (type == OPT_GLOBAL) ? &global_system_variables : &thd->variables; + if (sv->engine_condition_pushdown) + sv->optimizer_switch|= OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN; + else + sv->optimizer_switch&= ~OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN; + return false; +} +static Sys_var_mybool Sys_engine_condition_pushdown( + "engine_condition_pushdown", + "Push supported query conditions to the storage engine." + " Deprecated, use --optimizer-switch instead.", + SESSION_VAR(engine_condition_pushdown), + CMD_LINE(OPT_ARG, OPT_ENGINE_CONDITION_PUSHDOWN), + DEFAULT(TRUE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(NULL), + ON_UPDATE(fix_engine_condition_pushdown), + DEPRECATED(70000, "'@@optimizer_switch'")); + +static Sys_var_plugin Sys_default_storage_engine( + "default_storage_engine", "The default storage engine for new tables", + SESSION_VAR(table_plugin), NO_CMD_LINE, + MYSQL_STORAGE_ENGINE_PLUGIN, DEFAULT(&default_storage_engine), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_not_null)); + +// Alias for @@default_storage_engine +static Sys_var_plugin Sys_storage_engine( + "storage_engine", "Alias for @@default_storage_engine. Deprecated", + SESSION_VAR(table_plugin), NO_CMD_LINE, + MYSQL_STORAGE_ENGINE_PLUGIN, DEFAULT(&default_storage_engine), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_not_null)); + +#if defined(ENABLED_DEBUG_SYNC) +/* + Variable can be set for the session only. + + This could be changed later. Then we need to have a global array of + actions in addition to the thread local ones. SET GLOBAL would + manage the global array, SET [SESSION] the local array. A sync point + would need to look for a local and a global action. Setting and + executing of global actions need to be protected by a mutex. + + The purpose of global actions could be to allow synchronizing with + connectionless threads that cannot execute SET statements. +*/ +static Sys_var_debug_sync Sys_debug_sync( + "debug_sync", "Debug Sync Facility", + sys_var::ONLY_SESSION, NO_CMD_LINE, + DEFAULT(0), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_has_super)); +#endif /* defined(ENABLED_DEBUG_SYNC) */ + +/** + "time_format" "date_format" "datetime_format" + + the following three variables are unused, and the source of confusion + (bug reports like "I've changed date_format, but date format hasn't changed. + I've made them read-only, to alleviate the situation somewhat. + + @todo make them NO_CMD_LINE ? +*/ +static Sys_var_charptr Sys_date_format( + "date_format", "The DATE format (ignored)", + READ_ONLY GLOBAL_VAR(global_date_format.format.str), + CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET, + DEFAULT(known_date_time_formats[ISO_FORMAT].date_format)); + +static Sys_var_charptr Sys_datetime_format( + "datetime_format", "The DATETIME format (ignored)", + READ_ONLY GLOBAL_VAR(global_datetime_format.format.str), + CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET, + DEFAULT(known_date_time_formats[ISO_FORMAT].datetime_format)); + +static Sys_var_charptr Sys_time_format( + "time_format", "The TIME format (ignored)", + READ_ONLY GLOBAL_VAR(global_time_format.format.str), + CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET, + DEFAULT(known_date_time_formats[ISO_FORMAT].time_format)); + +static bool fix_autocommit(sys_var *self, THD *thd, enum_var_type type) +{ + if (type == OPT_GLOBAL) + { + if (global_system_variables.option_bits & OPTION_AUTOCOMMIT) + global_system_variables.option_bits&= ~OPTION_NOT_AUTOCOMMIT; + else + global_system_variables.option_bits|= OPTION_NOT_AUTOCOMMIT; + return false; + } + + if (thd->variables.option_bits & OPTION_AUTOCOMMIT && + thd->variables.option_bits & OPTION_NOT_AUTOCOMMIT) + { // activating autocommit + + if (ha_commit(thd)) + { + thd->variables.option_bits&= ~OPTION_AUTOCOMMIT; + return true; + } + + thd->variables.option_bits&= + ~(OPTION_BEGIN | OPTION_KEEP_LOG | OPTION_NOT_AUTOCOMMIT); + thd->transaction.all.modified_non_trans_table= false; + thd->server_status|= SERVER_STATUS_AUTOCOMMIT; + return false; + } + + if (!(thd->variables.option_bits & OPTION_AUTOCOMMIT) && + !(thd->variables.option_bits & OPTION_NOT_AUTOCOMMIT)) + { // disabling autocommit + + thd->transaction.all.modified_non_trans_table= false; + thd->server_status&= ~SERVER_STATUS_AUTOCOMMIT; + thd->variables.option_bits|= OPTION_NOT_AUTOCOMMIT; + return false; + } + + return false; // autocommit value wasn't changed +} +static Sys_var_bit Sys_autocommit( + "autocommit", "autocommit", + SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_AUTOCOMMIT, DEFAULT(TRUE), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(fix_autocommit)); +export sys_var *Sys_autocommit_ptr= &Sys_autocommit; // for sql_yacc.yy + +static Sys_var_mybool Sys_big_tables( + "big_tables", "Allow big result sets by saving all " + "temporary sets on file (Solves most 'table full' errors)", + SESSION_VAR(big_tables), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +#ifndef TO_BE_DELETED /* Alias for big_tables */ +static Sys_var_mybool Sys_sql_big_tables( + "sql_big_tables", "alias for big_tables", + SESSION_VAR(big_tables), NO_CMD_LINE, DEFAULT(FALSE)); +#endif + +static Sys_var_bit Sys_big_selects( + "sql_big_selects", "sql_big_selects", + SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_BIG_SELECTS, + DEFAULT(FALSE)); + +static Sys_var_bit Sys_log_off( + "sql_log_off", "sql_log_off", + SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_LOG_OFF, + DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_has_super)); + +static bool fix_sql_log_bin(sys_var *self, THD *thd, enum_var_type type) +{ + if (type != OPT_GLOBAL && !thd->in_sub_stmt) + thd->sql_log_bin_toplevel= thd->variables.option_bits & OPTION_BIN_LOG; + return false; +} +static Sys_var_bit Sys_log_binlog( + "sql_log_bin", "sql_log_bin", + SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_BIN_LOG, + DEFAULT(TRUE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_has_super), + ON_UPDATE(fix_sql_log_bin)); + +static bool deprecated_log_update(sys_var *self, THD *thd, set_var *var) +{ + /* + The update log is not supported anymore since 5.0. + See sql/mysqld.cc/, comments in function init_server_components() for an + explaination of the different warnings we send below + */ + + if (opt_sql_bin_update) + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_UPDATE_LOG_DEPRECATED_TRANSLATED, + ER(ER_UPDATE_LOG_DEPRECATED_TRANSLATED)); + else + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_UPDATE_LOG_DEPRECATED_IGNORED, + ER(ER_UPDATE_LOG_DEPRECATED_IGNORED)); + return check_has_super(self, thd, var); +} +static Sys_var_bit Sys_log_update( + "sql_log_update", "alias for sql_log_bin", + SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_BIN_LOG, + DEFAULT(TRUE), NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(deprecated_log_update), ON_UPDATE(fix_sql_log_bin)); + +static Sys_var_bit Sys_sql_warnings( + "sql_warnings", "sql_warnings", + SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_WARNINGS, + DEFAULT(FALSE)); + +static Sys_var_bit Sys_sql_notes( + "sql_notes", "sql_notes", + SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_SQL_NOTES, + DEFAULT(TRUE)); + +static Sys_var_bit Sys_auto_is_null( + "sql_auto_is_null", "sql_auto_is_null", + SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_AUTO_IS_NULL, + DEFAULT(FALSE), NO_MUTEX_GUARD, IN_BINLOG); + +static Sys_var_bit Sys_safe_updates( + "sql_safe_updates", "sql_safe_updates", + SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_SAFE_UPDATES, + DEFAULT(FALSE)); + +static Sys_var_bit Sys_buffer_results( + "sql_buffer_result", "sql_buffer_result", + SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_BUFFER_RESULT, + DEFAULT(FALSE)); + +static Sys_var_bit Sys_quote_show_create( + "sql_quote_show_create", "sql_quote_show_create", + SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_QUOTE_SHOW_CREATE, + DEFAULT(TRUE)); + +static Sys_var_bit Sys_foreign_key_checks( + "foreign_key_checks", "foreign_key_checks", + SESSION_VAR(option_bits), NO_CMD_LINE, + REVERSE(OPTION_NO_FOREIGN_KEY_CHECKS), + DEFAULT(TRUE), NO_MUTEX_GUARD, IN_BINLOG); + +static Sys_var_bit Sys_unique_checks( + "unique_checks", "unique_checks", + SESSION_VAR(option_bits), NO_CMD_LINE, + REVERSE(OPTION_RELAXED_UNIQUE_CHECKS), + DEFAULT(TRUE), NO_MUTEX_GUARD, IN_BINLOG); + +#ifdef ENABLED_PROFILING +static Sys_var_bit Sys_profiling( + "profiling", "profiling", + SESSION_VAR(option_bits), NO_CMD_LINE, OPTION_PROFILING, + DEFAULT(FALSE)); + +static Sys_var_ulong Sys_profiling_history_size( + "profiling_history_size", "Limit of query profiling memory", + SESSION_VAR(profiling_history_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, 100), DEFAULT(15), BLOCK_SIZE(1)); +#endif + +static Sys_var_harows Sys_select_limit( + "sql_select_limit", + "The maximum number of rows to return from SELECT statements", + SESSION_VAR(select_limit), NO_CMD_LINE, + VALID_RANGE(1, HA_POS_ERROR), DEFAULT(HA_POS_ERROR), BLOCK_SIZE(1)); + +static bool update_timestamp(THD *thd, set_var *var) +{ + if (var->value) + thd->set_time((time_t) var->save_result.ulonglong_value); + else // SET timestamp=DEFAULT + thd->user_time= 0; + return false; +} +static ulonglong read_timestamp(THD *thd) +{ + return (ulonglong) thd->start_time; +} +static Sys_var_session_special Sys_timestamp( + "timestamp", "Set the time for this client", + sys_var::ONLY_SESSION, NO_CMD_LINE, + VALID_RANGE(0, ~(time_t)0), BLOCK_SIZE(1), + NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(0), ON_UPDATE(update_timestamp), + ON_READ(read_timestamp)); + +static bool update_last_insert_id(THD *thd, set_var *var) +{ + if (!var->value) + { + my_error(ER_NO_DEFAULT, MYF(0), var->var->name); + return true; + } + thd->first_successful_insert_id_in_prev_stmt= + var->save_result.ulonglong_value; + return false; +} +static ulonglong read_last_insert_id(THD *thd) +{ + return (ulonglong) thd->read_first_successful_insert_id_in_prev_stmt(); +} +static Sys_var_session_special Sys_last_insert_id( + "last_insert_id", "The value to be returned from LAST_INSERT_ID()", + sys_var::ONLY_SESSION, NO_CMD_LINE, + VALID_RANGE(0, ULONGLONG_MAX), BLOCK_SIZE(1), + NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(0), + ON_UPDATE(update_last_insert_id), ON_READ(read_last_insert_id)); + +// alias for last_insert_id(), Sybase-style +static Sys_var_session_special Sys_identity( + "identity", "Synonym for the last_insert_id variable", + sys_var::ONLY_SESSION, NO_CMD_LINE, + VALID_RANGE(0, ULONGLONG_MAX), BLOCK_SIZE(1), + NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(0), + ON_UPDATE(update_last_insert_id), ON_READ(read_last_insert_id)); + +/* + insert_id should *not* be marked as written to the binlog (i.e., it + should *not* be IN_BINLOG), because we want any statement that + refers to insert_id explicitly to be unsafe. (By "explicitly", we + mean using @@session.insert_id, whereas insert_id is used + "implicitly" when NULL value is inserted into an auto_increment + column). + + We want statements referring explicitly to @@session.insert_id to be + unsafe, because insert_id is modified internally by the slave sql + thread when NULL values are inserted in an AUTO_INCREMENT column. + This modification interfers with the value of the + @@session.insert_id variable if @@session.insert_id is referred + explicitly by an insert statement (as is seen by executing "SET + @@session.insert_id=0; CREATE TABLE t (a INT, b INT KEY + AUTO_INCREMENT); INSERT INTO t(a) VALUES (@@session.insert_id);" in + statement-based logging mode: t will be different on master and + slave). +*/ +static bool update_insert_id(THD *thd, set_var *var) +{ + if (!var->value) + { + my_error(ER_NO_DEFAULT, MYF(0), var->var->name); + return true; + } + thd->force_one_auto_inc_interval(var->save_result.ulonglong_value); + return false; +} + +static ulonglong read_insert_id(THD *thd) +{ + return thd->auto_inc_intervals_forced.minimum(); +} +static Sys_var_session_special Sys_insert_id( + "insert_id", "The value to be used by the following INSERT " + "or ALTER TABLE statement when inserting an AUTO_INCREMENT value", + sys_var::ONLY_SESSION, NO_CMD_LINE, + VALID_RANGE(0, ULONGLONG_MAX), BLOCK_SIZE(1), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(update_insert_id), ON_READ(read_insert_id)); + +static bool update_rand_seed1(THD *thd, set_var *var) +{ + if (!var->value) + { + my_error(ER_NO_DEFAULT, MYF(0), var->var->name); + return true; + } + thd->rand.seed1= (ulong) var->save_result.ulonglong_value; + return false; +} +static ulonglong read_rand_seed(THD *thd) +{ + return 0; +} +static Sys_var_session_special Sys_rand_seed1( + "rand_seed1", "Sets the internal state of the RAND() " + "generator for replication purposes", + sys_var::ONLY_SESSION, NO_CMD_LINE, + VALID_RANGE(0, ULONG_MAX), BLOCK_SIZE(1), + NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(0), + ON_UPDATE(update_rand_seed1), ON_READ(read_rand_seed)); + +static bool update_rand_seed2(THD *thd, set_var *var) +{ + if (!var->value) + { + my_error(ER_NO_DEFAULT, MYF(0), var->var->name); + return true; + } + thd->rand.seed2= (ulong) var->save_result.ulonglong_value; + return false; +} +static Sys_var_session_special Sys_rand_seed2( + "rand_seed2", "Sets the internal state of the RAND() " + "generator for replication purposes", + sys_var::ONLY_SESSION, NO_CMD_LINE, + VALID_RANGE(0, ULONG_MAX), BLOCK_SIZE(1), + NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(0), + ON_UPDATE(update_rand_seed2), ON_READ(read_rand_seed)); + +static ulonglong read_error_count(THD *thd) +{ + return thd->warning_info->error_count(); +} +// this really belongs to the SHOW STATUS +static Sys_var_session_special Sys_error_count( + "error_count", "The number of errors that resulted from the " + "last statement that generated messages", + READ_ONLY sys_var::ONLY_SESSION, NO_CMD_LINE, + VALID_RANGE(0, ULONGLONG_MAX), BLOCK_SIZE(1), NO_MUTEX_GUARD, + NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(0), ON_READ(read_error_count)); + +static ulonglong read_warning_count(THD *thd) +{ + return thd->warning_info->warn_count(); +} +// this really belongs to the SHOW STATUS +static Sys_var_session_special Sys_warning_count( + "warning_count", "The number of errors, warnings, and notes " + "that resulted from the last statement that generated messages", + READ_ONLY sys_var::ONLY_SESSION, NO_CMD_LINE, + VALID_RANGE(0, ULONGLONG_MAX), BLOCK_SIZE(1), NO_MUTEX_GUARD, + NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(0), ON_READ(read_warning_count)); + +static Sys_var_ulong Sys_default_week_format( + "default_week_format", + "The default week format used by WEEK() functions", + SESSION_VAR(default_week_format), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, 7), DEFAULT(0), BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_group_concat_max_len( + "group_concat_max_len", + "The maximum length of the result of function GROUP_CONCAT()", + SESSION_VAR(group_concat_max_len), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(4, ULONG_MAX), DEFAULT(1024), BLOCK_SIZE(1)); + +static char *glob_hostname_ptr; +static Sys_var_charptr Sys_hostname( + "hostname", "Server host name", + READ_ONLY GLOBAL_VAR(glob_hostname_ptr), NO_CMD_LINE, + IN_FS_CHARSET, DEFAULT(glob_hostname)); + +#ifndef EMBEDDED_LIBRARY +static Sys_var_charptr Sys_repl_report_host( + "report_host", + "Hostname or IP of the slave to be reported to the master during " + "slave registration. Will appear in the output of SHOW SLAVE HOSTS. " + "Leave unset if you do not want the slave to register itself with the " + "master. Note that it is not sufficient for the master to simply read " + "the IP of the slave off the socket once the slave connects. Due to " + "NAT and other routing issues, that IP may not be valid for connecting " + "to the slave from the master or other hosts", + READ_ONLY GLOBAL_VAR(report_host), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(0)); + +static Sys_var_charptr Sys_repl_report_user( + "report_user", + "The account user name of the slave to be reported to the master " + "during slave registration", + READ_ONLY GLOBAL_VAR(report_user), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(0)); + +static Sys_var_charptr Sys_repl_report_password( + "report_password", + "The account password of the slave to be reported to the master " + "during slave registration", + READ_ONLY GLOBAL_VAR(report_password), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(0)); + +static Sys_var_uint Sys_repl_report_port( + "report_port", + "Port for connecting to slave reported to the master during slave " + "registration. Set it only if the slave is listening on a non-default " + "port or if you have a special tunnel from the master or other clients " + "to the slave. If not sure, leave this option unset", + READ_ONLY GLOBAL_VAR(report_port), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, UINT_MAX), DEFAULT(MYSQL_PORT), BLOCK_SIZE(1)); +#endif + +static Sys_var_mybool Sys_keep_files_on_create( + "keep_files_on_create", + "Don't overwrite stale .MYD and .MYI even if no directory is specified", + SESSION_VAR(keep_files_on_create), CMD_LINE(OPT_ARG), + DEFAULT(FALSE)); + +static char *license; +static Sys_var_charptr Sys_license( + "license", "The type of license the server has", + READ_ONLY GLOBAL_VAR(license), NO_CMD_LINE, IN_SYSTEM_CHARSET, + DEFAULT(STRINGIFY_ARG(LICENSE))); + +static bool check_log_path(sys_var *self, THD *thd, set_var *var) +{ + if (!var->value) + return false; // DEFAULT is ok + + if (!var->save_result.string_value.str) + return true; + + if (var->save_result.string_value.length > FN_REFLEN) + { // path is too long + my_error(ER_PATH_LENGTH, MYF(0), self->name.str); + return true; + } + + char path[FN_REFLEN]; + size_t path_length= unpack_filename(path, var->save_result.string_value.str); + + if (!path_length) + return true; + + MY_STAT f_stat; + + if (my_stat(path, &f_stat, MYF(0))) + { + if (!MY_S_ISREG(f_stat.st_mode) || !(f_stat.st_mode & MY_S_IWRITE)) + return true; // not a regular writable file + return false; + } + + (void) dirname_part(path, var->save_result.string_value.str, &path_length); + + if (var->save_result.string_value.length - path_length >= FN_LEN) + { // filename is too long + my_error(ER_PATH_LENGTH, MYF(0), self->name.str); + return true; + } + + if (!path_length) // no path is good path (remember, relative to datadir) + return false; + + if (my_access(path, (F_OK|W_OK))) + return true; // directory is not writable + + return false; +} +static bool fix_log(char** logname, const char* default_logname, + const char*ext, bool enabled, void (*reopen)(char*)) +{ + if (!*logname) // SET ... = DEFAULT + { + char buff[FN_REFLEN]; + *logname= my_strdup(make_log_name(buff, default_logname, ext), + MYF(MY_FAE+MY_WME)); + if (!*logname) + return true; + } + logger.lock_exclusive(); + mysql_mutex_unlock(&LOCK_global_system_variables); + if (enabled) + reopen(*logname); + logger.unlock(); + mysql_mutex_lock(&LOCK_global_system_variables); + return false; +} +static void reopen_general_log(char* name) +{ + logger.get_log_file_handler()->close(0); + logger.get_log_file_handler()->open_query_log(name); +} +static bool fix_general_log_file(sys_var *self, THD *thd, enum_var_type type) +{ + return fix_log(&opt_logname, default_logfile_name, ".log", opt_log, + reopen_general_log); +} +static Sys_var_charptr Sys_general_log_path( + "general_log_file", "Log connections and queries to given file", + PREALLOCATED GLOBAL_VAR(opt_logname), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(0), NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(check_log_path), ON_UPDATE(fix_general_log_file)); + +static void reopen_slow_log(char* name) +{ + logger.get_slow_log_file_handler()->close(0); + logger.get_slow_log_file_handler()->open_slow_log(name); +} +static bool fix_slow_log_file(sys_var *self, THD *thd, enum_var_type type) +{ + return fix_log(&opt_slow_logname, default_logfile_name, "-slow.log", + opt_slow_log, reopen_slow_log); +} +static Sys_var_charptr Sys_slow_log_path( + "slow_query_log_file", "Log slow queries to given log file. " + "Defaults logging to hostname-slow.log. Must be enabled to activate " + "other slow log options", + PREALLOCATED GLOBAL_VAR(opt_slow_logname), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(0), NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(check_log_path), ON_UPDATE(fix_slow_log_file)); + +/// @todo deprecate these four legacy have_PLUGIN variables and use I_S instead +export SHOW_COMP_OPTION have_csv, have_innodb; +export SHOW_COMP_OPTION have_ndbcluster, have_partitioning; +static Sys_var_have Sys_have_csv( + "have_csv", "have_csv", + READ_ONLY GLOBAL_VAR(have_csv), NO_CMD_LINE); + +static Sys_var_have Sys_have_innodb( + "have_innodb", "have_innodb", + READ_ONLY GLOBAL_VAR(have_innodb), NO_CMD_LINE); + +static Sys_var_have Sys_have_ndbcluster( + "have_ndbcluster", "have_ndbcluster", + READ_ONLY GLOBAL_VAR(have_ndbcluster), NO_CMD_LINE); + +static Sys_var_have Sys_have_partition_db( + "have_partitioning", "have_partitioning", + READ_ONLY GLOBAL_VAR(have_partitioning), NO_CMD_LINE); + +static Sys_var_have Sys_have_compress( + "have_compress", "have_compress", + READ_ONLY GLOBAL_VAR(have_compress), NO_CMD_LINE); + +static Sys_var_have Sys_have_crypt( + "have_crypt", "have_crypt", + READ_ONLY GLOBAL_VAR(have_crypt), NO_CMD_LINE); + +static Sys_var_have Sys_have_dlopen( + "have_dynamic_loading", "have_dynamic_loading", + READ_ONLY GLOBAL_VAR(have_dlopen), NO_CMD_LINE); + +static Sys_var_have Sys_have_geometry( + "have_geometry", "have_geometry", + READ_ONLY GLOBAL_VAR(have_geometry), NO_CMD_LINE); + +static Sys_var_have Sys_have_openssl( + "have_openssl", "have_openssl", + READ_ONLY GLOBAL_VAR(have_ssl), NO_CMD_LINE); + +static Sys_var_have Sys_have_profiling( + "have_profiling", "have_profiling", + READ_ONLY GLOBAL_VAR(have_profiling), NO_CMD_LINE); + +static Sys_var_have Sys_have_query_cache( + "have_query_cache", "have_query_cache", + READ_ONLY GLOBAL_VAR(have_query_cache), NO_CMD_LINE); + +static Sys_var_have Sys_have_rtree_keys( + "have_rtree_keys", "have_rtree_keys", + READ_ONLY GLOBAL_VAR(have_rtree_keys), NO_CMD_LINE); + +static Sys_var_have Sys_have_ssl( + "have_ssl", "have_ssl", + READ_ONLY GLOBAL_VAR(have_ssl), NO_CMD_LINE); + +static Sys_var_have Sys_have_symlink( + "have_symlink", "have_symlink", + READ_ONLY GLOBAL_VAR(have_symlink), NO_CMD_LINE); + +static bool fix_log_state(sys_var *self, THD *thd, enum_var_type type); +static Sys_var_mybool Sys_general_log( + "general_log", "Log connections and queries to a table or log file. " + "Defaults logging to a file hostname.log or a table mysql.general_log" + "if --log-output=TABLE is used", + GLOBAL_VAR(opt_log), CMD_LINE(OPT_ARG), + DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_log_state)); + +// Synonym of "general_log" for consistency with SHOW VARIABLES output +static Sys_var_mybool Sys_log( + "log", "Alias for --general-log. Deprecated", + GLOBAL_VAR(opt_log), NO_CMD_LINE, + DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_log_state), DEPRECATED(70000, "'@@general_log'")); + +static Sys_var_mybool Sys_slow_query_log( + "slow_query_log", + "Log slow queries to a table or log file. Defaults logging to a file " + "hostname-slow.log or a table mysql.slow_log if --log-output=TABLE is " + "used. Must be enabled to activate other slow log options", + GLOBAL_VAR(opt_slow_log), CMD_LINE(OPT_ARG), + DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_log_state)); + +/* Synonym of "slow_query_log" for consistency with SHOW VARIABLES output */ +static Sys_var_mybool Sys_log_slow( + "log_slow_queries", + "Alias for --slow-query-log. Deprecated", + GLOBAL_VAR(opt_slow_log), NO_CMD_LINE, + DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_log_state), DEPRECATED(70000, "'@@slow_query_log'")); + +static bool fix_log_state(sys_var *self, THD *thd, enum_var_type type) +{ + bool res; + my_bool *newvalptr, newval, oldval; + uint log_type; + + if (self == &Sys_general_log || self == &Sys_log) + { + newvalptr= &opt_log; + oldval= logger.get_log_file_handler()->is_open(); + log_type= QUERY_LOG_GENERAL; + } + else if (self == &Sys_slow_query_log || self == &Sys_log_slow) + { + newvalptr= &opt_slow_log; + oldval= logger.get_slow_log_file_handler()->is_open(); + log_type= QUERY_LOG_SLOW; + } + else + DBUG_ASSERT(FALSE); + + newval= *newvalptr; + if (oldval == newval) + return false; + + *newvalptr= oldval; // [de]activate_log_handler works that way (sigh) + + mysql_mutex_unlock(&LOCK_global_system_variables); + if (!newval) + { + logger.deactivate_log_handler(thd, log_type); + res= false; + } + else + res= logger.activate_log_handler(thd, log_type); + mysql_mutex_lock(&LOCK_global_system_variables); + return res; +} + +static bool check_not_empty_set(sys_var *self, THD *thd, set_var *var) +{ + return var->save_result.ulonglong_value == 0; +} +static bool fix_log_output(sys_var *self, THD *thd, enum_var_type type) +{ + logger.lock_exclusive(); + logger.init_slow_log(log_output_options); + logger.init_general_log(log_output_options); + logger.unlock(); + return false; +} + +static Sys_var_set Sys_log_output( + "log_output", "Syntax: log-output=value[,value...], " + "where \"value\" could be TABLE, FILE or NONE", + GLOBAL_VAR(log_output_options), CMD_LINE(REQUIRED_ARG), + log_output_names, DEFAULT(LOG_FILE), NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(check_not_empty_set), ON_UPDATE(fix_log_output)); + +#ifdef HAVE_REPLICATION +static Sys_var_mybool Sys_log_slave_updates( + "log_slave_updates", "Tells the slave to log the updates from " + "the slave thread to the binary log. You will need to turn it on if " + "you plan to daisy-chain the slaves", + READ_ONLY GLOBAL_VAR(opt_log_slave_updates), CMD_LINE(OPT_ARG), + DEFAULT(0)); + +static Sys_var_charptr Sys_relay_log( + "relay_log", "The location and name to use for relay logs", + READ_ONLY GLOBAL_VAR(opt_relay_logname), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(0)); + +static Sys_var_charptr Sys_relay_log_index( + "relay_log_index", "The location and name to use for the file " + "that keeps a list of the last relay logs", + READ_ONLY GLOBAL_VAR(opt_relaylog_index_name), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(0)); + +static Sys_var_charptr Sys_relay_log_info_file( + "relay_log_info_file", "The location and name of the file that " + "remembers where the SQL replication thread is in the relay logs", + READ_ONLY GLOBAL_VAR(relay_log_info_file), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(0)); + +static Sys_var_mybool Sys_relay_log_purge( + "relay_log_purge", "if disabled - do not purge relay logs. " + "if enabled - purge them as soon as they are no more needed", + GLOBAL_VAR(relay_log_purge), CMD_LINE(OPT_ARG), DEFAULT(TRUE)); + +static Sys_var_mybool Sys_relay_log_recovery( + "relay_log_recovery", "Enables automatic relay log recovery " + "right after the database startup, which means that the IO Thread " + "starts re-fetching from the master right after the last transaction " + "processed", + GLOBAL_VAR(relay_log_recovery), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static Sys_var_charptr Sys_slave_load_tmpdir( + "slave_load_tmpdir", "The location where the slave should put " + "its temporary files when replicating a LOAD DATA INFILE command", + READ_ONLY GLOBAL_VAR(slave_load_tmpdir), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(0)); + +static bool fix_slave_net_timeout(sys_var *self, THD *thd, enum_var_type type) +{ + mysql_mutex_lock(&LOCK_active_mi); + DBUG_PRINT("info", ("slave_net_timeout=%lu mi->heartbeat_period=%.3f", + slave_net_timeout, + (active_mi? active_mi->heartbeat_period : 0.0))); + if (active_mi && slave_net_timeout < active_mi->heartbeat_period) + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE, + "The current value for master_heartbeat_period" + " exceeds the new value of `slave_net_timeout' sec." + " A sensible value for the period should be" + " less than the timeout."); + mysql_mutex_unlock(&LOCK_active_mi); + return false; +} +static Sys_var_ulong Sys_slave_net_timeout( + "slave_net_timeout", "Number of seconds to wait for more data " + "from a master/slave connection before aborting the read", + GLOBAL_VAR(slave_net_timeout), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, LONG_TIMEOUT), DEFAULT(SLAVE_NET_TIMEOUT), BLOCK_SIZE(1), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_slave_net_timeout)); + +static bool check_slave_skip_counter(sys_var *self, THD *thd, set_var *var) +{ + bool result= false; + mysql_mutex_lock(&LOCK_active_mi); + mysql_mutex_lock(&active_mi->rli.run_lock); + if (active_mi->rli.slave_running) + { + my_message(ER_SLAVE_MUST_STOP, ER(ER_SLAVE_MUST_STOP), MYF(0)); + result= true; + } + mysql_mutex_unlock(&active_mi->rli.run_lock); + mysql_mutex_unlock(&LOCK_active_mi); + return result; +} +static bool fix_slave_skip_counter(sys_var *self, THD *thd, enum_var_type type) +{ + mysql_mutex_lock(&LOCK_active_mi); + mysql_mutex_lock(&active_mi->rli.run_lock); + /* + The following test should normally never be true as we test this + in the check function; To be safe against multiple + SQL_SLAVE_SKIP_COUNTER request, we do the check anyway + */ + if (!active_mi->rli.slave_running) + { + mysql_mutex_lock(&active_mi->rli.data_lock); + active_mi->rli.slave_skip_counter= sql_slave_skip_counter; + mysql_mutex_unlock(&active_mi->rli.data_lock); + } + mysql_mutex_unlock(&active_mi->rli.run_lock); + mysql_mutex_unlock(&LOCK_active_mi); + return 0; +} +static Sys_var_uint Sys_slave_skip_counter( + "sql_slave_skip_counter", "sql_slave_skip_counter", + GLOBAL_VAR(sql_slave_skip_counter), NO_CMD_LINE, + VALID_RANGE(0, UINT_MAX), DEFAULT(0), BLOCK_SIZE(1), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_slave_skip_counter), + ON_UPDATE(fix_slave_skip_counter)); + +static Sys_var_charptr Sys_slave_skip_errors( + "slave_skip_errors", "Tells the slave thread to continue " + "replication when a query event returns an error from the " + "provided list", + READ_ONLY GLOBAL_VAR(opt_slave_skip_errors), CMD_LINE(REQUIRED_ARG), + IN_SYSTEM_CHARSET, DEFAULT(0)); + +static Sys_var_ulonglong Sys_relay_log_space_limit( + "relay_log_space_limit", "Maximum space to use for all relay logs", + READ_ONLY GLOBAL_VAR(relay_log_space_limit), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, ULONG_MAX), DEFAULT(0), BLOCK_SIZE(1)); + +static Sys_var_uint Sys_sync_relaylog_period( + "sync_relay_log", "Synchronously flush relay log to disk after " + "every #th event. Use 0 (default) to disable synchronous flushing", + GLOBAL_VAR(sync_relaylog_period), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, UINT_MAX), DEFAULT(0), BLOCK_SIZE(1)); + +static Sys_var_uint Sys_sync_relayloginfo_period( + "sync_relay_log_info", "Synchronously flush relay log info " + "to disk after every #th transaction. Use 0 (default) to disable " + "synchronous flushing", + GLOBAL_VAR(sync_relayloginfo_period), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, UINT_MAX), DEFAULT(0), BLOCK_SIZE(1)); +#endif + +static Sys_var_uint Sys_sync_binlog_period( + "sync_binlog", "Synchronously flush binary log to disk after " + "every #th event. Use 0 (default) to disable synchronous flushing", + GLOBAL_VAR(sync_binlog_period), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, UINT_MAX), DEFAULT(0), BLOCK_SIZE(1)); + +static Sys_var_uint Sys_sync_masterinfo_period( + "sync_master_info", "Synchronously flush master info to disk " + "after every #th event. Use 0 (default) to disable synchronous flushing", + GLOBAL_VAR(sync_masterinfo_period), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, UINT_MAX), DEFAULT(0), BLOCK_SIZE(1)); + +#ifdef HAVE_REPLICATION +static Sys_var_ulong Sys_slave_trans_retries( + "slave_transaction_retries", "Number of times the slave SQL " + "thread will retry a transaction in case it failed with a deadlock " + "or elapsed lock wait timeout, before giving up and stopping", + GLOBAL_VAR(slave_trans_retries), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, ULONG_MAX), DEFAULT(10), BLOCK_SIZE(1)); +#endif + +static bool check_locale(sys_var *self, THD *thd, set_var *var) +{ + if (!var->value) + return false; + + MY_LOCALE *locale; + char buff[STRING_BUFFER_USUAL_SIZE]; + if (var->value->result_type() == INT_RESULT) + { + int lcno= (int)var->value->val_int(); + if (!(locale= my_locale_by_number(lcno))) + { + my_error(ER_UNKNOWN_LOCALE, MYF(0), llstr(lcno, buff)); + return true; + } + if (check_not_null(self, thd, var)) + return true; + } + else // STRING_RESULT + { + String str(buff, sizeof(buff), system_charset_info), *res; + if (!(res=var->value->val_str(&str))) + return true; + else if (!(locale= my_locale_by_name(res->c_ptr()))) + { + ErrConvString err(res); + my_error(ER_UNKNOWN_LOCALE, MYF(0), err.ptr()); + return true; + } + } + + var->save_result.ptr= locale; + + if (!locale->errmsgs->errmsgs) + { + mysql_mutex_lock(&LOCK_error_messages); + if (!locale->errmsgs->errmsgs && + read_texts(ERRMSG_FILE, locale->errmsgs->language, + &locale->errmsgs->errmsgs, + ER_ERROR_LAST - ER_ERROR_FIRST + 1)) + { + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR, + "Can't process error message file for locale '%s'", + locale->name); + mysql_mutex_unlock(&LOCK_error_messages); + return true; + } + mysql_mutex_unlock(&LOCK_error_messages); + } + return false; +} +static Sys_var_struct Sys_lc_messages( + "lc_messages", "Set the language used for the error messages", + SESSION_VAR(lc_messages), NO_CMD_LINE, + my_offsetof(MY_LOCALE, name), DEFAULT(&my_default_lc_messages), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_locale)); + +static Sys_var_struct Sys_lc_time_names( + "lc_time_names", "Set the language used for the month " + "names and the days of the week", + SESSION_VAR(lc_time_names), NO_CMD_LINE, + my_offsetof(MY_LOCALE, name), DEFAULT(&my_default_lc_time_names), + NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_locale)); + +static Sys_var_tz Sys_time_zone( + "time_zone", "time_zone", + SESSION_VAR(time_zone), NO_CMD_LINE, + DEFAULT(&default_tz), NO_MUTEX_GUARD, IN_BINLOG); + diff --git a/sql/sys_vars.h b/sql/sys_vars.h new file mode 100644 index 00000000000..ccc36c72786 --- /dev/null +++ b/sql/sys_vars.h @@ -0,0 +1,1612 @@ +/* Copyright (C) 2002-2006 MySQL AB, 2009-2010 Sun Microsystems, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/** + @file + "private" interface to sys_var - server configuration variables. + + This header is included only by the file that contains declarations + of sys_var variables (sys_vars.cc). +*/ + +#include "sys_vars_shared.h" +#include <my_getopt.h> +#include <my_bit.h> +#include <my_dir.h> +#include "keycaches.h" + +/* + a set of mostly trivial (as in f(X)=X) defines below to make system variable + declarations more readable +*/ +#define VALID_RANGE(X,Y) X,Y +#define DEFAULT(X) X +#define BLOCK_SIZE(X) X +#define GLOBAL_VAR(X) sys_var::GLOBAL, (((char*)&(X))-(char*)&global_system_variables), sizeof(X) +#define SESSION_VAR(X) sys_var::SESSION, offsetof(SV, X), sizeof(((SV *)0)->X) +#define SESSION_ONLY(X) sys_var::ONLY_SESSION, offsetof(SV, X), sizeof(((SV *)0)->X) +#define NO_CMD_LINE CMD_LINE(NO_ARG, -1) +/* + the define below means that there's no *second* mutex guard, + LOCK_global_system_variables always guards all system variables +*/ +#define NO_MUTEX_GUARD ((PolyLock*)0) +#define IN_BINLOG sys_var::SESSION_VARIABLE_IN_BINLOG +#define NOT_IN_BINLOG sys_var::VARIABLE_NOT_IN_BINLOG +#define ON_READ(X) X +#define ON_CHECK(X) X +#define ON_UPDATE(X) X +#define READ_ONLY sys_var::READONLY+ +// this means that Sys_var_charptr initial value was malloc()ed +#define PREALLOCATED sys_var::ALLOCATED+ +/* + Sys_var_bit meaning is reversed, like in + @@foreign_key_checks <-> OPTION_NO_FOREIGN_KEY_CHECKS +*/ +#define REVERSE(X) ~(X) +#define DEPRECATED(X, Y) X, Y + +#define session_var(THD, TYPE) (*(TYPE*)session_var_ptr(THD)) +#define global_var(TYPE) (*(TYPE*)global_var_ptr()) + +#if SIZEOF_OFF_T > 4 && defined(BIG_TABLES) +#define GET_HA_ROWS GET_ULL +#else +#define GET_HA_ROWS GET_ULONG +#endif + +enum charset_enum {IN_SYSTEM_CHARSET, IN_FS_CHARSET}; + +static const char *bool_values[3]= {"OFF", "ON", 0}; +TYPELIB bool_typelib={ array_elements(bool_values)-1, "", bool_values, 0 }; + +/** + A small wrapper class to pass getopt arguments as a pair + to the Sys_var_* constructors. It improves type safety and helps + to catch errors in the argument order. +*/ +struct CMD_LINE +{ + int id; + enum get_opt_arg_type arg_type; + CMD_LINE(enum get_opt_arg_type getopt_arg_type, int getopt_id=0) + : id(getopt_id), arg_type(getopt_arg_type) {} +}; + +/** + Sys_var_unsigned template is used to generate Sys_var_* classes + for variables that represent the value as an unsigned integer. + They are Sys_var_uint, Sys_var_ulong, Sys_var_harows, Sys_var_ulonglong. + + An integer variable has a minimal and maximal values, and a "block_size" + (any valid value of the variable must be divisible by the block_size). + + Class specific constructor arguments: min, max, block_size + Backing store: uint, ulong, ha_rows, ulonglong, depending on the Sys_var_* +*/ +template <typename T, ulong ARGT, enum enum_mysql_show_type SHOWT> +class Sys_var_unsigned: public sys_var +{ +public: + Sys_var_unsigned(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + T min_val, T max_val, T def_val, uint block_size, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + uint deprecated_version=0, const char *substitute=0, + int parse_flag= PARSE_NORMAL) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOWT, def_val, lock, binlog_status_arg, + on_check_func, on_update_func, deprecated_version, + substitute, parse_flag) + { + option.var_type= ARGT; + option.min_value= min_val; + option.max_value= max_val; + option.block_size= block_size; + option.u_max_value= (uchar**)max_var_ptr(); + if (max_var_ptr()) + *max_var_ptr()= max_val; + global_var(T)= def_val; + DBUG_ASSERT(size == sizeof(T)); + DBUG_ASSERT(min_val < max_val); + DBUG_ASSERT(min_val <= def_val); + DBUG_ASSERT(max_val >= def_val); + DBUG_ASSERT(block_size > 0); + DBUG_ASSERT(def_val % block_size == 0); + } + bool do_check(THD *thd, set_var *var) + { + my_bool fixed= FALSE; + ulonglong uv; + longlong v; + + v= var->value->val_int(); + if (var->value->unsigned_flag) + uv= (ulonglong) v; + else + uv= (ulonglong) (v < 0 ? 0 : v); + + var->save_result.ulonglong_value= + getopt_ull_limit_value(uv, &option, &fixed); + + if (max_var_ptr() && var->save_result.ulonglong_value > *max_var_ptr()) + var->save_result.ulonglong_value= *max_var_ptr(); + + return throw_bounds_warning(thd, name.str, + var->save_result.ulonglong_value != uv, + var->value->unsigned_flag, v); + } + bool session_update(THD *thd, set_var *var) + { + session_var(thd, T)= var->save_result.ulonglong_value; + return false; + } + bool global_update(THD *thd, set_var *var) + { + global_var(T)= var->save_result.ulonglong_value; + return false; + } + bool check_update_type(Item_result type) + { return type != INT_RESULT; } + void session_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= (ulonglong)*(T*)global_value_ptr(thd, 0); } + void global_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= option.def_value; } + private: + T *max_var_ptr() + { + return scope() == SESSION ? (T*)(((uchar*)&max_system_variables) + offset) + : 0; + } +}; + +typedef Sys_var_unsigned<uint, GET_UINT, SHOW_INT> Sys_var_uint; +typedef Sys_var_unsigned<ulong, GET_ULONG, SHOW_LONG> Sys_var_ulong; +typedef Sys_var_unsigned<ha_rows, GET_HA_ROWS, SHOW_HA_ROWS> Sys_var_harows; +typedef Sys_var_unsigned<ulonglong, GET_ULL, SHOW_LONGLONG> Sys_var_ulonglong; + +/** + Helper class for variables that take values from a TYPELIB +*/ +class Sys_var_typelib: public sys_var +{ +protected: + TYPELIB typelib; +public: + Sys_var_typelib(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, + CMD_LINE getopt, + SHOW_TYPE show_val_type_arg, const char *values[], + ulonglong def_val, PolyLock *lock, + enum binlog_status_enum binlog_status_arg, + on_check_function on_check_func, on_update_function on_update_func, + uint deprecated_version, const char *substitute, int parse_flag= PARSE_NORMAL) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, show_val_type_arg, def_val, lock, + binlog_status_arg, on_check_func, + on_update_func, deprecated_version, substitute, parse_flag) + { + for (typelib.count= 0; values[typelib.count]; typelib.count++) /*no-op */; + typelib.name=""; + typelib.type_names= values; + typelib.type_lengths= 0; // only used by Fields_enum and Field_set + option.typelib= &typelib; + } + bool do_check(THD *thd, set_var *var) // works for enums and my_bool + { + char buff[STRING_BUFFER_USUAL_SIZE]; + String str(buff, sizeof(buff), system_charset_info), *res; + + if (var->value->result_type() == STRING_RESULT) + { + if (!(res=var->value->val_str(&str))) + return true; + else + if (!(var->save_result.ulonglong_value= + find_type(&typelib, res->ptr(), res->length(), false))) + return true; + else + var->save_result.ulonglong_value--; + } + else + { + longlong tmp=var->value->val_int(); + if (tmp < 0 || tmp >= typelib.count) + return true; + else + var->save_result.ulonglong_value= tmp; + } + + return false; + } + bool check_update_type(Item_result type) + { return type != INT_RESULT && type != STRING_RESULT; } +}; + +/** + The class for ENUM variables - variables that take one value from a fixed + list of values. + + Class specific constructor arguments: + char* values[] - 0-terminated list of strings of valid values + + Backing store: uint + + @note + Do *not* use "enum FOO" variables as a backing store, there is no + guarantee that sizeof(enum FOO) == sizeof(uint), there is no guarantee + even that sizeof(enum FOO) == sizeof(enum BAR) +*/ +class Sys_var_enum: public Sys_var_typelib +{ +public: + Sys_var_enum(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + const char *values[], uint def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + uint deprecated_version=0, const char *substitute=0) + : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, + SHOW_CHAR, values, def_val, lock, + binlog_status_arg, on_check_func, on_update_func, + deprecated_version, substitute) + { + option.var_type= GET_ENUM; + global_var(uint)= def_val; + DBUG_ASSERT(def_val < typelib.count); + DBUG_ASSERT(size == sizeof(uint)); + } + bool session_update(THD *thd, set_var *var) + { + session_var(thd, uint)= var->save_result.ulonglong_value; + return false; + } + bool global_update(THD *thd, set_var *var) + { + global_var(uint)= var->save_result.ulonglong_value; + return false; + } + void session_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= global_var(uint); } + void global_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= option.def_value; } + uchar *session_value_ptr(THD *thd, LEX_STRING *base) + { return (uchar*)typelib.type_names[session_var(thd, uint)]; } + uchar *global_value_ptr(THD *thd, LEX_STRING *base) + { return (uchar*)typelib.type_names[global_var(uint)]; } +}; + +/** + The class for boolean variables - a variant of ENUM variables + with the fixed list of values of { OFF , ON } + + Backing store: my_bool +*/ +class Sys_var_mybool: public Sys_var_typelib +{ +public: + Sys_var_mybool(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + my_bool def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + uint deprecated_version=0, const char *substitute=0, + int parse_flag= PARSE_NORMAL) + : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, + SHOW_MY_BOOL, bool_values, def_val, lock, + binlog_status_arg, on_check_func, on_update_func, + deprecated_version, substitute, parse_flag) + { + option.var_type= GET_BOOL; + global_var(my_bool)= def_val; + DBUG_ASSERT(def_val < 2); + DBUG_ASSERT(getopt.arg_type == OPT_ARG || getopt.id == -1); + DBUG_ASSERT(size == sizeof(my_bool)); + } + bool session_update(THD *thd, set_var *var) + { + session_var(thd, my_bool)= var->save_result.ulonglong_value; + return false; + } + bool global_update(THD *thd, set_var *var) + { + global_var(my_bool)= var->save_result.ulonglong_value; + return false; + } + void session_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= (ulonglong)*(my_bool *)global_value_ptr(thd, 0); } + void global_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= option.def_value; } +}; + +/** + The class for string variables. The string can be in character_set_filesystem + or in character_set_system. The string can be allocated with my_malloc() + or not. The state of the initial value is specified in the constructor, + after that it's managed automatically. The value of NULL is supported. + + Class specific constructor arguments: + enum charset_enum is_os_charset_arg + + Backing store: char* + + @note + This class supports only GLOBAL variables, because THD on destruction + does not destroy individual members of SV, there's no way to free + allocated string variables for every thread. +*/ +class Sys_var_charptr: public sys_var +{ +public: + Sys_var_charptr(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + enum charset_enum is_os_charset_arg, + const char *def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + uint deprecated_version=0, const char *substitute=0, + int parse_flag= PARSE_NORMAL) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOW_CHAR_PTR, (intptr)def_val, + lock, binlog_status_arg, on_check_func, on_update_func, + deprecated_version, substitute, parse_flag) + { + is_os_charset= is_os_charset_arg == IN_FS_CHARSET; + /* + use GET_STR_ALLOC - if ALLOCATED it must be *always* allocated, + otherwise (GET_STR) you'll never know whether to free it or not. + (think of an exit because of an error right after my_getopt) + */ + option.var_type= (flags & ALLOCATED) ? GET_STR_ALLOC : GET_STR; + global_var(const char*)= def_val; + DBUG_ASSERT(scope() == GLOBAL); + DBUG_ASSERT(size == sizeof(char *)); + } + ~Sys_var_charptr() + { + if (flags & ALLOCATED) + my_free(global_var(char*), MYF(MY_ALLOW_ZERO_PTR)); + flags&= ~ALLOCATED; + } + bool do_check(THD *thd, set_var *var) + { + char buff[STRING_BUFFER_USUAL_SIZE], buff2[STRING_BUFFER_USUAL_SIZE]; + String str(buff, sizeof(buff), charset(thd)); + String str2(buff2, sizeof(buff2), charset(thd)), *res; + + if (!(res=var->value->val_str(&str))) + var->save_result.string_value.str= 0; + else + { + uint32 unused; + if (String::needs_conversion(res->length(), res->charset(), + charset(thd), &unused)) + { + uint errors; + str2.copy(res->ptr(), res->length(), res->charset(), charset(thd), + &errors); + res=&str2; + + } + var->save_result.string_value.str= thd->strmake(res->ptr(), res->length()); + var->save_result.string_value.length= res->length(); + } + + return false; + } + bool session_update(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + return true; + } + bool global_update(THD *thd, set_var *var) + { + char *new_val, *ptr= var->save_result.string_value.str; + size_t len=var->save_result.string_value.length; + if (ptr) + { + new_val= (char*)my_memdup(ptr, len+1, MYF(MY_WME)); + if (!new_val) return true; + new_val[len]=0; + } + else + new_val= 0; + if (flags & ALLOCATED) + my_free(global_var(char*), MYF(MY_ALLOW_ZERO_PTR)); + flags|= ALLOCATED; + global_var(char*)= new_val; + return false; + } + void session_save_default(THD *thd, set_var *var) + { DBUG_ASSERT(FALSE); } + void global_save_default(THD *thd, set_var *var) + { + char *ptr= (char*)(intptr)option.def_value; + var->save_result.string_value.str= ptr; + var->save_result.string_value.length= ptr ? strlen(ptr) : 0; + } + bool check_update_type(Item_result type) + { return type != STRING_RESULT; } +}; + +/** + The class for string variables. Useful for strings that aren't necessarily + \0-terminated. Otherwise the same as Sys_var_charptr. + + Class specific constructor arguments: + enum charset_enum is_os_charset_arg + + Backing store: LEX_STRING + + @note + Behaves exactly as Sys_var_charptr, only the backing store is different. +*/ +class Sys_var_lexstring: public Sys_var_charptr +{ +public: + Sys_var_lexstring(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + enum charset_enum is_os_charset_arg, + const char *def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + uint deprecated_version=0, const char *substitute=0) + : Sys_var_charptr(name_arg, comment, flag_args, off, sizeof(char*), + getopt, is_os_charset_arg, def_val, lock, binlog_status_arg, + on_check_func, on_update_func, deprecated_version, substitute) + { + global_var(LEX_STRING).length= strlen(def_val); + DBUG_ASSERT(size == sizeof(LEX_STRING)); + *const_cast<SHOW_TYPE*>(&show_val_type)= SHOW_LEX_STRING; + } + bool global_update(THD *thd, set_var *var) + { + if (Sys_var_charptr::global_update(thd, var)) + return true; + global_var(LEX_STRING).length= var->save_result.string_value.length; + return false; + } +}; + +#ifndef DBUG_OFF +/** + @@session.dbug and @@global.dbug variables. + + @@dbug variable differs from other variables in one aspect: + if its value is not assigned in the session, it "points" to the global + value, and so when the global value is changed, the change + immediately takes effect in the session. + + This semantics is intentional, to be able to debug one session from + another. +*/ +class Sys_var_dbug: public sys_var +{ +public: + Sys_var_dbug(const char *name_arg, + const char *comment, int flag_args, + CMD_LINE getopt, + const char *def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + uint deprecated_version=0, const char *substitute=0, + int parse_flag= PARSE_NORMAL) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id, + getopt.arg_type, SHOW_CHAR, (intptr)def_val, + lock, binlog_status_arg, on_check_func, on_update_func, + deprecated_version, substitute, parse_flag) + { option.var_type= GET_NO_ARG; } + bool do_check(THD *thd, set_var *var) + { + char buff[STRING_BUFFER_USUAL_SIZE]; + String str(buff, sizeof(buff), system_charset_info), *res; + + if (!(res=var->value->val_str(&str))) + var->save_result.string_value.str= const_cast<char*>(""); + else + var->save_result.string_value.str= thd->strmake(res->ptr(), res->length()); + return false; + } + bool session_update(THD *thd, set_var *var) + { + const char *val= var->save_result.string_value.str; + if (!var->value) + DBUG_POP(); + else + DBUG_SET(val); + return false; + } + bool global_update(THD *thd, set_var *var) + { + const char *val= var->save_result.string_value.str; + DBUG_SET_INITIAL(val); + return false; + } + void session_save_default(THD *thd, set_var *var) + { } + void global_save_default(THD *thd, set_var *var) + { + char *ptr= (char*)(intptr)option.def_value; + var->save_result.string_value.str= ptr; + } + uchar *session_value_ptr(THD *thd, LEX_STRING *base) + { + char buf[256]; + DBUG_EXPLAIN(buf, sizeof(buf)); + return (uchar*) thd->strdup(buf); + } + uchar *global_value_ptr(THD *thd, LEX_STRING *base) + { + char buf[256]; + DBUG_EXPLAIN_INITIAL(buf, sizeof(buf)); + return (uchar*) thd->strdup(buf); + } + bool check_update_type(Item_result type) + { return type != STRING_RESULT; } +}; +#endif + +#define KEYCACHE_VAR(X) sys_var::GLOBAL,offsetof(KEY_CACHE, X), sizeof(((KEY_CACHE *)0)->X) +#define keycache_var_ptr(KC, OFF) (((uchar*)(KC))+(OFF)) +#define keycache_var(KC, OFF) (*(ulonglong*)keycache_var_ptr(KC, OFF)) +typedef bool (*keycache_update_function)(THD *, KEY_CACHE *, ptrdiff_t, ulonglong); + +/** + The class for keycache_* variables. Supports structured names, + keycache_name.variable_name. + + Class specific constructor arguments: + everything derived from Sys_var_ulonglong + + Backing store: ulonglong + + @note these variables can be only GLOBAL +*/ +class Sys_var_keycache: public Sys_var_ulonglong +{ + keycache_update_function keycache_update; +public: + Sys_var_keycache(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + ulonglong min_val, ulonglong max_val, ulonglong def_val, + ulonglong block_size, PolyLock *lock, + enum binlog_status_enum binlog_status_arg, + on_check_function on_check_func, + keycache_update_function on_update_func, + uint deprecated_version=0, const char *substitute=0) + : Sys_var_ulonglong(name_arg, comment, flag_args, off, size, + getopt, min_val, max_val, def_val, + block_size, lock, binlog_status_arg, on_check_func, 0, + deprecated_version, substitute), + keycache_update(on_update_func) + { + option.var_type|= GET_ASK_ADDR; + option.value= (uchar**)1; // crash me, please + keycache_var(dflt_key_cache, off)= def_val; + DBUG_ASSERT(scope() == GLOBAL); + } + bool global_update(THD *thd, set_var *var) + { + ulonglong new_value= var->save_result.ulonglong_value; + LEX_STRING *base_name= &var->base; + KEY_CACHE *key_cache; + + /* If no basename, assume it's for the key cache named 'default' */ + if (!base_name->length) + base_name= &default_key_cache_base; + + key_cache= get_key_cache(base_name); + + if (!key_cache) + { // Key cache didn't exists */ + if (!new_value) // Tried to delete cache + return false; // Ok, nothing to do + if (!(key_cache= create_key_cache(base_name->str, base_name->length))) + return true; + } + + /** + Abort if some other thread is changing the key cache + @todo This should be changed so that we wait until the previous + assignment is done and then do the new assign + */ + if (key_cache->in_init) + return true; + + return keycache_update(thd, key_cache, offset, new_value); + } + uchar *global_value_ptr(THD *thd, LEX_STRING *base) + { + KEY_CACHE *key_cache= get_key_cache(base); + if (!key_cache) + key_cache= &zero_key_cache; + return keycache_var_ptr(key_cache, offset); + } +}; + +static bool update_buffer_size(THD *thd, KEY_CACHE *key_cache, + ptrdiff_t offset, ulonglong new_value) +{ + bool error= false; + DBUG_ASSERT(offset == offsetof(KEY_CACHE, param_buff_size)); + + if (new_value == 0) + { + if (key_cache == dflt_key_cache) + { + my_error(ER_WARN_CANT_DROP_DEFAULT_KEYCACHE, MYF(0)); + return true; + } + + if (key_cache->key_cache_inited) // If initied + { + /* + Move tables using this key cache to the default key cache + and clear the old key cache. + */ + key_cache->in_init= 1; + mysql_mutex_unlock(&LOCK_global_system_variables); + key_cache->param_buff_size= 0; + ha_resize_key_cache(key_cache); + ha_change_key_cache(key_cache, dflt_key_cache); + /* + We don't delete the key cache as some running threads my still be in + the key cache code with a pointer to the deleted (empty) key cache + */ + mysql_mutex_lock(&LOCK_global_system_variables); + key_cache->in_init= 0; + } + return error; + } + + key_cache->param_buff_size= new_value; + + /* If key cache didn't exist initialize it, else resize it */ + key_cache->in_init= 1; + mysql_mutex_unlock(&LOCK_global_system_variables); + + if (!key_cache->key_cache_inited) + error= ha_init_key_cache(0, key_cache); + else + error= ha_resize_key_cache(key_cache); + + mysql_mutex_lock(&LOCK_global_system_variables); + key_cache->in_init= 0; + + return error; +} + +static bool update_keycache_param(THD *thd, KEY_CACHE *key_cache, + ptrdiff_t offset, ulonglong new_value) +{ + bool error= false; + DBUG_ASSERT(offset != offsetof(KEY_CACHE, param_buff_size)); + + keycache_var(key_cache, offset)= new_value; + + key_cache->in_init= 1; + mysql_mutex_unlock(&LOCK_global_system_variables); + error= ha_resize_key_cache(key_cache); + + mysql_mutex_lock(&LOCK_global_system_variables); + key_cache->in_init= 0; + + return error; +} + +/** + The class for floating point variables + + Class specific constructor arguments: min, max + + Backing store: double +*/ +class Sys_var_double: public sys_var +{ +public: + Sys_var_double(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + double min_val, double max_val, double def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + uint deprecated_version=0, const char *substitute=0, + int parse_flag= PARSE_NORMAL) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOW_DOUBLE, def_val, lock, binlog_status_arg, + on_check_func, on_update_func, deprecated_version, substitute, + parse_flag) + { + option.var_type= GET_DOUBLE; + option.min_value= min_val; + option.max_value= max_val; + global_var(double)= (double)option.def_value; + DBUG_ASSERT(min_val < max_val); + DBUG_ASSERT(min_val <= def_val); + DBUG_ASSERT(max_val >= def_val); + DBUG_ASSERT(size == sizeof(double)); + } + bool do_check(THD *thd, set_var *var) + { + my_bool fixed; + double v= var->value->val_real(); + var->save_result.double_value= getopt_double_limit_value(v, &option, &fixed); + + return throw_bounds_warning(thd, name.str, fixed, v); + } + bool session_update(THD *thd, set_var *var) + { + session_var(thd, double)= var->save_result.double_value; + return false; + } + bool global_update(THD *thd, set_var *var) + { + global_var(double)= var->save_result.double_value; + return false; + } + bool check_update_type(Item_result type) + { + return type != INT_RESULT && type != REAL_RESULT && type != DECIMAL_RESULT; + } + void session_save_default(THD *thd, set_var *var) + { var->save_result.double_value= global_var(double); } + void global_save_default(THD *thd, set_var *var) + { var->save_result.double_value= (double)option.def_value; } +}; + +/** + The class for the @max_user_connections. + It's derived from Sys_var_uint, but non-standard session value + requires a new class. + + Class specific constructor arguments: + everything derived from Sys_var_uint + + Backing store: uint +*/ +class Sys_var_max_user_conn: public Sys_var_uint +{ +public: + Sys_var_max_user_conn(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + uint min_val, uint max_val, uint def_val, + uint block_size, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + uint deprecated_version=0, const char *substitute=0) + : Sys_var_uint(name_arg, comment, SESSION, off, size, getopt, + min_val, max_val, def_val, block_size, + lock, binlog_status_arg, on_check_func, on_update_func, + deprecated_version, substitute) + { } + uchar *session_value_ptr(THD *thd, LEX_STRING *base) + { + if (thd->user_connect && thd->user_connect->user_resources.user_conn) + return (uchar*) &(thd->user_connect->user_resources.user_conn); + return global_value_ptr(thd, base); + } +}; + +// overflow-safe (1 << X)-1 +#define MAX_SET(X) ((((1UL << ((X)-1))-1) << 1) | 1) + +/** + The class for flagset variables - a variant of SET that allows in-place + editing (turning on/off individual bits). String representations looks like + a "flag=val,flag=val,...". Example: @@optimizer_switch + + Class specific constructor arguments: + char* values[] - 0-terminated list of strings of valid values + + Backing store: ulonglong + + @note + the last value in the values[] array should + *always* be the string "default". +*/ +class Sys_var_flagset: public Sys_var_typelib +{ +public: + Sys_var_flagset(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + const char *values[], ulonglong def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + uint deprecated_version=0, const char *substitute=0) + : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, + SHOW_CHAR, values, def_val, lock, + binlog_status_arg, on_check_func, on_update_func, + deprecated_version, substitute) + { + option.var_type= GET_FLAGSET; + global_var(ulonglong)= def_val; + DBUG_ASSERT(typelib.count > 1); + DBUG_ASSERT(typelib.count <= 65); + DBUG_ASSERT(def_val < MAX_SET(typelib.count)); + DBUG_ASSERT(strcmp(values[typelib.count-1], "default") == 0); + DBUG_ASSERT(size == sizeof(ulonglong)); + } + bool do_check(THD *thd, set_var *var) + { + char buff[STRING_BUFFER_USUAL_SIZE]; + String str(buff, sizeof(buff), system_charset_info), *res; + ulonglong default_value, current_value; + if (var->type == OPT_GLOBAL) + { + default_value= option.def_value; + current_value= global_var(ulonglong); + } + else + { + default_value= global_var(ulonglong); + current_value= session_var(thd, ulonglong); + } + + if (var->value->result_type() == STRING_RESULT) + { + if (!(res=var->value->val_str(&str))) + return true; + else + { + char *error; + uint error_len; + + var->save_result.ulonglong_value= + find_set_from_flags(&typelib, + typelib.count, + current_value, + default_value, + res->ptr(), res->length(), + &error, &error_len); + if (error) + { + ErrConvString err(error, error_len, res->charset()); + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr()); + return true; + } + } + } + else + { + longlong tmp=var->value->val_int(); + if ((tmp < 0 && ! var->value->unsigned_flag) + || (ulonglong)tmp > MAX_SET(typelib.count)) + return true; + else + var->save_result.ulonglong_value= tmp; + } + + return false; + } + bool session_update(THD *thd, set_var *var) + { + session_var(thd, ulonglong)= var->save_result.ulonglong_value; + return false; + } + bool global_update(THD *thd, set_var *var) + { + global_var(ulonglong)= var->save_result.ulonglong_value; + return false; + } + void session_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= global_var(ulonglong); } + void global_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= option.def_value; } + uchar *session_value_ptr(THD *thd, LEX_STRING *base) + { + return (uchar*)flagset_to_string(thd, 0, session_var(thd, ulonglong), + typelib.type_names); + } + uchar *global_value_ptr(THD *thd, LEX_STRING *base) + { + return (uchar*)flagset_to_string(thd, 0, global_var(ulonglong), + typelib.type_names); + } +}; + +/** + The class for SET variables - variables taking zero or more values + from the given list. Example: @@sql_mode + + Class specific constructor arguments: + char* values[] - 0-terminated list of strings of valid values + + Backing store: ulonglong +*/ +class Sys_var_set: public Sys_var_typelib +{ +public: + Sys_var_set(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + const char *values[], ulonglong def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + uint deprecated_version=0, const char *substitute=0) + : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, + SHOW_CHAR, values, def_val, lock, + binlog_status_arg, on_check_func, on_update_func, + deprecated_version, substitute) + { + option.var_type= GET_SET; + global_var(ulonglong)= def_val; + DBUG_ASSERT(typelib.count > 0); + DBUG_ASSERT(typelib.count <= 64); + DBUG_ASSERT(def_val < MAX_SET(typelib.count)); + DBUG_ASSERT(size == sizeof(ulonglong)); + } + bool do_check(THD *thd, set_var *var) + { + char buff[STRING_BUFFER_USUAL_SIZE]; + String str(buff, sizeof(buff), system_charset_info), *res; + + if (var->value->result_type() == STRING_RESULT) + { + if (!(res=var->value->val_str(&str))) + return true; + else + { + char *error; + uint error_len; + bool not_used; + + var->save_result.ulonglong_value= + find_set(&typelib, res->ptr(), res->length(), NULL, + &error, &error_len, ¬_used); + /* + note, we only issue an error if error_len > 0. + That is even while empty (zero-length) values are considered + errors by find_set(), these errors are ignored here + */ + if (error_len) + { + ErrConvString err(error, error_len, res->charset()); + my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr()); + return true; + } + } + } + else + { + longlong tmp=var->value->val_int(); + if ((tmp < 0 && ! var->value->unsigned_flag) + || (ulonglong)tmp > MAX_SET(typelib.count)) + return true; + else + var->save_result.ulonglong_value= tmp; + } + + return false; + } + bool session_update(THD *thd, set_var *var) + { + session_var(thd, ulonglong)= var->save_result.ulonglong_value; + return false; + } + bool global_update(THD *thd, set_var *var) + { + global_var(ulonglong)= var->save_result.ulonglong_value; + return false; + } + void session_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= global_var(ulonglong); } + void global_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= option.def_value; } + uchar *session_value_ptr(THD *thd, LEX_STRING *base) + { + return (uchar*)set_to_string(thd, 0, session_var(thd, ulonglong), + typelib.type_names); + } + uchar *global_value_ptr(THD *thd, LEX_STRING *base) + { + return (uchar*)set_to_string(thd, 0, global_var(ulonglong), + typelib.type_names); + } +}; + +/** + The class for variables which value is a plugin. + Example: @@default_storage_engine + + Class specific constructor arguments: + int plugin_type_arg (for example MYSQL_STORAGE_ENGINE_PLUGIN) + + Backing store: plugin_ref + + @note + these variables don't support command-line equivalents, any such + command-line options should be added manually to my_long_options in mysqld.cc +*/ +class Sys_var_plugin: public sys_var +{ + int plugin_type; +public: + Sys_var_plugin(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + int plugin_type_arg, char **def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + uint deprecated_version=0, const char *substitute=0, + int parse_flag= PARSE_NORMAL) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOW_CHAR, (intptr)def_val, + lock, binlog_status_arg, on_check_func, on_update_func, + deprecated_version, substitute, parse_flag), + plugin_type(plugin_type_arg) + { + option.var_type= GET_STR; + DBUG_ASSERT(size == sizeof(plugin_ref)); + DBUG_ASSERT(getopt.id == -1); // force NO_CMD_LINE + } + bool do_check(THD *thd, set_var *var) + { + char buff[STRING_BUFFER_USUAL_SIZE]; + String str(buff,sizeof(buff), system_charset_info), *res; + if (!(res=var->value->val_str(&str))) + var->save_result.plugin= NULL; + else + { + const LEX_STRING pname= { const_cast<char*>(res->ptr()), res->length() }; + plugin_ref plugin; + + // special code for storage engines (e.g. to handle historical aliases) + if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN) + plugin= ha_resolve_by_name(thd, &pname); + else + plugin= my_plugin_lock_by_name(thd, &pname, plugin_type); + if (!plugin) + { + // historically different error code + if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN) + { + ErrConvString err(res); + my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), err.ptr()); + } + return true; + } + var->save_result.plugin= plugin; + } + return false; + } + void do_update(plugin_ref *valptr, plugin_ref newval) + { + plugin_ref oldval= *valptr; + if (oldval != newval) + { + *valptr= my_plugin_lock(NULL, &newval); + plugin_unlock(NULL, oldval); + } + } + bool session_update(THD *thd, set_var *var) + { + do_update((plugin_ref*)session_var_ptr(thd), + var->save_result.plugin); + return false; + } + bool global_update(THD *thd, set_var *var) + { + do_update((plugin_ref*)global_var_ptr(), + var->save_result.plugin); + return false; + } + void session_save_default(THD *thd, set_var *var) + { + plugin_ref plugin= global_var(plugin_ref); + var->save_result.plugin= my_plugin_lock(thd, &plugin); + } + void global_save_default(THD *thd, set_var *var) + { + LEX_STRING pname; + pname.str= *(char**)option.def_value; + pname.length= strlen(pname.str); + + plugin_ref plugin; + if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN) + plugin= ha_resolve_by_name(thd, &pname); + else + plugin= my_plugin_lock_by_name(thd, &pname, plugin_type); + DBUG_ASSERT(plugin); + + var->save_result.plugin= my_plugin_lock(thd, &plugin); + } + bool check_update_type(Item_result type) + { return type != STRING_RESULT; } + uchar *session_value_ptr(THD *thd, LEX_STRING *base) + { + plugin_ref plugin= session_var(thd, plugin_ref); + return (uchar*)(plugin ? thd->strmake(plugin_name(plugin)->str, + plugin_name(plugin)->length) : 0); + } + uchar *global_value_ptr(THD *thd, LEX_STRING *base) + { + plugin_ref plugin= global_var(plugin_ref); + return (uchar*)(plugin ? thd->strmake(plugin_name(plugin)->str, + plugin_name(plugin)->length) : 0); + } +}; + +#if defined(ENABLED_DEBUG_SYNC) +/** + The class for @@debug_sync session-only variable +*/ +class Sys_var_debug_sync :public sys_var +{ +public: + Sys_var_debug_sync(const char *name_arg, + const char *comment, int flag_args, + CMD_LINE getopt, + const char *def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + uint deprecated_version=0, const char *substitute=0, + int parse_flag= PARSE_NORMAL) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id, + getopt.arg_type, SHOW_CHAR, (intptr)def_val, + lock, binlog_status_arg, on_check_func, on_update_func, + deprecated_version, substitute, parse_flag) + { + DBUG_ASSERT(scope() == ONLY_SESSION); + option.var_type= GET_NO_ARG; + } + bool do_check(THD *thd, set_var *var) + { + char buff[STRING_BUFFER_USUAL_SIZE]; + String str(buff, sizeof(buff), system_charset_info), *res; + + if (!(res=var->value->val_str(&str))) + var->save_result.string_value.str= const_cast<char*>(""); + else + var->save_result.string_value.str= thd->strmake(res->ptr(), res->length()); + return false; + } + bool session_update(THD *thd, set_var *var) + { + extern bool debug_sync_update(THD *thd, char *val_str); + return debug_sync_update(thd, var->save_result.string_value.str); + } + bool global_update(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + return true; + } + void session_save_default(THD *thd, set_var *var) + { + var->save_result.string_value.str= const_cast<char*>(""); + var->save_result.string_value.length= 0; + } + void global_save_default(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + } + uchar *session_value_ptr(THD *thd, LEX_STRING *base) + { + extern uchar *debug_sync_value_ptr(THD *thd); + return debug_sync_value_ptr(thd); + } + uchar *global_value_ptr(THD *thd, LEX_STRING *base) + { + DBUG_ASSERT(FALSE); + return 0; + } + bool check_update_type(Item_result type) + { return type != STRING_RESULT; } +}; +#endif /* defined(ENABLED_DEBUG_SYNC) */ + +/** + The class for bit variables - a variant of boolean that stores the value + in a bit. + + Class specific constructor arguments: + ulonglong bitmask_arg - the mask for the bit to set in the ulonglong + backing store + + Backing store: ulonglong + + @note + This class supports the "reverse" semantics, when the value of the bit + being 0 corresponds to the value of variable being set. To activate it + use REVERSE(bitmask) instead of simply bitmask in the constructor. + + @note + variables of this class cannot be set from the command line as + my_getopt does not support bits. +*/ +class Sys_var_bit: public Sys_var_typelib +{ + ulonglong bitmask; + bool reverse_semantics; + void set(uchar *ptr, ulonglong value) + { + if ((value != 0) ^ reverse_semantics) + (*(ulonglong *)ptr)|= bitmask; + else + (*(ulonglong *)ptr)&= ~bitmask; + } +public: + Sys_var_bit(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + ulonglong bitmask_arg, my_bool def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + uint deprecated_version=0, const char *substitute=0) + : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, + SHOW_MY_BOOL, bool_values, def_val, lock, + binlog_status_arg, on_check_func, on_update_func, + deprecated_version, substitute) + { + option.var_type= GET_BOOL; + reverse_semantics= my_count_bits(bitmask_arg) > 1; + bitmask= reverse_semantics ? ~bitmask_arg : bitmask_arg; + set(global_var_ptr(), def_val); + DBUG_ASSERT(def_val < 2); + DBUG_ASSERT(getopt.id == -1); // force NO_CMD_LINE + DBUG_ASSERT(size == sizeof(ulonglong)); + } + bool session_update(THD *thd, set_var *var) + { + set(session_var_ptr(thd), var->save_result.ulonglong_value); + return false; + } + bool global_update(THD *thd, set_var *var) + { + set(global_var_ptr(), var->save_result.ulonglong_value); + return false; + } + void session_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= global_var(ulonglong) & bitmask; } + void global_save_default(THD *thd, set_var *var) + { var->save_result.ulonglong_value= option.def_value; } + uchar *session_value_ptr(THD *thd, LEX_STRING *base) + { + thd->sys_var_tmp.my_bool_value= reverse_semantics ^ + ((session_var(thd, ulonglong) & bitmask) != 0); + return (uchar*) &thd->sys_var_tmp.my_bool_value; + } + uchar *global_value_ptr(THD *thd, LEX_STRING *base) + { + thd->sys_var_tmp.my_bool_value= reverse_semantics ^ + ((global_var(ulonglong) & bitmask) != 0); + return (uchar*) &thd->sys_var_tmp.my_bool_value; + } +}; + +/** + The class for variables that have a special meaning for a session, + such as @@timestamp or @@rnd_seed1, their values typically cannot be read + from SV structure, and a special "read" callback is provided. + + Class specific constructor arguments: + everything derived from Sys_var_ulonglong + session_special_read_function read_func_arg + + Backing store: ulonglong + + @note + These variables are session-only, global or command-line equivalents + are not supported as they're generally meaningless. +*/ +class Sys_var_session_special: public Sys_var_ulonglong +{ + typedef bool (*session_special_update_function)(THD *thd, set_var *var); + typedef ulonglong (*session_special_read_function)(THD *thd); + + session_special_read_function read_func; + session_special_update_function update_func; +public: + Sys_var_session_special(const char *name_arg, + const char *comment, int flag_args, + CMD_LINE getopt, + ulonglong min_val, ulonglong max_val, ulonglong block_size, + PolyLock *lock, enum binlog_status_enum binlog_status_arg, + on_check_function on_check_func, + session_special_update_function update_func_arg, + session_special_read_function read_func_arg, + uint deprecated_version=0, const char *substitute=0) + : Sys_var_ulonglong(name_arg, comment, flag_args, 0, + sizeof(ulonglong), getopt, min_val, + max_val, 0, block_size, lock, binlog_status_arg, on_check_func, 0, + deprecated_version, substitute), + read_func(read_func_arg), update_func(update_func_arg) + { + DBUG_ASSERT(scope() == ONLY_SESSION); + DBUG_ASSERT(getopt.id == -1); // NO_CMD_LINE, because the offset is fake + } + bool session_update(THD *thd, set_var *var) + { return update_func(thd, var); } + bool global_update(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + return true; + } + void session_save_default(THD *thd, set_var *var) + { var->value= 0; } + void global_save_default(THD *thd, set_var *var) + { DBUG_ASSERT(FALSE); } + uchar *session_value_ptr(THD *thd, LEX_STRING *base) + { + thd->sys_var_tmp.ulonglong_value= read_func(thd); + return (uchar*) &thd->sys_var_tmp.ulonglong_value; + } + uchar *global_value_ptr(THD *thd, LEX_STRING *base) + { + DBUG_ASSERT(FALSE); + return 0; + } +}; + +/** + The class for read-only variables that show whether a particular + feature is supported by the server. Example: have_compression + + Backing store: enum SHOW_COMP_OPTION + + @note + These variables are necessarily read-only, only global, and have no + command-line equivalent. +*/ +class Sys_var_have: public sys_var +{ +public: + Sys_var_have(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + uint deprecated_version=0, const char *substitute=0, + int parse_flag= PARSE_NORMAL) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOW_CHAR, 0, + lock, binlog_status_arg, on_check_func, on_update_func, + deprecated_version, substitute, parse_flag) + { + DBUG_ASSERT(scope() == GLOBAL); + DBUG_ASSERT(getopt.id == -1); + DBUG_ASSERT(lock == 0); + DBUG_ASSERT(binlog_status_arg == VARIABLE_NOT_IN_BINLOG); + DBUG_ASSERT(is_readonly()); + DBUG_ASSERT(on_update == 0); + DBUG_ASSERT(size == sizeof(enum SHOW_COMP_OPTION)); + } + bool do_check(THD *thd, set_var *var) { + DBUG_ASSERT(FALSE); + return true; + } + bool session_update(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + return true; + } + bool global_update(THD *thd, set_var *var) + { + DBUG_ASSERT(FALSE); + return true; + } + void session_save_default(THD *thd, set_var *var) { } + void global_save_default(THD *thd, set_var *var) { } + uchar *session_value_ptr(THD *thd, LEX_STRING *base) + { + DBUG_ASSERT(FALSE); + return 0; + } + uchar *global_value_ptr(THD *thd, LEX_STRING *base) + { + return (uchar*)show_comp_option_name[global_var(enum SHOW_COMP_OPTION)]; + } + bool check_update_type(Item_result type) { return false; } +}; + +/** + Generic class for variables for storing entities that are internally + represented as structures, have names, and possibly can be referred to by + numbers. Examples: character sets, collations, locales, + + Class specific constructor arguments: + ptrdiff_t name_offset - offset of the 'name' field in the structure + + Backing store: void* + + @note + As every such a structure requires special treatment from my_getopt, + these variables don't support command-line equivalents, any such + command-line options should be added manually to my_long_options in mysqld.cc +*/ +class Sys_var_struct: public sys_var +{ + ptrdiff_t name_offset; // offset to the 'name' property in the structure +public: + Sys_var_struct(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + ptrdiff_t name_off, void *def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + uint deprecated_version=0, const char *substitute=0, + int parse_flag= PARSE_NORMAL) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOW_CHAR, (intptr)def_val, + lock, binlog_status_arg, on_check_func, on_update_func, + deprecated_version, substitute, parse_flag), + name_offset(name_off) + { + option.var_type= GET_STR; + /* + struct variables are special on the command line - often (e.g. for + charsets) the name cannot be immediately resolved, but only after all + options (in particular, basedir) are parsed. + + thus all struct command-line options should be added manually + to my_long_options in mysqld.cc + */ + DBUG_ASSERT(getopt.id == -1); + DBUG_ASSERT(size == sizeof(void *)); + } + bool do_check(THD *thd, set_var *var) + { return false; } + bool session_update(THD *thd, set_var *var) + { + session_var(thd, void*)= var->save_result.ptr; + return false; + } + bool global_update(THD *thd, set_var *var) + { + global_var(void*)= var->save_result.ptr; + return false; + } + void session_save_default(THD *thd, set_var *var) + { var->save_result.ptr= global_var(void*); } + void global_save_default(THD *thd, set_var *var) + { var->save_result.ptr= *(void**)option.def_value; } + bool check_update_type(Item_result type) + { return type != INT_RESULT && type != STRING_RESULT; } + uchar *session_value_ptr(THD *thd, LEX_STRING *base) + { + uchar *ptr= session_var(thd, uchar*); + return ptr ? *(uchar**)(ptr+name_offset) : 0; + } + uchar *global_value_ptr(THD *thd, LEX_STRING *base) + { + uchar *ptr= global_var(uchar*); + return ptr ? *(uchar**)(ptr+name_offset) : 0; + } +}; + +/** + The class for variables that store time zones + + Backing store: Time_zone* + + @note + Time zones cannot be supported directly by my_getopt, thus + these variables don't support command-line equivalents, any such + command-line options should be added manually to my_long_options in mysqld.cc +*/ +class Sys_var_tz: public sys_var +{ +public: + Sys_var_tz(const char *name_arg, + const char *comment, int flag_args, ptrdiff_t off, size_t size, + CMD_LINE getopt, + Time_zone **def_val, PolyLock *lock=0, + enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, + on_check_function on_check_func=0, + on_update_function on_update_func=0, + uint deprecated_version=0, const char *substitute=0, + int parse_flag= PARSE_NORMAL) + : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, + getopt.arg_type, SHOW_CHAR, (intptr)def_val, + lock, binlog_status_arg, on_check_func, on_update_func, + deprecated_version, substitute, parse_flag) + { + DBUG_ASSERT(getopt.id == -1); + DBUG_ASSERT(size == sizeof(Time_zone *)); + } + bool do_check(THD *thd, set_var *var) + { + char buff[MAX_TIME_ZONE_NAME_LENGTH]; + String str(buff, sizeof(buff), &my_charset_latin1); + String *res= var->value->val_str(&str); + + if (!res) + return true; + + if (!(var->save_result.time_zone= my_tz_find(thd, res))) + { + ErrConvString err(res); + my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), err.ptr()); + return true; + } + return false; + } + bool session_update(THD *thd, set_var *var) + { + session_var(thd, Time_zone*)= var->save_result.time_zone; + return false; + } + bool global_update(THD *thd, set_var *var) + { + global_var(Time_zone*)= var->save_result.time_zone; + return false; + } + void session_save_default(THD *thd, set_var *var) + { + var->save_result.time_zone= global_var(Time_zone*); + } + void global_save_default(THD *thd, set_var *var) + { + var->save_result.time_zone= + *(Time_zone**)(intptr)option.def_value; + } + uchar *session_value_ptr(THD *thd, LEX_STRING *base) + { + /* + This is an ugly fix for replication: we don't replicate properly queries + invoking system variables' values to update tables; but + CONVERT_TZ(,,@@session.time_zone) is so popular that we make it + replicable (i.e. we tell the binlog code to store the session + timezone). If it's the global value which was used we can't replicate + (binlog code stores session value only). + */ + thd->time_zone_used= 1; + return (uchar *)(session_var(thd, Time_zone*)->get_name()->ptr()); + } + uchar *global_value_ptr(THD *thd, LEX_STRING *base) + { + return (uchar *)(global_var(Time_zone*)->get_name()->ptr()); + } + bool check_update_type(Item_result type) + { return type != STRING_RESULT; } +}; + +/**************************************************************************** + Used templates +****************************************************************************/ + +#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION +template class List<set_var_base>; +template class List_iterator_fast<set_var_base>; +template class Sys_var_unsigned<uint, GET_UINT, SHOW_INT>; +template class Sys_var_unsigned<ulong, GET_ULONG, SHOW_LONG>; +template class Sys_var_unsigned<ha_rows, GET_HA_ROWS, SHOW_HA_ROWS>; +template class Sys_var_unsigned<ulonglong, GET_ULL, SHOW_LONGLONG>; +#endif + diff --git a/sql/sys_vars_shared.h b/sql/sys_vars_shared.h new file mode 100644 index 00000000000..a8ef9034715 --- /dev/null +++ b/sql/sys_vars_shared.h @@ -0,0 +1,81 @@ +/* Copyright (C) 2002-2006 MySQL AB, 2009-2010 Sun Microsystems, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/** + @file + "protected" interface to sys_var - server configuration variables. + + This header is included by files implementing support and utility + functions of sys_var's (set_var.cc) and files implementing + classes in the sys_var hierarchy (sql_plugin.cc) +*/ + +#include <mysql_priv.h> +#include "set_var.h" + +extern bool throw_bounds_warning(THD *thd, const char *name, + bool fixed, bool is_unsigned, longlong v); +extern bool throw_bounds_warning(THD *thd, const char *name, bool fixed, + double v); +extern sys_var *intern_find_sys_var(const char *str, uint length); + +extern sys_var_chain all_sys_vars; + +/** wrapper to hide a mutex and an rwlock under a common interface */ +class PolyLock +{ +public: + virtual void rdlock()= 0; + virtual void wrlock()= 0; + virtual void unlock()= 0; + virtual ~PolyLock() {} +}; + +class PolyLock_mutex: public PolyLock +{ + mysql_mutex_t *mutex; +public: + PolyLock_mutex(mysql_mutex_t *arg): mutex(arg) {} + void rdlock() { mysql_mutex_lock(mutex); } + void wrlock() { mysql_mutex_lock(mutex); } + void unlock() { mysql_mutex_unlock(mutex); } +}; + +class PolyLock_rwlock: public PolyLock +{ + mysql_rwlock_t *rwlock; +public: + PolyLock_rwlock(mysql_rwlock_t *arg): rwlock(arg) {} + void rdlock() { mysql_rwlock_rdlock(rwlock); } + void wrlock() { mysql_rwlock_wrlock(rwlock); } + void unlock() { mysql_rwlock_unlock(rwlock); } +}; + +class AutoWLock +{ + PolyLock *lock; +public: + AutoWLock(PolyLock *l) : lock(l) { if (lock) lock->wrlock(); } + ~AutoWLock() { if (lock) lock->unlock(); } +}; + +class AutoRLock +{ + PolyLock *lock; +public: + AutoRLock(PolyLock *l) : lock(l) { if (lock) lock->rdlock(); } + ~AutoRLock() { if (lock) lock->unlock(); } +}; + diff --git a/sql/table.cc b/sql/table.cc index 6841efee54e..3e2e5adc2c7 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,6 +24,9 @@ /* INFORMATION_SCHEMA name */ LEX_STRING INFORMATION_SCHEMA_NAME= {C_STRING_WITH_LEN("information_schema")}; +/* PERFORMANCE_SCHEMA name */ +LEX_STRING PERFORMANCE_SCHEMA_DB_NAME= {C_STRING_WITH_LEN("performance_schema")}; + /* MYSQL_SCHEMA name */ LEX_STRING MYSQL_SCHEMA_NAME= {C_STRING_WITH_LEN("mysql")}; @@ -212,36 +215,34 @@ TABLE_CATEGORY get_table_category(const LEX_STRING *db, const LEX_STRING *name) DBUG_ASSERT(db != NULL); DBUG_ASSERT(name != NULL); - if (is_schema_db(db->str, db->length)) - { + if (is_infoschema_db(db->str, db->length)) return TABLE_CATEGORY_INFORMATION; - } + + if ((db->length == PERFORMANCE_SCHEMA_DB_NAME.length) && + (my_strcasecmp(system_charset_info, + PERFORMANCE_SCHEMA_DB_NAME.str, + db->str) == 0)) + return TABLE_CATEGORY_PERFORMANCE; if ((db->length == MYSQL_SCHEMA_NAME.length) && (my_strcasecmp(system_charset_info, - MYSQL_SCHEMA_NAME.str, - db->str) == 0)) + MYSQL_SCHEMA_NAME.str, + db->str) == 0)) { if (is_system_table_name(name->str, name->length)) - { return TABLE_CATEGORY_SYSTEM; - } if ((name->length == GENERAL_LOG_NAME.length) && (my_strcasecmp(system_charset_info, - GENERAL_LOG_NAME.str, - name->str) == 0)) - { - return TABLE_CATEGORY_PERFORMANCE; - } + GENERAL_LOG_NAME.str, + name->str) == 0)) + return TABLE_CATEGORY_LOG; if ((name->length == SLOW_LOG_NAME.length) && (my_strcasecmp(system_charset_info, - SLOW_LOG_NAME.str, - name->str) == 0)) - { - return TABLE_CATEGORY_PERFORMANCE; - } + SLOW_LOG_NAME.str, + name->str) == 0)) + return TABLE_CATEGORY_LOG; } return TABLE_CATEGORY_USER; @@ -314,8 +315,8 @@ TABLE_SHARE *alloc_table_share(TABLE_LIST *table_list, char *key, share->cached_row_logging_check= -1; memcpy((char*) &share->mem_root, (char*) &mem_root, sizeof(mem_root)); - pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST); - pthread_cond_init(&share->cond, NULL); + mysql_mutex_init(key_TABLE_SHARE_mutex, &share->mutex, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_TABLE_SHARE_cond, &share->cond, NULL); } DBUG_RETURN(share); } @@ -412,13 +413,13 @@ void free_table_share(TABLE_SHARE *share) /* share->mutex is locked in release_table_share() */ while (share->waiting_on_cond) { - pthread_cond_broadcast(&share->cond); - pthread_cond_wait(&share->cond, &share->mutex); + mysql_cond_broadcast(&share->cond); + mysql_cond_wait(&share->cond, &share->mutex); } /* No thread refers to this anymore */ - pthread_mutex_unlock(&share->mutex); - pthread_mutex_destroy(&share->mutex); - pthread_cond_destroy(&share->cond); + mysql_mutex_unlock(&share->mutex); + mysql_mutex_destroy(&share->mutex); + mysql_cond_destroy(&share->cond); } my_hash_free(&share->name_hash); @@ -536,7 +537,8 @@ int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags) disk_buff= NULL; strxmov(path, share->normalized_path.str, reg_ext, NullS); - if ((file= my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0) + if ((file= mysql_file_open(key_file_frm, + path, O_RDONLY | O_SHARE, MYF(0))) < 0) { /* We don't try to open 5.0 unencoded name, if @@ -547,7 +549,7 @@ int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags) - non-encoded db or table name contain "#mysql50#" prefix. This kind of tables must have been opened only by the - my_open() above. + mysql_file_open() above. */ if (strchr(share->table_name.str, '@') || !strncmp(share->db.str, MYSQL50_TABLE_NAME_PREFIX, @@ -573,7 +575,8 @@ int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags) so no need to check the old file name. */ if (length == share->normalized_path.length || - ((file= my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0)) + ((file= mysql_file_open(key_file_frm, + path, O_RDONLY | O_SHARE, MYF(0))) < 0)) goto err_not_open; /* Unencoded 5.0 table name found */ @@ -583,7 +586,7 @@ int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags) } error= 4; - if (my_read(file, head, 64, MYF(MY_NABP))) + if (mysql_file_read(file, head, 64, MYF(MY_NABP))) goto err; if (head[0] == (uchar) 254 && head[1] == 1) @@ -636,7 +639,7 @@ int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags) thd->status_var.opened_shares++; err: - my_close(file, MYF(MY_WME)); + mysql_file_close(file, MYF(MY_WME)); err_not_open: if (error && !error_given) @@ -750,7 +753,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, /* Read keyinformation */ key_info_length= (uint) uint2korr(head+28); - VOID(my_seek(file,(ulong) uint2korr(head+6),MY_SEEK_SET,MYF(0))); + mysql_file_seek(file, (ulong) uint2korr(head+6), MY_SEEK_SET, MYF(0)); if (read_string(file,(uchar**) &disk_buff,key_info_length)) goto err; /* purecov: inspected */ if (disk_buff[0] & 0x80) @@ -854,8 +857,8 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, DBUG_PRINT("info", ("extra segment size is %u bytes", n_length)); if (!(next_chunk= buff= (uchar*) my_malloc(n_length, MYF(MY_WME)))) goto err; - if (my_pread(file, buff, n_length, record_offset + share->reclength, - MYF(MY_NABP))) + if (mysql_file_pread(file, buff, n_length, record_offset + share->reclength, + MYF(MY_NABP))) { my_free(buff, MYF(0)); goto err; @@ -931,6 +934,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, { /* purecov: begin inspected */ error= 8; + name.str[name.length]=0; my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), name.str); my_free(buff, MYF(0)); goto err; @@ -1023,12 +1027,12 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, rec_buff_length))) goto err; /* purecov: inspected */ share->default_values= record; - if (my_pread(file, record, (size_t) share->reclength, - record_offset, MYF(MY_NABP))) + if (mysql_file_pread(file, record, (size_t) share->reclength, + record_offset, MYF(MY_NABP))) goto err; /* purecov: inspected */ - VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0))); - if (my_read(file, head,288,MYF(MY_NABP))) + mysql_file_seek(file, pos, MY_SEEK_SET, MYF(0)); + if (mysql_file_read(file, head, 288, MYF(MY_NABP))) goto err; #ifdef HAVE_CRYPTED_FRM if (crypted) @@ -1403,12 +1407,6 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, keyinfo->extra_length+=HA_KEY_BLOB_LENGTH; key_part->store_length+=HA_KEY_BLOB_LENGTH; keyinfo->key_length+= HA_KEY_BLOB_LENGTH; - /* - Mark that there may be many matching values for one key - combination ('a', 'a ', 'a '...) - */ - if (!(field->flags & BINARY_FLAG)) - keyinfo->flags|= HA_END_SPACE_KEY; } if (field->type() == MYSQL_TYPE_BIT) key_part->key_part_flag|= HA_BIT_PART; @@ -1654,9 +1652,6 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, DBUG_PRINT("enter",("name: '%s.%s' form: 0x%lx", share->db.str, share->table_name.str, (long) outparam)); - /* Parsing of partitioning information from .frm needs thd->lex set up. */ - DBUG_ASSERT(thd->lex->is_lex_started); - error= 1; bzero((char*) outparam, sizeof(*outparam)); outparam->in_use= thd; @@ -2064,11 +2059,11 @@ ulong get_form_pos(File file, uchar *head, TYPELIB *save_names) if (names) { length=uint2korr(head+4); - VOID(my_seek(file,64L,MY_SEEK_SET,MYF(0))); + mysql_file_seek(file, 64L, MY_SEEK_SET, MYF(0)); if (!(buf= (uchar*) my_malloc((size_t) length+a_length+names*4, MYF(MY_WME))) || - my_read(file, buf+a_length, (size_t) (length+names*4), - MYF(MY_NABP))) + mysql_file_read(file, buf+a_length, (size_t) (length+names*4), + MYF(MY_NABP))) { /* purecov: inspected */ x_free((uchar*) buf); /* purecov: inspected */ DBUG_RETURN(0L); /* purecov: inspected */ @@ -2106,7 +2101,7 @@ int read_string(File file, uchar**to, size_t length) x_free(*to); if (!(*to= (uchar*) my_malloc(length+1,MYF(MY_WME))) || - my_read(file, *to, length,MYF(MY_NABP))) + mysql_file_read(file, *to, length, MYF(MY_NABP))) { x_free(*to); /* purecov: inspected */ *to= 0; /* purecov: inspected */ @@ -2138,23 +2133,24 @@ ulong make_new_entry(File file, uchar *fileinfo, TYPELIB *formnames, { /* Expand file */ newpos+=IO_SIZE; int4store(fileinfo+10,newpos); - endpos=(ulong) my_seek(file,0L,MY_SEEK_END,MYF(0));/* Copy from file-end */ + /* Copy from file-end */ + endpos= (ulong) mysql_file_seek(file, 0L, MY_SEEK_END, MYF(0)); bufflength= (uint) (endpos & (IO_SIZE-1)); /* IO_SIZE is a power of 2 */ while (endpos > maxlength) { - VOID(my_seek(file,(ulong) (endpos-bufflength),MY_SEEK_SET,MYF(0))); - if (my_read(file, buff, bufflength, MYF(MY_NABP+MY_WME))) + mysql_file_seek(file, (ulong) (endpos-bufflength), MY_SEEK_SET, MYF(0)); + if (mysql_file_read(file, buff, bufflength, MYF(MY_NABP+MY_WME))) DBUG_RETURN(0L); - VOID(my_seek(file,(ulong) (endpos-bufflength+IO_SIZE),MY_SEEK_SET, - MYF(0))); - if ((my_write(file, buff,bufflength,MYF(MY_NABP+MY_WME)))) + mysql_file_seek(file, (ulong) (endpos-bufflength+IO_SIZE), MY_SEEK_SET, + MYF(0)); + if ((mysql_file_write(file, buff, bufflength, MYF(MY_NABP+MY_WME)))) DBUG_RETURN(0); endpos-=bufflength; bufflength=IO_SIZE; } bzero(buff,IO_SIZE); /* Null new block */ - VOID(my_seek(file,(ulong) maxlength,MY_SEEK_SET,MYF(0))); - if (my_write(file,buff,bufflength,MYF(MY_NABP+MY_WME))) + mysql_file_seek(file, (ulong) maxlength, MY_SEEK_SET, MYF(0)); + if (mysql_file_write(file, buff, bufflength, MYF(MY_NABP+MY_WME))) DBUG_RETURN(0L); maxlength+=IO_SIZE; /* Fix old ref */ int2store(fileinfo+6,maxlength); @@ -2169,20 +2165,21 @@ ulong make_new_entry(File file, uchar *fileinfo, TYPELIB *formnames, if (n_length == 1 ) { /* First name */ length++; - VOID(strxmov((char*) buff,"/",newname,"/",NullS)); + (void) strxmov((char*) buff,"/",newname,"/",NullS); } else - VOID(strxmov((char*) buff,newname,"/",NullS)); /* purecov: inspected */ - VOID(my_seek(file,63L+(ulong) n_length,MY_SEEK_SET,MYF(0))); - if (my_write(file, buff, (size_t) length+1,MYF(MY_NABP+MY_WME)) || - (names && my_write(file,(uchar*) (*formnames->type_names+n_length-1), - names*4, MYF(MY_NABP+MY_WME))) || - my_write(file, fileinfo+10, 4,MYF(MY_NABP+MY_WME))) + (void) strxmov((char*) buff,newname,"/",NullS); /* purecov: inspected */ + mysql_file_seek(file, 63L+(ulong) n_length, MY_SEEK_SET, MYF(0)); + if (mysql_file_write(file, buff, (size_t) length+1, MYF(MY_NABP+MY_WME)) || + (names && mysql_file_write(file, + (uchar*) (*formnames->type_names+n_length-1), + names*4, MYF(MY_NABP+MY_WME))) || + mysql_file_write(file, fileinfo+10, 4, MYF(MY_NABP+MY_WME))) DBUG_RETURN(0L); /* purecov: inspected */ int2store(fileinfo+8,names+1); int2store(fileinfo+4,n_length+length); - VOID(my_chsize(file, newpos, 0, MYF(MY_WME)));/* Append file with '\0' */ + (void) mysql_file_chsize(file, newpos, 0, MYF(MY_WME));/* Append file with '\0' */ DBUG_RETURN(newpos); } /* make_new_entry */ @@ -2464,7 +2461,8 @@ File create_frm(THD *thd, const char *name, const char *db, if (create_info->min_rows > UINT_MAX32) create_info->min_rows= UINT_MAX32; - if ((file= my_create(name, CREATE_MODE, create_flags, MYF(0))) >= 0) + if ((file= mysql_file_create(key_file_frm, + name, CREATE_MODE, create_flags, MYF(0))) >= 0) { uint key_length, tmp_key_length, tmp, csid; bzero((char*) fileinfo,64); @@ -2534,10 +2532,10 @@ File create_frm(THD *thd, const char *name, const char *db, bzero(fill,IO_SIZE); for (; length > IO_SIZE ; length-= IO_SIZE) { - if (my_write(file,fill, IO_SIZE, MYF(MY_WME | MY_NABP))) + if (mysql_file_write(file, fill, IO_SIZE, MYF(MY_WME | MY_NABP))) { - VOID(my_close(file,MYF(0))); - VOID(my_delete(name,MYF(0))); + (void) mysql_file_close(file, MYF(0)); + (void) mysql_file_delete(key_file_frm, name, MYF(0)); return(-1); } } @@ -2574,9 +2572,9 @@ int rename_file_ext(const char * from,const char * to,const char * ext) { char from_b[FN_REFLEN],to_b[FN_REFLEN]; - VOID(strxmov(from_b,from,ext,NullS)); - VOID(strxmov(to_b,to,ext,NullS)); - return (my_rename(from_b,to_b,MYF(MY_WME))); + (void) strxmov(from_b,from,ext,NullS); + (void) strxmov(to_b,to,ext,NullS); + return (mysql_file_rename(key_file_frm, from_b, to_b, MYF(MY_WME))); } @@ -3940,7 +3938,8 @@ const char *Natural_join_column::db_name() DBUG_ASSERT(!strcmp(table_ref->db, table_ref->table->s->db.str) || (table_ref->schema_table && - is_schema_db(table_ref->table->s->db.str))); + is_infoschema_db(table_ref->table->s->db.str, + table_ref->table->s->db.length))); return table_ref->db; } @@ -4158,7 +4157,8 @@ const char *Field_iterator_table_ref::get_db_name() */ DBUG_ASSERT(!strcmp(table_ref->db, table_ref->table->s->db.str) || (table_ref->schema_table && - is_schema_db(table_ref->table->s->db.str))); + is_infoschema_db(table_ref->table->s->db.str, + table_ref->table->s->db.length))); return table_ref->db; } diff --git a/sql/table.h b/sql/table.h index 6723dfc40dd..b2b84ed283d 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1,7 +1,7 @@ #ifndef TABLE_INCLUDED #define TABLE_INCLUDED -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. +/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,7 +16,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - /* Structs that defines the TABLE */ class Item; /* Needed by ORDER */ @@ -28,6 +27,8 @@ class st_select_lex; class partition_info; class COND_EQUAL; class Security_context; +class ACL_internal_schema_access; +class ACL_internal_table_access; /*************************************************************************/ @@ -71,6 +72,25 @@ typedef struct st_order { } ORDER; /** + State information for internal tables grants. + This structure is part of the TABLE_LIST, and is updated + during the ACL check process. + @sa GRANT_INFO +*/ +struct st_grant_internal_info +{ + /** True if the internal lookup by schema name was done. */ + bool m_schema_lookup_done; + /** Cached internal schema access. */ + const ACL_internal_schema_access *m_schema_access; + /** True if the internal lookup by table name was done. */ + bool m_table_lookup_done; + /** Cached internal table access. */ + const ACL_internal_table_access *m_table_access; +}; +typedef struct st_grant_internal_info GRANT_INTERNAL_INFO; + +/** @brief The current state of the privilege checking process for the current user, SQL statement and SQL object. @@ -131,6 +151,8 @@ typedef struct st_grant_info check access rights to the underlying tables of a view. */ ulong orig_want_privilege; + /** The grant state for internal tables. */ + GRANT_INTERNAL_INFO m_internal; } GRANT_INFO; enum tmp_table_type @@ -247,7 +269,7 @@ enum enum_table_category - LOCK TABLE t FOR READ/WRITE - FLUSH TABLES WITH READ LOCK - SET GLOBAL READ_ONLY = ON - as there is no point in locking explicitely + as there is no point in locking explicitly an INFORMATION_SCHEMA table. Nothing is directly written to information schema tables. Note that this value is not used currently, @@ -262,16 +284,16 @@ enum enum_table_category TABLE_CATEGORY_INFORMATION=4, /** - Performance schema tables. + Log tables. These tables are an interface provided by the system - to inspect the system performance data. + to inspect the system logs. These tables do *not* honor: - LOCK TABLE t FOR READ/WRITE - FLUSH TABLES WITH READ LOCK - SET GLOBAL READ_ONLY = ON - as there is no point in locking explicitely - a PERFORMANCE_SCHEMA table. - An example of PERFORMANCE_SCHEMA tables are: + as there is no point in locking explicitly + a LOG table. + An example of LOG tables are: - mysql.slow_log - mysql.general_log, which *are* updated even when there is either @@ -279,9 +301,31 @@ enum enum_table_category User queries do not write directly to these tables (there are exceptions for log tables). The server implementation perform writes. + Log tables are cached in the table cache. + */ + TABLE_CATEGORY_LOG=5, + + /** + Performance schema tables. + These tables are an interface provided by the system + to inspect the system performance data. + These tables do *not* honor: + - LOCK TABLE t FOR READ/WRITE + - FLUSH TABLES WITH READ LOCK + - SET GLOBAL READ_ONLY = ON + as there is no point in locking explicitly + a PERFORMANCE_SCHEMA table. + An example of PERFORMANCE_SCHEMA tables are: + - performance_schema.* + which *are* updated (but not using the handler interface) + even when there is either + a GLOBAL READ LOCK or a GLOBAL READ_ONLY in effect. + User queries do not write directly to these tables + (there are exceptions for SETUP_* tables). + The server implementation perform writes. Performance tables are cached in the table cache. */ - TABLE_CATEGORY_PERFORMANCE=5 + TABLE_CATEGORY_PERFORMANCE=6 }; typedef enum enum_table_category TABLE_CATEGORY; @@ -336,8 +380,8 @@ struct TABLE_SHARE TYPELIB keynames; /* Pointers to keynames */ TYPELIB fieldnames; /* Pointer to fieldnames */ TYPELIB *intervals; /* pointer to interval info */ - pthread_mutex_t mutex; /* For locking the share */ - pthread_cond_t cond; /* To signal that share is ready */ + mysql_mutex_t mutex; /* For locking the share */ + mysql_cond_t cond; /* To signal that share is ready */ TABLE_SHARE *next, **prev; /* Link to unused shares */ /* The following is copied to each TABLE on OPEN */ @@ -466,6 +510,8 @@ struct TABLE_SHARE void *ha_data; void (*ha_data_destroy)(void *); /* An optional destructor for ha_data */ + /** Instrumentation for this table share. */ + PSI_table_share *m_psi; /* Set share's table cache key and update its db and table name appropriately. @@ -527,7 +573,7 @@ struct TABLE_SHARE inline bool require_write_privileges() { - return (table_category == TABLE_CATEGORY_PERFORMANCE); + return (table_category == TABLE_CATEGORY_LOG); } inline ulong get_table_def_version() @@ -920,47 +966,6 @@ typedef struct st_foreign_key_info List<LEX_STRING> referenced_fields; } FOREIGN_KEY_INFO; -/* - Make sure that the order of schema_tables and enum_schema_tables are the same. -*/ - -enum enum_schema_tables -{ - SCH_CHARSETS= 0, - SCH_COLLATIONS, - SCH_COLLATION_CHARACTER_SET_APPLICABILITY, - SCH_COLUMNS, - SCH_COLUMN_PRIVILEGES, - SCH_ENGINES, - SCH_EVENTS, - SCH_FILES, - SCH_GLOBAL_STATUS, - SCH_GLOBAL_VARIABLES, - SCH_KEY_COLUMN_USAGE, - SCH_OPEN_TABLES, - SCH_PARTITIONS, - SCH_PLUGINS, - SCH_PROCESSLIST, - SCH_PROFILES, - SCH_REFERENTIAL_CONSTRAINTS, - SCH_PROCEDURES, - SCH_SCHEMATA, - SCH_SCHEMA_PRIVILEGES, - SCH_SESSION_STATUS, - SCH_SESSION_VARIABLES, - SCH_STATISTICS, - SCH_STATUS, - SCH_TABLES, - SCH_TABLE_CONSTRAINTS, - SCH_TABLE_NAMES, - SCH_TABLE_PRIVILEGES, - SCH_TRIGGERS, - SCH_USER_PRIVILEGES, - SCH_VARIABLES, - SCH_VIEWS -}; - - #define MY_I_S_MAYBE_NULL 1 #define MY_I_S_UNSIGNED 2 @@ -1374,6 +1379,12 @@ struct TABLE_LIST */ bool create; bool internal_tmp_table; + /** TRUE if an alias for this table was specified in the SQL. */ + bool is_alias; + /** TRUE if the table is referred to in the statement using a fully + qualified name (<db_name>.<table_name>). + */ + bool is_fqtn; /* View creation context. */ diff --git a/sql/tztime.cc b/sql/tztime.cc index 650678c721b..442669d9c3d 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2004 MySQL AB +/* Copyright (C) 2004 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -40,6 +40,7 @@ #include "tzfile.h" #include <m_string.h> #include <my_dir.h> +#include <mysql/psi/mysql_file.h> /* Now we don't use abbreviations in server but we will do this in future. @@ -156,9 +157,9 @@ tz_load(const char *name, TIME_ZONE_INFO *sp, MEM_ROOT *storage) uchar *p; int read_from_file; uint i; - FILE *file; + MYSQL_FILE *file; - if (!(file= my_fopen(name, O_RDONLY|O_BINARY, MYF(MY_WME)))) + if (!(file= mysql_file_fopen(0, name, O_RDONLY|O_BINARY, MYF(MY_WME)))) return 1; { union @@ -175,9 +176,9 @@ tz_load(const char *name, TIME_ZONE_INFO *sp, MEM_ROOT *storage) uint ttisgmtcnt; char *tzinfo_buf; - read_from_file= my_fread(file, u.buf, sizeof(u.buf), MYF(MY_WME)); + read_from_file= mysql_file_fread(file, u.buf, sizeof(u.buf), MYF(MY_WME)); - if (my_fclose(file, MYF(MY_WME)) != 0) + if (mysql_file_fclose(file, MYF(MY_WME)) != 0) return 1; if (read_from_file < (int)sizeof(struct tzhead)) @@ -1432,7 +1433,7 @@ static MEM_ROOT tz_storage; time zone in offset_tzs or creating if it didn't existed before in tz_storage. So contention is low. */ -static pthread_mutex_t tz_LOCK; +static mysql_mutex_t tz_LOCK; static bool tz_inited= 0; /* @@ -1532,6 +1533,27 @@ tz_init_table_list(TABLE_LIST *tz_tabs) } } +#ifdef HAVE_PSI_INTERFACE +static PSI_mutex_key key_tz_LOCK; + +static PSI_mutex_info all_tz_mutexes[]= +{ + { & key_tz_LOCK, "tz_LOCK", PSI_FLAG_GLOBAL} +}; + +static void init_tz_psi_keys(void) +{ + const char* category= "sql"; + int count; + + if (PSI_server == NULL) + return; + + count= array_elements(all_tz_mutexes); + PSI_server->register_mutex(category, all_tz_mutexes, count); +} +#endif /* HAVE_PSI_INTERFACE */ + /* Initialize time zone support infrastructure. @@ -1571,6 +1593,10 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) int res; DBUG_ENTER("my_tz_init"); +#ifdef HAVE_PSI_INTERFACE + init_tz_psi_keys(); +#endif + /* To be able to run this from boot, we allocate a temporary THD */ @@ -1578,7 +1604,6 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) DBUG_RETURN(1); thd->thread_stack= (char*) &thd; thd->store_globals(); - lex_start(thd); /* Init all memory structures that require explicit destruction */ if (my_hash_init(&tz_names, &my_charset_latin1, 20, @@ -1594,8 +1619,8 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) my_hash_free(&tz_names); goto end; } - init_alloc_root(&tz_storage, 32 * 1024, 0); - VOID(pthread_mutex_init(&tz_LOCK, MY_MUTEX_INIT_FAST)); + init_sql_alloc(&tz_storage, 32 * 1024, 0); + mysql_mutex_init(key_tz_LOCK, &tz_LOCK, MY_MUTEX_INIT_FAST); tz_inited= 1; /* Add 'SYSTEM' time zone to tz_names hash */ @@ -1757,6 +1782,10 @@ end: my_pthread_setspecific_ptr(THR_THD, 0); my_pthread_setspecific_ptr(THR_MALLOC, 0); } + + default_tz= default_tz_name ? global_system_variables.time_zone + : my_tz_SYSTEM; + DBUG_RETURN(return_val); } @@ -1773,7 +1802,7 @@ void my_tz_free() if (tz_inited) { tz_inited= 0; - VOID(pthread_mutex_destroy(&tz_LOCK)); + mysql_mutex_destroy(&tz_LOCK); my_hash_free(&offset_tzs); my_hash_free(&tz_names); free_root(&tz_storage, MYF(0)); @@ -2262,7 +2291,7 @@ my_tz_find(THD *thd, const String *name) if (!name) DBUG_RETURN(0); - VOID(pthread_mutex_lock(&tz_LOCK)); + mysql_mutex_lock(&tz_LOCK); if (!str_to_offset(name->ptr(), name->length(), &offset)) { @@ -2305,7 +2334,7 @@ my_tz_find(THD *thd, const String *name) } } - VOID(pthread_mutex_unlock(&tz_LOCK)); + mysql_mutex_unlock(&tz_LOCK); DBUG_RETURN(result_tz); } diff --git a/sql/udf_example.c b/sql/udf_example.c index 4e3dd82c467..73256bb5529 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -767,14 +767,14 @@ char *lookup(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, return 0; } #else - VOID(pthread_mutex_lock(&LOCK_hostname)); + pthread_mutex_lock(&LOCK_hostname); if (!(hostent= gethostbyname((char*) name_buff))) { - VOID(pthread_mutex_unlock(&LOCK_hostname)); + pthread_mutex_unlock(&LOCK_hostname); *null_value= 1; return 0; } - VOID(pthread_mutex_unlock(&LOCK_hostname)); + pthread_mutex_unlock(&LOCK_hostname); #endif memcpy_fixed((char*) &in,(char*) *hostent->h_addr_list, sizeof(in.s_addr)); *res_length= (ulong) (strmov(result, inet_ntoa(in)) - result); @@ -871,14 +871,14 @@ char *reverse_lookup(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, return 0; } #else - VOID(pthread_mutex_lock(&LOCK_hostname)); + pthread_mutex_lock(&LOCK_hostname); if (!(hp= gethostbyaddr((char*) &taddr, sizeof(taddr), AF_INET))) { - VOID(pthread_mutex_unlock(&LOCK_hostname)); + pthread_mutex_unlock(&LOCK_hostname); *null_value= 1; return 0; } - VOID(pthread_mutex_unlock(&LOCK_hostname)); + pthread_mutex_unlock(&LOCK_hostname); #endif *res_length=(ulong) (strmov(result,hp->h_name) - result); return result; diff --git a/sql/uniques.cc b/sql/uniques.cc index 7b6b628f924..f7c290ae61d 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -66,8 +66,8 @@ Unique::Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg, */ max_elements= (ulong) (max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+size)); - VOID(open_cached_file(&file, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE, - MYF(MY_WME))); + (void) open_cached_file(&file, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE, + MYF(MY_WME)); } diff --git a/sql/unireg.cc b/sql/unireg.cc index f08c64a3182..b20e759efbb 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000-2006 MySQL AB +/* Copyright (C) 2000-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -199,7 +199,7 @@ bool mysql_create_frm(THD *thd, const char *file_name, key_buff_length= uint4korr(fileinfo+47); keybuff=(uchar*) my_malloc(key_buff_length, MYF(0)); key_info_length= pack_keys(keybuff, keys, key_info, data_offset); - VOID(get_form_pos(file,fileinfo,&formnames)); + (void) get_form_pos(file,fileinfo,&formnames); if (!(filepos=make_new_entry(file,fileinfo,&formnames,""))) goto err; maxlength=(uint) next_io_size((ulong) (uint2korr(forminfo)+1000)); @@ -258,27 +258,27 @@ bool mysql_create_frm(THD *thd, const char *file_name, #endif int2store(fileinfo+59,db_file->extra_rec_buf_length()); - if (my_pwrite(file, fileinfo, 64, 0L, MYF_RW) || - my_pwrite(file, keybuff, key_info_length, - (ulong) uint2korr(fileinfo+6),MYF_RW)) + if (mysql_file_pwrite(file, fileinfo, 64, 0L, MYF_RW) || + mysql_file_pwrite(file, keybuff, key_info_length, + (ulong) uint2korr(fileinfo+6), MYF_RW)) goto err; - VOID(my_seek(file, - (ulong) uint2korr(fileinfo+6)+ (ulong) key_buff_length, - MY_SEEK_SET,MYF(0))); + mysql_file_seek(file, + (ulong) uint2korr(fileinfo+6) + (ulong) key_buff_length, + MY_SEEK_SET, MYF(0)); if (make_empty_rec(thd,file,ha_legacy_type(create_info->db_type), create_info->table_options, create_fields,reclength, data_offset, db_file)) goto err; int2store(buff, create_info->connect_string.length); - if (my_write(file, (const uchar*)buff, 2, MYF(MY_NABP)) || - my_write(file, (const uchar*)create_info->connect_string.str, + if (mysql_file_write(file, (const uchar*)buff, 2, MYF(MY_NABP)) || + mysql_file_write(file, (const uchar*)create_info->connect_string.str, create_info->connect_string.length, MYF(MY_NABP))) goto err; int2store(buff, str_db_type.length); - if (my_write(file, (const uchar*)buff, 2, MYF(MY_NABP)) || - my_write(file, (const uchar*)str_db_type.str, + if (mysql_file_write(file, (const uchar*)buff, 2, MYF(MY_NABP)) || + mysql_file_write(file, (const uchar*)str_db_type.str, str_db_type.length, MYF(MY_NABP))) goto err; @@ -287,32 +287,32 @@ bool mysql_create_frm(THD *thd, const char *file_name, { char auto_partitioned= part_info->is_auto_partitioned ? 1 : 0; int4store(buff, part_info->part_info_len); - if (my_write(file, (const uchar*)buff, 4, MYF_RW) || - my_write(file, (const uchar*)part_info->part_info_string, + if (mysql_file_write(file, (const uchar*)buff, 4, MYF_RW) || + mysql_file_write(file, (const uchar*)part_info->part_info_string, part_info->part_info_len + 1, MYF_RW) || - my_write(file, (const uchar*)&auto_partitioned, 1, MYF_RW)) + mysql_file_write(file, (const uchar*)&auto_partitioned, 1, MYF_RW)) goto err; } else #endif { bzero((uchar*) buff, 6); - if (my_write(file, (uchar*) buff, 6, MYF_RW)) + if (mysql_file_write(file, (uchar*) buff, 6, MYF_RW)) goto err; } for (i= 0; i < keys; i++) { if (key_info[i].parser_name) { - if (my_write(file, (const uchar*)key_info[i].parser_name->str, - key_info[i].parser_name->length + 1, MYF(MY_NABP))) + if (mysql_file_write(file, (const uchar*)key_info[i].parser_name->str, + key_info[i].parser_name->length + 1, MYF(MY_NABP))) goto err; } } - VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0))); - if (my_write(file, forminfo, 288, MYF_RW) || - my_write(file, screen_buff, info_length, MYF_RW) || + mysql_file_seek(file, filepos, MY_SEEK_SET, MYF(0)); + if (mysql_file_write(file, forminfo, 288, MYF_RW) || + mysql_file_write(file, screen_buff, info_length, MYF_RW) || pack_fields(file, create_fields, data_offset)) goto err; @@ -321,15 +321,15 @@ bool mysql_create_frm(THD *thd, const char *file_name, { char tmp=2,*disk_buff=0; SQL_CRYPT *crypted=new SQL_CRYPT(create_info->password); - if (!crypted || my_pwrite(file,&tmp,1,26,MYF_RW)) // Mark crypted + if (!crypted || mysql_file_pwrite(file, &tmp, 1, 26, MYF_RW))// Mark crypted goto err; uint read_length=uint2korr(forminfo)-256; - VOID(my_seek(file,filepos+256,MY_SEEK_SET,MYF(0))); + mysql_file_seek(file, filepos+256, MY_SEEK_SET, MYF(0)); if (read_string(file,(uchar**) &disk_buff,read_length)) goto err; crypted->encode(disk_buff,read_length); delete crypted; - if (my_pwrite(file,disk_buff,read_length,filepos+256,MYF_RW)) + if (mysql_file_pwrite(file, disk_buff, read_length, filepos+256, MYF_RW)) { my_free(disk_buff,MYF(0)); goto err; @@ -342,11 +342,11 @@ bool mysql_create_frm(THD *thd, const char *file_name, my_free(keybuff, MYF(0)); if (opt_sync_frm && !(create_info->options & HA_LEX_CREATE_TMP_TABLE) && - (my_sync(file, MYF(MY_WME)) || + (mysql_file_sync(file, MYF(MY_WME)) || my_sync_dir_by_file(file_name, MYF(MY_WME)))) goto err2; - if (my_close(file,MYF(MY_WME))) + if (mysql_file_close(file, MYF(MY_WME))) goto err3; { @@ -371,9 +371,9 @@ err: my_free(screen_buff, MYF(0)); my_free(keybuff, MYF(0)); err2: - VOID(my_close(file,MYF(MY_WME))); + (void) mysql_file_close(file, MYF(MY_WME)); err3: - my_delete(file_name,MYF(0)); + mysql_file_delete(key_file_frm, file_name, MYF(0)); DBUG_RETURN(1); } /* mysql_create_frm */ @@ -425,8 +425,8 @@ int rea_create_table(THD *thd, const char *path, DBUG_RETURN(0); err_handler: - VOID(file->ha_create_handler_files(path, NULL, CHF_DELETE_FLAG, create_info)); - my_delete(frm_name, MYF(0)); + (void) file->ha_create_handler_files(path, NULL, CHF_DELETE_FLAG, create_info); + mysql_file_delete(key_file_frm, frm_name, MYF(0)); DBUG_RETURN(1); } /* rea_create_table */ @@ -825,13 +825,13 @@ static bool pack_fields(File file, List<Create_field> &create_fields, int2store(buff+15, field->comment.length); comment_length+= field->comment.length; set_if_bigger(int_count,field->interval_id); - if (my_write(file, buff, FCOMP, MYF_RW)) + if (mysql_file_write(file, buff, FCOMP, MYF_RW)) DBUG_RETURN(1); } /* Write fieldnames */ buff[0]=(uchar) NAMES_SEP_CHAR; - if (my_write(file, buff, 1, MYF_RW)) + if (mysql_file_write(file, buff, 1, MYF_RW)) DBUG_RETURN(1); i=0; it.rewind(); @@ -841,7 +841,7 @@ static bool pack_fields(File file, List<Create_field> &create_fields, *pos++=NAMES_SEP_CHAR; if (i == create_fields.elements-1) *pos++=0; - if (my_write(file, buff, (size_t) (pos-(char*) buff),MYF_RW)) + if (mysql_file_write(file, buff, (size_t) (pos-(char*) buff), MYF_RW)) DBUG_RETURN(1); i++; } @@ -901,7 +901,7 @@ static bool pack_fields(File file, List<Create_field> &create_fields, tmp.append('\0'); // End of intervall } } - if (my_write(file,(uchar*) tmp.ptr(),tmp.length(),MYF_RW)) + if (mysql_file_write(file, (uchar*) tmp.ptr(), tmp.length(), MYF_RW)) DBUG_RETURN(1); } if (comment_length) @@ -911,8 +911,8 @@ static bool pack_fields(File file, List<Create_field> &create_fields, while ((field=it++)) { if (field->comment.length) - if (my_write(file, (uchar*) field->comment.str, field->comment.length, - MYF_RW)) + if (mysql_file_write(file, (uchar*) field->comment.str, + field->comment.length, MYF_RW)) DBUG_RETURN(1); } } @@ -1035,7 +1035,7 @@ static bool make_empty_rec(THD *thd, File file,enum legacy_db_type table_type, if (null_count & 7) *(null_pos + null_count / 8)|= ~(((uchar) 1 << (null_count & 7)) - 1); - error= my_write(file, buff, (size_t) reclength,MYF_RW) != 0; + error= mysql_file_write(file, buff, (size_t) reclength, MYF_RW) != 0; err: my_free(buff, MYF(MY_FAE)); diff --git a/sql/unireg.h b/sql/unireg.h index e915b234a6b..9932be7ae74 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -96,8 +96,8 @@ #define MAX_SELECT_NESTING (sizeof(nesting_map)*8-1) -#define MAX_SORT_MEMORY (2048*1024-MALLOC_OVERHEAD) -#define MIN_SORT_MEMORY (32*1024-MALLOC_OVERHEAD) +#define MAX_SORT_MEMORY 2048*1024 +#define MIN_SORT_MEMORY 32*1024 /* Memory allocated when parsing a statement / saving a statement */ #define MEM_ROOT_BLOCK_SIZE 8192 @@ -129,7 +129,7 @@ #define SPECIAL_SAME_DB_NAME 16 /* form name = file name */ #define SPECIAL_ENGLISH 32 /* English error messages */ #define SPECIAL_NO_RESOLVE 64 /* Don't use gethostname */ -#define SPECIAL_NO_PRIOR 128 /* Don't prioritize threads */ +#define SPECIAL_NO_PRIOR 128 /* Obsolete */ #define SPECIAL_BIG_SELECTS 256 /* Don't use heap tables */ #define SPECIAL_NO_HOST_CACHE 512 /* Don't cache hosts */ #define SPECIAL_SHORT_LOG_FORMAT 1024 @@ -197,6 +197,11 @@ */ #define OPTIMIZE_I_S_TABLE OPEN_VIEW_FULL*2 +/* + The flag means that we need to process trigger files only. +*/ +#define OPEN_TRIGGER_ONLY OPTIMIZE_I_S_TABLE*2 + #define SC_INFO_LENGTH 4 /* Form format constant */ #define TE_INFO_LENGTH 3 #define MTYP_NOEMPTY_BIT 128 @@ -216,7 +221,6 @@ */ #define BIN_LOG_HEADER_SIZE 4 -#define FLOATING_POINT_BUFFER 331 #define DEFAULT_KEY_CACHE_NAME "default" |