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