1/* Copyright (c) 2002, 2011, Oracle and/or its affiliates. 2 Copyright (c) 2010, 2019, MariaDB Corporation. 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; version 2 of the License. 7 8 This program is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License 14 along with this program; if not, write to the Free Software 15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ 16 17/** 18 @file 19 "private" interface to sys_var - server configuration variables. 20 21 This header is included only by the file that contains declarations 22 of sys_var variables (sys_vars.cc). 23*/ 24 25#include "sys_vars_shared.h" 26#include <my_getopt.h> 27#include <my_bit.h> 28#include <my_dir.h> 29#include "keycaches.h" 30#include "strfunc.h" 31#include "tztime.h" // my_tz_find, my_tz_SYSTEM, struct Time_zone 32#include "rpl_mi.h" // For Multi-Source Replication 33#include "debug_sync.h" 34 35/* 36 a set of mostly trivial (as in f(X)=X) defines below to make system variable 37 declarations more readable 38*/ 39#define VALID_RANGE(X,Y) X,Y 40#define DEFAULT(X) X 41#define BLOCK_SIZE(X) X 42#define GLOBAL_VAR(X) sys_var::GLOBAL, (((char*)&(X))-(char*)&global_system_variables), sizeof(X) 43#define SESSION_VAR(X) sys_var::SESSION, offsetof(SV, X), sizeof(((SV *)0)->X) 44#define SESSION_ONLY(X) sys_var::ONLY_SESSION, offsetof(SV, X), sizeof(((SV *)0)->X) 45#define NO_CMD_LINE CMD_LINE(NO_ARG, sys_var::NO_GETOPT) 46#define CMD_LINE_HELP_ONLY CMD_LINE(NO_ARG, sys_var::GETOPT_ONLY_HELP) 47/* 48 the define below means that there's no *second* mutex guard, 49 LOCK_global_system_variables always guards all system variables 50*/ 51#define NO_MUTEX_GUARD ((PolyLock*)0) 52#define IN_BINLOG sys_var::SESSION_VARIABLE_IN_BINLOG 53#define NOT_IN_BINLOG sys_var::VARIABLE_NOT_IN_BINLOG 54#define ON_READ(X) X 55#define ON_CHECK(X) X 56#define ON_UPDATE(X) X 57#define READ_ONLY sys_var::READONLY+ 58#define AUTO_SET sys_var::AUTO_SET+ 59// this means that Sys_var_charptr initial value was malloc()ed 60#define PREALLOCATED sys_var::ALLOCATED+ 61#define PARSED_EARLY sys_var::PARSE_EARLY+ 62#define NO_SET_STMT sys_var::NO_SET_STATEMENT+ 63 64/* 65 Sys_var_bit meaning is reversed, like in 66 @@foreign_key_checks <-> OPTION_NO_FOREIGN_KEY_CHECKS 67*/ 68#define REVERSE(X) ~(X) 69#define DEPRECATED(X) X 70 71#define session_var(THD, TYPE) (*(TYPE*)session_var_ptr(THD)) 72#define global_var(TYPE) (*(TYPE*)global_var_ptr()) 73 74#if SIZEOF_OFF_T > 4 && defined(BIG_TABLES) 75#define GET_HA_ROWS GET_ULL 76#else 77#define GET_HA_ROWS GET_ULONG 78#endif 79 80// Disable warning caused by SESSION_VAR() macro 81#ifdef __clang__ 82#pragma clang diagnostic ignored "-Winvalid-offsetof" 83#endif 84 85/* 86 special assert for sysvars. Tells the name of the variable, 87 and fails even in non-debug builds. 88 89 It is supposed to be used *only* in Sys_var* constructors, 90 and has name_arg hard-coded to prevent incorrect usage. 91*/ 92#define SYSVAR_ASSERT(X) \ 93 while(!(X)) \ 94 { \ 95 fprintf(stderr, "Sysvar '%s' failed '%s'\n", name_arg, #X); \ 96 DBUG_ASSERT(0); \ 97 exit(255); \ 98 } 99 100enum charset_enum {IN_SYSTEM_CHARSET, IN_FS_CHARSET}; 101 102static const char *bool_values[3]= {"OFF", "ON", 0}; 103TYPELIB bool_typelib={ array_elements(bool_values)-1, "", bool_values, 0 }; 104 105/** 106 A small wrapper class to pass getopt arguments as a pair 107 to the Sys_var_* constructors. It improves type safety and helps 108 to catch errors in the argument order. 109*/ 110struct CMD_LINE 111{ 112 int id; 113 enum get_opt_arg_type arg_type; 114 CMD_LINE(enum get_opt_arg_type getopt_arg_type, int getopt_id=0) 115 : id(getopt_id), arg_type(getopt_arg_type) {} 116}; 117 118/** 119 Sys_var_integer template is used to generate Sys_var_* classes 120 for variables that represent the value as an integer number. 121 They are Sys_var_uint, Sys_var_ulong, Sys_var_harows, Sys_var_ulonglong, 122 Sys_var_int. 123 124 An integer variable has a minimal and maximal values, and a "block_size" 125 (any valid value of the variable must be divisible by the block_size). 126 127 Class specific constructor arguments: min, max, block_size 128 Backing store: int, uint, ulong, ha_rows, ulonglong, depending on the class 129*/ 130template <typename T, ulong ARGT, enum enum_mysql_show_type SHOWT> 131class Sys_var_integer: public sys_var 132{ 133public: 134 Sys_var_integer(const char *name_arg, 135 const char *comment, int flag_args, ptrdiff_t off, size_t size, 136 CMD_LINE getopt, 137 T min_val, T max_val, T def_val, uint block_size, PolyLock *lock=0, 138 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 139 on_check_function on_check_func=0, 140 on_update_function on_update_func=0, 141 const char *substitute=0) 142 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 143 getopt.arg_type, SHOWT, def_val, lock, binlog_status_arg, 144 on_check_func, on_update_func, substitute) 145 { 146 option.var_type|= ARGT; 147 option.min_value= min_val; 148 option.max_value= max_val; 149 option.block_size= block_size; 150 if ((option.u_max_value= (uchar**) max_var_ptr())) 151 { 152 *((T*) option.u_max_value)= max_val; 153 } 154 155 global_var(T)= def_val; 156 SYSVAR_ASSERT(size == sizeof(T)); 157 SYSVAR_ASSERT(min_val < max_val); 158 SYSVAR_ASSERT(min_val <= def_val); 159 SYSVAR_ASSERT(max_val >= def_val); 160 SYSVAR_ASSERT(block_size > 0); 161 SYSVAR_ASSERT(def_val % block_size == 0); 162 } 163 bool do_check(THD *thd, set_var *var) 164 { 165 my_bool fixed= FALSE, unused; 166 longlong v= var->value->val_int(); 167 168 if ((ARGT == GET_HA_ROWS) || (ARGT == GET_UINT) || 169 (ARGT == GET_ULONG) || (ARGT == GET_ULL)) 170 { 171 ulonglong uv; 172 173 /* 174 if the value is signed and negative, 175 and a variable is unsigned, it is set to zero 176 */ 177 if ((fixed= (!var->value->unsigned_flag && v < 0))) 178 uv= 0; 179 else 180 uv= v; 181 182 var->save_result.ulonglong_value= 183 getopt_ull_limit_value(uv, &option, &unused); 184 185 if (max_var_ptr() && (T)var->save_result.ulonglong_value > get_max_var()) 186 var->save_result.ulonglong_value= get_max_var(); 187 188 fixed= fixed || var->save_result.ulonglong_value != uv; 189 } 190 else 191 { 192 /* 193 if the value is unsigned and has the highest bit set 194 and a variable is signed, it is set to max signed value 195 */ 196 if ((fixed= (var->value->unsigned_flag && v < 0))) 197 v= LONGLONG_MAX; 198 199 var->save_result.longlong_value= 200 getopt_ll_limit_value(v, &option, &unused); 201 202 if (max_var_ptr() && (T)var->save_result.longlong_value > get_max_var()) 203 var->save_result.longlong_value= get_max_var(); 204 205 fixed= fixed || var->save_result.longlong_value != v; 206 } 207 return throw_bounds_warning(thd, name.str, fixed, 208 var->value->unsigned_flag, v); 209 } 210 bool session_update(THD *thd, set_var *var) 211 { 212 session_var(thd, T)= static_cast<T>(var->save_result.ulonglong_value); 213 return false; 214 } 215 bool global_update(THD *thd, set_var *var) 216 { 217 global_var(T)= static_cast<T>(var->save_result.ulonglong_value); 218 return false; 219 } 220 void session_save_default(THD *thd, set_var *var) 221 { var->save_result.ulonglong_value= (ulonglong)*(T*)global_value_ptr(thd, 0); } 222 void global_save_default(THD *thd, set_var *var) 223 { var->save_result.ulonglong_value= option.def_value; } 224 private: 225 T get_max_var() { return *((T*) max_var_ptr()); } 226 const uchar *default_value_ptr(THD *thd) const { return (uchar*) &option.def_value; } 227}; 228 229typedef Sys_var_integer<int, GET_INT, SHOW_SINT> Sys_var_int; 230typedef Sys_var_integer<uint, GET_UINT, SHOW_UINT> Sys_var_uint; 231typedef Sys_var_integer<ulong, GET_ULONG, SHOW_ULONG> Sys_var_ulong; 232typedef Sys_var_integer<ha_rows, GET_HA_ROWS, SHOW_HA_ROWS> Sys_var_harows; 233typedef Sys_var_integer<ulonglong, GET_ULL, SHOW_ULONGLONG> Sys_var_ulonglong; 234typedef Sys_var_integer<long, GET_LONG, SHOW_SLONG> Sys_var_long; 235 236 237template<> const uchar *Sys_var_int::default_value_ptr(THD *thd) const 238{ 239 thd->sys_var_tmp.int_value= (int)option.def_value; 240 return (uchar*) &thd->sys_var_tmp.int_value; 241} 242 243template<> const uchar *Sys_var_uint::default_value_ptr(THD *thd) const 244{ 245 thd->sys_var_tmp.uint_value= (uint)option.def_value; 246 return (uchar*) &thd->sys_var_tmp.uint_value; 247} 248 249template<> const uchar *Sys_var_long::default_value_ptr(THD *thd) const 250{ 251 thd->sys_var_tmp.long_value= (long)option.def_value; 252 return (uchar*) &thd->sys_var_tmp.long_value; 253} 254 255template<> const uchar *Sys_var_ulong::default_value_ptr(THD *thd) const 256{ 257 thd->sys_var_tmp.ulong_value= (ulong)option.def_value; 258 return (uchar*) &thd->sys_var_tmp.ulong_value; 259} 260 261 262/** 263 Helper class for variables that take values from a TYPELIB 264*/ 265class Sys_var_typelib: public sys_var 266{ 267protected: 268 TYPELIB typelib; 269 virtual bool check_maximum(THD *thd, set_var *var, 270 const char *c_val, longlong i_val) 271 { return FALSE; } 272public: 273 Sys_var_typelib(const char *name_arg, 274 const char *comment, int flag_args, ptrdiff_t off, 275 CMD_LINE getopt, 276 SHOW_TYPE show_val_type_arg, const char *values[], 277 ulonglong def_val, PolyLock *lock, 278 enum binlog_status_enum binlog_status_arg, 279 on_check_function on_check_func, on_update_function on_update_func, 280 const char *substitute) 281 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 282 getopt.arg_type, show_val_type_arg, def_val, lock, 283 binlog_status_arg, on_check_func, 284 on_update_func, substitute) 285 { 286 for (typelib.count= 0; values[typelib.count]; typelib.count++) /*no-op */; 287 typelib.name=""; 288 typelib.type_names= values; 289 typelib.type_lengths= 0; // only used by Fields_enum and Field_set 290 option.typelib= &typelib; 291 } 292 bool do_check(THD *thd, set_var *var) // works for enums and my_bool 293 { 294 char buff[STRING_BUFFER_USUAL_SIZE]; 295 String str(buff, sizeof(buff), system_charset_info), *res; 296 297 if (var->value->result_type() == STRING_RESULT) 298 { 299 if (!(res=var->value->val_str(&str))) 300 return true; 301 else 302 if (!(var->save_result.ulonglong_value= 303 find_type(&typelib, res->ptr(), res->length(), false))) 304 return true; 305 else 306 var->save_result.ulonglong_value--; 307 return check_maximum(thd, var, res->ptr(), 0); 308 } 309 310 longlong tmp=var->value->val_int(); 311 if (tmp < 0 || tmp >= typelib.count) 312 return true; 313 var->save_result.ulonglong_value= tmp; 314 return check_maximum(thd, var, 0, tmp); 315 } 316}; 317 318/** 319 The class for ENUM variables - variables that take one value from a fixed 320 list of values. 321 322 Class specific constructor arguments: 323 char* values[] - 0-terminated list of strings of valid values 324 325 Backing store: ulong 326 327 @note 328 Do *not* use "enum FOO" variables as a backing store, there is no 329 guarantee that sizeof(enum FOO) == sizeof(uint), there is no guarantee 330 even that sizeof(enum FOO) == sizeof(enum BAR) 331*/ 332class Sys_var_enum: public Sys_var_typelib 333{ 334public: 335 Sys_var_enum(const char *name_arg, 336 const char *comment, int flag_args, ptrdiff_t off, size_t size, 337 CMD_LINE getopt, 338 const char *values[], uint def_val, PolyLock *lock=0, 339 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 340 on_check_function on_check_func=0, 341 on_update_function on_update_func=0, 342 const char *substitute=0) 343 : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, 344 SHOW_CHAR, values, def_val, lock, 345 binlog_status_arg, on_check_func, on_update_func, 346 substitute) 347 { 348 option.var_type|= GET_ENUM; 349 option.min_value= 0; 350 option.max_value= ULONG_MAX; 351 global_var(ulong)= def_val; 352 if ((option.u_max_value= (uchar**)max_var_ptr())) 353 { 354 *((ulong *) option.u_max_value)= ULONG_MAX; 355 } 356 SYSVAR_ASSERT(def_val < typelib.count); 357 SYSVAR_ASSERT(size == sizeof(ulong)); 358 } 359 bool check_maximum(THD *thd, set_var *var, 360 const char *c_val, longlong i_val) 361 { 362 if (!max_var_ptr() || 363 var->save_result.ulonglong_value <= get_max_var()) 364 return FALSE; 365 var->save_result.ulonglong_value= get_max_var(); 366 367 return c_val ? throw_bounds_warning(thd, name.str, c_val) : 368 throw_bounds_warning(thd, name.str, TRUE, 369 var->value->unsigned_flag, i_val); 370 } 371 bool session_update(THD *thd, set_var *var) 372 { 373 session_var(thd, ulong)= static_cast<ulong>(var->save_result.ulonglong_value); 374 return false; 375 } 376 bool global_update(THD *thd, set_var *var) 377 { 378 global_var(ulong)= static_cast<ulong>(var->save_result.ulonglong_value); 379 return false; 380 } 381 void session_save_default(THD *thd, set_var *var) 382 { var->save_result.ulonglong_value= global_var(ulong); } 383 void global_save_default(THD *thd, set_var *var) 384 { var->save_result.ulonglong_value= option.def_value; } 385 const uchar *valptr(THD *thd, ulong val) const 386 { return reinterpret_cast<const uchar*>(typelib.type_names[val]); } 387 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 388 { return valptr(thd, session_var(thd, ulong)); } 389 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const 390 { return valptr(thd, global_var(ulong)); } 391 const uchar *default_value_ptr(THD *thd) const 392 { return valptr(thd, (ulong)option.def_value); } 393 394 ulong get_max_var() { return *((ulong *) max_var_ptr()); } 395}; 396 397/** 398 The class for boolean variables - a variant of ENUM variables 399 with the fixed list of values of { OFF , ON } 400 401 Backing store: my_bool 402*/ 403class Sys_var_mybool: public Sys_var_typelib 404{ 405public: 406 Sys_var_mybool(const char *name_arg, 407 const char *comment, int flag_args, ptrdiff_t off, size_t size, 408 CMD_LINE getopt, 409 my_bool def_val, PolyLock *lock=0, 410 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 411 on_check_function on_check_func=0, 412 on_update_function on_update_func=0, 413 const char *substitute=0) 414 : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, 415 SHOW_MY_BOOL, bool_values, def_val, lock, 416 binlog_status_arg, on_check_func, on_update_func, 417 substitute) 418 { 419 option.var_type|= GET_BOOL; 420 global_var(my_bool)= def_val; 421 SYSVAR_ASSERT(def_val < 2); 422 SYSVAR_ASSERT(getopt.arg_type == OPT_ARG || getopt.id < 0); 423 SYSVAR_ASSERT(size == sizeof(my_bool)); 424 } 425 bool session_update(THD *thd, set_var *var) 426 { 427 session_var(thd, my_bool)= var->save_result.ulonglong_value != 0; 428 return false; 429 } 430 bool global_update(THD *thd, set_var *var) 431 { 432 global_var(my_bool)= var->save_result.ulonglong_value != 0; 433 return false; 434 } 435 void session_save_default(THD *thd, set_var *var) 436 { var->save_result.ulonglong_value= (ulonglong)*(my_bool *)global_value_ptr(thd, 0); } 437 void global_save_default(THD *thd, set_var *var) 438 { var->save_result.ulonglong_value= option.def_value; } 439 const uchar *default_value_ptr(THD *thd) const 440 { 441 thd->sys_var_tmp.my_bool_value=(my_bool) option.def_value; 442 return (uchar*) &thd->sys_var_tmp.my_bool_value; 443 } 444}; 445 446/** 447 The class for string variables. The string can be in character_set_filesystem 448 or in character_set_system. The string can be allocated with my_malloc() 449 or not. The state of the initial value is specified in the constructor, 450 after that it's managed automatically. The value of NULL is supported. 451 452 Class specific constructor arguments: 453 enum charset_enum is_os_charset_arg 454 455 Backing store: char* 456 457 @note 458 This class supports only GLOBAL variables, because THD on destruction 459 does not destroy individual members of SV, there's no way to free 460 allocated string variables for every thread. 461*/ 462class Sys_var_charptr_base: public sys_var 463{ 464public: 465 Sys_var_charptr_base(const char *name_arg, 466 const char *comment, int flag_args, ptrdiff_t off, size_t size, 467 CMD_LINE getopt, 468 enum charset_enum is_os_charset_arg, 469 const char *def_val, PolyLock *lock=0, 470 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 471 on_check_function on_check_func=0, 472 on_update_function on_update_func=0, 473 const char *substitute=0) 474 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 475 getopt.arg_type, SHOW_CHAR_PTR, (intptr)def_val, 476 lock, binlog_status_arg, on_check_func, on_update_func, 477 substitute) 478 { 479 is_os_charset= is_os_charset_arg == IN_FS_CHARSET; 480 /* 481 use GET_STR_ALLOC - if ALLOCATED it must be *always* allocated, 482 otherwise (GET_STR) you'll never know whether to free it or not. 483 (think of an exit because of an error right after my_getopt) 484 */ 485 option.var_type|= (flags & ALLOCATED) ? GET_STR_ALLOC : GET_STR; 486 global_var(const char*)= def_val; 487 } 488 void cleanup() 489 { 490 if (flags & ALLOCATED) 491 { 492 my_free(global_var(char*)); 493 global_var(char *)= NULL; 494 } 495 flags&= ~ALLOCATED; 496 } 497 static bool do_string_check(THD *thd, set_var *var, CHARSET_INFO *charset) 498 { 499 char buff[STRING_BUFFER_USUAL_SIZE], buff2[STRING_BUFFER_USUAL_SIZE]; 500 String str(buff, sizeof(buff), charset); 501 String str2(buff2, sizeof(buff2), charset), *res; 502 503 if (!(res=var->value->val_str(&str))) 504 { 505 var->save_result.string_value.str= 0; 506 var->save_result.string_value.length= 0; // safety 507 } 508 else 509 { 510 uint32 unused; 511 if (String::needs_conversion(res->length(), res->charset(), 512 charset, &unused)) 513 { 514 uint errors; 515 str2.copy(res->ptr(), res->length(), res->charset(), charset, 516 &errors); 517 res=&str2; 518 519 } 520 var->save_result.string_value.str= thd->strmake(res->ptr(), res->length()); 521 var->save_result.string_value.length= res->length(); 522 } 523 524 return false; 525 } 526 bool do_check(THD *thd, set_var *var) 527 { return do_string_check(thd, var, charset(thd)); } 528 bool session_update(THD *thd, set_var *var)= 0; 529 char *global_update_prepare(THD *thd, set_var *var) 530 { 531 char *new_val, *ptr= var->save_result.string_value.str; 532 size_t len=var->save_result.string_value.length; 533 if (ptr) 534 { 535 new_val= (char*)my_memdup(ptr, len+1, MYF(MY_WME)); 536 if (!new_val) return 0; 537 new_val[len]=0; 538 } 539 else 540 new_val= 0; 541 return new_val; 542 } 543 void global_update_finish(char *new_val) 544 { 545 if (flags & ALLOCATED) 546 my_free(global_var(char*)); 547 flags|= ALLOCATED; 548 global_var(char*)= new_val; 549 } 550 bool global_update(THD *thd, set_var *var) 551 { 552 char *new_val= global_update_prepare(thd, var); 553 global_update_finish(new_val); 554 return (new_val == 0 && var->save_result.string_value.str != 0); 555 } 556 void session_save_default(THD *thd, set_var *var)= 0; 557 void global_save_default(THD *thd, set_var *var) 558 { 559 char *ptr= (char*)(intptr)option.def_value; 560 var->save_result.string_value.str= ptr; 561 var->save_result.string_value.length= ptr ? strlen(ptr) : 0; 562 } 563}; 564 565class Sys_var_charptr: public Sys_var_charptr_base 566{ 567public: 568 Sys_var_charptr(const char *name_arg, 569 const char *comment, int flag_args, ptrdiff_t off, size_t size, 570 CMD_LINE getopt, 571 enum charset_enum is_os_charset_arg, 572 const char *def_val, PolyLock *lock=0, 573 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 574 on_check_function on_check_func=0, 575 on_update_function on_update_func=0, 576 const char *substitute=0) : 577 Sys_var_charptr_base(name_arg, comment, flag_args, off, size, getopt, 578 is_os_charset_arg, def_val, lock, binlog_status_arg, 579 on_check_func, on_update_func, substitute) 580 { 581 SYSVAR_ASSERT(scope() == GLOBAL); 582 SYSVAR_ASSERT(size == sizeof(char *)); 583 } 584 585 bool session_update(THD *thd, set_var *var) 586 { 587 DBUG_ASSERT(FALSE); 588 return true; 589 } 590 void session_save_default(THD *thd, set_var *var) 591 { DBUG_ASSERT(FALSE); } 592}; 593 594#ifndef EMBEDDED_LIBRARY 595class Sys_var_sesvartrack: public Sys_var_charptr_base 596{ 597public: 598 Sys_var_sesvartrack(const char *name_arg, 599 const char *comment, 600 CMD_LINE getopt, 601 enum charset_enum is_os_charset_arg, 602 const char *def_val, PolyLock *lock) : 603 Sys_var_charptr_base(name_arg, comment, 604 SESSION_VAR(session_track_system_variables), 605 getopt, is_os_charset_arg, def_val, lock, 606 VARIABLE_NOT_IN_BINLOG, 0, 0, 0) 607 {} 608 bool do_check(THD *thd, set_var *var) 609 { 610 if (Sys_var_charptr_base::do_check(thd, var) || 611 sysvartrack_validate_value(thd, var->save_result.string_value.str, 612 var->save_result.string_value.length)) 613 return TRUE; 614 return FALSE; 615 } 616 bool global_update(THD *thd, set_var *var) 617 { 618 char *new_val= global_update_prepare(thd, var); 619 if (new_val) 620 { 621 if (sysvartrack_global_update(thd, new_val, 622 var->save_result.string_value.length)) 623 new_val= 0; 624 } 625 global_update_finish(new_val); 626 return (new_val == 0 && var->save_result.string_value.str != 0); 627 } 628 bool session_update(THD *thd, set_var *var) 629 { return thd->session_tracker.sysvars.update(thd, var); } 630 void session_save_default(THD *thd, set_var *var) 631 { 632 var->save_result.string_value.str= global_var(char*); 633 var->save_result.string_value.length= 634 strlen(var->save_result.string_value.str); 635 /* parse and feel list with default values */ 636 if (thd) 637 { 638#ifdef DBUG_ASSERT_EXISTS 639 bool res= 640#endif 641 sysvartrack_validate_value(thd, 642 var->save_result.string_value.str, 643 var->save_result.string_value.length); 644 DBUG_ASSERT(res == 0); 645 } 646 } 647}; 648#endif //EMBEDDED_LIBRARY 649 650 651class Sys_var_proxy_user: public sys_var 652{ 653public: 654 Sys_var_proxy_user(const char *name_arg, 655 const char *comment, enum charset_enum is_os_charset_arg) 656 : sys_var(&all_sys_vars, name_arg, comment, 657 sys_var::READONLY+sys_var::ONLY_SESSION, 0, NO_GETOPT, 658 NO_ARG, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, 659 NULL, NULL, NULL) 660 { 661 is_os_charset= is_os_charset_arg == IN_FS_CHARSET; 662 option.var_type|= GET_STR; 663 } 664 bool do_check(THD *thd, set_var *var) 665 { 666 DBUG_ASSERT(FALSE); 667 return true; 668 } 669 bool session_update(THD *thd, set_var *var) 670 { 671 DBUG_ASSERT(FALSE); 672 return true; 673 } 674 bool global_update(THD *thd, set_var *var) 675 { 676 DBUG_ASSERT(FALSE); 677 return false; 678 } 679 void session_save_default(THD *thd, set_var *var) 680 { DBUG_ASSERT(FALSE); } 681 void global_save_default(THD *thd, set_var *var) 682 { DBUG_ASSERT(FALSE); } 683protected: 684 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 685 { 686 return thd->security_ctx->proxy_user[0] ? 687 (uchar *) &(thd->security_ctx->proxy_user[0]) : NULL; 688 } 689}; 690 691class Sys_var_external_user : public Sys_var_proxy_user 692{ 693public: 694 Sys_var_external_user(const char *name_arg, const char *comment_arg, 695 enum charset_enum is_os_charset_arg) 696 : Sys_var_proxy_user (name_arg, comment_arg, is_os_charset_arg) 697 {} 698 699protected: 700 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 701 { 702 return (uchar*)thd->security_ctx->external_user; 703 } 704}; 705 706class Master_info; 707class Sys_var_rpl_filter: public sys_var 708{ 709private: 710 int opt_id; 711 712public: 713 Sys_var_rpl_filter(const char *name, int getopt_id, const char *comment) 714 : sys_var(&all_sys_vars, name, comment, sys_var::GLOBAL, 0, NO_GETOPT, 715 NO_ARG, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, 716 NULL, NULL, NULL), opt_id(getopt_id) 717 { 718 option.var_type|= GET_STR | GET_ASK_ADDR; 719 } 720 721 bool do_check(THD *thd, set_var *var) 722 { 723 return Sys_var_charptr::do_string_check(thd, var, charset(thd)); 724 } 725 void session_save_default(THD *thd, set_var *var) 726 { DBUG_ASSERT(FALSE); } 727 728 void global_save_default(THD *thd, set_var *var) 729 { 730 char *ptr= (char*)(intptr)option.def_value; 731 var->save_result.string_value.str= ptr; 732 var->save_result.string_value.length= ptr ? strlen(ptr) : 0; 733 } 734 735 bool session_update(THD *thd, set_var *var) 736 { 737 DBUG_ASSERT(FALSE); 738 return true; 739 } 740 741 bool global_update(THD *thd, set_var *var); 742 743protected: 744 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const; 745 bool set_filter_value(const char *value, Master_info *mi); 746}; 747 748/** 749 The class for string variables. Useful for strings that aren't necessarily 750 \0-terminated. Otherwise the same as Sys_var_charptr. 751 752 Class specific constructor arguments: 753 enum charset_enum is_os_charset_arg 754 755 Backing store: LEX_CSTRING 756 757 @note 758 Behaves exactly as Sys_var_charptr, only the backing store is different. 759*/ 760class Sys_var_lexstring: public Sys_var_charptr 761{ 762public: 763 Sys_var_lexstring(const char *name_arg, 764 const char *comment, int flag_args, ptrdiff_t off, size_t size, 765 CMD_LINE getopt, 766 enum charset_enum is_os_charset_arg, 767 const char *def_val, PolyLock *lock=0, 768 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 769 on_check_function on_check_func=0, 770 on_update_function on_update_func=0, 771 const char *substitute=0) 772 : Sys_var_charptr(name_arg, comment, flag_args, off, sizeof(char*), 773 getopt, is_os_charset_arg, def_val, lock, binlog_status_arg, 774 on_check_func, on_update_func, substitute) 775 { 776 global_var(LEX_CSTRING).length= strlen(def_val); 777 SYSVAR_ASSERT(size == sizeof(LEX_CSTRING)); 778 *const_cast<SHOW_TYPE*>(&show_val_type)= SHOW_LEX_STRING; 779 } 780 bool global_update(THD *thd, set_var *var) 781 { 782 if (Sys_var_charptr::global_update(thd, var)) 783 return true; 784 global_var(LEX_CSTRING).length= var->save_result.string_value.length; 785 return false; 786 } 787}; 788 789 790/* 791 A LEX_CSTRING stored only in thd->variables 792 Only to be used for small buffers 793*/ 794 795class Sys_var_session_lexstring: public sys_var 796{ 797 size_t max_length; 798public: 799 Sys_var_session_lexstring(const char *name_arg, 800 const char *comment, int flag_args, 801 ptrdiff_t off, size_t size, CMD_LINE getopt, 802 enum charset_enum is_os_charset_arg, 803 const char *def_val, size_t max_length_arg, 804 on_check_function on_check_func=0, 805 on_update_function on_update_func=0) 806 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 807 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 808 0, VARIABLE_NOT_IN_BINLOG, on_check_func, on_update_func, 809 0),max_length(max_length_arg) 810 { 811 option.var_type|= GET_STR; 812 SYSVAR_ASSERT(scope() == ONLY_SESSION) 813 *const_cast<SHOW_TYPE*>(&show_val_type)= SHOW_LEX_STRING; 814 } 815 bool do_check(THD *thd, set_var *var) 816 { 817 char buff[STRING_BUFFER_USUAL_SIZE]; 818 String str(buff, sizeof(buff), system_charset_info), *res; 819 820 if (!(res=var->value->val_str(&str))) 821 { 822 var->save_result.string_value.str= 0; /* NULL */ 823 var->save_result.string_value.length= 0; 824 } 825 else 826 { 827 if (res->length() > max_length) 828 { 829 my_error(ER_WRONG_STRING_LENGTH, MYF(0), 830 res->ptr(), name.str, (int) max_length); 831 return true; 832 } 833 var->save_result.string_value.str= thd->strmake(res->ptr(), 834 res->length()); 835 var->save_result.string_value.length= res->length(); 836 } 837 return false; 838 } 839 bool session_update(THD *thd, set_var *var) 840 { 841 LEX_CSTRING *tmp= &session_var(thd, LEX_CSTRING); 842 tmp->length= var->save_result.string_value.length; 843 /* Store as \0 terminated string (just to be safe) */ 844 strmake((char*) tmp->str, var->save_result.string_value.str, tmp->length); 845 return false; 846 } 847 bool global_update(THD *thd, set_var *var) 848 { 849 DBUG_ASSERT(FALSE); 850 return false; 851 } 852 void session_save_default(THD *thd, set_var *var) 853 { 854 char *ptr= (char*)(intptr)option.def_value; 855 var->save_result.string_value.str= ptr; 856 var->save_result.string_value.length= strlen(ptr); 857 } 858 void global_save_default(THD *thd, set_var *var) 859 { 860 DBUG_ASSERT(FALSE); 861 } 862 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const 863 { 864 DBUG_ASSERT(FALSE); 865 return NULL; 866 } 867}; 868 869 870#ifndef DBUG_OFF 871/** 872 @@session.debug_dbug and @@global.debug_dbug variables. 873 874 @@dbug variable differs from other variables in one aspect: 875 if its value is not assigned in the session, it "points" to the global 876 value, and so when the global value is changed, the change 877 immediately takes effect in the session. 878 879 This semantics is intentional, to be able to debug one session from 880 another. 881*/ 882class Sys_var_dbug: public sys_var 883{ 884public: 885 Sys_var_dbug(const char *name_arg, 886 const char *comment, int flag_args, 887 CMD_LINE getopt, 888 const char *def_val, PolyLock *lock=0, 889 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 890 on_check_function on_check_func=0, 891 on_update_function on_update_func=0, 892 const char *substitute=0) 893 : sys_var(&all_sys_vars, name_arg, comment, flag_args, 894 (char*)¤t_dbug_option-(char*)&global_system_variables, getopt.id, 895 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 896 lock, binlog_status_arg, on_check_func, on_update_func, 897 substitute) 898 { option.var_type|= GET_STR; } 899 bool do_check(THD *thd, set_var *var) 900 { 901 char buff[STRING_BUFFER_USUAL_SIZE]; 902 String str(buff, sizeof(buff), system_charset_info), *res; 903 904 if (!(res=var->value->val_str(&str))) 905 { 906 var->save_result.string_value.str= const_cast<char*>(""); 907 var->save_result.string_value.length= 0; 908 } 909 else 910 { 911 size_t len= res->length(); 912 var->save_result.string_value.str= thd->strmake(res->ptr(), len); 913 var->save_result.string_value.length= len; 914 } 915 return false; 916 } 917 bool session_update(THD *thd, set_var *var) 918 { 919 const char *val= var->save_result.string_value.str; 920 if (!var->value) 921 DBUG_POP(); 922 else 923 DBUG_SET(val); 924 return false; 925 } 926 bool global_update(THD *thd, set_var *var) 927 { 928 const char *val= var->save_result.string_value.str; 929 DBUG_SET_INITIAL(val); 930 return false; 931 } 932 void session_save_default(THD *thd, set_var *var) 933 { } 934 void global_save_default(THD *thd, set_var *var) 935 { 936 char *ptr= (char*)(intptr)option.def_value; 937 var->save_result.string_value.str= ptr; 938 var->save_result.string_value.length= safe_strlen(ptr); 939 } 940 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 941 { 942 char buf[256]; 943 DBUG_EXPLAIN(buf, sizeof(buf)); 944 return (uchar*) thd->strdup(buf); 945 } 946 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const 947 { 948 char buf[256]; 949 DBUG_EXPLAIN_INITIAL(buf, sizeof(buf)); 950 return (uchar*) thd->strdup(buf); 951 } 952 const uchar *default_value_ptr(THD *thd) const 953 { return (uchar*)""; } 954}; 955#endif 956 957#define KEYCACHE_VAR(X) GLOBAL_VAR(dflt_key_cache_var.X) 958#define keycache_var_ptr(KC, OFF) (((uchar*)(KC))+(OFF)) 959#define keycache_var(KC, OFF) (*(ulonglong*)keycache_var_ptr(KC, OFF)) 960typedef bool (*keycache_update_function)(THD *, KEY_CACHE *, ptrdiff_t, ulonglong); 961 962/** 963 The class for keycache_* variables. Supports structured names, 964 keycache_name.variable_name. 965 966 Class specific constructor arguments: 967 everything derived from Sys_var_ulonglong 968 969 Backing store: ulonglong 970 971 @note these variables can be only GLOBAL 972*/ 973class Sys_var_keycache: public Sys_var_ulonglong 974{ 975 keycache_update_function keycache_update; 976public: 977 Sys_var_keycache(const char *name_arg, 978 const char *comment, int flag_args, ptrdiff_t off, size_t size, 979 CMD_LINE getopt, 980 ulonglong min_val, ulonglong max_val, ulonglong def_val, 981 uint block_size, PolyLock *lock, 982 enum binlog_status_enum binlog_status_arg, 983 on_check_function on_check_func, 984 keycache_update_function on_update_func, 985 const char *substitute=0) 986 : Sys_var_ulonglong(name_arg, comment, flag_args, off, size, 987 getopt, min_val, max_val, def_val, 988 block_size, lock, binlog_status_arg, on_check_func, 0, 989 substitute), 990 keycache_update(on_update_func) 991 { 992 option.var_type|= GET_ASK_ADDR; 993 option.value= (uchar**)1; // crash me, please 994 // fix an offset from global_system_variables to be an offset in KEY_CACHE 995 offset= global_var_ptr() - (uchar*)dflt_key_cache; 996 SYSVAR_ASSERT(scope() == GLOBAL); 997 } 998 bool global_update(THD *thd, set_var *var) 999 { 1000 ulonglong new_value= var->save_result.ulonglong_value; 1001 LEX_CSTRING *base_name= &var->base; 1002 KEY_CACHE *key_cache; 1003 1004 /* If no basename, assume it's for the key cache named 'default' */ 1005 if (!base_name->length) 1006 base_name= &default_key_cache_base; 1007 1008 key_cache= get_key_cache(base_name); 1009 1010 if (!key_cache) 1011 { // Key cache didn't exists */ 1012 if (!new_value) // Tried to delete cache 1013 return false; // Ok, nothing to do 1014 if (!(key_cache= create_key_cache(base_name->str, base_name->length))) 1015 return true; 1016 } 1017 1018 /** 1019 Abort if some other thread is changing the key cache 1020 @todo This should be changed so that we wait until the previous 1021 assignment is done and then do the new assign 1022 */ 1023 if (key_cache->in_init) 1024 return true; 1025 1026 return keycache_update(thd, key_cache, offset, new_value); 1027 } 1028 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const 1029 { 1030 KEY_CACHE *key_cache= get_key_cache(base); 1031 if (!key_cache) 1032 key_cache= &zero_key_cache; 1033 return keycache_var_ptr(key_cache, offset); 1034 } 1035}; 1036 1037static bool update_buffer_size(THD *thd, KEY_CACHE *key_cache, 1038 ptrdiff_t offset, ulonglong new_value) 1039{ 1040 bool error= false; 1041 DBUG_ASSERT(offset == offsetof(KEY_CACHE, param_buff_size)); 1042 1043 if (new_value == 0) 1044 { 1045 if (key_cache == dflt_key_cache) 1046 { 1047 my_error(ER_WARN_CANT_DROP_DEFAULT_KEYCACHE, MYF(0)); 1048 return true; 1049 } 1050 1051 if (key_cache->key_cache_inited) // If initied 1052 { 1053 /* 1054 Move tables using this key cache to the default key cache 1055 and clear the old key cache. 1056 */ 1057 key_cache->in_init= 1; 1058 mysql_mutex_unlock(&LOCK_global_system_variables); 1059 key_cache->param_buff_size= 0; 1060 ha_resize_key_cache(key_cache); 1061 ha_change_key_cache(key_cache, dflt_key_cache); 1062 /* 1063 We don't delete the key cache as some running threads my still be in 1064 the key cache code with a pointer to the deleted (empty) key cache 1065 */ 1066 mysql_mutex_lock(&LOCK_global_system_variables); 1067 key_cache->in_init= 0; 1068 } 1069 return error; 1070 } 1071 1072 key_cache->param_buff_size= new_value; 1073 1074 /* If key cache didn't exist initialize it, else resize it */ 1075 key_cache->in_init= 1; 1076 mysql_mutex_unlock(&LOCK_global_system_variables); 1077 1078 if (!key_cache->key_cache_inited) 1079 error= ha_init_key_cache(0, key_cache, 0); 1080 else 1081 error= ha_resize_key_cache(key_cache); 1082 1083 mysql_mutex_lock(&LOCK_global_system_variables); 1084 key_cache->in_init= 0; 1085 1086 return error; 1087} 1088 1089static bool update_keycache(THD *thd, KEY_CACHE *key_cache, 1090 ptrdiff_t offset, ulonglong new_value, 1091 int (*func)(KEY_CACHE *)) 1092{ 1093 bool error= false; 1094 DBUG_ASSERT(offset != offsetof(KEY_CACHE, param_buff_size)); 1095 1096 keycache_var(key_cache, offset)= new_value; 1097 1098 key_cache->in_init= 1; 1099 mysql_mutex_unlock(&LOCK_global_system_variables); 1100 error= func(key_cache); 1101 mysql_mutex_lock(&LOCK_global_system_variables); 1102 key_cache->in_init= 0; 1103 1104 return error; 1105} 1106 1107static bool resize_keycache(THD *thd, KEY_CACHE *key_cache, 1108 ptrdiff_t offset, ulonglong new_value) 1109{ 1110 return update_keycache(thd, key_cache, offset, new_value, 1111 ha_resize_key_cache); 1112} 1113 1114static bool change_keycache_param(THD *thd, KEY_CACHE *key_cache, 1115 ptrdiff_t offset, ulonglong new_value) 1116{ 1117 return update_keycache(thd, key_cache, offset, new_value, 1118 ha_change_key_cache_param); 1119} 1120 1121static bool repartition_keycache(THD *thd, KEY_CACHE *key_cache, 1122 ptrdiff_t offset, ulonglong new_value) 1123{ 1124 return update_keycache(thd, key_cache, offset, new_value, 1125 ha_repartition_key_cache); 1126} 1127 1128 1129/** 1130 The class for floating point variables 1131 1132 Class specific constructor arguments: min, max 1133 1134 Backing store: double 1135*/ 1136class Sys_var_double: public sys_var 1137{ 1138public: 1139 Sys_var_double(const char *name_arg, 1140 const char *comment, int flag_args, ptrdiff_t off, size_t size, 1141 CMD_LINE getopt, 1142 double min_val, double max_val, double def_val, PolyLock *lock=0, 1143 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 1144 on_check_function on_check_func=0, 1145 on_update_function on_update_func=0, 1146 const char *substitute=0) 1147 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 1148 getopt.arg_type, SHOW_DOUBLE, 1149 (longlong) getopt_double2ulonglong(def_val), 1150 lock, binlog_status_arg, on_check_func, on_update_func, 1151 substitute) 1152 { 1153 option.var_type|= GET_DOUBLE; 1154 option.min_value= (longlong) getopt_double2ulonglong(min_val); 1155 option.max_value= (longlong) getopt_double2ulonglong(max_val); 1156 global_var(double)= (double)option.def_value; 1157 SYSVAR_ASSERT(min_val < max_val); 1158 SYSVAR_ASSERT(min_val <= def_val); 1159 SYSVAR_ASSERT(max_val >= def_val); 1160 SYSVAR_ASSERT(size == sizeof(double)); 1161 } 1162 bool do_check(THD *thd, set_var *var) 1163 { 1164 my_bool fixed; 1165 double v= var->value->val_real(); 1166 var->save_result.double_value= getopt_double_limit_value(v, &option, &fixed); 1167 1168 return throw_bounds_warning(thd, name.str, fixed, v); 1169 } 1170 bool session_update(THD *thd, set_var *var) 1171 { 1172 session_var(thd, double)= var->save_result.double_value; 1173 return false; 1174 } 1175 bool global_update(THD *thd, set_var *var) 1176 { 1177 global_var(double)= var->save_result.double_value; 1178 return false; 1179 } 1180 void session_save_default(THD *thd, set_var *var) 1181 { var->save_result.double_value= global_var(double); } 1182 void global_save_default(THD *thd, set_var *var) 1183 { var->save_result.double_value= getopt_ulonglong2double(option.def_value); } 1184}; 1185 1186/** 1187 The class for the @max_user_connections. 1188 It's derived from Sys_var_uint, but non-standard session value 1189 requires a new class. 1190 1191 Class specific constructor arguments: 1192 everything derived from Sys_var_uint 1193 1194 Backing store: uint 1195*/ 1196class Sys_var_max_user_conn: public Sys_var_int 1197{ 1198public: 1199 Sys_var_max_user_conn(const char *name_arg, 1200 const char *comment, int flag_args, ptrdiff_t off, size_t size, 1201 CMD_LINE getopt, 1202 int min_val, int max_val, int def_val, 1203 uint block_size, PolyLock *lock=0, 1204 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 1205 on_check_function on_check_func=0, 1206 on_update_function on_update_func=0, 1207 const char *substitute=0) 1208 : Sys_var_int(name_arg, comment, SESSION, off, size, getopt, 1209 min_val, max_val, def_val, block_size, 1210 lock, binlog_status_arg, on_check_func, on_update_func, 1211 substitute) 1212 { } 1213 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 1214 { 1215 if (thd->user_connect && thd->user_connect->user_resources.user_conn) 1216 return (uchar*) &(thd->user_connect->user_resources.user_conn); 1217 return global_value_ptr(thd, base); 1218 } 1219}; 1220 1221/** 1222 The class for flagset variables - a variant of SET that allows in-place 1223 editing (turning on/off individual bits). String representations looks like 1224 a "flag=val,flag=val,...". Example: @@optimizer_switch 1225 1226 Class specific constructor arguments: 1227 char* values[] - 0-terminated list of strings of valid values 1228 1229 Backing store: ulonglong 1230 1231 @note 1232 the last value in the values[] array should 1233 *always* be the string "default". 1234*/ 1235class Sys_var_flagset: public Sys_var_typelib 1236{ 1237public: 1238 Sys_var_flagset(const char *name_arg, 1239 const char *comment, int flag_args, ptrdiff_t off, size_t size, 1240 CMD_LINE getopt, 1241 const char *values[], ulonglong def_val, PolyLock *lock=0, 1242 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 1243 on_check_function on_check_func=0, 1244 on_update_function on_update_func=0, 1245 const char *substitute=0) 1246 : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, 1247 SHOW_CHAR, values, def_val, lock, 1248 binlog_status_arg, on_check_func, on_update_func, 1249 substitute) 1250 { 1251 option.var_type|= GET_FLAGSET; 1252 global_var(ulonglong)= def_val; 1253 SYSVAR_ASSERT(typelib.count > 1); 1254 SYSVAR_ASSERT(typelib.count <= 65); 1255 SYSVAR_ASSERT(def_val <= my_set_bits(typelib.count-1)); 1256 SYSVAR_ASSERT(strcmp(values[typelib.count-1], "default") == 0); 1257 SYSVAR_ASSERT(size == sizeof(ulonglong)); 1258 } 1259 bool do_check(THD *thd, set_var *var) 1260 { 1261 char buff[STRING_BUFFER_USUAL_SIZE]; 1262 String str(buff, sizeof(buff), system_charset_info), *res; 1263 ulonglong default_value, current_value; 1264 if (var->type == OPT_GLOBAL) 1265 { 1266 default_value= option.def_value; 1267 current_value= global_var(ulonglong); 1268 } 1269 else 1270 { 1271 default_value= global_var(ulonglong); 1272 current_value= session_var(thd, ulonglong); 1273 } 1274 1275 if (var->value->result_type() == STRING_RESULT) 1276 { 1277 if (!(res=var->value->val_str(&str))) 1278 return true; 1279 else 1280 { 1281 char *error; 1282 uint error_len; 1283 1284 var->save_result.ulonglong_value= 1285 find_set_from_flags(&typelib, 1286 typelib.count, 1287 current_value, 1288 default_value, 1289 res->ptr(), res->length(), 1290 &error, &error_len); 1291 if (unlikely(error)) 1292 { 1293 ErrConvString err(error, error_len, res->charset()); 1294 my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr()); 1295 return true; 1296 } 1297 } 1298 } 1299 else 1300 { 1301 longlong tmp=var->value->val_int(); 1302 if ((tmp < 0 && ! var->value->unsigned_flag) 1303 || (ulonglong)tmp > my_set_bits(typelib.count)) 1304 return true; 1305 else 1306 var->save_result.ulonglong_value= tmp; 1307 } 1308 1309 return false; 1310 } 1311 bool session_update(THD *thd, set_var *var) 1312 { 1313 session_var(thd, ulonglong)= var->save_result.ulonglong_value; 1314 return false; 1315 } 1316 bool global_update(THD *thd, set_var *var) 1317 { 1318 global_var(ulonglong)= var->save_result.ulonglong_value; 1319 return false; 1320 } 1321 void session_save_default(THD *thd, set_var *var) 1322 { var->save_result.ulonglong_value= global_var(ulonglong); } 1323 void global_save_default(THD *thd, set_var *var) 1324 { var->save_result.ulonglong_value= option.def_value; } 1325 const uchar *valptr(THD *thd, ulonglong val) const 1326 { return (uchar*)flagset_to_string(thd, 0, val, typelib.type_names); } 1327 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 1328 { return valptr(thd, session_var(thd, ulonglong)); } 1329 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const 1330 { return valptr(thd, global_var(ulonglong)); } 1331 const uchar *default_value_ptr(THD *thd) const 1332 { return valptr(thd, option.def_value); } 1333}; 1334 1335/** 1336 The class for SET variables - variables taking zero or more values 1337 from the given list. Example: @@sql_mode 1338 1339 Class specific constructor arguments: 1340 char* values[] - 0-terminated list of strings of valid values 1341 1342 Backing store: ulonglong 1343*/ 1344class Sys_var_set: public Sys_var_typelib 1345{ 1346public: 1347 Sys_var_set(const char *name_arg, 1348 const char *comment, int flag_args, ptrdiff_t off, size_t size, 1349 CMD_LINE getopt, 1350 const char *values[], ulonglong def_val, PolyLock *lock=0, 1351 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 1352 on_check_function on_check_func=0, 1353 on_update_function on_update_func=0, 1354 const char *substitute=0) 1355 : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, 1356 SHOW_CHAR, values, def_val, lock, 1357 binlog_status_arg, on_check_func, on_update_func, 1358 substitute) 1359 { 1360 option.var_type|= GET_SET; 1361 option.min_value= 0; 1362 option.max_value= ~0ULL; 1363 global_var(ulonglong)= def_val; 1364 if ((option.u_max_value= (uchar**)max_var_ptr())) 1365 { 1366 *((ulonglong*) option.u_max_value)= ~0ULL; 1367 } 1368 SYSVAR_ASSERT(typelib.count > 0); 1369 SYSVAR_ASSERT(typelib.count <= 64); 1370 SYSVAR_ASSERT(def_val <= my_set_bits(typelib.count)); 1371 SYSVAR_ASSERT(size == sizeof(ulonglong)); 1372 } 1373 bool check_maximum(THD *thd, set_var *var, 1374 const char *c_val, longlong i_val) 1375 { 1376 if (!max_var_ptr() || 1377 (var->save_result.ulonglong_value & ~(get_max_var())) == 0) 1378 return FALSE; 1379 var->save_result.ulonglong_value&= get_max_var(); 1380 1381 return c_val ? throw_bounds_warning(thd, name.str, c_val) : 1382 throw_bounds_warning(thd, name.str, TRUE, 1383 var->value->unsigned_flag, i_val); 1384 } 1385 bool do_check(THD *thd, set_var *var) 1386 { 1387 char buff[STRING_BUFFER_USUAL_SIZE]; 1388 String str(buff, sizeof(buff), system_charset_info), *res; 1389 1390 if (var->value->result_type() == STRING_RESULT) 1391 { 1392 char *error; 1393 uint error_len; 1394 bool not_used; 1395 1396 if (!(res= var->value->val_str_ascii_revert_empty_string_is_null(thd, 1397 &str))) 1398 return true; 1399 1400 var->save_result.ulonglong_value= 1401 find_set(&typelib, res->ptr(), res->length(), NULL, 1402 &error, &error_len, ¬_used); 1403 /* 1404 note, we only issue an error if error_len > 0. 1405 That is even while empty (zero-length) values are considered 1406 errors by find_set(), these errors are ignored here 1407 */ 1408 if (error_len) 1409 { 1410 ErrConvString err(error, error_len, res->charset()); 1411 my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr()); 1412 return true; 1413 } 1414 return check_maximum(thd, var, res->ptr(), 0); 1415 } 1416 1417 longlong tmp=var->value->val_int(); 1418 if ((tmp < 0 && ! var->value->unsigned_flag) 1419 || (ulonglong)tmp > my_set_bits(typelib.count)) 1420 return true; 1421 1422 var->save_result.ulonglong_value= tmp; 1423 return check_maximum(thd, var, 0, tmp); 1424 } 1425 bool session_update(THD *thd, set_var *var) 1426 { 1427 session_var(thd, ulonglong)= var->save_result.ulonglong_value; 1428 return false; 1429 } 1430 bool global_update(THD *thd, set_var *var) 1431 { 1432 global_var(ulonglong)= var->save_result.ulonglong_value; 1433 return false; 1434 } 1435 void session_save_default(THD *thd, set_var *var) 1436 { var->save_result.ulonglong_value= global_var(ulonglong); } 1437 void global_save_default(THD *thd, set_var *var) 1438 { var->save_result.ulonglong_value= option.def_value; } 1439 const uchar *valptr(THD *thd, ulonglong val) const 1440 { return reinterpret_cast<const uchar*>(set_to_string(thd, 0, val, typelib.type_names)); } 1441 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 1442 { return valptr(thd, session_var(thd, ulonglong)); } 1443 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const 1444 { return valptr(thd, global_var(ulonglong)); } 1445 const uchar *default_value_ptr(THD *thd) const 1446 { return valptr(thd, option.def_value); } 1447 1448 ulonglong get_max_var() { return *((ulonglong*) max_var_ptr()); } 1449}; 1450 1451/** 1452 The class for variables which value is a plugin. 1453 Example: @@default_storage_engine 1454 1455 Class specific constructor arguments: 1456 int plugin_type_arg (for example MYSQL_STORAGE_ENGINE_PLUGIN) 1457 1458 Backing store: plugin_ref 1459 1460 @note 1461 these variables don't support command-line equivalents, any such 1462 command-line options should be added manually to my_long_options in mysqld.cc 1463*/ 1464class Sys_var_plugin: public sys_var 1465{ 1466 int plugin_type; 1467public: 1468 Sys_var_plugin(const char *name_arg, 1469 const char *comment, int flag_args, ptrdiff_t off, size_t size, 1470 CMD_LINE getopt, 1471 int plugin_type_arg, char **def_val, PolyLock *lock=0, 1472 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 1473 on_check_function on_check_func=0, 1474 on_update_function on_update_func=0, 1475 const char *substitute=0) 1476 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 1477 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 1478 lock, binlog_status_arg, on_check_func, on_update_func, 1479 substitute), 1480 plugin_type(plugin_type_arg) 1481 { 1482 option.var_type|= GET_STR; 1483 SYSVAR_ASSERT(size == sizeof(plugin_ref)); 1484 SYSVAR_ASSERT(getopt.id < 0); // force NO_CMD_LINE 1485 } 1486 bool do_check(THD *thd, set_var *var) 1487 { 1488 char buff[STRING_BUFFER_USUAL_SIZE]; 1489 String str(buff,sizeof(buff), system_charset_info), *res; 1490 if (!(res=var->value->val_str(&str))) 1491 var->save_result.plugin= NULL; 1492 else 1493 { 1494 const LEX_CSTRING pname= { const_cast<char*>(res->ptr()), res->length() }; 1495 plugin_ref plugin; 1496 1497 // special code for storage engines (e.g. to handle historical aliases) 1498 if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN) 1499 plugin= ha_resolve_by_name(thd, &pname, false); 1500 else 1501 plugin= my_plugin_lock_by_name(thd, &pname, plugin_type); 1502 if (unlikely(!plugin)) 1503 { 1504 // historically different error code 1505 if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN) 1506 { 1507 ErrConvString err(res); 1508 my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), err.ptr()); 1509 } 1510 return true; 1511 } 1512 var->save_result.plugin= plugin; 1513 } 1514 return false; 1515 } 1516 void do_update(plugin_ref *valptr, plugin_ref newval) 1517 { 1518 plugin_ref oldval= *valptr; 1519 if (oldval != newval) 1520 { 1521 *valptr= newval ? my_plugin_lock(NULL, newval) : 0; 1522 plugin_unlock(NULL, oldval); 1523 } 1524 } 1525 bool session_update(THD *thd, set_var *var) 1526 { 1527 do_update((plugin_ref*)session_var_ptr(thd), 1528 var->save_result.plugin); 1529 return false; 1530 } 1531 bool global_update(THD *thd, set_var *var) 1532 { 1533 do_update((plugin_ref*)global_var_ptr(), 1534 var->save_result.plugin); 1535 return false; 1536 } 1537 void session_save_default(THD *thd, set_var *var) 1538 { 1539 plugin_ref plugin= global_var(plugin_ref); 1540 var->save_result.plugin= plugin ? my_plugin_lock(thd, plugin) : 0; 1541 } 1542 plugin_ref get_default(THD *thd) const 1543 { 1544 char *default_value= *reinterpret_cast<char**>(option.def_value); 1545 if (!default_value) 1546 return 0; 1547 1548 LEX_CSTRING pname= { default_value, strlen(default_value) }; 1549 plugin_ref plugin; 1550 1551 if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN) 1552 plugin= ha_resolve_by_name(thd, &pname, false); 1553 else 1554 plugin= my_plugin_lock_by_name(thd, &pname, plugin_type); 1555 DBUG_ASSERT(plugin); 1556 return my_plugin_lock(thd, plugin); 1557 } 1558 1559 void global_save_default(THD *thd, set_var *var) 1560 { 1561 var->save_result.plugin= get_default(thd); 1562 } 1563 1564 uchar *valptr(THD *thd, plugin_ref plugin) const 1565 { 1566 return (uchar*)(plugin ? thd->strmake(plugin_name(plugin)->str, 1567 plugin_name(plugin)->length) : 0); 1568 } 1569 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 1570 { return valptr(thd, session_var(thd, plugin_ref)); } 1571 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const 1572 { return valptr(thd, global_var(plugin_ref)); } 1573 const uchar *default_value_ptr(THD *thd) const 1574 { return valptr(thd, get_default(thd)); } 1575}; 1576 1577/** 1578 Class for variables that containg a list of plugins. 1579 Currently this is used only for @@gtid_pos_auto_create_engines 1580 1581 Backing store: plugin_ref 1582 1583 @note 1584 Currently this is only used for storage engine type plugins, and thus only 1585 storage engine type plugin is implemented. It could be extended to other 1586 plugin types later if needed, similar to Sys_var_plugin. 1587 1588 These variables don't support command-line equivalents, any such 1589 command-line options should be added manually to my_long_options in mysqld.cc 1590 1591 Note on lifetimes of resources allocated: We allocate a zero-terminated array 1592 of plugin_ref*, and lock the contained plugins. The list in the global 1593 variable must be freed (with free_engine_list()). However, the way Sys_var 1594 works, there is no place to explicitly free other lists, like the one 1595 returned from get_default(). 1596 1597 Therefore, the code needs to work with temporary lists, which are 1598 registered in the THD to be automatically freed (and plugins similarly 1599 automatically unlocked). This is why do_check() allocates a temporary 1600 list, from which do_update() then makes a permanent copy. 1601*/ 1602class Sys_var_pluginlist: public sys_var 1603{ 1604public: 1605 Sys_var_pluginlist(const char *name_arg, 1606 const char *comment, int flag_args, ptrdiff_t off, size_t size, 1607 CMD_LINE getopt, 1608 char **def_val, PolyLock *lock=0, 1609 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 1610 on_check_function on_check_func=0, 1611 on_update_function on_update_func=0, 1612 const char *substitute=0) 1613 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 1614 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 1615 lock, binlog_status_arg, on_check_func, on_update_func, 1616 substitute) 1617 { 1618 option.var_type|= GET_STR; 1619 SYSVAR_ASSERT(size == sizeof(plugin_ref)); 1620 SYSVAR_ASSERT(getopt.id < 0); // force NO_CMD_LINE 1621 } 1622 bool do_check(THD *thd, set_var *var) 1623 { 1624 char buff[STRING_BUFFER_USUAL_SIZE]; 1625 String str(buff,sizeof(buff), system_charset_info), *res; 1626 plugin_ref *plugins; 1627 1628 if (!(res=var->value->val_str(&str))) 1629 plugins= resolve_engine_list(thd, "", 0, true, true); 1630 else 1631 plugins= resolve_engine_list(thd, res->ptr(), res->length(), true, true); 1632 if (!plugins) 1633 return true; 1634 var->save_result.plugins= plugins; 1635 return false; 1636 } 1637 void do_update(plugin_ref **valptr, plugin_ref* newval) 1638 { 1639 plugin_ref *oldval= *valptr; 1640 *valptr= copy_engine_list(newval); 1641 free_engine_list(oldval); 1642 } 1643 bool session_update(THD *thd, set_var *var) 1644 { 1645 do_update((plugin_ref**)session_var_ptr(thd), 1646 var->save_result.plugins); 1647 return false; 1648 } 1649 bool global_update(THD *thd, set_var *var) 1650 { 1651 do_update((plugin_ref**)global_var_ptr(), 1652 var->save_result.plugins); 1653 return false; 1654 } 1655 void session_save_default(THD *thd, set_var *var) 1656 { 1657 plugin_ref* plugins= global_var(plugin_ref *); 1658 var->save_result.plugins= plugins ? temp_copy_engine_list(thd, plugins) : 0; 1659 } 1660 plugin_ref *get_default(THD *thd) const 1661 { 1662 char *default_value= *reinterpret_cast<char**>(option.def_value); 1663 if (!default_value) 1664 return 0; 1665 return resolve_engine_list(thd, default_value, strlen(default_value), 1666 false, true); 1667 } 1668 1669 void global_save_default(THD *thd, set_var *var) 1670 { 1671 var->save_result.plugins= get_default(thd); 1672 } 1673 1674 uchar *valptr(THD *thd, plugin_ref *plugins) const 1675 { 1676 return reinterpret_cast<uchar*>(pretty_print_engine_list(thd, plugins)); 1677 } 1678 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 1679 { return valptr(thd, session_var(thd, plugin_ref*)); } 1680 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const 1681 { return valptr(thd, global_var(plugin_ref*)); } 1682 const uchar *default_value_ptr(THD *thd) const 1683 { return valptr(thd, get_default(thd)); } 1684}; 1685 1686#if defined(ENABLED_DEBUG_SYNC) 1687 1688#include "debug_sync.h" 1689 1690/** 1691 The class for @@debug_sync session-only variable 1692*/ 1693class Sys_var_debug_sync :public sys_var 1694{ 1695public: 1696 Sys_var_debug_sync(const char *name_arg, 1697 const char *comment, int flag_args, 1698 CMD_LINE getopt, 1699 const char *def_val, PolyLock *lock=0, 1700 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 1701 on_check_function on_check_func=0, 1702 on_update_function on_update_func=0, 1703 const char *substitute=0) 1704 : sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id, 1705 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 1706 lock, binlog_status_arg, on_check_func, on_update_func, 1707 substitute) 1708 { 1709 SYSVAR_ASSERT(scope() == ONLY_SESSION); 1710 option.var_type|= GET_STR; 1711 } 1712 bool do_check(THD *thd, set_var *var) 1713 { 1714 char buff[STRING_BUFFER_USUAL_SIZE]; 1715 String str(buff, sizeof(buff), system_charset_info), *res; 1716 1717 if (!(res=var->value->val_str(&str))) 1718 var->save_result.string_value= empty_lex_str; 1719 else 1720 { 1721 if (!thd->make_lex_string(&var->save_result.string_value, 1722 res->ptr(), res->length())) 1723 return true; 1724 } 1725 return false; 1726 } 1727 bool session_update(THD *thd, set_var *var) 1728 { 1729 return debug_sync_update(thd, var->save_result.string_value.str, 1730 var->save_result.string_value.length); 1731 } 1732 bool global_update(THD *thd, set_var *var) 1733 { 1734 DBUG_ASSERT(FALSE); 1735 return true; 1736 } 1737 void session_save_default(THD *thd, set_var *var) 1738 { 1739 var->save_result.string_value.str= const_cast<char*>(""); 1740 var->save_result.string_value.length= 0; 1741 } 1742 void global_save_default(THD *thd, set_var *var) 1743 { 1744 DBUG_ASSERT(FALSE); 1745 } 1746 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 1747 { 1748 return debug_sync_value_ptr(thd); 1749 } 1750 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const 1751 { 1752 DBUG_ASSERT(FALSE); 1753 return 0; 1754 } 1755 const uchar *default_value_ptr(THD *thd) const 1756 { return (uchar*)""; } 1757}; 1758#endif /* defined(ENABLED_DEBUG_SYNC) */ 1759 1760 1761/** 1762 The class for bit variables - a variant of boolean that stores the value 1763 in a bit. 1764 1765 Class specific constructor arguments: 1766 ulonglong bitmask_arg - the mask for the bit to set in the ulonglong 1767 backing store 1768 1769 Backing store: ulonglong 1770 1771 @note 1772 This class supports the "reverse" semantics, when the value of the bit 1773 being 0 corresponds to the value of variable being set. To activate it 1774 use REVERSE(bitmask) instead of simply bitmask in the constructor. 1775 1776 @note 1777 variables of this class cannot be set from the command line as 1778 my_getopt does not support bits. 1779*/ 1780class Sys_var_bit: public Sys_var_typelib 1781{ 1782 ulonglong bitmask; 1783 bool reverse_semantics; 1784 void set(uchar *ptr, ulonglong value) 1785 { 1786 if ((value != 0) ^ reverse_semantics) 1787 (*(ulonglong *)ptr)|= bitmask; 1788 else 1789 (*(ulonglong *)ptr)&= ~bitmask; 1790 } 1791public: 1792 Sys_var_bit(const char *name_arg, 1793 const char *comment, int flag_args, ptrdiff_t off, size_t size, 1794 CMD_LINE getopt, 1795 ulonglong bitmask_arg, my_bool def_val, PolyLock *lock=0, 1796 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 1797 on_check_function on_check_func=0, 1798 on_update_function on_update_func=0, 1799 const char *substitute=0) 1800 : Sys_var_typelib(name_arg, comment, flag_args, off, getopt, 1801 SHOW_MY_BOOL, bool_values, def_val, lock, 1802 binlog_status_arg, on_check_func, on_update_func, 1803 substitute) 1804 { 1805 option.var_type|= GET_BIT; 1806 reverse_semantics= my_count_bits(bitmask_arg) > 1; 1807 bitmask= reverse_semantics ? ~bitmask_arg : bitmask_arg; 1808 option.block_size= reverse_semantics ? -(long) bitmask : (long)bitmask; 1809 set(global_var_ptr(), def_val); 1810 SYSVAR_ASSERT(def_val < 2); 1811 SYSVAR_ASSERT(size == sizeof(ulonglong)); 1812 } 1813 bool session_update(THD *thd, set_var *var) 1814 { 1815 set(session_var_ptr(thd), var->save_result.ulonglong_value); 1816 return false; 1817 } 1818 bool global_update(THD *thd, set_var *var) 1819 { 1820 set(global_var_ptr(), var->save_result.ulonglong_value); 1821 return false; 1822 } 1823 void session_save_default(THD *thd, set_var *var) 1824 { 1825 var->save_result.ulonglong_value= 1826 (reverse_semantics == !(global_var(ulonglong) & bitmask)); 1827 } 1828 void global_save_default(THD *thd, set_var *var) 1829 { var->save_result.ulonglong_value= option.def_value; } 1830 1831 uchar *valptr(THD *thd, ulonglong val) const 1832 { 1833 thd->sys_var_tmp.my_bool_value= (reverse_semantics == !(val & bitmask)); 1834 return (uchar*) &thd->sys_var_tmp.my_bool_value; 1835 } 1836 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 1837 { return valptr(thd, session_var(thd, ulonglong)); } 1838 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const 1839 { return valptr(thd, global_var(ulonglong)); } 1840 const uchar *default_value_ptr(THD *thd) const 1841 { 1842 thd->sys_var_tmp.my_bool_value= option.def_value != 0; 1843 return (uchar*) &thd->sys_var_tmp.my_bool_value; 1844 } 1845}; 1846 1847/** 1848 The class for variables that have a special meaning for a session, 1849 such as @@timestamp or @@rnd_seed1, their values typically cannot be read 1850 from SV structure, and a special "read" callback is provided. 1851 1852 Class specific constructor arguments: 1853 everything derived from Sys_var_ulonglong 1854 session_special_read_function read_func_arg 1855 1856 Backing store: ulonglong 1857 1858 @note 1859 These variables are session-only, global or command-line equivalents 1860 are not supported as they're generally meaningless. 1861*/ 1862class Sys_var_session_special: public Sys_var_ulonglong 1863{ 1864 typedef bool (*session_special_update_function)(THD *thd, set_var *var); 1865 typedef ulonglong (*session_special_read_function)(THD *thd); 1866 1867 session_special_read_function read_func; 1868 session_special_update_function update_func; 1869public: 1870 Sys_var_session_special(const char *name_arg, 1871 const char *comment, int flag_args, 1872 CMD_LINE getopt, 1873 ulonglong min_val, ulonglong max_val, uint block_size, 1874 PolyLock *lock, enum binlog_status_enum binlog_status_arg, 1875 on_check_function on_check_func, 1876 session_special_update_function update_func_arg, 1877 session_special_read_function read_func_arg, 1878 const char *substitute=0) 1879 : Sys_var_ulonglong(name_arg, comment, flag_args, 0, 1880 sizeof(ulonglong), getopt, min_val, 1881 max_val, 0, block_size, lock, binlog_status_arg, on_check_func, 0, 1882 substitute), 1883 read_func(read_func_arg), update_func(update_func_arg) 1884 { 1885 SYSVAR_ASSERT(scope() == ONLY_SESSION); 1886 SYSVAR_ASSERT(getopt.id < 0); // NO_CMD_LINE, because the offset is fake 1887 } 1888 bool session_update(THD *thd, set_var *var) 1889 { return update_func(thd, var); } 1890 bool global_update(THD *thd, set_var *var) 1891 { 1892 DBUG_ASSERT(FALSE); 1893 return true; 1894 } 1895 void session_save_default(THD *thd, set_var *var) 1896 { var->value= 0; } 1897 void global_save_default(THD *thd, set_var *var) 1898 { DBUG_ASSERT(FALSE); } 1899 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 1900 { 1901 thd->sys_var_tmp.ulonglong_value= read_func(thd); 1902 return (uchar*) &thd->sys_var_tmp.ulonglong_value; 1903 } 1904 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const 1905 { 1906 DBUG_ASSERT(FALSE); 1907 return 0; 1908 } 1909 const uchar *default_value_ptr(THD *thd) const 1910 { 1911 thd->sys_var_tmp.ulonglong_value= 0; 1912 return (uchar*) &thd->sys_var_tmp.ulonglong_value; 1913 } 1914}; 1915 1916 1917/* 1918 Dedicated class because of a weird behavior of a default value. 1919 Assigning timestamp to itself 1920 1921 SET @@timestamp = @@timestamp 1922 1923 make it non-default and stops the time flow. 1924*/ 1925class Sys_var_timestamp: public Sys_var_double 1926{ 1927public: 1928 Sys_var_timestamp(const char *name_arg, 1929 const char *comment, int flag_args, 1930 CMD_LINE getopt, 1931 double min_val, double max_val, 1932 PolyLock *lock, enum binlog_status_enum binlog_status_arg, 1933 on_check_function on_check_func=0) 1934 : Sys_var_double(name_arg, comment, flag_args, 0, 1935 sizeof(double), getopt, min_val, 1936 max_val, 0, lock, binlog_status_arg, on_check_func) 1937 { 1938 SYSVAR_ASSERT(scope() == ONLY_SESSION); 1939 SYSVAR_ASSERT(getopt.id < 0); // NO_CMD_LINE, because the offset is fake 1940 } 1941 bool session_update(THD *thd, set_var *var) 1942 { 1943 if (var->value) 1944 { 1945 my_hrtime_t hrtime = { hrtime_from_time(var->save_result.double_value) }; 1946 thd->set_time(hrtime); 1947 } 1948 else // SET timestamp=DEFAULT 1949 thd->user_time.val= 0; 1950 return false; 1951 } 1952 bool global_update(THD *thd, set_var *var) 1953 { 1954 DBUG_ASSERT(FALSE); 1955 return true; 1956 } 1957 bool session_is_default(THD *thd) 1958 { 1959 return thd->user_time.val == 0; 1960 } 1961 void session_save_default(THD *thd, set_var *var) 1962 { var->value= 0; } 1963 void global_save_default(THD *thd, set_var *var) 1964 { DBUG_ASSERT(FALSE); } 1965 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 1966 { 1967 thd->sys_var_tmp.double_value= thd->start_time + 1968 thd->start_time_sec_part/(double)TIME_SECOND_PART_FACTOR; 1969 return (uchar*) &thd->sys_var_tmp.double_value; 1970 } 1971 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const 1972 { 1973 DBUG_ASSERT(FALSE); 1974 return 0; 1975 } 1976 const uchar *default_value_ptr(THD *thd) const 1977 { 1978 thd->sys_var_tmp.double_value= 0; 1979 return (uchar*) &thd->sys_var_tmp.double_value; 1980 } 1981}; 1982 1983 1984/** 1985 The class for read-only variables that show whether a particular 1986 feature is supported by the server. Example: have_compression 1987 1988 Backing store: enum SHOW_COMP_OPTION 1989 1990 @note 1991 These variables are necessarily read-only, only global, and have no 1992 command-line equivalent. 1993*/ 1994class Sys_var_have: public sys_var 1995{ 1996public: 1997 Sys_var_have(const char *name_arg, 1998 const char *comment, int flag_args, ptrdiff_t off, size_t size, 1999 CMD_LINE getopt, 2000 PolyLock *lock=0, 2001 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 2002 on_check_function on_check_func=0, 2003 on_update_function on_update_func=0, 2004 const char *substitute=0) 2005 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 2006 getopt.arg_type, SHOW_CHAR, 0, 2007 lock, binlog_status_arg, on_check_func, on_update_func, 2008 substitute) 2009 { 2010 SYSVAR_ASSERT(scope() == GLOBAL); 2011 SYSVAR_ASSERT(getopt.id < 0); 2012 SYSVAR_ASSERT(lock == 0); 2013 SYSVAR_ASSERT(binlog_status_arg == VARIABLE_NOT_IN_BINLOG); 2014 SYSVAR_ASSERT(is_readonly()); 2015 SYSVAR_ASSERT(on_update == 0); 2016 SYSVAR_ASSERT(size == sizeof(enum SHOW_COMP_OPTION)); 2017 option.var_type|= GET_STR; 2018 } 2019 bool do_check(THD *thd, set_var *var) { 2020 DBUG_ASSERT(FALSE); 2021 return true; 2022 } 2023 bool session_update(THD *thd, set_var *var) 2024 { 2025 DBUG_ASSERT(FALSE); 2026 return true; 2027 } 2028 bool global_update(THD *thd, set_var *var) 2029 { 2030 DBUG_ASSERT(FALSE); 2031 return true; 2032 } 2033 void session_save_default(THD *thd, set_var *var) { } 2034 void global_save_default(THD *thd, set_var *var) { } 2035 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 2036 { 2037 DBUG_ASSERT(FALSE); 2038 return 0; 2039 } 2040 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const 2041 { 2042 return (uchar*)show_comp_option_name[global_var(enum SHOW_COMP_OPTION)]; 2043 } 2044}; 2045 2046/** 2047 Generic class for variables for storing entities that are internally 2048 represented as structures, have names, and possibly can be referred to by 2049 numbers. Examples: character sets, collations, locales, 2050 2051 Class specific constructor arguments: 2052 ptrdiff_t name_offset - offset of the 'name' field in the structure 2053 2054 Backing store: void* 2055 2056 @note 2057 As every such a structure requires special treatment from my_getopt, 2058 these variables don't support command-line equivalents, any such 2059 command-line options should be added manually to my_long_options in mysqld.cc 2060*/ 2061class Sys_var_struct: public sys_var 2062{ 2063 ptrdiff_t name_offset; // offset to the 'name' property in the structure 2064public: 2065 Sys_var_struct(const char *name_arg, 2066 const char *comment, int flag_args, ptrdiff_t off, size_t size, 2067 CMD_LINE getopt, 2068 ptrdiff_t name_off, void *def_val, PolyLock *lock=0, 2069 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 2070 on_check_function on_check_func=0, 2071 on_update_function on_update_func=0, 2072 const char *substitute=0) 2073 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 2074 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 2075 lock, binlog_status_arg, on_check_func, on_update_func, 2076 substitute), 2077 name_offset(name_off) 2078 { 2079 option.var_type|= GET_ENUM; // because we accept INT and STRING here 2080 /* 2081 struct variables are special on the command line - often (e.g. for 2082 charsets) the name cannot be immediately resolved, but only after all 2083 options (in particular, basedir) are parsed. 2084 2085 thus all struct command-line options should be added manually 2086 to my_long_options in mysqld.cc 2087 */ 2088 SYSVAR_ASSERT(getopt.id < 0); 2089 SYSVAR_ASSERT(size == sizeof(void *)); 2090 } 2091 bool do_check(THD *thd, set_var *var) 2092 { return false; } 2093 bool session_update(THD *thd, set_var *var) 2094 { 2095 session_var(thd, const void*)= var->save_result.ptr; 2096 return false; 2097 } 2098 bool global_update(THD *thd, set_var *var) 2099 { 2100 global_var(const void*)= var->save_result.ptr; 2101 return false; 2102 } 2103 void session_save_default(THD *thd, set_var *var) 2104 { var->save_result.ptr= global_var(void*); } 2105 void global_save_default(THD *thd, set_var *var) 2106 { 2107 void **default_value= reinterpret_cast<void**>(option.def_value); 2108 var->save_result.ptr= *default_value; 2109 } 2110 uchar *valptr(THD *thd, uchar *val) const 2111 { return val ? *(uchar**)(val+name_offset) : 0; } 2112 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 2113 { return valptr(thd, session_var(thd, uchar*)); } 2114 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const 2115 { return valptr(thd, global_var(uchar*)); } 2116 const uchar *default_value_ptr(THD *thd) const 2117 { return valptr(thd, *(uchar**)option.def_value); } 2118}; 2119 2120/** 2121 The class for variables that store time zones 2122 2123 Backing store: Time_zone* 2124 2125 @note 2126 Time zones cannot be supported directly by my_getopt, thus 2127 these variables don't support command-line equivalents, any such 2128 command-line options should be added manually to my_long_options in mysqld.cc 2129*/ 2130class Sys_var_tz: public sys_var 2131{ 2132public: 2133 Sys_var_tz(const char *name_arg, 2134 const char *comment, int flag_args, ptrdiff_t off, size_t size, 2135 CMD_LINE getopt, 2136 Time_zone **def_val, PolyLock *lock=0, 2137 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG, 2138 on_check_function on_check_func=0, 2139 on_update_function on_update_func=0, 2140 const char *substitute=0) 2141 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 2142 getopt.arg_type, SHOW_CHAR, (intptr)def_val, 2143 lock, binlog_status_arg, on_check_func, on_update_func, 2144 substitute) 2145 { 2146 SYSVAR_ASSERT(getopt.id < 0); 2147 SYSVAR_ASSERT(size == sizeof(Time_zone *)); 2148 option.var_type|= GET_STR; 2149 } 2150 bool do_check(THD *thd, set_var *var) 2151 { 2152 char buff[MAX_TIME_ZONE_NAME_LENGTH]; 2153 String str(buff, sizeof(buff), &my_charset_latin1); 2154 String *res= var->value->val_str(&str); 2155 2156 if (!res) 2157 return true; 2158 2159 if (!(var->save_result.time_zone= my_tz_find(thd, res))) 2160 { 2161 ErrConvString err(res); 2162 my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), err.ptr()); 2163 return true; 2164 } 2165 return false; 2166 } 2167 bool session_update(THD *thd, set_var *var) 2168 { 2169 session_var(thd, Time_zone*)= var->save_result.time_zone; 2170 return false; 2171 } 2172 bool global_update(THD *thd, set_var *var) 2173 { 2174 global_var(Time_zone*)= var->save_result.time_zone; 2175 return false; 2176 } 2177 void session_save_default(THD *thd, set_var *var) 2178 { 2179 var->save_result.time_zone= global_var(Time_zone*); 2180 } 2181 void global_save_default(THD *thd, set_var *var) 2182 { 2183 var->save_result.time_zone= 2184 *(Time_zone**)(intptr)option.def_value; 2185 } 2186 const uchar *valptr(THD *thd, Time_zone *val) const 2187 { return reinterpret_cast<const uchar*>(val->get_name()->ptr()); } 2188 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 2189 { 2190 /* 2191 This is an ugly fix for replication: we don't replicate properly queries 2192 invoking system variables' values to update tables; but 2193 CONVERT_TZ(,,@@session.time_zone) is so popular that we make it 2194 replicable (i.e. we tell the binlog code to store the session 2195 timezone). If it's the global value which was used we can't replicate 2196 (binlog code stores session value only). 2197 */ 2198 thd->time_zone_used= 1; 2199 return valptr(thd, session_var(thd, Time_zone *)); 2200 } 2201 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const 2202 { return valptr(thd, global_var(Time_zone*)); } 2203 const uchar *default_value_ptr(THD *thd) const 2204 { return valptr(thd, *(Time_zone**)option.def_value); } 2205}; 2206 2207/** 2208 Special implementation for transaction isolation, that 2209 distingushes between 2210 2211 SET GLOBAL TRANSACTION ISOLATION (stored in global_system_variables) 2212 SET SESSION TRANSACTION ISOLATION (stored in thd->variables) 2213 SET TRANSACTION ISOLATION (stored in thd->tx_isolation) 2214 2215 where the last statement sets isolation level for the next transaction only 2216*/ 2217class Sys_var_tx_isolation: public Sys_var_enum 2218{ 2219public: 2220 Sys_var_tx_isolation(const char *name_arg, 2221 const char *comment, int flag_args, ptrdiff_t off, size_t size, 2222 CMD_LINE getopt, 2223 const char *values[], uint def_val, PolyLock *lock, 2224 enum binlog_status_enum binlog_status_arg, 2225 on_check_function on_check_func) 2226 :Sys_var_enum(name_arg, comment, flag_args, off, size, getopt, 2227 values, def_val, lock, binlog_status_arg, on_check_func) 2228 {} 2229 bool session_update(THD *thd, set_var *var) 2230 { 2231 if (var->type == OPT_SESSION && Sys_var_enum::session_update(thd, var)) 2232 return TRUE; 2233 if (var->type == OPT_DEFAULT || !thd->in_active_multi_stmt_transaction()) 2234 { 2235 thd->tx_isolation= (enum_tx_isolation) var->save_result.ulonglong_value; 2236 2237#ifndef EMBEDDED_LIBRARY 2238 if (var->type == OPT_DEFAULT) 2239 { 2240 enum enum_tx_isol_level l; 2241 switch (thd->tx_isolation) { 2242 case ISO_READ_UNCOMMITTED: 2243 l= TX_ISOL_UNCOMMITTED; 2244 break; 2245 case ISO_READ_COMMITTED: 2246 l= TX_ISOL_COMMITTED; 2247 break; 2248 case ISO_REPEATABLE_READ: 2249 l= TX_ISOL_REPEATABLE; 2250 break; 2251 case ISO_SERIALIZABLE: 2252 l= TX_ISOL_SERIALIZABLE; 2253 break; 2254 default: 2255 DBUG_ASSERT(0); 2256 return TRUE; 2257 } 2258 if (thd->variables.session_track_transaction_info > TX_TRACK_NONE) 2259 thd->session_tracker.transaction_info.set_isol_level(thd, l); 2260 } 2261 else if (thd->variables.session_track_transaction_info > TX_TRACK_NONE) 2262 thd->session_tracker.transaction_info.set_isol_level(thd, TX_ISOL_INHERIT); 2263#endif //EMBEDDED_LIBRARY 2264 } 2265 return FALSE; 2266 } 2267}; 2268 2269 2270/** 2271 Class representing the tx_read_only system variable for setting 2272 default transaction access mode. 2273 2274 Note that there is a special syntax - SET TRANSACTION READ ONLY 2275 (or READ WRITE) that sets the access mode for the next transaction 2276 only. 2277*/ 2278 2279class Sys_var_tx_read_only: public Sys_var_mybool 2280{ 2281public: 2282 Sys_var_tx_read_only(const char *name_arg, const char *comment, int flag_args, 2283 ptrdiff_t off, size_t size, CMD_LINE getopt, 2284 my_bool def_val, PolyLock *lock, 2285 enum binlog_status_enum binlog_status_arg, 2286 on_check_function on_check_func) 2287 :Sys_var_mybool(name_arg, comment, flag_args, off, size, getopt, 2288 def_val, lock, binlog_status_arg, on_check_func) 2289 {} 2290 virtual bool session_update(THD *thd, set_var *var); 2291}; 2292 2293/* 2294 Class for replicate_events_marked_for_skip. 2295 We need a custom update function that ensures the slave is stopped when 2296 the update is happening. 2297*/ 2298class Sys_var_replicate_events_marked_for_skip: public Sys_var_enum 2299{ 2300public: 2301 Sys_var_replicate_events_marked_for_skip(const char *name_arg, 2302 const char *comment, int flag_args, ptrdiff_t off, size_t size, 2303 CMD_LINE getopt, 2304 const char *values[], uint def_val, PolyLock *lock= 0, 2305 enum binlog_status_enum binlog_status_arg= VARIABLE_NOT_IN_BINLOG) 2306 :Sys_var_enum(name_arg, comment, flag_args, off, size, getopt, 2307 values, def_val, lock, binlog_status_arg) 2308 {} 2309 bool global_update(THD *thd, set_var *var); 2310}; 2311 2312/* 2313 Class for handing multi-source replication variables 2314 Variable values are store in Master_info, but to make it possible to 2315 access variable without locks we also store it thd->variables. 2316 These can be used as GLOBAL or SESSION, but both points to the same 2317 variable. This is to make things compatible with MySQL 5.5 where variables 2318 like sql_slave_skip_counter are GLOBAL. 2319*/ 2320 2321#define MASTER_INFO_VAR(X) my_offsetof(Master_info, X), sizeof(((Master_info *)0x10)->X) 2322class Sys_var_multi_source_ulonglong; 2323class Master_info; 2324 2325typedef bool (*on_multi_source_update_function)(sys_var *self, THD *thd, 2326 Master_info *mi); 2327bool update_multi_source_variable(sys_var *self, 2328 THD *thd, enum_var_type type); 2329 2330 2331class Sys_var_multi_source_ulonglong :public Sys_var_ulonglong 2332{ 2333 ptrdiff_t master_info_offset; 2334 on_multi_source_update_function update_multi_source_variable_func; 2335public: 2336 Sys_var_multi_source_ulonglong(const char *name_arg, 2337 const char *comment, int flag_args, 2338 ptrdiff_t off, size_t size, 2339 CMD_LINE getopt, 2340 ptrdiff_t master_info_offset_arg, 2341 size_t master_info_arg_size, 2342 ulonglong min_val, ulonglong max_val, 2343 ulonglong def_val, uint block_size, 2344 on_multi_source_update_function on_update_func) 2345 :Sys_var_ulonglong(name_arg, comment, flag_args, off, size, 2346 getopt, min_val, max_val, def_val, block_size, 2347 0, VARIABLE_NOT_IN_BINLOG, 0, update_multi_source_variable), 2348 master_info_offset(master_info_offset_arg), 2349 update_multi_source_variable_func(on_update_func) 2350 { 2351 SYSVAR_ASSERT(master_info_arg_size == size); 2352 } 2353 bool global_update(THD *thd, set_var *var) 2354 { 2355 return session_update(thd, var); 2356 } 2357 void session_save_default(THD *thd, set_var *var) 2358 { 2359 /* Use value given in variable declaration */ 2360 global_save_default(thd, var); 2361 } 2362 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 2363 { 2364 ulonglong *tmp, res; 2365 tmp= (ulonglong*) (((uchar*)&(thd->variables)) + offset); 2366 res= get_master_info_ulonglong_value(thd, master_info_offset); 2367 *tmp= res; 2368 return (uchar*) tmp; 2369 } 2370 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const 2371 { 2372 return session_value_ptr(thd, base); 2373 } 2374 ulonglong get_master_info_ulonglong_value(THD *thd, ptrdiff_t offset) const; 2375 bool update_variable(THD *thd, Master_info *mi) 2376 { 2377 return update_multi_source_variable_func(this, thd, mi); 2378 } 2379}; 2380 2381 2382/** 2383 Class for @@global.gtid_current_pos. 2384*/ 2385class Sys_var_gtid_current_pos: public sys_var 2386{ 2387public: 2388 Sys_var_gtid_current_pos(const char *name_arg, 2389 const char *comment, int flag_args, ptrdiff_t off, size_t size, 2390 CMD_LINE getopt) 2391 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 2392 getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, 2393 NULL, NULL, NULL) 2394 { 2395 SYSVAR_ASSERT(getopt.id < 0); 2396 SYSVAR_ASSERT(is_readonly()); 2397 option.var_type|= GET_STR; 2398 } 2399 bool do_check(THD *thd, set_var *var) 2400 { 2401 DBUG_ASSERT(false); 2402 return true; 2403 } 2404 bool session_update(THD *thd, set_var *var) 2405 { 2406 DBUG_ASSERT(false); 2407 return true; 2408 } 2409 bool global_update(THD *thd, set_var *var) 2410 { 2411 DBUG_ASSERT(false); 2412 return true; 2413 } 2414 void session_save_default(THD *thd, set_var *var) 2415 { 2416 DBUG_ASSERT(false); 2417 } 2418 void global_save_default(THD *thd, set_var *var) 2419 { 2420 DBUG_ASSERT(false); 2421 } 2422 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 2423 { 2424 DBUG_ASSERT(false); 2425 return NULL; 2426 } 2427 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const; 2428}; 2429 2430 2431/** 2432 Class for @@global.gtid_binlog_pos. 2433*/ 2434class Sys_var_gtid_binlog_pos: public sys_var 2435{ 2436public: 2437 Sys_var_gtid_binlog_pos(const char *name_arg, 2438 const char *comment, int flag_args, ptrdiff_t off, size_t size, 2439 CMD_LINE getopt) 2440 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 2441 getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, 2442 NULL, NULL, NULL) 2443 { 2444 SYSVAR_ASSERT(getopt.id < 0); 2445 SYSVAR_ASSERT(is_readonly()); 2446 option.var_type|= GET_STR; 2447 } 2448 bool do_check(THD *thd, set_var *var) 2449 { 2450 DBUG_ASSERT(false); 2451 return true; 2452 } 2453 bool session_update(THD *thd, set_var *var) 2454 { 2455 DBUG_ASSERT(false); 2456 return true; 2457 } 2458 bool global_update(THD *thd, set_var *var) 2459 { 2460 DBUG_ASSERT(false); 2461 return true; 2462 } 2463 void session_save_default(THD *thd, set_var *var) 2464 { 2465 DBUG_ASSERT(false); 2466 } 2467 void global_save_default(THD *thd, set_var *var) 2468 { 2469 DBUG_ASSERT(false); 2470 } 2471 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 2472 { 2473 DBUG_ASSERT(false); 2474 return NULL; 2475 } 2476 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const; 2477}; 2478 2479 2480/** 2481 Class for @@global.gtid_slave_pos. 2482*/ 2483class Sys_var_gtid_slave_pos: public sys_var 2484{ 2485public: 2486 Sys_var_gtid_slave_pos(const char *name_arg, 2487 const char *comment, int flag_args, ptrdiff_t off, size_t size, 2488 CMD_LINE getopt) 2489 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 2490 getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, 2491 NULL, NULL, NULL) 2492 { 2493 option.var_type|= GET_STR; 2494 } 2495 bool do_check(THD *thd, set_var *var); 2496 bool session_update(THD *thd, set_var *var) 2497 { 2498 DBUG_ASSERT(false); 2499 return true; 2500 } 2501 bool global_update(THD *thd, set_var *var); 2502 void session_save_default(THD *thd, set_var *var) 2503 { 2504 DBUG_ASSERT(false); 2505 } 2506 void global_save_default(THD *thd, set_var *var) 2507 { 2508 /* Record the attempt to use default so we can error. */ 2509 var->value= 0; 2510 } 2511 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 2512 { 2513 DBUG_ASSERT(false); 2514 return NULL; 2515 } 2516 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const; 2517 const uchar *default_value_ptr(THD *thd) const 2518 { return 0; } 2519}; 2520 2521 2522/** 2523 Class for @@global.gtid_binlog_state. 2524*/ 2525class Sys_var_gtid_binlog_state: public sys_var 2526{ 2527public: 2528 Sys_var_gtid_binlog_state(const char *name_arg, 2529 const char *comment, int flag_args, ptrdiff_t off, size_t size, 2530 CMD_LINE getopt) 2531 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id, 2532 getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, 2533 NULL, NULL, NULL) 2534 { 2535 option.var_type|= GET_STR; 2536 } 2537 bool do_check(THD *thd, set_var *var); 2538 bool session_update(THD *thd, set_var *var) 2539 { 2540 DBUG_ASSERT(false); 2541 return true; 2542 } 2543 bool global_update(THD *thd, set_var *var); 2544 void session_save_default(THD *thd, set_var *var) 2545 { 2546 DBUG_ASSERT(false); 2547 } 2548 void global_save_default(THD *thd, set_var *var) 2549 { 2550 /* Record the attempt to use default so we can error. */ 2551 var->value= 0; 2552 } 2553 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 2554 { 2555 DBUG_ASSERT(false); 2556 return NULL; 2557 } 2558 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const; 2559 const uchar *default_value_ptr(THD *thd) const 2560 { return 0; } 2561}; 2562 2563 2564/** 2565 Class for @@session.last_gtid. 2566*/ 2567class Sys_var_last_gtid: public sys_var 2568{ 2569public: 2570 Sys_var_last_gtid(const char *name_arg, 2571 const char *comment, int flag_args, CMD_LINE getopt) 2572 : sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id, 2573 getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG, 2574 NULL, NULL, NULL) 2575 { 2576 SYSVAR_ASSERT(getopt.id < 0); 2577 SYSVAR_ASSERT(is_readonly()); 2578 option.var_type|= GET_STR; 2579 } 2580 bool do_check(THD *thd, set_var *var) 2581 { 2582 DBUG_ASSERT(false); 2583 return true; 2584 } 2585 bool session_update(THD *thd, set_var *var) 2586 { 2587 DBUG_ASSERT(false); 2588 return true; 2589 } 2590 bool global_update(THD *thd, set_var *var) 2591 { 2592 DBUG_ASSERT(false); 2593 return true; 2594 } 2595 void session_save_default(THD *thd, set_var *var) 2596 { 2597 DBUG_ASSERT(false); 2598 } 2599 void global_save_default(THD *thd, set_var *var) 2600 { 2601 DBUG_ASSERT(false); 2602 } 2603 const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const; 2604 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const 2605 { 2606 DBUG_ASSERT(false); 2607 return NULL; 2608 } 2609}; 2610 2611 2612/** 2613 Class for connection_name.slave_parallel_mode. 2614*/ 2615class Sys_var_slave_parallel_mode: public Sys_var_enum 2616{ 2617public: 2618 Sys_var_slave_parallel_mode(const char *name_arg, 2619 const char *comment, int flag_args, ptrdiff_t off, size_t size, 2620 CMD_LINE getopt, const char *values[], 2621 enum_slave_parallel_mode def_val) 2622 : Sys_var_enum(name_arg, comment, flag_args, off, size, 2623 getopt, values, def_val) 2624 { 2625 option.var_type|= GET_ASK_ADDR; 2626 option.value= (uchar**)1; // crash me, please 2627 SYSVAR_ASSERT(scope() == GLOBAL); 2628 } 2629 bool global_update(THD *thd, set_var *var); 2630 const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const; 2631}; 2632 2633 2634class Sys_var_vers_asof: public sys_var 2635{ 2636public: 2637 Sys_var_vers_asof(const char *name_arg, 2638 const char *comment, int flag_args, ptrdiff_t off, size_t size, 2639 CMD_LINE getopt, uint def_val, 2640 PolyLock *lock= NO_MUTEX_GUARD, 2641 binlog_status_enum binlog_status_arg= VARIABLE_NOT_IN_BINLOG, 2642 on_check_function on_check_func= NULL, 2643 on_update_function on_update_func= NULL, 2644 const char *substitute= NULL) 2645 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, 2646 getopt.id, getopt.arg_type, SHOW_CHAR, def_val, lock, 2647 binlog_status_arg, on_check_func, on_update_func, substitute) 2648 { 2649 option.var_type= GET_STR; 2650 } 2651 virtual bool do_check(THD *thd, set_var *var) 2652 { 2653 if (!var->value) 2654 return false; 2655 2656 MYSQL_TIME ltime; 2657 bool res= var->value->get_date(<ime, 2658 TIME_NO_ZERO_IN_DATE | TIME_NO_ZERO_DATE); 2659 if (!res) 2660 { 2661 uint error; 2662 var->save_result.timestamp.unix_time= 2663 thd->variables.time_zone->TIME_to_gmt_sec(<ime, &error); 2664 var->save_result.timestamp.second_part= ltime.second_part; 2665 res= error != 0; 2666 } 2667 return res; 2668 } 2669 2670private: 2671 static bool update(THD *thd, set_var *var, vers_asof_timestamp_t *out) 2672 { 2673 if (var->value) 2674 { 2675 out->type = SYSTEM_TIME_AS_OF; 2676 out->unix_time = var->save_result.timestamp.unix_time; 2677 out->second_part= var->save_result.timestamp.second_part; 2678 } 2679 return 0; 2680 } 2681 2682 static void save_default(set_var *var, vers_asof_timestamp_t *out) 2683 { 2684 out->type= SYSTEM_TIME_UNSPECIFIED; 2685 } 2686 2687public: 2688 virtual bool global_update(THD *thd, set_var *var) 2689 { 2690 return update(thd, var, &global_var(vers_asof_timestamp_t)); 2691 } 2692 virtual bool session_update(THD *thd, set_var *var) 2693 { 2694 return update(thd, var, &session_var(thd, vers_asof_timestamp_t)); 2695 } 2696 2697 virtual bool session_is_default(THD *thd) 2698 { 2699 const vers_asof_timestamp_t &var= session_var(thd, vers_asof_timestamp_t); 2700 return var.type == SYSTEM_TIME_UNSPECIFIED; 2701 } 2702 2703 virtual void session_save_default(THD *thd, set_var *var) 2704 { 2705 save_default(var, &session_var(thd, vers_asof_timestamp_t)); 2706 } 2707 virtual void global_save_default(THD *thd, set_var *var) 2708 { 2709 save_default(var, &global_var(vers_asof_timestamp_t)); 2710 } 2711 2712private: 2713 const uchar *value_ptr(THD *thd, vers_asof_timestamp_t &val) const 2714 { 2715 const char *value; 2716 switch (val.type) 2717 { 2718 case SYSTEM_TIME_UNSPECIFIED: 2719 return (uchar*)"DEFAULT"; 2720 break; 2721 case SYSTEM_TIME_AS_OF: 2722 { 2723 char *buf= (char*) thd->alloc(MAX_DATE_STRING_REP_LENGTH); 2724 MYSQL_TIME ltime; 2725 2726 thd->variables.time_zone->gmt_sec_to_TIME(<ime, val.unix_time); 2727 ltime.second_part= val.second_part; 2728 2729 value= buf; 2730 if (buf && !my_datetime_to_str(<ime, buf, 6)) 2731 { 2732 my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, "NULL (wrong datetime)"); 2733 value= thd->strdup("Error: wrong datetime"); 2734 } 2735 break; 2736 } 2737 default: 2738 my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, "NULL (wrong range type)"); 2739 value= thd->strdup("Error: wrong range type"); 2740 } 2741 return reinterpret_cast<const uchar *>(value); 2742 } 2743 2744public: 2745 virtual const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const 2746 { return value_ptr(thd, session_var(thd, vers_asof_timestamp_t)); } 2747 virtual const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const 2748 { return value_ptr(thd, global_var(vers_asof_timestamp_t)); } 2749}; 2750