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