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 | |