1/* Copyright (c) 2002, 2011, Oracle and/or its affiliates.
2 Copyright (c) 2010, 2013, Monty Program Ab.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16
17/**
18 @file
19 "private" interface to sys_var - server configuration variables.
20
21 This header is included only by the file that contains declarations
22 of sys_var variables (sys_vars.cc).
23*/
24
25#include "sys_vars_shared.h"
26#include <my_getopt.h>
27#include <my_bit.h>
28#include <my_dir.h>
29#include "keycaches.h"
30#include "strfunc.h"
31#include "tztime.h" // my_tz_find, my_tz_SYSTEM, struct Time_zone
32#include "rpl_mi.h" // For Multi-Source Replication
33#include "debug_sync.h"
34
35/*
36 a set of mostly trivial (as in f(X)=X) defines below to make system variable
37 declarations more readable
38*/
39#define VALID_RANGE(X,Y) X,Y
40#define DEFAULT(X) X
41#define BLOCK_SIZE(X) X
42#define GLOBAL_VAR(X) sys_var::GLOBAL, (((char*)&(X))-(char*)&global_system_variables), sizeof(X)
43#define SESSION_VAR(X) sys_var::SESSION, offsetof(SV, X), sizeof(((SV *)0)->X)
44#define SESSION_ONLY(X) sys_var::ONLY_SESSION, offsetof(SV, X), sizeof(((SV *)0)->X)
45#define NO_CMD_LINE CMD_LINE(NO_ARG, sys_var::NO_GETOPT)
46#define CMD_LINE_HELP_ONLY CMD_LINE(NO_ARG, sys_var::GETOPT_ONLY_HELP)
47/*
48 the define below means that there's no *second* mutex guard,
49 LOCK_global_system_variables always guards all system variables
50*/
51#define NO_MUTEX_GUARD ((PolyLock*)0)
52#define IN_BINLOG sys_var::SESSION_VARIABLE_IN_BINLOG
53#define NOT_IN_BINLOG sys_var::VARIABLE_NOT_IN_BINLOG
54#define ON_READ(X) X
55#define ON_CHECK(X) X
56#define ON_UPDATE(X) X
57#define READ_ONLY sys_var::READONLY+
58#define AUTO_SET sys_var::AUTO_SET+
59// this means that Sys_var_charptr initial value was malloc()ed
60#define PREALLOCATED sys_var::ALLOCATED+
61#define PARSED_EARLY sys_var::PARSE_EARLY+
62#define NO_SET_STMT sys_var::NO_SET_STATEMENT+
63
64/*
65 Sys_var_bit meaning is reversed, like in
66 @@foreign_key_checks <-> OPTION_NO_FOREIGN_KEY_CHECKS
67*/
68#define REVERSE(X) ~(X)
69#define DEPRECATED(X) X
70
71#define session_var(THD, TYPE) (*(TYPE*)session_var_ptr(THD))
72#define global_var(TYPE) (*(TYPE*)global_var_ptr())
73
74#if SIZEOF_OFF_T > 4 && defined(BIG_TABLES)
75#define GET_HA_ROWS GET_ULL
76#else
77#define GET_HA_ROWS GET_ULONG
78#endif
79
80// Disable warning caused by SESSION_VAR() macro
81#ifdef __clang__
82#pragma clang diagnostic ignored "-Winvalid-offsetof"
83#endif
84
85/*
86 special assert for sysvars. Tells the name of the variable,
87 and fails even in non-debug builds.
88
89 It is supposed to be used *only* in Sys_var* constructors,
90 and has name_arg hard-coded to prevent incorrect usage.
91*/
92#define SYSVAR_ASSERT(X) \
93 while(!(X)) \
94 { \
95 fprintf(stderr, "Sysvar '%s' failed '%s'\n", name_arg, #X); \
96 DBUG_ASSERT(0); \
97 exit(255); \
98 }
99
100enum charset_enum {IN_SYSTEM_CHARSET, IN_FS_CHARSET};
101
102static const char *bool_values[3]= {"OFF", "ON", 0};
103TYPELIB bool_typelib={ array_elements(bool_values)-1, "", bool_values, 0 };
104
105/**
106 A small wrapper class to pass getopt arguments as a pair
107 to the Sys_var_* constructors. It improves type safety and helps
108 to catch errors in the argument order.
109*/
110struct CMD_LINE
111{
112 int id;
113 enum get_opt_arg_type arg_type;
114 CMD_LINE(enum get_opt_arg_type getopt_arg_type, int getopt_id=0)
115 : id(getopt_id), arg_type(getopt_arg_type) {}
116};
117
118/**
119 Sys_var_integer template is used to generate Sys_var_* classes
120 for variables that represent the value as an integer number.
121 They are Sys_var_uint, Sys_var_ulong, Sys_var_harows, Sys_var_ulonglong,
122 Sys_var_int.
123
124 An integer variable has a minimal and maximal values, and a "block_size"
125 (any valid value of the variable must be divisible by the block_size).
126
127 Class specific constructor arguments: min, max, block_size
128 Backing store: int, uint, ulong, ha_rows, ulonglong, depending on the class
129*/
130template <typename T, ulong ARGT, enum enum_mysql_show_type SHOWT>
131class Sys_var_integer: public sys_var
132{
133public:
134 Sys_var_integer(const char *name_arg,
135 const char *comment, int flag_args, ptrdiff_t off, size_t size,
136 CMD_LINE getopt,
137 T min_val, T max_val, T def_val, uint block_size, PolyLock *lock=0,
138 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
139 on_check_function on_check_func=0,
140 on_update_function on_update_func=0,
141 const char *substitute=0)
142 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
143 getopt.arg_type, SHOWT, def_val, lock, binlog_status_arg,
144 on_check_func, on_update_func, substitute)
145 {
146 option.var_type|= ARGT;
147 option.min_value= min_val;
148 option.max_value= max_val;
149 option.block_size= block_size;
150 option.u_max_value= (uchar**)max_var_ptr();
151 if (max_var_ptr())
152 *max_var_ptr()= max_val;
153
154 global_var(T)= def_val;
155 SYSVAR_ASSERT(size == sizeof(T));
156 SYSVAR_ASSERT(min_val < max_val);
157 SYSVAR_ASSERT(min_val <= def_val);
158 SYSVAR_ASSERT(max_val >= def_val);
159 SYSVAR_ASSERT(block_size > 0);
160 SYSVAR_ASSERT(def_val % block_size == 0);
161 }
162 bool do_check(THD *thd, set_var *var)
163 {
164 my_bool fixed= FALSE, unused;
165 longlong v= var->value->val_int();
166
167 if ((ARGT == GET_HA_ROWS) || (ARGT == GET_UINT) ||
168 (ARGT == GET_ULONG) || (ARGT == GET_ULL))
169 {
170 ulonglong uv;
171
172 /*
173 if the value is signed and negative,
174 and a variable is unsigned, it is set to zero
175 */
176 if ((fixed= (!var->value->unsigned_flag && v < 0)))
177 uv= 0;
178 else
179 uv= v;
180
181 var->save_result.ulonglong_value=
182 getopt_ull_limit_value(uv, &option, &unused);
183
184 if (max_var_ptr() && (T)var->save_result.ulonglong_value > *max_var_ptr())
185 var->save_result.ulonglong_value= *max_var_ptr();
186
187 fixed= fixed || var->save_result.ulonglong_value != uv;
188 }
189 else
190 {
191 /*
192 if the value is unsigned and has the highest bit set
193 and a variable is signed, it is set to max signed value
194 */
195 if ((fixed= (var->value->unsigned_flag && v < 0)))
196 v= LONGLONG_MAX;
197
198 var->save_result.longlong_value=
199 getopt_ll_limit_value(v, &option, &unused);
200
201 if (max_var_ptr() && (T)var->save_result.longlong_value > *max_var_ptr())
202 var->save_result.longlong_value= *max_var_ptr();
203
204 fixed= fixed || var->save_result.longlong_value != v;
205 }
206 return throw_bounds_warning(thd, name.str, fixed,
207 var->value->unsigned_flag, v);
208 }
209 bool session_update(THD *thd, set_var *var)
210 {
211 session_var(thd, T)= static_cast<T>(var->save_result.ulonglong_value);
212 return false;
213 }
214 bool global_update(THD *thd, set_var *var)
215 {
216 global_var(T)= static_cast<T>(var->save_result.ulonglong_value);
217 return false;
218 }
219 void session_save_default(THD *thd, set_var *var)
220 { var->save_result.ulonglong_value= (ulonglong)*(T*)global_value_ptr(thd, 0); }
221 void global_save_default(THD *thd, set_var *var)
222 { var->save_result.ulonglong_value= option.def_value; }
223 private:
224 T *max_var_ptr()
225 {
226 return scope() == SESSION ? (T*)(((uchar*)&max_system_variables) + offset)
227 : 0;
228 }
229 uchar *default_value_ptr(THD *thd) { return (uchar*) &option.def_value; }
230};
231
232typedef Sys_var_integer<int, GET_INT, SHOW_SINT> Sys_var_int;
233typedef Sys_var_integer<uint, GET_UINT, SHOW_UINT> Sys_var_uint;
234typedef Sys_var_integer<ulong, GET_ULONG, SHOW_ULONG> Sys_var_ulong;
235typedef Sys_var_integer<ha_rows, GET_HA_ROWS, SHOW_HA_ROWS> Sys_var_harows;
236typedef Sys_var_integer<ulonglong, GET_ULL, SHOW_ULONGLONG> Sys_var_ulonglong;
237typedef Sys_var_integer<long, GET_LONG, SHOW_SLONG> Sys_var_long;
238
239
240template<> uchar *Sys_var_int::default_value_ptr(THD *thd)
241{
242 thd->sys_var_tmp.int_value= (int)option.def_value;
243 return (uchar*) &thd->sys_var_tmp.int_value;
244}
245
246template<> uchar *Sys_var_uint::default_value_ptr(THD *thd)
247{
248 thd->sys_var_tmp.uint_value= (uint)option.def_value;
249 return (uchar*) &thd->sys_var_tmp.uint_value;
250}
251
252template<> uchar *Sys_var_long::default_value_ptr(THD *thd)
253{
254 thd->sys_var_tmp.long_value= (long)option.def_value;
255 return (uchar*) &thd->sys_var_tmp.long_value;
256}
257
258template<> uchar *Sys_var_ulong::default_value_ptr(THD *thd)
259{
260 thd->sys_var_tmp.ulong_value= (ulong)option.def_value;
261 return (uchar*) &thd->sys_var_tmp.ulong_value;
262}
263
264
265/**
266 Helper class for variables that take values from a TYPELIB
267*/
268class Sys_var_typelib: public sys_var
269{
270protected:
271 TYPELIB typelib;
272public:
273 Sys_var_typelib(const char *name_arg,
274 const char *comment, int flag_args, ptrdiff_t off,
275 CMD_LINE getopt,
276 SHOW_TYPE show_val_type_arg, const char *values[],
277 ulonglong def_val, PolyLock *lock,
278 enum binlog_status_enum binlog_status_arg,
279 on_check_function on_check_func, on_update_function on_update_func,
280 const char *substitute)
281 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
282 getopt.arg_type, show_val_type_arg, def_val, lock,
283 binlog_status_arg, on_check_func,
284 on_update_func, substitute)
285 {
286 for (typelib.count= 0; values[typelib.count]; typelib.count++) /*no-op */;
287 typelib.name="";
288 typelib.type_names= values;
289 typelib.type_lengths= 0; // only used by Fields_enum and Field_set
290 option.typelib= &typelib;
291 }
292 bool do_check(THD *thd, set_var *var) // works for enums and my_bool
293 {
294 char buff[STRING_BUFFER_USUAL_SIZE];
295 String str(buff, sizeof(buff), system_charset_info), *res;
296
297 if (var->value->result_type() == STRING_RESULT)
298 {
299 if (!(res=var->value->val_str(&str)))
300 return true;
301 else
302 if (!(var->save_result.ulonglong_value=
303 find_type(&typelib, res->ptr(), res->length(), false)))
304 return true;
305 else
306 var->save_result.ulonglong_value--;
307 }
308 else
309 {
310 longlong tmp=var->value->val_int();
311 if (tmp < 0 || tmp >= typelib.count)
312 return true;
313 else
314 var->save_result.ulonglong_value= tmp;
315 }
316
317 return false;
318 }
319};
320
321/**
322 The class for ENUM variables - variables that take one value from a fixed
323 list of values.
324
325 Class specific constructor arguments:
326 char* values[] - 0-terminated list of strings of valid values
327
328 Backing store: ulong
329
330 @note
331 Do *not* use "enum FOO" variables as a backing store, there is no
332 guarantee that sizeof(enum FOO) == sizeof(uint), there is no guarantee
333 even that sizeof(enum FOO) == sizeof(enum BAR)
334*/
335class Sys_var_enum: public Sys_var_typelib
336{
337public:
338 Sys_var_enum(const char *name_arg,
339 const char *comment, int flag_args, ptrdiff_t off, size_t size,
340 CMD_LINE getopt,
341 const char *values[], uint def_val, PolyLock *lock=0,
342 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
343 on_check_function on_check_func=0,
344 on_update_function on_update_func=0,
345 const char *substitute=0)
346 : Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
347 SHOW_CHAR, values, def_val, lock,
348 binlog_status_arg, on_check_func, on_update_func,
349 substitute)
350 {
351 option.var_type|= GET_ENUM;
352 global_var(ulong)= def_val;
353 SYSVAR_ASSERT(def_val < typelib.count);
354 SYSVAR_ASSERT(size == sizeof(ulong));
355 }
356 bool session_update(THD *thd, set_var *var)
357 {
358 session_var(thd, ulong)= static_cast<ulong>(var->save_result.ulonglong_value);
359 return false;
360 }
361 bool global_update(THD *thd, set_var *var)
362 {
363 global_var(ulong)= static_cast<ulong>(var->save_result.ulonglong_value);
364 return false;
365 }
366 void session_save_default(THD *thd, set_var *var)
367 { var->save_result.ulonglong_value= global_var(ulong); }
368 void global_save_default(THD *thd, set_var *var)
369 { var->save_result.ulonglong_value= option.def_value; }
370 uchar *valptr(THD *thd, ulong val)
371 { return (uchar*)typelib.type_names[val]; }
372 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
373 { return valptr(thd, session_var(thd, ulong)); }
374 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
375 { return valptr(thd, global_var(ulong)); }
376 uchar *default_value_ptr(THD *thd)
377 { return valptr(thd, (ulong)option.def_value); }
378};
379
380/**
381 The class for boolean variables - a variant of ENUM variables
382 with the fixed list of values of { OFF , ON }
383
384 Backing store: my_bool
385*/
386class Sys_var_mybool: public Sys_var_typelib
387{
388public:
389 Sys_var_mybool(const char *name_arg,
390 const char *comment, int flag_args, ptrdiff_t off, size_t size,
391 CMD_LINE getopt,
392 my_bool def_val, PolyLock *lock=0,
393 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
394 on_check_function on_check_func=0,
395 on_update_function on_update_func=0,
396 const char *substitute=0)
397 : Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
398 SHOW_MY_BOOL, bool_values, def_val, lock,
399 binlog_status_arg, on_check_func, on_update_func,
400 substitute)
401 {
402 option.var_type|= GET_BOOL;
403 global_var(my_bool)= def_val;
404 SYSVAR_ASSERT(def_val < 2);
405 SYSVAR_ASSERT(getopt.arg_type == OPT_ARG || getopt.id < 0);
406 SYSVAR_ASSERT(size == sizeof(my_bool));
407 }
408 bool session_update(THD *thd, set_var *var)
409 {
410 session_var(thd, my_bool)= var->save_result.ulonglong_value != 0;
411 return false;
412 }
413 bool global_update(THD *thd, set_var *var)
414 {
415 global_var(my_bool)= var->save_result.ulonglong_value != 0;
416 return false;
417 }
418 void session_save_default(THD *thd, set_var *var)
419 { var->save_result.ulonglong_value= (ulonglong)*(my_bool *)global_value_ptr(thd, 0); }
420 void global_save_default(THD *thd, set_var *var)
421 { var->save_result.ulonglong_value= option.def_value; }
422 uchar *default_value_ptr(THD *thd)
423 {
424 thd->sys_var_tmp.my_bool_value=(my_bool) option.def_value;
425 return (uchar*) &thd->sys_var_tmp.my_bool_value;
426 }
427};
428
429/**
430 The class for string variables. The string can be in character_set_filesystem
431 or in character_set_system. The string can be allocated with my_malloc()
432 or not. The state of the initial value is specified in the constructor,
433 after that it's managed automatically. The value of NULL is supported.
434
435 Class specific constructor arguments:
436 enum charset_enum is_os_charset_arg
437
438 Backing store: char*
439
440 @note
441 This class supports only GLOBAL variables, because THD on destruction
442 does not destroy individual members of SV, there's no way to free
443 allocated string variables for every thread.
444*/
445class Sys_var_charptr_base: public sys_var
446{
447public:
448 Sys_var_charptr_base(const char *name_arg,
449 const char *comment, int flag_args, ptrdiff_t off, size_t size,
450 CMD_LINE getopt,
451 enum charset_enum is_os_charset_arg,
452 const char *def_val, PolyLock *lock=0,
453 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
454 on_check_function on_check_func=0,
455 on_update_function on_update_func=0,
456 const char *substitute=0)
457 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
458 getopt.arg_type, SHOW_CHAR_PTR, (intptr)def_val,
459 lock, binlog_status_arg, on_check_func, on_update_func,
460 substitute)
461 {
462 is_os_charset= is_os_charset_arg == IN_FS_CHARSET;
463 /*
464 use GET_STR_ALLOC - if ALLOCATED it must be *always* allocated,
465 otherwise (GET_STR) you'll never know whether to free it or not.
466 (think of an exit because of an error right after my_getopt)
467 */
468 option.var_type|= (flags & ALLOCATED) ? GET_STR_ALLOC : GET_STR;
469 global_var(const char*)= def_val;
470 }
471 void cleanup()
472 {
473 if (flags & ALLOCATED)
474 {
475 my_free(global_var(char*));
476 global_var(char *)= NULL;
477 }
478 flags&= ~ALLOCATED;
479 }
480 static bool do_string_check(THD *thd, set_var *var, CHARSET_INFO *charset)
481 {
482 char buff[STRING_BUFFER_USUAL_SIZE], buff2[STRING_BUFFER_USUAL_SIZE];
483 String str(buff, sizeof(buff), charset);
484 String str2(buff2, sizeof(buff2), charset), *res;
485
486 if (!(res=var->value->val_str(&str)))
487 var->save_result.string_value.str= 0;
488 else
489 {
490 uint32 unused;
491 if (String::needs_conversion(res->length(), res->charset(),
492 charset, &unused))
493 {
494 uint errors;
495 str2.copy(res->ptr(), res->length(), res->charset(), charset,
496 &errors);
497 res=&str2;
498
499 }
500 var->save_result.string_value.str= thd->strmake(res->ptr(), res->length());
501 var->save_result.string_value.length= res->length();
502 }
503
504 return false;
505 }
506 bool do_check(THD *thd, set_var *var)
507 { return do_string_check(thd, var, charset(thd)); }
508 bool session_update(THD *thd, set_var *var)= 0;
509 char *global_update_prepare(THD *thd, set_var *var)
510 {
511 char *new_val, *ptr= var->save_result.string_value.str;
512 size_t len=var->save_result.string_value.length;
513 if (ptr)
514 {
515 new_val= (char*)my_memdup(ptr, len+1, MYF(MY_WME));
516 if (!new_val) return 0;
517 new_val[len]=0;
518 }
519 else
520 new_val= 0;
521 return new_val;
522 }
523 void global_update_finish(char *new_val)
524 {
525 if (flags & ALLOCATED)
526 my_free(global_var(char*));
527 flags|= ALLOCATED;
528 global_var(char*)= new_val;
529 }
530 bool global_update(THD *thd, set_var *var)
531 {
532 char *new_val= global_update_prepare(thd, var);
533 global_update_finish(new_val);
534 return (new_val == 0 && var->save_result.string_value.str != 0);
535 }
536 void session_save_default(THD *thd, set_var *var)= 0;
537 void global_save_default(THD *thd, set_var *var)
538 {
539 char *ptr= (char*)(intptr)option.def_value;
540 var->save_result.string_value.str= ptr;
541 var->save_result.string_value.length= ptr ? strlen(ptr) : 0;
542 }
543};
544
545class Sys_var_charptr: public Sys_var_charptr_base
546{
547public:
548 Sys_var_charptr(const char *name_arg,
549 const char *comment, int flag_args, ptrdiff_t off, size_t size,
550 CMD_LINE getopt,
551 enum charset_enum is_os_charset_arg,
552 const char *def_val, PolyLock *lock=0,
553 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
554 on_check_function on_check_func=0,
555 on_update_function on_update_func=0,
556 const char *substitute=0) :
557 Sys_var_charptr_base(name_arg, comment, flag_args, off, size, getopt,
558 is_os_charset_arg, def_val, lock, binlog_status_arg,
559 on_check_func, on_update_func, substitute)
560 {
561 SYSVAR_ASSERT(scope() == GLOBAL);
562 SYSVAR_ASSERT(size == sizeof(char *));
563 }
564
565 bool session_update(THD *thd, set_var *var)
566 {
567 DBUG_ASSERT(FALSE);
568 return true;
569 }
570 void session_save_default(THD *thd, set_var *var)
571 { DBUG_ASSERT(FALSE); }
572};
573
574#ifndef EMBEDDED_LIBRARY
575class Sys_var_sesvartrack: public Sys_var_charptr_base
576{
577public:
578 Sys_var_sesvartrack(const char *name_arg,
579 const char *comment,
580 CMD_LINE getopt,
581 enum charset_enum is_os_charset_arg,
582 const char *def_val, PolyLock *lock) :
583 Sys_var_charptr_base(name_arg, comment,
584 SESSION_VAR(session_track_system_variables),
585 getopt, is_os_charset_arg, def_val, lock,
586 VARIABLE_NOT_IN_BINLOG, 0, 0, 0)
587 {}
588 bool do_check(THD *thd, set_var *var)
589 {
590 if (Sys_var_charptr_base::do_check(thd, var) ||
591 sysvartrack_validate_value(thd, var->save_result.string_value.str,
592 var->save_result.string_value.length))
593 return TRUE;
594 return FALSE;
595 }
596 bool global_update(THD *thd, set_var *var)
597 {
598 char *new_val= global_update_prepare(thd, var);
599 if (new_val)
600 {
601 if (sysvartrack_reprint_value(thd, new_val,
602 var->save_result.string_value.length))
603 new_val= 0;
604 }
605 global_update_finish(new_val);
606 return (new_val == 0 && var->save_result.string_value.str != 0);
607 }
608 bool session_update(THD *thd, set_var *var)
609 {
610 return sysvartrack_update(thd, var);
611 }
612 void session_save_default(THD *thd, set_var *var)
613 {
614 var->save_result.string_value.str= global_var(char*);
615 var->save_result.string_value.length=
616 strlen(var->save_result.string_value.str);
617 /* parse and feel list with default values */
618 if (thd)
619 {
620#ifdef DBUG_ASSERT_EXISTS
621 bool res=
622#endif
623 sysvartrack_validate_value(thd,
624 var->save_result.string_value.str,
625 var->save_result.string_value.length);
626 DBUG_ASSERT(res == 0);
627 }
628 }
629 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
630 {
631 DBUG_ASSERT(thd != NULL);
632 size_t len= sysvartrack_value_len(thd);
633 char *res= (char *)thd->alloc(len + sizeof(char *));
634 if (res)
635 {
636 char *buf= res + sizeof(char *);
637 *((char**) res)= buf;
638 sysvartrack_value_construct(thd, buf, len);
639 }
640 return (uchar *)res;
641 }
642};
643#endif //EMBEDDED_LIBRARY
644
645
646class Sys_var_proxy_user: public sys_var
647{
648public:
649 Sys_var_proxy_user(const char *name_arg,
650 const char *comment, enum charset_enum is_os_charset_arg)
651 : sys_var(&all_sys_vars, name_arg, comment,
652 sys_var::READONLY+sys_var::ONLY_SESSION, 0, NO_GETOPT,
653 NO_ARG, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG,
654 NULL, NULL, NULL)
655 {
656 is_os_charset= is_os_charset_arg == IN_FS_CHARSET;
657 option.var_type|= GET_STR;
658 }
659 bool do_check(THD *thd, set_var *var)
660 {
661 DBUG_ASSERT(FALSE);
662 return true;
663 }
664 bool session_update(THD *thd, set_var *var)
665 {
666 DBUG_ASSERT(FALSE);
667 return true;
668 }
669 bool global_update(THD *thd, set_var *var)
670 {
671 DBUG_ASSERT(FALSE);
672 return false;
673 }
674 void session_save_default(THD *thd, set_var *var)
675 { DBUG_ASSERT(FALSE); }
676 void global_save_default(THD *thd, set_var *var)
677 { DBUG_ASSERT(FALSE); }
678protected:
679 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
680 {
681 return thd->security_ctx->proxy_user[0] ?
682 (uchar *) &(thd->security_ctx->proxy_user[0]) : NULL;
683 }
684};
685
686class Sys_var_external_user : public Sys_var_proxy_user
687{
688public:
689 Sys_var_external_user(const char *name_arg, const char *comment_arg,
690 enum charset_enum is_os_charset_arg)
691 : Sys_var_proxy_user (name_arg, comment_arg, is_os_charset_arg)
692 {}
693
694protected:
695 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
696 {
697 return (uchar*)thd->security_ctx->external_user;
698 }
699};
700
701class Master_info;
702class Sys_var_rpl_filter: public sys_var
703{
704private:
705 int opt_id;
706
707public:
708 Sys_var_rpl_filter(const char *name, int getopt_id, const char *comment)
709 : sys_var(&all_sys_vars, name, comment, sys_var::GLOBAL, 0, NO_GETOPT,
710 NO_ARG, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG,
711 NULL, NULL, NULL), opt_id(getopt_id)
712 {
713 option.var_type|= GET_STR | GET_ASK_ADDR;
714 }
715
716 bool do_check(THD *thd, set_var *var)
717 {
718 return Sys_var_charptr::do_string_check(thd, var, charset(thd));
719 }
720 void session_save_default(THD *thd, set_var *var)
721 { DBUG_ASSERT(FALSE); }
722
723 void global_save_default(THD *thd, set_var *var)
724 { DBUG_ASSERT(FALSE); }
725
726 bool session_update(THD *thd, set_var *var)
727 {
728 DBUG_ASSERT(FALSE);
729 return true;
730 }
731
732 bool global_update(THD *thd, set_var *var);
733
734protected:
735 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base);
736 bool set_filter_value(const char *value, Master_info *mi);
737};
738
739/**
740 The class for string variables. Useful for strings that aren't necessarily
741 \0-terminated. Otherwise the same as Sys_var_charptr.
742
743 Class specific constructor arguments:
744 enum charset_enum is_os_charset_arg
745
746 Backing store: LEX_CSTRING
747
748 @note
749 Behaves exactly as Sys_var_charptr, only the backing store is different.
750*/
751class Sys_var_lexstring: public Sys_var_charptr
752{
753public:
754 Sys_var_lexstring(const char *name_arg,
755 const char *comment, int flag_args, ptrdiff_t off, size_t size,
756 CMD_LINE getopt,
757 enum charset_enum is_os_charset_arg,
758 const char *def_val, PolyLock *lock=0,
759 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
760 on_check_function on_check_func=0,
761 on_update_function on_update_func=0,
762 const char *substitute=0)
763 : Sys_var_charptr(name_arg, comment, flag_args, off, sizeof(char*),
764 getopt, is_os_charset_arg, def_val, lock, binlog_status_arg,
765 on_check_func, on_update_func, substitute)
766 {
767 global_var(LEX_CSTRING).length= strlen(def_val);
768 SYSVAR_ASSERT(size == sizeof(LEX_CSTRING));
769 *const_cast<SHOW_TYPE*>(&show_val_type)= SHOW_LEX_STRING;
770 }
771 bool global_update(THD *thd, set_var *var)
772 {
773 if (Sys_var_charptr::global_update(thd, var))
774 return true;
775 global_var(LEX_CSTRING).length= var->save_result.string_value.length;
776 return false;
777 }
778};
779
780
781/*
782 A LEX_CSTRING stored only in thd->variables
783 Only to be used for small buffers
784*/
785
786class Sys_var_session_lexstring: public sys_var
787{
788 size_t max_length;
789public:
790 Sys_var_session_lexstring(const char *name_arg,
791 const char *comment, int flag_args,
792 ptrdiff_t off, size_t size, CMD_LINE getopt,
793 enum charset_enum is_os_charset_arg,
794 const char *def_val, size_t max_length_arg,
795 on_check_function on_check_func=0,
796 on_update_function on_update_func=0)
797 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
798 getopt.arg_type, SHOW_CHAR, (intptr)def_val,
799 0, VARIABLE_NOT_IN_BINLOG, on_check_func, on_update_func,
800 0),max_length(max_length_arg)
801 {
802 option.var_type|= GET_STR;
803 SYSVAR_ASSERT(scope() == ONLY_SESSION)
804 *const_cast<SHOW_TYPE*>(&show_val_type)= SHOW_LEX_STRING;
805 }
806 bool do_check(THD *thd, set_var *var)
807 {
808 char buff[STRING_BUFFER_USUAL_SIZE];
809 String str(buff, sizeof(buff), system_charset_info), *res;
810
811 if (!(res=var->value->val_str(&str)))
812 {
813 var->save_result.string_value.str= 0; /* NULL */
814 var->save_result.string_value.length= 0;
815 }
816 else
817 {
818 if (res->length() > max_length)
819 {
820 my_error(ER_WRONG_STRING_LENGTH, MYF(0),
821 res->ptr(), name.str, (int) max_length);
822 return true;
823 }
824 var->save_result.string_value.str= thd->strmake(res->ptr(),
825 res->length());
826 var->save_result.string_value.length= res->length();
827 }
828 return false;
829 }
830 bool session_update(THD *thd, set_var *var)
831 {
832 LEX_CSTRING *tmp= &session_var(thd, LEX_CSTRING);
833 tmp->length= var->save_result.string_value.length;
834 /* Store as \0 terminated string (just to be safe) */
835 strmake((char*) tmp->str, var->save_result.string_value.str, tmp->length);
836 return false;
837 }
838 bool global_update(THD *thd, set_var *var)
839 {
840 DBUG_ASSERT(FALSE);
841 return false;
842 }
843 void session_save_default(THD *thd, set_var *var)
844 {
845 char *ptr= (char*)(intptr)option.def_value;
846 var->save_result.string_value.str= ptr;
847 var->save_result.string_value.length= strlen(ptr);
848 }
849 void global_save_default(THD *thd, set_var *var)
850 {
851 DBUG_ASSERT(FALSE);
852 }
853 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
854 {
855 DBUG_ASSERT(FALSE);
856 return NULL;
857 }
858};
859
860
861#ifndef DBUG_OFF
862/**
863 @@session.debug_dbug and @@global.debug_dbug variables.
864
865 @@dbug variable differs from other variables in one aspect:
866 if its value is not assigned in the session, it "points" to the global
867 value, and so when the global value is changed, the change
868 immediately takes effect in the session.
869
870 This semantics is intentional, to be able to debug one session from
871 another.
872*/
873class Sys_var_dbug: public sys_var
874{
875public:
876 Sys_var_dbug(const char *name_arg,
877 const char *comment, int flag_args,
878 CMD_LINE getopt,
879 const char *def_val, PolyLock *lock=0,
880 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
881 on_check_function on_check_func=0,
882 on_update_function on_update_func=0,
883 const char *substitute=0)
884 : sys_var(&all_sys_vars, name_arg, comment, flag_args,
885 (char*)&current_dbug_option-(char*)&global_system_variables, getopt.id,
886 getopt.arg_type, SHOW_CHAR, (intptr)def_val,
887 lock, binlog_status_arg, on_check_func, on_update_func,
888 substitute)
889 { option.var_type|= GET_STR; }
890 bool do_check(THD *thd, set_var *var)
891 {
892 char buff[STRING_BUFFER_USUAL_SIZE];
893 String str(buff, sizeof(buff), system_charset_info), *res;
894
895 if (!(res=var->value->val_str(&str)))
896 var->save_result.string_value.str= const_cast<char*>("");
897 else
898 var->save_result.string_value.str= thd->strmake(res->ptr(), res->length());
899 return false;
900 }
901 bool session_update(THD *thd, set_var *var)
902 {
903 const char *val= var->save_result.string_value.str;
904 if (!var->value)
905 DBUG_POP();
906 else
907 DBUG_SET(val);
908 return false;
909 }
910 bool global_update(THD *thd, set_var *var)
911 {
912 const char *val= var->save_result.string_value.str;
913 DBUG_SET_INITIAL(val);
914 return false;
915 }
916 void session_save_default(THD *thd, set_var *var)
917 { }
918 void global_save_default(THD *thd, set_var *var)
919 {
920 char *ptr= (char*)(intptr)option.def_value;
921 var->save_result.string_value.str= ptr;
922 }
923 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
924 {
925 char buf[256];
926 DBUG_EXPLAIN(buf, sizeof(buf));
927 return (uchar*) thd->strdup(buf);
928 }
929 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
930 {
931 char buf[256];
932 DBUG_EXPLAIN_INITIAL(buf, sizeof(buf));
933 return (uchar*) thd->strdup(buf);
934 }
935 uchar *default_value_ptr(THD *thd)
936 { return (uchar*)""; }
937};
938#endif
939
940#define KEYCACHE_VAR(X) GLOBAL_VAR(dflt_key_cache_var.X)
941#define keycache_var_ptr(KC, OFF) (((uchar*)(KC))+(OFF))
942#define keycache_var(KC, OFF) (*(ulonglong*)keycache_var_ptr(KC, OFF))
943typedef bool (*keycache_update_function)(THD *, KEY_CACHE *, ptrdiff_t, ulonglong);
944
945/**
946 The class for keycache_* variables. Supports structured names,
947 keycache_name.variable_name.
948
949 Class specific constructor arguments:
950 everything derived from Sys_var_ulonglong
951
952 Backing store: ulonglong
953
954 @note these variables can be only GLOBAL
955*/
956class Sys_var_keycache: public Sys_var_ulonglong
957{
958 keycache_update_function keycache_update;
959public:
960 Sys_var_keycache(const char *name_arg,
961 const char *comment, int flag_args, ptrdiff_t off, size_t size,
962 CMD_LINE getopt,
963 ulonglong min_val, ulonglong max_val, ulonglong def_val,
964 uint block_size, PolyLock *lock,
965 enum binlog_status_enum binlog_status_arg,
966 on_check_function on_check_func,
967 keycache_update_function on_update_func,
968 const char *substitute=0)
969 : Sys_var_ulonglong(name_arg, comment, flag_args, off, size,
970 getopt, min_val, max_val, def_val,
971 block_size, lock, binlog_status_arg, on_check_func, 0,
972 substitute),
973 keycache_update(on_update_func)
974 {
975 option.var_type|= GET_ASK_ADDR;
976 option.value= (uchar**)1; // crash me, please
977 // fix an offset from global_system_variables to be an offset in KEY_CACHE
978 offset= global_var_ptr() - (uchar*)dflt_key_cache;
979 SYSVAR_ASSERT(scope() == GLOBAL);
980 }
981 bool global_update(THD *thd, set_var *var)
982 {
983 ulonglong new_value= var->save_result.ulonglong_value;
984 LEX_CSTRING *base_name= &var->base;
985 KEY_CACHE *key_cache;
986
987 /* If no basename, assume it's for the key cache named 'default' */
988 if (!base_name->length)
989 base_name= &default_key_cache_base;
990
991 key_cache= get_key_cache(base_name);
992
993 if (!key_cache)
994 { // Key cache didn't exists */
995 if (!new_value) // Tried to delete cache
996 return false; // Ok, nothing to do
997 if (!(key_cache= create_key_cache(base_name->str, base_name->length)))
998 return true;
999 }
1000
1001 /**
1002 Abort if some other thread is changing the key cache
1003 @todo This should be changed so that we wait until the previous
1004 assignment is done and then do the new assign
1005 */
1006 if (key_cache->in_init)
1007 return true;
1008
1009 return keycache_update(thd, key_cache, offset, new_value);
1010 }
1011 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
1012 {
1013 KEY_CACHE *key_cache= get_key_cache(base);
1014 if (!key_cache)
1015 key_cache= &zero_key_cache;
1016 return keycache_var_ptr(key_cache, offset);
1017 }
1018};
1019
1020static bool update_buffer_size(THD *thd, KEY_CACHE *key_cache,
1021 ptrdiff_t offset, ulonglong new_value)
1022{
1023 bool error= false;
1024 DBUG_ASSERT(offset == offsetof(KEY_CACHE, param_buff_size));
1025
1026 if (new_value == 0)
1027 {
1028 if (key_cache == dflt_key_cache)
1029 {
1030 my_error(ER_WARN_CANT_DROP_DEFAULT_KEYCACHE, MYF(0));
1031 return true;
1032 }
1033
1034 if (key_cache->key_cache_inited) // If initied
1035 {
1036 /*
1037 Move tables using this key cache to the default key cache
1038 and clear the old key cache.
1039 */
1040 key_cache->in_init= 1;
1041 mysql_mutex_unlock(&LOCK_global_system_variables);
1042 key_cache->param_buff_size= 0;
1043 ha_resize_key_cache(key_cache);
1044 ha_change_key_cache(key_cache, dflt_key_cache);
1045 /*
1046 We don't delete the key cache as some running threads my still be in
1047 the key cache code with a pointer to the deleted (empty) key cache
1048 */
1049 mysql_mutex_lock(&LOCK_global_system_variables);
1050 key_cache->in_init= 0;
1051 }
1052 return error;
1053 }
1054
1055 key_cache->param_buff_size= new_value;
1056
1057 /* If key cache didn't exist initialize it, else resize it */
1058 key_cache->in_init= 1;
1059 mysql_mutex_unlock(&LOCK_global_system_variables);
1060
1061 if (!key_cache->key_cache_inited)
1062 error= ha_init_key_cache(0, key_cache, 0);
1063 else
1064 error= ha_resize_key_cache(key_cache);
1065
1066 mysql_mutex_lock(&LOCK_global_system_variables);
1067 key_cache->in_init= 0;
1068
1069 return error;
1070}
1071
1072static bool update_keycache(THD *thd, KEY_CACHE *key_cache,
1073 ptrdiff_t offset, ulonglong new_value,
1074 int (*func)(KEY_CACHE *))
1075{
1076 bool error= false;
1077 DBUG_ASSERT(offset != offsetof(KEY_CACHE, param_buff_size));
1078
1079 keycache_var(key_cache, offset)= new_value;
1080
1081 key_cache->in_init= 1;
1082 mysql_mutex_unlock(&LOCK_global_system_variables);
1083 error= func(key_cache);
1084 mysql_mutex_lock(&LOCK_global_system_variables);
1085 key_cache->in_init= 0;
1086
1087 return error;
1088}
1089
1090static bool resize_keycache(THD *thd, KEY_CACHE *key_cache,
1091 ptrdiff_t offset, ulonglong new_value)
1092{
1093 return update_keycache(thd, key_cache, offset, new_value,
1094 ha_resize_key_cache);
1095}
1096
1097static bool change_keycache_param(THD *thd, KEY_CACHE *key_cache,
1098 ptrdiff_t offset, ulonglong new_value)
1099{
1100 return update_keycache(thd, key_cache, offset, new_value,
1101 ha_change_key_cache_param);
1102}
1103
1104static bool repartition_keycache(THD *thd, KEY_CACHE *key_cache,
1105 ptrdiff_t offset, ulonglong new_value)
1106{
1107 return update_keycache(thd, key_cache, offset, new_value,
1108 ha_repartition_key_cache);
1109}
1110
1111
1112/**
1113 The class for floating point variables
1114
1115 Class specific constructor arguments: min, max
1116
1117 Backing store: double
1118*/
1119class Sys_var_double: public sys_var
1120{
1121public:
1122 Sys_var_double(const char *name_arg,
1123 const char *comment, int flag_args, ptrdiff_t off, size_t size,
1124 CMD_LINE getopt,
1125 double min_val, double max_val, double def_val, PolyLock *lock=0,
1126 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
1127 on_check_function on_check_func=0,
1128 on_update_function on_update_func=0,
1129 const char *substitute=0)
1130 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
1131 getopt.arg_type, SHOW_DOUBLE,
1132 (longlong) getopt_double2ulonglong(def_val),
1133 lock, binlog_status_arg, on_check_func, on_update_func,
1134 substitute)
1135 {
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)= (double)option.def_value;
1140 SYSVAR_ASSERT(min_val < max_val);
1141 SYSVAR_ASSERT(min_val <= def_val);
1142 SYSVAR_ASSERT(max_val >= def_val);
1143 SYSVAR_ASSERT(size == sizeof(double));
1144 }
1145 bool do_check(THD *thd, set_var *var)
1146 {
1147 my_bool fixed;
1148 double v= var->value->val_real();
1149 var->save_result.double_value= getopt_double_limit_value(v, &option, &fixed);
1150
1151 return throw_bounds_warning(thd, name.str, fixed, v);
1152 }
1153 bool session_update(THD *thd, set_var *var)
1154 {
1155 session_var(thd, double)= var->save_result.double_value;
1156 return false;
1157 }
1158 bool global_update(THD *thd, set_var *var)
1159 {
1160 global_var(double)= var->save_result.double_value;
1161 return false;
1162 }
1163 void session_save_default(THD *thd, set_var *var)
1164 { var->save_result.double_value= global_var(double); }
1165 void global_save_default(THD *thd, set_var *var)
1166 { var->save_result.double_value= getopt_ulonglong2double(option.def_value); }
1167};
1168
1169/**
1170 The class for the @max_user_connections.
1171 It's derived from Sys_var_uint, but non-standard session value
1172 requires a new class.
1173
1174 Class specific constructor arguments:
1175 everything derived from Sys_var_uint
1176
1177 Backing store: uint
1178*/
1179class Sys_var_max_user_conn: public Sys_var_int
1180{
1181public:
1182 Sys_var_max_user_conn(const char *name_arg,
1183 const char *comment, int flag_args, ptrdiff_t off, size_t size,
1184 CMD_LINE getopt,
1185 int min_val, int max_val, int def_val,
1186 uint block_size, PolyLock *lock=0,
1187 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
1188 on_check_function on_check_func=0,
1189 on_update_function on_update_func=0,
1190 const char *substitute=0)
1191 : Sys_var_int(name_arg, comment, SESSION, off, size, getopt,
1192 min_val, max_val, def_val, block_size,
1193 lock, binlog_status_arg, on_check_func, on_update_func,
1194 substitute)
1195 { }
1196 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
1197 {
1198 if (thd->user_connect && thd->user_connect->user_resources.user_conn)
1199 return (uchar*) &(thd->user_connect->user_resources.user_conn);
1200 return global_value_ptr(thd, base);
1201 }
1202};
1203
1204/**
1205 The class for flagset variables - a variant of SET that allows in-place
1206 editing (turning on/off individual bits). String representations looks like
1207 a "flag=val,flag=val,...". Example: @@optimizer_switch
1208
1209 Class specific constructor arguments:
1210 char* values[] - 0-terminated list of strings of valid values
1211
1212 Backing store: ulonglong
1213
1214 @note
1215 the last value in the values[] array should
1216 *always* be the string "default".
1217*/
1218class Sys_var_flagset: public Sys_var_typelib
1219{
1220public:
1221 Sys_var_flagset(const char *name_arg,
1222 const char *comment, int flag_args, ptrdiff_t off, size_t size,
1223 CMD_LINE getopt,
1224 const char *values[], ulonglong def_val, PolyLock *lock=0,
1225 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
1226 on_check_function on_check_func=0,
1227 on_update_function on_update_func=0,
1228 const char *substitute=0)
1229 : Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
1230 SHOW_CHAR, values, def_val, lock,
1231 binlog_status_arg, on_check_func, on_update_func,
1232 substitute)
1233 {
1234 option.var_type|= GET_FLAGSET;
1235 global_var(ulonglong)= def_val;
1236 SYSVAR_ASSERT(typelib.count > 1);
1237 SYSVAR_ASSERT(typelib.count <= 65);
1238 SYSVAR_ASSERT(def_val <= my_set_bits(typelib.count-1));
1239 SYSVAR_ASSERT(strcmp(values[typelib.count-1], "default") == 0);
1240 SYSVAR_ASSERT(size == sizeof(ulonglong));
1241 }
1242 bool do_check(THD *thd, set_var *var)
1243 {
1244 char buff[STRING_BUFFER_USUAL_SIZE];
1245 String str(buff, sizeof(buff), system_charset_info), *res;
1246 ulonglong default_value, current_value;
1247 if (var->type == OPT_GLOBAL)
1248 {
1249 default_value= option.def_value;
1250 current_value= global_var(ulonglong);
1251 }
1252 else
1253 {
1254 default_value= global_var(ulonglong);
1255 current_value= session_var(thd, ulonglong);
1256 }
1257
1258 if (var->value->result_type() == STRING_RESULT)
1259 {
1260 if (!(res=var->value->val_str(&str)))
1261 return true;
1262 else
1263 {
1264 char *error;
1265 uint error_len;
1266
1267 var->save_result.ulonglong_value=
1268 find_set_from_flags(&typelib,
1269 typelib.count,
1270 current_value,
1271 default_value,
1272 res->ptr(), res->length(),
1273 &error, &error_len);
1274 if (unlikely(error))
1275 {
1276 ErrConvString err(error, error_len, res->charset());
1277 my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr());
1278 return true;
1279 }
1280 }
1281 }
1282 else
1283 {
1284 longlong tmp=var->value->val_int();
1285 if ((tmp < 0 && ! var->value->unsigned_flag)
1286 || (ulonglong)tmp > my_set_bits(typelib.count))
1287 return true;
1288 else
1289 var->save_result.ulonglong_value= tmp;
1290 }
1291
1292 return false;
1293 }
1294 bool session_update(THD *thd, set_var *var)
1295 {
1296 session_var(thd, ulonglong)= var->save_result.ulonglong_value;
1297 return false;
1298 }
1299 bool global_update(THD *thd, set_var *var)
1300 {
1301 global_var(ulonglong)= var->save_result.ulonglong_value;
1302 return false;
1303 }
1304 void session_save_default(THD *thd, set_var *var)
1305 { var->save_result.ulonglong_value= global_var(ulonglong); }
1306 void global_save_default(THD *thd, set_var *var)
1307 { var->save_result.ulonglong_value= option.def_value; }
1308 uchar *valptr(THD *thd, ulonglong val)
1309 { return (uchar*)flagset_to_string(thd, 0, val, typelib.type_names); }
1310 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
1311 { return valptr(thd, session_var(thd, ulonglong)); }
1312 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
1313 { return valptr(thd, global_var(ulonglong)); }
1314 uchar *default_value_ptr(THD *thd)
1315 { return valptr(thd, option.def_value); }
1316};
1317
1318/**
1319 The class for SET variables - variables taking zero or more values
1320 from the given list. Example: @@sql_mode
1321
1322 Class specific constructor arguments:
1323 char* values[] - 0-terminated list of strings of valid values
1324
1325 Backing store: ulonglong
1326*/
1327class Sys_var_set: public Sys_var_typelib
1328{
1329public:
1330 Sys_var_set(const char *name_arg,
1331 const char *comment, int flag_args, ptrdiff_t off, size_t size,
1332 CMD_LINE getopt,
1333 const char *values[], ulonglong def_val, PolyLock *lock=0,
1334 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
1335 on_check_function on_check_func=0,
1336 on_update_function on_update_func=0,
1337 const char *substitute=0)
1338 : Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
1339 SHOW_CHAR, values, def_val, lock,
1340 binlog_status_arg, on_check_func, on_update_func,
1341 substitute)
1342 {
1343 option.var_type|= GET_SET;
1344 global_var(ulonglong)= def_val;
1345 SYSVAR_ASSERT(typelib.count > 0);
1346 SYSVAR_ASSERT(typelib.count <= 64);
1347 SYSVAR_ASSERT(def_val <= my_set_bits(typelib.count));
1348 SYSVAR_ASSERT(size == sizeof(ulonglong));
1349 }
1350 bool do_check(THD *thd, set_var *var)
1351 {
1352 char buff[STRING_BUFFER_USUAL_SIZE];
1353 String str(buff, sizeof(buff), system_charset_info), *res;
1354
1355 if (var->value->result_type() == STRING_RESULT)
1356 {
1357 if (!(res=var->value->val_str_ascii(&str)))
1358 return true;
1359 else
1360 {
1361 char *error;
1362 uint error_len;
1363 bool not_used;
1364
1365 var->save_result.ulonglong_value=
1366 find_set(&typelib, res->ptr(), res->length(), NULL,
1367 &error, &error_len, &not_used);
1368 /*
1369 note, we only issue an error if error_len > 0.
1370 That is even while empty (zero-length) values are considered
1371 errors by find_set(), these errors are ignored here
1372 */
1373 if (unlikely(error_len))
1374 {
1375 ErrConvString err(error, error_len, res->charset());
1376 my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr());
1377 return true;
1378 }
1379 }
1380 }
1381 else
1382 {
1383 longlong tmp=var->value->val_int();
1384 if ((tmp < 0 && ! var->value->unsigned_flag)
1385 || (ulonglong)tmp > my_set_bits(typelib.count))
1386 return true;
1387 else
1388 var->save_result.ulonglong_value= tmp;
1389 }
1390
1391 return false;
1392 }
1393 bool session_update(THD *thd, set_var *var)
1394 {
1395 session_var(thd, ulonglong)= var->save_result.ulonglong_value;
1396 return false;
1397 }
1398 bool global_update(THD *thd, set_var *var)
1399 {
1400 global_var(ulonglong)= var->save_result.ulonglong_value;
1401 return false;
1402 }
1403 void session_save_default(THD *thd, set_var *var)
1404 { var->save_result.ulonglong_value= global_var(ulonglong); }
1405 void global_save_default(THD *thd, set_var *var)
1406 { var->save_result.ulonglong_value= option.def_value; }
1407 uchar *valptr(THD *thd, ulonglong val)
1408 { return (uchar*)set_to_string(thd, 0, val, typelib.type_names); }
1409 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
1410 { return valptr(thd, session_var(thd, ulonglong)); }
1411 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
1412 { return valptr(thd, global_var(ulonglong)); }
1413 uchar *default_value_ptr(THD *thd)
1414 { return valptr(thd, option.def_value); }
1415};
1416
1417/**
1418 The class for variables which value is a plugin.
1419 Example: @@default_storage_engine
1420
1421 Class specific constructor arguments:
1422 int plugin_type_arg (for example MYSQL_STORAGE_ENGINE_PLUGIN)
1423
1424 Backing store: plugin_ref
1425
1426 @note
1427 these variables don't support command-line equivalents, any such
1428 command-line options should be added manually to my_long_options in mysqld.cc
1429*/
1430class Sys_var_plugin: public sys_var
1431{
1432 int plugin_type;
1433public:
1434 Sys_var_plugin(const char *name_arg,
1435 const char *comment, int flag_args, ptrdiff_t off, size_t size,
1436 CMD_LINE getopt,
1437 int plugin_type_arg, char **def_val, PolyLock *lock=0,
1438 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
1439 on_check_function on_check_func=0,
1440 on_update_function on_update_func=0,
1441 const char *substitute=0)
1442 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
1443 getopt.arg_type, SHOW_CHAR, (intptr)def_val,
1444 lock, binlog_status_arg, on_check_func, on_update_func,
1445 substitute),
1446 plugin_type(plugin_type_arg)
1447 {
1448 option.var_type|= GET_STR;
1449 SYSVAR_ASSERT(size == sizeof(plugin_ref));
1450 SYSVAR_ASSERT(getopt.id < 0); // force NO_CMD_LINE
1451 }
1452 bool do_check(THD *thd, set_var *var)
1453 {
1454 char buff[STRING_BUFFER_USUAL_SIZE];
1455 String str(buff,sizeof(buff), system_charset_info), *res;
1456 if (!(res=var->value->val_str(&str)))
1457 var->save_result.plugin= NULL;
1458 else
1459 {
1460 const LEX_CSTRING pname= { const_cast<char*>(res->ptr()), res->length() };
1461 plugin_ref plugin;
1462
1463 // special code for storage engines (e.g. to handle historical aliases)
1464 if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN)
1465 plugin= ha_resolve_by_name(thd, &pname, false);
1466 else
1467 plugin= my_plugin_lock_by_name(thd, &pname, plugin_type);
1468 if (unlikely(!plugin))
1469 {
1470 // historically different error code
1471 if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN)
1472 {
1473 ErrConvString err(res);
1474 my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), err.ptr());
1475 }
1476 return true;
1477 }
1478 var->save_result.plugin= plugin;
1479 }
1480 return false;
1481 }
1482 void do_update(plugin_ref *valptr, plugin_ref newval)
1483 {
1484 plugin_ref oldval= *valptr;
1485 if (oldval != newval)
1486 {
1487 *valptr= newval ? my_plugin_lock(NULL, newval) : 0;
1488 plugin_unlock(NULL, oldval);
1489 }
1490 }
1491 bool session_update(THD *thd, set_var *var)
1492 {
1493 do_update((plugin_ref*)session_var_ptr(thd),
1494 var->save_result.plugin);
1495 return false;
1496 }
1497 bool global_update(THD *thd, set_var *var)
1498 {
1499 do_update((plugin_ref*)global_var_ptr(),
1500 var->save_result.plugin);
1501 return false;
1502 }
1503 void session_save_default(THD *thd, set_var *var)
1504 {
1505 plugin_ref plugin= global_var(plugin_ref);
1506 var->save_result.plugin= plugin ? my_plugin_lock(thd, plugin) : 0;
1507 }
1508 plugin_ref get_default(THD *thd)
1509 {
1510 char *default_value= *reinterpret_cast<char**>(option.def_value);
1511 if (!default_value)
1512 return 0;
1513
1514 LEX_CSTRING pname= { default_value, strlen(default_value) };
1515 plugin_ref plugin;
1516
1517 if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN)
1518 plugin= ha_resolve_by_name(thd, &pname, false);
1519 else
1520 plugin= my_plugin_lock_by_name(thd, &pname, plugin_type);
1521 DBUG_ASSERT(plugin);
1522 return my_plugin_lock(thd, plugin);
1523 }
1524
1525 void global_save_default(THD *thd, set_var *var)
1526 {
1527 var->save_result.plugin= get_default(thd);
1528 }
1529
1530 uchar *valptr(THD *thd, plugin_ref plugin)
1531 {
1532 return (uchar*)(plugin ? thd->strmake(plugin_name(plugin)->str,
1533 plugin_name(plugin)->length) : 0);
1534 }
1535 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
1536 { return valptr(thd, session_var(thd, plugin_ref)); }
1537 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
1538 { return valptr(thd, global_var(plugin_ref)); }
1539 uchar *default_value_ptr(THD *thd)
1540 { return valptr(thd, get_default(thd)); }
1541};
1542
1543/**
1544 Class for variables that containg a list of plugins.
1545 Currently this is used only for @@gtid_pos_auto_create_engines
1546
1547 Backing store: plugin_ref
1548
1549 @note
1550 Currently this is only used for storage engine type plugins, and thus only
1551 storage engine type plugin is implemented. It could be extended to other
1552 plugin types later if needed, similar to Sys_var_plugin.
1553
1554 These variables don't support command-line equivalents, any such
1555 command-line options should be added manually to my_long_options in mysqld.cc
1556
1557 Note on lifetimes of resources allocated: We allocate a zero-terminated array
1558 of plugin_ref*, and lock the contained plugins. The list in the global
1559 variable must be freed (with free_engine_list()). However, the way Sys_var
1560 works, there is no place to explicitly free other lists, like the one
1561 returned from get_default().
1562
1563 Therefore, the code needs to work with temporary lists, which are
1564 registered in the THD to be automatically freed (and plugins similarly
1565 automatically unlocked). This is why do_check() allocates a temporary
1566 list, from which do_update() then makes a permanent copy.
1567*/
1568class Sys_var_pluginlist: public sys_var
1569{
1570public:
1571 Sys_var_pluginlist(const char *name_arg,
1572 const char *comment, int flag_args, ptrdiff_t off, size_t size,
1573 CMD_LINE getopt,
1574 char **def_val, PolyLock *lock=0,
1575 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
1576 on_check_function on_check_func=0,
1577 on_update_function on_update_func=0,
1578 const char *substitute=0)
1579 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
1580 getopt.arg_type, SHOW_CHAR, (intptr)def_val,
1581 lock, binlog_status_arg, on_check_func, on_update_func,
1582 substitute)
1583 {
1584 option.var_type|= GET_STR;
1585 SYSVAR_ASSERT(size == sizeof(plugin_ref));
1586 SYSVAR_ASSERT(getopt.id < 0); // force NO_CMD_LINE
1587 }
1588 bool do_check(THD *thd, set_var *var)
1589 {
1590 char buff[STRING_BUFFER_USUAL_SIZE];
1591 String str(buff,sizeof(buff), system_charset_info), *res;
1592 plugin_ref *plugins;
1593
1594 if (!(res=var->value->val_str(&str)))
1595 plugins= resolve_engine_list(thd, "", 0, true, true);
1596 else
1597 plugins= resolve_engine_list(thd, res->ptr(), res->length(), true, true);
1598 if (!plugins)
1599 return true;
1600 var->save_result.plugins= plugins;
1601 return false;
1602 }
1603 void do_update(plugin_ref **valptr, plugin_ref* newval)
1604 {
1605 plugin_ref *oldval= *valptr;
1606 *valptr= copy_engine_list(newval);
1607 free_engine_list(oldval);
1608 }
1609 bool session_update(THD *thd, set_var *var)
1610 {
1611 do_update((plugin_ref**)session_var_ptr(thd),
1612 var->save_result.plugins);
1613 return false;
1614 }
1615 bool global_update(THD *thd, set_var *var)
1616 {
1617 do_update((plugin_ref**)global_var_ptr(),
1618 var->save_result.plugins);
1619 return false;
1620 }
1621 void session_save_default(THD *thd, set_var *var)
1622 {
1623 plugin_ref* plugins= global_var(plugin_ref *);
1624 var->save_result.plugins= plugins ? temp_copy_engine_list(thd, plugins) : 0;
1625 }
1626 plugin_ref *get_default(THD *thd)
1627 {
1628 char *default_value= *reinterpret_cast<char**>(option.def_value);
1629 if (!default_value)
1630 return 0;
1631 return resolve_engine_list(thd, default_value, strlen(default_value),
1632 false, true);
1633 }
1634
1635 void global_save_default(THD *thd, set_var *var)
1636 {
1637 var->save_result.plugins= get_default(thd);
1638 }
1639
1640 uchar *valptr(THD *thd, plugin_ref *plugins)
1641 {
1642 return (uchar*)pretty_print_engine_list(thd, plugins);
1643 }
1644 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
1645 { return valptr(thd, session_var(thd, plugin_ref*)); }
1646 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
1647 { return valptr(thd, global_var(plugin_ref*)); }
1648 uchar *default_value_ptr(THD *thd)
1649 { return valptr(thd, get_default(thd)); }
1650};
1651
1652#if defined(ENABLED_DEBUG_SYNC)
1653
1654#include "debug_sync.h"
1655
1656/**
1657 The class for @@debug_sync session-only variable
1658*/
1659class Sys_var_debug_sync :public sys_var
1660{
1661public:
1662 Sys_var_debug_sync(const char *name_arg,
1663 const char *comment, int flag_args,
1664 CMD_LINE getopt,
1665 const char *def_val, PolyLock *lock=0,
1666 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
1667 on_check_function on_check_func=0,
1668 on_update_function on_update_func=0,
1669 const char *substitute=0)
1670 : sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id,
1671 getopt.arg_type, SHOW_CHAR, (intptr)def_val,
1672 lock, binlog_status_arg, on_check_func, on_update_func,
1673 substitute)
1674 {
1675 SYSVAR_ASSERT(scope() == ONLY_SESSION);
1676 option.var_type|= GET_STR;
1677 }
1678 bool do_check(THD *thd, set_var *var)
1679 {
1680 char buff[STRING_BUFFER_USUAL_SIZE];
1681 String str(buff, sizeof(buff), system_charset_info), *res;
1682
1683 if (!(res=var->value->val_str(&str)))
1684 var->save_result.string_value= empty_lex_str;
1685 else
1686 {
1687 if (!thd->make_lex_string(&var->save_result.string_value,
1688 res->ptr(), res->length()))
1689 return true;
1690 }
1691 return false;
1692 }
1693 bool session_update(THD *thd, set_var *var)
1694 {
1695 return debug_sync_update(thd, var->save_result.string_value.str,
1696 var->save_result.string_value.length);
1697 }
1698 bool global_update(THD *thd, set_var *var)
1699 {
1700 DBUG_ASSERT(FALSE);
1701 return true;
1702 }
1703 void session_save_default(THD *thd, set_var *var)
1704 {
1705 var->save_result.string_value.str= const_cast<char*>("");
1706 var->save_result.string_value.length= 0;
1707 }
1708 void global_save_default(THD *thd, set_var *var)
1709 {
1710 DBUG_ASSERT(FALSE);
1711 }
1712 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
1713 {
1714 return debug_sync_value_ptr(thd);
1715 }
1716 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
1717 {
1718 DBUG_ASSERT(FALSE);
1719 return 0;
1720 }
1721 uchar *default_value_ptr(THD *thd)
1722 { return (uchar*)""; }
1723};
1724#endif /* defined(ENABLED_DEBUG_SYNC) */
1725
1726
1727/**
1728 The class for bit variables - a variant of boolean that stores the value
1729 in a bit.
1730
1731 Class specific constructor arguments:
1732 ulonglong bitmask_arg - the mask for the bit to set in the ulonglong
1733 backing store
1734
1735 Backing store: ulonglong
1736
1737 @note
1738 This class supports the "reverse" semantics, when the value of the bit
1739 being 0 corresponds to the value of variable being set. To activate it
1740 use REVERSE(bitmask) instead of simply bitmask in the constructor.
1741
1742 @note
1743 variables of this class cannot be set from the command line as
1744 my_getopt does not support bits.
1745*/
1746class Sys_var_bit: public Sys_var_typelib
1747{
1748 ulonglong bitmask;
1749 bool reverse_semantics;
1750 void set(uchar *ptr, ulonglong value)
1751 {
1752 if ((value != 0) ^ reverse_semantics)
1753 (*(ulonglong *)ptr)|= bitmask;
1754 else
1755 (*(ulonglong *)ptr)&= ~bitmask;
1756 }
1757public:
1758 Sys_var_bit(const char *name_arg,
1759 const char *comment, int flag_args, ptrdiff_t off, size_t size,
1760 CMD_LINE getopt,
1761 ulonglong bitmask_arg, my_bool def_val, PolyLock *lock=0,
1762 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
1763 on_check_function on_check_func=0,
1764 on_update_function on_update_func=0,
1765 const char *substitute=0)
1766 : Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
1767 SHOW_MY_BOOL, bool_values, def_val, lock,
1768 binlog_status_arg, on_check_func, on_update_func,
1769 substitute)
1770 {
1771 option.var_type|= GET_BIT;
1772 reverse_semantics= my_count_bits(bitmask_arg) > 1;
1773 bitmask= reverse_semantics ? ~bitmask_arg : bitmask_arg;
1774 option.block_size= reverse_semantics ? -(long) bitmask : (long)bitmask;
1775 set(global_var_ptr(), def_val);
1776 SYSVAR_ASSERT(def_val < 2);
1777 SYSVAR_ASSERT(size == sizeof(ulonglong));
1778 }
1779 bool session_update(THD *thd, set_var *var)
1780 {
1781 set(session_var_ptr(thd), var->save_result.ulonglong_value);
1782 return false;
1783 }
1784 bool global_update(THD *thd, set_var *var)
1785 {
1786 set(global_var_ptr(), var->save_result.ulonglong_value);
1787 return false;
1788 }
1789 void session_save_default(THD *thd, set_var *var)
1790 { var->save_result.ulonglong_value= global_var(ulonglong) & bitmask; }
1791 void global_save_default(THD *thd, set_var *var)
1792 { var->save_result.ulonglong_value= option.def_value; }
1793
1794 uchar *valptr(THD *thd, ulonglong val)
1795 {
1796 thd->sys_var_tmp.my_bool_value= reverse_semantics ^ ((val & bitmask) != 0);
1797 return (uchar*) &thd->sys_var_tmp.my_bool_value;
1798 }
1799 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
1800 { return valptr(thd, session_var(thd, ulonglong)); }
1801 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
1802 { return valptr(thd, global_var(ulonglong)); }
1803 uchar *default_value_ptr(THD *thd)
1804 {
1805 thd->sys_var_tmp.my_bool_value= option.def_value != 0;
1806 return (uchar*) &thd->sys_var_tmp.my_bool_value;
1807 }
1808};
1809
1810/**
1811 The class for variables that have a special meaning for a session,
1812 such as @@timestamp or @@rnd_seed1, their values typically cannot be read
1813 from SV structure, and a special "read" callback is provided.
1814
1815 Class specific constructor arguments:
1816 everything derived from Sys_var_ulonglong
1817 session_special_read_function read_func_arg
1818
1819 Backing store: ulonglong
1820
1821 @note
1822 These variables are session-only, global or command-line equivalents
1823 are not supported as they're generally meaningless.
1824*/
1825class Sys_var_session_special: public Sys_var_ulonglong
1826{
1827 typedef bool (*session_special_update_function)(THD *thd, set_var *var);
1828 typedef ulonglong (*session_special_read_function)(THD *thd);
1829
1830 session_special_read_function read_func;
1831 session_special_update_function update_func;
1832public:
1833 Sys_var_session_special(const char *name_arg,
1834 const char *comment, int flag_args,
1835 CMD_LINE getopt,
1836 ulonglong min_val, ulonglong max_val, uint block_size,
1837 PolyLock *lock, enum binlog_status_enum binlog_status_arg,
1838 on_check_function on_check_func,
1839 session_special_update_function update_func_arg,
1840 session_special_read_function read_func_arg,
1841 const char *substitute=0)
1842 : Sys_var_ulonglong(name_arg, comment, flag_args, 0,
1843 sizeof(ulonglong), getopt, min_val,
1844 max_val, 0, block_size, lock, binlog_status_arg, on_check_func, 0,
1845 substitute),
1846 read_func(read_func_arg), update_func(update_func_arg)
1847 {
1848 SYSVAR_ASSERT(scope() == ONLY_SESSION);
1849 SYSVAR_ASSERT(getopt.id < 0); // NO_CMD_LINE, because the offset is fake
1850 }
1851 bool session_update(THD *thd, set_var *var)
1852 { return update_func(thd, var); }
1853 bool global_update(THD *thd, set_var *var)
1854 {
1855 DBUG_ASSERT(FALSE);
1856 return true;
1857 }
1858 void session_save_default(THD *thd, set_var *var)
1859 { var->value= 0; }
1860 void global_save_default(THD *thd, set_var *var)
1861 { DBUG_ASSERT(FALSE); }
1862 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
1863 {
1864 thd->sys_var_tmp.ulonglong_value= read_func(thd);
1865 return (uchar*) &thd->sys_var_tmp.ulonglong_value;
1866 }
1867 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
1868 {
1869 DBUG_ASSERT(FALSE);
1870 return 0;
1871 }
1872 uchar *default_value_ptr(THD *thd)
1873 {
1874 thd->sys_var_tmp.ulonglong_value= 0;
1875 return (uchar*) &thd->sys_var_tmp.ulonglong_value;
1876 }
1877};
1878
1879
1880/*
1881 Dedicated class because of a weird behavior of a default value.
1882 Assigning timestamp to itself
1883
1884 SET @@timestamp = @@timestamp
1885
1886 make it non-default and stops the time flow.
1887*/
1888class Sys_var_timestamp: public Sys_var_double
1889{
1890public:
1891 Sys_var_timestamp(const char *name_arg,
1892 const char *comment, int flag_args,
1893 CMD_LINE getopt,
1894 double min_val, double max_val,
1895 PolyLock *lock, enum binlog_status_enum binlog_status_arg,
1896 on_check_function on_check_func=0)
1897 : Sys_var_double(name_arg, comment, flag_args, 0,
1898 sizeof(double), getopt, min_val,
1899 max_val, 0, lock, binlog_status_arg, on_check_func)
1900 {
1901 SYSVAR_ASSERT(scope() == ONLY_SESSION);
1902 SYSVAR_ASSERT(getopt.id < 0); // NO_CMD_LINE, because the offset is fake
1903 }
1904 bool session_update(THD *thd, set_var *var)
1905 {
1906 if (var->value)
1907 {
1908 my_hrtime_t hrtime = { hrtime_from_time(var->save_result.double_value) };
1909 thd->set_time(hrtime);
1910 }
1911 else // SET timestamp=DEFAULT
1912 thd->user_time.val= 0;
1913 return false;
1914 }
1915 bool global_update(THD *thd, set_var *var)
1916 {
1917 DBUG_ASSERT(FALSE);
1918 return true;
1919 }
1920 bool session_is_default(THD *thd)
1921 {
1922 return thd->user_time.val == 0;
1923 }
1924 void session_save_default(THD *thd, set_var *var)
1925 { var->value= 0; }
1926 void global_save_default(THD *thd, set_var *var)
1927 { DBUG_ASSERT(FALSE); }
1928 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
1929 {
1930 thd->sys_var_tmp.double_value= thd->start_time +
1931 thd->start_time_sec_part/(double)TIME_SECOND_PART_FACTOR;
1932 return (uchar*) &thd->sys_var_tmp.double_value;
1933 }
1934 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
1935 {
1936 DBUG_ASSERT(FALSE);
1937 return 0;
1938 }
1939 uchar *default_value_ptr(THD *thd)
1940 {
1941 thd->sys_var_tmp.double_value= 0;
1942 return (uchar*) &thd->sys_var_tmp.double_value;
1943 }
1944};
1945
1946
1947/**
1948 The class for read-only variables that show whether a particular
1949 feature is supported by the server. Example: have_compression
1950
1951 Backing store: enum SHOW_COMP_OPTION
1952
1953 @note
1954 These variables are necessarily read-only, only global, and have no
1955 command-line equivalent.
1956*/
1957class Sys_var_have: public sys_var
1958{
1959public:
1960 Sys_var_have(const char *name_arg,
1961 const char *comment, int flag_args, ptrdiff_t off, size_t size,
1962 CMD_LINE getopt,
1963 PolyLock *lock=0,
1964 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
1965 on_check_function on_check_func=0,
1966 on_update_function on_update_func=0,
1967 const char *substitute=0)
1968 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
1969 getopt.arg_type, SHOW_CHAR, 0,
1970 lock, binlog_status_arg, on_check_func, on_update_func,
1971 substitute)
1972 {
1973 SYSVAR_ASSERT(scope() == GLOBAL);
1974 SYSVAR_ASSERT(getopt.id < 0);
1975 SYSVAR_ASSERT(lock == 0);
1976 SYSVAR_ASSERT(binlog_status_arg == VARIABLE_NOT_IN_BINLOG);
1977 SYSVAR_ASSERT(is_readonly());
1978 SYSVAR_ASSERT(on_update == 0);
1979 SYSVAR_ASSERT(size == sizeof(enum SHOW_COMP_OPTION));
1980 option.var_type|= GET_STR;
1981 }
1982 bool do_check(THD *thd, set_var *var) {
1983 DBUG_ASSERT(FALSE);
1984 return true;
1985 }
1986 bool session_update(THD *thd, set_var *var)
1987 {
1988 DBUG_ASSERT(FALSE);
1989 return true;
1990 }
1991 bool global_update(THD *thd, set_var *var)
1992 {
1993 DBUG_ASSERT(FALSE);
1994 return true;
1995 }
1996 void session_save_default(THD *thd, set_var *var) { }
1997 void global_save_default(THD *thd, set_var *var) { }
1998 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
1999 {
2000 DBUG_ASSERT(FALSE);
2001 return 0;
2002 }
2003 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
2004 {
2005 return (uchar*)show_comp_option_name[global_var(enum SHOW_COMP_OPTION)];
2006 }
2007};
2008
2009/**
2010 Generic class for variables for storing entities that are internally
2011 represented as structures, have names, and possibly can be referred to by
2012 numbers. Examples: character sets, collations, locales,
2013
2014 Class specific constructor arguments:
2015 ptrdiff_t name_offset - offset of the 'name' field in the structure
2016
2017 Backing store: void*
2018
2019 @note
2020 As every such a structure requires special treatment from my_getopt,
2021 these variables don't support command-line equivalents, any such
2022 command-line options should be added manually to my_long_options in mysqld.cc
2023*/
2024class Sys_var_struct: public sys_var
2025{
2026 ptrdiff_t name_offset; // offset to the 'name' property in the structure
2027public:
2028 Sys_var_struct(const char *name_arg,
2029 const char *comment, int flag_args, ptrdiff_t off, size_t size,
2030 CMD_LINE getopt,
2031 ptrdiff_t name_off, void *def_val, PolyLock *lock=0,
2032 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
2033 on_check_function on_check_func=0,
2034 on_update_function on_update_func=0,
2035 const char *substitute=0)
2036 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
2037 getopt.arg_type, SHOW_CHAR, (intptr)def_val,
2038 lock, binlog_status_arg, on_check_func, on_update_func,
2039 substitute),
2040 name_offset(name_off)
2041 {
2042 option.var_type|= GET_ENUM; // because we accept INT and STRING here
2043 /*
2044 struct variables are special on the command line - often (e.g. for
2045 charsets) the name cannot be immediately resolved, but only after all
2046 options (in particular, basedir) are parsed.
2047
2048 thus all struct command-line options should be added manually
2049 to my_long_options in mysqld.cc
2050 */
2051 SYSVAR_ASSERT(getopt.id < 0);
2052 SYSVAR_ASSERT(size == sizeof(void *));
2053 }
2054 bool do_check(THD *thd, set_var *var)
2055 { return false; }
2056 bool session_update(THD *thd, set_var *var)
2057 {
2058 session_var(thd, const void*)= var->save_result.ptr;
2059 return false;
2060 }
2061 bool global_update(THD *thd, set_var *var)
2062 {
2063 global_var(const void*)= var->save_result.ptr;
2064 return false;
2065 }
2066 void session_save_default(THD *thd, set_var *var)
2067 { var->save_result.ptr= global_var(void*); }
2068 void global_save_default(THD *thd, set_var *var)
2069 {
2070 void **default_value= reinterpret_cast<void**>(option.def_value);
2071 var->save_result.ptr= *default_value;
2072 }
2073 uchar *valptr(THD *thd, uchar *val)
2074 { return val ? *(uchar**)(val+name_offset) : 0; }
2075 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
2076 { return valptr(thd, session_var(thd, uchar*)); }
2077 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
2078 { return valptr(thd, global_var(uchar*)); }
2079 uchar *default_value_ptr(THD *thd)
2080 { return valptr(thd, *(uchar**)option.def_value); }
2081};
2082
2083/**
2084 The class for variables that store time zones
2085
2086 Backing store: Time_zone*
2087
2088 @note
2089 Time zones cannot be supported directly by my_getopt, thus
2090 these variables don't support command-line equivalents, any such
2091 command-line options should be added manually to my_long_options in mysqld.cc
2092*/
2093class Sys_var_tz: public sys_var
2094{
2095public:
2096 Sys_var_tz(const char *name_arg,
2097 const char *comment, int flag_args, ptrdiff_t off, size_t size,
2098 CMD_LINE getopt,
2099 Time_zone **def_val, PolyLock *lock=0,
2100 enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
2101 on_check_function on_check_func=0,
2102 on_update_function on_update_func=0,
2103 const char *substitute=0)
2104 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
2105 getopt.arg_type, SHOW_CHAR, (intptr)def_val,
2106 lock, binlog_status_arg, on_check_func, on_update_func,
2107 substitute)
2108 {
2109 SYSVAR_ASSERT(getopt.id < 0);
2110 SYSVAR_ASSERT(size == sizeof(Time_zone *));
2111 option.var_type|= GET_STR;
2112 }
2113 bool do_check(THD *thd, set_var *var)
2114 {
2115 char buff[MAX_TIME_ZONE_NAME_LENGTH];
2116 String str(buff, sizeof(buff), &my_charset_latin1);
2117 String *res= var->value->val_str(&str);
2118
2119 if (!res)
2120 return true;
2121
2122 if (!(var->save_result.time_zone= my_tz_find(thd, res)))
2123 {
2124 ErrConvString err(res);
2125 my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), err.ptr());
2126 return true;
2127 }
2128 return false;
2129 }
2130 bool session_update(THD *thd, set_var *var)
2131 {
2132 session_var(thd, Time_zone*)= var->save_result.time_zone;
2133 return false;
2134 }
2135 bool global_update(THD *thd, set_var *var)
2136 {
2137 global_var(Time_zone*)= var->save_result.time_zone;
2138 return false;
2139 }
2140 void session_save_default(THD *thd, set_var *var)
2141 {
2142 var->save_result.time_zone= global_var(Time_zone*);
2143 }
2144 void global_save_default(THD *thd, set_var *var)
2145 {
2146 var->save_result.time_zone=
2147 *(Time_zone**)(intptr)option.def_value;
2148 }
2149 uchar *valptr(THD *thd, Time_zone *val)
2150 { return (uchar *)(val->get_name()->ptr()); }
2151 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
2152 {
2153 /*
2154 This is an ugly fix for replication: we don't replicate properly queries
2155 invoking system variables' values to update tables; but
2156 CONVERT_TZ(,,@@session.time_zone) is so popular that we make it
2157 replicable (i.e. we tell the binlog code to store the session
2158 timezone). If it's the global value which was used we can't replicate
2159 (binlog code stores session value only).
2160 */
2161 thd->time_zone_used= 1;
2162 return valptr(thd, session_var(thd, Time_zone *));
2163 }
2164 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
2165 { return valptr(thd, global_var(Time_zone*)); }
2166 uchar *default_value_ptr(THD *thd)
2167 { return valptr(thd, *(Time_zone**)option.def_value); }
2168};
2169
2170/**
2171 Special implementation for transaction isolation, that
2172 distingushes between
2173
2174 SET GLOBAL TRANSACTION ISOLATION (stored in global_system_variables)
2175 SET SESSION TRANSACTION ISOLATION (stored in thd->variables)
2176 SET TRANSACTION ISOLATION (stored in thd->tx_isolation)
2177
2178 where the last statement sets isolation level for the next transaction only
2179*/
2180class Sys_var_tx_isolation: public Sys_var_enum
2181{
2182public:
2183 Sys_var_tx_isolation(const char *name_arg,
2184 const char *comment, int flag_args, ptrdiff_t off, size_t size,
2185 CMD_LINE getopt,
2186 const char *values[], uint def_val, PolyLock *lock,
2187 enum binlog_status_enum binlog_status_arg,
2188 on_check_function on_check_func)
2189 :Sys_var_enum(name_arg, comment, flag_args, off, size, getopt,
2190 values, def_val, lock, binlog_status_arg, on_check_func)
2191 {}
2192 bool session_update(THD *thd, set_var *var)
2193 {
2194 if (var->type == OPT_SESSION && Sys_var_enum::session_update(thd, var))
2195 return TRUE;
2196 if (var->type == OPT_DEFAULT || !thd->in_active_multi_stmt_transaction())
2197 {
2198#ifndef EMBEDDED_LIBRARY
2199 Transaction_state_tracker *tst= NULL;
2200
2201 if (thd->variables.session_track_transaction_info > TX_TRACK_NONE)
2202 tst= (Transaction_state_tracker *)
2203 thd->session_tracker.get_tracker(TRANSACTION_INFO_TRACKER);
2204#endif //EMBEDDED_LIBRARY
2205
2206 thd->tx_isolation= (enum_tx_isolation) var->save_result.ulonglong_value;
2207
2208#ifndef EMBEDDED_LIBRARY
2209 if (var->type == OPT_DEFAULT)
2210 {
2211 enum enum_tx_isol_level l;
2212 switch (thd->tx_isolation) {
2213 case ISO_READ_UNCOMMITTED:
2214 l= TX_ISOL_UNCOMMITTED;
2215 break;
2216 case ISO_READ_COMMITTED:
2217 l= TX_ISOL_COMMITTED;
2218 break;
2219 case ISO_REPEATABLE_READ:
2220 l= TX_ISOL_REPEATABLE;
2221 break;
2222 case ISO_SERIALIZABLE:
2223 l= TX_ISOL_SERIALIZABLE;
2224 break;
2225 default:
2226 DBUG_ASSERT(0);
2227 return TRUE;
2228 }
2229 if (tst)
2230 tst->set_isol_level(thd, l);
2231 }
2232 else if (tst)
2233 {
2234 tst->set_isol_level(thd, TX_ISOL_INHERIT);
2235 }
2236#endif //EMBEDDED_LIBRARY
2237 }
2238 return FALSE;
2239 }
2240};
2241
2242
2243/**
2244 Class representing the tx_read_only system variable for setting
2245 default transaction access mode.
2246
2247 Note that there is a special syntax - SET TRANSACTION READ ONLY
2248 (or READ WRITE) that sets the access mode for the next transaction
2249 only.
2250*/
2251
2252class Sys_var_tx_read_only: public Sys_var_mybool
2253{
2254public:
2255 Sys_var_tx_read_only(const char *name_arg, const char *comment, int flag_args,
2256 ptrdiff_t off, size_t size, CMD_LINE getopt,
2257 my_bool def_val, PolyLock *lock,
2258 enum binlog_status_enum binlog_status_arg,
2259 on_check_function on_check_func)
2260 :Sys_var_mybool(name_arg, comment, flag_args, off, size, getopt,
2261 def_val, lock, binlog_status_arg, on_check_func)
2262 {}
2263 virtual bool session_update(THD *thd, set_var *var);
2264};
2265
2266/*
2267 Class for replicate_events_marked_for_skip.
2268 We need a custom update function that ensures the slave is stopped when
2269 the update is happening.
2270*/
2271class Sys_var_replicate_events_marked_for_skip: public Sys_var_enum
2272{
2273public:
2274 Sys_var_replicate_events_marked_for_skip(const char *name_arg,
2275 const char *comment, int flag_args, ptrdiff_t off, size_t size,
2276 CMD_LINE getopt,
2277 const char *values[], uint def_val, PolyLock *lock= 0,
2278 enum binlog_status_enum binlog_status_arg= VARIABLE_NOT_IN_BINLOG)
2279 :Sys_var_enum(name_arg, comment, flag_args, off, size, getopt,
2280 values, def_val, lock, binlog_status_arg)
2281 {}
2282 bool global_update(THD *thd, set_var *var);
2283};
2284
2285/*
2286 Class for handing multi-source replication variables
2287 Variable values are store in Master_info, but to make it possible to
2288 access variable without locks we also store it thd->variables.
2289 These can be used as GLOBAL or SESSION, but both points to the same
2290 variable. This is to make things compatible with MySQL 5.5 where variables
2291 like sql_slave_skip_counter are GLOBAL.
2292*/
2293
2294#define MASTER_INFO_VAR(X) my_offsetof(Master_info, X), sizeof(((Master_info *)0x10)->X)
2295class Sys_var_multi_source_ulonglong;
2296class Master_info;
2297
2298typedef bool (*on_multi_source_update_function)(sys_var *self, THD *thd,
2299 Master_info *mi);
2300bool update_multi_source_variable(sys_var *self,
2301 THD *thd, enum_var_type type);
2302
2303
2304class Sys_var_multi_source_ulonglong :public Sys_var_ulonglong
2305{
2306 ptrdiff_t master_info_offset;
2307 on_multi_source_update_function update_multi_source_variable_func;
2308public:
2309 Sys_var_multi_source_ulonglong(const char *name_arg,
2310 const char *comment, int flag_args,
2311 ptrdiff_t off, size_t size,
2312 CMD_LINE getopt,
2313 ptrdiff_t master_info_offset_arg,
2314 size_t master_info_arg_size,
2315 ulonglong min_val, ulonglong max_val,
2316 ulonglong def_val, uint block_size,
2317 on_multi_source_update_function on_update_func)
2318 :Sys_var_ulonglong(name_arg, comment, flag_args, off, size,
2319 getopt, min_val, max_val, def_val, block_size,
2320 0, VARIABLE_NOT_IN_BINLOG, 0, update_multi_source_variable),
2321 master_info_offset(master_info_offset_arg),
2322 update_multi_source_variable_func(on_update_func)
2323 {
2324 SYSVAR_ASSERT(master_info_arg_size == size);
2325 }
2326 bool global_update(THD *thd, set_var *var)
2327 {
2328 return session_update(thd, var);
2329 }
2330 void session_save_default(THD *thd, set_var *var)
2331 {
2332 /* Use value given in variable declaration */
2333 global_save_default(thd, var);
2334 }
2335 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
2336 {
2337 ulonglong *tmp, res;
2338 tmp= (ulonglong*) (((uchar*)&(thd->variables)) + offset);
2339 res= get_master_info_ulonglong_value(thd, master_info_offset);
2340 *tmp= res;
2341 return (uchar*) tmp;
2342 }
2343 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
2344 {
2345 return session_value_ptr(thd, base);
2346 }
2347 ulonglong get_master_info_ulonglong_value(THD *thd, ptrdiff_t offset);
2348 bool update_variable(THD *thd, Master_info *mi)
2349 {
2350 return update_multi_source_variable_func(this, thd, mi);
2351 }
2352};
2353
2354
2355/**
2356 Class for @@global.gtid_current_pos.
2357*/
2358class Sys_var_gtid_current_pos: public sys_var
2359{
2360public:
2361 Sys_var_gtid_current_pos(const char *name_arg,
2362 const char *comment, int flag_args, ptrdiff_t off, size_t size,
2363 CMD_LINE getopt)
2364 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
2365 getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG,
2366 NULL, NULL, NULL)
2367 {
2368 SYSVAR_ASSERT(getopt.id < 0);
2369 SYSVAR_ASSERT(is_readonly());
2370 option.var_type|= GET_STR;
2371 }
2372 bool do_check(THD *thd, set_var *var)
2373 {
2374 DBUG_ASSERT(false);
2375 return true;
2376 }
2377 bool session_update(THD *thd, set_var *var)
2378 {
2379 DBUG_ASSERT(false);
2380 return true;
2381 }
2382 bool global_update(THD *thd, set_var *var)
2383 {
2384 DBUG_ASSERT(false);
2385 return true;
2386 }
2387 void session_save_default(THD *thd, set_var *var)
2388 {
2389 DBUG_ASSERT(false);
2390 }
2391 void global_save_default(THD *thd, set_var *var)
2392 {
2393 DBUG_ASSERT(false);
2394 }
2395 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
2396 {
2397 DBUG_ASSERT(false);
2398 return NULL;
2399 }
2400 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base);
2401};
2402
2403
2404/**
2405 Class for @@global.gtid_binlog_pos.
2406*/
2407class Sys_var_gtid_binlog_pos: public sys_var
2408{
2409public:
2410 Sys_var_gtid_binlog_pos(const char *name_arg,
2411 const char *comment, int flag_args, ptrdiff_t off, size_t size,
2412 CMD_LINE getopt)
2413 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
2414 getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG,
2415 NULL, NULL, NULL)
2416 {
2417 SYSVAR_ASSERT(getopt.id < 0);
2418 SYSVAR_ASSERT(is_readonly());
2419 option.var_type|= GET_STR;
2420 }
2421 bool do_check(THD *thd, set_var *var)
2422 {
2423 DBUG_ASSERT(false);
2424 return true;
2425 }
2426 bool session_update(THD *thd, set_var *var)
2427 {
2428 DBUG_ASSERT(false);
2429 return true;
2430 }
2431 bool global_update(THD *thd, set_var *var)
2432 {
2433 DBUG_ASSERT(false);
2434 return true;
2435 }
2436 void session_save_default(THD *thd, set_var *var)
2437 {
2438 DBUG_ASSERT(false);
2439 }
2440 void global_save_default(THD *thd, set_var *var)
2441 {
2442 DBUG_ASSERT(false);
2443 }
2444 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
2445 {
2446 DBUG_ASSERT(false);
2447 return NULL;
2448 }
2449 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base);
2450};
2451
2452
2453/**
2454 Class for @@global.gtid_slave_pos.
2455*/
2456class Sys_var_gtid_slave_pos: public sys_var
2457{
2458public:
2459 Sys_var_gtid_slave_pos(const char *name_arg,
2460 const char *comment, int flag_args, ptrdiff_t off, size_t size,
2461 CMD_LINE getopt)
2462 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
2463 getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG,
2464 NULL, NULL, NULL)
2465 {
2466 option.var_type|= GET_STR;
2467 }
2468 bool do_check(THD *thd, set_var *var);
2469 bool session_update(THD *thd, set_var *var)
2470 {
2471 DBUG_ASSERT(false);
2472 return true;
2473 }
2474 bool global_update(THD *thd, set_var *var);
2475 void session_save_default(THD *thd, set_var *var)
2476 {
2477 DBUG_ASSERT(false);
2478 }
2479 void global_save_default(THD *thd, set_var *var)
2480 {
2481 /* Record the attempt to use default so we can error. */
2482 var->value= 0;
2483 }
2484 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
2485 {
2486 DBUG_ASSERT(false);
2487 return NULL;
2488 }
2489 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base);
2490 uchar *default_value_ptr(THD *thd)
2491 { return 0; }
2492};
2493
2494
2495/**
2496 Class for @@global.gtid_binlog_state.
2497*/
2498class Sys_var_gtid_binlog_state: public sys_var
2499{
2500public:
2501 Sys_var_gtid_binlog_state(const char *name_arg,
2502 const char *comment, int flag_args, ptrdiff_t off, size_t size,
2503 CMD_LINE getopt)
2504 : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
2505 getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG,
2506 NULL, NULL, NULL)
2507 {
2508 option.var_type|= GET_STR;
2509 }
2510 bool do_check(THD *thd, set_var *var);
2511 bool session_update(THD *thd, set_var *var)
2512 {
2513 DBUG_ASSERT(false);
2514 return true;
2515 }
2516 bool global_update(THD *thd, set_var *var);
2517 void session_save_default(THD *thd, set_var *var)
2518 {
2519 DBUG_ASSERT(false);
2520 }
2521 void global_save_default(THD *thd, set_var *var)
2522 {
2523 /* Record the attempt to use default so we can error. */
2524 var->value= 0;
2525 }
2526 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
2527 {
2528 DBUG_ASSERT(false);
2529 return NULL;
2530 }
2531 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base);
2532 uchar *default_value_ptr(THD *thd)
2533 { return 0; }
2534};
2535
2536
2537/**
2538 Class for @@session.last_gtid.
2539*/
2540class Sys_var_last_gtid: public sys_var
2541{
2542public:
2543 Sys_var_last_gtid(const char *name_arg,
2544 const char *comment, int flag_args, CMD_LINE getopt)
2545 : sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id,
2546 getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG,
2547 NULL, NULL, NULL)
2548 {
2549 SYSVAR_ASSERT(getopt.id < 0);
2550 SYSVAR_ASSERT(is_readonly());
2551 option.var_type|= GET_STR;
2552 }
2553 bool do_check(THD *thd, set_var *var)
2554 {
2555 DBUG_ASSERT(false);
2556 return true;
2557 }
2558 bool session_update(THD *thd, set_var *var)
2559 {
2560 DBUG_ASSERT(false);
2561 return true;
2562 }
2563 bool global_update(THD *thd, set_var *var)
2564 {
2565 DBUG_ASSERT(false);
2566 return true;
2567 }
2568 void session_save_default(THD *thd, set_var *var)
2569 {
2570 DBUG_ASSERT(false);
2571 }
2572 void global_save_default(THD *thd, set_var *var)
2573 {
2574 DBUG_ASSERT(false);
2575 }
2576 uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base);
2577 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
2578 {
2579 DBUG_ASSERT(false);
2580 return NULL;
2581 }
2582};
2583
2584
2585/**
2586 Class for connection_name.slave_parallel_mode.
2587*/
2588class Sys_var_slave_parallel_mode: public Sys_var_enum
2589{
2590public:
2591 Sys_var_slave_parallel_mode(const char *name_arg,
2592 const char *comment, int flag_args, ptrdiff_t off, size_t size,
2593 CMD_LINE getopt, const char *values[],
2594 enum_slave_parallel_mode def_val)
2595 : Sys_var_enum(name_arg, comment, flag_args, off, size,
2596 getopt, values, def_val)
2597 {
2598 option.var_type|= GET_ASK_ADDR;
2599 option.value= (uchar**)1; // crash me, please
2600 SYSVAR_ASSERT(scope() == GLOBAL);
2601 }
2602 bool global_update(THD *thd, set_var *var);
2603 uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base);
2604};
2605
2606
2607class Sys_var_vers_asof: public Sys_var_enum
2608{
2609public:
2610 static const char *asof_keywords[];
2611
2612public:
2613 Sys_var_vers_asof(const char *name_arg,
2614 const char *comment, int flag_args, ptrdiff_t off, size_t size,
2615 CMD_LINE getopt, const char *values[],
2616 uint def_val)
2617 : Sys_var_enum(name_arg, comment, flag_args, off, size,
2618 getopt, values, def_val)
2619 {
2620 // setval() accepts string rather enum
2621 option.var_type= GET_STR;
2622 }
2623 virtual bool do_check(THD *thd, set_var *var)
2624 {
2625 if (!Sys_var_enum::do_check(thd, var))
2626 return false;
2627 MYSQL_TIME ltime;
2628 bool res= var->value->get_date(&ltime, 0);
2629 if (!res)
2630 {
2631 var->save_result.ulonglong_value= SYSTEM_TIME_AS_OF;
2632 }
2633 return res;
2634 }
2635
2636private:
2637 bool update(set_var *var, vers_asof_timestamp_t &out)
2638 {
2639 bool res= false;
2640 out.type= static_cast<enum_var_type>(var->save_result.ulonglong_value);
2641 if (out.type == SYSTEM_TIME_AS_OF)
2642 {
2643 if (var->value)
2644 {
2645 res= var->value->get_date(&out.ltime, 0);
2646 }
2647 else // set DEFAULT from global var
2648 {
2649 out= global_var(vers_asof_timestamp_t);
2650 res= false;
2651 }
2652 }
2653 return res;
2654 }
2655
2656public:
2657 virtual bool global_update(THD *thd, set_var *var)
2658 {
2659 return update(var, global_var(vers_asof_timestamp_t));
2660 }
2661 virtual bool session_update(THD *thd, set_var *var)
2662 {
2663 return update(var, session_var(thd, vers_asof_timestamp_t));
2664 }
2665
2666private:
2667 uchar *value_ptr(THD *thd, vers_asof_timestamp_t &val)
2668 {
2669 switch (val.type)
2670 {
2671 case SYSTEM_TIME_UNSPECIFIED:
2672 case SYSTEM_TIME_ALL:
2673 return (uchar*) thd->strdup(asof_keywords[val.type]);
2674 case SYSTEM_TIME_AS_OF:
2675 {
2676 uchar *buf= (uchar*) thd->alloc(MAX_DATE_STRING_REP_LENGTH);
2677 if (buf &&!my_datetime_to_str(&val.ltime, (char*) buf, 6))
2678 {
2679 // TODO: figure out variable name
2680 my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "system_versioning_asof_timestamp", "NULL (wrong datetime)");
2681 return (uchar*) thd->strdup("Error: wrong datetime");
2682 }
2683 return buf;
2684 }
2685 default:
2686 break;
2687 }
2688 my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "system_versioning_asof_timestamp", "NULL (wrong range type)");
2689 return (uchar*) thd->strdup("Error: wrong range type");
2690 }
2691
2692public:
2693 virtual uchar *session_value_ptr(THD *thd, const LEX_CSTRING *base)
2694 { return value_ptr(thd, session_var(thd, vers_asof_timestamp_t)); }
2695 virtual uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base)
2696 { return value_ptr(thd, global_var(vers_asof_timestamp_t)); }
2697};
2698