1 #ifndef SET_VAR_INCLUDED 2 #define SET_VAR_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 "public" interface to sys_var - server configuration variables. 28 */ 29 30 #include "my_config.h" 31 32 #include <stddef.h> 33 #include <string.h> 34 #include <sys/types.h> 35 #include <string> 36 #include <vector> 37 38 #include "lex_string.h" 39 #include "m_ctype.h" 40 #include "my_getopt.h" // get_opt_arg_type 41 #include "my_hostname.h" // HOSTNAME_LENGTH 42 #include "my_inttypes.h" 43 #include "my_sys.h" 44 #include "my_systime.h" // my_micro_time() 45 #include "mysql/components/services/system_variable_source_type.h" 46 #include "mysql/status_var.h" 47 #include "mysql/udf_registration_types.h" 48 #include "mysql_com.h" // Item_result 49 #include "prealloced_array.h" // Prealloced_array 50 #include "sql/sql_const.h" // SHOW_COMP_OPTION 51 #include "sql/sql_plugin_ref.h" // plugin_ref 52 #include "typelib.h" // TYPELIB 53 54 class Item; 55 class Item_func_set_user_var; 56 class PolyLock; 57 class String; 58 class THD; 59 class Time_zone; 60 class set_var; 61 class sys_var; 62 class sys_var_pluginvar; 63 struct LEX_USER; 64 template <class Key, class Value> 65 class collation_unordered_map; 66 67 typedef ulonglong sql_mode_t; 68 typedef enum enum_mysql_show_type SHOW_TYPE; 69 typedef enum enum_mysql_show_scope SHOW_SCOPE; 70 template <class T> 71 class List; 72 73 extern TYPELIB bool_typelib; 74 75 /* Number of system variable elements to preallocate. */ 76 #define SHOW_VAR_PREALLOC 200 77 typedef Prealloced_array<SHOW_VAR, SHOW_VAR_PREALLOC> Show_var_array; 78 79 struct sys_var_chain { 80 sys_var *first; 81 sys_var *last; 82 }; 83 84 int mysql_add_sys_var_chain(sys_var *chain); 85 int mysql_del_sys_var_chain(sys_var *chain); 86 87 enum enum_var_type : int { 88 OPT_DEFAULT = 0, 89 OPT_SESSION, 90 OPT_GLOBAL, 91 OPT_PERSIST, 92 OPT_PERSIST_ONLY 93 }; 94 95 /** 96 A class representing one system variable - that is something 97 that can be accessed as @@global.variable_name or @@session.variable_name, 98 visible in SHOW xxx VARIABLES and in INFORMATION_SCHEMA.xxx_VARIABLES, 99 optionally it can be assigned to, optionally it can have a command-line 100 counterpart with the same name. 101 */ 102 class sys_var { 103 public: 104 sys_var *next; 105 LEX_CSTRING name; 106 enum flag_enum { 107 GLOBAL = 0x0001, 108 SESSION = 0x0002, 109 ONLY_SESSION = 0x0004, 110 SCOPE_MASK = 0x03FF, // 1023 111 READONLY = 0x0400, // 1024 112 ALLOCATED = 0x0800, // 2048 113 INVISIBLE = 0x1000, // 4096 114 TRI_LEVEL = 0x2000, // 8192 - default is neither GLOBAL nor SESSION 115 NOTPERSIST = 0x4000, 116 HINT_UPDATEABLE = 0x8000, // Variable is updateable using SET_VAR hint 117 /** 118 There can be some variables which needs to be set before plugin is loaded. 119 ex: binlog_checksum needs to be set before GR plugin is loaded. 120 Also, there are some variables which needs to be set before some server 121 internal component initialization. 122 ex: binlog_encryption needs to be set before binary and relay log 123 files generation. 124 */ 125 126 PERSIST_AS_READ_ONLY = 0x10000 127 }; 128 static const int PARSE_EARLY = 1; 129 static const int PARSE_NORMAL = 2; 130 /** 131 Enumeration type to indicate for a system variable whether 132 it will be written to the binlog or not. 133 */ 134 enum binlog_status_enum { 135 VARIABLE_NOT_IN_BINLOG, 136 SESSION_VARIABLE_IN_BINLOG 137 } binlog_status; 138 139 protected: 140 typedef bool (*on_check_function)(sys_var *self, THD *thd, set_var *var); 141 typedef bool (*on_update_function)(sys_var *self, THD *thd, 142 enum_var_type type); 143 144 int flags; ///< or'ed flag_enum values 145 int m_parse_flag; ///< either PARSE_EARLY or PARSE_NORMAL. 146 const SHOW_TYPE show_val_type; ///< what value_ptr() returns for sql_show.cc 147 my_option option; ///< min, max, default values are stored here 148 PolyLock *guard; ///< *second* lock that protects the variable 149 ptrdiff_t offset; ///< offset to the value from global_system_variables 150 on_check_function on_check; 151 on_update_function on_update; 152 const char *const deprecation_substitute; 153 bool is_os_charset; ///< true if the value is in character_set_filesystem 154 struct get_opt_arg_source source; 155 char user[USERNAME_CHAR_LENGTH + 1]; /* which user has set this variable */ 156 char host[HOSTNAME_LENGTH + 1]; /* host on which this variable is set */ 157 ulonglong timestamp; /* represents when this variable was set */ 158 159 public: 160 sys_var(sys_var_chain *chain, const char *name_arg, const char *comment, 161 int flag_args, ptrdiff_t off, int getopt_id, 162 enum get_opt_arg_type getopt_arg_type, SHOW_TYPE show_val_type_arg, 163 longlong def_val, PolyLock *lock, 164 enum binlog_status_enum binlog_status_arg, 165 on_check_function on_check_func, on_update_function on_update_func, 166 const char *substitute, int parse_flag); 167 ~sys_var()168 virtual ~sys_var() {} 169 170 /** 171 All the cleanup procedures should be performed here 172 */ cleanup()173 virtual void cleanup() {} 174 /** 175 downcast for sys_var_pluginvar. Returns this if it's an instance 176 of sys_var_pluginvar, and 0 otherwise. 177 */ cast_pluginvar()178 virtual sys_var_pluginvar *cast_pluginvar() { return nullptr; } 179 180 bool check(THD *thd, set_var *var); 181 const uchar *value_ptr(THD *running_thd, THD *target_thd, enum_var_type type, 182 LEX_STRING *base); 183 const uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); update_default(longlong new_def_value)184 virtual void update_default(longlong new_def_value) { 185 option.def_value = new_def_value; 186 } get_default()187 longlong get_default() { return option.def_value; } get_min_value()188 virtual longlong get_min_value() { return option.min_value; } get_max_value()189 virtual ulonglong get_max_value() { return option.max_value; } 190 /** 191 Returns variable type. 192 193 @return variable type 194 */ get_var_type()195 virtual ulong get_var_type() { return (option.var_type & GET_TYPE_MASK); } set_arg_source(get_opt_arg_source *)196 virtual void set_arg_source(get_opt_arg_source *) {} set_is_plugin(bool)197 virtual void set_is_plugin(bool) {} get_source()198 enum_variable_source get_source() { return source.m_source; } get_source_name()199 const char *get_source_name() { return source.m_path_name; } set_source(enum_variable_source src)200 void set_source(enum_variable_source src) { 201 option.arg_source->m_source = src; 202 } set_source_name(const char * path)203 bool set_source_name(const char *path) { 204 return set_and_truncate(option.arg_source->m_path_name, path, 205 sizeof(option.arg_source->m_path_name)); 206 } set_user(const char * usr)207 bool set_user(const char *usr) { 208 return set_and_truncate(user, usr, sizeof(user)); 209 } get_user()210 const char *get_user() { return user; } get_host()211 const char *get_host() { return host; } set_host(const char * hst)212 bool set_host(const char *hst) { 213 return set_and_truncate(host, hst, sizeof(host)); 214 } get_timestamp()215 ulonglong get_timestamp() const { return timestamp; } 216 void set_user_host(THD *thd); get_option()217 my_option *get_option() { return &option; } set_timestamp()218 void set_timestamp() { timestamp = my_micro_time(); } set_timestamp(ulonglong ts)219 void set_timestamp(ulonglong ts) { timestamp = ts; } clear_user_host_timestamp()220 void clear_user_host_timestamp() { 221 user[0] = '\0'; 222 host[0] = '\0'; 223 timestamp = 0; 224 } is_non_persistent()225 virtual bool is_non_persistent() { return flags & NOTPERSIST; } 226 227 /** 228 Update the system variable with the default value from either 229 session or global scope. The default value is stored in the 230 'var' argument. Return false when successful. 231 */ 232 bool set_default(THD *thd, set_var *var); 233 bool update(THD *thd, set_var *var); 234 235 /** 236 This function converts value stored in save_result to string. This 237 function must ba called after calling save_default() as save_default() will 238 store default value to save_result. 239 */ 240 virtual void saved_value_to_string(THD *thd, set_var *var, char *def_val) = 0; 241 show_type()242 SHOW_TYPE show_type() { return show_val_type; } scope()243 int scope() const { return flags & SCOPE_MASK; } 244 const CHARSET_INFO *charset(THD *thd); is_readonly()245 bool is_readonly() const { return flags & READONLY; } not_visible()246 bool not_visible() const { return flags & INVISIBLE; } is_trilevel()247 bool is_trilevel() const { return flags & TRI_LEVEL; } is_persist_readonly()248 bool is_persist_readonly() const { return flags & PERSIST_AS_READ_ONLY; } 249 /** 250 Check if the variable can be set using SET_VAR hint. 251 252 @return true if the variable can be set using SET_VAR hint, 253 false otherwise. 254 */ is_hint_updateable()255 bool is_hint_updateable() const { return flags & HINT_UPDATEABLE; } 256 /** 257 the following is only true for keycache variables, 258 that support the syntax @@keycache_name.variable_name 259 */ is_struct()260 bool is_struct() { return option.var_type & GET_ASK_ADDR; } is_written_to_binlog(enum_var_type type)261 bool is_written_to_binlog(enum_var_type type) { 262 return type != OPT_GLOBAL && binlog_status == SESSION_VARIABLE_IN_BINLOG; 263 } 264 virtual bool check_update_type(Item_result type) = 0; 265 266 /** 267 Return true for success if: 268 Global query and variable scope is GLOBAL or SESSION, or 269 Session query and variable scope is SESSION or ONLY_SESSION. 270 */ check_scope(enum_var_type query_type)271 bool check_scope(enum_var_type query_type) { 272 switch (query_type) { 273 case OPT_PERSIST: 274 case OPT_PERSIST_ONLY: 275 case OPT_GLOBAL: 276 return scope() & (GLOBAL | SESSION); 277 case OPT_SESSION: 278 return scope() & (SESSION | ONLY_SESSION); 279 case OPT_DEFAULT: 280 return scope() & (SESSION | ONLY_SESSION); 281 } 282 return false; 283 } is_global_persist(enum_var_type type)284 bool is_global_persist(enum_var_type type) { 285 return (type == OPT_GLOBAL || type == OPT_PERSIST || 286 type == OPT_PERSIST_ONLY); 287 } 288 289 /** 290 Return true if settable at the command line 291 */ is_settable_at_command_line()292 bool is_settable_at_command_line() { return option.id != -1; } 293 register_option(std::vector<my_option> * array,int parse_flags)294 bool register_option(std::vector<my_option> *array, int parse_flags) { 295 return is_settable_at_command_line() && (m_parse_flag & parse_flags) && 296 (array->push_back(option), false); 297 } 298 void do_deprecated_warning(THD *thd); 299 /** 300 Create item from system variable value. 301 302 @param thd pointer to THD object 303 304 @return pointer to Item object or NULL if it's 305 impossible to obtain the value. 306 */ 307 Item *copy_value(THD *thd); 308 save_default(THD * thd,set_var * var)309 void save_default(THD *thd, set_var *var) { global_save_default(thd, var); } 310 311 private: set_and_truncate(char * dst,const char * string,size_t sizeof_dst)312 inline static bool set_and_truncate(char *dst, const char *string, 313 size_t sizeof_dst) { 314 size_t string_length = strlen(string), length; 315 length = std::min(sizeof_dst - 1, string_length); 316 memcpy(dst, string, length); 317 dst[length] = 0; 318 return length < string_length; // truncated 319 } 320 virtual bool do_check(THD *thd, set_var *var) = 0; 321 /** 322 save the session default value of the variable in var 323 */ 324 virtual void session_save_default(THD *thd, set_var *var) = 0; 325 /** 326 save the global default value of the variable in var 327 */ 328 virtual void global_save_default(THD *thd, set_var *var) = 0; 329 virtual bool session_update(THD *thd, set_var *var) = 0; 330 virtual bool global_update(THD *thd, set_var *var) = 0; 331 332 protected: 333 /** 334 A pointer to a value of the variable for SHOW. 335 It must be of show_val_type type (bool for SHOW_BOOL, int for SHOW_INT, 336 longlong for SHOW_LONGLONG, etc). 337 */ 338 virtual const uchar *session_value_ptr(THD *running_thd, THD *target_thd, 339 LEX_STRING *base); 340 virtual const uchar *global_value_ptr(THD *thd, LEX_STRING *base); 341 342 /** 343 A pointer to a storage area of the variable, to the raw data. 344 Typically it's the same as session_value_ptr(), but it's different, 345 for example, for ENUM, that is printed as a string, but stored as a number. 346 */ 347 uchar *session_var_ptr(THD *thd); 348 349 uchar *global_var_ptr(); 350 }; 351 352 /**************************************************************************** 353 Classes for parsing of the SET command 354 ****************************************************************************/ 355 356 /** 357 A base class for everything that can be set with SET command. 358 It's similar to Items, an instance of this is created by the parser 359 for every assigmnent in SET (or elsewhere, e.g. in SELECT). 360 */ 361 class set_var_base { 362 public: set_var_base()363 set_var_base() {} ~set_var_base()364 virtual ~set_var_base() {} 365 virtual int resolve(THD *thd) = 0; ///< Check privileges & fix_fields 366 virtual int check(THD *thd) = 0; ///< Evaluate the expression 367 virtual int update(THD *thd) = 0; ///< Set the value 368 virtual void print(const THD *thd, String *str) = 0; ///< To self-print 369 370 /** 371 @returns whether this variable is @@@@optimizer_trace. 372 */ is_var_optimizer_trace()373 virtual bool is_var_optimizer_trace() const { return false; } 374 375 /** 376 Used only by prepared statements to resolve and check. No locking of tables 377 between the two phases. 378 */ light_check(THD * thd)379 virtual int light_check(THD *thd) { return (resolve(thd) || check(thd)); } 380 }; 381 382 /** 383 set_var_base descendant for assignments to the system variables. 384 */ 385 class set_var : public set_var_base { 386 public: 387 sys_var *var; ///< system variable to be updated 388 Item *value; ///< the expression that provides the new value of the variable 389 enum_var_type type; 390 union ///< temp storage to hold a value between sys_var::check and ::update 391 { 392 ulonglong ulonglong_value; ///< for all integer, set, enum sysvars 393 double double_value; ///< for Sys_var_double 394 plugin_ref plugin; ///< for Sys_var_plugin 395 Time_zone *time_zone; ///< for Sys_var_tz 396 LEX_STRING string_value; ///< for Sys_var_charptr and others 397 const void *ptr; ///< for Sys_var_struct 398 } save_result; 399 LEX_CSTRING 400 base; /**< for structured variables, like keycache_name.variable_name */ 401 402 set_var(enum_var_type type_arg, sys_var *var_arg, LEX_CSTRING base_name_arg, 403 Item *value_arg); 404 405 int resolve(THD *thd); 406 int check(THD *thd); 407 int update(THD *thd); 408 void update_source_user_host_timestamp(THD *thd); 409 int light_check(THD *thd); 410 /** 411 Print variable in short form. 412 413 @param thd Thread handle. 414 @param str String buffer to append the partial assignment to. 415 */ 416 void print_short(const THD *thd, String *str); 417 void print(const THD *, String *str); /* To self-print */ is_global_persist()418 bool is_global_persist() { 419 return (type == OPT_GLOBAL || type == OPT_PERSIST || 420 type == OPT_PERSIST_ONLY); 421 } is_var_optimizer_trace()422 virtual bool is_var_optimizer_trace() const { 423 extern sys_var *Sys_optimizer_trace_ptr; 424 return var == Sys_optimizer_trace_ptr; 425 } 426 }; 427 428 /* User variables like @my_own_variable */ 429 class set_var_user : public set_var_base { 430 Item_func_set_user_var *user_var_item; 431 432 public: set_var_user(Item_func_set_user_var * item)433 set_var_user(Item_func_set_user_var *item) : user_var_item(item) {} 434 int resolve(THD *thd); 435 int check(THD *thd); 436 int update(THD *thd); 437 int light_check(THD *thd); 438 void print(const THD *thd, String *str); /* To self-print */ 439 }; 440 441 class set_var_password : public set_var_base { 442 LEX_USER *user; 443 char *password; 444 const char *current_password; 445 bool retain_current_password; 446 bool generate_password; 447 char *str_generated_password; 448 449 public: 450 set_var_password(LEX_USER *user_arg, char *password_arg, 451 char *current_password_arg, bool retain_current, 452 bool generate_password); 453 get_user(void)454 const LEX_USER *get_user(void) { return user; } has_generated_password(void)455 bool has_generated_password(void) { return generate_password; } get_generated_password(void)456 const char *get_generated_password(void) { return str_generated_password; } resolve(THD *)457 int resolve(THD *) { return 0; } 458 int check(THD *thd); 459 int update(THD *thd); 460 void print(const THD *thd, String *str); /* To self-print */ 461 virtual ~set_var_password(); 462 }; 463 464 /* For SET NAMES and SET CHARACTER SET */ 465 466 class set_var_collation_client : public set_var_base { 467 int set_cs_flags; 468 const CHARSET_INFO *character_set_client; 469 const CHARSET_INFO *character_set_results; 470 const CHARSET_INFO *collation_connection; 471 472 public: 473 enum set_cs_flags_enum { 474 SET_CS_NAMES = 1, 475 SET_CS_DEFAULT = 2, 476 SET_CS_COLLATE = 4 477 }; set_var_collation_client(int set_cs_flags_arg,const CHARSET_INFO * client_coll_arg,const CHARSET_INFO * connection_coll_arg,const CHARSET_INFO * result_coll_arg)478 set_var_collation_client(int set_cs_flags_arg, 479 const CHARSET_INFO *client_coll_arg, 480 const CHARSET_INFO *connection_coll_arg, 481 const CHARSET_INFO *result_coll_arg) 482 : set_cs_flags(set_cs_flags_arg), 483 character_set_client(client_coll_arg), 484 character_set_results(result_coll_arg), 485 collation_connection(connection_coll_arg) {} resolve(THD *)486 int resolve(THD *) { return 0; } 487 int check(THD *thd); 488 int update(THD *thd); 489 void print(const THD *thd, String *str); /* To self-print */ 490 }; 491 492 /* optional things, have_* variables */ 493 extern SHOW_COMP_OPTION have_profiling; 494 495 extern SHOW_COMP_OPTION have_symlink, have_dlopen; 496 extern SHOW_COMP_OPTION have_query_cache; 497 extern SHOW_COMP_OPTION have_geometry, have_rtree_keys; 498 extern SHOW_COMP_OPTION have_compress; 499 extern SHOW_COMP_OPTION have_statement_timeout; 500 501 /* 502 Helper functions 503 */ 504 ulong get_system_variable_hash_records(void); 505 ulonglong get_system_variable_hash_version(void); 506 collation_unordered_map<std::string, sys_var *> *get_system_variable_hash(void); 507 508 extern bool get_sysvar_source(const char *name, uint length, 509 enum enum_variable_source *source); 510 511 bool enumerate_sys_vars(Show_var_array *show_var_array, bool sort, 512 enum enum_var_type type, bool strict); 513 void lock_plugin_mutex(); 514 void unlock_plugin_mutex(); 515 sys_var *find_sys_var(THD *thd, const char *str, size_t length = 0); 516 sys_var *find_sys_var_ex(THD *thd, const char *str, size_t length = 0, 517 bool throw_error = false, bool locked = false); 518 int sql_set_variables(THD *thd, List<set_var_base> *var_list, bool opened); 519 bool keyring_access_test(); 520 bool fix_delay_key_write(sys_var *self, THD *thd, enum_var_type type); 521 522 sql_mode_t expand_sql_mode(sql_mode_t sql_mode, THD *thd); 523 bool sql_mode_string_representation(THD *thd, sql_mode_t sql_mode, 524 LEX_STRING *ls); 525 bool sql_mode_quoted_string_representation(THD *thd, sql_mode_t sql_mode, 526 LEX_STRING *ls); 527 void update_parser_max_mem_size(); 528 529 extern sys_var *Sys_autocommit_ptr; 530 extern sys_var *Sys_gtid_next_ptr; 531 extern sys_var *Sys_gtid_next_list_ptr; 532 extern sys_var *Sys_gtid_purged_ptr; 533 534 extern ulonglong system_variable_hash_version; 535 536 const CHARSET_INFO *get_old_charset_by_name(const char *old_name); 537 538 int sys_var_init(); 539 int sys_var_add_options(std::vector<my_option> *long_options, int parse_flags); 540 void sys_var_end(void); 541 542 /* check needed privileges to perform SET PERSIST[_only] or RESET PERSIST */ 543 bool check_priv(THD *thd, bool static_variable); 544 545 #define PERSIST_ONLY_ADMIN_X509_SUBJECT "persist_only_admin_x509_subject" 546 #define PERSISTED_GLOBALS_LOAD "persisted_globals_load" 547 extern char *sys_var_persist_only_admin_x509_subject; 548 549 #endif 550