1 #ifndef SET_VAR_INCLUDED
2 #define SET_VAR_INCLUDED
3 /* Copyright (c) 2002, 2013, Oracle and/or its affiliates.
4    Copyright (c) 2009, 2020, MariaDB
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; version 2 of the License.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1335  USA */
18 
19 /**
20   @file
21   "public" interface to sys_var - server configuration variables.
22 */
23 
24 #ifdef USE_PRAGMA_INTERFACE
25 #pragma interface                       /* gcc class implementation */
26 #endif
27 
28 #include <my_getopt.h>
29 
30 class sys_var;
31 class set_var;
32 class sys_var_pluginvar;
33 class PolyLock;
34 class Item_func_set_user_var;
35 
36 // This include needs to be here since item.h requires enum_var_type :-P
37 #include "item.h"                          /* Item */
38 #include "sql_class.h"                     /* THD  */
39 
40 extern TYPELIB bool_typelib;
41 
42 struct sys_var_chain
43 {
44   sys_var *first;
45   sys_var *last;
46 };
47 
48 int mysql_add_sys_var_chain(sys_var *chain);
49 int mysql_del_sys_var_chain(sys_var *chain);
50 
51 
52 /**
53   A class representing one system variable - that is something
54   that can be accessed as @@global.variable_name or @@session.variable_name,
55   visible in SHOW xxx VARIABLES and in INFORMATION_SCHEMA.xxx_VARIABLES,
56   optionally it can be assigned to, optionally it can have a command-line
57   counterpart with the same name.
58 */
59 class sys_var: protected Value_source // for double_from_string_with_check
60 {
61 public:
62   sys_var *next;
63   LEX_CSTRING name;
64   bool *test_load;
65   enum flag_enum { GLOBAL, SESSION, ONLY_SESSION, SCOPE_MASK=1023,
66                    READONLY=1024, ALLOCATED=2048, PARSE_EARLY=4096,
67                    NO_SET_STATEMENT=8192, AUTO_SET=16384};
68   enum { NO_GETOPT=-1, GETOPT_ONLY_HELP=-2 };
69   enum where { CONFIG, COMMAND_LINE, AUTO, SQL, COMPILE_TIME, ENV };
70 
71   /**
72     Enumeration type to indicate for a system variable whether
73     it will be written to the binlog or not.
74   */
75   enum binlog_status_enum { VARIABLE_NOT_IN_BINLOG,
76                             SESSION_VARIABLE_IN_BINLOG } binlog_status;
77 
78   my_option option;     ///< min, max, default values are stored here
79   enum where value_origin;
80   const char *origin_filename;
81 
82 protected:
83   typedef bool (*on_check_function)(sys_var *self, THD *thd, set_var *var);
84   typedef bool (*on_update_function)(sys_var *self, THD *thd, enum_var_type type);
85 
86   int flags;            ///< or'ed flag_enum values
87   const SHOW_TYPE show_val_type; ///< what value_ptr() returns for sql_show.cc
88   PolyLock *guard;      ///< *second* lock that protects the variable
89   ptrdiff_t offset;     ///< offset to the value from global_system_variables
90   on_check_function on_check;
91   on_update_function on_update;
92   const char *const deprecation_substitute;
93 
94 public:
95   sys_var(sys_var_chain *chain, const char *name_arg, const char *comment,
96           int flag_args, ptrdiff_t off, int getopt_id,
97           enum get_opt_arg_type getopt_arg_type, SHOW_TYPE show_val_type_arg,
98           longlong def_val, PolyLock *lock, enum binlog_status_enum binlog_status_arg,
99           on_check_function on_check_func, on_update_function on_update_func,
100           const char *substitute);
101 
~sys_var()102   virtual ~sys_var() {}
103 
104   /**
105     All the cleanup procedures should be performed here
106   */
cleanup()107   virtual void cleanup() {}
108   /**
109     downcast for sys_var_pluginvar. Returns this if it's an instance
110     of sys_var_pluginvar, and 0 otherwise.
111   */
cast_pluginvar()112   virtual sys_var_pluginvar *cast_pluginvar() { return 0; }
113 
114   bool check(THD *thd, set_var *var);
115   const uchar *value_ptr(THD *thd, enum_var_type type, const LEX_CSTRING *base) const;
116 
117   /**
118      Update the system variable with the default value from either
119      session or global scope.  The default value is stored in the
120      'var' argument. Return false when successful.
121   */
122   bool set_default(THD *thd, set_var *var);
123   bool update(THD *thd, set_var *var);
124 
125   String *val_str_nolock(String *str, THD *thd, const uchar *value);
126   longlong val_int(bool *is_null, THD *thd, enum_var_type type, const LEX_CSTRING *base);
127   String *val_str(String *str, THD *thd, enum_var_type type, const LEX_CSTRING *base);
128   double val_real(bool *is_null, THD *thd, enum_var_type type, const LEX_CSTRING *base);
129 
show_type()130   SHOW_TYPE show_type() const { return show_val_type; }
scope()131   int scope() const { return flags & SCOPE_MASK; }
charset(THD * thd)132   virtual CHARSET_INFO *charset(THD *thd) const
133   {
134     return system_charset_info;
135   }
is_readonly()136   bool is_readonly() const { return flags & READONLY; }
137   /**
138     the following is only true for keycache variables,
139     that support the syntax @@keycache_name.variable_name
140   */
is_struct()141   bool is_struct() { return option.var_type & GET_ASK_ADDR; }
is_set_stmt_ok()142   bool is_set_stmt_ok() const { return !(flags & NO_SET_STATEMENT); }
is_written_to_binlog(enum_var_type type)143   bool is_written_to_binlog(enum_var_type type)
144   { return type != OPT_GLOBAL && binlog_status == SESSION_VARIABLE_IN_BINLOG; }
check_update_type(const Item * item)145   bool check_update_type(const Item *item)
146   {
147     Item_result type= item->result_type();
148     switch (option.var_type & GET_TYPE_MASK) {
149     case GET_INT:
150     case GET_UINT:
151     case GET_LONG:
152     case GET_ULONG:
153     case GET_LL:
154     case GET_ULL:
155       return type != INT_RESULT &&
156              (type != DECIMAL_RESULT || item->decimals != 0);
157     case GET_STR:
158     case GET_STR_ALLOC:
159       return type != STRING_RESULT;
160     case GET_ENUM:
161     case GET_BOOL:
162     case GET_SET:
163     case GET_FLAGSET:
164     case GET_BIT:
165       return type != STRING_RESULT && type != INT_RESULT;
166     case GET_DOUBLE:
167       return type != INT_RESULT && type != REAL_RESULT && type != DECIMAL_RESULT;
168     default:
169       return true;
170     }
171   }
172 
check_type(enum_var_type type)173   bool check_type(enum_var_type type)
174   {
175     switch (scope())
176     {
177     case GLOBAL:       return type != OPT_GLOBAL;
178     case SESSION:      return false; // always ok
179     case ONLY_SESSION: return type == OPT_GLOBAL;
180     }
181     return true; // keep gcc happy
182   }
register_option(DYNAMIC_ARRAY * array,int parse_flags)183   bool register_option(DYNAMIC_ARRAY *array, int parse_flags)
184   {
185     DBUG_ASSERT(parse_flags == GETOPT_ONLY_HELP ||
186                 parse_flags == PARSE_EARLY || parse_flags == 0);
187     if (option.id == NO_GETOPT)
188       return 0;
189     if (parse_flags == GETOPT_ONLY_HELP)
190     {
191       if (option.id != GETOPT_ONLY_HELP)
192         return 0;
193     }
194     else
195     {
196       if (option.id == GETOPT_ONLY_HELP)
197         return 0;
198       if ((flags & PARSE_EARLY) != parse_flags)
199         return 0;
200     }
201     return insert_dynamic(array, (uchar*)&option);
202   }
203   void do_deprecated_warning(THD *thd);
204   /**
205     whether session value of a sysvar is a default one.
206 
207     in this simple implementation we don't distinguish between default
208     and non-default values. for most variables it's ok, they don't treat
209     default values specially. this method is overwritten in descendant
210     classes as necessary.
211   */
session_is_default(THD * thd)212   virtual bool session_is_default(THD *thd) { return false; }
213 
default_value_ptr(THD * thd)214   virtual const uchar *default_value_ptr(THD *thd) const
215   { return (uchar*)&option.def_value; }
216 
217   virtual bool on_check_access_global(THD *thd) const;
on_check_access_session(THD * thd)218   virtual bool on_check_access_session(THD *thd) const
219   {
220     return false;
221   }
222 
223 private:
224   virtual bool do_check(THD *thd, set_var *var) = 0;
225   /**
226     save the session default value of the variable in var
227   */
228   virtual void session_save_default(THD *thd, set_var *var) = 0;
229   /**
230     save the global default value of the variable in var
231   */
232   virtual void global_save_default(THD *thd, set_var *var) = 0;
233   virtual bool session_update(THD *thd, set_var *var) = 0;
234   virtual bool global_update(THD *thd, set_var *var) = 0;
235 
236 protected:
237   /**
238     A pointer to a value of the variable for SHOW.
239     It must be of show_val_type type (my_bool for SHOW_MY_BOOL,
240     int for SHOW_INT, longlong for SHOW_LONGLONG, etc).
241   */
242   virtual const uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base) const;
243   virtual const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const;
244 
245   /**
246     A pointer to a storage area of the variable, to the raw data.
247     Typically it's the same as session_value_ptr(), but it's different,
248     for example, for ENUM, that is printed as a string, but stored as a number.
249   */
session_var_ptr(THD * thd)250   uchar *session_var_ptr(THD *thd) const
251   { return ((uchar*)&(thd->variables)) + offset; }
252 
global_var_ptr()253   uchar *global_var_ptr() const
254   { return ((uchar*)&global_system_variables) + offset; }
255 
max_var_ptr()256   void *max_var_ptr()
257   {
258     return scope() == SESSION ? (((uchar*)&max_system_variables) + offset) :
259                                 0;
260   }
261 
262   friend class Session_sysvars_tracker;
263   friend class Session_tracker;
264 };
265 
266 #include "sql_plugin.h"                    /* SHOW_HA_ROWS, SHOW_MY_BOOL */
267 
268 
269 /****************************************************************************
270   Classes for parsing of the SET command
271 ****************************************************************************/
272 
273 /**
274   A base class for everything that can be set with SET command.
275   It's similar to Items, an instance of this is created by the parser
276   for every assigmnent in SET (or elsewhere, e.g. in SELECT).
277 */
278 class set_var_base :public Sql_alloc
279 {
280 public:
set_var_base()281   set_var_base() {}
~set_var_base()282   virtual ~set_var_base() {}
283   virtual int check(THD *thd)=0;           /* To check privileges etc. */
284   virtual int update(THD *thd)=0;                  /* To set the value */
light_check(THD * thd)285   virtual int light_check(THD *thd) { return check(thd); }   /* for PS */
is_system()286   virtual bool is_system() { return FALSE; }
287   /**
288     @returns whether this variable is @@@@optimizer_trace.
289   */
is_var_optimizer_trace()290   virtual bool is_var_optimizer_trace() const { return false; }
291 };
292 
293 
294 /**
295   Structure for holding unix timestamp and high precision second part.
296  */
297 typedef struct my_time_t_hires
298 {
299   my_time_t unix_time;
300   ulong second_part;
301 } my_time_t_hires;
302 
303 
304 /**
305   set_var_base descendant for assignments to the system variables.
306 */
307 class set_var :public set_var_base
308 {
309 public:
310   sys_var *var; ///< system variable to be updated
311   Item *value;  ///< the expression that provides the new value of the variable
312   enum_var_type type;
313   union ///< temp storage to hold a value between sys_var::check and ::update
314   {
315     ulonglong ulonglong_value;          ///< for unsigned integer, set, enum sysvars
316     longlong longlong_value;            ///< for signed integer
317     double double_value;                ///< for Sys_var_double
318     plugin_ref plugin;                  ///< for Sys_var_plugin
319     plugin_ref *plugins;                ///< for Sys_var_pluginlist
320     Time_zone *time_zone;               ///< for Sys_var_tz
321     LEX_STRING string_value;            ///< for Sys_var_charptr and others
322     my_time_t_hires timestamp;          ///< for Sys_var_vers_asof
323     const void *ptr;                    ///< for Sys_var_struct
324   } save_result;
325   LEX_CSTRING base; /**< for structured variables, like keycache_name.variable_name */
326 
327   set_var(THD *thd, enum_var_type type_arg, sys_var *var_arg,
328           const LEX_CSTRING *base_name_arg, Item *value_arg);
is_system()329   virtual bool is_system() { return 1; }
330   int check(THD *thd);
331   int update(THD *thd);
332   int light_check(THD *thd);
is_var_optimizer_trace()333   virtual bool is_var_optimizer_trace() const
334   {
335     extern sys_var *Sys_optimizer_trace_ptr;
336     return var == Sys_optimizer_trace_ptr;
337   }
338 };
339 
340 
341 /* User variables like @my_own_variable */
342 class set_var_user: public set_var_base
343 {
344   Item_func_set_user_var *user_var_item;
345 public:
set_var_user(Item_func_set_user_var * item)346   set_var_user(Item_func_set_user_var *item)
347     :user_var_item(item)
348   {}
349   int check(THD *thd);
350   int update(THD *thd);
351   int light_check(THD *thd);
352 };
353 
354 /* For SET PASSWORD */
355 
356 class set_var_password: public set_var_base
357 {
358   LEX_USER *user;
359 public:
set_var_password(LEX_USER * user_arg)360   set_var_password(LEX_USER *user_arg) :user(user_arg)
361   {}
362   int check(THD *thd);
363   int update(THD *thd);
364 };
365 
366 /* For SET ROLE */
367 
368 class set_var_role: public set_var_base
369 {
370   LEX_CSTRING role;
371   privilege_t access;
372 public:
set_var_role(LEX_CSTRING role_arg)373   set_var_role(LEX_CSTRING role_arg) : role(role_arg), access(NO_ACL) {}
374   int check(THD *thd);
375   int update(THD *thd);
376 };
377 
378 /* For SET DEFAULT ROLE */
379 
380 class set_var_default_role: public set_var_base
381 {
382   LEX_USER *user, *real_user;
383   LEX_CSTRING role;
384   const char *real_role;
385 public:
set_var_default_role(LEX_USER * user_arg,LEX_CSTRING role_arg)386   set_var_default_role(LEX_USER *user_arg, LEX_CSTRING role_arg) :
387     user(user_arg), role(role_arg) {}
388   int check(THD *thd);
389   int update(THD *thd);
390 };
391 
392 /* For SET NAMES and SET CHARACTER SET */
393 
394 class set_var_collation_client: public set_var_base
395 {
396   CHARSET_INFO *character_set_client;
397   CHARSET_INFO *character_set_results;
398   CHARSET_INFO *collation_connection;
399 public:
set_var_collation_client(CHARSET_INFO * client_coll_arg,CHARSET_INFO * connection_coll_arg,CHARSET_INFO * result_coll_arg)400   set_var_collation_client(CHARSET_INFO *client_coll_arg,
401                            CHARSET_INFO *connection_coll_arg,
402                            CHARSET_INFO *result_coll_arg)
403     :character_set_client(client_coll_arg),
404      character_set_results(result_coll_arg),
405      collation_connection(connection_coll_arg)
406   {}
407   int check(THD *thd);
408   int update(THD *thd);
409 };
410 
411 
412 /* optional things, have_* variables */
413 extern SHOW_COMP_OPTION have_csv, have_innodb;
414 extern SHOW_COMP_OPTION have_ndbcluster, have_partitioning;
415 extern SHOW_COMP_OPTION have_profiling;
416 
417 extern SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen;
418 extern SHOW_COMP_OPTION have_query_cache;
419 extern SHOW_COMP_OPTION have_geometry, have_rtree_keys;
420 extern SHOW_COMP_OPTION have_crypt;
421 extern SHOW_COMP_OPTION have_compress;
422 extern SHOW_COMP_OPTION have_openssl;
423 
424 /*
425   Prototypes for helper functions
426 */
427 ulong get_system_variable_hash_records(void);
428 ulonglong get_system_variable_hash_version(void);
429 
430 SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted, enum enum_var_type type);
431 int fill_sysvars(THD *thd, TABLE_LIST *tables, COND *cond);
432 
433 sys_var *find_sys_var(THD *thd, const char *str, size_t length= 0,
434                       bool throw_error= false);
435 int sql_set_variables(THD *thd, List<set_var_base> *var_list, bool free);
436 
437 #define SYSVAR_AUTOSIZE(VAR,VAL)                        \
438   do {                                                  \
439     VAR= (VAL);                                         \
440     set_sys_var_value_origin(&VAR, sys_var::AUTO);      \
441   } while(0)
442 
443 #define SYSVAR_AUTOSIZE_IF_CHANGED(VAR,VAL,TYPE)        \
444   do {                                                  \
445     TYPE tmp= (VAL);                                    \
446     if (VAR != tmp)                                     \
447     {                                                   \
448       VAR= (VAL);                                       \
449       set_sys_var_value_origin(&VAR, sys_var::AUTO);    \
450     }                                                   \
451   } while(0)
452 
453 void set_sys_var_value_origin(void *ptr, enum sys_var::where here,
454                               const char *filename= NULL);
455 
456 enum sys_var::where get_sys_var_value_origin(void *ptr);
IS_SYSVAR_AUTOSIZE(void * ptr)457 inline bool IS_SYSVAR_AUTOSIZE(void *ptr)
458 {
459   enum sys_var::where res= get_sys_var_value_origin(ptr);
460   return (res == sys_var::AUTO || res == sys_var::COMPILE_TIME);
461 }
462 
463 bool fix_delay_key_write(sys_var *self, THD *thd, enum_var_type type);
464 
465 sql_mode_t expand_sql_mode(sql_mode_t sql_mode);
466 const char *sql_mode_string_representation(uint bit_number);
467 bool sql_mode_string_representation(THD *thd, sql_mode_t sql_mode,
468                                     LEX_CSTRING *ls);
469 int default_regex_flags_pcre(THD *thd);
470 
471 extern sys_var *Sys_autocommit_ptr, *Sys_last_gtid_ptr,
472   *Sys_character_set_client_ptr, *Sys_character_set_connection_ptr,
473   *Sys_character_set_results_ptr;
474 
475 CHARSET_INFO *get_old_charset_by_name(const char *old_name);
476 
477 int sys_var_init();
478 uint sys_var_elements();
479 int sys_var_add_options(DYNAMIC_ARRAY *long_options, int parse_flags);
480 void sys_var_end(void);
481 bool check_has_super(sys_var *self, THD *thd, set_var *var);
482 plugin_ref *resolve_engine_list(THD *thd, const char *str_arg, size_t str_arg_len,
483                                 bool error_on_unknown_engine, bool temp_copy);
484 void free_engine_list(plugin_ref *list);
485 plugin_ref *copy_engine_list(plugin_ref *list);
486 plugin_ref *temp_copy_engine_list(THD *thd, plugin_ref *list);
487 char *pretty_print_engine_list(THD *thd, plugin_ref *list);
488 
489 #endif
490