1 /* Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License, version 2.0, 5 as published by the Free Software Foundation. 6 7 This program is also distributed with certain software (including 8 but not limited to OpenSSL) that is licensed under separate terms, 9 as designated in a particular file or component or in included license 10 documentation. The authors of MySQL hereby grant you an additional 11 permission to link the program and your derivative works with the 12 separately licensed software that they have included with MySQL. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License, version 2.0, for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 22 23 /** 24 @file 25 "private" interface to sys_var - server configuration variables. 26 27 This header is included only by the file that contains declarations 28 of sys_var variables (sys_vars.cc). 29 */ 30 31 #include "sys_vars_shared.h" 32 #include <my_getopt.h> 33 #include <my_bit.h> 34 #include <my_dir.h> 35 #include "keycaches.h" 36 #include "strfunc.h" 37 #include "tztime.h" // my_tz_find, my_tz_SYSTEM, struct Time_zone 38 #include "rpl_gtid.h" 39 #include <ctype.h> 40 41 /* 42 a set of mostly trivial (as in f(X)=X) defines below to make system variable 43 declarations more readable 44 */ 45 #define VALID_RANGE(X,Y) X,Y 46 #define DEFAULT(X) X 47 #define BLOCK_SIZE(X) X 48 #define GLOBAL_VAR(X) sys_var::GLOBAL, (((char*)&(X))-(char*)&global_system_variables), sizeof(X) 49 #define SESSION_VAR(X) sys_var::SESSION, offsetof(SV, X), sizeof(((SV *)0)->X) 50 #define SESSION_ONLY(X) sys_var::ONLY_SESSION, offsetof(SV, X), sizeof(((SV *)0)->X) 51 #define NO_CMD_LINE CMD_LINE(NO_ARG, -1) 52 /* 53 the define below means that there's no *second* mutex guard, 54 LOCK_global_system_variables always guards all system variables 55 */ 56 #define NO_MUTEX_GUARD ((PolyLock*)0) 57 #define IN_BINLOG sys_var::SESSION_VARIABLE_IN_BINLOG 58 #define NOT_IN_BINLOG sys_var::VARIABLE_NOT_IN_BINLOG 59 #define ON_READ(X) X 60 #define ON_CHECK(X) X 61 #define ON_UPDATE(X) X 62 #define READ_ONLY sys_var::READONLY+ 63 #define NOT_VISIBLE sys_var::INVISIBLE+ 64 // this means that Sys_var_charptr initial value was malloc()ed 65 #define PREALLOCATED sys_var::ALLOCATED+ 66 /* 67 Sys_var_bit meaning is reversed, like in 68 @@foreign_key_checks <-> OPTION_NO_FOREIGN_KEY_CHECKS 69 */ 70 #define REVERSE(X) ~(X) 71 #define DEPRECATED(X) X 72 73 #define session_var(THD, TYPE) (*(TYPE*)session_var_ptr(THD)) 74 #define global_var(TYPE) (*(TYPE*)global_var_ptr()) 75 76 #if SIZEOF_OFF_T > 4 && defined(BIG_TABLES) 77 #define GET_HA_ROWS GET_ULL 78 #else 79 #define GET_HA_ROWS GET_ULONG 80 #endif 81 82 enum charset_enum {IN_SYSTEM_CHARSET, IN_FS_CHARSET}; 83 84 static const char *bool_values[3]= {"OFF", "ON", 0}; 85 86 /** 87 A small wrapper class to pass getopt arguments as a pair 88 to the Sys_var_* constructors. It improves type safety and helps 89 to catch errors in the argument order. 90 */ 91 struct CMD_LINE 92 { 93 int id; 94 enum get_opt_arg_type arg_type; 95 CMD_LINE(enum get_opt_arg_type getopt_arg_type, int getopt_id=0) idCMD_LINE96 : id(getopt_id), arg_type(getopt_arg_type) {} 97 }; 98 99 /** 100 Sys_var_integer template is used to generate Sys_var_* classes 101 for variables that represent the value as a signed or unsigned integer. 102 They are Sys_var_uint, Sys_var_ulong, Sys_var_harows, Sys_var_ulonglong, 103 and Sys_var_long. 104 105 An integer variable has a minimal and maximal values, and a "block_size" 106 (any valid value of the variable must be divisible by the block_size). 107 108 Class specific constructor arguments: min, max, block_size 109 Backing store: uint, ulong, ha_rows, ulonglong, long, depending on the 110 Sys_var_* 111 */ 112 template 113 <typename T, ulong ARGT, enum enum_mysql_show_type SHOWT, bool SIGNED> 114 class Sys_var_integer: public sys_var 115 { 116 public: 117 Sys_var_integer(const char *name_arg, 118 const char *comment, int flag_args, ptrdiff_t off, size_t size, 119 CMD_LINE getopt, 120 T min_val, T max_val, T def_val, uint block_size, PolyLock *lock=0, 121 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 122 on_check_function on_check_func=0, 123 on_update_function on_update_func=0, 124 const char *substitute=0, 125 int parse_flag= PARSE_NORMAL) 126 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 127 getopt.arg_type, SHOWT, def_val, lock, binlog_status_arg, 128 on_check_func, on_update_func, 129 substitute, parse_flag) 130 { 131 option.var_type= ARGT; 132 option.min_value= min_val; 133 option.max_value= max_val; 134 option.block_size= block_size; 135 option.u_max_value= (uchar**)max_var_ptr(); 136 if (max_var_ptr()) 137 *max_var_ptr()= max_val; 138 139 // Do not set global_var for Sys_var_keycache objects 140 if (offset >= 0) 141 global_var(T)= def_val; 142 143 DBUG_ASSERT(size == sizeof(T)); 144 DBUG_ASSERT(min_val < max_val); 145 DBUG_ASSERT(min_val <= def_val); 146 DBUG_ASSERT(max_val >= def_val); 147 DBUG_ASSERT(block_size > 0); 148 DBUG_ASSERT(def_val % block_size == 0); 149 } 150 bool do_check(THD *thd, set_var *var) 151 { 152 my_bool fixed= FALSE; 153 longlong v; 154 ulonglong uv; 155 156 v= var->value->val_int(); 157 if (SIGNED) /* target variable has signed type */ 158 { 159 if (var->value->unsigned_flag) 160 { 161 /* 162 Input value is such a large positive number that MySQL used an 163 unsigned item to hold it. When cast to a signed longlong, if the 164 result is negative there is "cycling" and this is incorrect (large 165 positive input value should not end up as a large negative value in 166 the session signed variable to be set); instead, we need to pick the 167 allowed number closest to the positive input value, i.e. pick the 168 biggest allowed positive integer. 169 */ 170 if (v < 0) 171 uv= max_of_int_range(ARGT); 172 else /* no cycling, longlong can hold true value */ 173 uv= (ulonglong) v; 174 } 175 else 176 uv= v; 177 /* This will further restrict with VALID_RANGE, BLOCK_SIZE */ 178 var->save_result.ulonglong_value= 179 getopt_ll_limit_value(uv, &option, &fixed); 180 } 181 else 182 { 183 if (var->value->unsigned_flag) 184 { 185 /* Guaranteed positive input value, ulonglong can hold it */ 186 uv= (ulonglong) v; 187 } 188 else 189 { 190 /* 191 Maybe negative input value; in this case, cast to ulonglong makes it 192 positive, which is wrong. Pick the closest allowed value i.e. 0. 193 */ 194 uv= (ulonglong) (v < 0 ? 0 : v); 195 } 196 var->save_result.ulonglong_value= 197 getopt_ull_limit_value(uv, &option, &fixed); 198 } 199 200 if (max_var_ptr()) 201 { 202 /* check constraint set with --maximum-...=X */ 203 if (SIGNED) 204 { 205 longlong max_val= *max_var_ptr(); 206 if (((longlong)(var->save_result.ulonglong_value)) > max_val) 207 var->save_result.ulonglong_value= max_val; 208 /* 209 Signed variable probably has some kind of symmetry. Then it's good 210 to limit negative values just as we limit positive values. 211 */ 212 max_val= -max_val; 213 if (((longlong)(var->save_result.ulonglong_value)) < max_val) 214 var->save_result.ulonglong_value= max_val; 215 } 216 else 217 { 218 ulonglong max_val= *max_var_ptr(); 219 if (var->save_result.ulonglong_value > max_val) 220 var->save_result.ulonglong_value= max_val; 221 } 222 } 223 224 return throw_bounds_warning(thd, name.str, 225 var->save_result.ulonglong_value != 226 (ulonglong)v, 227 var->value->unsigned_flag, v); 228 } 229 bool session_update(THD *thd, set_var *var) 230 { 231 session_var(thd, T)= var->save_result.ulonglong_value; 232 return false; 233 } 234 bool global_update(THD *thd, set_var *var) 235 { 236 global_var(T)= var->save_result.ulonglong_value; 237 return false; 238 } 239 bool check_update_type(Item_result type) 240 { return type != INT_RESULT; } 241 void session_save_default(THD *thd, set_var *var) 242 { var->save_result.ulonglong_value= (ulonglong)*(T*)global_value_ptr(thd, 0); } 243 void global_save_default(THD *thd, set_var *var) 244 { var->save_result.ulonglong_value= option.def_value; } 245 private: 246 T *max_var_ptr() 247 { 248 return scope() == SESSION ? (T*)(((uchar*)&max_system_variables) + offset) 249 : 0; 250 } 251 }; 252 253 typedef Sys_var_integer<int32, GET_UINT, SHOW_INT, FALSE> Sys_var_int32; 254 typedef Sys_var_integer<uint, GET_UINT, SHOW_INT, FALSE> Sys_var_uint; 255 typedef Sys_var_integer<ulong, GET_ULONG, SHOW_LONG, FALSE> Sys_var_ulong; 256 typedef Sys_var_integer<ha_rows, GET_HA_ROWS, SHOW_HA_ROWS, FALSE> 257 Sys_var_harows; 258 typedef Sys_var_integer<ulonglong, GET_ULL, SHOW_LONGLONG, FALSE> 259 Sys_var_ulonglong; 260 typedef Sys_var_integer<long, GET_LONG, SHOW_SIGNED_LONG, TRUE> Sys_var_long; 261 262 /** 263 Helper class for variables that take values from a TYPELIB 264 */ 265 class Sys_var_typelib: public sys_var 266 { 267 protected: 268 TYPELIB typelib; 269 public: 270 Sys_var_typelib(const char *name_arg, 271 const char *comment, int flag_args, ptrdiff_t off, 272 CMD_LINE getopt, 273 SHOW_TYPE show_val_type_arg, const char *values[], 274 ulonglong def_val, PolyLock *lock, 275 enum binlog_status_enum binlog_status_arg, 276 on_check_function on_check_func, on_update_function on_update_func, 277 const char *substitute, int parse_flag= PARSE_NORMAL) 278 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 279 getopt.arg_type, show_val_type_arg, def_val, lock, 280 binlog_status_arg, on_check_func, 281 on_update_func, substitute, parse_flag) 282 { 283 for (typelib.count= 0; values[typelib.count]; typelib.count++) /*no-op */; 284 typelib.name=""; 285 typelib.type_names= values; 286 typelib.type_lengths= 0; // only used by Fields_enum and Field_set 287 option.typelib= &typelib; 288 } do_check(THD * thd,set_var * var)289 bool do_check(THD *thd, set_var *var) // works for enums and my_bool 290 { 291 char buff[STRING_BUFFER_USUAL_SIZE]; 292 String str(buff, sizeof(buff), system_charset_info), *res; 293 294 if (var->value->result_type() == STRING_RESULT) 295 { 296 if (!(res=var->value->val_str(&str))) 297 return true; 298 else 299 if (!(var->save_result.ulonglong_value= 300 find_type(&typelib, res->ptr(), res->length(), false))) 301 return true; 302 else 303 var->save_result.ulonglong_value--; 304 } 305 else 306 { 307 longlong tmp=var->value->val_int(); 308 if (tmp < 0 || tmp >= typelib.count) 309 return true; 310 else 311 var->save_result.ulonglong_value= tmp; 312 } 313 314 return false; 315 } check_update_type(Item_result type)316 bool check_update_type(Item_result type) 317 { return type != INT_RESULT && type != STRING_RESULT; } 318 }; 319 320 /** 321 The class for ENUM variables - variables that take one value from a fixed 322 list of values. 323 324 Class specific constructor arguments: 325 char* values[] - 0-terminated list of strings of valid values 326 327 Backing store: uint 328 329 @note 330 Do *not* use "enum FOO" variables as a backing store, there is no 331 guarantee that sizeof(enum FOO) == sizeof(uint), there is no guarantee 332 even that sizeof(enum FOO) == sizeof(enum BAR) 333 */ 334 class Sys_var_enum: public Sys_var_typelib 335 { 336 public: 337 Sys_var_enum(const char *name_arg, 338 const char *comment, int flag_args, ptrdiff_t off, size_t size, 339 CMD_LINE getopt, 340 const char *values[], uint def_val, PolyLock *lock=0, 341 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 342 on_check_function on_check_func=0, 343 on_update_function on_update_func=0, 344 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,substitute)345 : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, 346 SHOW_CHAR, values, def_val, lock, 347 binlog_status_arg, on_check_func, on_update_func, 348 substitute) 349 { 350 option.var_type= GET_ENUM; 351 global_var(ulong)= def_val; 352 DBUG_ASSERT(def_val < typelib.count); 353 DBUG_ASSERT(size == sizeof(ulong)); 354 } session_update(THD * thd,set_var * var)355 bool session_update(THD *thd, set_var *var) 356 { 357 session_var(thd, ulong)= var->save_result.ulonglong_value; 358 return false; 359 } global_update(THD * thd,set_var * var)360 bool global_update(THD *thd, set_var *var) 361 { 362 global_var(ulong)= var->save_result.ulonglong_value; 363 return false; 364 } session_save_default(THD * thd,set_var * var)365 void session_save_default(THD *thd, set_var *var) 366 { var->save_result.ulonglong_value= global_var(ulong); } global_save_default(THD * thd,set_var * var)367 void global_save_default(THD *thd, set_var *var) 368 { var->save_result.ulonglong_value= option.def_value; } session_value_ptr(THD * thd,LEX_STRING * base)369 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 370 { return (uchar*)typelib.type_names[session_var(thd, ulong)]; } global_value_ptr(THD * thd,LEX_STRING * base)371 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 372 { return (uchar*)typelib.type_names[global_var(ulong)]; } 373 }; 374 375 /** 376 The class for boolean variables - a variant of ENUM variables 377 with the fixed list of values of { OFF , ON } 378 379 Backing store: my_bool 380 */ 381 class Sys_var_mybool: public Sys_var_typelib 382 { 383 public: 384 Sys_var_mybool(const char *name_arg, 385 const char *comment, int flag_args, ptrdiff_t off, size_t size, 386 CMD_LINE getopt, 387 my_bool def_val, PolyLock *lock=0, 388 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 389 on_check_function on_check_func=0, 390 on_update_function on_update_func=0, 391 const char *substitute=0, 392 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,substitute,parse_flag)393 : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, 394 SHOW_MY_BOOL, bool_values, def_val, lock, 395 binlog_status_arg, on_check_func, on_update_func, 396 substitute, parse_flag) 397 { 398 option.var_type= GET_BOOL; 399 global_var(my_bool)= def_val; 400 DBUG_ASSERT(def_val < 2); 401 DBUG_ASSERT(getopt.arg_type == OPT_ARG || getopt.id == -1); 402 DBUG_ASSERT(size == sizeof(my_bool)); 403 } session_update(THD * thd,set_var * var)404 bool session_update(THD *thd, set_var *var) 405 { 406 session_var(thd, my_bool)= var->save_result.ulonglong_value; 407 return false; 408 } global_update(THD * thd,set_var * var)409 bool global_update(THD *thd, set_var *var) 410 { 411 global_var(my_bool)= var->save_result.ulonglong_value; 412 return false; 413 } session_save_default(THD * thd,set_var * var)414 void session_save_default(THD *thd, set_var *var) 415 { var->save_result.ulonglong_value= (ulonglong)*(my_bool *)global_value_ptr(thd, 0); } global_save_default(THD * thd,set_var * var)416 void global_save_default(THD *thd, set_var *var) 417 { var->save_result.ulonglong_value= option.def_value; } 418 }; 419 420 /** 421 The class for string variables. The string can be in character_set_filesystem 422 or in character_set_system. The string can be allocated with my_malloc() 423 or not. The state of the initial value is specified in the constructor, 424 after that it's managed automatically. The value of NULL is supported. 425 426 Class specific constructor arguments: 427 enum charset_enum is_os_charset_arg 428 429 Backing store: char* 430 431 @note 432 This class supports only GLOBAL variables, because THD on destruction 433 does not destroy individual members of SV, there's no way to free 434 allocated string variables for every thread. 435 */ 436 class Sys_var_charptr: public sys_var 437 { 438 public: 439 Sys_var_charptr(const char *name_arg, 440 const char *comment, int flag_args, ptrdiff_t off, size_t size, 441 CMD_LINE getopt, 442 enum charset_enum is_os_charset_arg, 443 const char *def_val, PolyLock *lock=0, 444 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 445 on_check_function on_check_func=0, 446 on_update_function on_update_func=0, 447 const char *substitute=0, 448 int parse_flag= PARSE_NORMAL) 449 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 450 getopt.arg_type, SHOW_CHAR_PTR, (intptr)def_val, 451 lock, binlog_status_arg, on_check_func, on_update_func, 452 substitute, parse_flag) 453 { 454 is_os_charset= is_os_charset_arg == IN_FS_CHARSET; 455 /* 456 use GET_STR_ALLOC - if ALLOCATED it must be *always* allocated, 457 otherwise (GET_STR) you'll never know whether to free it or not. 458 (think of an exit because of an error right after my_getopt) 459 */ 460 option.var_type= (flags & ALLOCATED) ? GET_STR_ALLOC : GET_STR; 461 global_var(const char*)= def_val; 462 DBUG_ASSERT(scope() == GLOBAL); 463 DBUG_ASSERT(size == sizeof(char *)); 464 } cleanup()465 void cleanup() 466 { 467 if (flags & ALLOCATED) 468 my_free(global_var(char*)); 469 flags&= ~ALLOCATED; 470 } do_check(THD * thd,set_var * var)471 bool do_check(THD *thd, set_var *var) 472 { 473 char buff[STRING_BUFFER_USUAL_SIZE], buff2[STRING_BUFFER_USUAL_SIZE]; 474 String str(buff, sizeof(buff), charset(thd)); 475 String str2(buff2, sizeof(buff2), charset(thd)), *res; 476 477 if (!(res=var->value->val_str(&str))) 478 var->save_result.string_value.str= 0; 479 else 480 { 481 uint32 unused; 482 if (String::needs_conversion(res->length(), res->charset(), 483 charset(thd), &unused)) 484 { 485 uint errors; 486 str2.copy(res->ptr(), res->length(), res->charset(), charset(thd), 487 &errors); 488 res=&str2; 489 490 } 491 var->save_result.string_value.str= thd->strmake(res->ptr(), res->length()); 492 var->save_result.string_value.length= res->length(); 493 } 494 495 return false; 496 } session_update(THD * thd,set_var * var)497 bool session_update(THD *thd, set_var *var) 498 { 499 DBUG_ASSERT(FALSE); 500 return true; 501 } global_update(THD * thd,set_var * var)502 bool global_update(THD *thd, set_var *var) 503 { 504 char *new_val, *ptr= var->save_result.string_value.str; 505 size_t len=var->save_result.string_value.length; 506 if (ptr) 507 { 508 new_val= (char*)my_memdup(ptr, len+1, MYF(MY_WME)); 509 if (!new_val) return true; 510 new_val[len]=0; 511 } 512 else 513 new_val= 0; 514 if (flags & ALLOCATED) 515 my_free(global_var(char*)); 516 flags|= ALLOCATED; 517 global_var(char*)= new_val; 518 return false; 519 } session_save_default(THD * thd,set_var * var)520 void session_save_default(THD *thd, set_var *var) 521 { DBUG_ASSERT(FALSE); } global_save_default(THD * thd,set_var * var)522 void global_save_default(THD *thd, set_var *var) 523 { 524 char *ptr= (char*)(intptr)option.def_value; 525 var->save_result.string_value.str= ptr; 526 var->save_result.string_value.length= ptr ? strlen(ptr) : 0; 527 } check_update_type(Item_result type)528 bool check_update_type(Item_result type) 529 { return type != STRING_RESULT; } 530 }; 531 532 533 class Sys_var_proxy_user: public sys_var 534 { 535 public: Sys_var_proxy_user(const char * name_arg,const char * comment,enum charset_enum is_os_charset_arg)536 Sys_var_proxy_user(const char *name_arg, 537 const char *comment, enum charset_enum is_os_charset_arg) 538 : sys_var(&all_sys_vars, name_arg, comment, 539 sys_var::READONLY+sys_var::ONLY_SESSION, 0, -1, 540 NO_ARG, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, 541 NULL, NULL, NULL, PARSE_NORMAL) 542 { 543 is_os_charset= is_os_charset_arg == IN_FS_CHARSET; 544 option.var_type= GET_STR; 545 } do_check(THD * thd,set_var * var)546 bool do_check(THD *thd, set_var *var) 547 { 548 DBUG_ASSERT(FALSE); 549 return true; 550 } session_update(THD * thd,set_var * var)551 bool session_update(THD *thd, set_var *var) 552 { 553 DBUG_ASSERT(FALSE); 554 return true; 555 } global_update(THD * thd,set_var * var)556 bool global_update(THD *thd, set_var *var) 557 { 558 DBUG_ASSERT(FALSE); 559 return false; 560 } session_save_default(THD * thd,set_var * var)561 void session_save_default(THD *thd, set_var *var) 562 { DBUG_ASSERT(FALSE); } global_save_default(THD * thd,set_var * var)563 void global_save_default(THD *thd, set_var *var) 564 { DBUG_ASSERT(FALSE); } check_update_type(Item_result type)565 bool check_update_type(Item_result type) 566 { return true; } 567 protected: session_value_ptr(THD * thd,LEX_STRING * base)568 virtual uchar *session_value_ptr(THD *thd, LEX_STRING *base) 569 { 570 return thd->security_ctx->proxy_user[0] ? 571 (uchar *) &(thd->security_ctx->proxy_user[0]) : NULL; 572 } 573 }; 574 575 class Sys_var_external_user : public Sys_var_proxy_user 576 { 577 public: Sys_var_external_user(const char * name_arg,const char * comment_arg,enum charset_enum is_os_charset_arg)578 Sys_var_external_user(const char *name_arg, const char *comment_arg, 579 enum charset_enum is_os_charset_arg) 580 : Sys_var_proxy_user (name_arg, comment_arg, is_os_charset_arg) 581 {} 582 583 protected: session_value_ptr(THD * thd,LEX_STRING * base)584 virtual uchar *session_value_ptr(THD *thd, LEX_STRING *base) 585 { 586 return thd->security_ctx->proxy_user[0] ? 587 (uchar *) &(thd->security_ctx->proxy_user[0]) : NULL; 588 } 589 }; 590 591 /** 592 The class for string variables. Useful for strings that aren't necessarily 593 \0-terminated. Otherwise the same as Sys_var_charptr. 594 595 Class specific constructor arguments: 596 enum charset_enum is_os_charset_arg 597 598 Backing store: LEX_STRING 599 600 @note 601 Behaves exactly as Sys_var_charptr, only the backing store is different. 602 */ 603 class Sys_var_lexstring: public Sys_var_charptr 604 { 605 public: 606 Sys_var_lexstring(const char *name_arg, 607 const char *comment, int flag_args, ptrdiff_t off, size_t size, 608 CMD_LINE getopt, 609 enum charset_enum is_os_charset_arg, 610 const char *def_val, PolyLock *lock=0, 611 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 612 on_check_function on_check_func=0, 613 on_update_function on_update_func=0, 614 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,substitute)615 : Sys_var_charptr(name_arg, comment, flag_args, off, sizeof(char*), 616 getopt, is_os_charset_arg, def_val, lock, binlog_status_arg, 617 on_check_func, on_update_func, substitute) 618 { 619 global_var(LEX_STRING).length= strlen(def_val); 620 DBUG_ASSERT(size == sizeof(LEX_STRING)); 621 *const_cast<SHOW_TYPE*>(&show_val_type)= SHOW_LEX_STRING; 622 } global_update(THD * thd,set_var * var)623 bool global_update(THD *thd, set_var *var) 624 { 625 if (Sys_var_charptr::global_update(thd, var)) 626 return true; 627 global_var(LEX_STRING).length= var->save_result.string_value.length; 628 return false; 629 } 630 }; 631 632 #ifndef DBUG_OFF 633 /** 634 @@session.dbug and @@global.dbug variables. 635 636 @@dbug variable differs from other variables in one aspect: 637 if its value is not assigned in the session, it "points" to the global 638 value, and so when the global value is changed, the change 639 immediately takes effect in the session. 640 641 This semantics is intentional, to be able to debug one session from 642 another. 643 */ 644 class Sys_var_dbug: public sys_var 645 { 646 public: 647 Sys_var_dbug(const char *name_arg, 648 const char *comment, int flag_args, 649 CMD_LINE getopt, 650 const char *def_val, PolyLock *lock=0, 651 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 652 on_check_function on_check_func=0, 653 on_update_function on_update_func=0, 654 const char *substitute=0, 655 int parse_flag= PARSE_NORMAL) 656 : sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id, 657 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 658 lock, binlog_status_arg, on_check_func, on_update_func, 659 substitute, parse_flag) 660 { option.var_type= GET_NO_ARG; } do_check(THD * thd,set_var * var)661 bool do_check(THD *thd, set_var *var) 662 { 663 char buff[STRING_BUFFER_USUAL_SIZE]; 664 String str(buff, sizeof(buff), system_charset_info), *res; 665 666 if (!(res=var->value->val_str(&str))) 667 var->save_result.string_value.str= const_cast<char*>(""); 668 else 669 var->save_result.string_value.str= thd->strmake(res->ptr(), res->length()); 670 return false; 671 } session_update(THD * thd,set_var * var)672 bool session_update(THD *thd, set_var *var) 673 { 674 const char *val= var->save_result.string_value.str; 675 if (!var->value) 676 DBUG_POP(); 677 else 678 DBUG_SET(val); 679 return false; 680 } global_update(THD * thd,set_var * var)681 bool global_update(THD *thd, set_var *var) 682 { 683 const char *val= var->save_result.string_value.str; 684 DBUG_SET_INITIAL(val); 685 return false; 686 } session_save_default(THD * thd,set_var * var)687 void session_save_default(THD *thd, set_var *var) 688 { } global_save_default(THD * thd,set_var * var)689 void global_save_default(THD *thd, set_var *var) 690 { 691 char *ptr= (char*)(intptr)option.def_value; 692 var->save_result.string_value.str= ptr; 693 } session_value_ptr(THD * thd,LEX_STRING * base)694 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 695 { 696 char buf[256]; 697 DBUG_EXPLAIN(buf, sizeof(buf)); 698 return (uchar*) thd->strdup(buf); 699 } global_value_ptr(THD * thd,LEX_STRING * base)700 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 701 { 702 char buf[256]; 703 DBUG_EXPLAIN_INITIAL(buf, sizeof(buf)); 704 return (uchar*) thd->strdup(buf); 705 } check_update_type(Item_result type)706 bool check_update_type(Item_result type) 707 { return type != STRING_RESULT; } 708 }; 709 #endif 710 711 #define KEYCACHE_VAR(X) sys_var::GLOBAL,offsetof(KEY_CACHE, X), sizeof(((KEY_CACHE *)0)->X) 712 #define keycache_var_ptr(KC, OFF) (((uchar*)(KC))+(OFF)) 713 #define keycache_var(KC, OFF) (*(ulonglong*)keycache_var_ptr(KC, OFF)) 714 typedef bool (*keycache_update_function)(THD *, KEY_CACHE *, ptrdiff_t, ulonglong); 715 716 /** 717 The class for keycache_* variables. Supports structured names, 718 keycache_name.variable_name. 719 720 Class specific constructor arguments: 721 everything derived from Sys_var_ulonglong 722 723 Backing store: ulonglong 724 725 @note these variables can be only GLOBAL 726 */ 727 class Sys_var_keycache: public Sys_var_ulonglong 728 { 729 keycache_update_function keycache_update; 730 public: 731 Sys_var_keycache(const char *name_arg, 732 const char *comment, int flag_args, ptrdiff_t off, size_t size, 733 CMD_LINE getopt, 734 ulonglong min_val, ulonglong max_val, ulonglong def_val, 735 ulonglong block_size, PolyLock *lock, 736 enum binlog_status_enum binlog_status_arg, 737 on_check_function on_check_func, 738 keycache_update_function on_update_func, 739 const char *substitute=0) 740 : Sys_var_ulonglong(name_arg, comment, flag_args, 741 -1, /* offset, see base class CTOR */ 742 size, 743 getopt, min_val, max_val, def_val, 744 block_size, lock, binlog_status_arg, on_check_func, 0, 745 substitute), 746 keycache_update(on_update_func) 747 { 748 offset= off; /* Remember offset in KEY_CACHE */ 749 option.var_type|= GET_ASK_ADDR; 750 option.value= (uchar**)1; // crash me, please 751 keycache_var(dflt_key_cache, off)= def_val; 752 DBUG_ASSERT(scope() == GLOBAL); 753 } global_update(THD * thd,set_var * var)754 bool global_update(THD *thd, set_var *var) 755 { 756 ulonglong new_value= var->save_result.ulonglong_value; 757 LEX_STRING *base_name= &var->base; 758 KEY_CACHE *key_cache; 759 760 /* If no basename, assume it's for the key cache named 'default' */ 761 if (!base_name->length) 762 base_name= &default_key_cache_base; 763 764 key_cache= get_key_cache(base_name); 765 766 if (!key_cache) 767 { // Key cache didn't exists */ 768 if (!new_value) // Tried to delete cache 769 return false; // Ok, nothing to do 770 if (!(key_cache= create_key_cache(base_name->str, base_name->length))) 771 return true; 772 } 773 774 /** 775 Abort if some other thread is changing the key cache 776 @todo This should be changed so that we wait until the previous 777 assignment is done and then do the new assign 778 */ 779 if (key_cache->in_init) 780 return true; 781 782 return keycache_update(thd, key_cache, offset, new_value); 783 } global_value_ptr(THD * thd,LEX_STRING * base)784 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 785 { 786 KEY_CACHE *key_cache= get_key_cache(base); 787 if (!key_cache) 788 key_cache= &zero_key_cache; 789 return keycache_var_ptr(key_cache, offset); 790 } 791 }; 792 793 /** 794 The class for floating point variables 795 796 Class specific constructor arguments: min, max 797 798 Backing store: double 799 */ 800 class Sys_var_double: public sys_var 801 { 802 public: 803 Sys_var_double(const char *name_arg, 804 const char *comment, int flag_args, ptrdiff_t off, size_t size, 805 CMD_LINE getopt, 806 double min_val, double max_val, double def_val, PolyLock *lock=0, 807 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 808 on_check_function on_check_func=0, 809 on_update_function on_update_func=0, 810 const char *substitute=0, 811 int parse_flag= PARSE_NORMAL) 812 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 813 getopt.arg_type, SHOW_DOUBLE, 814 (longlong) getopt_double2ulonglong(def_val), 815 lock, binlog_status_arg, on_check_func, on_update_func, 816 substitute, parse_flag) 817 { 818 option.var_type= GET_DOUBLE; 819 option.min_value= (longlong) getopt_double2ulonglong(min_val); 820 option.max_value= (longlong) getopt_double2ulonglong(max_val); 821 global_var(double)= (double)option.def_value; 822 DBUG_ASSERT(min_val <= max_val); 823 DBUG_ASSERT(min_val <= def_val); 824 DBUG_ASSERT(max_val >= def_val); 825 DBUG_ASSERT(size == sizeof(double)); 826 } do_check(THD * thd,set_var * var)827 bool do_check(THD *thd, set_var *var) 828 { 829 my_bool fixed; 830 double v= var->value->val_real(); 831 var->save_result.double_value= getopt_double_limit_value(v, &option, &fixed); 832 833 return throw_bounds_warning(thd, name.str, fixed, v); 834 } session_update(THD * thd,set_var * var)835 bool session_update(THD *thd, set_var *var) 836 { 837 session_var(thd, double)= var->save_result.double_value; 838 return false; 839 } global_update(THD * thd,set_var * var)840 bool global_update(THD *thd, set_var *var) 841 { 842 global_var(double)= var->save_result.double_value; 843 return false; 844 } check_update_type(Item_result type)845 bool check_update_type(Item_result type) 846 { 847 return type != INT_RESULT && type != REAL_RESULT && type != DECIMAL_RESULT; 848 } session_save_default(THD * thd,set_var * var)849 void session_save_default(THD *thd, set_var *var) 850 { var->save_result.double_value= global_var(double); } global_save_default(THD * thd,set_var * var)851 void global_save_default(THD *thd, set_var *var) 852 { var->save_result.double_value= getopt_ulonglong2double(option.def_value); } 853 }; 854 855 /** 856 The class for @test_flags (core_file for now). 857 It's derived from Sys_var_mybool. 858 859 Class specific constructor arguments: 860 Caller need not pass in a variable as we make up the value on the 861 fly, that is, we derive it from the global test_flags bit vector. 862 863 Backing store: my_bool 864 */ 865 class Sys_var_test_flag: public Sys_var_mybool 866 { 867 private: 868 my_bool test_flag_value; 869 uint test_flag_mask; 870 public: Sys_var_test_flag(const char * name_arg,const char * comment,uint mask)871 Sys_var_test_flag(const char *name_arg, const char *comment, uint mask) 872 : Sys_var_mybool(name_arg, comment, READ_ONLY GLOBAL_VAR(test_flag_value), 873 NO_CMD_LINE, DEFAULT(FALSE)) 874 { 875 test_flag_mask= mask; 876 } global_value_ptr(THD * thd,LEX_STRING * base)877 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 878 { 879 test_flag_value= ((test_flags & test_flag_mask) > 0); 880 return (uchar*) &test_flag_value; 881 } 882 }; 883 884 /** 885 The class for the @max_user_connections. 886 It's derived from Sys_var_uint, but non-standard session value 887 requires a new class. 888 889 Class specific constructor arguments: 890 everything derived from Sys_var_uint 891 892 Backing store: uint 893 */ 894 class Sys_var_max_user_conn: public Sys_var_uint 895 { 896 public: 897 Sys_var_max_user_conn(const char *name_arg, 898 const char *comment, int flag_args, ptrdiff_t off, size_t size, 899 CMD_LINE getopt, 900 uint min_val, uint max_val, uint def_val, 901 uint block_size, PolyLock *lock=0, 902 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 903 on_check_function on_check_func=0, 904 on_update_function on_update_func=0, 905 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,substitute)906 : Sys_var_uint(name_arg, comment, SESSION, off, size, getopt, 907 min_val, max_val, def_val, block_size, 908 lock, binlog_status_arg, on_check_func, on_update_func, 909 substitute) 910 { } session_value_ptr(THD * thd,LEX_STRING * base)911 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 912 { 913 const USER_CONN *uc= thd->get_user_connect(); 914 if (uc && uc->user_resources.user_conn) 915 return (uchar*) &(uc->user_resources.user_conn); 916 return global_value_ptr(thd, base); 917 } 918 }; 919 920 // overflow-safe (1 << X)-1 921 #define MAX_SET(X) ((((1UL << ((X)-1))-1) << 1) | 1) 922 923 /** 924 The class for flagset variables - a variant of SET that allows in-place 925 editing (turning on/off individual bits). String representations looks like 926 a "flag=val,flag=val,...". Example: @@optimizer_switch 927 928 Class specific constructor arguments: 929 char* values[] - 0-terminated list of strings of valid values 930 931 Backing store: ulonglong 932 933 @note 934 the last value in the values[] array should 935 *always* be the string "default". 936 */ 937 class Sys_var_flagset: public Sys_var_typelib 938 { 939 public: 940 Sys_var_flagset(const char *name_arg, 941 const char *comment, int flag_args, ptrdiff_t off, size_t size, 942 CMD_LINE getopt, 943 const char *values[], ulonglong def_val, PolyLock *lock=0, 944 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 945 on_check_function on_check_func=0, 946 on_update_function on_update_func=0, 947 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,substitute)948 : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, 949 SHOW_CHAR, values, def_val, lock, 950 binlog_status_arg, on_check_func, on_update_func, 951 substitute) 952 { 953 option.var_type= GET_FLAGSET; 954 global_var(ulonglong)= def_val; 955 DBUG_ASSERT(typelib.count > 1); 956 DBUG_ASSERT(typelib.count <= 65); 957 DBUG_ASSERT(def_val < MAX_SET(typelib.count)); 958 DBUG_ASSERT(strcmp(values[typelib.count-1], "default") == 0); 959 DBUG_ASSERT(size == sizeof(ulonglong)); 960 } do_check(THD * thd,set_var * var)961 bool do_check(THD *thd, set_var *var) 962 { 963 char buff[STRING_BUFFER_USUAL_SIZE]; 964 String str(buff, sizeof(buff), system_charset_info), *res; 965 ulonglong default_value, current_value; 966 if (var->type == OPT_GLOBAL) 967 { 968 default_value= option.def_value; 969 current_value= global_var(ulonglong); 970 } 971 else 972 { 973 default_value= global_var(ulonglong); 974 current_value= session_var(thd, ulonglong); 975 } 976 977 if (var->value->result_type() == STRING_RESULT) 978 { 979 if (!(res=var->value->val_str(&str))) 980 return true; 981 else 982 { 983 char *error; 984 uint error_len; 985 986 var->save_result.ulonglong_value= 987 find_set_from_flags(&typelib, 988 typelib.count, 989 current_value, 990 default_value, 991 res->ptr(), res->length(), 992 &error, &error_len); 993 if (error) 994 { 995 ErrConvString err(error, error_len, res->charset()); 996 my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr()); 997 return true; 998 } 999 } 1000 } 1001 else 1002 { 1003 longlong tmp=var->value->val_int(); 1004 if ((tmp < 0 && ! var->value->unsigned_flag) 1005 || (ulonglong)tmp > MAX_SET(typelib.count)) 1006 return true; 1007 else 1008 var->save_result.ulonglong_value= tmp; 1009 } 1010 1011 return false; 1012 } session_update(THD * thd,set_var * var)1013 bool session_update(THD *thd, set_var *var) 1014 { 1015 session_var(thd, ulonglong)= var->save_result.ulonglong_value; 1016 return false; 1017 } global_update(THD * thd,set_var * var)1018 bool global_update(THD *thd, set_var *var) 1019 { 1020 global_var(ulonglong)= var->save_result.ulonglong_value; 1021 return false; 1022 } session_save_default(THD * thd,set_var * var)1023 void session_save_default(THD *thd, set_var *var) 1024 { var->save_result.ulonglong_value= global_var(ulonglong); } global_save_default(THD * thd,set_var * var)1025 void global_save_default(THD *thd, set_var *var) 1026 { var->save_result.ulonglong_value= option.def_value; } session_value_ptr(THD * thd,LEX_STRING * base)1027 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 1028 { 1029 return (uchar*)flagset_to_string(thd, 0, session_var(thd, ulonglong), 1030 typelib.type_names); 1031 } global_value_ptr(THD * thd,LEX_STRING * base)1032 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 1033 { 1034 return (uchar*)flagset_to_string(thd, 0, global_var(ulonglong), 1035 typelib.type_names); 1036 } 1037 }; 1038 1039 /** 1040 The class for SET variables - variables taking zero or more values 1041 from the given list. Example: @@sql_mode 1042 1043 Class specific constructor arguments: 1044 char* values[] - 0-terminated list of strings of valid values 1045 1046 Backing store: ulonglong 1047 */ 1048 class Sys_var_set: public Sys_var_typelib 1049 { 1050 public: 1051 Sys_var_set(const char *name_arg, 1052 const char *comment, int flag_args, ptrdiff_t off, size_t size, 1053 CMD_LINE getopt, 1054 const char *values[], ulonglong def_val, PolyLock *lock=0, 1055 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 1056 on_check_function on_check_func=0, 1057 on_update_function on_update_func=0, 1058 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,substitute)1059 : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, 1060 SHOW_CHAR, values, def_val, lock, 1061 binlog_status_arg, on_check_func, on_update_func, 1062 substitute) 1063 { 1064 option.var_type= GET_SET; 1065 global_var(ulonglong)= def_val; 1066 DBUG_ASSERT(typelib.count > 0); 1067 DBUG_ASSERT(typelib.count <= 64); 1068 DBUG_ASSERT(def_val < MAX_SET(typelib.count)); 1069 DBUG_ASSERT(size == sizeof(ulonglong)); 1070 } do_check(THD * thd,set_var * var)1071 bool do_check(THD *thd, set_var *var) 1072 { 1073 char buff[STRING_BUFFER_USUAL_SIZE]; 1074 String str(buff, sizeof(buff), system_charset_info), *res; 1075 1076 if (var->value->result_type() == STRING_RESULT) 1077 { 1078 if (!(res=var->value->val_str(&str))) 1079 return true; 1080 else 1081 { 1082 char *error; 1083 uint error_len; 1084 bool not_used; 1085 1086 var->save_result.ulonglong_value= 1087 find_set(&typelib, res->ptr(), res->length(), NULL, 1088 &error, &error_len, ¬_used); 1089 /* 1090 note, we only issue an error if error_len > 0. 1091 That is even while empty (zero-length) values are considered 1092 errors by find_set(), these errors are ignored here 1093 */ 1094 if (error_len) 1095 { 1096 ErrConvString err(error, error_len, res->charset()); 1097 my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr()); 1098 return true; 1099 } 1100 } 1101 } 1102 else 1103 { 1104 longlong tmp=var->value->val_int(); 1105 if ((tmp < 0 && ! var->value->unsigned_flag) 1106 || (ulonglong)tmp > MAX_SET(typelib.count)) 1107 return true; 1108 else 1109 var->save_result.ulonglong_value= tmp; 1110 } 1111 1112 return false; 1113 } session_update(THD * thd,set_var * var)1114 bool session_update(THD *thd, set_var *var) 1115 { 1116 session_var(thd, ulonglong)= var->save_result.ulonglong_value; 1117 return false; 1118 } global_update(THD * thd,set_var * var)1119 bool global_update(THD *thd, set_var *var) 1120 { 1121 global_var(ulonglong)= var->save_result.ulonglong_value; 1122 return false; 1123 } session_save_default(THD * thd,set_var * var)1124 void session_save_default(THD *thd, set_var *var) 1125 { var->save_result.ulonglong_value= global_var(ulonglong); } global_save_default(THD * thd,set_var * var)1126 void global_save_default(THD *thd, set_var *var) 1127 { var->save_result.ulonglong_value= option.def_value; } session_value_ptr(THD * thd,LEX_STRING * base)1128 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 1129 { 1130 return (uchar*)set_to_string(thd, 0, session_var(thd, ulonglong), 1131 typelib.type_names); 1132 } global_value_ptr(THD * thd,LEX_STRING * base)1133 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 1134 { 1135 return (uchar*)set_to_string(thd, 0, global_var(ulonglong), 1136 typelib.type_names); 1137 } 1138 }; 1139 1140 /** 1141 The class for variables which value is a plugin. 1142 Example: @@default_storage_engine 1143 1144 Class specific constructor arguments: 1145 int plugin_type_arg (for example MYSQL_STORAGE_ENGINE_PLUGIN) 1146 1147 Backing store: plugin_ref 1148 1149 @note 1150 these variables don't support command-line equivalents, any such 1151 command-line options should be added manually to my_long_options in mysqld.cc 1152 */ 1153 class Sys_var_plugin: public sys_var 1154 { 1155 int plugin_type; 1156 public: 1157 Sys_var_plugin(const char *name_arg, 1158 const char *comment, int flag_args, ptrdiff_t off, size_t size, 1159 CMD_LINE getopt, 1160 int plugin_type_arg, char **def_val, PolyLock *lock=0, 1161 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 1162 on_check_function on_check_func=0, 1163 on_update_function on_update_func=0, 1164 const char *substitute=0, 1165 int parse_flag= PARSE_NORMAL) 1166 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 1167 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 1168 lock, binlog_status_arg, on_check_func, on_update_func, 1169 substitute, parse_flag), 1170 plugin_type(plugin_type_arg) 1171 { 1172 option.var_type= GET_STR; 1173 DBUG_ASSERT(size == sizeof(plugin_ref)); 1174 DBUG_ASSERT(getopt.id == -1); // force NO_CMD_LINE 1175 } do_check(THD * thd,set_var * var)1176 bool do_check(THD *thd, set_var *var) 1177 { 1178 char buff[STRING_BUFFER_USUAL_SIZE]; 1179 String str(buff,sizeof(buff), system_charset_info), *res; 1180 if (!(res=var->value->val_str(&str))) 1181 var->save_result.plugin= NULL; 1182 else 1183 { 1184 const LEX_STRING pname= { const_cast<char*>(res->ptr()), res->length() }; 1185 plugin_ref plugin; 1186 1187 // special code for storage engines (e.g. to handle historical aliases) 1188 if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN) 1189 plugin= ha_resolve_by_name(thd, &pname, FALSE); 1190 else 1191 plugin= my_plugin_lock_by_name(thd, &pname, plugin_type); 1192 if (!plugin) 1193 { 1194 // historically different error code 1195 if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN) 1196 { 1197 ErrConvString err(res); 1198 my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), err.ptr()); 1199 } 1200 return true; 1201 } 1202 var->save_result.plugin= plugin; 1203 } 1204 return false; 1205 } do_update(plugin_ref * valptr,plugin_ref newval)1206 void do_update(plugin_ref *valptr, plugin_ref newval) 1207 { 1208 plugin_ref oldval= *valptr; 1209 if (oldval != newval) 1210 { 1211 *valptr= my_plugin_lock(NULL, &newval); 1212 plugin_unlock(NULL, oldval); 1213 } 1214 } session_update(THD * thd,set_var * var)1215 bool session_update(THD *thd, set_var *var) 1216 { 1217 do_update((plugin_ref*)session_var_ptr(thd), 1218 var->save_result.plugin); 1219 return false; 1220 } global_update(THD * thd,set_var * var)1221 bool global_update(THD *thd, set_var *var) 1222 { 1223 do_update((plugin_ref*)global_var_ptr(), 1224 var->save_result.plugin); 1225 return false; 1226 } session_save_default(THD * thd,set_var * var)1227 void session_save_default(THD *thd, set_var *var) 1228 { 1229 plugin_ref plugin= global_var(plugin_ref); 1230 var->save_result.plugin= my_plugin_lock(thd, &plugin); 1231 } global_save_default(THD * thd,set_var * var)1232 void global_save_default(THD *thd, set_var *var) 1233 { 1234 LEX_STRING pname; 1235 char **default_value= reinterpret_cast<char**>(option.def_value); 1236 pname.str= *default_value; 1237 pname.length= strlen(pname.str); 1238 1239 plugin_ref plugin; 1240 if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN) 1241 plugin= ha_resolve_by_name(thd, &pname, FALSE); 1242 else 1243 plugin= my_plugin_lock_by_name(thd, &pname, plugin_type); 1244 DBUG_ASSERT(plugin); 1245 1246 var->save_result.plugin= my_plugin_lock(thd, &plugin); 1247 } check_update_type(Item_result type)1248 bool check_update_type(Item_result type) 1249 { return type != STRING_RESULT; } session_value_ptr(THD * thd,LEX_STRING * base)1250 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 1251 { 1252 plugin_ref plugin= session_var(thd, plugin_ref); 1253 return (uchar*)(plugin ? thd->strmake(plugin_name(plugin)->str, 1254 plugin_name(plugin)->length) : 0); 1255 } global_value_ptr(THD * thd,LEX_STRING * base)1256 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 1257 { 1258 plugin_ref plugin= global_var(plugin_ref); 1259 return (uchar*)(plugin ? thd->strmake(plugin_name(plugin)->str, 1260 plugin_name(plugin)->length) : 0); 1261 } 1262 }; 1263 1264 #if defined(ENABLED_DEBUG_SYNC) 1265 /** 1266 The class for @@debug_sync session-only variable 1267 */ 1268 class Sys_var_debug_sync :public sys_var 1269 { 1270 public: 1271 Sys_var_debug_sync(const char *name_arg, 1272 const char *comment, int flag_args, 1273 CMD_LINE getopt, 1274 const char *def_val, PolyLock *lock=0, 1275 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 1276 on_check_function on_check_func=0, 1277 on_update_function on_update_func=0, 1278 const char *substitute=0, 1279 int parse_flag= PARSE_NORMAL) 1280 : sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id, 1281 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 1282 lock, binlog_status_arg, on_check_func, on_update_func, 1283 substitute, parse_flag) 1284 { 1285 DBUG_ASSERT(scope() == ONLY_SESSION); 1286 option.var_type= GET_NO_ARG; 1287 } do_check(THD * thd,set_var * var)1288 bool do_check(THD *thd, set_var *var) 1289 { 1290 char buff[STRING_BUFFER_USUAL_SIZE]; 1291 String str(buff, sizeof(buff), system_charset_info), *res; 1292 1293 if (!(res=var->value->val_str(&str))) 1294 var->save_result.string_value.str= const_cast<char*>(""); 1295 else 1296 var->save_result.string_value.str= thd->strmake(res->ptr(), res->length()); 1297 return false; 1298 } session_update(THD * thd,set_var * var)1299 bool session_update(THD *thd, set_var *var) 1300 { 1301 extern bool debug_sync_update(THD *thd, char *val_str); 1302 return debug_sync_update(thd, var->save_result.string_value.str); 1303 } global_update(THD * thd,set_var * var)1304 bool global_update(THD *thd, set_var *var) 1305 { 1306 DBUG_ASSERT(FALSE); 1307 return true; 1308 } session_save_default(THD * thd,set_var * var)1309 void session_save_default(THD *thd, set_var *var) 1310 { 1311 var->save_result.string_value.str= const_cast<char*>(""); 1312 var->save_result.string_value.length= 0; 1313 } global_save_default(THD * thd,set_var * var)1314 void global_save_default(THD *thd, set_var *var) 1315 { 1316 DBUG_ASSERT(FALSE); 1317 } session_value_ptr(THD * thd,LEX_STRING * base)1318 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 1319 { 1320 extern uchar *debug_sync_value_ptr(THD *thd); 1321 return debug_sync_value_ptr(thd); 1322 } global_value_ptr(THD * thd,LEX_STRING * base)1323 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 1324 { 1325 DBUG_ASSERT(FALSE); 1326 return 0; 1327 } check_update_type(Item_result type)1328 bool check_update_type(Item_result type) 1329 { return type != STRING_RESULT; } 1330 }; 1331 #endif /* defined(ENABLED_DEBUG_SYNC) */ 1332 1333 /** 1334 The class for bit variables - a variant of boolean that stores the value 1335 in a bit. 1336 1337 Class specific constructor arguments: 1338 ulonglong bitmask_arg - the mask for the bit to set in the ulonglong 1339 backing store 1340 1341 Backing store: ulonglong 1342 1343 @note 1344 This class supports the "reverse" semantics, when the value of the bit 1345 being 0 corresponds to the value of variable being set. To activate it 1346 use REVERSE(bitmask) instead of simply bitmask in the constructor. 1347 1348 @note 1349 variables of this class cannot be set from the command line as 1350 my_getopt does not support bits. 1351 */ 1352 class Sys_var_bit: public Sys_var_typelib 1353 { 1354 ulonglong bitmask; 1355 bool reverse_semantics; set(uchar * ptr,ulonglong value)1356 void set(uchar *ptr, ulonglong value) 1357 { 1358 if ((value != 0) ^ reverse_semantics) 1359 (*(ulonglong *)ptr)|= bitmask; 1360 else 1361 (*(ulonglong *)ptr)&= ~bitmask; 1362 } 1363 public: 1364 Sys_var_bit(const char *name_arg, 1365 const char *comment, int flag_args, ptrdiff_t off, size_t size, 1366 CMD_LINE getopt, 1367 ulonglong bitmask_arg, my_bool def_val, PolyLock *lock=0, 1368 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 1369 on_check_function on_check_func=0, 1370 on_update_function on_update_func=0, 1371 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,substitute)1372 : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, 1373 SHOW_MY_BOOL, bool_values, def_val, lock, 1374 binlog_status_arg, on_check_func, on_update_func, 1375 substitute) 1376 { 1377 option.var_type= GET_BOOL; 1378 reverse_semantics= my_count_bits(bitmask_arg) > 1; 1379 bitmask= reverse_semantics ? ~bitmask_arg : bitmask_arg; 1380 set(global_var_ptr(), def_val); 1381 DBUG_ASSERT(def_val < 2); 1382 DBUG_ASSERT(getopt.id == -1); // force NO_CMD_LINE 1383 DBUG_ASSERT(size == sizeof(ulonglong)); 1384 } session_update(THD * thd,set_var * var)1385 bool session_update(THD *thd, set_var *var) 1386 { 1387 set(session_var_ptr(thd), var->save_result.ulonglong_value); 1388 return false; 1389 } global_update(THD * thd,set_var * var)1390 bool global_update(THD *thd, set_var *var) 1391 { 1392 set(global_var_ptr(), var->save_result.ulonglong_value); 1393 return false; 1394 } session_save_default(THD * thd,set_var * var)1395 void session_save_default(THD *thd, set_var *var) 1396 { var->save_result.ulonglong_value= global_var(ulonglong) & bitmask; } global_save_default(THD * thd,set_var * var)1397 void global_save_default(THD *thd, set_var *var) 1398 { var->save_result.ulonglong_value= option.def_value; } session_value_ptr(THD * thd,LEX_STRING * base)1399 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 1400 { 1401 thd->sys_var_tmp.my_bool_value= reverse_semantics ^ 1402 ((session_var(thd, ulonglong) & bitmask) != 0); 1403 return (uchar*) &thd->sys_var_tmp.my_bool_value; 1404 } global_value_ptr(THD * thd,LEX_STRING * base)1405 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 1406 { 1407 thd->sys_var_tmp.my_bool_value= reverse_semantics ^ 1408 ((global_var(ulonglong) & bitmask) != 0); 1409 return (uchar*) &thd->sys_var_tmp.my_bool_value; 1410 } 1411 }; 1412 1413 /** 1414 The class for variables that have a special meaning for a session, 1415 such as @@timestamp or @@rnd_seed1, their values typically cannot be read 1416 from SV structure, and a special "read" callback is provided. 1417 1418 Class specific constructor arguments: 1419 everything derived from Sys_var_ulonglong 1420 session_special_read_function read_func_arg 1421 1422 Backing store: ulonglong 1423 1424 @note 1425 These variables are session-only, global or command-line equivalents 1426 are not supported as they're generally meaningless. 1427 */ 1428 class Sys_var_session_special: public Sys_var_ulonglong 1429 { 1430 typedef bool (*session_special_update_function)(THD *thd, set_var *var); 1431 typedef ulonglong (*session_special_read_function)(THD *thd); 1432 1433 session_special_read_function read_func; 1434 session_special_update_function update_func; 1435 public: 1436 Sys_var_session_special(const char *name_arg, 1437 const char *comment, int flag_args, 1438 CMD_LINE getopt, 1439 ulonglong min_val, ulonglong max_val, ulonglong block_size, 1440 PolyLock *lock, enum binlog_status_enum binlog_status_arg, 1441 on_check_function on_check_func, 1442 session_special_update_function update_func_arg, 1443 session_special_read_function read_func_arg, 1444 const char *substitute=0) 1445 : Sys_var_ulonglong(name_arg, comment, flag_args, 0, 1446 sizeof(ulonglong), getopt, min_val, 1447 max_val, 0, block_size, lock, binlog_status_arg, on_check_func, 0, 1448 substitute), 1449 read_func(read_func_arg), update_func(update_func_arg) 1450 { 1451 DBUG_ASSERT(scope() == ONLY_SESSION); 1452 DBUG_ASSERT(getopt.id == -1); // NO_CMD_LINE, because the offset is fake 1453 } session_update(THD * thd,set_var * var)1454 bool session_update(THD *thd, set_var *var) 1455 { return update_func(thd, var); } global_update(THD * thd,set_var * var)1456 bool global_update(THD *thd, set_var *var) 1457 { 1458 DBUG_ASSERT(FALSE); 1459 return true; 1460 } session_save_default(THD * thd,set_var * var)1461 void session_save_default(THD *thd, set_var *var) 1462 { var->value= 0; } global_save_default(THD * thd,set_var * var)1463 void global_save_default(THD *thd, set_var *var) 1464 { DBUG_ASSERT(FALSE); } session_value_ptr(THD * thd,LEX_STRING * base)1465 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 1466 { 1467 thd->sys_var_tmp.ulonglong_value= read_func(thd); 1468 return (uchar*) &thd->sys_var_tmp.ulonglong_value; 1469 } global_value_ptr(THD * thd,LEX_STRING * base)1470 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 1471 { 1472 DBUG_ASSERT(FALSE); 1473 return 0; 1474 } 1475 }; 1476 1477 1478 /** 1479 Similar to Sys_var_session_special, but with double storage. 1480 */ 1481 class Sys_var_session_special_double: public Sys_var_double 1482 { 1483 typedef bool (*session_special_update_function)(THD *thd, set_var *var); 1484 typedef double (*session_special_read_double_function)(THD *thd); 1485 1486 session_special_read_double_function read_func; 1487 session_special_update_function update_func; 1488 public: 1489 Sys_var_session_special_double(const char *name_arg, 1490 const char *comment, int flag_args, 1491 CMD_LINE getopt, 1492 ulonglong min_val, ulonglong max_val, ulonglong block_size, 1493 PolyLock *lock, enum binlog_status_enum binlog_status_arg, 1494 on_check_function on_check_func, 1495 session_special_update_function update_func_arg, 1496 session_special_read_double_function read_func_arg, 1497 const char *substitute=0) 1498 : Sys_var_double(name_arg, comment, flag_args, 0, 1499 sizeof(double), getopt, 1500 min_val, max_val, 0, 1501 lock, binlog_status_arg, on_check_func, 0, 1502 substitute), 1503 read_func(read_func_arg), update_func(update_func_arg) 1504 { 1505 DBUG_ASSERT(scope() == ONLY_SESSION); 1506 DBUG_ASSERT(getopt.id == -1); // NO_CMD_LINE, because the offset is fake 1507 } session_update(THD * thd,set_var * var)1508 bool session_update(THD *thd, set_var *var) 1509 { return update_func(thd, var); } global_update(THD * thd,set_var * var)1510 bool global_update(THD *thd, set_var *var) 1511 { 1512 DBUG_ASSERT(FALSE); 1513 return true; 1514 } session_save_default(THD * thd,set_var * var)1515 void session_save_default(THD *thd, set_var *var) 1516 { var->value= 0; } global_save_default(THD * thd,set_var * var)1517 void global_save_default(THD *thd, set_var *var) 1518 { DBUG_ASSERT(FALSE); } session_value_ptr(THD * thd,LEX_STRING * base)1519 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 1520 { 1521 thd->sys_var_tmp.double_value= read_func(thd); 1522 return (uchar *) &thd->sys_var_tmp.double_value; 1523 } global_value_ptr(THD * thd,LEX_STRING * base)1524 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 1525 { 1526 DBUG_ASSERT(FALSE); 1527 return 0; 1528 } 1529 }; 1530 1531 1532 /** 1533 The class for read-only variables that show whether a particular 1534 feature is supported by the server. Example: have_compression 1535 1536 Backing store: enum SHOW_COMP_OPTION 1537 1538 @note 1539 These variables are necessarily read-only, only global, and have no 1540 command-line equivalent. 1541 */ 1542 class Sys_var_have: public sys_var 1543 { 1544 public: 1545 Sys_var_have(const char *name_arg, 1546 const char *comment, int flag_args, ptrdiff_t off, size_t size, 1547 CMD_LINE getopt, 1548 PolyLock *lock=0, 1549 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 1550 on_check_function on_check_func=0, 1551 on_update_function on_update_func=0, 1552 const char *substitute=0, 1553 int parse_flag= PARSE_NORMAL) 1554 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 1555 getopt.arg_type, SHOW_CHAR, 0, 1556 lock, binlog_status_arg, on_check_func, on_update_func, 1557 substitute, parse_flag) 1558 { 1559 DBUG_ASSERT(scope() == GLOBAL); 1560 DBUG_ASSERT(getopt.id == -1); 1561 DBUG_ASSERT(lock == 0); 1562 DBUG_ASSERT(binlog_status_arg == VARIABLE_NOT_IN_BINLOG); 1563 DBUG_ASSERT(is_readonly()); 1564 DBUG_ASSERT(on_update == 0); 1565 DBUG_ASSERT(size == sizeof(enum SHOW_COMP_OPTION)); 1566 } do_check(THD * thd,set_var * var)1567 bool do_check(THD *thd, set_var *var) { 1568 DBUG_ASSERT(FALSE); 1569 return true; 1570 } session_update(THD * thd,set_var * var)1571 bool session_update(THD *thd, set_var *var) 1572 { 1573 DBUG_ASSERT(FALSE); 1574 return true; 1575 } global_update(THD * thd,set_var * var)1576 bool global_update(THD *thd, set_var *var) 1577 { 1578 DBUG_ASSERT(FALSE); 1579 return true; 1580 } session_save_default(THD * thd,set_var * var)1581 void session_save_default(THD *thd, set_var *var) { } global_save_default(THD * thd,set_var * var)1582 void global_save_default(THD *thd, set_var *var) { } session_value_ptr(THD * thd,LEX_STRING * base)1583 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 1584 { 1585 DBUG_ASSERT(FALSE); 1586 return 0; 1587 } global_value_ptr(THD * thd,LEX_STRING * base)1588 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 1589 { 1590 return (uchar*)show_comp_option_name[global_var(enum SHOW_COMP_OPTION)]; 1591 } check_update_type(Item_result type)1592 bool check_update_type(Item_result type) { return false; } 1593 }; 1594 1595 /** 1596 Generic class for variables for storing entities that are internally 1597 represented as structures, have names, and possibly can be referred to by 1598 numbers. Examples: character sets, collations, locales, 1599 1600 Class specific constructor arguments: 1601 ptrdiff_t name_offset - offset of the 'name' field in the structure 1602 1603 Backing store: void* 1604 1605 @note 1606 As every such a structure requires special treatment from my_getopt, 1607 these variables don't support command-line equivalents, any such 1608 command-line options should be added manually to my_long_options in mysqld.cc 1609 */ 1610 class Sys_var_struct: public sys_var 1611 { 1612 ptrdiff_t name_offset; // offset to the 'name' property in the structure 1613 public: 1614 Sys_var_struct(const char *name_arg, 1615 const char *comment, int flag_args, ptrdiff_t off, size_t size, 1616 CMD_LINE getopt, 1617 ptrdiff_t name_off, void *def_val, PolyLock *lock=0, 1618 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 1619 on_check_function on_check_func=0, 1620 on_update_function on_update_func=0, 1621 const char *substitute=0, 1622 int parse_flag= PARSE_NORMAL) 1623 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 1624 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 1625 lock, binlog_status_arg, on_check_func, on_update_func, 1626 substitute, parse_flag), 1627 name_offset(name_off) 1628 { 1629 option.var_type= GET_STR; 1630 /* 1631 struct variables are special on the command line - often (e.g. for 1632 charsets) the name cannot be immediately resolved, but only after all 1633 options (in particular, basedir) are parsed. 1634 1635 thus all struct command-line options should be added manually 1636 to my_long_options in mysqld.cc 1637 */ 1638 DBUG_ASSERT(getopt.id == -1); 1639 DBUG_ASSERT(size == sizeof(void *)); 1640 } do_check(THD * thd,set_var * var)1641 bool do_check(THD *thd, set_var *var) 1642 { return false; } session_update(THD * thd,set_var * var)1643 bool session_update(THD *thd, set_var *var) 1644 { 1645 session_var(thd, const void*)= var->save_result.ptr; 1646 return false; 1647 } global_update(THD * thd,set_var * var)1648 bool global_update(THD *thd, set_var *var) 1649 { 1650 global_var(const void*)= var->save_result.ptr; 1651 return false; 1652 } session_save_default(THD * thd,set_var * var)1653 void session_save_default(THD *thd, set_var *var) 1654 { var->save_result.ptr= global_var(void*); } global_save_default(THD * thd,set_var * var)1655 void global_save_default(THD *thd, set_var *var) 1656 { 1657 void **default_value= reinterpret_cast<void**>(option.def_value); 1658 var->save_result.ptr= *default_value; 1659 } check_update_type(Item_result type)1660 bool check_update_type(Item_result type) 1661 { return type != INT_RESULT && type != STRING_RESULT; } session_value_ptr(THD * thd,LEX_STRING * base)1662 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 1663 { 1664 uchar *ptr= session_var(thd, uchar*); 1665 return ptr ? *(uchar**)(ptr+name_offset) : 0; 1666 } global_value_ptr(THD * thd,LEX_STRING * base)1667 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 1668 { 1669 uchar *ptr= global_var(uchar*); 1670 return ptr ? *(uchar**)(ptr+name_offset) : 0; 1671 } 1672 }; 1673 1674 /** 1675 The class for variables that store time zones 1676 1677 Backing store: Time_zone* 1678 1679 @note 1680 Time zones cannot be supported directly by my_getopt, thus 1681 these variables don't support command-line equivalents, any such 1682 command-line options should be added manually to my_long_options in mysqld.cc 1683 */ 1684 class Sys_var_tz: public sys_var 1685 { 1686 public: 1687 Sys_var_tz(const char *name_arg, 1688 const char *comment, int flag_args, ptrdiff_t off, size_t size, 1689 CMD_LINE getopt, 1690 Time_zone **def_val, PolyLock *lock=0, 1691 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 1692 on_check_function on_check_func=0, 1693 on_update_function on_update_func=0, 1694 const char *substitute=0, 1695 int parse_flag= PARSE_NORMAL) 1696 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 1697 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 1698 lock, binlog_status_arg, on_check_func, on_update_func, 1699 substitute, parse_flag) 1700 { 1701 DBUG_ASSERT(getopt.id == -1); 1702 DBUG_ASSERT(size == sizeof(Time_zone *)); 1703 } do_check(THD * thd,set_var * var)1704 bool do_check(THD *thd, set_var *var) 1705 { 1706 char buff[MAX_TIME_ZONE_NAME_LENGTH]; 1707 String str(buff, sizeof(buff), &my_charset_latin1); 1708 String *res= var->value->val_str(&str); 1709 1710 if (!res) 1711 return true; 1712 1713 if (!(var->save_result.time_zone= my_tz_find(thd, res))) 1714 { 1715 ErrConvString err(res); 1716 my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), err.ptr()); 1717 return true; 1718 } 1719 return false; 1720 } session_update(THD * thd,set_var * var)1721 bool session_update(THD *thd, set_var *var) 1722 { 1723 session_var(thd, Time_zone*)= var->save_result.time_zone; 1724 return false; 1725 } global_update(THD * thd,set_var * var)1726 bool global_update(THD *thd, set_var *var) 1727 { 1728 global_var(Time_zone*)= var->save_result.time_zone; 1729 return false; 1730 } session_save_default(THD * thd,set_var * var)1731 void session_save_default(THD *thd, set_var *var) 1732 { 1733 var->save_result.time_zone= global_var(Time_zone*); 1734 } global_save_default(THD * thd,set_var * var)1735 void global_save_default(THD *thd, set_var *var) 1736 { 1737 var->save_result.time_zone= 1738 *(Time_zone**)(intptr)option.def_value; 1739 } session_value_ptr(THD * thd,LEX_STRING * base)1740 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 1741 { 1742 /* 1743 This is an ugly fix for replication: we don't replicate properly queries 1744 invoking system variables' values to update tables; but 1745 CONVERT_TZ(,,@@session.time_zone) is so popular that we make it 1746 replicable (i.e. we tell the binlog code to store the session 1747 timezone). If it's the global value which was used we can't replicate 1748 (binlog code stores session value only). 1749 */ 1750 thd->time_zone_used= 1; 1751 return (uchar *)(session_var(thd, Time_zone*)->get_name()->ptr()); 1752 } global_value_ptr(THD * thd,LEX_STRING * base)1753 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 1754 { 1755 return (uchar *)(global_var(Time_zone*)->get_name()->ptr()); 1756 } check_update_type(Item_result type)1757 bool check_update_type(Item_result type) 1758 { return type != STRING_RESULT; } 1759 }; 1760 1761 1762 class Sys_var_tx_isolation: public Sys_var_enum 1763 { 1764 public: Sys_var_tx_isolation(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,enum binlog_status_enum binlog_status_arg,on_check_function on_check_func)1765 Sys_var_tx_isolation(const char *name_arg, 1766 const char *comment, int flag_args, ptrdiff_t off, size_t size, 1767 CMD_LINE getopt, 1768 const char *values[], uint def_val, PolyLock *lock, 1769 enum binlog_status_enum binlog_status_arg, 1770 on_check_function on_check_func) 1771 :Sys_var_enum(name_arg, comment, flag_args, off, size, getopt, 1772 values, def_val, lock, binlog_status_arg, on_check_func) 1773 {} 1774 virtual bool session_update(THD *thd, set_var *var); 1775 }; 1776 1777 1778 /** 1779 Class representing the tx_read_only system variable for setting 1780 default transaction access mode. 1781 1782 Note that there is a special syntax - SET TRANSACTION READ ONLY 1783 (or READ WRITE) that sets the access mode for the next transaction 1784 only. 1785 */ 1786 1787 class Sys_var_tx_read_only: public Sys_var_mybool 1788 { 1789 public: Sys_var_tx_read_only(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,enum binlog_status_enum binlog_status_arg,on_check_function on_check_func)1790 Sys_var_tx_read_only(const char *name_arg, const char *comment, int flag_args, 1791 ptrdiff_t off, size_t size, CMD_LINE getopt, 1792 my_bool def_val, PolyLock *lock, 1793 enum binlog_status_enum binlog_status_arg, 1794 on_check_function on_check_func) 1795 :Sys_var_mybool(name_arg, comment, flag_args, off, size, getopt, 1796 def_val, lock, binlog_status_arg, on_check_func) 1797 {} 1798 virtual bool session_update(THD *thd, set_var *var); 1799 }; 1800 1801 1802 /** 1803 A class for @@global.binlog_checksum that has 1804 a specialized update method. 1805 */ 1806 class Sys_var_enum_binlog_checksum: public Sys_var_enum 1807 { 1808 public: Sys_var_enum_binlog_checksum(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,enum binlog_status_enum binlog_status_arg)1809 Sys_var_enum_binlog_checksum(const char *name_arg, 1810 const char *comment, int flag_args, ptrdiff_t off, size_t size, 1811 CMD_LINE getopt, 1812 const char *values[], uint def_val, PolyLock *lock, 1813 enum binlog_status_enum binlog_status_arg) 1814 :Sys_var_enum(name_arg, comment, flag_args, off, size, getopt, 1815 values, def_val, lock, binlog_status_arg, NULL) 1816 {} 1817 virtual bool global_update(THD *thd, set_var *var); 1818 }; 1819 1820 1821 /** 1822 Class for variables that store values of type Gtid_specification. 1823 */ 1824 class Sys_var_gtid_specification: public sys_var 1825 { 1826 public: 1827 Sys_var_gtid_specification(const char *name_arg, 1828 const char *comment, int flag_args, ptrdiff_t off, size_t size, 1829 CMD_LINE getopt, 1830 const char *def_val, 1831 PolyLock *lock= 0, 1832 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 1833 on_check_function on_check_func=0, 1834 on_update_function on_update_func=0, 1835 const char *substitute=0, 1836 int parse_flag= PARSE_NORMAL) 1837 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 1838 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 1839 lock, binlog_status_arg, on_check_func, on_update_func, 1840 substitute, parse_flag) 1841 { 1842 DBUG_ASSERT(size == sizeof(Gtid_specification)); 1843 } session_update(THD * thd,set_var * var)1844 bool session_update(THD *thd, set_var *var) 1845 { 1846 DBUG_ENTER("Sys_var_gtid::session_update"); 1847 global_sid_lock->rdlock(); 1848 bool ret= (((Gtid_specification *)session_var_ptr(thd))-> 1849 parse(global_sid_map, 1850 var->save_result.string_value.str) != 0); 1851 global_sid_lock->unlock(); 1852 DBUG_RETURN(ret); 1853 } global_update(THD * thd,set_var * var)1854 bool global_update(THD *thd, set_var *var) 1855 { DBUG_ASSERT(FALSE); return true; } session_save_default(THD * thd,set_var * var)1856 void session_save_default(THD *thd, set_var *var) 1857 { 1858 DBUG_ENTER("Sys_var_gtid::session_save_default"); 1859 char *ptr= (char*)(intptr)option.def_value; 1860 var->save_result.string_value.str= ptr; 1861 var->save_result.string_value.length= ptr ? strlen(ptr) : 0; 1862 DBUG_VOID_RETURN; 1863 } global_save_default(THD * thd,set_var * var)1864 void global_save_default(THD *thd, set_var *var) 1865 { DBUG_ASSERT(FALSE); } do_check(THD * thd,set_var * var)1866 bool do_check(THD *thd, set_var *var) 1867 { 1868 DBUG_ENTER("Sys_var_gtid::do_check"); 1869 char buf[Gtid_specification::MAX_TEXT_LENGTH + 1]; 1870 String str(buf, sizeof(buf), &my_charset_latin1); 1871 String *res= var->value->val_str(&str); 1872 if (!res) 1873 DBUG_RETURN(true); 1874 var->save_result.string_value.str= thd->strmake(res->c_ptr_safe(), res->length()); 1875 if (!var->save_result.string_value.str) 1876 { 1877 my_error(ER_OUT_OF_RESOURCES, MYF(0)); // thd->strmake failed 1878 DBUG_RETURN(true); 1879 } 1880 var->save_result.string_value.length= res->length(); 1881 bool ret= Gtid_specification::is_valid(res->c_ptr_safe()) ? false : true; 1882 DBUG_PRINT("info", ("ret=%d", ret)); 1883 DBUG_RETURN(ret); 1884 } check_update_type(Item_result type)1885 bool check_update_type(Item_result type) 1886 { return type != STRING_RESULT; } session_value_ptr(THD * thd,LEX_STRING * base)1887 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 1888 { 1889 DBUG_ENTER("Sys_var_gtid::session_value_ptr"); 1890 char buf[Gtid_specification::MAX_TEXT_LENGTH + 1]; 1891 global_sid_lock->rdlock(); 1892 ((Gtid_specification *)session_var_ptr(thd))-> 1893 to_string(global_sid_map, buf); 1894 global_sid_lock->unlock(); 1895 char *ret= thd->strdup(buf); 1896 DBUG_RETURN((uchar *)ret); 1897 } global_value_ptr(THD * thd,LEX_STRING * base)1898 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 1899 { DBUG_ASSERT(FALSE); return NULL; } 1900 }; 1901 1902 #ifdef HAVE_GTID_NEXT_LIST 1903 /** 1904 Class for variables that store values of type Gtid_set. 1905 1906 The back-end storage should be a Gtid_set_or_null, and it should be 1907 set to null by default. When the variable is set for the first 1908 time, the Gtid_set* will be allocated. 1909 */ 1910 class Sys_var_gtid_set: public sys_var 1911 { 1912 public: 1913 Sys_var_gtid_set(const char *name_arg, 1914 const char *comment, int flag_args, ptrdiff_t off, size_t size, 1915 CMD_LINE getopt, 1916 const char *def_val, 1917 PolyLock *lock= 0, 1918 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 1919 on_check_function on_check_func=0, 1920 on_update_function on_update_func=0, 1921 const char *substitute=0, 1922 int parse_flag= PARSE_NORMAL) 1923 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 1924 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 1925 lock, binlog_status_arg, on_check_func, on_update_func, 1926 substitute, parse_flag) 1927 { 1928 DBUG_ASSERT(size == sizeof(Gtid_set_or_null)); 1929 } session_update(THD * thd,set_var * var)1930 bool session_update(THD *thd, set_var *var) 1931 { 1932 DBUG_ENTER("Sys_var_gtid_set::session_update"); 1933 Gtid_set_or_null *gsn= 1934 (Gtid_set_or_null *)session_var_ptr(thd); 1935 char *value= var->save_result.string_value.str; 1936 if (value == NULL) 1937 gsn->set_null(); 1938 else 1939 { 1940 Gtid_set *gs= gsn->set_non_null(global_sid_map); 1941 if (gs == NULL) 1942 { 1943 my_error(ER_OUT_OF_RESOURCES, MYF(0)); // allocation failed 1944 DBUG_RETURN(true); 1945 } 1946 /* 1947 If string begins with '+', add to the existing set, otherwise 1948 replace existing set. 1949 */ 1950 while (isspace(*value)) 1951 value++; 1952 if (*value == '+') 1953 value++; 1954 else 1955 gs->clear(); 1956 // Add specified set of groups to Gtid_set. 1957 global_sid_lock->rdlock(); 1958 enum_return_status ret= gs->add_gtid_text(value); 1959 global_sid_lock->unlock(); 1960 if (ret != RETURN_STATUS_OK) 1961 { 1962 gsn->set_null(); 1963 DBUG_RETURN(true); 1964 } 1965 } 1966 DBUG_RETURN(false); 1967 } global_update(THD * thd,set_var * var)1968 bool global_update(THD *thd, set_var *var) 1969 { DBUG_ASSERT(FALSE); return true; } session_save_default(THD * thd,set_var * var)1970 void session_save_default(THD *thd, set_var *var) 1971 { 1972 DBUG_ENTER("Sys_var_gtid_set::session_save_default"); 1973 char *ptr= (char*)(intptr)option.def_value; 1974 var->save_result.string_value.str= ptr; 1975 var->save_result.string_value.length= ptr ? strlen(ptr) : 0; 1976 DBUG_VOID_RETURN; 1977 } global_save_default(THD * thd,set_var * var)1978 void global_save_default(THD *thd, set_var *var) 1979 { DBUG_ASSERT(FALSE); } do_check(THD * thd,set_var * var)1980 bool do_check(THD *thd, set_var *var) 1981 { 1982 DBUG_ENTER("Sys_var_gtid_set::do_check"); 1983 String str; 1984 String *res= var->value->val_str(&str); 1985 if (res == NULL) 1986 { 1987 var->save_result.string_value.str= NULL; 1988 DBUG_RETURN(FALSE); 1989 } 1990 DBUG_ASSERT(res->ptr() != NULL); 1991 var->save_result.string_value.str= thd->strmake(res->ptr(), res->length()); 1992 if (var->save_result.string_value.str == NULL) 1993 { 1994 my_error(ER_OUT_OF_RESOURCES, MYF(0)); // thd->strmake failed 1995 DBUG_RETURN(1); 1996 } 1997 var->save_result.string_value.length= res->length(); 1998 bool ret= !Gtid_set::is_valid(res->ptr()); 1999 DBUG_RETURN(ret); 2000 } check_update_type(Item_result type)2001 bool check_update_type(Item_result type) 2002 { return type != STRING_RESULT; } session_value_ptr(THD * thd,LEX_STRING * base)2003 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 2004 { 2005 DBUG_ENTER("Sys_var_gtid_set::session_value_ptr"); 2006 Gtid_set_or_null *gsn= (Gtid_set_or_null *)session_var_ptr(thd); 2007 Gtid_set *gs= gsn->get_gtid_set(); 2008 if (gs == NULL) 2009 DBUG_RETURN(NULL); 2010 char *buf; 2011 global_sid_lock->rdlock(); 2012 buf= (char *)thd->alloc(gs->get_string_length() + 1); 2013 if (buf) 2014 gs->to_string(buf); 2015 else 2016 my_error(ER_OUT_OF_RESOURCES, MYF(0)); // thd->alloc faile 2017 global_sid_lock->unlock(); 2018 DBUG_RETURN((uchar *)buf); 2019 } global_value_ptr(THD * thd,LEX_STRING * base)2020 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 2021 { DBUG_ASSERT(FALSE); return NULL; } 2022 }; 2023 #endif 2024 2025 2026 /** 2027 Abstract base class for read-only variables (global or session) of 2028 string type where the value is generated by some function. This 2029 needs to be subclassed; the session_value_ptr or global_value_ptr 2030 function should be overridden. 2031 */ 2032 class Sys_var_charptr_func: public sys_var 2033 { 2034 public: Sys_var_charptr_func(const char * name_arg,const char * comment,flag_enum flag_arg)2035 Sys_var_charptr_func(const char *name_arg, const char *comment, 2036 flag_enum flag_arg) 2037 : sys_var(&all_sys_vars, name_arg, comment, READ_ONLY flag_arg, 2038 0/*off*/, NO_CMD_LINE.id, NO_CMD_LINE.arg_type, 2039 SHOW_CHAR, (intptr)0/*def_val*/, 2040 NULL/*polylock*/, VARIABLE_NOT_IN_BINLOG, 2041 NULL/*on_check_func*/, NULL/*on_update_func*/, 2042 NULL/*substitute*/, PARSE_NORMAL/*parse_flag*/) 2043 { 2044 DBUG_ASSERT(flag_arg == sys_var::GLOBAL || flag_arg == sys_var::SESSION || 2045 flag_arg == sys_var::ONLY_SESSION); 2046 } session_update(THD * thd,set_var * var)2047 bool session_update(THD *thd, set_var *var) 2048 { DBUG_ASSERT(FALSE); return true; } global_update(THD * thd,set_var * var)2049 bool global_update(THD *thd, set_var *var) 2050 { DBUG_ASSERT(FALSE); return true; } session_save_default(THD * thd,set_var * var)2051 void session_save_default(THD *thd, set_var *var) { DBUG_ASSERT(FALSE); } global_save_default(THD * thd,set_var * var)2052 void global_save_default(THD *thd, set_var *var) { DBUG_ASSERT(FALSE); } do_check(THD * thd,set_var * var)2053 bool do_check(THD *thd, set_var *var) { DBUG_ASSERT(FALSE); return true; } check_update_type(Item_result type)2054 bool check_update_type(Item_result type) { DBUG_ASSERT(FALSE); return true; } session_value_ptr(THD * thd,LEX_STRING * base)2055 virtual uchar *session_value_ptr(THD *thd, LEX_STRING *base) 2056 { DBUG_ASSERT(FALSE); return NULL; } global_value_ptr(THD * thd,LEX_STRING * base)2057 virtual uchar *global_value_ptr(THD *thd, LEX_STRING *base) 2058 { DBUG_ASSERT(FALSE); return NULL; } 2059 }; 2060 2061 2062 /** 2063 Abstract base class for read-only variables (global or session) of 2064 string type where the value is the string representation of a 2065 Gtid_set generated by some function. This needs to be subclassed; 2066 the session_value_ptr or global_value_ptr should be overwritten. 2067 */ 2068 class Sys_var_gtid_set_func: public Sys_var_charptr_func 2069 { 2070 public: Sys_var_gtid_set_func(const char * name_arg,const char * comment,flag_enum flag_arg)2071 Sys_var_gtid_set_func(const char *name_arg, const char *comment, 2072 flag_enum flag_arg) 2073 : Sys_var_charptr_func(name_arg, comment, flag_arg) {} 2074 2075 typedef enum_return_status (*Gtid_set_getter)(THD *, Gtid_set *); 2076 get_string_from_gtid_set(THD * thd,Gtid_set_getter get_gtid_set)2077 static uchar *get_string_from_gtid_set(THD *thd, 2078 Gtid_set_getter get_gtid_set) 2079 { 2080 DBUG_ENTER("Sys_var_gtid_ended_groups::session_value_ptr"); 2081 Gtid_set gs(global_sid_map); 2082 char *buf; 2083 // As an optimization, add 10 Intervals that do not need to be 2084 // allocated. 2085 Gtid_set::Interval ivs[10]; 2086 gs.add_interval_memory(10, ivs); 2087 global_sid_lock->wrlock(); 2088 if (get_gtid_set(thd, &gs) != RETURN_STATUS_OK) 2089 goto error; 2090 // allocate string and print to it 2091 buf= (char *)thd->alloc(gs.get_string_length() + 1); 2092 if (buf == NULL) 2093 { 2094 my_error(ER_OUT_OF_RESOURCES, MYF(0)); 2095 goto error; 2096 } 2097 gs.to_string(buf); 2098 global_sid_lock->unlock(); 2099 DBUG_RETURN((uchar *)buf); 2100 error: 2101 global_sid_lock->unlock(); 2102 DBUG_RETURN(NULL); 2103 } 2104 }; 2105 2106 2107 /** 2108 Class for @@session.gtid_executed and @@global.gtid_executed. 2109 */ 2110 class Sys_var_gtid_executed : Sys_var_gtid_set_func 2111 { 2112 public: Sys_var_gtid_executed(const char * name_arg,const char * comment_arg)2113 Sys_var_gtid_executed(const char *name_arg, const char *comment_arg) 2114 : Sys_var_gtid_set_func(name_arg, comment_arg, SESSION) {} 2115 global_value_ptr(THD * thd,LEX_STRING * base)2116 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 2117 { 2118 DBUG_ENTER("Sys_var_gtid_executed::global_value_ptr"); 2119 global_sid_lock->wrlock(); 2120 const Gtid_set *gs= gtid_state->get_logged_gtids(); 2121 char *buf= (char *)thd->alloc(gs->get_string_length() + 1); 2122 if (buf == NULL) 2123 my_error(ER_OUT_OF_RESOURCES, MYF(0)); 2124 else 2125 gs->to_string(buf); 2126 global_sid_lock->unlock(); 2127 DBUG_RETURN((uchar *)buf); 2128 } 2129 2130 private: get_groups_from_trx_cache(THD * thd,Gtid_set * gs)2131 static enum_return_status get_groups_from_trx_cache(THD *thd, Gtid_set *gs) 2132 { 2133 DBUG_ENTER("Sys_var_gtid_executed::get_groups_from_trx_cache"); 2134 if (opt_bin_log) 2135 { 2136 thd->binlog_setup_trx_data(); 2137 PROPAGATE_REPORTED_ERROR(thd->get_group_cache(true)->get_gtids(gs)); 2138 } 2139 RETURN_OK; 2140 } 2141 2142 public: session_value_ptr(THD * thd,LEX_STRING * base)2143 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 2144 { 2145 return get_string_from_gtid_set(thd, get_groups_from_trx_cache); 2146 } 2147 }; 2148 2149 2150 /** 2151 Class for @@session.gtid_purged. 2152 */ 2153 class Sys_var_gtid_purged : public sys_var 2154 { 2155 public: 2156 Sys_var_gtid_purged(const char *name_arg, 2157 const char *comment, int flag_args, ptrdiff_t off, size_t size, 2158 CMD_LINE getopt, 2159 const char *def_val, 2160 PolyLock *lock= 0, 2161 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 2162 on_check_function on_check_func=0, 2163 on_update_function on_update_func=0, 2164 const char *substitute=0, 2165 int parse_flag= PARSE_NORMAL) 2166 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 2167 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 2168 lock, binlog_status_arg, on_check_func, on_update_func, 2169 substitute, parse_flag) 2170 {} 2171 session_update(THD * thd,set_var * var)2172 bool session_update(THD *thd, set_var *var) 2173 { 2174 DBUG_ASSERT(FALSE); 2175 return true; 2176 } 2177 session_save_default(THD * thd,set_var * var)2178 void session_save_default(THD *thd, set_var *var) 2179 { DBUG_ASSERT(FALSE); } 2180 global_update(THD * thd,set_var * var)2181 bool global_update(THD *thd, set_var *var) 2182 { 2183 DBUG_ENTER("Sys_var_gtid_purged::global_update"); 2184 #ifdef HAVE_REPLICATION 2185 bool error= false; 2186 int rotate_res= 0; 2187 2188 global_sid_lock->wrlock(); 2189 char *previous_gtid_logged= gtid_state->get_logged_gtids()->to_string(); 2190 char *previous_gtid_lost= gtid_state->get_lost_gtids()->to_string(); 2191 enum_return_status ret= gtid_state->add_lost_gtids(var->save_result.string_value.str); 2192 char *current_gtid_logged= gtid_state->get_logged_gtids()->to_string(); 2193 char *current_gtid_lost= gtid_state->get_lost_gtids()->to_string(); 2194 global_sid_lock->unlock(); 2195 if (RETURN_STATUS_OK != ret) 2196 { 2197 error= true; 2198 goto end; 2199 } 2200 2201 // Log messages saying that GTID_PURGED and GTID_EXECUTED were changed. 2202 sql_print_information(ER(ER_GTID_PURGED_WAS_CHANGED), 2203 previous_gtid_lost, current_gtid_lost); 2204 sql_print_information(ER(ER_GTID_EXECUTED_WAS_CHANGED), 2205 previous_gtid_logged, current_gtid_logged); 2206 2207 // Rotate logs to have Previous_gtid_event on last binlog. 2208 rotate_res= mysql_bin_log.rotate_and_purge(thd, true); 2209 if (rotate_res) 2210 { 2211 error= true; 2212 goto end; 2213 } 2214 2215 end: 2216 my_free(previous_gtid_logged); 2217 my_free(previous_gtid_lost); 2218 my_free(current_gtid_logged); 2219 my_free(current_gtid_lost); 2220 DBUG_RETURN(error); 2221 #else 2222 DBUG_RETURN(true); 2223 #endif /* HAVE_REPLICATION */ 2224 } 2225 global_save_default(THD * thd,set_var * var)2226 void global_save_default(THD *thd, set_var *var) 2227 { 2228 /* gtid_purged does not have default value */ 2229 my_error(ER_NO_DEFAULT, MYF(0), var->var->name.str); 2230 } 2231 do_check(THD * thd,set_var * var)2232 bool do_check(THD *thd, set_var *var) 2233 { 2234 DBUG_ENTER("Sys_var_gtid_purged::do_check"); 2235 char buf[1024]; 2236 String str(buf, sizeof(buf), system_charset_info); 2237 String *res= var->value->val_str(&str); 2238 if (!res) 2239 DBUG_RETURN(true); 2240 var->save_result.string_value.str= thd->strmake(res->c_ptr_safe(), 2241 res->length()); 2242 if (!var->save_result.string_value.str) 2243 { 2244 my_error(ER_OUT_OF_RESOURCES, MYF(0)); // thd->strmake failed 2245 DBUG_RETURN(true); 2246 } 2247 var->save_result.string_value.length= res->length(); 2248 bool ret= Gtid_set::is_valid(res->c_ptr_safe()) ? false : true; 2249 DBUG_PRINT("info", ("ret=%d", ret)); 2250 DBUG_RETURN(ret); 2251 } 2252 check_update_type(Item_result type)2253 bool check_update_type(Item_result type) 2254 { return type != STRING_RESULT; } 2255 global_value_ptr(THD * thd,LEX_STRING * base)2256 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 2257 { 2258 DBUG_ENTER("Sys_var_gtid_purged::global_value_ptr"); 2259 global_sid_lock->wrlock(); 2260 const Gtid_set *gs= gtid_state->get_lost_gtids(); 2261 char *buf= (char *)thd->alloc(gs->get_string_length() + 1); 2262 if (buf == NULL) 2263 my_error(ER_OUT_OF_RESOURCES, MYF(0)); 2264 else 2265 gs->to_string(buf); 2266 global_sid_lock->unlock(); 2267 DBUG_RETURN((uchar *)buf); 2268 } 2269 session_value_ptr(THD * thd,LEX_STRING * base)2270 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 2271 { DBUG_ASSERT(0); return NULL; } 2272 }; 2273 2274 2275 class Sys_var_gtid_owned : Sys_var_gtid_set_func 2276 { 2277 public: Sys_var_gtid_owned(const char * name_arg,const char * comment_arg)2278 Sys_var_gtid_owned(const char *name_arg, const char *comment_arg) 2279 : Sys_var_gtid_set_func(name_arg, comment_arg, SESSION) {} 2280 2281 public: session_value_ptr(THD * thd,LEX_STRING * base)2282 uchar *session_value_ptr(THD *thd, LEX_STRING *base) 2283 { 2284 DBUG_ENTER("Sys_var_gtid_owned::session_value_ptr"); 2285 char *buf= NULL; 2286 if (thd->owned_gtid.sidno == 0) 2287 DBUG_RETURN((uchar *)thd->strdup("")); 2288 if (thd->owned_gtid.sidno == -1) 2289 { 2290 #ifdef HAVE_GTID_NEXT_LIST 2291 buf= (char *)thd->alloc(thd->owned_gtid_set.get_string_length() + 1); 2292 if (buf) 2293 { 2294 global_sid_lock->rdlock(); 2295 thd->owned_gtid_set.to_string(buf); 2296 global_sid_lock->unlock(); 2297 } 2298 else 2299 my_error(ER_OUT_OF_RESOURCES, MYF(0)); 2300 #else 2301 DBUG_ASSERT(0); 2302 #endif 2303 } 2304 else 2305 { 2306 buf= (char *)thd->alloc(Gtid::MAX_TEXT_LENGTH + 1); 2307 if (buf) 2308 { 2309 global_sid_lock->rdlock(); 2310 thd->owned_gtid.to_string(global_sid_map, buf); 2311 global_sid_lock->unlock(); 2312 } 2313 else 2314 my_error(ER_OUT_OF_RESOURCES, MYF(0)); 2315 } 2316 DBUG_RETURN((uchar *)buf); 2317 } 2318 global_value_ptr(THD * thd,LEX_STRING * base)2319 uchar *global_value_ptr(THD *thd, LEX_STRING *base) 2320 { 2321 DBUG_ENTER("Sys_var_gtid_owned::global_value_ptr"); 2322 const Owned_gtids *owned_gtids= gtid_state->get_owned_gtids(); 2323 global_sid_lock->wrlock(); 2324 char *buf= (char *)thd->alloc(owned_gtids->get_max_string_length()); 2325 if (buf) 2326 owned_gtids->to_string(buf); 2327 else 2328 my_error(ER_OUT_OF_RESOURCES, MYF(0)); // thd->alloc faile 2329 global_sid_lock->unlock(); 2330 DBUG_RETURN((uchar *)buf); 2331 } 2332 }; 2333