My Project
sys_vars.h
Go to the documentation of this file.
00001 /* Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; version 2 of the License.
00006 
00007    This program is distributed in the hope that it will be useful,
00008    but WITHOUT ANY WARRANTY; without even the implied warranty of
00009    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010    GNU General Public License for more details.
00011 
00012    You should have received a copy of the GNU General Public License
00013    along with this program; if not, write to the Free Software
00014    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
00015 
00024 #include "sys_vars_shared.h"
00025 #include <my_getopt.h>
00026 #include <my_bit.h>
00027 #include <my_dir.h>
00028 #include "keycaches.h"
00029 #include "strfunc.h"
00030 #include "tztime.h"     // my_tz_find, my_tz_SYSTEM, struct Time_zone
00031 #include "rpl_gtid.h"
00032 #include <ctype.h>
00033 
00034 /*
00035   a set of mostly trivial (as in f(X)=X) defines below to make system variable
00036   declarations more readable
00037 */
00038 #define VALID_RANGE(X,Y) X,Y
00039 #define DEFAULT(X) X
00040 #define BLOCK_SIZE(X) X
00041 #define GLOBAL_VAR(X) sys_var::GLOBAL, (((char*)&(X))-(char*)&global_system_variables), sizeof(X)
00042 #define SESSION_VAR(X) sys_var::SESSION, offsetof(SV, X), sizeof(((SV *)0)->X)
00043 #define SESSION_ONLY(X) sys_var::ONLY_SESSION, offsetof(SV, X), sizeof(((SV *)0)->X)
00044 #define NO_CMD_LINE CMD_LINE(NO_ARG, -1)
00045 /*
00046   the define below means that there's no *second* mutex guard,
00047   LOCK_global_system_variables always guards all system variables
00048 */
00049 #define NO_MUTEX_GUARD ((PolyLock*)0)
00050 #define IN_BINLOG sys_var::SESSION_VARIABLE_IN_BINLOG
00051 #define NOT_IN_BINLOG sys_var::VARIABLE_NOT_IN_BINLOG
00052 #define ON_READ(X) X
00053 #define ON_CHECK(X) X
00054 #define ON_UPDATE(X) X
00055 #define READ_ONLY sys_var::READONLY+
00056 #define NOT_VISIBLE sys_var::INVISIBLE+
00057 // this means that Sys_var_charptr initial value was malloc()ed
00058 #define PREALLOCATED sys_var::ALLOCATED+
00059 /*
00060   Sys_var_bit meaning is reversed, like in
00061   @@foreign_key_checks <-> OPTION_NO_FOREIGN_KEY_CHECKS
00062 */
00063 #define REVERSE(X) ~(X)
00064 #define DEPRECATED(X) X
00065 
00066 #define session_var(THD, TYPE) (*(TYPE*)session_var_ptr(THD))
00067 #define global_var(TYPE) (*(TYPE*)global_var_ptr())
00068 
00069 #if SIZEOF_OFF_T > 4 && defined(BIG_TABLES)
00070 #define GET_HA_ROWS GET_ULL
00071 #else
00072 #define GET_HA_ROWS GET_ULONG
00073 #endif
00074 
00075 enum charset_enum {IN_SYSTEM_CHARSET, IN_FS_CHARSET};
00076 
00077 static const char *bool_values[3]= {"OFF", "ON", 0};
00078 
00084 struct CMD_LINE
00085 {
00086   int id;
00087   enum get_opt_arg_type arg_type;
00088   CMD_LINE(enum get_opt_arg_type getopt_arg_type, int getopt_id=0)
00089     : id(getopt_id), arg_type(getopt_arg_type) {}
00090 };
00091 
00105 template
00106   <typename T, ulong ARGT, enum enum_mysql_show_type SHOWT, bool SIGNED>
00107 class Sys_var_integer: public sys_var
00108 {
00109 public:
00110   Sys_var_integer(const char *name_arg,
00111           const char *comment, int flag_args, ptrdiff_t off, size_t size,
00112           CMD_LINE getopt,
00113           T min_val, T max_val, T def_val, uint block_size, PolyLock *lock=0,
00114           enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
00115           on_check_function on_check_func=0,
00116           on_update_function on_update_func=0,
00117           const char *substitute=0,
00118           int parse_flag= PARSE_NORMAL)
00119     : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
00120               getopt.arg_type, SHOWT, def_val, lock, binlog_status_arg,
00121               on_check_func, on_update_func,
00122               substitute, parse_flag)
00123   {
00124     option.var_type= ARGT;
00125     option.min_value= min_val;
00126     option.max_value= max_val;
00127     option.block_size= block_size;
00128     option.u_max_value= (uchar**)max_var_ptr();
00129     if (max_var_ptr())
00130       *max_var_ptr()= max_val;
00131 
00132     // Do not set global_var for Sys_var_keycache objects
00133     if (offset >= 0)
00134       global_var(T)= def_val;
00135 
00136     DBUG_ASSERT(size == sizeof(T));
00137     DBUG_ASSERT(min_val < max_val);
00138     DBUG_ASSERT(min_val <= def_val);
00139     DBUG_ASSERT(max_val >= def_val);
00140     DBUG_ASSERT(block_size > 0);
00141     DBUG_ASSERT(def_val % block_size == 0);
00142   }
00143   bool do_check(THD *thd, set_var *var)
00144   {
00145     my_bool fixed= FALSE;
00146     longlong v;
00147     ulonglong uv;
00148 
00149     v= var->value->val_int();
00150     if (SIGNED) /* target variable has signed type */
00151     {
00152       if (var->value->unsigned_flag)
00153       {
00154         /*
00155           Input value is such a large positive number that MySQL used an
00156           unsigned item to hold it. When cast to a signed longlong, if the
00157           result is negative there is "cycling" and this is incorrect (large
00158           positive input value should not end up as a large negative value in
00159           the session signed variable to be set); instead, we need to pick the
00160           allowed number closest to the positive input value, i.e. pick the
00161           biggest allowed positive integer.
00162         */
00163         if (v < 0)
00164           uv= max_of_int_range(ARGT);
00165         else /* no cycling, longlong can hold true value */
00166           uv= (ulonglong) v;
00167       }
00168       else
00169         uv= v;
00170       /* This will further restrict with VALID_RANGE, BLOCK_SIZE */
00171       var->save_result.ulonglong_value=
00172         getopt_ll_limit_value(uv, &option, &fixed);
00173     }
00174     else
00175     {
00176       if (var->value->unsigned_flag)
00177       {
00178         /* Guaranteed positive input value, ulonglong can hold it */
00179         uv= (ulonglong) v;
00180       }
00181       else
00182       {
00183         /*
00184           Maybe negative input value; in this case, cast to ulonglong makes it
00185           positive, which is wrong. Pick the closest allowed value i.e. 0.
00186         */
00187         uv= (ulonglong) (v < 0 ? 0 : v);
00188       }
00189       var->save_result.ulonglong_value=
00190         getopt_ull_limit_value(uv, &option, &fixed);
00191     }
00192 
00193     if (max_var_ptr())
00194     {
00195       /* check constraint set with --maximum-...=X */
00196       if (SIGNED)
00197       {
00198         longlong max_val= *max_var_ptr();
00199         if (((longlong)(var->save_result.ulonglong_value)) > max_val)
00200           var->save_result.ulonglong_value= max_val;
00201         /*
00202           Signed variable probably has some kind of symmetry. Then it's good
00203           to limit negative values just as we limit positive values.
00204         */
00205         max_val= -max_val;
00206         if (((longlong)(var->save_result.ulonglong_value)) < max_val)
00207           var->save_result.ulonglong_value= max_val;
00208       }
00209       else
00210       {
00211         ulonglong max_val= *max_var_ptr();
00212         if (var->save_result.ulonglong_value > max_val)
00213           var->save_result.ulonglong_value= max_val;
00214       }
00215     }
00216 
00217     return throw_bounds_warning(thd, name.str,
00218                                 var->save_result.ulonglong_value !=
00219                                 (ulonglong)v,
00220                                 var->value->unsigned_flag, v);
00221   }
00222   bool session_update(THD *thd, set_var *var)
00223   {
00224     session_var(thd, T)= var->save_result.ulonglong_value;
00225     return false;
00226   }
00227   bool global_update(THD *thd, set_var *var)
00228   {
00229     global_var(T)= var->save_result.ulonglong_value;
00230     return false;
00231   }
00232   bool check_update_type(Item_result type)
00233   { return type != INT_RESULT; }
00234   void session_save_default(THD *thd, set_var *var)
00235   { var->save_result.ulonglong_value= (ulonglong)*(T*)global_value_ptr(thd, 0); }
00236   void global_save_default(THD *thd, set_var *var)
00237   { var->save_result.ulonglong_value= option.def_value; }
00238   private:
00239   T *max_var_ptr()
00240   {
00241     return scope() == SESSION ? (T*)(((uchar*)&max_system_variables) + offset)
00242                               : 0;
00243   }
00244 };
00245 
00246 typedef Sys_var_integer<int32, GET_UINT, SHOW_INT, FALSE> Sys_var_int32;
00247 typedef Sys_var_integer<uint, GET_UINT, SHOW_INT, FALSE> Sys_var_uint;
00248 typedef Sys_var_integer<ulong, GET_ULONG, SHOW_LONG, FALSE> Sys_var_ulong;
00249 typedef Sys_var_integer<ha_rows, GET_HA_ROWS, SHOW_HA_ROWS, FALSE>
00250   Sys_var_harows;
00251 typedef Sys_var_integer<ulonglong, GET_ULL, SHOW_LONGLONG, FALSE>
00252   Sys_var_ulonglong;
00253 typedef Sys_var_integer<long, GET_LONG, SHOW_SIGNED_LONG, TRUE> Sys_var_long;
00254 
00258 class Sys_var_typelib: public sys_var
00259 {
00260 protected:
00261   TYPELIB typelib;
00262 public:
00263   Sys_var_typelib(const char *name_arg,
00264           const char *comment, int flag_args, ptrdiff_t off,
00265           CMD_LINE getopt,
00266           SHOW_TYPE show_val_type_arg, const char *values[],
00267           ulonglong def_val, PolyLock *lock,
00268           enum binlog_status_enum binlog_status_arg,
00269           on_check_function on_check_func, on_update_function on_update_func,
00270           const char *substitute, int parse_flag= PARSE_NORMAL)
00271     : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
00272               getopt.arg_type, show_val_type_arg, def_val, lock,
00273               binlog_status_arg, on_check_func,
00274               on_update_func, substitute, parse_flag)
00275   {
00276     for (typelib.count= 0; values[typelib.count]; typelib.count++) /*no-op */;
00277     typelib.name="";
00278     typelib.type_names= values;
00279     typelib.type_lengths= 0;    // only used by Fields_enum and Field_set
00280     option.typelib= &typelib;
00281   }
00282   bool do_check(THD *thd, set_var *var) // works for enums and my_bool
00283   {
00284     char buff[STRING_BUFFER_USUAL_SIZE];
00285     String str(buff, sizeof(buff), system_charset_info), *res;
00286 
00287     if (var->value->result_type() == STRING_RESULT)
00288     {
00289       if (!(res=var->value->val_str(&str)))
00290         return true;
00291       else
00292       if (!(var->save_result.ulonglong_value=
00293             find_type(&typelib, res->ptr(), res->length(), false)))
00294         return true;
00295       else
00296         var->save_result.ulonglong_value--;
00297     }
00298     else
00299     {
00300       longlong tmp=var->value->val_int();
00301       if (tmp < 0 || tmp >= typelib.count)
00302         return true;
00303       else
00304         var->save_result.ulonglong_value= tmp;
00305     }
00306 
00307     return false;
00308   }
00309   bool check_update_type(Item_result type)
00310   { return type != INT_RESULT && type != STRING_RESULT; }
00311 };
00312 
00327 class Sys_var_enum: public Sys_var_typelib
00328 {
00329 public:
00330   Sys_var_enum(const char *name_arg,
00331           const char *comment, int flag_args, ptrdiff_t off, size_t size,
00332           CMD_LINE getopt,
00333           const char *values[], uint def_val, PolyLock *lock=0,
00334           enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
00335           on_check_function on_check_func=0,
00336           on_update_function on_update_func=0,
00337           const char *substitute=0)
00338     : Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
00339                       SHOW_CHAR, values, def_val, lock,
00340                       binlog_status_arg, on_check_func, on_update_func,
00341                       substitute)
00342   {
00343     option.var_type= GET_ENUM;
00344     global_var(ulong)= def_val;
00345     DBUG_ASSERT(def_val < typelib.count);
00346     DBUG_ASSERT(size == sizeof(ulong));
00347   }
00348   bool session_update(THD *thd, set_var *var)
00349   {
00350     session_var(thd, ulong)= var->save_result.ulonglong_value;
00351     return false;
00352   }
00353   bool global_update(THD *thd, set_var *var)
00354   {
00355     global_var(ulong)= var->save_result.ulonglong_value;
00356     return false;
00357   }
00358   void session_save_default(THD *thd, set_var *var)
00359   { var->save_result.ulonglong_value= global_var(ulong); }
00360   void global_save_default(THD *thd, set_var *var)
00361   { var->save_result.ulonglong_value= option.def_value; }
00362   uchar *session_value_ptr(THD *thd, LEX_STRING *base)
00363   { return (uchar*)typelib.type_names[session_var(thd, ulong)]; }
00364   uchar *global_value_ptr(THD *thd, LEX_STRING *base)
00365   { return (uchar*)typelib.type_names[global_var(ulong)]; }
00366 };
00367 
00374 class Sys_var_mybool: public Sys_var_typelib
00375 {
00376 public:
00377   Sys_var_mybool(const char *name_arg,
00378           const char *comment, int flag_args, ptrdiff_t off, size_t size,
00379           CMD_LINE getopt,
00380           my_bool def_val, PolyLock *lock=0,
00381           enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
00382           on_check_function on_check_func=0,
00383           on_update_function on_update_func=0,
00384           const char *substitute=0,
00385           int parse_flag= PARSE_NORMAL)
00386     : Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
00387                       SHOW_MY_BOOL, bool_values, def_val, lock,
00388                       binlog_status_arg, on_check_func, on_update_func,
00389                       substitute, parse_flag)
00390   {
00391     option.var_type= GET_BOOL;
00392     global_var(my_bool)= def_val;
00393     DBUG_ASSERT(def_val < 2);
00394     DBUG_ASSERT(getopt.arg_type == OPT_ARG || getopt.id == -1);
00395     DBUG_ASSERT(size == sizeof(my_bool));
00396   }
00397   bool session_update(THD *thd, set_var *var)
00398   {
00399     session_var(thd, my_bool)= var->save_result.ulonglong_value;
00400     return false;
00401   }
00402   bool global_update(THD *thd, set_var *var)
00403   {
00404     global_var(my_bool)= var->save_result.ulonglong_value;
00405     return false;
00406   }
00407   void session_save_default(THD *thd, set_var *var)
00408   { var->save_result.ulonglong_value= (ulonglong)*(my_bool *)global_value_ptr(thd, 0); }
00409   void global_save_default(THD *thd, set_var *var)
00410   { var->save_result.ulonglong_value= option.def_value; }
00411 };
00412 
00429 class Sys_var_charptr: public sys_var
00430 {
00431 public:
00432   Sys_var_charptr(const char *name_arg,
00433           const char *comment, int flag_args, ptrdiff_t off, size_t size,
00434           CMD_LINE getopt,
00435           enum charset_enum is_os_charset_arg,
00436           const char *def_val, PolyLock *lock=0,
00437           enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
00438           on_check_function on_check_func=0,
00439           on_update_function on_update_func=0,
00440           const char *substitute=0,
00441           int parse_flag= PARSE_NORMAL)
00442     : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
00443               getopt.arg_type, SHOW_CHAR_PTR, (intptr)def_val,
00444               lock, binlog_status_arg, on_check_func, on_update_func,
00445               substitute, parse_flag)
00446   {
00447     is_os_charset= is_os_charset_arg == IN_FS_CHARSET;
00448     /*
00449      use GET_STR_ALLOC - if ALLOCATED it must be *always* allocated,
00450      otherwise (GET_STR) you'll never know whether to free it or not.
00451      (think of an exit because of an error right after my_getopt)
00452     */
00453     option.var_type= (flags & ALLOCATED) ? GET_STR_ALLOC : GET_STR;
00454     global_var(const char*)= def_val;
00455     DBUG_ASSERT(scope() == GLOBAL);
00456     DBUG_ASSERT(size == sizeof(char *));
00457   }
00458   void cleanup()
00459   {
00460     if (flags & ALLOCATED)
00461       my_free(global_var(char*));
00462     flags&= ~ALLOCATED;
00463   }
00464   bool do_check(THD *thd, set_var *var)
00465   {
00466     char buff[STRING_BUFFER_USUAL_SIZE], buff2[STRING_BUFFER_USUAL_SIZE];
00467     String str(buff, sizeof(buff), charset(thd));
00468     String str2(buff2, sizeof(buff2), charset(thd)), *res;
00469 
00470     if (!(res=var->value->val_str(&str)))
00471       var->save_result.string_value.str= 0;
00472     else
00473     {
00474       uint32 unused;
00475       if (String::needs_conversion(res->length(), res->charset(),
00476                                    charset(thd), &unused))
00477       {
00478         uint errors;
00479         str2.copy(res->ptr(), res->length(), res->charset(), charset(thd),
00480                   &errors);
00481         res=&str2;
00482 
00483       }
00484       var->save_result.string_value.str= thd->strmake(res->ptr(), res->length());
00485       var->save_result.string_value.length= res->length();
00486     }
00487 
00488     return false;
00489   }
00490   bool session_update(THD *thd, set_var *var)
00491   {
00492     DBUG_ASSERT(FALSE);
00493     return true;
00494   }
00495   bool global_update(THD *thd, set_var *var)
00496   {
00497     char *new_val, *ptr= var->save_result.string_value.str;
00498     size_t len=var->save_result.string_value.length;
00499     if (ptr)
00500     {
00501       new_val= (char*)my_memdup(ptr, len+1, MYF(MY_WME));
00502       if (!new_val) return true;
00503       new_val[len]=0;
00504     }
00505     else
00506       new_val= 0;
00507     if (flags & ALLOCATED)
00508       my_free(global_var(char*));
00509     flags|= ALLOCATED;
00510     global_var(char*)= new_val;
00511     return false;
00512   }
00513   void session_save_default(THD *thd, set_var *var)
00514   { DBUG_ASSERT(FALSE); }
00515   void global_save_default(THD *thd, set_var *var)
00516   {
00517     char *ptr= (char*)(intptr)option.def_value;
00518     var->save_result.string_value.str= ptr;
00519     var->save_result.string_value.length= ptr ? strlen(ptr) : 0;
00520   }
00521   bool check_update_type(Item_result type)
00522   { return type != STRING_RESULT; }
00523 };
00524 
00525 
00526 class Sys_var_proxy_user: public sys_var
00527 {
00528 public:
00529   Sys_var_proxy_user(const char *name_arg,
00530           const char *comment, enum charset_enum is_os_charset_arg)
00531     : sys_var(&all_sys_vars, name_arg, comment,
00532               sys_var::READONLY+sys_var::ONLY_SESSION, 0, -1,
00533               NO_ARG, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG,
00534               NULL, NULL, NULL, PARSE_NORMAL)
00535   {
00536     is_os_charset= is_os_charset_arg == IN_FS_CHARSET;
00537     option.var_type= GET_STR;
00538   }
00539   bool do_check(THD *thd, set_var *var)
00540   {
00541     DBUG_ASSERT(FALSE);
00542     return true;
00543   }
00544   bool session_update(THD *thd, set_var *var)
00545   {
00546     DBUG_ASSERT(FALSE);
00547     return true;
00548   }
00549   bool global_update(THD *thd, set_var *var)
00550   {
00551     DBUG_ASSERT(FALSE);
00552     return false;
00553   }
00554   void session_save_default(THD *thd, set_var *var)
00555   { DBUG_ASSERT(FALSE); }
00556   void global_save_default(THD *thd, set_var *var)
00557   { DBUG_ASSERT(FALSE); }
00558   bool check_update_type(Item_result type)
00559   { return true; }
00560 protected:
00561   virtual uchar *session_value_ptr(THD *thd, LEX_STRING *base)
00562   {
00563     return thd->security_ctx->proxy_user[0] ?
00564       (uchar *) &(thd->security_ctx->proxy_user[0]) : NULL;
00565   }
00566 };
00567 
00568 class Sys_var_external_user : public Sys_var_proxy_user
00569 {
00570 public:
00571   Sys_var_external_user(const char *name_arg, const char *comment_arg,
00572           enum charset_enum is_os_charset_arg)
00573     : Sys_var_proxy_user (name_arg, comment_arg, is_os_charset_arg)
00574   {}
00575 
00576 protected:
00577   virtual uchar *session_value_ptr(THD *thd, LEX_STRING *base)
00578   {
00579     return thd->security_ctx->proxy_user[0] ?
00580       (uchar *) &(thd->security_ctx->proxy_user[0]) : NULL;
00581   }
00582 };
00583 
00596 class Sys_var_lexstring: public Sys_var_charptr
00597 {
00598 public:
00599   Sys_var_lexstring(const char *name_arg,
00600           const char *comment, int flag_args, ptrdiff_t off, size_t size,
00601           CMD_LINE getopt,
00602           enum charset_enum is_os_charset_arg,
00603           const char *def_val, PolyLock *lock=0,
00604           enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
00605           on_check_function on_check_func=0,
00606           on_update_function on_update_func=0,
00607           const char *substitute=0)
00608     : Sys_var_charptr(name_arg, comment, flag_args, off, sizeof(char*),
00609               getopt, is_os_charset_arg, def_val, lock, binlog_status_arg,
00610               on_check_func, on_update_func, substitute)
00611   {
00612     global_var(LEX_STRING).length= strlen(def_val);
00613     DBUG_ASSERT(size == sizeof(LEX_STRING));
00614     *const_cast<SHOW_TYPE*>(&show_val_type)= SHOW_LEX_STRING;
00615   }
00616   bool global_update(THD *thd, set_var *var)
00617   {
00618     if (Sys_var_charptr::global_update(thd, var))
00619       return true;
00620     global_var(LEX_STRING).length= var->save_result.string_value.length;
00621     return false;
00622   }
00623 };
00624 
00625 #ifndef DBUG_OFF
00626 
00637 class Sys_var_dbug: public sys_var
00638 {
00639 public:
00640   Sys_var_dbug(const char *name_arg,
00641                const char *comment, int flag_args,
00642                CMD_LINE getopt,
00643                const char *def_val, PolyLock *lock=0,
00644                enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
00645                on_check_function on_check_func=0,
00646                on_update_function on_update_func=0,
00647                const char *substitute=0,
00648                int parse_flag= PARSE_NORMAL)
00649     : sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id,
00650               getopt.arg_type, SHOW_CHAR, (intptr)def_val,
00651               lock, binlog_status_arg, on_check_func, on_update_func,
00652               substitute, parse_flag)
00653   { option.var_type= GET_NO_ARG; }
00654   bool do_check(THD *thd, set_var *var)
00655   {
00656     char buff[STRING_BUFFER_USUAL_SIZE];
00657     String str(buff, sizeof(buff), system_charset_info), *res;
00658 
00659     if (!(res=var->value->val_str(&str)))
00660       var->save_result.string_value.str= const_cast<char*>("");
00661     else
00662       var->save_result.string_value.str= thd->strmake(res->ptr(), res->length());
00663     return false;
00664   }
00665   bool session_update(THD *thd, set_var *var)
00666   {
00667     const char *val= var->save_result.string_value.str;
00668     if (!var->value)
00669       DBUG_POP();
00670     else
00671       DBUG_SET(val);
00672     return false;
00673   }
00674   bool global_update(THD *thd, set_var *var)
00675   {
00676     const char *val= var->save_result.string_value.str;
00677     DBUG_SET_INITIAL(val);
00678     return false;
00679   }
00680   void session_save_default(THD *thd, set_var *var)
00681   { }
00682   void global_save_default(THD *thd, set_var *var)
00683   {
00684     char *ptr= (char*)(intptr)option.def_value;
00685     var->save_result.string_value.str= ptr;
00686   }
00687   uchar *session_value_ptr(THD *thd, LEX_STRING *base)
00688   {
00689     char buf[256];
00690     DBUG_EXPLAIN(buf, sizeof(buf));
00691     return (uchar*) thd->strdup(buf);
00692   }
00693   uchar *global_value_ptr(THD *thd, LEX_STRING *base)
00694   {
00695     char buf[256];
00696     DBUG_EXPLAIN_INITIAL(buf, sizeof(buf));
00697     return (uchar*) thd->strdup(buf);
00698   }
00699   bool check_update_type(Item_result type)
00700   { return type != STRING_RESULT; }
00701 };
00702 #endif
00703 
00704 #define KEYCACHE_VAR(X) sys_var::GLOBAL,offsetof(KEY_CACHE, X), sizeof(((KEY_CACHE *)0)->X)
00705 #define keycache_var_ptr(KC, OFF) (((uchar*)(KC))+(OFF))
00706 #define keycache_var(KC, OFF) (*(ulonglong*)keycache_var_ptr(KC, OFF))
00707 typedef bool (*keycache_update_function)(THD *, KEY_CACHE *, ptrdiff_t, ulonglong);
00708 
00720 class Sys_var_keycache: public Sys_var_ulonglong
00721 {
00722   keycache_update_function keycache_update;
00723 public:
00724   Sys_var_keycache(const char *name_arg,
00725           const char *comment, int flag_args, ptrdiff_t off, size_t size,
00726           CMD_LINE getopt,
00727           ulonglong min_val, ulonglong max_val, ulonglong def_val,
00728           ulonglong block_size, PolyLock *lock,
00729           enum binlog_status_enum binlog_status_arg,
00730           on_check_function on_check_func,
00731           keycache_update_function on_update_func,
00732           const char *substitute=0)
00733     : Sys_var_ulonglong(name_arg, comment, flag_args,
00734                         -1,     /* offset, see base class CTOR */
00735                         size,
00736                         getopt, min_val, max_val, def_val,
00737                         block_size, lock, binlog_status_arg, on_check_func, 0,
00738                         substitute),
00739     keycache_update(on_update_func)
00740   {
00741     offset= off; /* Remember offset in KEY_CACHE */
00742     option.var_type|= GET_ASK_ADDR;
00743     option.value= (uchar**)1; // crash me, please
00744     keycache_var(dflt_key_cache, off)= def_val;
00745     DBUG_ASSERT(scope() == GLOBAL);
00746   }
00747   bool global_update(THD *thd, set_var *var)
00748   {
00749     ulonglong new_value= var->save_result.ulonglong_value;
00750     LEX_STRING *base_name= &var->base;
00751     KEY_CACHE *key_cache;
00752 
00753     /* If no basename, assume it's for the key cache named 'default' */
00754     if (!base_name->length)
00755       base_name= &default_key_cache_base;
00756 
00757     key_cache= get_key_cache(base_name);
00758 
00759     if (!key_cache)
00760     {                                           // Key cache didn't exists */
00761       if (!new_value)                           // Tried to delete cache
00762         return false;                           // Ok, nothing to do
00763       if (!(key_cache= create_key_cache(base_name->str, base_name->length)))
00764         return true;
00765     }
00766 
00772     if (key_cache->in_init)
00773       return true;
00774 
00775     return keycache_update(thd, key_cache, offset, new_value);
00776   }
00777   uchar *global_value_ptr(THD *thd, LEX_STRING *base)
00778   {
00779     KEY_CACHE *key_cache= get_key_cache(base);
00780     if (!key_cache)
00781       key_cache= &zero_key_cache;
00782     return keycache_var_ptr(key_cache, offset);
00783   }
00784 };
00785 
00793 class Sys_var_double: public sys_var
00794 {
00795 public:
00796   Sys_var_double(const char *name_arg,
00797           const char *comment, int flag_args, ptrdiff_t off, size_t size,
00798           CMD_LINE getopt,
00799           double min_val, double max_val, double def_val, PolyLock *lock=0,
00800           enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
00801           on_check_function on_check_func=0,
00802           on_update_function on_update_func=0,
00803           const char *substitute=0,
00804           int parse_flag= PARSE_NORMAL)
00805     : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
00806               getopt.arg_type, SHOW_DOUBLE,
00807               (longlong) getopt_double2ulonglong(def_val),
00808               lock, binlog_status_arg, on_check_func, on_update_func,
00809               substitute, parse_flag)
00810   {
00811     option.var_type= GET_DOUBLE;
00812     option.min_value= (longlong) getopt_double2ulonglong(min_val);
00813     option.max_value= (longlong) getopt_double2ulonglong(max_val);
00814     global_var(double)= (double)option.def_value;
00815     DBUG_ASSERT(min_val <= max_val);
00816     DBUG_ASSERT(min_val <= def_val);
00817     DBUG_ASSERT(max_val >= def_val);
00818     DBUG_ASSERT(size == sizeof(double));
00819   }
00820   bool do_check(THD *thd, set_var *var)
00821   {
00822     my_bool fixed;
00823     double v= var->value->val_real();
00824     var->save_result.double_value= getopt_double_limit_value(v, &option, &fixed);
00825 
00826     return throw_bounds_warning(thd, name.str, fixed, v);
00827   }
00828   bool session_update(THD *thd, set_var *var)
00829   {
00830     session_var(thd, double)= var->save_result.double_value;
00831     return false;
00832   }
00833   bool global_update(THD *thd, set_var *var)
00834   {
00835     global_var(double)= var->save_result.double_value;
00836     return false;
00837   }
00838   bool check_update_type(Item_result type)
00839   {
00840     return type != INT_RESULT && type != REAL_RESULT && type != DECIMAL_RESULT;
00841   }
00842   void session_save_default(THD *thd, set_var *var)
00843   { var->save_result.double_value= global_var(double); }
00844   void global_save_default(THD *thd, set_var *var)
00845   { var->save_result.double_value= getopt_ulonglong2double(option.def_value); }
00846 };
00847 
00858 class Sys_var_test_flag: public Sys_var_mybool
00859 {
00860 private:
00861   my_bool test_flag_value;
00862   uint    test_flag_mask;
00863 public:
00864   Sys_var_test_flag(const char *name_arg, const char *comment, uint mask)
00865   : Sys_var_mybool(name_arg, comment, READ_ONLY GLOBAL_VAR(test_flag_value),
00866           NO_CMD_LINE, DEFAULT(FALSE))
00867   {
00868     test_flag_mask= mask;
00869   }
00870   uchar *global_value_ptr(THD *thd, LEX_STRING *base)
00871   {
00872     test_flag_value= ((test_flags & test_flag_mask) > 0);
00873     return (uchar*) &test_flag_value;
00874   }
00875 };
00876 
00887 class Sys_var_max_user_conn: public Sys_var_uint
00888 {
00889 public:
00890   Sys_var_max_user_conn(const char *name_arg,
00891           const char *comment, int flag_args, ptrdiff_t off, size_t size,
00892           CMD_LINE getopt,
00893           uint min_val, uint max_val, uint def_val,
00894           uint block_size, PolyLock *lock=0,
00895           enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
00896           on_check_function on_check_func=0,
00897           on_update_function on_update_func=0,
00898           const char *substitute=0)
00899     : Sys_var_uint(name_arg, comment, SESSION, off, size, getopt,
00900               min_val, max_val, def_val, block_size,
00901               lock, binlog_status_arg, on_check_func, on_update_func,
00902               substitute)
00903   { }
00904   uchar *session_value_ptr(THD *thd, LEX_STRING *base)
00905   {
00906     const USER_CONN *uc= thd->get_user_connect();
00907     if (uc && uc->user_resources.user_conn)
00908       return (uchar*) &(uc->user_resources.user_conn);
00909     return global_value_ptr(thd, base);
00910   }
00911 };
00912 
00913 // overflow-safe (1 << X)-1
00914 #define MAX_SET(X) ((((1UL << ((X)-1))-1) << 1) | 1)
00915 
00930 class Sys_var_flagset: public Sys_var_typelib
00931 {
00932 public:
00933   Sys_var_flagset(const char *name_arg,
00934           const char *comment, int flag_args, ptrdiff_t off, size_t size,
00935           CMD_LINE getopt,
00936           const char *values[], ulonglong def_val, PolyLock *lock=0,
00937           enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
00938           on_check_function on_check_func=0,
00939           on_update_function on_update_func=0,
00940           const char *substitute=0)
00941     : Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
00942                       SHOW_CHAR, values, def_val, lock,
00943                       binlog_status_arg, on_check_func, on_update_func,
00944                       substitute)
00945   {
00946     option.var_type= GET_FLAGSET;
00947     global_var(ulonglong)= def_val;
00948     DBUG_ASSERT(typelib.count > 1);
00949     DBUG_ASSERT(typelib.count <= 65);
00950     DBUG_ASSERT(def_val < MAX_SET(typelib.count));
00951     DBUG_ASSERT(strcmp(values[typelib.count-1], "default") == 0);
00952     DBUG_ASSERT(size == sizeof(ulonglong));
00953   }
00954   bool do_check(THD *thd, set_var *var)
00955   {
00956     char buff[STRING_BUFFER_USUAL_SIZE];
00957     String str(buff, sizeof(buff), system_charset_info), *res;
00958     ulonglong default_value, current_value;
00959     if (var->type == OPT_GLOBAL)
00960     {
00961       default_value= option.def_value;
00962       current_value= global_var(ulonglong);
00963     }
00964     else
00965     {
00966       default_value= global_var(ulonglong);
00967       current_value= session_var(thd, ulonglong);
00968     }
00969 
00970     if (var->value->result_type() == STRING_RESULT)
00971     {
00972       if (!(res=var->value->val_str(&str)))
00973         return true;
00974       else
00975       {
00976         char *error;
00977         uint error_len;
00978 
00979         var->save_result.ulonglong_value=
00980               find_set_from_flags(&typelib,
00981                                   typelib.count,
00982                                   current_value,
00983                                   default_value,
00984                                   res->ptr(), res->length(),
00985                                   &error, &error_len);
00986         if (error)
00987         {
00988           ErrConvString err(error, error_len, res->charset());
00989           my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr());
00990           return true;
00991         }
00992       }
00993     }
00994     else
00995     {
00996       longlong tmp=var->value->val_int();
00997       if ((tmp < 0 && ! var->value->unsigned_flag)
00998           || (ulonglong)tmp > MAX_SET(typelib.count))
00999         return true;
01000       else
01001         var->save_result.ulonglong_value= tmp;
01002     }
01003 
01004     return false;
01005   }
01006   bool session_update(THD *thd, set_var *var)
01007   {
01008     session_var(thd, ulonglong)= var->save_result.ulonglong_value;
01009     return false;
01010   }
01011   bool global_update(THD *thd, set_var *var)
01012   {
01013     global_var(ulonglong)= var->save_result.ulonglong_value;
01014     return false;
01015   }
01016   void session_save_default(THD *thd, set_var *var)
01017   { var->save_result.ulonglong_value= global_var(ulonglong); }
01018   void global_save_default(THD *thd, set_var *var)
01019   { var->save_result.ulonglong_value= option.def_value; }
01020   uchar *session_value_ptr(THD *thd, LEX_STRING *base)
01021   {
01022     return (uchar*)flagset_to_string(thd, 0, session_var(thd, ulonglong),
01023                                      typelib.type_names);
01024   }
01025   uchar *global_value_ptr(THD *thd, LEX_STRING *base)
01026   {
01027     return (uchar*)flagset_to_string(thd, 0, global_var(ulonglong),
01028                                      typelib.type_names);
01029   }
01030 };
01031 
01041 class Sys_var_set: public Sys_var_typelib
01042 {
01043 public:
01044   Sys_var_set(const char *name_arg,
01045           const char *comment, int flag_args, ptrdiff_t off, size_t size,
01046           CMD_LINE getopt,
01047           const char *values[], ulonglong def_val, PolyLock *lock=0,
01048           enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
01049           on_check_function on_check_func=0,
01050           on_update_function on_update_func=0,
01051           const char *substitute=0)
01052     : Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
01053                       SHOW_CHAR, values, def_val, lock,
01054                       binlog_status_arg, on_check_func, on_update_func,
01055                       substitute)
01056   {
01057     option.var_type= GET_SET;
01058     global_var(ulonglong)= def_val;
01059     DBUG_ASSERT(typelib.count > 0);
01060     DBUG_ASSERT(typelib.count <= 64);
01061     DBUG_ASSERT(def_val < MAX_SET(typelib.count));
01062     DBUG_ASSERT(size == sizeof(ulonglong));
01063   }
01064   bool do_check(THD *thd, set_var *var)
01065   {
01066     char buff[STRING_BUFFER_USUAL_SIZE];
01067     String str(buff, sizeof(buff), system_charset_info), *res;
01068 
01069     if (var->value->result_type() == STRING_RESULT)
01070     {
01071       if (!(res=var->value->val_str(&str)))
01072         return true;
01073       else
01074       {
01075         char *error;
01076         uint error_len;
01077         bool not_used;
01078 
01079         var->save_result.ulonglong_value=
01080               find_set(&typelib, res->ptr(), res->length(), NULL,
01081                       &error, &error_len, &not_used);
01082         /*
01083           note, we only issue an error if error_len > 0.
01084           That is even while empty (zero-length) values are considered
01085           errors by find_set(), these errors are ignored here
01086         */
01087         if (error_len)
01088         {
01089           ErrConvString err(error, error_len, res->charset());
01090           my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr());
01091           return true;
01092         }
01093       }
01094     }
01095     else
01096     {
01097       longlong tmp=var->value->val_int();
01098       if ((tmp < 0 && ! var->value->unsigned_flag)
01099           || (ulonglong)tmp > MAX_SET(typelib.count))
01100         return true;
01101       else
01102         var->save_result.ulonglong_value= tmp;
01103     }
01104 
01105     return false;
01106   }
01107   bool session_update(THD *thd, set_var *var)
01108   {
01109     session_var(thd, ulonglong)= var->save_result.ulonglong_value;
01110     return false;
01111   }
01112   bool global_update(THD *thd, set_var *var)
01113   {
01114     global_var(ulonglong)= var->save_result.ulonglong_value;
01115     return false;
01116   }
01117   void session_save_default(THD *thd, set_var *var)
01118   { var->save_result.ulonglong_value= global_var(ulonglong); }
01119   void global_save_default(THD *thd, set_var *var)
01120   { var->save_result.ulonglong_value= option.def_value; }
01121   uchar *session_value_ptr(THD *thd, LEX_STRING *base)
01122   {
01123     return (uchar*)set_to_string(thd, 0, session_var(thd, ulonglong),
01124                                  typelib.type_names);
01125   }
01126   uchar *global_value_ptr(THD *thd, LEX_STRING *base)
01127   {
01128     return (uchar*)set_to_string(thd, 0, global_var(ulonglong),
01129                                  typelib.type_names);
01130   }
01131 };
01132 
01146 class Sys_var_plugin: public sys_var
01147 {
01148   int plugin_type;
01149 public:
01150   Sys_var_plugin(const char *name_arg,
01151           const char *comment, int flag_args, ptrdiff_t off, size_t size,
01152           CMD_LINE getopt,
01153           int plugin_type_arg, char **def_val, PolyLock *lock=0,
01154           enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
01155           on_check_function on_check_func=0,
01156           on_update_function on_update_func=0,
01157           const char *substitute=0,
01158           int parse_flag= PARSE_NORMAL)
01159     : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
01160               getopt.arg_type, SHOW_CHAR, (intptr)def_val,
01161               lock, binlog_status_arg, on_check_func, on_update_func,
01162               substitute, parse_flag),
01163     plugin_type(plugin_type_arg)
01164   {
01165     option.var_type= GET_STR;
01166     DBUG_ASSERT(size == sizeof(plugin_ref));
01167     DBUG_ASSERT(getopt.id == -1); // force NO_CMD_LINE
01168   }
01169   bool do_check(THD *thd, set_var *var)
01170   {
01171     char buff[STRING_BUFFER_USUAL_SIZE];
01172     String str(buff,sizeof(buff), system_charset_info), *res;
01173     if (!(res=var->value->val_str(&str)))
01174       var->save_result.plugin= NULL;
01175     else
01176     {
01177       const LEX_STRING pname= { const_cast<char*>(res->ptr()), res->length() };
01178       plugin_ref plugin;
01179 
01180       // special code for storage engines (e.g. to handle historical aliases)
01181       if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN)
01182         plugin= ha_resolve_by_name(thd, &pname, FALSE);
01183       else
01184         plugin= my_plugin_lock_by_name(thd, &pname, plugin_type);
01185       if (!plugin)
01186       {
01187         // historically different error code
01188         if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN)
01189         {
01190           ErrConvString err(res);
01191           my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), err.ptr());
01192         }
01193         return true;
01194       }
01195       var->save_result.plugin= plugin;
01196     }
01197     return false;
01198   }
01199   void do_update(plugin_ref *valptr, plugin_ref newval)
01200   {
01201     plugin_ref oldval= *valptr;
01202     if (oldval != newval)
01203     {
01204       *valptr= my_plugin_lock(NULL, &newval);
01205       plugin_unlock(NULL, oldval);
01206     }
01207   }
01208   bool session_update(THD *thd, set_var *var)
01209   {
01210     do_update((plugin_ref*)session_var_ptr(thd),
01211               var->save_result.plugin);
01212     return false;
01213   }
01214   bool global_update(THD *thd, set_var *var)
01215   {
01216     do_update((plugin_ref*)global_var_ptr(),
01217               var->save_result.plugin);
01218     return false;
01219   }
01220   void session_save_default(THD *thd, set_var *var)
01221   {
01222     plugin_ref plugin= global_var(plugin_ref);
01223     var->save_result.plugin= my_plugin_lock(thd, &plugin);
01224   }
01225   void global_save_default(THD *thd, set_var *var)
01226   {
01227     LEX_STRING pname;
01228     char **default_value= reinterpret_cast<char**>(option.def_value);
01229     pname.str= *default_value;
01230     pname.length= strlen(pname.str);
01231 
01232     plugin_ref plugin;
01233     if (plugin_type == MYSQL_STORAGE_ENGINE_PLUGIN)
01234       plugin= ha_resolve_by_name(thd, &pname, FALSE);
01235     else
01236       plugin= my_plugin_lock_by_name(thd, &pname, plugin_type);
01237     DBUG_ASSERT(plugin);
01238 
01239     var->save_result.plugin= my_plugin_lock(thd, &plugin);
01240   }
01241   bool check_update_type(Item_result type)
01242   { return type != STRING_RESULT; }
01243   uchar *session_value_ptr(THD *thd, LEX_STRING *base)
01244   {
01245     plugin_ref plugin= session_var(thd, plugin_ref);
01246     return (uchar*)(plugin ? thd->strmake(plugin_name(plugin)->str,
01247                                           plugin_name(plugin)->length) : 0);
01248   }
01249   uchar *global_value_ptr(THD *thd, LEX_STRING *base)
01250   {
01251     plugin_ref plugin= global_var(plugin_ref);
01252     return (uchar*)(plugin ? thd->strmake(plugin_name(plugin)->str,
01253                                           plugin_name(plugin)->length) : 0);
01254   }
01255 };
01256 
01257 #if defined(ENABLED_DEBUG_SYNC)
01258 
01261 class Sys_var_debug_sync :public sys_var
01262 {
01263 public:
01264   Sys_var_debug_sync(const char *name_arg,
01265                const char *comment, int flag_args,
01266                CMD_LINE getopt,
01267                const char *def_val, PolyLock *lock=0,
01268                enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
01269                on_check_function on_check_func=0,
01270                on_update_function on_update_func=0,
01271                const char *substitute=0,
01272                int parse_flag= PARSE_NORMAL)
01273     : sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id,
01274               getopt.arg_type, SHOW_CHAR, (intptr)def_val,
01275               lock, binlog_status_arg, on_check_func, on_update_func,
01276               substitute, parse_flag)
01277   {
01278     DBUG_ASSERT(scope() == ONLY_SESSION);
01279     option.var_type= GET_NO_ARG;
01280   }
01281   bool do_check(THD *thd, set_var *var)
01282   {
01283     char buff[STRING_BUFFER_USUAL_SIZE];
01284     String str(buff, sizeof(buff), system_charset_info), *res;
01285 
01286     if (!(res=var->value->val_str(&str)))
01287       var->save_result.string_value.str= const_cast<char*>("");
01288     else
01289       var->save_result.string_value.str= thd->strmake(res->ptr(), res->length());
01290     return false;
01291   }
01292   bool session_update(THD *thd, set_var *var)
01293   {
01294     extern bool debug_sync_update(THD *thd, char *val_str);
01295     return debug_sync_update(thd, var->save_result.string_value.str);
01296   }
01297   bool global_update(THD *thd, set_var *var)
01298   {
01299     DBUG_ASSERT(FALSE);
01300     return true;
01301   }
01302   void session_save_default(THD *thd, set_var *var)
01303   {
01304     var->save_result.string_value.str= const_cast<char*>("");
01305     var->save_result.string_value.length= 0;
01306   }
01307   void global_save_default(THD *thd, set_var *var)
01308   {
01309     DBUG_ASSERT(FALSE);
01310   }
01311   uchar *session_value_ptr(THD *thd, LEX_STRING *base)
01312   {
01313     extern uchar *debug_sync_value_ptr(THD *thd);
01314     return debug_sync_value_ptr(thd);
01315   }
01316   uchar *global_value_ptr(THD *thd, LEX_STRING *base)
01317   {
01318     DBUG_ASSERT(FALSE);
01319     return 0;
01320   }
01321   bool check_update_type(Item_result type)
01322   { return type != STRING_RESULT; }
01323 };
01324 #endif /* defined(ENABLED_DEBUG_SYNC) */
01325 
01345 class Sys_var_bit: public Sys_var_typelib
01346 {
01347   ulonglong bitmask;
01348   bool reverse_semantics;
01349   void set(uchar *ptr, ulonglong value)
01350   {
01351     if ((value != 0) ^ reverse_semantics)
01352       (*(ulonglong *)ptr)|= bitmask;
01353     else
01354       (*(ulonglong *)ptr)&= ~bitmask;
01355   }
01356 public:
01357   Sys_var_bit(const char *name_arg,
01358           const char *comment, int flag_args, ptrdiff_t off, size_t size,
01359           CMD_LINE getopt,
01360           ulonglong bitmask_arg, my_bool def_val, PolyLock *lock=0,
01361           enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
01362           on_check_function on_check_func=0,
01363           on_update_function on_update_func=0,
01364           const char *substitute=0)
01365     : Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
01366                       SHOW_MY_BOOL, bool_values, def_val, lock,
01367                       binlog_status_arg, on_check_func, on_update_func,
01368                       substitute)
01369   {
01370     option.var_type= GET_BOOL;
01371     reverse_semantics= my_count_bits(bitmask_arg) > 1;
01372     bitmask= reverse_semantics ? ~bitmask_arg : bitmask_arg;
01373     set(global_var_ptr(), def_val);
01374     DBUG_ASSERT(def_val < 2);
01375     DBUG_ASSERT(getopt.id == -1); // force NO_CMD_LINE
01376     DBUG_ASSERT(size == sizeof(ulonglong));
01377   }
01378   bool session_update(THD *thd, set_var *var)
01379   {
01380     set(session_var_ptr(thd), var->save_result.ulonglong_value);
01381     return false;
01382   }
01383   bool global_update(THD *thd, set_var *var)
01384   {
01385     set(global_var_ptr(), var->save_result.ulonglong_value);
01386     return false;
01387   }
01388   void session_save_default(THD *thd, set_var *var)
01389   { var->save_result.ulonglong_value= global_var(ulonglong) & bitmask; }
01390   void global_save_default(THD *thd, set_var *var)
01391   { var->save_result.ulonglong_value= option.def_value; }
01392   uchar *session_value_ptr(THD *thd, LEX_STRING *base)
01393   {
01394     thd->sys_var_tmp.my_bool_value= reverse_semantics ^
01395       ((session_var(thd, ulonglong) & bitmask) != 0);
01396     return (uchar*) &thd->sys_var_tmp.my_bool_value;
01397   }
01398   uchar *global_value_ptr(THD *thd, LEX_STRING *base)
01399   {
01400     thd->sys_var_tmp.my_bool_value= reverse_semantics ^
01401       ((global_var(ulonglong) & bitmask) != 0);
01402     return (uchar*) &thd->sys_var_tmp.my_bool_value;
01403   }
01404 };
01405 
01421 class Sys_var_session_special: public Sys_var_ulonglong
01422 {
01423   typedef bool (*session_special_update_function)(THD *thd, set_var *var);
01424   typedef ulonglong (*session_special_read_function)(THD *thd);
01425 
01426   session_special_read_function read_func;
01427   session_special_update_function update_func;
01428 public:
01429   Sys_var_session_special(const char *name_arg,
01430                const char *comment, int flag_args,
01431                CMD_LINE getopt,
01432                ulonglong min_val, ulonglong max_val, ulonglong block_size,
01433                PolyLock *lock, enum binlog_status_enum binlog_status_arg,
01434                on_check_function on_check_func,
01435                session_special_update_function update_func_arg,
01436                session_special_read_function read_func_arg,
01437                const char *substitute=0)
01438     : Sys_var_ulonglong(name_arg, comment, flag_args, 0,
01439               sizeof(ulonglong), getopt, min_val,
01440               max_val, 0, block_size, lock, binlog_status_arg, on_check_func, 0,
01441               substitute),
01442       read_func(read_func_arg), update_func(update_func_arg)
01443   {
01444     DBUG_ASSERT(scope() == ONLY_SESSION);
01445     DBUG_ASSERT(getopt.id == -1); // NO_CMD_LINE, because the offset is fake
01446   }
01447   bool session_update(THD *thd, set_var *var)
01448   { return update_func(thd, var); }
01449   bool global_update(THD *thd, set_var *var)
01450   {
01451     DBUG_ASSERT(FALSE);
01452     return true;
01453   }
01454   void session_save_default(THD *thd, set_var *var)
01455   { var->value= 0; }
01456   void global_save_default(THD *thd, set_var *var)
01457   { DBUG_ASSERT(FALSE); }
01458   uchar *session_value_ptr(THD *thd, LEX_STRING *base)
01459   {
01460     thd->sys_var_tmp.ulonglong_value= read_func(thd);
01461     return (uchar*) &thd->sys_var_tmp.ulonglong_value;
01462   }
01463   uchar *global_value_ptr(THD *thd, LEX_STRING *base)
01464   {
01465     DBUG_ASSERT(FALSE);
01466     return 0;
01467   }
01468 };
01469 
01470 
01474 class Sys_var_session_special_double: public Sys_var_double
01475 {
01476   typedef bool (*session_special_update_function)(THD *thd, set_var *var);
01477   typedef double (*session_special_read_double_function)(THD *thd);
01478 
01479   session_special_read_double_function read_func;
01480   session_special_update_function update_func;
01481 public:
01482   Sys_var_session_special_double(const char *name_arg,
01483                const char *comment, int flag_args,
01484                CMD_LINE getopt,
01485                ulonglong min_val, ulonglong max_val, ulonglong block_size,
01486                PolyLock *lock, enum binlog_status_enum binlog_status_arg,
01487                on_check_function on_check_func,
01488                session_special_update_function update_func_arg,
01489                session_special_read_double_function read_func_arg,
01490                const char *substitute=0)
01491     : Sys_var_double(name_arg, comment, flag_args, 0,
01492               sizeof(double), getopt,
01493               min_val, max_val, 0,
01494               lock, binlog_status_arg, on_check_func, 0,
01495               substitute),
01496       read_func(read_func_arg), update_func(update_func_arg)
01497   {
01498     DBUG_ASSERT(scope() == ONLY_SESSION);
01499     DBUG_ASSERT(getopt.id == -1); // NO_CMD_LINE, because the offset is fake
01500   }
01501   bool session_update(THD *thd, set_var *var)
01502   { return update_func(thd, var); }
01503   bool global_update(THD *thd, set_var *var)
01504   {
01505     DBUG_ASSERT(FALSE);
01506     return true;
01507   }
01508   void session_save_default(THD *thd, set_var *var)
01509   { var->value= 0; }
01510   void global_save_default(THD *thd, set_var *var)
01511   { DBUG_ASSERT(FALSE); }
01512   uchar *session_value_ptr(THD *thd, LEX_STRING *base)
01513   {
01514     thd->sys_var_tmp.double_value= read_func(thd);
01515     return (uchar *) &thd->sys_var_tmp.double_value;
01516   }
01517   uchar *global_value_ptr(THD *thd, LEX_STRING *base)
01518   {
01519     DBUG_ASSERT(FALSE);
01520     return 0;
01521   }
01522 };
01523 
01524 
01535 class Sys_var_have: public sys_var
01536 {
01537 public:
01538   Sys_var_have(const char *name_arg,
01539                const char *comment, int flag_args, ptrdiff_t off, size_t size,
01540                CMD_LINE getopt,
01541                PolyLock *lock=0,
01542                enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
01543                on_check_function on_check_func=0,
01544                on_update_function on_update_func=0,
01545                const char *substitute=0,
01546                int parse_flag= PARSE_NORMAL)
01547     : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
01548               getopt.arg_type, SHOW_CHAR, 0,
01549               lock, binlog_status_arg, on_check_func, on_update_func,
01550               substitute, parse_flag)
01551   {
01552     DBUG_ASSERT(scope() == GLOBAL);
01553     DBUG_ASSERT(getopt.id == -1);
01554     DBUG_ASSERT(lock == 0);
01555     DBUG_ASSERT(binlog_status_arg == VARIABLE_NOT_IN_BINLOG);
01556     DBUG_ASSERT(is_readonly());
01557     DBUG_ASSERT(on_update == 0);
01558     DBUG_ASSERT(size == sizeof(enum SHOW_COMP_OPTION));
01559   }
01560   bool do_check(THD *thd, set_var *var) {
01561     DBUG_ASSERT(FALSE);
01562     return true;
01563   }
01564   bool session_update(THD *thd, set_var *var)
01565   {
01566     DBUG_ASSERT(FALSE);
01567     return true;
01568   }
01569   bool global_update(THD *thd, set_var *var)
01570   {
01571     DBUG_ASSERT(FALSE);
01572     return true;
01573   }
01574   void session_save_default(THD *thd, set_var *var) { }
01575   void global_save_default(THD *thd, set_var *var) { }
01576   uchar *session_value_ptr(THD *thd, LEX_STRING *base)
01577   {
01578     DBUG_ASSERT(FALSE);
01579     return 0;
01580   }
01581   uchar *global_value_ptr(THD *thd, LEX_STRING *base)
01582   {
01583     return (uchar*)show_comp_option_name[global_var(enum SHOW_COMP_OPTION)];
01584   }
01585   bool check_update_type(Item_result type) { return false; }
01586 };
01587 
01603 class Sys_var_struct: public sys_var
01604 {
01605   ptrdiff_t name_offset; // offset to the 'name' property in the structure
01606 public:
01607   Sys_var_struct(const char *name_arg,
01608           const char *comment, int flag_args, ptrdiff_t off, size_t size,
01609           CMD_LINE getopt,
01610           ptrdiff_t name_off, void *def_val, PolyLock *lock=0,
01611           enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
01612           on_check_function on_check_func=0,
01613           on_update_function on_update_func=0,
01614           const char *substitute=0,
01615           int parse_flag= PARSE_NORMAL)
01616     : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
01617               getopt.arg_type, SHOW_CHAR, (intptr)def_val,
01618               lock, binlog_status_arg, on_check_func, on_update_func,
01619               substitute, parse_flag),
01620       name_offset(name_off)
01621   {
01622     option.var_type= GET_STR;
01623     /*
01624       struct variables are special on the command line - often (e.g. for
01625       charsets) the name cannot be immediately resolved, but only after all
01626       options (in particular, basedir) are parsed.
01627 
01628       thus all struct command-line options should be added manually
01629       to my_long_options in mysqld.cc
01630     */
01631     DBUG_ASSERT(getopt.id == -1);
01632     DBUG_ASSERT(size == sizeof(void *));
01633   }
01634   bool do_check(THD *thd, set_var *var)
01635   { return false; }
01636   bool session_update(THD *thd, set_var *var)
01637   {
01638     session_var(thd, const void*)= var->save_result.ptr;
01639     return false;
01640   }
01641   bool global_update(THD *thd, set_var *var)
01642   {
01643     global_var(const void*)= var->save_result.ptr;
01644     return false;
01645   }
01646   void session_save_default(THD *thd, set_var *var)
01647   { var->save_result.ptr= global_var(void*); }
01648   void global_save_default(THD *thd, set_var *var)
01649   {
01650     void **default_value= reinterpret_cast<void**>(option.def_value);
01651     var->save_result.ptr= *default_value;
01652   }
01653   bool check_update_type(Item_result type)
01654   { return type != INT_RESULT && type != STRING_RESULT; }
01655   uchar *session_value_ptr(THD *thd, LEX_STRING *base)
01656   {
01657     uchar *ptr= session_var(thd, uchar*);
01658     return ptr ? *(uchar**)(ptr+name_offset) : 0;
01659   }
01660   uchar *global_value_ptr(THD *thd, LEX_STRING *base)
01661   {
01662     uchar *ptr= global_var(uchar*);
01663     return ptr ? *(uchar**)(ptr+name_offset) : 0;
01664   }
01665 };
01666 
01677 class Sys_var_tz: public sys_var
01678 {
01679 public:
01680   Sys_var_tz(const char *name_arg,
01681              const char *comment, int flag_args, ptrdiff_t off, size_t size,
01682              CMD_LINE getopt,
01683              Time_zone **def_val, PolyLock *lock=0,
01684              enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
01685              on_check_function on_check_func=0,
01686              on_update_function on_update_func=0,
01687              const char *substitute=0,
01688              int parse_flag= PARSE_NORMAL)
01689     : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
01690               getopt.arg_type, SHOW_CHAR, (intptr)def_val,
01691               lock, binlog_status_arg, on_check_func, on_update_func,
01692               substitute, parse_flag)
01693   {
01694     DBUG_ASSERT(getopt.id == -1);
01695     DBUG_ASSERT(size == sizeof(Time_zone *));
01696   }
01697   bool do_check(THD *thd, set_var *var)
01698   {
01699     char buff[MAX_TIME_ZONE_NAME_LENGTH];
01700     String str(buff, sizeof(buff), &my_charset_latin1);
01701     String *res= var->value->val_str(&str);
01702 
01703     if (!res)
01704       return true;
01705 
01706     if (!(var->save_result.time_zone= my_tz_find(thd, res)))
01707     {
01708       ErrConvString err(res);
01709       my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), err.ptr());
01710       return true;
01711     }
01712     return false;
01713   }
01714   bool session_update(THD *thd, set_var *var)
01715   {
01716     session_var(thd, Time_zone*)= var->save_result.time_zone;
01717     return false;
01718   }
01719   bool global_update(THD *thd, set_var *var)
01720   {
01721     global_var(Time_zone*)= var->save_result.time_zone;
01722     return false;
01723   }
01724   void session_save_default(THD *thd, set_var *var)
01725   {
01726     var->save_result.time_zone= global_var(Time_zone*);
01727   }
01728   void global_save_default(THD *thd, set_var *var)
01729   {
01730     var->save_result.time_zone=
01731       *(Time_zone**)(intptr)option.def_value;
01732   }
01733   uchar *session_value_ptr(THD *thd, LEX_STRING *base)
01734   {
01735     /*
01736       This is an ugly fix for replication: we don't replicate properly queries
01737       invoking system variables' values to update tables; but
01738       CONVERT_TZ(,,@@session.time_zone) is so popular that we make it
01739       replicable (i.e. we tell the binlog code to store the session
01740       timezone). If it's the global value which was used we can't replicate
01741       (binlog code stores session value only).
01742     */
01743     thd->time_zone_used= 1;
01744     return (uchar *)(session_var(thd, Time_zone*)->get_name()->ptr());
01745   }
01746   uchar *global_value_ptr(THD *thd, LEX_STRING *base)
01747   {
01748     return (uchar *)(global_var(Time_zone*)->get_name()->ptr());
01749   }
01750   bool check_update_type(Item_result type)
01751   { return type != STRING_RESULT; }
01752 };
01753 
01754 
01755 class Sys_var_tx_isolation: public Sys_var_enum
01756 {
01757 public:
01758   Sys_var_tx_isolation(const char *name_arg,
01759           const char *comment, int flag_args, ptrdiff_t off, size_t size,
01760           CMD_LINE getopt,
01761           const char *values[], uint def_val, PolyLock *lock,
01762           enum binlog_status_enum binlog_status_arg,
01763           on_check_function on_check_func)
01764     :Sys_var_enum(name_arg, comment, flag_args, off, size, getopt,
01765                   values, def_val, lock, binlog_status_arg, on_check_func)
01766   {}
01767   virtual bool session_update(THD *thd, set_var *var);
01768 };
01769 
01770 
01780 class Sys_var_tx_read_only: public Sys_var_mybool
01781 {
01782 public:
01783   Sys_var_tx_read_only(const char *name_arg, const char *comment, int flag_args,
01784                        ptrdiff_t off, size_t size, CMD_LINE getopt,
01785                        my_bool def_val, PolyLock *lock,
01786                        enum binlog_status_enum binlog_status_arg,
01787                        on_check_function on_check_func)
01788     :Sys_var_mybool(name_arg, comment, flag_args, off, size, getopt,
01789                     def_val, lock, binlog_status_arg, on_check_func)
01790   {}
01791   virtual bool session_update(THD *thd, set_var *var);
01792 };
01793 
01794 
01799 class Sys_var_enum_binlog_checksum: public Sys_var_enum
01800 {
01801 public:
01802   Sys_var_enum_binlog_checksum(const char *name_arg,
01803           const char *comment, int flag_args, ptrdiff_t off, size_t size,
01804           CMD_LINE getopt,
01805           const char *values[], uint def_val, PolyLock *lock,
01806           enum binlog_status_enum binlog_status_arg)
01807     :Sys_var_enum(name_arg, comment, flag_args, off, size, getopt,
01808                   values, def_val, lock, binlog_status_arg, NULL)
01809   {}
01810   virtual bool global_update(THD *thd, set_var *var);
01811 };
01812 
01813 
01817 class Sys_var_gtid_specification: public sys_var
01818 {
01819 public:
01820   Sys_var_gtid_specification(const char *name_arg,
01821           const char *comment, int flag_args, ptrdiff_t off, size_t size,
01822           CMD_LINE getopt,
01823           const char *def_val,
01824           PolyLock *lock= 0,
01825           enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
01826           on_check_function on_check_func=0,
01827           on_update_function on_update_func=0,
01828           const char *substitute=0,
01829           int parse_flag= PARSE_NORMAL)
01830     : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
01831               getopt.arg_type, SHOW_CHAR, (intptr)def_val,
01832               lock, binlog_status_arg, on_check_func, on_update_func,
01833               substitute, parse_flag)
01834   {
01835     DBUG_ASSERT(size == sizeof(Gtid_specification));
01836   }
01837   bool session_update(THD *thd, set_var *var)
01838   {
01839     DBUG_ENTER("Sys_var_gtid::session_update");
01840     global_sid_lock->rdlock();
01841     bool ret= (((Gtid_specification *)session_var_ptr(thd))->
01842                parse(global_sid_map,
01843                      var->save_result.string_value.str) != 0);
01844     global_sid_lock->unlock();
01845     DBUG_RETURN(ret);
01846   }
01847   bool global_update(THD *thd, set_var *var)
01848   { DBUG_ASSERT(FALSE); return true; }
01849   void session_save_default(THD *thd, set_var *var)
01850   {
01851     DBUG_ENTER("Sys_var_gtid::session_save_default");
01852     char *ptr= (char*)(intptr)option.def_value;
01853     var->save_result.string_value.str= ptr;
01854     var->save_result.string_value.length= ptr ? strlen(ptr) : 0;
01855     DBUG_VOID_RETURN;
01856   }
01857   void global_save_default(THD *thd, set_var *var)
01858   { DBUG_ASSERT(FALSE); }
01859   bool do_check(THD *thd, set_var *var)
01860   {
01861     DBUG_ENTER("Sys_var_gtid::do_check");
01862     char buf[Gtid_specification::MAX_TEXT_LENGTH + 1];
01863     String str(buf, sizeof(buf), &my_charset_latin1);
01864     String *res= var->value->val_str(&str);
01865     if (!res)
01866       DBUG_RETURN(true);
01867     var->save_result.string_value.str= thd->strmake(res->c_ptr_safe(), res->length());
01868     if (!var->save_result.string_value.str)
01869     {
01870       my_error(ER_OUT_OF_RESOURCES, MYF(0)); // thd->strmake failed
01871       DBUG_RETURN(true);
01872     }
01873     var->save_result.string_value.length= res->length();
01874     bool ret= Gtid_specification::is_valid(res->c_ptr_safe()) ? false : true;
01875     DBUG_PRINT("info", ("ret=%d", ret));
01876     DBUG_RETURN(ret);
01877   }
01878   bool check_update_type(Item_result type)
01879   { return type != STRING_RESULT; }
01880   uchar *session_value_ptr(THD *thd, LEX_STRING *base)
01881   {
01882     DBUG_ENTER("Sys_var_gtid::session_value_ptr");
01883     char buf[Gtid_specification::MAX_TEXT_LENGTH + 1];
01884     global_sid_lock->rdlock();
01885     ((Gtid_specification *)session_var_ptr(thd))->
01886       to_string(global_sid_map, buf);
01887     global_sid_lock->unlock();
01888     char *ret= thd->strdup(buf);
01889     DBUG_RETURN((uchar *)ret);
01890   }
01891   uchar *global_value_ptr(THD *thd, LEX_STRING *base)
01892   { DBUG_ASSERT(FALSE); return NULL; }
01893 };
01894 
01895 #ifdef HAVE_GTID_NEXT_LIST
01896 
01903 class Sys_var_gtid_set: public sys_var
01904 {
01905 public:
01906   Sys_var_gtid_set(const char *name_arg,
01907           const char *comment, int flag_args, ptrdiff_t off, size_t size,
01908           CMD_LINE getopt,
01909           const char *def_val,
01910           PolyLock *lock= 0,
01911           enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
01912           on_check_function on_check_func=0,
01913           on_update_function on_update_func=0,
01914           const char *substitute=0,
01915           int parse_flag= PARSE_NORMAL)
01916     : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
01917               getopt.arg_type, SHOW_CHAR, (intptr)def_val,
01918               lock, binlog_status_arg, on_check_func, on_update_func,
01919               substitute, parse_flag)
01920   {
01921     DBUG_ASSERT(size == sizeof(Gtid_set_or_null));
01922   }
01923   bool session_update(THD *thd, set_var *var)
01924   {
01925     DBUG_ENTER("Sys_var_gtid_set::session_update");
01926     Gtid_set_or_null *gsn=
01927       (Gtid_set_or_null *)session_var_ptr(thd);
01928     char *value= var->save_result.string_value.str;
01929     if (value == NULL)
01930       gsn->set_null();
01931     else
01932     {
01933       Gtid_set *gs= gsn->set_non_null(global_sid_map);
01934       if (gs == NULL)
01935       {
01936         my_error(ER_OUT_OF_RESOURCES, MYF(0)); // allocation failed
01937         DBUG_RETURN(true);
01938       }
01939       /*
01940         If string begins with '+', add to the existing set, otherwise
01941         replace existing set.
01942       */
01943       while (isspace(*value))
01944         value++;
01945       if (*value == '+')
01946         value++;
01947       else
01948         gs->clear();
01949       // Add specified set of groups to Gtid_set.
01950       global_sid_lock->rdlock();
01951       enum_return_status ret= gs->add_gtid_text(value);
01952       global_sid_lock->unlock();
01953       if (ret != RETURN_STATUS_OK)
01954       {
01955         gsn->set_null();
01956         DBUG_RETURN(true);
01957       }
01958     }
01959     DBUG_RETURN(false);
01960   }
01961   bool global_update(THD *thd, set_var *var)
01962   { DBUG_ASSERT(FALSE); return true; }
01963   void session_save_default(THD *thd, set_var *var)
01964   {
01965     DBUG_ENTER("Sys_var_gtid_set::session_save_default");
01966     char *ptr= (char*)(intptr)option.def_value;
01967     var->save_result.string_value.str= ptr;
01968     var->save_result.string_value.length= ptr ? strlen(ptr) : 0;
01969     DBUG_VOID_RETURN;
01970   }
01971   void global_save_default(THD *thd, set_var *var)
01972   { DBUG_ASSERT(FALSE); }
01973   bool do_check(THD *thd, set_var *var)
01974   {
01975     DBUG_ENTER("Sys_var_gtid_set::do_check");
01976     String str;
01977     String *res= var->value->val_str(&str);
01978     if (res == NULL)
01979     {
01980       var->save_result.string_value.str= NULL;
01981       DBUG_RETURN(FALSE);
01982     }
01983     DBUG_ASSERT(res->ptr() != NULL);
01984     var->save_result.string_value.str= thd->strmake(res->ptr(), res->length());
01985     if (var->save_result.string_value.str == NULL)
01986     {
01987       my_error(ER_OUT_OF_RESOURCES, MYF(0)); // thd->strmake failed
01988       DBUG_RETURN(1);
01989     }
01990     var->save_result.string_value.length= res->length();
01991     bool ret= !Gtid_set::is_valid(res->ptr());
01992     DBUG_RETURN(ret);
01993   }
01994   bool check_update_type(Item_result type)
01995   { return type != STRING_RESULT; }
01996   uchar *session_value_ptr(THD *thd, LEX_STRING *base)
01997   {
01998     DBUG_ENTER("Sys_var_gtid_set::session_value_ptr");
01999     Gtid_set_or_null *gsn= (Gtid_set_or_null *)session_var_ptr(thd);
02000     Gtid_set *gs= gsn->get_gtid_set();
02001     if (gs == NULL)
02002       DBUG_RETURN(NULL);
02003     char *buf;
02004     global_sid_lock->rdlock();
02005     buf= (char *)thd->alloc(gs->get_string_length() + 1);
02006     if (buf)
02007       gs->to_string(buf);
02008     else
02009       my_error(ER_OUT_OF_RESOURCES, MYF(0)); // thd->alloc faile
02010     global_sid_lock->unlock();
02011     DBUG_RETURN((uchar *)buf);
02012   }
02013   uchar *global_value_ptr(THD *thd, LEX_STRING *base)
02014   { DBUG_ASSERT(FALSE); return NULL; }
02015 };
02016 #endif
02017 
02018 
02025 class Sys_var_charptr_func: public sys_var
02026 {
02027 public:
02028   Sys_var_charptr_func(const char *name_arg, const char *comment,
02029                        flag_enum flag_arg)
02030     : sys_var(&all_sys_vars, name_arg, comment, READ_ONLY flag_arg,
02031               0/*off*/, NO_CMD_LINE.id, NO_CMD_LINE.arg_type,
02032               SHOW_CHAR, (intptr)0/*def_val*/,
02033               NULL/*polylock*/, VARIABLE_NOT_IN_BINLOG,
02034               NULL/*on_check_func*/, NULL/*on_update_func*/,
02035               NULL/*substitute*/, PARSE_NORMAL/*parse_flag*/)
02036   {
02037     DBUG_ASSERT(flag_arg == sys_var::GLOBAL || flag_arg == sys_var::SESSION ||
02038                 flag_arg == sys_var::ONLY_SESSION);
02039   }
02040   bool session_update(THD *thd, set_var *var)
02041   { DBUG_ASSERT(FALSE); return true; }
02042   bool global_update(THD *thd, set_var *var)
02043   { DBUG_ASSERT(FALSE); return true; }
02044   void session_save_default(THD *thd, set_var *var) { DBUG_ASSERT(FALSE); }
02045   void global_save_default(THD *thd, set_var *var) { DBUG_ASSERT(FALSE); }
02046   bool do_check(THD *thd, set_var *var) { DBUG_ASSERT(FALSE); return true; }
02047   bool check_update_type(Item_result type) { DBUG_ASSERT(FALSE); return true; }
02048   virtual uchar *session_value_ptr(THD *thd, LEX_STRING *base)
02049   { DBUG_ASSERT(FALSE); return NULL; }
02050   virtual uchar *global_value_ptr(THD *thd, LEX_STRING *base)
02051   { DBUG_ASSERT(FALSE); return NULL; }
02052 };
02053 
02054 
02061 class Sys_var_gtid_set_func: public Sys_var_charptr_func
02062 {
02063 public:
02064   Sys_var_gtid_set_func(const char *name_arg, const char *comment,
02065                         flag_enum flag_arg)
02066     : Sys_var_charptr_func(name_arg, comment, flag_arg) {}
02067 
02068   typedef enum_return_status (*Gtid_set_getter)(THD *, Gtid_set *);
02069 
02070   static uchar *get_string_from_gtid_set(THD *thd,
02071                                          Gtid_set_getter get_gtid_set)
02072   {
02073     DBUG_ENTER("Sys_var_gtid_ended_groups::session_value_ptr");
02074     Gtid_set gs(global_sid_map);
02075     char *buf;
02076     // As an optimization, add 10 Intervals that do not need to be
02077     // allocated.
02078     Gtid_set::Interval ivs[10];
02079     gs.add_interval_memory(10, ivs);
02080     global_sid_lock->wrlock();
02081     if (get_gtid_set(thd, &gs) != RETURN_STATUS_OK)
02082       goto error;
02083     // allocate string and print to it
02084     buf= (char *)thd->alloc(gs.get_string_length() + 1);
02085     if (buf == NULL)
02086     {
02087       my_error(ER_OUT_OF_RESOURCES, MYF(0));
02088       goto error;
02089     }
02090     gs.to_string(buf);
02091     global_sid_lock->unlock();
02092     DBUG_RETURN((uchar *)buf);
02093   error:
02094     global_sid_lock->unlock();
02095     DBUG_RETURN(NULL);
02096   }
02097 };
02098 
02099 
02103 class Sys_var_gtid_executed : Sys_var_gtid_set_func
02104 {
02105 public:
02106   Sys_var_gtid_executed(const char *name_arg, const char *comment_arg)
02107     : Sys_var_gtid_set_func(name_arg, comment_arg, SESSION) {}
02108 
02109   uchar *global_value_ptr(THD *thd, LEX_STRING *base)
02110   {
02111     DBUG_ENTER("Sys_var_gtid_executed::global_value_ptr");
02112     global_sid_lock->wrlock();
02113     const Gtid_set *gs= gtid_state->get_logged_gtids();
02114     char *buf= (char *)thd->alloc(gs->get_string_length() + 1);
02115     if (buf == NULL)
02116       my_error(ER_OUT_OF_RESOURCES, MYF(0));
02117     else
02118       gs->to_string(buf);
02119     global_sid_lock->unlock();
02120     DBUG_RETURN((uchar *)buf);
02121   }
02122 
02123 private:
02124   static enum_return_status get_groups_from_trx_cache(THD *thd, Gtid_set *gs)
02125   {
02126     DBUG_ENTER("Sys_var_gtid_executed::get_groups_from_trx_cache");
02127     if (opt_bin_log)
02128     {
02129       thd->binlog_setup_trx_data();
02130       PROPAGATE_REPORTED_ERROR(thd->get_group_cache(true)->get_gtids(gs));
02131     }
02132     RETURN_OK;
02133   }
02134 
02135 public:
02136   uchar *session_value_ptr(THD *thd, LEX_STRING *base)
02137   {
02138     return get_string_from_gtid_set(thd, get_groups_from_trx_cache);
02139   }
02140 };
02141 
02142 
02146 class Sys_var_gtid_purged : public sys_var
02147 {
02148 public:
02149   Sys_var_gtid_purged(const char *name_arg,
02150           const char *comment, int flag_args, ptrdiff_t off, size_t size,
02151           CMD_LINE getopt,
02152           const char *def_val,
02153           PolyLock *lock= 0,
02154           enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
02155           on_check_function on_check_func=0,
02156           on_update_function on_update_func=0,
02157           const char *substitute=0,
02158           int parse_flag= PARSE_NORMAL)
02159     : sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
02160               getopt.arg_type, SHOW_CHAR, (intptr)def_val,
02161               lock, binlog_status_arg, on_check_func, on_update_func,
02162               substitute, parse_flag)
02163   {}
02164 
02165   bool session_update(THD *thd, set_var *var)
02166   {
02167     DBUG_ASSERT(FALSE);
02168     return true;
02169   }
02170 
02171   void session_save_default(THD *thd, set_var *var)
02172   { DBUG_ASSERT(FALSE); }
02173 
02174   bool global_update(THD *thd, set_var *var)
02175   {
02176     DBUG_ENTER("Sys_var_gtid_purged::global_update");
02177 #ifdef HAVE_REPLICATION
02178     bool error= false;
02179     int rotate_res= 0;
02180 
02181     global_sid_lock->wrlock();
02182     char *previous_gtid_logged= gtid_state->get_logged_gtids()->to_string();
02183     char *previous_gtid_lost= gtid_state->get_lost_gtids()->to_string();
02184     enum_return_status ret= gtid_state->add_lost_gtids(var->save_result.string_value.str);
02185     char *current_gtid_logged= gtid_state->get_logged_gtids()->to_string();
02186     char *current_gtid_lost= gtid_state->get_lost_gtids()->to_string();
02187     global_sid_lock->unlock();
02188     if (RETURN_STATUS_OK != ret)
02189     {
02190       error= true;
02191       goto end;
02192     }
02193 
02194     // Log messages saying that GTID_PURGED and GTID_EXECUTED were changed.
02195     sql_print_information(ER(ER_GTID_PURGED_WAS_CHANGED),
02196                           previous_gtid_lost, current_gtid_lost);
02197     sql_print_information(ER(ER_GTID_EXECUTED_WAS_CHANGED),
02198                           previous_gtid_logged, current_gtid_logged);
02199 
02200     // Rotate logs to have Previous_gtid_event on last binlog.
02201     rotate_res= mysql_bin_log.rotate_and_purge(thd, true);
02202     if (rotate_res)
02203     {
02204       error= true;
02205       goto end;
02206     }
02207 
02208 end:
02209     my_free(previous_gtid_logged);
02210     my_free(previous_gtid_lost);
02211     my_free(current_gtid_logged);
02212     my_free(current_gtid_lost);
02213     DBUG_RETURN(error);
02214 #else
02215     DBUG_RETURN(true);
02216 #endif /* HAVE_REPLICATION */
02217   }
02218 
02219   void global_save_default(THD *thd, set_var *var)
02220   {
02221     /* gtid_purged does not have default value */
02222     my_error(ER_NO_DEFAULT, MYF(0), var->var->name.str);
02223   }
02224 
02225   bool do_check(THD *thd, set_var *var)
02226   {
02227     DBUG_ENTER("Sys_var_gtid_purged::do_check");
02228     char buf[1024];
02229     String str(buf, sizeof(buf), system_charset_info);
02230     String *res= var->value->val_str(&str);
02231     if (!res)
02232       DBUG_RETURN(true);
02233     var->save_result.string_value.str= thd->strmake(res->c_ptr_safe(),
02234                                                     res->length());
02235     if (!var->save_result.string_value.str)
02236     {
02237       my_error(ER_OUT_OF_RESOURCES, MYF(0)); // thd->strmake failed
02238       DBUG_RETURN(true);
02239     }
02240     var->save_result.string_value.length= res->length();
02241     bool ret= Gtid_set::is_valid(res->c_ptr_safe()) ? false : true;
02242     DBUG_PRINT("info", ("ret=%d", ret));
02243     DBUG_RETURN(ret);
02244   }
02245 
02246   bool check_update_type(Item_result type)
02247   { return type != STRING_RESULT; }
02248 
02249   uchar *global_value_ptr(THD *thd, LEX_STRING *base)
02250   {
02251     DBUG_ENTER("Sys_var_gtid_purged::global_value_ptr");
02252     global_sid_lock->wrlock();
02253     const Gtid_set *gs= gtid_state->get_lost_gtids();
02254     char *buf= (char *)thd->alloc(gs->get_string_length() + 1);
02255     if (buf == NULL)
02256       my_error(ER_OUT_OF_RESOURCES, MYF(0));
02257     else
02258       gs->to_string(buf);
02259     global_sid_lock->unlock();
02260     DBUG_RETURN((uchar *)buf);
02261   }
02262 
02263   uchar *session_value_ptr(THD *thd, LEX_STRING *base)
02264   { DBUG_ASSERT(0); return NULL; }
02265 };
02266 
02267 
02268 class Sys_var_gtid_owned : Sys_var_gtid_set_func
02269 {
02270 public:
02271   Sys_var_gtid_owned(const char *name_arg, const char *comment_arg)
02272     : Sys_var_gtid_set_func(name_arg, comment_arg, SESSION) {}
02273 
02274 public:
02275   uchar *session_value_ptr(THD *thd, LEX_STRING *base)
02276   {
02277     DBUG_ENTER("Sys_var_gtid_owned::session_value_ptr");
02278     char *buf= NULL;
02279     if (thd->owned_gtid.sidno == 0)
02280       DBUG_RETURN((uchar *)thd->strdup(""));
02281     if (thd->owned_gtid.sidno == -1)
02282     {
02283 #ifdef HAVE_GTID_NEXT_LIST
02284       buf= (char *)thd->alloc(thd->owned_gtid_set.get_string_length() + 1);
02285       if (buf)
02286       {
02287         global_sid_lock->rdlock();
02288         thd->owned_gtid_set.to_string(buf);
02289         global_sid_lock->unlock();
02290       }
02291       else
02292         my_error(ER_OUT_OF_RESOURCES, MYF(0));
02293 #else
02294      DBUG_ASSERT(0); 
02295 #endif
02296     }
02297     else
02298     {
02299       buf= (char *)thd->alloc(Gtid::MAX_TEXT_LENGTH + 1);
02300       if (buf)
02301       {
02302         global_sid_lock->rdlock();
02303         thd->owned_gtid.to_string(global_sid_map, buf);
02304         global_sid_lock->unlock();
02305       }
02306       else
02307         my_error(ER_OUT_OF_RESOURCES, MYF(0));
02308     }
02309     DBUG_RETURN((uchar *)buf);
02310   }
02311 
02312   uchar *global_value_ptr(THD *thd, LEX_STRING *base)
02313   {
02314     DBUG_ENTER("Sys_var_gtid_owned::global_value_ptr");
02315     const Owned_gtids *owned_gtids= gtid_state->get_owned_gtids();
02316     global_sid_lock->wrlock();
02317     char *buf= (char *)thd->alloc(owned_gtids->get_max_string_length());
02318     if (buf)
02319       owned_gtids->to_string(buf);
02320     else
02321       my_error(ER_OUT_OF_RESOURCES, MYF(0)); // thd->alloc faile
02322     global_sid_lock->unlock();
02323     DBUG_RETURN((uchar *)buf);
02324   }
02325 };
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines