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