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