My Project
|
00001 /* Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; version 2 of the License. 00006 00007 This program is distributed in the hope that it will be useful, 00008 but WITHOUT ANY WARRANTY; without even the implied warranty of 00009 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00010 GNU General Public License for more details. 00011 00012 You should have received a copy of the GNU General Public License 00013 along with this program; if not, write to the Free Software 00014 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 00015 00024 #include "sys_vars_shared.h" 00025 #include <my_getopt.h> 00026 #include <my_bit.h> 00027 #include <my_dir.h> 00028 #include "keycaches.h" 00029 #include "strfunc.h" 00030 #include "tztime.h" // my_tz_find, my_tz_SYSTEM, struct Time_zone 00031 #include "rpl_gtid.h" 00032 #include <ctype.h> 00033 00034 /* 00035 a set of mostly trivial (as in f(X)=X) defines below to make system variable 00036 declarations more readable 00037 */ 00038 #define VALID_RANGE(X,Y) X,Y 00039 #define DEFAULT(X) X 00040 #define BLOCK_SIZE(X) X 00041 #define GLOBAL_VAR(X) sys_var::GLOBAL, (((char*)&(X))-(char*)&global_system_variables), sizeof(X) 00042 #define SESSION_VAR(X) sys_var::SESSION, offsetof(SV, X), sizeof(((SV *)0)->X) 00043 #define SESSION_ONLY(X) sys_var::ONLY_SESSION, offsetof(SV, X), sizeof(((SV *)0)->X) 00044 #define NO_CMD_LINE CMD_LINE(NO_ARG, -1) 00045 /* 00046 the define below means that there's no *second* mutex guard, 00047 LOCK_global_system_variables always guards all system variables 00048 */ 00049 #define NO_MUTEX_GUARD ((PolyLock*)0) 00050 #define IN_BINLOG sys_var::SESSION_VARIABLE_IN_BINLOG 00051 #define NOT_IN_BINLOG sys_var::VARIABLE_NOT_IN_BINLOG 00052 #define ON_READ(X) X 00053 #define ON_CHECK(X) X 00054 #define ON_UPDATE(X) X 00055 #define READ_ONLY sys_var::READONLY+ 00056 #define NOT_VISIBLE sys_var::INVISIBLE+ 00057 // this means that Sys_var_charptr initial value was malloc()ed 00058 #define PREALLOCATED sys_var::ALLOCATED+ 00059 /* 00060 Sys_var_bit meaning is reversed, like in 00061 @@foreign_key_checks <-> OPTION_NO_FOREIGN_KEY_CHECKS 00062 */ 00063 #define REVERSE(X) ~(X) 00064 #define DEPRECATED(X) X 00065 00066 #define session_var(THD, TYPE) (*(TYPE*)session_var_ptr(THD)) 00067 #define global_var(TYPE) (*(TYPE*)global_var_ptr()) 00068 00069 #if SIZEOF_OFF_T > 4 && defined(BIG_TABLES) 00070 #define GET_HA_ROWS GET_ULL 00071 #else 00072 #define GET_HA_ROWS GET_ULONG 00073 #endif 00074 00075 enum charset_enum {IN_SYSTEM_CHARSET, IN_FS_CHARSET}; 00076 00077 static const char *bool_values[3]= {"OFF", "ON", 0}; 00078 00084 struct CMD_LINE 00085 { 00086 int id; 00087 enum get_opt_arg_type arg_type; 00088 CMD_LINE(enum get_opt_arg_type getopt_arg_type, int getopt_id=0) 00089 : id(getopt_id), arg_type(getopt_arg_type) {} 00090 }; 00091 00105 template 00106 <typename T, ulong ARGT, enum enum_mysql_show_type SHOWT, bool SIGNED> 00107 class Sys_var_integer: public sys_var 00108 { 00109 public: 00110 Sys_var_integer(const char *name_arg, 00111 const char *comment, int flag_args, ptrdiff_t off, size_t size, 00112 CMD_LINE getopt, 00113 T min_val, T max_val, T def_val, uint block_size, PolyLock *lock=0, 00114 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 00115 on_check_function on_check_func=0, 00116 on_update_function on_update_func=0, 00117 const char *substitute=0, 00118 int parse_flag= PARSE_NORMAL) 00119 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 00120 getopt.arg_type, SHOWT, def_val, lock, binlog_status_arg, 00121 on_check_func, on_update_func, 00122 substitute, parse_flag) 00123 { 00124 option.var_type= ARGT; 00125 option.min_value= min_val; 00126 option.max_value= max_val; 00127 option.block_size= block_size; 00128 option.u_max_value= (uchar**)max_var_ptr(); 00129 if (max_var_ptr()) 00130 *max_var_ptr()= max_val; 00131 00132 // Do not set global_var for Sys_var_keycache objects 00133 if (offset >= 0) 00134 global_var(T)= def_val; 00135 00136 DBUG_ASSERT(size == sizeof(T)); 00137 DBUG_ASSERT(min_val < max_val); 00138 DBUG_ASSERT(min_val <= def_val); 00139 DBUG_ASSERT(max_val >= def_val); 00140 DBUG_ASSERT(block_size > 0); 00141 DBUG_ASSERT(def_val % block_size == 0); 00142 } 00143 bool do_check(THD *thd, set_var *var) 00144 { 00145 my_bool fixed= FALSE; 00146 longlong v; 00147 ulonglong uv; 00148 00149 v= var->value->val_int(); 00150 if (SIGNED) /* target variable has signed type */ 00151 { 00152 if (var->value->unsigned_flag) 00153 { 00154 /* 00155 Input value is such a large positive number that MySQL used an 00156 unsigned item to hold it. When cast to a signed longlong, if the 00157 result is negative there is "cycling" and this is incorrect (large 00158 positive input value should not end up as a large negative value in 00159 the session signed variable to be set); instead, we need to pick the 00160 allowed number closest to the positive input value, i.e. pick the 00161 biggest allowed positive integer. 00162 */ 00163 if (v < 0) 00164 uv= max_of_int_range(ARGT); 00165 else /* no cycling, longlong can hold true value */ 00166 uv= (ulonglong) v; 00167 } 00168 else 00169 uv= v; 00170 /* This will further restrict with VALID_RANGE, BLOCK_SIZE */ 00171 var->save_result.ulonglong_value= 00172 getopt_ll_limit_value(uv, &option, &fixed); 00173 } 00174 else 00175 { 00176 if (var->value->unsigned_flag) 00177 { 00178 /* Guaranteed positive input value, ulonglong can hold it */ 00179 uv= (ulonglong) v; 00180 } 00181 else 00182 { 00183 /* 00184 Maybe negative input value; in this case, cast to ulonglong makes it 00185 positive, which is wrong. Pick the closest allowed value i.e. 0. 00186 */ 00187 uv= (ulonglong) (v < 0 ? 0 : v); 00188 } 00189 var->save_result.ulonglong_value= 00190 getopt_ull_limit_value(uv, &option, &fixed); 00191 } 00192 00193 if (max_var_ptr()) 00194 { 00195 /* check constraint set with --maximum-...=X */ 00196 if (SIGNED) 00197 { 00198 longlong max_val= *max_var_ptr(); 00199 if (((longlong)(var->save_result.ulonglong_value)) > max_val) 00200 var->save_result.ulonglong_value= max_val; 00201 /* 00202 Signed variable probably has some kind of symmetry. Then it's good 00203 to limit negative values just as we limit positive values. 00204 */ 00205 max_val= -max_val; 00206 if (((longlong)(var->save_result.ulonglong_value)) < max_val) 00207 var->save_result.ulonglong_value= max_val; 00208 } 00209 else 00210 { 00211 ulonglong max_val= *max_var_ptr(); 00212 if (var->save_result.ulonglong_value > max_val) 00213 var->save_result.ulonglong_value= max_val; 00214 } 00215 } 00216 00217 return throw_bounds_warning(thd, name.str, 00218 var->save_result.ulonglong_value != 00219 (ulonglong)v, 00220 var->value->unsigned_flag, v); 00221 } 00222 bool session_update(THD *thd, set_var *var) 00223 { 00224 session_var(thd, T)= var->save_result.ulonglong_value; 00225 return false; 00226 } 00227 bool global_update(THD *thd, set_var *var) 00228 { 00229 global_var(T)= var->save_result.ulonglong_value; 00230 return false; 00231 } 00232 bool check_update_type(Item_result type) 00233 { return type != INT_RESULT; } 00234 void session_save_default(THD *thd, set_var *var) 00235 { var->save_result.ulonglong_value= (ulonglong)*(T*)global_value_ptr(thd, 0); } 00236 void global_save_default(THD *thd, set_var *var) 00237 { var->save_result.ulonglong_value= option.def_value; } 00238 private: 00239 T *max_var_ptr() 00240 { 00241 return scope() == SESSION ? (T*)(((uchar*)&max_system_variables) + offset) 00242 : 0; 00243 } 00244 }; 00245 00246 typedef Sys_var_integer<int32, GET_UINT, SHOW_INT, FALSE> Sys_var_int32; 00247 typedef Sys_var_integer<uint, GET_UINT, SHOW_INT, FALSE> Sys_var_uint; 00248 typedef Sys_var_integer<ulong, GET_ULONG, SHOW_LONG, FALSE> Sys_var_ulong; 00249 typedef Sys_var_integer<ha_rows, GET_HA_ROWS, SHOW_HA_ROWS, FALSE> 00250 Sys_var_harows; 00251 typedef Sys_var_integer<ulonglong, GET_ULL, SHOW_LONGLONG, FALSE> 00252 Sys_var_ulonglong; 00253 typedef Sys_var_integer<long, GET_LONG, SHOW_SIGNED_LONG, TRUE> Sys_var_long; 00254 00258 class Sys_var_typelib: public sys_var 00259 { 00260 protected: 00261 TYPELIB typelib; 00262 public: 00263 Sys_var_typelib(const char *name_arg, 00264 const char *comment, int flag_args, ptrdiff_t off, 00265 CMD_LINE getopt, 00266 SHOW_TYPE show_val_type_arg, const char *values[], 00267 ulonglong def_val, PolyLock *lock, 00268 enum binlog_status_enum binlog_status_arg, 00269 on_check_function on_check_func, on_update_function on_update_func, 00270 const char *substitute, int parse_flag= PARSE_NORMAL) 00271 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 00272 getopt.arg_type, show_val_type_arg, def_val, lock, 00273 binlog_status_arg, on_check_func, 00274 on_update_func, substitute, parse_flag) 00275 { 00276 for (typelib.count= 0; values[typelib.count]; typelib.count++) /*no-op */; 00277 typelib.name=""; 00278 typelib.type_names= values; 00279 typelib.type_lengths= 0; // only used by Fields_enum and Field_set 00280 option.typelib= &typelib; 00281 } 00282 bool do_check(THD *thd, set_var *var) // works for enums and my_bool 00283 { 00284 char buff[STRING_BUFFER_USUAL_SIZE]; 00285 String str(buff, sizeof(buff), system_charset_info), *res; 00286 00287 if (var->value->result_type() == STRING_RESULT) 00288 { 00289 if (!(res=var->value->val_str(&str))) 00290 return true; 00291 else 00292 if (!(var->save_result.ulonglong_value= 00293 find_type(&typelib, res->ptr(), res->length(), false))) 00294 return true; 00295 else 00296 var->save_result.ulonglong_value--; 00297 } 00298 else 00299 { 00300 longlong tmp=var->value->val_int(); 00301 if (tmp < 0 || tmp >= typelib.count) 00302 return true; 00303 else 00304 var->save_result.ulonglong_value= tmp; 00305 } 00306 00307 return false; 00308 } 00309 bool check_update_type(Item_result type) 00310 { return type != INT_RESULT && type != STRING_RESULT; } 00311 }; 00312 00327 class Sys_var_enum: public Sys_var_typelib 00328 { 00329 public: 00330 Sys_var_enum(const char *name_arg, 00331 const char *comment, int flag_args, ptrdiff_t off, size_t size, 00332 CMD_LINE getopt, 00333 const char *values[], uint def_val, PolyLock *lock=0, 00334 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 00335 on_check_function on_check_func=0, 00336 on_update_function on_update_func=0, 00337 const char *substitute=0) 00338 : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, 00339 SHOW_CHAR, values, def_val, lock, 00340 binlog_status_arg, on_check_func, on_update_func, 00341 substitute) 00342 { 00343 option.var_type= GET_ENUM; 00344 global_var(ulong)= def_val; 00345 DBUG_ASSERT(def_val < typelib.count); 00346 DBUG_ASSERT(size == sizeof(ulong)); 00347 } 00348 bool session_update(THD *thd, set_var *var) 00349 { 00350 session_var(thd, ulong)= var->save_result.ulonglong_value; 00351 return false; 00352 } 00353 bool global_update(THD *thd, set_var *var) 00354 { 00355 global_var(ulong)= var->save_result.ulonglong_value; 00356 return false; 00357 } 00358 void session_save_default(THD *thd, set_var *var) 00359 { var->save_result.ulonglong_value= global_var(ulong); } 00360 void global_save_default(THD *thd, set_var *var) 00361 { var->save_result.ulonglong_value= option.def_value; } 00362 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 00363 { return (uchar*)typelib.type_names[session_var(thd, ulong)]; } 00364 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 00365 { return (uchar*)typelib.type_names[global_var(ulong)]; } 00366 }; 00367 00374 class Sys_var_mybool: public Sys_var_typelib 00375 { 00376 public: 00377 Sys_var_mybool(const char *name_arg, 00378 const char *comment, int flag_args, ptrdiff_t off, size_t size, 00379 CMD_LINE getopt, 00380 my_bool def_val, PolyLock *lock=0, 00381 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 00382 on_check_function on_check_func=0, 00383 on_update_function on_update_func=0, 00384 const char *substitute=0, 00385 int parse_flag= PARSE_NORMAL) 00386 : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, 00387 SHOW_MY_BOOL, bool_values, def_val, lock, 00388 binlog_status_arg, on_check_func, on_update_func, 00389 substitute, parse_flag) 00390 { 00391 option.var_type= GET_BOOL; 00392 global_var(my_bool)= def_val; 00393 DBUG_ASSERT(def_val < 2); 00394 DBUG_ASSERT(getopt.arg_type == OPT_ARG || getopt.id == -1); 00395 DBUG_ASSERT(size == sizeof(my_bool)); 00396 } 00397 bool session_update(THD *thd, set_var *var) 00398 { 00399 session_var(thd, my_bool)= var->save_result.ulonglong_value; 00400 return false; 00401 } 00402 bool global_update(THD *thd, set_var *var) 00403 { 00404 global_var(my_bool)= var->save_result.ulonglong_value; 00405 return false; 00406 } 00407 void session_save_default(THD *thd, set_var *var) 00408 { var->save_result.ulonglong_value= (ulonglong)*(my_bool *)global_value_ptr(thd, 0); } 00409 void global_save_default(THD *thd, set_var *var) 00410 { var->save_result.ulonglong_value= option.def_value; } 00411 }; 00412 00429 class Sys_var_charptr: public sys_var 00430 { 00431 public: 00432 Sys_var_charptr(const char *name_arg, 00433 const char *comment, int flag_args, ptrdiff_t off, size_t size, 00434 CMD_LINE getopt, 00435 enum charset_enum is_os_charset_arg, 00436 const char *def_val, PolyLock *lock=0, 00437 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 00438 on_check_function on_check_func=0, 00439 on_update_function on_update_func=0, 00440 const char *substitute=0, 00441 int parse_flag= PARSE_NORMAL) 00442 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 00443 getopt.arg_type, SHOW_CHAR_PTR, (intptr)def_val, 00444 lock, binlog_status_arg, on_check_func, on_update_func, 00445 substitute, parse_flag) 00446 { 00447 is_os_charset= is_os_charset_arg == IN_FS_CHARSET; 00448 /* 00449 use GET_STR_ALLOC - if ALLOCATED it must be *always* allocated, 00450 otherwise (GET_STR) you'll never know whether to free it or not. 00451 (think of an exit because of an error right after my_getopt) 00452 */ 00453 option.var_type= (flags & ALLOCATED) ? GET_STR_ALLOC : GET_STR; 00454 global_var(const char*)= def_val; 00455 DBUG_ASSERT(scope() == GLOBAL); 00456 DBUG_ASSERT(size == sizeof(char *)); 00457 } 00458 void cleanup() 00459 { 00460 if (flags & ALLOCATED) 00461 my_free(global_var(char*)); 00462 flags&= ~ALLOCATED; 00463 } 00464 bool do_check(THD *thd, set_var *var) 00465 { 00466 char buff[STRING_BUFFER_USUAL_SIZE], buff2[STRING_BUFFER_USUAL_SIZE]; 00467 String str(buff, sizeof(buff), charset(thd)); 00468 String str2(buff2, sizeof(buff2), charset(thd)), *res; 00469 00470 if (!(res=var->value->val_str(&str))) 00471 var->save_result.string_value.str= 0; 00472 else 00473 { 00474 uint32 unused; 00475 if (String::needs_conversion(res->length(), res->charset(), 00476 charset(thd), &unused)) 00477 { 00478 uint errors; 00479 str2.copy(res->ptr(), res->length(), res->charset(), charset(thd), 00480 &errors); 00481 res=&str2; 00482 00483 } 00484 var->save_result.string_value.str= thd->strmake(res->ptr(), res->length()); 00485 var->save_result.string_value.length= res->length(); 00486 } 00487 00488 return false; 00489 } 00490 bool session_update(THD *thd, set_var *var) 00491 { 00492 DBUG_ASSERT(FALSE); 00493 return true; 00494 } 00495 bool global_update(THD *thd, set_var *var) 00496 { 00497 char *new_val, *ptr= var->save_result.string_value.str; 00498 size_t len=var->save_result.string_value.length; 00499 if (ptr) 00500 { 00501 new_val= (char*)my_memdup(ptr, len+1, MYF(MY_WME)); 00502 if (!new_val) return true; 00503 new_val[len]=0; 00504 } 00505 else 00506 new_val= 0; 00507 if (flags & ALLOCATED) 00508 my_free(global_var(char*)); 00509 flags|= ALLOCATED; 00510 global_var(char*)= new_val; 00511 return false; 00512 } 00513 void session_save_default(THD *thd, set_var *var) 00514 { DBUG_ASSERT(FALSE); } 00515 void global_save_default(THD *thd, set_var *var) 00516 { 00517 char *ptr= (char*)(intptr)option.def_value; 00518 var->save_result.string_value.str= ptr; 00519 var->save_result.string_value.length= ptr ? strlen(ptr) : 0; 00520 } 00521 bool check_update_type(Item_result type) 00522 { return type != STRING_RESULT; } 00523 }; 00524 00525 00526 class Sys_var_proxy_user: public sys_var 00527 { 00528 public: 00529 Sys_var_proxy_user(const char *name_arg, 00530 const char *comment, enum charset_enum is_os_charset_arg) 00531 : sys_var(&all_sys_vars, name_arg, comment, 00532 sys_var::READONLY+sys_var::ONLY_SESSION, 0, -1, 00533 NO_ARG, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, 00534 NULL, NULL, NULL, PARSE_NORMAL) 00535 { 00536 is_os_charset= is_os_charset_arg == IN_FS_CHARSET; 00537 option.var_type= GET_STR; 00538 } 00539 bool do_check(THD *thd, set_var *var) 00540 { 00541 DBUG_ASSERT(FALSE); 00542 return true; 00543 } 00544 bool session_update(THD *thd, set_var *var) 00545 { 00546 DBUG_ASSERT(FALSE); 00547 return true; 00548 } 00549 bool global_update(THD *thd, set_var *var) 00550 { 00551 DBUG_ASSERT(FALSE); 00552 return false; 00553 } 00554 void session_save_default(THD *thd, set_var *var) 00555 { DBUG_ASSERT(FALSE); } 00556 void global_save_default(THD *thd, set_var *var) 00557 { DBUG_ASSERT(FALSE); } 00558 bool check_update_type(Item_result type) 00559 { return true; } 00560 protected: 00561 virtual uchar *session_value_ptr(THD *thd, LEX_STRING *base) 00562 { 00563 return thd->security_ctx->proxy_user[0] ? 00564 (uchar *) &(thd->security_ctx->proxy_user[0]) : NULL; 00565 } 00566 }; 00567 00568 class Sys_var_external_user : public Sys_var_proxy_user 00569 { 00570 public: 00571 Sys_var_external_user(const char *name_arg, const char *comment_arg, 00572 enum charset_enum is_os_charset_arg) 00573 : Sys_var_proxy_user (name_arg, comment_arg, is_os_charset_arg) 00574 {} 00575 00576 protected: 00577 virtual uchar *session_value_ptr(THD *thd, LEX_STRING *base) 00578 { 00579 return thd->security_ctx->proxy_user[0] ? 00580 (uchar *) &(thd->security_ctx->proxy_user[0]) : NULL; 00581 } 00582 }; 00583 00596 class Sys_var_lexstring: public Sys_var_charptr 00597 { 00598 public: 00599 Sys_var_lexstring(const char *name_arg, 00600 const char *comment, int flag_args, ptrdiff_t off, size_t size, 00601 CMD_LINE getopt, 00602 enum charset_enum is_os_charset_arg, 00603 const char *def_val, PolyLock *lock=0, 00604 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 00605 on_check_function on_check_func=0, 00606 on_update_function on_update_func=0, 00607 const char *substitute=0) 00608 : Sys_var_charptr(name_arg, comment, flag_args, off, sizeof(char*), 00609 getopt, is_os_charset_arg, def_val, lock, binlog_status_arg, 00610 on_check_func, on_update_func, substitute) 00611 { 00612 global_var(LEX_STRING).length= strlen(def_val); 00613 DBUG_ASSERT(size == sizeof(LEX_STRING)); 00614 *const_cast<SHOW_TYPE*>(&show_val_type)= SHOW_LEX_STRING; 00615 } 00616 bool global_update(THD *thd, set_var *var) 00617 { 00618 if (Sys_var_charptr::global_update(thd, var)) 00619 return true; 00620 global_var(LEX_STRING).length= var->save_result.string_value.length; 00621 return false; 00622 } 00623 }; 00624 00625 #ifndef DBUG_OFF 00626 00637 class Sys_var_dbug: public sys_var 00638 { 00639 public: 00640 Sys_var_dbug(const char *name_arg, 00641 const char *comment, int flag_args, 00642 CMD_LINE getopt, 00643 const char *def_val, PolyLock *lock=0, 00644 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 00645 on_check_function on_check_func=0, 00646 on_update_function on_update_func=0, 00647 const char *substitute=0, 00648 int parse_flag= PARSE_NORMAL) 00649 : sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id, 00650 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 00651 lock, binlog_status_arg, on_check_func, on_update_func, 00652 substitute, parse_flag) 00653 { option.var_type= GET_NO_ARG; } 00654 bool do_check(THD *thd, set_var *var) 00655 { 00656 char buff[STRING_BUFFER_USUAL_SIZE]; 00657 String str(buff, sizeof(buff), system_charset_info), *res; 00658 00659 if (!(res=var->value->val_str(&str))) 00660 var->save_result.string_value.str= const_cast<char*>(""); 00661 else 00662 var->save_result.string_value.str= thd->strmake(res->ptr(), res->length()); 00663 return false; 00664 } 00665 bool session_update(THD *thd, set_var *var) 00666 { 00667 const char *val= var->save_result.string_value.str; 00668 if (!var->value) 00669 DBUG_POP(); 00670 else 00671 DBUG_SET(val); 00672 return false; 00673 } 00674 bool global_update(THD *thd, set_var *var) 00675 { 00676 const char *val= var->save_result.string_value.str; 00677 DBUG_SET_INITIAL(val); 00678 return false; 00679 } 00680 void session_save_default(THD *thd, set_var *var) 00681 { } 00682 void global_save_default(THD *thd, set_var *var) 00683 { 00684 char *ptr= (char*)(intptr)option.def_value; 00685 var->save_result.string_value.str= ptr; 00686 } 00687 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 00688 { 00689 char buf[256]; 00690 DBUG_EXPLAIN(buf, sizeof(buf)); 00691 return (uchar*) thd->strdup(buf); 00692 } 00693 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 00694 { 00695 char buf[256]; 00696 DBUG_EXPLAIN_INITIAL(buf, sizeof(buf)); 00697 return (uchar*) thd->strdup(buf); 00698 } 00699 bool check_update_type(Item_result type) 00700 { return type != STRING_RESULT; } 00701 }; 00702 #endif 00703 00704 #define KEYCACHE_VAR(X) sys_var::GLOBAL,offsetof(KEY_CACHE, X), sizeof(((KEY_CACHE *)0)->X) 00705 #define keycache_var_ptr(KC, OFF) (((uchar*)(KC))+(OFF)) 00706 #define keycache_var(KC, OFF) (*(ulonglong*)keycache_var_ptr(KC, OFF)) 00707 typedef bool (*keycache_update_function)(THD *, KEY_CACHE *, ptrdiff_t, ulonglong); 00708 00720 class Sys_var_keycache: public Sys_var_ulonglong 00721 { 00722 keycache_update_function keycache_update; 00723 public: 00724 Sys_var_keycache(const char *name_arg, 00725 const char *comment, int flag_args, ptrdiff_t off, size_t size, 00726 CMD_LINE getopt, 00727 ulonglong min_val, ulonglong max_val, ulonglong def_val, 00728 ulonglong block_size, PolyLock *lock, 00729 enum binlog_status_enum binlog_status_arg, 00730 on_check_function on_check_func, 00731 keycache_update_function on_update_func, 00732 const char *substitute=0) 00733 : Sys_var_ulonglong(name_arg, comment, flag_args, 00734 -1, /* offset, see base class CTOR */ 00735 size, 00736 getopt, min_val, max_val, def_val, 00737 block_size, lock, binlog_status_arg, on_check_func, 0, 00738 substitute), 00739 keycache_update(on_update_func) 00740 { 00741 offset= off; /* Remember offset in KEY_CACHE */ 00742 option.var_type|= GET_ASK_ADDR; 00743 option.value= (uchar**)1; // crash me, please 00744 keycache_var(dflt_key_cache, off)= def_val; 00745 DBUG_ASSERT(scope() == GLOBAL); 00746 } 00747 bool global_update(THD *thd, set_var *var) 00748 { 00749 ulonglong new_value= var->save_result.ulonglong_value; 00750 LEX_STRING *base_name= &var->base; 00751 KEY_CACHE *key_cache; 00752 00753 /* If no basename, assume it's for the key cache named 'default' */ 00754 if (!base_name->length) 00755 base_name= &default_key_cache_base; 00756 00757 key_cache= get_key_cache(base_name); 00758 00759 if (!key_cache) 00760 { // Key cache didn't exists */ 00761 if (!new_value) // Tried to delete cache 00762 return false; // Ok, nothing to do 00763 if (!(key_cache= create_key_cache(base_name->str, base_name->length))) 00764 return true; 00765 } 00766 00772 if (key_cache->in_init) 00773 return true; 00774 00775 return keycache_update(thd, key_cache, offset, new_value); 00776 } 00777 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 00778 { 00779 KEY_CACHE *key_cache= get_key_cache(base); 00780 if (!key_cache) 00781 key_cache= &zero_key_cache; 00782 return keycache_var_ptr(key_cache, offset); 00783 } 00784 }; 00785 00793 class Sys_var_double: public sys_var 00794 { 00795 public: 00796 Sys_var_double(const char *name_arg, 00797 const char *comment, int flag_args, ptrdiff_t off, size_t size, 00798 CMD_LINE getopt, 00799 double min_val, double max_val, double def_val, PolyLock *lock=0, 00800 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 00801 on_check_function on_check_func=0, 00802 on_update_function on_update_func=0, 00803 const char *substitute=0, 00804 int parse_flag= PARSE_NORMAL) 00805 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 00806 getopt.arg_type, SHOW_DOUBLE, 00807 (longlong) getopt_double2ulonglong(def_val), 00808 lock, binlog_status_arg, on_check_func, on_update_func, 00809 substitute, parse_flag) 00810 { 00811 option.var_type= GET_DOUBLE; 00812 option.min_value= (longlong) getopt_double2ulonglong(min_val); 00813 option.max_value= (longlong) getopt_double2ulonglong(max_val); 00814 global_var(double)= (double)option.def_value; 00815 DBUG_ASSERT(min_val <= max_val); 00816 DBUG_ASSERT(min_val <= def_val); 00817 DBUG_ASSERT(max_val >= def_val); 00818 DBUG_ASSERT(size == sizeof(double)); 00819 } 00820 bool do_check(THD *thd, set_var *var) 00821 { 00822 my_bool fixed; 00823 double v= var->value->val_real(); 00824 var->save_result.double_value= getopt_double_limit_value(v, &option, &fixed); 00825 00826 return throw_bounds_warning(thd, name.str, fixed, v); 00827 } 00828 bool session_update(THD *thd, set_var *var) 00829 { 00830 session_var(thd, double)= var->save_result.double_value; 00831 return false; 00832 } 00833 bool global_update(THD *thd, set_var *var) 00834 { 00835 global_var(double)= var->save_result.double_value; 00836 return false; 00837 } 00838 bool check_update_type(Item_result type) 00839 { 00840 return type != INT_RESULT && type != REAL_RESULT && type != DECIMAL_RESULT; 00841 } 00842 void session_save_default(THD *thd, set_var *var) 00843 { var->save_result.double_value= global_var(double); } 00844 void global_save_default(THD *thd, set_var *var) 00845 { var->save_result.double_value= getopt_ulonglong2double(option.def_value); } 00846 }; 00847 00858 class Sys_var_test_flag: public Sys_var_mybool 00859 { 00860 private: 00861 my_bool test_flag_value; 00862 uint test_flag_mask; 00863 public: 00864 Sys_var_test_flag(const char *name_arg, const char *comment, uint mask) 00865 : Sys_var_mybool(name_arg, comment, READ_ONLY GLOBAL_VAR(test_flag_value), 00866 NO_CMD_LINE, DEFAULT(FALSE)) 00867 { 00868 test_flag_mask= mask; 00869 } 00870 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 00871 { 00872 test_flag_value= ((test_flags & test_flag_mask) > 0); 00873 return (uchar*) &test_flag_value; 00874 } 00875 }; 00876 00887 class Sys_var_max_user_conn: public Sys_var_uint 00888 { 00889 public: 00890 Sys_var_max_user_conn(const char *name_arg, 00891 const char *comment, int flag_args, ptrdiff_t off, size_t size, 00892 CMD_LINE getopt, 00893 uint min_val, uint max_val, uint def_val, 00894 uint block_size, PolyLock *lock=0, 00895 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 00896 on_check_function on_check_func=0, 00897 on_update_function on_update_func=0, 00898 const char *substitute=0) 00899 : Sys_var_uint(name_arg, comment, SESSION, off, size, getopt, 00900 min_val, max_val, def_val, block_size, 00901 lock, binlog_status_arg, on_check_func, on_update_func, 00902 substitute) 00903 { } 00904 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 00905 { 00906 const USER_CONN *uc= thd->get_user_connect(); 00907 if (uc && uc->user_resources.user_conn) 00908 return (uchar*) &(uc->user_resources.user_conn); 00909 return global_value_ptr(thd, base); 00910 } 00911 }; 00912 00913 // overflow-safe (1 << X)-1 00914 #define MAX_SET(X) ((((1UL << ((X)-1))-1) << 1) | 1) 00915 00930 class Sys_var_flagset: public Sys_var_typelib 00931 { 00932 public: 00933 Sys_var_flagset(const char *name_arg, 00934 const char *comment, int flag_args, ptrdiff_t off, size_t size, 00935 CMD_LINE getopt, 00936 const char *values[], ulonglong def_val, PolyLock *lock=0, 00937 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 00938 on_check_function on_check_func=0, 00939 on_update_function on_update_func=0, 00940 const char *substitute=0) 00941 : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, 00942 SHOW_CHAR, values, def_val, lock, 00943 binlog_status_arg, on_check_func, on_update_func, 00944 substitute) 00945 { 00946 option.var_type= GET_FLAGSET; 00947 global_var(ulonglong)= def_val; 00948 DBUG_ASSERT(typelib.count > 1); 00949 DBUG_ASSERT(typelib.count <= 65); 00950 DBUG_ASSERT(def_val < MAX_SET(typelib.count)); 00951 DBUG_ASSERT(strcmp(values[typelib.count-1], "default") == 0); 00952 DBUG_ASSERT(size == sizeof(ulonglong)); 00953 } 00954 bool do_check(THD *thd, set_var *var) 00955 { 00956 char buff[STRING_BUFFER_USUAL_SIZE]; 00957 String str(buff, sizeof(buff), system_charset_info), *res; 00958 ulonglong default_value, current_value; 00959 if (var->type == OPT_GLOBAL) 00960 { 00961 default_value= option.def_value; 00962 current_value= global_var(ulonglong); 00963 } 00964 else 00965 { 00966 default_value= global_var(ulonglong); 00967 current_value= session_var(thd, ulonglong); 00968 } 00969 00970 if (var->value->result_type() == STRING_RESULT) 00971 { 00972 if (!(res=var->value->val_str(&str))) 00973 return true; 00974 else 00975 { 00976 char *error; 00977 uint error_len; 00978 00979 var->save_result.ulonglong_value= 00980 find_set_from_flags(&typelib, 00981 typelib.count, 00982 current_value, 00983 default_value, 00984 res->ptr(), res->length(), 00985 &error, &error_len); 00986 if (error) 00987 { 00988 ErrConvString err(error, error_len, res->charset()); 00989 my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr()); 00990 return true; 00991 } 00992 } 00993 } 00994 else 00995 { 00996 longlong tmp=var->value->val_int(); 00997 if ((tmp < 0 && ! var->value->unsigned_flag) 00998 || (ulonglong)tmp > MAX_SET(typelib.count)) 00999 return true; 01000 else 01001 var->save_result.ulonglong_value= tmp; 01002 } 01003 01004 return false; 01005 } 01006 bool session_update(THD *thd, set_var *var) 01007 { 01008 session_var(thd, ulonglong)= var->save_result.ulonglong_value; 01009 return false; 01010 } 01011 bool global_update(THD *thd, set_var *var) 01012 { 01013 global_var(ulonglong)= var->save_result.ulonglong_value; 01014 return false; 01015 } 01016 void session_save_default(THD *thd, set_var *var) 01017 { var->save_result.ulonglong_value= global_var(ulonglong); } 01018 void global_save_default(THD *thd, set_var *var) 01019 { var->save_result.ulonglong_value= option.def_value; } 01020 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 01021 { 01022 return (uchar*)flagset_to_string(thd, 0, session_var(thd, ulonglong), 01023 typelib.type_names); 01024 } 01025 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 01026 { 01027 return (uchar*)flagset_to_string(thd, 0, global_var(ulonglong), 01028 typelib.type_names); 01029 } 01030 }; 01031 01041 class Sys_var_set: public Sys_var_typelib 01042 { 01043 public: 01044 Sys_var_set(const char *name_arg, 01045 const char *comment, int flag_args, ptrdiff_t off, size_t size, 01046 CMD_LINE getopt, 01047 const char *values[], ulonglong def_val, PolyLock *lock=0, 01048 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 01049 on_check_function on_check_func=0, 01050 on_update_function on_update_func=0, 01051 const char *substitute=0) 01052 : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, 01053 SHOW_CHAR, values, def_val, lock, 01054 binlog_status_arg, on_check_func, on_update_func, 01055 substitute) 01056 { 01057 option.var_type= GET_SET; 01058 global_var(ulonglong)= def_val; 01059 DBUG_ASSERT(typelib.count > 0); 01060 DBUG_ASSERT(typelib.count <= 64); 01061 DBUG_ASSERT(def_val < MAX_SET(typelib.count)); 01062 DBUG_ASSERT(size == sizeof(ulonglong)); 01063 } 01064 bool do_check(THD *thd, set_var *var) 01065 { 01066 char buff[STRING_BUFFER_USUAL_SIZE]; 01067 String str(buff, sizeof(buff), system_charset_info), *res; 01068 01069 if (var->value->result_type() == STRING_RESULT) 01070 { 01071 if (!(res=var->value->val_str(&str))) 01072 return true; 01073 else 01074 { 01075 char *error; 01076 uint error_len; 01077 bool not_used; 01078 01079 var->save_result.ulonglong_value= 01080 find_set(&typelib, res->ptr(), res->length(), NULL, 01081 &error, &error_len, ¬_used); 01082 /* 01083 note, we only issue an error if error_len > 0. 01084 That is even while empty (zero-length) values are considered 01085 errors by find_set(), these errors are ignored here 01086 */ 01087 if (error_len) 01088 { 01089 ErrConvString err(error, error_len, res->charset()); 01090 my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr()); 01091 return true; 01092 } 01093 } 01094 } 01095 else 01096 { 01097 longlong tmp=var->value->val_int(); 01098 if ((tmp < 0 && ! var->value->unsigned_flag) 01099 || (ulonglong)tmp > MAX_SET(typelib.count)) 01100 return true; 01101 else 01102 var->save_result.ulonglong_value= tmp; 01103 } 01104 01105 return false; 01106 } 01107 bool session_update(THD *thd, set_var *var) 01108 { 01109 session_var(thd, ulonglong)= var->save_result.ulonglong_value; 01110 return false; 01111 } 01112 bool global_update(THD *thd, set_var *var) 01113 { 01114 global_var(ulonglong)= var->save_result.ulonglong_value; 01115 return false; 01116 } 01117 void session_save_default(THD *thd, set_var *var) 01118 { var->save_result.ulonglong_value= global_var(ulonglong); } 01119 void global_save_default(THD *thd, set_var *var) 01120 { var->save_result.ulonglong_value= option.def_value; } 01121 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 01122 { 01123 return (uchar*)set_to_string(thd, 0, session_var(thd, ulonglong), 01124 typelib.type_names); 01125 } 01126 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 01127 { 01128 return (uchar*)set_to_string(thd, 0, global_var(ulonglong), 01129 typelib.type_names); 01130 } 01131 }; 01132 01146 class Sys_var_plugin: public sys_var 01147 { 01148 int plugin_type; 01149 public: 01150 Sys_var_plugin(const char *name_arg, 01151 const char *comment, int flag_args, ptrdiff_t off, size_t size, 01152 CMD_LINE getopt, 01153 int plugin_type_arg, char **def_val, PolyLock *lock=0, 01154 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 01155 on_check_function on_check_func=0, 01156 on_update_function on_update_func=0, 01157 const char *substitute=0, 01158 int parse_flag= PARSE_NORMAL) 01159 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 01160 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 01161 lock, binlog_status_arg, on_check_func, on_update_func, 01162 substitute, parse_flag), 01163 plugin_type(plugin_type_arg) 01164 { 01165 option.var_type= GET_STR; 01166 DBUG_ASSERT(size == sizeof(plugin_ref)); 01167 DBUG_ASSERT(getopt.id == -1); // force NO_CMD_LINE 01168 } 01169 bool do_check(THD *thd, set_var *var) 01170 { 01171 char buff[STRING_BUFFER_USUAL_SIZE]; 01172 String str(buff,sizeof(buff), system_charset_info), *res; 01173 if (!(res=var->value->val_str(&str))) 01174 var->save_result.plugin= NULL; 01175 else 01176 { 01177 const LEX_STRING pname= { const_cast<char*>(res->ptr()), res->length() }; 01178 plugin_ref plugin; 01179 01180 // special code for storage engines (e.g. to handle historical aliases) 01181 if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN) 01182 plugin= ha_resolve_by_name(thd, &pname, FALSE); 01183 else 01184 plugin= my_plugin_lock_by_name(thd, &pname, plugin_type); 01185 if (!plugin) 01186 { 01187 // historically different error code 01188 if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN) 01189 { 01190 ErrConvString err(res); 01191 my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), err.ptr()); 01192 } 01193 return true; 01194 } 01195 var->save_result.plugin= plugin; 01196 } 01197 return false; 01198 } 01199 void do_update(plugin_ref *valptr, plugin_ref newval) 01200 { 01201 plugin_ref oldval= *valptr; 01202 if (oldval != newval) 01203 { 01204 *valptr= my_plugin_lock(NULL, &newval); 01205 plugin_unlock(NULL, oldval); 01206 } 01207 } 01208 bool session_update(THD *thd, set_var *var) 01209 { 01210 do_update((plugin_ref*)session_var_ptr(thd), 01211 var->save_result.plugin); 01212 return false; 01213 } 01214 bool global_update(THD *thd, set_var *var) 01215 { 01216 do_update((plugin_ref*)global_var_ptr(), 01217 var->save_result.plugin); 01218 return false; 01219 } 01220 void session_save_default(THD *thd, set_var *var) 01221 { 01222 plugin_ref plugin= global_var(plugin_ref); 01223 var->save_result.plugin= my_plugin_lock(thd, &plugin); 01224 } 01225 void global_save_default(THD *thd, set_var *var) 01226 { 01227 LEX_STRING pname; 01228 char **default_value= reinterpret_cast<char**>(option.def_value); 01229 pname.str= *default_value; 01230 pname.length= strlen(pname.str); 01231 01232 plugin_ref plugin; 01233 if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN) 01234 plugin= ha_resolve_by_name(thd, &pname, FALSE); 01235 else 01236 plugin= my_plugin_lock_by_name(thd, &pname, plugin_type); 01237 DBUG_ASSERT(plugin); 01238 01239 var->save_result.plugin= my_plugin_lock(thd, &plugin); 01240 } 01241 bool check_update_type(Item_result type) 01242 { return type != STRING_RESULT; } 01243 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 01244 { 01245 plugin_ref plugin= session_var(thd, plugin_ref); 01246 return (uchar*)(plugin ? thd->strmake(plugin_name(plugin)->str, 01247 plugin_name(plugin)->length) : 0); 01248 } 01249 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 01250 { 01251 plugin_ref plugin= global_var(plugin_ref); 01252 return (uchar*)(plugin ? thd->strmake(plugin_name(plugin)->str, 01253 plugin_name(plugin)->length) : 0); 01254 } 01255 }; 01256 01257 #if defined(ENABLED_DEBUG_SYNC) 01258 01261 class Sys_var_debug_sync :public sys_var 01262 { 01263 public: 01264 Sys_var_debug_sync(const char *name_arg, 01265 const char *comment, int flag_args, 01266 CMD_LINE getopt, 01267 const char *def_val, PolyLock *lock=0, 01268 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 01269 on_check_function on_check_func=0, 01270 on_update_function on_update_func=0, 01271 const char *substitute=0, 01272 int parse_flag= PARSE_NORMAL) 01273 : sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id, 01274 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 01275 lock, binlog_status_arg, on_check_func, on_update_func, 01276 substitute, parse_flag) 01277 { 01278 DBUG_ASSERT(scope() == ONLY_SESSION); 01279 option.var_type= GET_NO_ARG; 01280 } 01281 bool do_check(THD *thd, set_var *var) 01282 { 01283 char buff[STRING_BUFFER_USUAL_SIZE]; 01284 String str(buff, sizeof(buff), system_charset_info), *res; 01285 01286 if (!(res=var->value->val_str(&str))) 01287 var->save_result.string_value.str= const_cast<char*>(""); 01288 else 01289 var->save_result.string_value.str= thd->strmake(res->ptr(), res->length()); 01290 return false; 01291 } 01292 bool session_update(THD *thd, set_var *var) 01293 { 01294 extern bool debug_sync_update(THD *thd, char *val_str); 01295 return debug_sync_update(thd, var->save_result.string_value.str); 01296 } 01297 bool global_update(THD *thd, set_var *var) 01298 { 01299 DBUG_ASSERT(FALSE); 01300 return true; 01301 } 01302 void session_save_default(THD *thd, set_var *var) 01303 { 01304 var->save_result.string_value.str= const_cast<char*>(""); 01305 var->save_result.string_value.length= 0; 01306 } 01307 void global_save_default(THD *thd, set_var *var) 01308 { 01309 DBUG_ASSERT(FALSE); 01310 } 01311 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 01312 { 01313 extern uchar *debug_sync_value_ptr(THD *thd); 01314 return debug_sync_value_ptr(thd); 01315 } 01316 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 01317 { 01318 DBUG_ASSERT(FALSE); 01319 return 0; 01320 } 01321 bool check_update_type(Item_result type) 01322 { return type != STRING_RESULT; } 01323 }; 01324 #endif /* defined(ENABLED_DEBUG_SYNC) */ 01325 01345 class Sys_var_bit: public Sys_var_typelib 01346 { 01347 ulonglong bitmask; 01348 bool reverse_semantics; 01349 void set(uchar *ptr, ulonglong value) 01350 { 01351 if ((value != 0) ^ reverse_semantics) 01352 (*(ulonglong *)ptr)|= bitmask; 01353 else 01354 (*(ulonglong *)ptr)&= ~bitmask; 01355 } 01356 public: 01357 Sys_var_bit(const char *name_arg, 01358 const char *comment, int flag_args, ptrdiff_t off, size_t size, 01359 CMD_LINE getopt, 01360 ulonglong bitmask_arg, my_bool def_val, PolyLock *lock=0, 01361 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 01362 on_check_function on_check_func=0, 01363 on_update_function on_update_func=0, 01364 const char *substitute=0) 01365 : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, 01366 SHOW_MY_BOOL, bool_values, def_val, lock, 01367 binlog_status_arg, on_check_func, on_update_func, 01368 substitute) 01369 { 01370 option.var_type= GET_BOOL; 01371 reverse_semantics= my_count_bits(bitmask_arg) > 1; 01372 bitmask= reverse_semantics ? ~bitmask_arg : bitmask_arg; 01373 set(global_var_ptr(), def_val); 01374 DBUG_ASSERT(def_val < 2); 01375 DBUG_ASSERT(getopt.id == -1); // force NO_CMD_LINE 01376 DBUG_ASSERT(size == sizeof(ulonglong)); 01377 } 01378 bool session_update(THD *thd, set_var *var) 01379 { 01380 set(session_var_ptr(thd), var->save_result.ulonglong_value); 01381 return false; 01382 } 01383 bool global_update(THD *thd, set_var *var) 01384 { 01385 set(global_var_ptr(), var->save_result.ulonglong_value); 01386 return false; 01387 } 01388 void session_save_default(THD *thd, set_var *var) 01389 { var->save_result.ulonglong_value= global_var(ulonglong) & bitmask; } 01390 void global_save_default(THD *thd, set_var *var) 01391 { var->save_result.ulonglong_value= option.def_value; } 01392 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 01393 { 01394 thd->sys_var_tmp.my_bool_value= reverse_semantics ^ 01395 ((session_var(thd, ulonglong) & bitmask) != 0); 01396 return (uchar*) &thd->sys_var_tmp.my_bool_value; 01397 } 01398 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 01399 { 01400 thd->sys_var_tmp.my_bool_value= reverse_semantics ^ 01401 ((global_var(ulonglong) & bitmask) != 0); 01402 return (uchar*) &thd->sys_var_tmp.my_bool_value; 01403 } 01404 }; 01405 01421 class Sys_var_session_special: public Sys_var_ulonglong 01422 { 01423 typedef bool (*session_special_update_function)(THD *thd, set_var *var); 01424 typedef ulonglong (*session_special_read_function)(THD *thd); 01425 01426 session_special_read_function read_func; 01427 session_special_update_function update_func; 01428 public: 01429 Sys_var_session_special(const char *name_arg, 01430 const char *comment, int flag_args, 01431 CMD_LINE getopt, 01432 ulonglong min_val, ulonglong max_val, ulonglong block_size, 01433 PolyLock *lock, enum binlog_status_enum binlog_status_arg, 01434 on_check_function on_check_func, 01435 session_special_update_function update_func_arg, 01436 session_special_read_function read_func_arg, 01437 const char *substitute=0) 01438 : Sys_var_ulonglong(name_arg, comment, flag_args, 0, 01439 sizeof(ulonglong), getopt, min_val, 01440 max_val, 0, block_size, lock, binlog_status_arg, on_check_func, 0, 01441 substitute), 01442 read_func(read_func_arg), update_func(update_func_arg) 01443 { 01444 DBUG_ASSERT(scope() == ONLY_SESSION); 01445 DBUG_ASSERT(getopt.id == -1); // NO_CMD_LINE, because the offset is fake 01446 } 01447 bool session_update(THD *thd, set_var *var) 01448 { return update_func(thd, var); } 01449 bool global_update(THD *thd, set_var *var) 01450 { 01451 DBUG_ASSERT(FALSE); 01452 return true; 01453 } 01454 void session_save_default(THD *thd, set_var *var) 01455 { var->value= 0; } 01456 void global_save_default(THD *thd, set_var *var) 01457 { DBUG_ASSERT(FALSE); } 01458 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 01459 { 01460 thd->sys_var_tmp.ulonglong_value= read_func(thd); 01461 return (uchar*) &thd->sys_var_tmp.ulonglong_value; 01462 } 01463 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 01464 { 01465 DBUG_ASSERT(FALSE); 01466 return 0; 01467 } 01468 }; 01469 01470 01474 class Sys_var_session_special_double: public Sys_var_double 01475 { 01476 typedef bool (*session_special_update_function)(THD *thd, set_var *var); 01477 typedef double (*session_special_read_double_function)(THD *thd); 01478 01479 session_special_read_double_function read_func; 01480 session_special_update_function update_func; 01481 public: 01482 Sys_var_session_special_double(const char *name_arg, 01483 const char *comment, int flag_args, 01484 CMD_LINE getopt, 01485 ulonglong min_val, ulonglong max_val, ulonglong block_size, 01486 PolyLock *lock, enum binlog_status_enum binlog_status_arg, 01487 on_check_function on_check_func, 01488 session_special_update_function update_func_arg, 01489 session_special_read_double_function read_func_arg, 01490 const char *substitute=0) 01491 : Sys_var_double(name_arg, comment, flag_args, 0, 01492 sizeof(double), getopt, 01493 min_val, max_val, 0, 01494 lock, binlog_status_arg, on_check_func, 0, 01495 substitute), 01496 read_func(read_func_arg), update_func(update_func_arg) 01497 { 01498 DBUG_ASSERT(scope() == ONLY_SESSION); 01499 DBUG_ASSERT(getopt.id == -1); // NO_CMD_LINE, because the offset is fake 01500 } 01501 bool session_update(THD *thd, set_var *var) 01502 { return update_func(thd, var); } 01503 bool global_update(THD *thd, set_var *var) 01504 { 01505 DBUG_ASSERT(FALSE); 01506 return true; 01507 } 01508 void session_save_default(THD *thd, set_var *var) 01509 { var->value= 0; } 01510 void global_save_default(THD *thd, set_var *var) 01511 { DBUG_ASSERT(FALSE); } 01512 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 01513 { 01514 thd->sys_var_tmp.double_value= read_func(thd); 01515 return (uchar *) &thd->sys_var_tmp.double_value; 01516 } 01517 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 01518 { 01519 DBUG_ASSERT(FALSE); 01520 return 0; 01521 } 01522 }; 01523 01524 01535 class Sys_var_have: public sys_var 01536 { 01537 public: 01538 Sys_var_have(const char *name_arg, 01539 const char *comment, int flag_args, ptrdiff_t off, size_t size, 01540 CMD_LINE getopt, 01541 PolyLock *lock=0, 01542 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 01543 on_check_function on_check_func=0, 01544 on_update_function on_update_func=0, 01545 const char *substitute=0, 01546 int parse_flag= PARSE_NORMAL) 01547 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 01548 getopt.arg_type, SHOW_CHAR, 0, 01549 lock, binlog_status_arg, on_check_func, on_update_func, 01550 substitute, parse_flag) 01551 { 01552 DBUG_ASSERT(scope() == GLOBAL); 01553 DBUG_ASSERT(getopt.id == -1); 01554 DBUG_ASSERT(lock == 0); 01555 DBUG_ASSERT(binlog_status_arg == VARIABLE_NOT_IN_BINLOG); 01556 DBUG_ASSERT(is_readonly()); 01557 DBUG_ASSERT(on_update == 0); 01558 DBUG_ASSERT(size == sizeof(enum SHOW_COMP_OPTION)); 01559 } 01560 bool do_check(THD *thd, set_var *var) { 01561 DBUG_ASSERT(FALSE); 01562 return true; 01563 } 01564 bool session_update(THD *thd, set_var *var) 01565 { 01566 DBUG_ASSERT(FALSE); 01567 return true; 01568 } 01569 bool global_update(THD *thd, set_var *var) 01570 { 01571 DBUG_ASSERT(FALSE); 01572 return true; 01573 } 01574 void session_save_default(THD *thd, set_var *var) { } 01575 void global_save_default(THD *thd, set_var *var) { } 01576 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 01577 { 01578 DBUG_ASSERT(FALSE); 01579 return 0; 01580 } 01581 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 01582 { 01583 return (uchar*)show_comp_option_name[global_var(enum SHOW_COMP_OPTION)]; 01584 } 01585 bool check_update_type(Item_result type) { return false; } 01586 }; 01587 01603 class Sys_var_struct: public sys_var 01604 { 01605 ptrdiff_t name_offset; // offset to the 'name' property in the structure 01606 public: 01607 Sys_var_struct(const char *name_arg, 01608 const char *comment, int flag_args, ptrdiff_t off, size_t size, 01609 CMD_LINE getopt, 01610 ptrdiff_t name_off, void *def_val, PolyLock *lock=0, 01611 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 01612 on_check_function on_check_func=0, 01613 on_update_function on_update_func=0, 01614 const char *substitute=0, 01615 int parse_flag= PARSE_NORMAL) 01616 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 01617 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 01618 lock, binlog_status_arg, on_check_func, on_update_func, 01619 substitute, parse_flag), 01620 name_offset(name_off) 01621 { 01622 option.var_type= GET_STR; 01623 /* 01624 struct variables are special on the command line - often (e.g. for 01625 charsets) the name cannot be immediately resolved, but only after all 01626 options (in particular, basedir) are parsed. 01627 01628 thus all struct command-line options should be added manually 01629 to my_long_options in mysqld.cc 01630 */ 01631 DBUG_ASSERT(getopt.id == -1); 01632 DBUG_ASSERT(size == sizeof(void *)); 01633 } 01634 bool do_check(THD *thd, set_var *var) 01635 { return false; } 01636 bool session_update(THD *thd, set_var *var) 01637 { 01638 session_var(thd, const void*)= var->save_result.ptr; 01639 return false; 01640 } 01641 bool global_update(THD *thd, set_var *var) 01642 { 01643 global_var(const void*)= var->save_result.ptr; 01644 return false; 01645 } 01646 void session_save_default(THD *thd, set_var *var) 01647 { var->save_result.ptr= global_var(void*); } 01648 void global_save_default(THD *thd, set_var *var) 01649 { 01650 void **default_value= reinterpret_cast<void**>(option.def_value); 01651 var->save_result.ptr= *default_value; 01652 } 01653 bool check_update_type(Item_result type) 01654 { return type != INT_RESULT && type != STRING_RESULT; } 01655 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 01656 { 01657 uchar *ptr= session_var(thd, uchar*); 01658 return ptr ? *(uchar**)(ptr+name_offset) : 0; 01659 } 01660 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 01661 { 01662 uchar *ptr= global_var(uchar*); 01663 return ptr ? *(uchar**)(ptr+name_offset) : 0; 01664 } 01665 }; 01666 01677 class Sys_var_tz: public sys_var 01678 { 01679 public: 01680 Sys_var_tz(const char *name_arg, 01681 const char *comment, int flag_args, ptrdiff_t off, size_t size, 01682 CMD_LINE getopt, 01683 Time_zone **def_val, PolyLock *lock=0, 01684 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 01685 on_check_function on_check_func=0, 01686 on_update_function on_update_func=0, 01687 const char *substitute=0, 01688 int parse_flag= PARSE_NORMAL) 01689 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 01690 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 01691 lock, binlog_status_arg, on_check_func, on_update_func, 01692 substitute, parse_flag) 01693 { 01694 DBUG_ASSERT(getopt.id == -1); 01695 DBUG_ASSERT(size == sizeof(Time_zone *)); 01696 } 01697 bool do_check(THD *thd, set_var *var) 01698 { 01699 char buff[MAX_TIME_ZONE_NAME_LENGTH]; 01700 String str(buff, sizeof(buff), &my_charset_latin1); 01701 String *res= var->value->val_str(&str); 01702 01703 if (!res) 01704 return true; 01705 01706 if (!(var->save_result.time_zone= my_tz_find(thd, res))) 01707 { 01708 ErrConvString err(res); 01709 my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), err.ptr()); 01710 return true; 01711 } 01712 return false; 01713 } 01714 bool session_update(THD *thd, set_var *var) 01715 { 01716 session_var(thd, Time_zone*)= var->save_result.time_zone; 01717 return false; 01718 } 01719 bool global_update(THD *thd, set_var *var) 01720 { 01721 global_var(Time_zone*)= var->save_result.time_zone; 01722 return false; 01723 } 01724 void session_save_default(THD *thd, set_var *var) 01725 { 01726 var->save_result.time_zone= global_var(Time_zone*); 01727 } 01728 void global_save_default(THD *thd, set_var *var) 01729 { 01730 var->save_result.time_zone= 01731 *(Time_zone**)(intptr)option.def_value; 01732 } 01733 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 01734 { 01735 /* 01736 This is an ugly fix for replication: we don't replicate properly queries 01737 invoking system variables' values to update tables; but 01738 CONVERT_TZ(,,@@session.time_zone) is so popular that we make it 01739 replicable (i.e. we tell the binlog code to store the session 01740 timezone). If it's the global value which was used we can't replicate 01741 (binlog code stores session value only). 01742 */ 01743 thd->time_zone_used= 1; 01744 return (uchar *)(session_var(thd, Time_zone*)->get_name()->ptr()); 01745 } 01746 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 01747 { 01748 return (uchar *)(global_var(Time_zone*)->get_name()->ptr()); 01749 } 01750 bool check_update_type(Item_result type) 01751 { return type != STRING_RESULT; } 01752 }; 01753 01754 01755 class Sys_var_tx_isolation: public Sys_var_enum 01756 { 01757 public: 01758 Sys_var_tx_isolation(const char *name_arg, 01759 const char *comment, int flag_args, ptrdiff_t off, size_t size, 01760 CMD_LINE getopt, 01761 const char *values[], uint def_val, PolyLock *lock, 01762 enum binlog_status_enum binlog_status_arg, 01763 on_check_function on_check_func) 01764 :Sys_var_enum(name_arg, comment, flag_args, off, size, getopt, 01765 values, def_val, lock, binlog_status_arg, on_check_func) 01766 {} 01767 virtual bool session_update(THD *thd, set_var *var); 01768 }; 01769 01770 01780 class Sys_var_tx_read_only: public Sys_var_mybool 01781 { 01782 public: 01783 Sys_var_tx_read_only(const char *name_arg, const char *comment, int flag_args, 01784 ptrdiff_t off, size_t size, CMD_LINE getopt, 01785 my_bool def_val, PolyLock *lock, 01786 enum binlog_status_enum binlog_status_arg, 01787 on_check_function on_check_func) 01788 :Sys_var_mybool(name_arg, comment, flag_args, off, size, getopt, 01789 def_val, lock, binlog_status_arg, on_check_func) 01790 {} 01791 virtual bool session_update(THD *thd, set_var *var); 01792 }; 01793 01794 01799 class Sys_var_enum_binlog_checksum: public Sys_var_enum 01800 { 01801 public: 01802 Sys_var_enum_binlog_checksum(const char *name_arg, 01803 const char *comment, int flag_args, ptrdiff_t off, size_t size, 01804 CMD_LINE getopt, 01805 const char *values[], uint def_val, PolyLock *lock, 01806 enum binlog_status_enum binlog_status_arg) 01807 :Sys_var_enum(name_arg, comment, flag_args, off, size, getopt, 01808 values, def_val, lock, binlog_status_arg, NULL) 01809 {} 01810 virtual bool global_update(THD *thd, set_var *var); 01811 }; 01812 01813 01817 class Sys_var_gtid_specification: public sys_var 01818 { 01819 public: 01820 Sys_var_gtid_specification(const char *name_arg, 01821 const char *comment, int flag_args, ptrdiff_t off, size_t size, 01822 CMD_LINE getopt, 01823 const char *def_val, 01824 PolyLock *lock= 0, 01825 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 01826 on_check_function on_check_func=0, 01827 on_update_function on_update_func=0, 01828 const char *substitute=0, 01829 int parse_flag= PARSE_NORMAL) 01830 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 01831 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 01832 lock, binlog_status_arg, on_check_func, on_update_func, 01833 substitute, parse_flag) 01834 { 01835 DBUG_ASSERT(size == sizeof(Gtid_specification)); 01836 } 01837 bool session_update(THD *thd, set_var *var) 01838 { 01839 DBUG_ENTER("Sys_var_gtid::session_update"); 01840 global_sid_lock->rdlock(); 01841 bool ret= (((Gtid_specification *)session_var_ptr(thd))-> 01842 parse(global_sid_map, 01843 var->save_result.string_value.str) != 0); 01844 global_sid_lock->unlock(); 01845 DBUG_RETURN(ret); 01846 } 01847 bool global_update(THD *thd, set_var *var) 01848 { DBUG_ASSERT(FALSE); return true; } 01849 void session_save_default(THD *thd, set_var *var) 01850 { 01851 DBUG_ENTER("Sys_var_gtid::session_save_default"); 01852 char *ptr= (char*)(intptr)option.def_value; 01853 var->save_result.string_value.str= ptr; 01854 var->save_result.string_value.length= ptr ? strlen(ptr) : 0; 01855 DBUG_VOID_RETURN; 01856 } 01857 void global_save_default(THD *thd, set_var *var) 01858 { DBUG_ASSERT(FALSE); } 01859 bool do_check(THD *thd, set_var *var) 01860 { 01861 DBUG_ENTER("Sys_var_gtid::do_check"); 01862 char buf[Gtid_specification::MAX_TEXT_LENGTH + 1]; 01863 String str(buf, sizeof(buf), &my_charset_latin1); 01864 String *res= var->value->val_str(&str); 01865 if (!res) 01866 DBUG_RETURN(true); 01867 var->save_result.string_value.str= thd->strmake(res->c_ptr_safe(), res->length()); 01868 if (!var->save_result.string_value.str) 01869 { 01870 my_error(ER_OUT_OF_RESOURCES, MYF(0)); // thd->strmake failed 01871 DBUG_RETURN(true); 01872 } 01873 var->save_result.string_value.length= res->length(); 01874 bool ret= Gtid_specification::is_valid(res->c_ptr_safe()) ? false : true; 01875 DBUG_PRINT("info", ("ret=%d", ret)); 01876 DBUG_RETURN(ret); 01877 } 01878 bool check_update_type(Item_result type) 01879 { return type != STRING_RESULT; } 01880 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 01881 { 01882 DBUG_ENTER("Sys_var_gtid::session_value_ptr"); 01883 char buf[Gtid_specification::MAX_TEXT_LENGTH + 1]; 01884 global_sid_lock->rdlock(); 01885 ((Gtid_specification *)session_var_ptr(thd))-> 01886 to_string(global_sid_map, buf); 01887 global_sid_lock->unlock(); 01888 char *ret= thd->strdup(buf); 01889 DBUG_RETURN((uchar *)ret); 01890 } 01891 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 01892 { DBUG_ASSERT(FALSE); return NULL; } 01893 }; 01894 01895 #ifdef HAVE_GTID_NEXT_LIST 01896 01903 class Sys_var_gtid_set: public sys_var 01904 { 01905 public: 01906 Sys_var_gtid_set(const char *name_arg, 01907 const char *comment, int flag_args, ptrdiff_t off, size_t size, 01908 CMD_LINE getopt, 01909 const char *def_val, 01910 PolyLock *lock= 0, 01911 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 01912 on_check_function on_check_func=0, 01913 on_update_function on_update_func=0, 01914 const char *substitute=0, 01915 int parse_flag= PARSE_NORMAL) 01916 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 01917 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 01918 lock, binlog_status_arg, on_check_func, on_update_func, 01919 substitute, parse_flag) 01920 { 01921 DBUG_ASSERT(size == sizeof(Gtid_set_or_null)); 01922 } 01923 bool session_update(THD *thd, set_var *var) 01924 { 01925 DBUG_ENTER("Sys_var_gtid_set::session_update"); 01926 Gtid_set_or_null *gsn= 01927 (Gtid_set_or_null *)session_var_ptr(thd); 01928 char *value= var->save_result.string_value.str; 01929 if (value == NULL) 01930 gsn->set_null(); 01931 else 01932 { 01933 Gtid_set *gs= gsn->set_non_null(global_sid_map); 01934 if (gs == NULL) 01935 { 01936 my_error(ER_OUT_OF_RESOURCES, MYF(0)); // allocation failed 01937 DBUG_RETURN(true); 01938 } 01939 /* 01940 If string begins with '+', add to the existing set, otherwise 01941 replace existing set. 01942 */ 01943 while (isspace(*value)) 01944 value++; 01945 if (*value == '+') 01946 value++; 01947 else 01948 gs->clear(); 01949 // Add specified set of groups to Gtid_set. 01950 global_sid_lock->rdlock(); 01951 enum_return_status ret= gs->add_gtid_text(value); 01952 global_sid_lock->unlock(); 01953 if (ret != RETURN_STATUS_OK) 01954 { 01955 gsn->set_null(); 01956 DBUG_RETURN(true); 01957 } 01958 } 01959 DBUG_RETURN(false); 01960 } 01961 bool global_update(THD *thd, set_var *var) 01962 { DBUG_ASSERT(FALSE); return true; } 01963 void session_save_default(THD *thd, set_var *var) 01964 { 01965 DBUG_ENTER("Sys_var_gtid_set::session_save_default"); 01966 char *ptr= (char*)(intptr)option.def_value; 01967 var->save_result.string_value.str= ptr; 01968 var->save_result.string_value.length= ptr ? strlen(ptr) : 0; 01969 DBUG_VOID_RETURN; 01970 } 01971 void global_save_default(THD *thd, set_var *var) 01972 { DBUG_ASSERT(FALSE); } 01973 bool do_check(THD *thd, set_var *var) 01974 { 01975 DBUG_ENTER("Sys_var_gtid_set::do_check"); 01976 String str; 01977 String *res= var->value->val_str(&str); 01978 if (res == NULL) 01979 { 01980 var->save_result.string_value.str= NULL; 01981 DBUG_RETURN(FALSE); 01982 } 01983 DBUG_ASSERT(res->ptr() != NULL); 01984 var->save_result.string_value.str= thd->strmake(res->ptr(), res->length()); 01985 if (var->save_result.string_value.str == NULL) 01986 { 01987 my_error(ER_OUT_OF_RESOURCES, MYF(0)); // thd->strmake failed 01988 DBUG_RETURN(1); 01989 } 01990 var->save_result.string_value.length= res->length(); 01991 bool ret= !Gtid_set::is_valid(res->ptr()); 01992 DBUG_RETURN(ret); 01993 } 01994 bool check_update_type(Item_result type) 01995 { return type != STRING_RESULT; } 01996 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 01997 { 01998 DBUG_ENTER("Sys_var_gtid_set::session_value_ptr"); 01999 Gtid_set_or_null *gsn= (Gtid_set_or_null *)session_var_ptr(thd); 02000 Gtid_set *gs= gsn->get_gtid_set(); 02001 if (gs == NULL) 02002 DBUG_RETURN(NULL); 02003 char *buf; 02004 global_sid_lock->rdlock(); 02005 buf= (char *)thd->alloc(gs->get_string_length() + 1); 02006 if (buf) 02007 gs->to_string(buf); 02008 else 02009 my_error(ER_OUT_OF_RESOURCES, MYF(0)); // thd->alloc faile 02010 global_sid_lock->unlock(); 02011 DBUG_RETURN((uchar *)buf); 02012 } 02013 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 02014 { DBUG_ASSERT(FALSE); return NULL; } 02015 }; 02016 #endif 02017 02018 02025 class Sys_var_charptr_func: public sys_var 02026 { 02027 public: 02028 Sys_var_charptr_func(const char *name_arg, const char *comment, 02029 flag_enum flag_arg) 02030 : sys_var(&all_sys_vars, name_arg, comment, READ_ONLY flag_arg, 02031 0/*off*/, NO_CMD_LINE.id, NO_CMD_LINE.arg_type, 02032 SHOW_CHAR, (intptr)0/*def_val*/, 02033 NULL/*polylock*/, VARIABLE_NOT_IN_BINLOG, 02034 NULL/*on_check_func*/, NULL/*on_update_func*/, 02035 NULL/*substitute*/, PARSE_NORMAL/*parse_flag*/) 02036 { 02037 DBUG_ASSERT(flag_arg == sys_var::GLOBAL || flag_arg == sys_var::SESSION || 02038 flag_arg == sys_var::ONLY_SESSION); 02039 } 02040 bool session_update(THD *thd, set_var *var) 02041 { DBUG_ASSERT(FALSE); return true; } 02042 bool global_update(THD *thd, set_var *var) 02043 { DBUG_ASSERT(FALSE); return true; } 02044 void session_save_default(THD *thd, set_var *var) { DBUG_ASSERT(FALSE); } 02045 void global_save_default(THD *thd, set_var *var) { DBUG_ASSERT(FALSE); } 02046 bool do_check(THD *thd, set_var *var) { DBUG_ASSERT(FALSE); return true; } 02047 bool check_update_type(Item_result type) { DBUG_ASSERT(FALSE); return true; } 02048 virtual uchar *session_value_ptr(THD *thd, LEX_STRING *base) 02049 { DBUG_ASSERT(FALSE); return NULL; } 02050 virtual uchar *global_value_ptr(THD *thd, LEX_STRING *base) 02051 { DBUG_ASSERT(FALSE); return NULL; } 02052 }; 02053 02054 02061 class Sys_var_gtid_set_func: public Sys_var_charptr_func 02062 { 02063 public: 02064 Sys_var_gtid_set_func(const char *name_arg, const char *comment, 02065 flag_enum flag_arg) 02066 : Sys_var_charptr_func(name_arg, comment, flag_arg) {} 02067 02068 typedef enum_return_status (*Gtid_set_getter)(THD *, Gtid_set *); 02069 02070 static uchar *get_string_from_gtid_set(THD *thd, 02071 Gtid_set_getter get_gtid_set) 02072 { 02073 DBUG_ENTER("Sys_var_gtid_ended_groups::session_value_ptr"); 02074 Gtid_set gs(global_sid_map); 02075 char *buf; 02076 // As an optimization, add 10 Intervals that do not need to be 02077 // allocated. 02078 Gtid_set::Interval ivs[10]; 02079 gs.add_interval_memory(10, ivs); 02080 global_sid_lock->wrlock(); 02081 if (get_gtid_set(thd, &gs) != RETURN_STATUS_OK) 02082 goto error; 02083 // allocate string and print to it 02084 buf= (char *)thd->alloc(gs.get_string_length() + 1); 02085 if (buf == NULL) 02086 { 02087 my_error(ER_OUT_OF_RESOURCES, MYF(0)); 02088 goto error; 02089 } 02090 gs.to_string(buf); 02091 global_sid_lock->unlock(); 02092 DBUG_RETURN((uchar *)buf); 02093 error: 02094 global_sid_lock->unlock(); 02095 DBUG_RETURN(NULL); 02096 } 02097 }; 02098 02099 02103 class Sys_var_gtid_executed : Sys_var_gtid_set_func 02104 { 02105 public: 02106 Sys_var_gtid_executed(const char *name_arg, const char *comment_arg) 02107 : Sys_var_gtid_set_func(name_arg, comment_arg, SESSION) {} 02108 02109 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 02110 { 02111 DBUG_ENTER("Sys_var_gtid_executed::global_value_ptr"); 02112 global_sid_lock->wrlock(); 02113 const Gtid_set *gs= gtid_state->get_logged_gtids(); 02114 char *buf= (char *)thd->alloc(gs->get_string_length() + 1); 02115 if (buf == NULL) 02116 my_error(ER_OUT_OF_RESOURCES, MYF(0)); 02117 else 02118 gs->to_string(buf); 02119 global_sid_lock->unlock(); 02120 DBUG_RETURN((uchar *)buf); 02121 } 02122 02123 private: 02124 static enum_return_status get_groups_from_trx_cache(THD *thd, Gtid_set *gs) 02125 { 02126 DBUG_ENTER("Sys_var_gtid_executed::get_groups_from_trx_cache"); 02127 if (opt_bin_log) 02128 { 02129 thd->binlog_setup_trx_data(); 02130 PROPAGATE_REPORTED_ERROR(thd->get_group_cache(true)->get_gtids(gs)); 02131 } 02132 RETURN_OK; 02133 } 02134 02135 public: 02136 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 02137 { 02138 return get_string_from_gtid_set(thd, get_groups_from_trx_cache); 02139 } 02140 }; 02141 02142 02146 class Sys_var_gtid_purged : public sys_var 02147 { 02148 public: 02149 Sys_var_gtid_purged(const char *name_arg, 02150 const char *comment, int flag_args, ptrdiff_t off, size_t size, 02151 CMD_LINE getopt, 02152 const char *def_val, 02153 PolyLock *lock= 0, 02154 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 02155 on_check_function on_check_func=0, 02156 on_update_function on_update_func=0, 02157 const char *substitute=0, 02158 int parse_flag= PARSE_NORMAL) 02159 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 02160 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 02161 lock, binlog_status_arg, on_check_func, on_update_func, 02162 substitute, parse_flag) 02163 {} 02164 02165 bool session_update(THD *thd, set_var *var) 02166 { 02167 DBUG_ASSERT(FALSE); 02168 return true; 02169 } 02170 02171 void session_save_default(THD *thd, set_var *var) 02172 { DBUG_ASSERT(FALSE); } 02173 02174 bool global_update(THD *thd, set_var *var) 02175 { 02176 DBUG_ENTER("Sys_var_gtid_purged::global_update"); 02177 #ifdef HAVE_REPLICATION 02178 bool error= false; 02179 int rotate_res= 0; 02180 02181 global_sid_lock->wrlock(); 02182 char *previous_gtid_logged= gtid_state->get_logged_gtids()->to_string(); 02183 char *previous_gtid_lost= gtid_state->get_lost_gtids()->to_string(); 02184 enum_return_status ret= gtid_state->add_lost_gtids(var->save_result.string_value.str); 02185 char *current_gtid_logged= gtid_state->get_logged_gtids()->to_string(); 02186 char *current_gtid_lost= gtid_state->get_lost_gtids()->to_string(); 02187 global_sid_lock->unlock(); 02188 if (RETURN_STATUS_OK != ret) 02189 { 02190 error= true; 02191 goto end; 02192 } 02193 02194 // Log messages saying that GTID_PURGED and GTID_EXECUTED were changed. 02195 sql_print_information(ER(ER_GTID_PURGED_WAS_CHANGED), 02196 previous_gtid_lost, current_gtid_lost); 02197 sql_print_information(ER(ER_GTID_EXECUTED_WAS_CHANGED), 02198 previous_gtid_logged, current_gtid_logged); 02199 02200 // Rotate logs to have Previous_gtid_event on last binlog. 02201 rotate_res= mysql_bin_log.rotate_and_purge(thd, true); 02202 if (rotate_res) 02203 { 02204 error= true; 02205 goto end; 02206 } 02207 02208 end: 02209 my_free(previous_gtid_logged); 02210 my_free(previous_gtid_lost); 02211 my_free(current_gtid_logged); 02212 my_free(current_gtid_lost); 02213 DBUG_RETURN(error); 02214 #else 02215 DBUG_RETURN(true); 02216 #endif /* HAVE_REPLICATION */ 02217 } 02218 02219 void global_save_default(THD *thd, set_var *var) 02220 { 02221 /* gtid_purged does not have default value */ 02222 my_error(ER_NO_DEFAULT, MYF(0), var->var->name.str); 02223 } 02224 02225 bool do_check(THD *thd, set_var *var) 02226 { 02227 DBUG_ENTER("Sys_var_gtid_purged::do_check"); 02228 char buf[1024]; 02229 String str(buf, sizeof(buf), system_charset_info); 02230 String *res= var->value->val_str(&str); 02231 if (!res) 02232 DBUG_RETURN(true); 02233 var->save_result.string_value.str= thd->strmake(res->c_ptr_safe(), 02234 res->length()); 02235 if (!var->save_result.string_value.str) 02236 { 02237 my_error(ER_OUT_OF_RESOURCES, MYF(0)); // thd->strmake failed 02238 DBUG_RETURN(true); 02239 } 02240 var->save_result.string_value.length= res->length(); 02241 bool ret= Gtid_set::is_valid(res->c_ptr_safe()) ? false : true; 02242 DBUG_PRINT("info", ("ret=%d", ret)); 02243 DBUG_RETURN(ret); 02244 } 02245 02246 bool check_update_type(Item_result type) 02247 { return type != STRING_RESULT; } 02248 02249 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 02250 { 02251 DBUG_ENTER("Sys_var_gtid_purged::global_value_ptr"); 02252 global_sid_lock->wrlock(); 02253 const Gtid_set *gs= gtid_state->get_lost_gtids(); 02254 char *buf= (char *)thd->alloc(gs->get_string_length() + 1); 02255 if (buf == NULL) 02256 my_error(ER_OUT_OF_RESOURCES, MYF(0)); 02257 else 02258 gs->to_string(buf); 02259 global_sid_lock->unlock(); 02260 DBUG_RETURN((uchar *)buf); 02261 } 02262 02263 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 02264 { DBUG_ASSERT(0); return NULL; } 02265 }; 02266 02267 02268 class Sys_var_gtid_owned : Sys_var_gtid_set_func 02269 { 02270 public: 02271 Sys_var_gtid_owned(const char *name_arg, const char *comment_arg) 02272 : Sys_var_gtid_set_func(name_arg, comment_arg, SESSION) {} 02273 02274 public: 02275 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 02276 { 02277 DBUG_ENTER("Sys_var_gtid_owned::session_value_ptr"); 02278 char *buf= NULL; 02279 if (thd->owned_gtid.sidno == 0) 02280 DBUG_RETURN((uchar *)thd->strdup("")); 02281 if (thd->owned_gtid.sidno == -1) 02282 { 02283 #ifdef HAVE_GTID_NEXT_LIST 02284 buf= (char *)thd->alloc(thd->owned_gtid_set.get_string_length() + 1); 02285 if (buf) 02286 { 02287 global_sid_lock->rdlock(); 02288 thd->owned_gtid_set.to_string(buf); 02289 global_sid_lock->unlock(); 02290 } 02291 else 02292 my_error(ER_OUT_OF_RESOURCES, MYF(0)); 02293 #else 02294 DBUG_ASSERT(0); 02295 #endif 02296 } 02297 else 02298 { 02299 buf= (char *)thd->alloc(Gtid::MAX_TEXT_LENGTH + 1); 02300 if (buf) 02301 { 02302 global_sid_lock->rdlock(); 02303 thd->owned_gtid.to_string(global_sid_map, buf); 02304 global_sid_lock->unlock(); 02305 } 02306 else 02307 my_error(ER_OUT_OF_RESOURCES, MYF(0)); 02308 } 02309 DBUG_RETURN((uchar *)buf); 02310 } 02311 02312 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 02313 { 02314 DBUG_ENTER("Sys_var_gtid_owned::global_value_ptr"); 02315 const Owned_gtids *owned_gtids= gtid_state->get_owned_gtids(); 02316 global_sid_lock->wrlock(); 02317 char *buf= (char *)thd->alloc(owned_gtids->get_max_string_length()); 02318 if (buf) 02319 owned_gtids->to_string(buf); 02320 else 02321 my_error(ER_OUT_OF_RESOURCES, MYF(0)); // thd->alloc faile 02322 global_sid_lock->unlock(); 02323 DBUG_RETURN((uchar *)buf); 02324 } 02325 };