MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sys_vars.h
Go to the documentation of this file.
1 /* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
24 #include "sys_vars_shared.h"
25 #include <my_getopt.h>
26 #include <my_bit.h>
27 #include <my_dir.h>
28 #include "keycaches.h"
29 #include "strfunc.h"
30 #include "tztime.h" // my_tz_find, my_tz_SYSTEM, struct Time_zone
31 #include "rpl_gtid.h"
32 #include <ctype.h>
33 
34 /*
35  a set of mostly trivial (as in f(X)=X) defines below to make system variable
36  declarations more readable
37 */
38 #define VALID_RANGE(X,Y) X,Y
39 #define DEFAULT(X) X
40 #define BLOCK_SIZE(X) X
41 #define GLOBAL_VAR(X) sys_var::GLOBAL, (((char*)&(X))-(char*)&global_system_variables), sizeof(X)
42 #define SESSION_VAR(X) sys_var::SESSION, offsetof(SV, X), sizeof(((SV *)0)->X)
43 #define SESSION_ONLY(X) sys_var::ONLY_SESSION, offsetof(SV, X), sizeof(((SV *)0)->X)
44 #define NO_CMD_LINE CMD_LINE(NO_ARG, -1)
45 /*
46  the define below means that there's no *second* mutex guard,
47  LOCK_global_system_variables always guards all system variables
48 */
49 #define NO_MUTEX_GUARD ((PolyLock*)0)
50 #define IN_BINLOG sys_var::SESSION_VARIABLE_IN_BINLOG
51 #define NOT_IN_BINLOG sys_var::VARIABLE_NOT_IN_BINLOG
52 #define ON_READ(X) X
53 #define ON_CHECK(X) X
54 #define ON_UPDATE(X) X
55 #define READ_ONLY sys_var::READONLY+
56 #define NOT_VISIBLE sys_var::INVISIBLE+
57 // this means that Sys_var_charptr initial value was malloc()ed
58 #define PREALLOCATED sys_var::ALLOCATED+
59 /*
60  Sys_var_bit meaning is reversed, like in
61  @@foreign_key_checks <-> OPTION_NO_FOREIGN_KEY_CHECKS
62 */
63 #define REVERSE(X) ~(X)
64 #define DEPRECATED(X) X
65 
66 #define session_var(THD, TYPE) (*(TYPE*)session_var_ptr(THD))
67 #define global_var(TYPE) (*(TYPE*)global_var_ptr())
68 
69 #if SIZEOF_OFF_T > 4 && defined(BIG_TABLES)
70 #define GET_HA_ROWS GET_ULL
71 #else
72 #define GET_HA_ROWS GET_ULONG
73 #endif
74 
75 enum charset_enum {IN_SYSTEM_CHARSET, IN_FS_CHARSET};
76 
77 static const char *bool_values[3]= {"OFF", "ON", 0};
78 
84 struct CMD_LINE
85 {
86  int id;
87  enum get_opt_arg_type arg_type;
88  CMD_LINE(enum get_opt_arg_type getopt_arg_type, int getopt_id=0)
89  : id(getopt_id), arg_type(getopt_arg_type) {}
90 };
91 
105 template
106  <typename T, ulong ARGT, enum enum_mysql_show_type SHOWT, bool SIGNED>
108 {
109 public:
110  Sys_var_integer(const char *name_arg,
111  const char *comment, int flag_args, ptrdiff_t off, size_t size,
112  CMD_LINE getopt,
113  T min_val, T max_val, T def_val, uint block_size, PolyLock *lock=0,
114  enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
115  on_check_function on_check_func=0,
116  on_update_function on_update_func=0,
117  const char *substitute=0,
118  int parse_flag= PARSE_NORMAL)
119  : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
120  getopt.arg_type, SHOWT, def_val, lock, binlog_status_arg,
121  on_check_func, on_update_func,
122  substitute, parse_flag)
123  {
124  option.var_type= ARGT;
125  option.min_value= min_val;
126  option.max_value= max_val;
127  option.block_size= block_size;
128  option.u_max_value= (uchar**)max_var_ptr();
129  if (max_var_ptr())
130  *max_var_ptr()= max_val;
131 
132  // Do not set global_var for Sys_var_keycache objects
133  if (offset >= 0)
134  global_var(T)= def_val;
135 
136  DBUG_ASSERT(size == sizeof(T));
137  DBUG_ASSERT(min_val < max_val);
138  DBUG_ASSERT(min_val <= def_val);
139  DBUG_ASSERT(max_val >= def_val);
140  DBUG_ASSERT(block_size > 0);
141  DBUG_ASSERT(def_val % block_size == 0);
142  }
143  bool do_check(THD *thd, set_var *var)
144  {
145  my_bool fixed= FALSE;
146  longlong v;
147  ulonglong uv;
148 
149  v= var->value->val_int();
150  if (SIGNED) /* target variable has signed type */
151  {
152  if (var->value->unsigned_flag)
153  {
154  /*
155  Input value is such a large positive number that MySQL used an
156  unsigned item to hold it. When cast to a signed longlong, if the
157  result is negative there is "cycling" and this is incorrect (large
158  positive input value should not end up as a large negative value in
159  the session signed variable to be set); instead, we need to pick the
160  allowed number closest to the positive input value, i.e. pick the
161  biggest allowed positive integer.
162  */
163  if (v < 0)
164  uv= max_of_int_range(ARGT);
165  else /* no cycling, longlong can hold true value */
166  uv= (ulonglong) v;
167  }
168  else
169  uv= v;
170  /* This will further restrict with VALID_RANGE, BLOCK_SIZE */
171  var->save_result.ulonglong_value=
172  getopt_ll_limit_value(uv, &option, &fixed);
173  }
174  else
175  {
176  if (var->value->unsigned_flag)
177  {
178  /* Guaranteed positive input value, ulonglong can hold it */
179  uv= (ulonglong) v;
180  }
181  else
182  {
183  /*
184  Maybe negative input value; in this case, cast to ulonglong makes it
185  positive, which is wrong. Pick the closest allowed value i.e. 0.
186  */
187  uv= (ulonglong) (v < 0 ? 0 : v);
188  }
189  var->save_result.ulonglong_value=
190  getopt_ull_limit_value(uv, &option, &fixed);
191  }
192 
193  if (max_var_ptr())
194  {
195  /* check constraint set with --maximum-...=X */
196  if (SIGNED)
197  {
198  longlong max_val= *max_var_ptr();
199  if (((longlong)(var->save_result.ulonglong_value)) > max_val)
200  var->save_result.ulonglong_value= max_val;
201  /*
202  Signed variable probably has some kind of symmetry. Then it's good
203  to limit negative values just as we limit positive values.
204  */
205  max_val= -max_val;
206  if (((longlong)(var->save_result.ulonglong_value)) < max_val)
207  var->save_result.ulonglong_value= max_val;
208  }
209  else
210  {
211  ulonglong max_val= *max_var_ptr();
212  if (var->save_result.ulonglong_value > max_val)
213  var->save_result.ulonglong_value= max_val;
214  }
215  }
216 
217  return throw_bounds_warning(thd, name.str,
218  var->save_result.ulonglong_value !=
219  (ulonglong)v,
220  var->value->unsigned_flag, v);
221  }
222  bool session_update(THD *thd, set_var *var)
223  {
224  session_var(thd, T)= var->save_result.ulonglong_value;
225  return false;
226  }
227  bool global_update(THD *thd, set_var *var)
228  {
229  global_var(T)= var->save_result.ulonglong_value;
230  return false;
231  }
232  bool check_update_type(Item_result type)
233  { return type != INT_RESULT; }
234  void session_save_default(THD *thd, set_var *var)
235  { var->save_result.ulonglong_value= (ulonglong)*(T*)global_value_ptr(thd, 0); }
236  void global_save_default(THD *thd, set_var *var)
237  { var->save_result.ulonglong_value= option.def_value; }
238  private:
239  T *max_var_ptr()
240  {
241  return scope() == SESSION ? (T*)(((uchar*)&max_system_variables) + offset)
242  : 0;
243  }
244 };
245 
254 
259 {
260 protected:
261  TYPELIB typelib;
262 public:
263  Sys_var_typelib(const char *name_arg,
264  const char *comment, int flag_args, ptrdiff_t off,
265  CMD_LINE getopt,
266  SHOW_TYPE show_val_type_arg, const char *values[],
267  ulonglong def_val, PolyLock *lock,
268  enum binlog_status_enum binlog_status_arg,
269  on_check_function on_check_func, on_update_function on_update_func,
270  const char *substitute, int parse_flag= PARSE_NORMAL)
271  : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
272  getopt.arg_type, show_val_type_arg, def_val, lock,
273  binlog_status_arg, on_check_func,
274  on_update_func, substitute, parse_flag)
275  {
276  for (typelib.count= 0; values[typelib.count]; typelib.count++) /*no-op */;
277  typelib.name="";
278  typelib.type_names= values;
279  typelib.type_lengths= 0; // only used by Fields_enum and Field_set
280  option.typelib= &typelib;
281  }
282  bool do_check(THD *thd, set_var *var) // works for enums and my_bool
283  {
284  char buff[STRING_BUFFER_USUAL_SIZE];
285  String str(buff, sizeof(buff), system_charset_info), *res;
286 
287  if (var->value->result_type() == STRING_RESULT)
288  {
289  if (!(res=var->value->val_str(&str)))
290  return true;
291  else
292  if (!(var->save_result.ulonglong_value=
293  find_type(&typelib, res->ptr(), res->length(), false)))
294  return true;
295  else
296  var->save_result.ulonglong_value--;
297  }
298  else
299  {
300  longlong tmp=var->value->val_int();
301  if (tmp < 0 || tmp >= typelib.count)
302  return true;
303  else
304  var->save_result.ulonglong_value= tmp;
305  }
306 
307  return false;
308  }
309  bool check_update_type(Item_result type)
310  { return type != INT_RESULT && type != STRING_RESULT; }
311 };
312 
328 {
329 public:
330  Sys_var_enum(const char *name_arg,
331  const char *comment, int flag_args, ptrdiff_t off, size_t size,
332  CMD_LINE getopt,
333  const char *values[], uint def_val, PolyLock *lock=0,
334  enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
335  on_check_function on_check_func=0,
336  on_update_function on_update_func=0,
337  const char *substitute=0)
338  : Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
339  SHOW_CHAR, values, def_val, lock,
340  binlog_status_arg, on_check_func, on_update_func,
341  substitute)
342  {
343  option.var_type= GET_ENUM;
344  global_var(ulong)= def_val;
345  DBUG_ASSERT(def_val < typelib.count);
346  DBUG_ASSERT(size == sizeof(ulong));
347  }
348  bool session_update(THD *thd, set_var *var)
349  {
350  session_var(thd, ulong)= var->save_result.ulonglong_value;
351  return false;
352  }
353  bool global_update(THD *thd, set_var *var)
354  {
355  global_var(ulong)= var->save_result.ulonglong_value;
356  return false;
357  }
358  void session_save_default(THD *thd, set_var *var)
359  { var->save_result.ulonglong_value= global_var(ulong); }
360  void global_save_default(THD *thd, set_var *var)
361  { var->save_result.ulonglong_value= option.def_value; }
362  uchar *session_value_ptr(THD *thd, LEX_STRING *base)
363  { return (uchar*)typelib.type_names[session_var(thd, ulong)]; }
364  uchar *global_value_ptr(THD *thd, LEX_STRING *base)
365  { return (uchar*)typelib.type_names[global_var(ulong)]; }
366 };
367 
375 {
376 public:
377  Sys_var_mybool(const char *name_arg,
378  const char *comment, int flag_args, ptrdiff_t off, size_t size,
379  CMD_LINE getopt,
380  my_bool def_val, PolyLock *lock=0,
381  enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
382  on_check_function on_check_func=0,
383  on_update_function on_update_func=0,
384  const char *substitute=0,
385  int parse_flag= PARSE_NORMAL)
386  : Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
387  SHOW_MY_BOOL, bool_values, def_val, lock,
388  binlog_status_arg, on_check_func, on_update_func,
389  substitute, parse_flag)
390  {
391  option.var_type= GET_BOOL;
392  global_var(my_bool)= def_val;
393  DBUG_ASSERT(def_val < 2);
394  DBUG_ASSERT(getopt.arg_type == OPT_ARG || getopt.id == -1);
395  DBUG_ASSERT(size == sizeof(my_bool));
396  }
397  bool session_update(THD *thd, set_var *var)
398  {
399  session_var(thd, my_bool)= var->save_result.ulonglong_value;
400  return false;
401  }
402  bool global_update(THD *thd, set_var *var)
403  {
404  global_var(my_bool)= var->save_result.ulonglong_value;
405  return false;
406  }
407  void session_save_default(THD *thd, set_var *var)
408  { var->save_result.ulonglong_value= (ulonglong)*(my_bool *)global_value_ptr(thd, 0); }
409  void global_save_default(THD *thd, set_var *var)
410  { var->save_result.ulonglong_value= option.def_value; }
411 };
412 
430 {
431 public:
432  Sys_var_charptr(const char *name_arg,
433  const char *comment, int flag_args, ptrdiff_t off, size_t size,
434  CMD_LINE getopt,
435  enum charset_enum is_os_charset_arg,
436  const char *def_val, PolyLock *lock=0,
437  enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
438  on_check_function on_check_func=0,
439  on_update_function on_update_func=0,
440  const char *substitute=0,
441  int parse_flag= PARSE_NORMAL)
442  : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
443  getopt.arg_type, SHOW_CHAR_PTR, (intptr)def_val,
444  lock, binlog_status_arg, on_check_func, on_update_func,
445  substitute, parse_flag)
446  {
447  is_os_charset= is_os_charset_arg == IN_FS_CHARSET;
448  /*
449  use GET_STR_ALLOC - if ALLOCATED it must be *always* allocated,
450  otherwise (GET_STR) you'll never know whether to free it or not.
451  (think of an exit because of an error right after my_getopt)
452  */
453  option.var_type= (flags & ALLOCATED) ? GET_STR_ALLOC : GET_STR;
454  global_var(const char*)= def_val;
455  DBUG_ASSERT(scope() == GLOBAL);
456  DBUG_ASSERT(size == sizeof(char *));
457  }
458  void cleanup()
459  {
460  if (flags & ALLOCATED)
461  my_free(global_var(char*));
462  flags&= ~ALLOCATED;
463  }
464  bool do_check(THD *thd, set_var *var)
465  {
466  char buff[STRING_BUFFER_USUAL_SIZE], buff2[STRING_BUFFER_USUAL_SIZE];
467  String str(buff, sizeof(buff), charset(thd));
468  String str2(buff2, sizeof(buff2), charset(thd)), *res;
469 
470  if (!(res=var->value->val_str(&str)))
471  var->save_result.string_value.str= 0;
472  else
473  {
474  uint32 unused;
475  if (String::needs_conversion(res->length(), res->charset(),
476  charset(thd), &unused))
477  {
478  uint errors;
479  str2.copy(res->ptr(), res->length(), res->charset(), charset(thd),
480  &errors);
481  res=&str2;
482 
483  }
484  var->save_result.string_value.str= thd->strmake(res->ptr(), res->length());
485  var->save_result.string_value.length= res->length();
486  }
487 
488  return false;
489  }
490  bool session_update(THD *thd, set_var *var)
491  {
492  DBUG_ASSERT(FALSE);
493  return true;
494  }
495  bool global_update(THD *thd, set_var *var)
496  {
497  char *new_val, *ptr= var->save_result.string_value.str;
498  size_t len=var->save_result.string_value.length;
499  if (ptr)
500  {
501  new_val= (char*)my_memdup(ptr, len+1, MYF(MY_WME));
502  if (!new_val) return true;
503  new_val[len]=0;
504  }
505  else
506  new_val= 0;
507  if (flags & ALLOCATED)
508  my_free(global_var(char*));
509  flags|= ALLOCATED;
510  global_var(char*)= new_val;
511  return false;
512  }
513  void session_save_default(THD *thd, set_var *var)
514  { DBUG_ASSERT(FALSE); }
515  void global_save_default(THD *thd, set_var *var)
516  {
517  char *ptr= (char*)(intptr)option.def_value;
518  var->save_result.string_value.str= ptr;
519  var->save_result.string_value.length= ptr ? strlen(ptr) : 0;
520  }
521  bool check_update_type(Item_result type)
522  { return type != STRING_RESULT; }
523 };
524 
525 
527 {
528 public:
529  Sys_var_proxy_user(const char *name_arg,
530  const char *comment, enum charset_enum is_os_charset_arg)
531  : sys_var(&all_sys_vars, name_arg, comment,
532  sys_var::READONLY+sys_var::ONLY_SESSION, 0, -1,
533  NO_ARG, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG,
534  NULL, NULL, NULL, PARSE_NORMAL)
535  {
536  is_os_charset= is_os_charset_arg == IN_FS_CHARSET;
537  option.var_type= GET_STR;
538  }
539  bool do_check(THD *thd, set_var *var)
540  {
541  DBUG_ASSERT(FALSE);
542  return true;
543  }
544  bool session_update(THD *thd, set_var *var)
545  {
546  DBUG_ASSERT(FALSE);
547  return true;
548  }
549  bool global_update(THD *thd, set_var *var)
550  {
551  DBUG_ASSERT(FALSE);
552  return false;
553  }
554  void session_save_default(THD *thd, set_var *var)
555  { DBUG_ASSERT(FALSE); }
556  void global_save_default(THD *thd, set_var *var)
557  { DBUG_ASSERT(FALSE); }
558  bool check_update_type(Item_result type)
559  { return true; }
560 protected:
561  virtual uchar *session_value_ptr(THD *thd, LEX_STRING *base)
562  {
563  return thd->security_ctx->proxy_user[0] ?
564  (uchar *) &(thd->security_ctx->proxy_user[0]) : NULL;
565  }
566 };
567 
569 {
570 public:
571  Sys_var_external_user(const char *name_arg, const char *comment_arg,
572  enum charset_enum is_os_charset_arg)
573  : Sys_var_proxy_user (name_arg, comment_arg, is_os_charset_arg)
574  {}
575 
576 protected:
577  virtual uchar *session_value_ptr(THD *thd, LEX_STRING *base)
578  {
579  return thd->security_ctx->proxy_user[0] ?
580  (uchar *) &(thd->security_ctx->proxy_user[0]) : NULL;
581  }
582 };
583 
597 {
598 public:
599  Sys_var_lexstring(const char *name_arg,
600  const char *comment, int flag_args, ptrdiff_t off, size_t size,
601  CMD_LINE getopt,
602  enum charset_enum is_os_charset_arg,
603  const char *def_val, PolyLock *lock=0,
604  enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
605  on_check_function on_check_func=0,
606  on_update_function on_update_func=0,
607  const char *substitute=0)
608  : Sys_var_charptr(name_arg, comment, flag_args, off, sizeof(char*),
609  getopt, is_os_charset_arg, def_val, lock, binlog_status_arg,
610  on_check_func, on_update_func, substitute)
611  {
612  global_var(LEX_STRING).length= strlen(def_val);
613  DBUG_ASSERT(size == sizeof(LEX_STRING));
614  *const_cast<SHOW_TYPE*>(&show_val_type)= SHOW_LEX_STRING;
615  }
616  bool global_update(THD *thd, set_var *var)
617  {
618  if (Sys_var_charptr::global_update(thd, var))
619  return true;
620  global_var(LEX_STRING).length= var->save_result.string_value.length;
621  return false;
622  }
623 };
624 
625 #ifndef DBUG_OFF
626 
637 class Sys_var_dbug: public sys_var
638 {
639 public:
640  Sys_var_dbug(const char *name_arg,
641  const char *comment, int flag_args,
642  CMD_LINE getopt,
643  const char *def_val, PolyLock *lock=0,
644  enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
645  on_check_function on_check_func=0,
646  on_update_function on_update_func=0,
647  const char *substitute=0,
648  int parse_flag= PARSE_NORMAL)
649  : sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id,
650  getopt.arg_type, SHOW_CHAR, (intptr)def_val,
651  lock, binlog_status_arg, on_check_func, on_update_func,
652  substitute, parse_flag)
653  { option.var_type= GET_NO_ARG; }
654  bool do_check(THD *thd, set_var *var)
655  {
656  char buff[STRING_BUFFER_USUAL_SIZE];
657  String str(buff, sizeof(buff), system_charset_info), *res;
658 
659  if (!(res=var->value->val_str(&str)))
660  var->save_result.string_value.str= const_cast<char*>("");
661  else
662  var->save_result.string_value.str= thd->strmake(res->ptr(), res->length());
663  return false;
664  }
665  bool session_update(THD *thd, set_var *var)
666  {
667  const char *val= var->save_result.string_value.str;
668  if (!var->value)
669  DBUG_POP();
670  else
671  DBUG_SET(val);
672  return false;
673  }
674  bool global_update(THD *thd, set_var *var)
675  {
676  const char *val= var->save_result.string_value.str;
677  DBUG_SET_INITIAL(val);
678  return false;
679  }
680  void session_save_default(THD *thd, set_var *var)
681  { }
682  void global_save_default(THD *thd, set_var *var)
683  {
684  char *ptr= (char*)(intptr)option.def_value;
685  var->save_result.string_value.str= ptr;
686  }
687  uchar *session_value_ptr(THD *thd, LEX_STRING *base)
688  {
689  char buf[256];
690  DBUG_EXPLAIN(buf, sizeof(buf));
691  return (uchar*) thd->strdup(buf);
692  }
693  uchar *global_value_ptr(THD *thd, LEX_STRING *base)
694  {
695  char buf[256];
696  DBUG_EXPLAIN_INITIAL(buf, sizeof(buf));
697  return (uchar*) thd->strdup(buf);
698  }
699  bool check_update_type(Item_result type)
700  { return type != STRING_RESULT; }
701 };
702 #endif
703 
704 #define KEYCACHE_VAR(X) sys_var::GLOBAL,offsetof(KEY_CACHE, X), sizeof(((KEY_CACHE *)0)->X)
705 #define keycache_var_ptr(KC, OFF) (((uchar*)(KC))+(OFF))
706 #define keycache_var(KC, OFF) (*(ulonglong*)keycache_var_ptr(KC, OFF))
707 typedef bool (*keycache_update_function)(THD *, KEY_CACHE *, ptrdiff_t, ulonglong);
708 
720 class Sys_var_keycache: public Sys_var_ulonglong
721 {
722  keycache_update_function keycache_update;
723 public:
724  Sys_var_keycache(const char *name_arg,
725  const char *comment, int flag_args, ptrdiff_t off, size_t size,
726  CMD_LINE getopt,
727  ulonglong min_val, ulonglong max_val, ulonglong def_val,
728  ulonglong block_size, PolyLock *lock,
729  enum binlog_status_enum binlog_status_arg,
730  on_check_function on_check_func,
731  keycache_update_function on_update_func,
732  const char *substitute=0)
733  : Sys_var_ulonglong(name_arg, comment, flag_args,
734  -1, /* offset, see base class CTOR */
735  size,
736  getopt, min_val, max_val, def_val,
737  block_size, lock, binlog_status_arg, on_check_func, 0,
738  substitute),
739  keycache_update(on_update_func)
740  {
741  offset= off; /* Remember offset in KEY_CACHE */
742  option.var_type|= GET_ASK_ADDR;
743  option.value= (uchar**)1; // crash me, please
744  keycache_var(dflt_key_cache, off)= def_val;
745  DBUG_ASSERT(scope() == GLOBAL);
746  }
747  bool global_update(THD *thd, set_var *var)
748  {
749  ulonglong new_value= var->save_result.ulonglong_value;
750  LEX_STRING *base_name= &var->base;
751  KEY_CACHE *key_cache;
752 
753  /* If no basename, assume it's for the key cache named 'default' */
754  if (!base_name->length)
755  base_name= &default_key_cache_base;
756 
757  key_cache= get_key_cache(base_name);
758 
759  if (!key_cache)
760  { // Key cache didn't exists */
761  if (!new_value) // Tried to delete cache
762  return false; // Ok, nothing to do
763  if (!(key_cache= create_key_cache(base_name->str, base_name->length)))
764  return true;
765  }
766 
772  if (key_cache->in_init)
773  return true;
774 
775  return keycache_update(thd, key_cache, offset, new_value);
776  }
777  uchar *global_value_ptr(THD *thd, LEX_STRING *base)
778  {
779  KEY_CACHE *key_cache= get_key_cache(base);
780  if (!key_cache)
781  key_cache= &zero_key_cache;
782  return keycache_var_ptr(key_cache, offset);
783  }
784 };
785 
793 class Sys_var_double: public sys_var
794 {
795 public:
796  Sys_var_double(const char *name_arg,
797  const char *comment, int flag_args, ptrdiff_t off, size_t size,
798  CMD_LINE getopt,
799  double min_val, double max_val, double def_val, PolyLock *lock=0,
800  enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
801  on_check_function on_check_func=0,
802  on_update_function on_update_func=0,
803  const char *substitute=0,
804  int parse_flag= PARSE_NORMAL)
805  : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
806  getopt.arg_type, SHOW_DOUBLE,
807  (longlong) getopt_double2ulonglong(def_val),
808  lock, binlog_status_arg, on_check_func, on_update_func,
809  substitute, parse_flag)
810  {
811  option.var_type= GET_DOUBLE;
812  option.min_value= (longlong) getopt_double2ulonglong(min_val);
813  option.max_value= (longlong) getopt_double2ulonglong(max_val);
814  global_var(double)= (double)option.def_value;
815  DBUG_ASSERT(min_val <= max_val);
816  DBUG_ASSERT(min_val <= def_val);
817  DBUG_ASSERT(max_val >= def_val);
818  DBUG_ASSERT(size == sizeof(double));
819  }
820  bool do_check(THD *thd, set_var *var)
821  {
822  my_bool fixed;
823  double v= var->value->val_real();
824  var->save_result.double_value= getopt_double_limit_value(v, &option, &fixed);
825 
826  return throw_bounds_warning(thd, name.str, fixed, v);
827  }
828  bool session_update(THD *thd, set_var *var)
829  {
830  session_var(thd, double)= var->save_result.double_value;
831  return false;
832  }
833  bool global_update(THD *thd, set_var *var)
834  {
835  global_var(double)= var->save_result.double_value;
836  return false;
837  }
838  bool check_update_type(Item_result type)
839  {
840  return type != INT_RESULT && type != REAL_RESULT && type != DECIMAL_RESULT;
841  }
842  void session_save_default(THD *thd, set_var *var)
843  { var->save_result.double_value= global_var(double); }
844  void global_save_default(THD *thd, set_var *var)
845  { var->save_result.double_value= getopt_ulonglong2double(option.def_value); }
846 };
847 
859 {
860 private:
861  my_bool test_flag_value;
862  uint test_flag_mask;
863 public:
864  Sys_var_test_flag(const char *name_arg, const char *comment, uint mask)
865  : Sys_var_mybool(name_arg, comment, READ_ONLY GLOBAL_VAR(test_flag_value),
866  NO_CMD_LINE, DEFAULT(FALSE))
867  {
868  test_flag_mask= mask;
869  }
870  uchar *global_value_ptr(THD *thd, LEX_STRING *base)
871  {
872  test_flag_value= ((test_flags & test_flag_mask) > 0);
873  return (uchar*) &test_flag_value;
874  }
875 };
876 
887 class Sys_var_max_user_conn: public Sys_var_uint
888 {
889 public:
890  Sys_var_max_user_conn(const char *name_arg,
891  const char *comment, int flag_args, ptrdiff_t off, size_t size,
892  CMD_LINE getopt,
893  uint min_val, uint max_val, uint def_val,
894  uint block_size, PolyLock *lock=0,
895  enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
896  on_check_function on_check_func=0,
897  on_update_function on_update_func=0,
898  const char *substitute=0)
899  : Sys_var_uint(name_arg, comment, SESSION, off, size, getopt,
900  min_val, max_val, def_val, block_size,
901  lock, binlog_status_arg, on_check_func, on_update_func,
902  substitute)
903  { }
904  uchar *session_value_ptr(THD *thd, LEX_STRING *base)
905  {
906  const USER_CONN *uc= thd->get_user_connect();
907  if (uc && uc->user_resources.user_conn)
908  return (uchar*) &(uc->user_resources.user_conn);
909  return global_value_ptr(thd, base);
910  }
911 };
912 
913 // overflow-safe (1 << X)-1
914 #define MAX_SET(X) ((((1UL << ((X)-1))-1) << 1) | 1)
915 
931 {
932 public:
933  Sys_var_flagset(const char *name_arg,
934  const char *comment, int flag_args, ptrdiff_t off, size_t size,
935  CMD_LINE getopt,
936  const char *values[], ulonglong def_val, PolyLock *lock=0,
937  enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
938  on_check_function on_check_func=0,
939  on_update_function on_update_func=0,
940  const char *substitute=0)
941  : Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
942  SHOW_CHAR, values, def_val, lock,
943  binlog_status_arg, on_check_func, on_update_func,
944  substitute)
945  {
946  option.var_type= GET_FLAGSET;
947  global_var(ulonglong)= def_val;
948  DBUG_ASSERT(typelib.count > 1);
949  DBUG_ASSERT(typelib.count <= 65);
950  DBUG_ASSERT(def_val < MAX_SET(typelib.count));
951  DBUG_ASSERT(strcmp(values[typelib.count-1], "default") == 0);
952  DBUG_ASSERT(size == sizeof(ulonglong));
953  }
954  bool do_check(THD *thd, set_var *var)
955  {
956  char buff[STRING_BUFFER_USUAL_SIZE];
957  String str(buff, sizeof(buff), system_charset_info), *res;
958  ulonglong default_value, current_value;
959  if (var->type == OPT_GLOBAL)
960  {
961  default_value= option.def_value;
962  current_value= global_var(ulonglong);
963  }
964  else
965  {
966  default_value= global_var(ulonglong);
967  current_value= session_var(thd, ulonglong);
968  }
969 
970  if (var->value->result_type() == STRING_RESULT)
971  {
972  if (!(res=var->value->val_str(&str)))
973  return true;
974  else
975  {
976  char *error;
977  uint error_len;
978 
979  var->save_result.ulonglong_value=
980  find_set_from_flags(&typelib,
981  typelib.count,
982  current_value,
983  default_value,
984  res->ptr(), res->length(),
985  &error, &error_len);
986  if (error)
987  {
988  ErrConvString err(error, error_len, res->charset());
989  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr());
990  return true;
991  }
992  }
993  }
994  else
995  {
996  longlong tmp=var->value->val_int();
997  if ((tmp < 0 && ! var->value->unsigned_flag)
998  || (ulonglong)tmp > MAX_SET(typelib.count))
999  return true;
1000  else
1001  var->save_result.ulonglong_value= tmp;
1002  }
1003 
1004  return false;
1005  }
1006  bool session_update(THD *thd, set_var *var)
1007  {
1008  session_var(thd, ulonglong)= var->save_result.ulonglong_value;
1009  return false;
1010  }
1011  bool global_update(THD *thd, set_var *var)
1012  {
1013  global_var(ulonglong)= var->save_result.ulonglong_value;
1014  return false;
1015  }
1016  void session_save_default(THD *thd, set_var *var)
1017  { var->save_result.ulonglong_value= global_var(ulonglong); }
1018  void global_save_default(THD *thd, set_var *var)
1019  { var->save_result.ulonglong_value= option.def_value; }
1020  uchar *session_value_ptr(THD *thd, LEX_STRING *base)
1021  {
1022  return (uchar*)flagset_to_string(thd, 0, session_var(thd, ulonglong),
1023  typelib.type_names);
1024  }
1025  uchar *global_value_ptr(THD *thd, LEX_STRING *base)
1026  {
1027  return (uchar*)flagset_to_string(thd, 0, global_var(ulonglong),
1028  typelib.type_names);
1029  }
1030 };
1031 
1042 {
1043 public:
1044  Sys_var_set(const char *name_arg,
1045  const char *comment, int flag_args, ptrdiff_t off, size_t size,
1046  CMD_LINE getopt,
1047  const char *values[], ulonglong def_val, PolyLock *lock=0,
1048  enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
1049  on_check_function on_check_func=0,
1050  on_update_function on_update_func=0,
1051  const char *substitute=0)
1052  : Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
1053  SHOW_CHAR, values, def_val, lock,
1054  binlog_status_arg, on_check_func, on_update_func,
1055  substitute)
1056  {
1057  option.var_type= GET_SET;
1058  global_var(ulonglong)= def_val;
1059  DBUG_ASSERT(typelib.count > 0);
1060  DBUG_ASSERT(typelib.count <= 64);
1061  DBUG_ASSERT(def_val < MAX_SET(typelib.count));
1062  DBUG_ASSERT(size == sizeof(ulonglong));
1063  }
1064  bool do_check(THD *thd, set_var *var)
1065  {
1066  char buff[STRING_BUFFER_USUAL_SIZE];
1067  String str(buff, sizeof(buff), system_charset_info), *res;
1068 
1069  if (var->value->result_type() == STRING_RESULT)
1070  {
1071  if (!(res=var->value->val_str(&str)))
1072  return true;
1073  else
1074  {
1075  char *error;
1076  uint error_len;
1077  bool not_used;
1078 
1079  var->save_result.ulonglong_value=
1080  find_set(&typelib, res->ptr(), res->length(), NULL,
1081  &error, &error_len, &not_used);
1082  /*
1083  note, we only issue an error if error_len > 0.
1084  That is even while empty (zero-length) values are considered
1085  errors by find_set(), these errors are ignored here
1086  */
1087  if (error_len)
1088  {
1089  ErrConvString err(error, error_len, res->charset());
1090  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr());
1091  return true;
1092  }
1093  }
1094  }
1095  else
1096  {
1097  longlong tmp=var->value->val_int();
1098  if ((tmp < 0 && ! var->value->unsigned_flag)
1099  || (ulonglong)tmp > MAX_SET(typelib.count))
1100  return true;
1101  else
1102  var->save_result.ulonglong_value= tmp;
1103  }
1104 
1105  return false;
1106  }
1107  bool session_update(THD *thd, set_var *var)
1108  {
1109  session_var(thd, ulonglong)= var->save_result.ulonglong_value;
1110  return false;
1111  }
1112  bool global_update(THD *thd, set_var *var)
1113  {
1114  global_var(ulonglong)= var->save_result.ulonglong_value;
1115  return false;
1116  }
1117  void session_save_default(THD *thd, set_var *var)
1118  { var->save_result.ulonglong_value= global_var(ulonglong); }
1119  void global_save_default(THD *thd, set_var *var)
1120  { var->save_result.ulonglong_value= option.def_value; }
1121  uchar *session_value_ptr(THD *thd, LEX_STRING *base)
1122  {
1123  return (uchar*)set_to_string(thd, 0, session_var(thd, ulonglong),
1124  typelib.type_names);
1125  }
1126  uchar *global_value_ptr(THD *thd, LEX_STRING *base)
1127  {
1128  return (uchar*)set_to_string(thd, 0, global_var(ulonglong),
1129  typelib.type_names);
1130  }
1131 };
1132 
1147 {
1148  int plugin_type;
1149 public:
1150  Sys_var_plugin(const char *name_arg,
1151  const char *comment, int flag_args, ptrdiff_t off, size_t size,
1152  CMD_LINE getopt,
1153  int plugin_type_arg, char **def_val, PolyLock *lock=0,
1154  enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
1155  on_check_function on_check_func=0,
1156  on_update_function on_update_func=0,
1157  const char *substitute=0,
1158  int parse_flag= PARSE_NORMAL)
1159  : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
1160  getopt.arg_type, SHOW_CHAR, (intptr)def_val,
1161  lock, binlog_status_arg, on_check_func, on_update_func,
1162  substitute, parse_flag),
1163  plugin_type(plugin_type_arg)
1164  {
1165  option.var_type= GET_STR;
1166  DBUG_ASSERT(size == sizeof(plugin_ref));
1167  DBUG_ASSERT(getopt.id == -1); // force NO_CMD_LINE
1168  }
1169  bool do_check(THD *thd, set_var *var)
1170  {
1171  char buff[STRING_BUFFER_USUAL_SIZE];
1172  String str(buff,sizeof(buff), system_charset_info), *res;
1173  if (!(res=var->value->val_str(&str)))
1174  var->save_result.plugin= NULL;
1175  else
1176  {
1177  const LEX_STRING pname= { const_cast<char*>(res->ptr()), res->length() };
1178  plugin_ref plugin;
1179 
1180  // special code for storage engines (e.g. to handle historical aliases)
1181  if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN)
1182  plugin= ha_resolve_by_name(thd, &pname, FALSE);
1183  else
1184  plugin= my_plugin_lock_by_name(thd, &pname, plugin_type);
1185  if (!plugin)
1186  {
1187  // historically different error code
1188  if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN)
1189  {
1190  ErrConvString err(res);
1191  my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), err.ptr());
1192  }
1193  return true;
1194  }
1195  var->save_result.plugin= plugin;
1196  }
1197  return false;
1198  }
1199  void do_update(plugin_ref *valptr, plugin_ref newval)
1200  {
1201  plugin_ref oldval= *valptr;
1202  if (oldval != newval)
1203  {
1204  *valptr= my_plugin_lock(NULL, &newval);
1205  plugin_unlock(NULL, oldval);
1206  }
1207  }
1208  bool session_update(THD *thd, set_var *var)
1209  {
1210  do_update((plugin_ref*)session_var_ptr(thd),
1211  var->save_result.plugin);
1212  return false;
1213  }
1214  bool global_update(THD *thd, set_var *var)
1215  {
1216  do_update((plugin_ref*)global_var_ptr(),
1217  var->save_result.plugin);
1218  return false;
1219  }
1220  void session_save_default(THD *thd, set_var *var)
1221  {
1222  plugin_ref plugin= global_var(plugin_ref);
1223  var->save_result.plugin= my_plugin_lock(thd, &plugin);
1224  }
1225  void global_save_default(THD *thd, set_var *var)
1226  {
1227  LEX_STRING pname;
1228  char **default_value= reinterpret_cast<char**>(option.def_value);
1229  pname.str= *default_value;
1230  pname.length= strlen(pname.str);
1231 
1232  plugin_ref plugin;
1233  if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN)
1234  plugin= ha_resolve_by_name(thd, &pname, FALSE);
1235  else
1236  plugin= my_plugin_lock_by_name(thd, &pname, plugin_type);
1237  DBUG_ASSERT(plugin);
1238 
1239  var->save_result.plugin= my_plugin_lock(thd, &plugin);
1240  }
1241  bool check_update_type(Item_result type)
1242  { return type != STRING_RESULT; }
1243  uchar *session_value_ptr(THD *thd, LEX_STRING *base)
1244  {
1245  plugin_ref plugin= session_var(thd, plugin_ref);
1246  return (uchar*)(plugin ? thd->strmake(plugin_name(plugin)->str,
1247  plugin_name(plugin)->length) : 0);
1248  }
1249  uchar *global_value_ptr(THD *thd, LEX_STRING *base)
1250  {
1251  plugin_ref plugin= global_var(plugin_ref);
1252  return (uchar*)(plugin ? thd->strmake(plugin_name(plugin)->str,
1253  plugin_name(plugin)->length) : 0);
1254  }
1255 };
1256 
1257 #if defined(ENABLED_DEBUG_SYNC)
1258 
1261 class Sys_var_debug_sync :public sys_var
1262 {
1263 public:
1264  Sys_var_debug_sync(const char *name_arg,
1265  const char *comment, int flag_args,
1266  CMD_LINE getopt,
1267  const char *def_val, PolyLock *lock=0,
1268  enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
1269  on_check_function on_check_func=0,
1270  on_update_function on_update_func=0,
1271  const char *substitute=0,
1272  int parse_flag= PARSE_NORMAL)
1273  : sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id,
1274  getopt.arg_type, SHOW_CHAR, (intptr)def_val,
1275  lock, binlog_status_arg, on_check_func, on_update_func,
1276  substitute, parse_flag)
1277  {
1278  DBUG_ASSERT(scope() == ONLY_SESSION);
1279  option.var_type= GET_NO_ARG;
1280  }
1281  bool do_check(THD *thd, set_var *var)
1282  {
1283  char buff[STRING_BUFFER_USUAL_SIZE];
1284  String str(buff, sizeof(buff), system_charset_info), *res;
1285 
1286  if (!(res=var->value->val_str(&str)))
1287  var->save_result.string_value.str= const_cast<char*>("");
1288  else
1289  var->save_result.string_value.str= thd->strmake(res->ptr(), res->length());
1290  return false;
1291  }
1292  bool session_update(THD *thd, set_var *var)
1293  {
1294  extern bool debug_sync_update(THD *thd, char *val_str);
1295  return debug_sync_update(thd, var->save_result.string_value.str);
1296  }
1297  bool global_update(THD *thd, set_var *var)
1298  {
1299  DBUG_ASSERT(FALSE);
1300  return true;
1301  }
1302  void session_save_default(THD *thd, set_var *var)
1303  {
1304  var->save_result.string_value.str= const_cast<char*>("");
1305  var->save_result.string_value.length= 0;
1306  }
1307  void global_save_default(THD *thd, set_var *var)
1308  {
1309  DBUG_ASSERT(FALSE);
1310  }
1311  uchar *session_value_ptr(THD *thd, LEX_STRING *base)
1312  {
1313  extern uchar *debug_sync_value_ptr(THD *thd);
1314  return debug_sync_value_ptr(thd);
1315  }
1316  uchar *global_value_ptr(THD *thd, LEX_STRING *base)
1317  {
1318  DBUG_ASSERT(FALSE);
1319  return 0;
1320  }
1321  bool check_update_type(Item_result type)
1322  { return type != STRING_RESULT; }
1323 };
1324 #endif /* defined(ENABLED_DEBUG_SYNC) */
1325 
1346 {
1347  ulonglong bitmask;
1348  bool reverse_semantics;
1349  void set(uchar *ptr, ulonglong value)
1350  {
1351  if ((value != 0) ^ reverse_semantics)
1352  (*(ulonglong *)ptr)|= bitmask;
1353  else
1354  (*(ulonglong *)ptr)&= ~bitmask;
1355  }
1356 public:
1357  Sys_var_bit(const char *name_arg,
1358  const char *comment, int flag_args, ptrdiff_t off, size_t size,
1359  CMD_LINE getopt,
1360  ulonglong bitmask_arg, my_bool def_val, PolyLock *lock=0,
1361  enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
1362  on_check_function on_check_func=0,
1363  on_update_function on_update_func=0,
1364  const char *substitute=0)
1365  : Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
1366  SHOW_MY_BOOL, bool_values, def_val, lock,
1367  binlog_status_arg, on_check_func, on_update_func,
1368  substitute)
1369  {
1370  option.var_type= GET_BOOL;
1371  reverse_semantics= my_count_bits(bitmask_arg) > 1;
1372  bitmask= reverse_semantics ? ~bitmask_arg : bitmask_arg;
1373  set(global_var_ptr(), def_val);
1374  DBUG_ASSERT(def_val < 2);
1375  DBUG_ASSERT(getopt.id == -1); // force NO_CMD_LINE
1376  DBUG_ASSERT(size == sizeof(ulonglong));
1377  }
1378  bool session_update(THD *thd, set_var *var)
1379  {
1380  set(session_var_ptr(thd), var->save_result.ulonglong_value);
1381  return false;
1382  }
1383  bool global_update(THD *thd, set_var *var)
1384  {
1385  set(global_var_ptr(), var->save_result.ulonglong_value);
1386  return false;
1387  }
1388  void session_save_default(THD *thd, set_var *var)
1389  { var->save_result.ulonglong_value= global_var(ulonglong) & bitmask; }
1390  void global_save_default(THD *thd, set_var *var)
1391  { var->save_result.ulonglong_value= option.def_value; }
1392  uchar *session_value_ptr(THD *thd, LEX_STRING *base)
1393  {
1394  thd->sys_var_tmp.my_bool_value= reverse_semantics ^
1395  ((session_var(thd, ulonglong) & bitmask) != 0);
1396  return (uchar*) &thd->sys_var_tmp.my_bool_value;
1397  }
1398  uchar *global_value_ptr(THD *thd, LEX_STRING *base)
1399  {
1400  thd->sys_var_tmp.my_bool_value= reverse_semantics ^
1401  ((global_var(ulonglong) & bitmask) != 0);
1402  return (uchar*) &thd->sys_var_tmp.my_bool_value;
1403  }
1404 };
1405 
1421 class Sys_var_session_special: public Sys_var_ulonglong
1422 {
1423  typedef bool (*session_special_update_function)(THD *thd, set_var *var);
1424  typedef ulonglong (*session_special_read_function)(THD *thd);
1425 
1426  session_special_read_function read_func;
1427  session_special_update_function update_func;
1428 public:
1429  Sys_var_session_special(const char *name_arg,
1430  const char *comment, int flag_args,
1431  CMD_LINE getopt,
1432  ulonglong min_val, ulonglong max_val, ulonglong block_size,
1433  PolyLock *lock, enum binlog_status_enum binlog_status_arg,
1434  on_check_function on_check_func,
1435  session_special_update_function update_func_arg,
1436  session_special_read_function read_func_arg,
1437  const char *substitute=0)
1438  : Sys_var_ulonglong(name_arg, comment, flag_args, 0,
1439  sizeof(ulonglong), getopt, min_val,
1440  max_val, 0, block_size, lock, binlog_status_arg, on_check_func, 0,
1441  substitute),
1442  read_func(read_func_arg), update_func(update_func_arg)
1443  {
1444  DBUG_ASSERT(scope() == ONLY_SESSION);
1445  DBUG_ASSERT(getopt.id == -1); // NO_CMD_LINE, because the offset is fake
1446  }
1447  bool session_update(THD *thd, set_var *var)
1448  { return update_func(thd, var); }
1449  bool global_update(THD *thd, set_var *var)
1450  {
1451  DBUG_ASSERT(FALSE);
1452  return true;
1453  }
1454  void session_save_default(THD *thd, set_var *var)
1455  { var->value= 0; }
1456  void global_save_default(THD *thd, set_var *var)
1457  { DBUG_ASSERT(FALSE); }
1458  uchar *session_value_ptr(THD *thd, LEX_STRING *base)
1459  {
1460  thd->sys_var_tmp.ulonglong_value= read_func(thd);
1461  return (uchar*) &thd->sys_var_tmp.ulonglong_value;
1462  }
1463  uchar *global_value_ptr(THD *thd, LEX_STRING *base)
1464  {
1465  DBUG_ASSERT(FALSE);
1466  return 0;
1467  }
1468 };
1469 
1470 
1475 {
1476  typedef bool (*session_special_update_function)(THD *thd, set_var *var);
1477  typedef double (*session_special_read_double_function)(THD *thd);
1478 
1479  session_special_read_double_function read_func;
1480  session_special_update_function update_func;
1481 public:
1482  Sys_var_session_special_double(const char *name_arg,
1483  const char *comment, int flag_args,
1484  CMD_LINE getopt,
1485  ulonglong min_val, ulonglong max_val, ulonglong block_size,
1486  PolyLock *lock, enum binlog_status_enum binlog_status_arg,
1487  on_check_function on_check_func,
1488  session_special_update_function update_func_arg,
1489  session_special_read_double_function read_func_arg,
1490  const char *substitute=0)
1491  : Sys_var_double(name_arg, comment, flag_args, 0,
1492  sizeof(double), getopt,
1493  min_val, max_val, 0,
1494  lock, binlog_status_arg, on_check_func, 0,
1495  substitute),
1496  read_func(read_func_arg), update_func(update_func_arg)
1497  {
1498  DBUG_ASSERT(scope() == ONLY_SESSION);
1499  DBUG_ASSERT(getopt.id == -1); // NO_CMD_LINE, because the offset is fake
1500  }
1501  bool session_update(THD *thd, set_var *var)
1502  { return update_func(thd, var); }
1503  bool global_update(THD *thd, set_var *var)
1504  {
1505  DBUG_ASSERT(FALSE);
1506  return true;
1507  }
1508  void session_save_default(THD *thd, set_var *var)
1509  { var->value= 0; }
1510  void global_save_default(THD *thd, set_var *var)
1511  { DBUG_ASSERT(FALSE); }
1512  uchar *session_value_ptr(THD *thd, LEX_STRING *base)
1513  {
1514  thd->sys_var_tmp.double_value= read_func(thd);
1515  return (uchar *) &thd->sys_var_tmp.double_value;
1516  }
1517  uchar *global_value_ptr(THD *thd, LEX_STRING *base)
1518  {
1519  DBUG_ASSERT(FALSE);
1520  return 0;
1521  }
1522 };
1523 
1524 
1535 class Sys_var_have: public sys_var
1536 {
1537 public:
1538  Sys_var_have(const char *name_arg,
1539  const char *comment, int flag_args, ptrdiff_t off, size_t size,
1540  CMD_LINE getopt,
1541  PolyLock *lock=0,
1542  enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
1543  on_check_function on_check_func=0,
1544  on_update_function on_update_func=0,
1545  const char *substitute=0,
1546  int parse_flag= PARSE_NORMAL)
1547  : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
1548  getopt.arg_type, SHOW_CHAR, 0,
1549  lock, binlog_status_arg, on_check_func, on_update_func,
1550  substitute, parse_flag)
1551  {
1552  DBUG_ASSERT(scope() == GLOBAL);
1553  DBUG_ASSERT(getopt.id == -1);
1554  DBUG_ASSERT(lock == 0);
1555  DBUG_ASSERT(binlog_status_arg == VARIABLE_NOT_IN_BINLOG);
1556  DBUG_ASSERT(is_readonly());
1557  DBUG_ASSERT(on_update == 0);
1558  DBUG_ASSERT(size == sizeof(enum SHOW_COMP_OPTION));
1559  }
1560  bool do_check(THD *thd, set_var *var) {
1561  DBUG_ASSERT(FALSE);
1562  return true;
1563  }
1564  bool session_update(THD *thd, set_var *var)
1565  {
1566  DBUG_ASSERT(FALSE);
1567  return true;
1568  }
1569  bool global_update(THD *thd, set_var *var)
1570  {
1571  DBUG_ASSERT(FALSE);
1572  return true;
1573  }
1574  void session_save_default(THD *thd, set_var *var) { }
1575  void global_save_default(THD *thd, set_var *var) { }
1576  uchar *session_value_ptr(THD *thd, LEX_STRING *base)
1577  {
1578  DBUG_ASSERT(FALSE);
1579  return 0;
1580  }
1581  uchar *global_value_ptr(THD *thd, LEX_STRING *base)
1582  {
1583  return (uchar*)show_comp_option_name[global_var(enum SHOW_COMP_OPTION)];
1584  }
1585  bool check_update_type(Item_result type) { return false; }
1586 };
1587 
1604 {
1605  ptrdiff_t name_offset; // offset to the 'name' property in the structure
1606 public:
1607  Sys_var_struct(const char *name_arg,
1608  const char *comment, int flag_args, ptrdiff_t off, size_t size,
1609  CMD_LINE getopt,
1610  ptrdiff_t name_off, void *def_val, PolyLock *lock=0,
1611  enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
1612  on_check_function on_check_func=0,
1613  on_update_function on_update_func=0,
1614  const char *substitute=0,
1615  int parse_flag= PARSE_NORMAL)
1616  : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
1617  getopt.arg_type, SHOW_CHAR, (intptr)def_val,
1618  lock, binlog_status_arg, on_check_func, on_update_func,
1619  substitute, parse_flag),
1620  name_offset(name_off)
1621  {
1622  option.var_type= GET_STR;
1623  /*
1624  struct variables are special on the command line - often (e.g. for
1625  charsets) the name cannot be immediately resolved, but only after all
1626  options (in particular, basedir) are parsed.
1627 
1628  thus all struct command-line options should be added manually
1629  to my_long_options in mysqld.cc
1630  */
1631  DBUG_ASSERT(getopt.id == -1);
1632  DBUG_ASSERT(size == sizeof(void *));
1633  }
1634  bool do_check(THD *thd, set_var *var)
1635  { return false; }
1636  bool session_update(THD *thd, set_var *var)
1637  {
1638  session_var(thd, const void*)= var->save_result.ptr;
1639  return false;
1640  }
1641  bool global_update(THD *thd, set_var *var)
1642  {
1643  global_var(const void*)= var->save_result.ptr;
1644  return false;
1645  }
1646  void session_save_default(THD *thd, set_var *var)
1647  { var->save_result.ptr= global_var(void*); }
1648  void global_save_default(THD *thd, set_var *var)
1649  {
1650  void **default_value= reinterpret_cast<void**>(option.def_value);
1651  var->save_result.ptr= *default_value;
1652  }
1653  bool check_update_type(Item_result type)
1654  { return type != INT_RESULT && type != STRING_RESULT; }
1655  uchar *session_value_ptr(THD *thd, LEX_STRING *base)
1656  {
1657  uchar *ptr= session_var(thd, uchar*);
1658  return ptr ? *(uchar**)(ptr+name_offset) : 0;
1659  }
1660  uchar *global_value_ptr(THD *thd, LEX_STRING *base)
1661  {
1662  uchar *ptr= global_var(uchar*);
1663  return ptr ? *(uchar**)(ptr+name_offset) : 0;
1664  }
1665 };
1666 
1677 class Sys_var_tz: public sys_var
1678 {
1679 public:
1680  Sys_var_tz(const char *name_arg,
1681  const char *comment, int flag_args, ptrdiff_t off, size_t size,
1682  CMD_LINE getopt,
1683  Time_zone **def_val, PolyLock *lock=0,
1684  enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
1685  on_check_function on_check_func=0,
1686  on_update_function on_update_func=0,
1687  const char *substitute=0,
1688  int parse_flag= PARSE_NORMAL)
1689  : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
1690  getopt.arg_type, SHOW_CHAR, (intptr)def_val,
1691  lock, binlog_status_arg, on_check_func, on_update_func,
1692  substitute, parse_flag)
1693  {
1694  DBUG_ASSERT(getopt.id == -1);
1695  DBUG_ASSERT(size == sizeof(Time_zone *));
1696  }
1697  bool do_check(THD *thd, set_var *var)
1698  {
1699  char buff[MAX_TIME_ZONE_NAME_LENGTH];
1700  String str(buff, sizeof(buff), &my_charset_latin1);
1701  String *res= var->value->val_str(&str);
1702 
1703  if (!res)
1704  return true;
1705 
1706  if (!(var->save_result.time_zone= my_tz_find(thd, res)))
1707  {
1708  ErrConvString err(res);
1709  my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), err.ptr());
1710  return true;
1711  }
1712  return false;
1713  }
1714  bool session_update(THD *thd, set_var *var)
1715  {
1716  session_var(thd, Time_zone*)= var->save_result.time_zone;
1717  return false;
1718  }
1719  bool global_update(THD *thd, set_var *var)
1720  {
1721  global_var(Time_zone*)= var->save_result.time_zone;
1722  return false;
1723  }
1724  void session_save_default(THD *thd, set_var *var)
1725  {
1726  var->save_result.time_zone= global_var(Time_zone*);
1727  }
1728  void global_save_default(THD *thd, set_var *var)
1729  {
1730  var->save_result.time_zone=
1731  *(Time_zone**)(intptr)option.def_value;
1732  }
1733  uchar *session_value_ptr(THD *thd, LEX_STRING *base)
1734  {
1735  /*
1736  This is an ugly fix for replication: we don't replicate properly queries
1737  invoking system variables' values to update tables; but
1738  CONVERT_TZ(,,@@session.time_zone) is so popular that we make it
1739  replicable (i.e. we tell the binlog code to store the session
1740  timezone). If it's the global value which was used we can't replicate
1741  (binlog code stores session value only).
1742  */
1743  thd->time_zone_used= 1;
1744  return (uchar *)(session_var(thd, Time_zone*)->get_name()->ptr());
1745  }
1746  uchar *global_value_ptr(THD *thd, LEX_STRING *base)
1747  {
1748  return (uchar *)(global_var(Time_zone*)->get_name()->ptr());
1749  }
1750  bool check_update_type(Item_result type)
1751  { return type != STRING_RESULT; }
1752 };
1753 
1754 
1756 {
1757 public:
1758  Sys_var_tx_isolation(const char *name_arg,
1759  const char *comment, int flag_args, ptrdiff_t off, size_t size,
1760  CMD_LINE getopt,
1761  const char *values[], uint def_val, PolyLock *lock,
1762  enum binlog_status_enum binlog_status_arg,
1763  on_check_function on_check_func)
1764  :Sys_var_enum(name_arg, comment, flag_args, off, size, getopt,
1765  values, def_val, lock, binlog_status_arg, on_check_func)
1766  {}
1767  virtual bool session_update(THD *thd, set_var *var);
1768 };
1769 
1770 
1781 {
1782 public:
1783  Sys_var_tx_read_only(const char *name_arg, const char *comment, int flag_args,
1784  ptrdiff_t off, size_t size, CMD_LINE getopt,
1785  my_bool def_val, PolyLock *lock,
1786  enum binlog_status_enum binlog_status_arg,
1787  on_check_function on_check_func)
1788  :Sys_var_mybool(name_arg, comment, flag_args, off, size, getopt,
1789  def_val, lock, binlog_status_arg, on_check_func)
1790  {}
1791  virtual bool session_update(THD *thd, set_var *var);
1792 };
1793 
1794 
1800 {
1801 public:
1802  Sys_var_enum_binlog_checksum(const char *name_arg,
1803  const char *comment, int flag_args, ptrdiff_t off, size_t size,
1804  CMD_LINE getopt,
1805  const char *values[], uint def_val, PolyLock *lock,
1806  enum binlog_status_enum binlog_status_arg)
1807  :Sys_var_enum(name_arg, comment, flag_args, off, size, getopt,
1808  values, def_val, lock, binlog_status_arg, NULL)
1809  {}
1810  virtual bool global_update(THD *thd, set_var *var);
1811 };
1812 
1813 
1818 {
1819 public:
1820  Sys_var_gtid_specification(const char *name_arg,
1821  const char *comment, int flag_args, ptrdiff_t off, size_t size,
1822  CMD_LINE getopt,
1823  const char *def_val,
1824  PolyLock *lock= 0,
1825  enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
1826  on_check_function on_check_func=0,
1827  on_update_function on_update_func=0,
1828  const char *substitute=0,
1829  int parse_flag= PARSE_NORMAL)
1830  : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
1831  getopt.arg_type, SHOW_CHAR, (intptr)def_val,
1832  lock, binlog_status_arg, on_check_func, on_update_func,
1833  substitute, parse_flag)
1834  {
1835  DBUG_ASSERT(size == sizeof(Gtid_specification));
1836  }
1837  bool session_update(THD *thd, set_var *var)
1838  {
1839  DBUG_ENTER("Sys_var_gtid::session_update");
1840  global_sid_lock->rdlock();
1841  bool ret= (((Gtid_specification *)session_var_ptr(thd))->
1842  parse(global_sid_map,
1843  var->save_result.string_value.str) != 0);
1844  global_sid_lock->unlock();
1845  DBUG_RETURN(ret);
1846  }
1847  bool global_update(THD *thd, set_var *var)
1848  { DBUG_ASSERT(FALSE); return true; }
1849  void session_save_default(THD *thd, set_var *var)
1850  {
1851  DBUG_ENTER("Sys_var_gtid::session_save_default");
1852  char *ptr= (char*)(intptr)option.def_value;
1853  var->save_result.string_value.str= ptr;
1854  var->save_result.string_value.length= ptr ? strlen(ptr) : 0;
1855  DBUG_VOID_RETURN;
1856  }
1857  void global_save_default(THD *thd, set_var *var)
1858  { DBUG_ASSERT(FALSE); }
1859  bool do_check(THD *thd, set_var *var)
1860  {
1861  DBUG_ENTER("Sys_var_gtid::do_check");
1862  char buf[Gtid_specification::MAX_TEXT_LENGTH + 1];
1863  String str(buf, sizeof(buf), &my_charset_latin1);
1864  String *res= var->value->val_str(&str);
1865  if (!res)
1866  DBUG_RETURN(true);
1867  var->save_result.string_value.str= thd->strmake(res->c_ptr_safe(), res->length());
1868  if (!var->save_result.string_value.str)
1869  {
1870  my_error(ER_OUT_OF_RESOURCES, MYF(0)); // thd->strmake failed
1871  DBUG_RETURN(true);
1872  }
1873  var->save_result.string_value.length= res->length();
1874  bool ret= Gtid_specification::is_valid(res->c_ptr_safe()) ? false : true;
1875  DBUG_PRINT("info", ("ret=%d", ret));
1876  DBUG_RETURN(ret);
1877  }
1878  bool check_update_type(Item_result type)
1879  { return type != STRING_RESULT; }
1880  uchar *session_value_ptr(THD *thd, LEX_STRING *base)
1881  {
1882  DBUG_ENTER("Sys_var_gtid::session_value_ptr");
1883  char buf[Gtid_specification::MAX_TEXT_LENGTH + 1];
1884  global_sid_lock->rdlock();
1886  to_string(global_sid_map, buf);
1887  global_sid_lock->unlock();
1888  char *ret= thd->strdup(buf);
1889  DBUG_RETURN((uchar *)ret);
1890  }
1891  uchar *global_value_ptr(THD *thd, LEX_STRING *base)
1892  { DBUG_ASSERT(FALSE); return NULL; }
1893 };
1894 
1895 #ifdef HAVE_GTID_NEXT_LIST
1896 
1903 class Sys_var_gtid_set: public sys_var
1904 {
1905 public:
1906  Sys_var_gtid_set(const char *name_arg,
1907  const char *comment, int flag_args, ptrdiff_t off, size_t size,
1908  CMD_LINE getopt,
1909  const char *def_val,
1910  PolyLock *lock= 0,
1911  enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
1912  on_check_function on_check_func=0,
1913  on_update_function on_update_func=0,
1914  const char *substitute=0,
1915  int parse_flag= PARSE_NORMAL)
1916  : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
1917  getopt.arg_type, SHOW_CHAR, (intptr)def_val,
1918  lock, binlog_status_arg, on_check_func, on_update_func,
1919  substitute, parse_flag)
1920  {
1921  DBUG_ASSERT(size == sizeof(Gtid_set_or_null));
1922  }
1923  bool session_update(THD *thd, set_var *var)
1924  {
1925  DBUG_ENTER("Sys_var_gtid_set::session_update");
1926  Gtid_set_or_null *gsn=
1928  char *value= var->save_result.string_value.str;
1929  if (value == NULL)
1930  gsn->set_null();
1931  else
1932  {
1933  Gtid_set *gs= gsn->set_non_null(global_sid_map);
1934  if (gs == NULL)
1935  {
1936  my_error(ER_OUT_OF_RESOURCES, MYF(0)); // allocation failed
1937  DBUG_RETURN(true);
1938  }
1939  /*
1940  If string begins with '+', add to the existing set, otherwise
1941  replace existing set.
1942  */
1943  while (isspace(*value))
1944  value++;
1945  if (*value == '+')
1946  value++;
1947  else
1948  gs->clear();
1949  // Add specified set of groups to Gtid_set.
1950  global_sid_lock->rdlock();
1951  enum_return_status ret= gs->add_gtid_text(value);
1952  global_sid_lock->unlock();
1953  if (ret != RETURN_STATUS_OK)
1954  {
1955  gsn->set_null();
1956  DBUG_RETURN(true);
1957  }
1958  }
1959  DBUG_RETURN(false);
1960  }
1961  bool global_update(THD *thd, set_var *var)
1962  { DBUG_ASSERT(FALSE); return true; }
1963  void session_save_default(THD *thd, set_var *var)
1964  {
1965  DBUG_ENTER("Sys_var_gtid_set::session_save_default");
1966  char *ptr= (char*)(intptr)option.def_value;
1967  var->save_result.string_value.str= ptr;
1968  var->save_result.string_value.length= ptr ? strlen(ptr) : 0;
1969  DBUG_VOID_RETURN;
1970  }
1971  void global_save_default(THD *thd, set_var *var)
1972  { DBUG_ASSERT(FALSE); }
1973  bool do_check(THD *thd, set_var *var)
1974  {
1975  DBUG_ENTER("Sys_var_gtid_set::do_check");
1976  String str;
1977  String *res= var->value->val_str(&str);
1978  if (res == NULL)
1979  {
1980  var->save_result.string_value.str= NULL;
1981  DBUG_RETURN(FALSE);
1982  }
1983  DBUG_ASSERT(res->ptr() != NULL);
1984  var->save_result.string_value.str= thd->strmake(res->ptr(), res->length());
1985  if (var->save_result.string_value.str == NULL)
1986  {
1987  my_error(ER_OUT_OF_RESOURCES, MYF(0)); // thd->strmake failed
1988  DBUG_RETURN(1);
1989  }
1990  var->save_result.string_value.length= res->length();
1991  bool ret= !Gtid_set::is_valid(res->ptr());
1992  DBUG_RETURN(ret);
1993  }
1994  bool check_update_type(Item_result type)
1995  { return type != STRING_RESULT; }
1996  uchar *session_value_ptr(THD *thd, LEX_STRING *base)
1997  {
1998  DBUG_ENTER("Sys_var_gtid_set::session_value_ptr");
2000  Gtid_set *gs= gsn->get_gtid_set();
2001  if (gs == NULL)
2002  DBUG_RETURN(NULL);
2003  char *buf;
2004  global_sid_lock->rdlock();
2005  buf= (char *)thd->alloc(gs->get_string_length() + 1);
2006  if (buf)
2007  gs->to_string(buf);
2008  else
2009  my_error(ER_OUT_OF_RESOURCES, MYF(0)); // thd->alloc faile
2010  global_sid_lock->unlock();
2011  DBUG_RETURN((uchar *)buf);
2012  }
2013  uchar *global_value_ptr(THD *thd, LEX_STRING *base)
2014  { DBUG_ASSERT(FALSE); return NULL; }
2015 };
2016 #endif
2017 
2018 
2026 {
2027 public:
2028  Sys_var_charptr_func(const char *name_arg, const char *comment,
2029  flag_enum flag_arg)
2030  : sys_var(&all_sys_vars, name_arg, comment, READ_ONLY flag_arg,
2031  0/*off*/, NO_CMD_LINE.id, NO_CMD_LINE.arg_type,
2032  SHOW_CHAR, (intptr)0/*def_val*/,
2033  NULL/*polylock*/, VARIABLE_NOT_IN_BINLOG,
2034  NULL/*on_check_func*/, NULL/*on_update_func*/,
2035  NULL/*substitute*/, PARSE_NORMAL/*parse_flag*/)
2036  {
2037  DBUG_ASSERT(flag_arg == sys_var::GLOBAL || flag_arg == sys_var::SESSION ||
2038  flag_arg == sys_var::ONLY_SESSION);
2039  }
2040  bool session_update(THD *thd, set_var *var)
2041  { DBUG_ASSERT(FALSE); return true; }
2042  bool global_update(THD *thd, set_var *var)
2043  { DBUG_ASSERT(FALSE); return true; }
2044  void session_save_default(THD *thd, set_var *var) { DBUG_ASSERT(FALSE); }
2045  void global_save_default(THD *thd, set_var *var) { DBUG_ASSERT(FALSE); }
2046  bool do_check(THD *thd, set_var *var) { DBUG_ASSERT(FALSE); return true; }
2047  bool check_update_type(Item_result type) { DBUG_ASSERT(FALSE); return true; }
2048  virtual uchar *session_value_ptr(THD *thd, LEX_STRING *base)
2049  { DBUG_ASSERT(FALSE); return NULL; }
2050  virtual uchar *global_value_ptr(THD *thd, LEX_STRING *base)
2051  { DBUG_ASSERT(FALSE); return NULL; }
2052 };
2053 
2054 
2062 {
2063 public:
2064  Sys_var_gtid_set_func(const char *name_arg, const char *comment,
2065  flag_enum flag_arg)
2066  : Sys_var_charptr_func(name_arg, comment, flag_arg) {}
2067 
2068  typedef enum_return_status (*Gtid_set_getter)(THD *, Gtid_set *);
2069 
2070  static uchar *get_string_from_gtid_set(THD *thd,
2071  Gtid_set_getter get_gtid_set)
2072  {
2073  DBUG_ENTER("Sys_var_gtid_ended_groups::session_value_ptr");
2074  Gtid_set gs(global_sid_map);
2075  char *buf;
2076  // As an optimization, add 10 Intervals that do not need to be
2077  // allocated.
2078  Gtid_set::Interval ivs[10];
2079  gs.add_interval_memory(10, ivs);
2080  global_sid_lock->wrlock();
2081  if (get_gtid_set(thd, &gs) != RETURN_STATUS_OK)
2082  goto error;
2083  // allocate string and print to it
2084  buf= (char *)thd->alloc(gs.get_string_length() + 1);
2085  if (buf == NULL)
2086  {
2087  my_error(ER_OUT_OF_RESOURCES, MYF(0));
2088  goto error;
2089  }
2090  gs.to_string(buf);
2091  global_sid_lock->unlock();
2092  DBUG_RETURN((uchar *)buf);
2093  error:
2094  global_sid_lock->unlock();
2095  DBUG_RETURN(NULL);
2096  }
2097 };
2098 
2099 
2104 {
2105 public:
2106  Sys_var_gtid_executed(const char *name_arg, const char *comment_arg)
2107  : Sys_var_gtid_set_func(name_arg, comment_arg, SESSION) {}
2108 
2109  uchar *global_value_ptr(THD *thd, LEX_STRING *base)
2110  {
2111  DBUG_ENTER("Sys_var_gtid_executed::global_value_ptr");
2112  global_sid_lock->wrlock();
2113  const Gtid_set *gs= gtid_state->get_logged_gtids();
2114  char *buf= (char *)thd->alloc(gs->get_string_length() + 1);
2115  if (buf == NULL)
2116  my_error(ER_OUT_OF_RESOURCES, MYF(0));
2117  else
2118  gs->to_string(buf);
2119  global_sid_lock->unlock();
2120  DBUG_RETURN((uchar *)buf);
2121  }
2122 
2123 private:
2124  static enum_return_status get_groups_from_trx_cache(THD *thd, Gtid_set *gs)
2125  {
2126  DBUG_ENTER("Sys_var_gtid_executed::get_groups_from_trx_cache");
2127  if (opt_bin_log)
2128  {
2129  thd->binlog_setup_trx_data();
2130  PROPAGATE_REPORTED_ERROR(thd->get_group_cache(true)->get_gtids(gs));
2131  }
2132  RETURN_OK;
2133  }
2134 
2135 public:
2136  uchar *session_value_ptr(THD *thd, LEX_STRING *base)
2137  {
2138  return get_string_from_gtid_set(thd, get_groups_from_trx_cache);
2139  }
2140 };
2141 
2142 
2147 {
2148 public:
2149  Sys_var_gtid_purged(const char *name_arg,
2150  const char *comment, int flag_args, ptrdiff_t off, size_t size,
2151  CMD_LINE getopt,
2152  const char *def_val,
2153  PolyLock *lock= 0,
2154  enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
2155  on_check_function on_check_func=0,
2156  on_update_function on_update_func=0,
2157  const char *substitute=0,
2158  int parse_flag= PARSE_NORMAL)
2159  : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
2160  getopt.arg_type, SHOW_CHAR, (intptr)def_val,
2161  lock, binlog_status_arg, on_check_func, on_update_func,
2162  substitute, parse_flag)
2163  {}
2164 
2165  bool session_update(THD *thd, set_var *var)
2166  {
2167  DBUG_ASSERT(FALSE);
2168  return true;
2169  }
2170 
2171  void session_save_default(THD *thd, set_var *var)
2172  { DBUG_ASSERT(FALSE); }
2173 
2174  bool global_update(THD *thd, set_var *var)
2175  {
2176  DBUG_ENTER("Sys_var_gtid_purged::global_update");
2177 #ifdef HAVE_REPLICATION
2178  bool error= false;
2179  int rotate_res= 0;
2180 
2181  global_sid_lock->wrlock();
2182  char *previous_gtid_logged= gtid_state->get_logged_gtids()->to_string();
2183  char *previous_gtid_lost= gtid_state->get_lost_gtids()->to_string();
2184  enum_return_status ret= gtid_state->add_lost_gtids(var->save_result.string_value.str);
2185  char *current_gtid_logged= gtid_state->get_logged_gtids()->to_string();
2186  char *current_gtid_lost= gtid_state->get_lost_gtids()->to_string();
2187  global_sid_lock->unlock();
2188  if (RETURN_STATUS_OK != ret)
2189  {
2190  error= true;
2191  goto end;
2192  }
2193 
2194  // Log messages saying that GTID_PURGED and GTID_EXECUTED were changed.
2195  sql_print_information(ER(ER_GTID_PURGED_WAS_CHANGED),
2196  previous_gtid_lost, current_gtid_lost);
2197  sql_print_information(ER(ER_GTID_EXECUTED_WAS_CHANGED),
2198  previous_gtid_logged, current_gtid_logged);
2199 
2200  // Rotate logs to have Previous_gtid_event on last binlog.
2201  rotate_res= mysql_bin_log.rotate_and_purge(true);
2202  if (rotate_res)
2203  {
2204  error= true;
2205  goto end;
2206  }
2207 
2208 end:
2209  my_free(previous_gtid_logged);
2210  my_free(previous_gtid_lost);
2211  my_free(current_gtid_logged);
2212  my_free(current_gtid_lost);
2213  DBUG_RETURN(error);
2214 #else
2215  DBUG_RETURN(true);
2216 #endif /* HAVE_REPLICATION */
2217  }
2218 
2219  void global_save_default(THD *thd, set_var *var)
2220  {
2221  /* gtid_purged does not have default value */
2222  my_error(ER_NO_DEFAULT, MYF(0), var->var->name.str);
2223  }
2224 
2225  bool do_check(THD *thd, set_var *var)
2226  {
2227  DBUG_ENTER("Sys_var_gtid_purged::do_check");
2228  char buf[1024];
2229  String str(buf, sizeof(buf), system_charset_info);
2230  String *res= var->value->val_str(&str);
2231  if (!res)
2232  DBUG_RETURN(true);
2233  var->save_result.string_value.str= thd->strmake(res->c_ptr_safe(),
2234  res->length());
2235  if (!var->save_result.string_value.str)
2236  {
2237  my_error(ER_OUT_OF_RESOURCES, MYF(0)); // thd->strmake failed
2238  DBUG_RETURN(true);
2239  }
2240  var->save_result.string_value.length= res->length();
2241  bool ret= Gtid_set::is_valid(res->c_ptr_safe()) ? false : true;
2242  DBUG_PRINT("info", ("ret=%d", ret));
2243  DBUG_RETURN(ret);
2244  }
2245 
2246  bool check_update_type(Item_result type)
2247  { return type != STRING_RESULT; }
2248 
2249  uchar *global_value_ptr(THD *thd, LEX_STRING *base)
2250  {
2251  DBUG_ENTER("Sys_var_gtid_purged::global_value_ptr");
2252  global_sid_lock->wrlock();
2253  const Gtid_set *gs= gtid_state->get_lost_gtids();
2254  char *buf= (char *)thd->alloc(gs->get_string_length() + 1);
2255  if (buf == NULL)
2256  my_error(ER_OUT_OF_RESOURCES, MYF(0));
2257  else
2258  gs->to_string(buf);
2259  global_sid_lock->unlock();
2260  DBUG_RETURN((uchar *)buf);
2261  }
2262 
2263  uchar *session_value_ptr(THD *thd, LEX_STRING *base)
2264  { DBUG_ASSERT(0); return NULL; }
2265 };
2266 
2267 
2269 {
2270 public:
2271  Sys_var_gtid_owned(const char *name_arg, const char *comment_arg)
2272  : Sys_var_gtid_set_func(name_arg, comment_arg, SESSION) {}
2273 
2274 public:
2275  uchar *session_value_ptr(THD *thd, LEX_STRING *base)
2276  {
2277  DBUG_ENTER("Sys_var_gtid_owned::session_value_ptr");
2278  char *buf= NULL;
2279  if (thd->owned_gtid.sidno == 0)
2280  DBUG_RETURN((uchar *)thd->strdup(""));
2281  if (thd->owned_gtid.sidno == -1)
2282  {
2283 #ifdef HAVE_GTID_NEXT_LIST
2284  buf= (char *)thd->alloc(thd->owned_gtid_set.get_string_length() + 1);
2285  if (buf)
2286  {
2287  global_sid_lock->rdlock();
2288  thd->owned_gtid_set.to_string(buf);
2289  global_sid_lock->unlock();
2290  }
2291  else
2292  my_error(ER_OUT_OF_RESOURCES, MYF(0));
2293 #else
2294  DBUG_ASSERT(0);
2295 #endif
2296  }
2297  else
2298  {
2299  buf= (char *)thd->alloc(Gtid::MAX_TEXT_LENGTH + 1);
2300  if (buf)
2301  {
2302  global_sid_lock->rdlock();
2303  thd->owned_gtid.to_string(global_sid_map, buf);
2304  global_sid_lock->unlock();
2305  }
2306  else
2307  my_error(ER_OUT_OF_RESOURCES, MYF(0));
2308  }
2309  DBUG_RETURN((uchar *)buf);
2310  }
2311 
2312  uchar *global_value_ptr(THD *thd, LEX_STRING *base)
2313  {
2314  DBUG_ENTER("Sys_var_gtid_owned::global_value_ptr");
2315  const Owned_gtids *owned_gtids= gtid_state->get_owned_gtids();
2316  global_sid_lock->wrlock();
2317  char *buf= (char *)thd->alloc(owned_gtids->get_max_string_length());
2318  if (buf)
2319  owned_gtids->to_string(buf);
2320  else
2321  my_error(ER_OUT_OF_RESOURCES, MYF(0)); // thd->alloc faile
2322  global_sid_lock->unlock();
2323  DBUG_RETURN((uchar *)buf);
2324  }
2325 };