set_var.cc 136 KB
Newer Older
1
/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
unknown's avatar
unknown committed
2 3 4

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
unknown's avatar
unknown committed
5
   the Free Software Foundation; version 2 of the License.
unknown's avatar
unknown committed
6 7 8 9 10 11 12 13 14 15

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

unknown's avatar
unknown committed
16 17 18 19
/**
  @file

  @brief
unknown's avatar
unknown committed
20 21
  Handling of MySQL SQL variables

unknown's avatar
unknown committed
22
  @details
unknown's avatar
unknown committed
23 24 25 26 27
  To add a new variable, one has to do the following:

  - Use one of the 'sys_var... classes from set_var.h or write a specific
    one for the variable type.
  - Define it in the 'variable definition list' in this file.
28 29
  - If the variable is thread specific, add it to 'system_variables' struct.
    If not, add it to mysqld.cc and an declaration in 'mysql_priv.h'
unknown's avatar
unknown committed
30
  - If the variable should be changed from the command line, add a definition
unknown's avatar
unknown committed
31
    of it in the my_option structure list in mysqld.cc
32 33
  - Don't forget to initialize new fields in global_system_variables and
    max_system_variables!
unknown's avatar
unknown committed
34

unknown's avatar
unknown committed
35 36 37 38 39 40 41 42 43 44
  @todo
    Add full support for the variable character_set (for 4.1)

  @todo
    When updating myisam_delay_key_write, we should do a 'flush tables'
    of all MyISAM tables to ensure that they are reopen with the
    new attribute.

  @note
    Be careful with var->save_result: sys_var::check() only updates
45 46 47
    ulonglong_value; so other members of the union are garbage then; to use
    them you must first assign a value to them (in specific ::check() for
    example).
unknown's avatar
unknown committed
48 49
*/

50
#ifdef USE_PRAGMA_IMPLEMENTATION
unknown's avatar
unknown committed
51 52 53 54
#pragma implementation				// gcc: Class implementation
#endif

#include "mysql_priv.h"
55
#include <mysql.h>
unknown's avatar
unknown committed
56
#include "slave.h"
57
#include "rpl_mi.h"
unknown's avatar
unknown committed
58
#include <my_getopt.h>
59
#include <thr_alarm.h>
unknown's avatar
unknown committed
60
#include <myisam.h>
61 62 63
#ifdef WITH_MARIA_STORAGE_ENGINE
#include <maria.h>
#endif
64
#include <my_dir.h>
65
#include <waiting_threads.h>
66
#include "events.h"
67

68
/* WITH_NDBCLUSTER_STORAGE_ENGINE */
69
#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
70
extern ulong ndb_cache_check_time;
71
extern char opt_ndb_constrbuf[];
unknown's avatar
unknown committed
72
extern ulong ndb_extra_logging;
73 74
#endif

unknown's avatar
unknown committed
75 76 77 78
#ifdef HAVE_NDB_BINLOG
extern ulong ndb_report_thresh_binlog_epoch_slip;
extern ulong ndb_report_thresh_binlog_mem_usage;
#endif
79

unknown's avatar
unknown committed
80
extern CHARSET_INFO *character_set_filesystem;
81 82


unknown's avatar
unknown committed
83
static HASH system_variable_hash;
unknown's avatar
unknown committed
84

unknown's avatar
unknown committed
85 86 87
const char *bool_type_names[]= { "OFF", "ON", NullS };
TYPELIB bool_typelib=
{
88
  array_elements(bool_type_names)-1, "", bool_type_names, NULL
unknown's avatar
unknown committed
89 90
};

91 92 93
const char *delay_key_write_type_names[]= { "OFF", "ON", "ALL", NullS };
TYPELIB delay_key_write_typelib=
{
94 95
  array_elements(delay_key_write_type_names)-1, "",
  delay_key_write_type_names, NULL
96 97
};

98 99 100 101 102 103 104 105 106 107
const char *slave_exec_mode_names[]=
{ "STRICT", "IDEMPOTENT", NullS };
static const unsigned int slave_exec_mode_names_len[]=
{ sizeof("STRICT") - 1, sizeof("IDEMPOTENT") - 1, 0 };
TYPELIB slave_exec_mode_typelib=
{
  array_elements(slave_exec_mode_names)-1, "",
  slave_exec_mode_names, (unsigned int *) slave_exec_mode_names_len
};

108 109 110
static int  sys_check_ftb_syntax(THD *thd,  set_var *var);
static bool sys_update_ftb_syntax(THD *thd, set_var * var);
static void sys_default_ftb_syntax(THD *thd, enum_var_type type);
unknown's avatar
unknown committed
111 112 113 114
static bool sys_update_init_connect(THD*, set_var*);
static void sys_default_init_connect(THD*, enum_var_type type);
static bool sys_update_init_slave(THD*, set_var*);
static void sys_default_init_slave(THD*, enum_var_type type);
unknown's avatar
unknown committed
115
static bool set_option_bit(THD *thd, set_var *var);
116
static bool set_option_log_bin_bit(THD *thd, set_var *var);
unknown's avatar
unknown committed
117
static bool set_option_autocommit(THD *thd, set_var *var);
118
static int  check_log_update(THD *thd, set_var *var);
unknown's avatar
unknown committed
119
static bool set_log_update(THD *thd, set_var *var);
120
static int  check_pseudo_thread_id(THD *thd, set_var *var);
121
void fix_binlog_format_after_update(THD *thd, enum_var_type type);
unknown's avatar
unknown committed
122
static void fix_low_priority_updates(THD *thd, enum_var_type type);
123
static int check_tx_isolation(THD *thd, set_var *var);
unknown's avatar
unknown committed
124
static void fix_tx_isolation(THD *thd, enum_var_type type);
unknown's avatar
unknown committed
125 126
static int check_completion_type(THD *thd, set_var *var);
static void fix_completion_type(THD *thd, enum_var_type type);
unknown's avatar
unknown committed
127 128
static void fix_net_read_timeout(THD *thd, enum_var_type type);
static void fix_net_write_timeout(THD *thd, enum_var_type type);
129
static void fix_net_retry_count(THD *thd, enum_var_type type);
unknown's avatar
unknown committed
130 131
static void fix_max_join_size(THD *thd, enum_var_type type);
static void fix_query_cache_size(THD *thd, enum_var_type type);
132
static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type);
133
static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type);
134 135
static void fix_max_binlog_size(THD *thd, enum_var_type type);
static void fix_max_relay_log_size(THD *thd, enum_var_type type);
136
static void fix_max_connections(THD *thd, enum_var_type type);
137
static int check_max_delayed_threads(THD *thd, set_var *var);
138 139
static void fix_thd_mem_root(THD *thd, enum_var_type type);
static void fix_trans_mem_root(THD *thd, enum_var_type type);
140
static void fix_server_id(THD *thd, enum_var_type type);
141 142
bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd,
                          const char *name, longlong val);
unknown's avatar
unknown committed
143
static KEY_CACHE *create_key_cache(const char *name, uint length);
144
void fix_sql_mode_var(THD *thd, enum_var_type type);
145 146 147
static uchar *get_error_count(THD *thd);
static uchar *get_warning_count(THD *thd);
static uchar *get_tmpdir(THD *thd);
148 149 150 151 152
static int  sys_check_log_path(THD *thd,  set_var *var);
static bool sys_update_general_log_path(THD *thd, set_var * var);
static void sys_default_general_log_path(THD *thd, enum_var_type type);
static bool sys_update_slow_log_path(THD *thd, set_var * var);
static void sys_default_slow_log_path(THD *thd, enum_var_type type);
153
static void fix_sys_log_slow_filter(THD *thd, enum_var_type);
unknown's avatar
unknown committed
154 155 156 157 158

/*
  Variable definition list

  These are variables that can be set from the command line, in
159 160 161 162
  alphabetic order.

  The variables are linked into the list. A variable is added to
  it in the constructor (see sys_var class for details).
unknown's avatar
unknown committed
163 164
*/

unknown's avatar
unknown committed
165
static sys_var_chain vars = { NULL, NULL };
166

167 168 169 170 171 172 173 174
static sys_var_thd_ulong
sys_auto_increment_increment(&vars, "auto_increment_increment",
                             &SV::auto_increment_increment, NULL, NULL,
                             sys_var::SESSION_VARIABLE_IN_BINLOG);
static sys_var_thd_ulong
sys_auto_increment_offset(&vars, "auto_increment_offset",
                          &SV::auto_increment_offset, NULL, NULL,
                          sys_var::SESSION_VARIABLE_IN_BINLOG);
175

unknown's avatar
unknown committed
176
static sys_var_bool_ptr	sys_automatic_sp_privileges(&vars, "automatic_sp_privileges",
177 178
					      &sp_automatic_privileges);

179 180 181
static sys_var_const            sys_back_log(&vars, "back_log",
                                             OPT_GLOBAL, SHOW_LONG,
                                             (uchar*) &back_log);
182
static sys_var_const_os_str       sys_basedir(&vars, "basedir", mysql_home);
unknown's avatar
unknown committed
183
static sys_var_long_ptr	sys_binlog_cache_size(&vars, "binlog_cache_size",
unknown's avatar
unknown committed
184
					      &binlog_cache_size);
unknown's avatar
unknown committed
185
static sys_var_thd_binlog_format sys_binlog_format(&vars, "binlog_format",
186
                                            &SV::binlog_format);
unknown's avatar
unknown committed
187
static sys_var_thd_ulong	sys_bulk_insert_buff_size(&vars, "bulk_insert_buffer_size",
unknown's avatar
unknown committed
188
						  &SV::bulk_insert_buff_size);
189
static sys_var_const_os         sys_character_sets_dir(&vars,
190 191 192 193
                                                       "character_sets_dir",
                                                       OPT_GLOBAL, SHOW_CHAR,
                                                       (uchar*)
                                                       mysql_charsets_dir);
194 195 196 197
static sys_var_character_set_sv
sys_character_set_server(&vars, "character_set_server",
                         &SV::collation_server, &default_charset_info, 0,
                         sys_var::SESSION_VARIABLE_IN_BINLOG);
unknown's avatar
unknown committed
198
sys_var_const_str       sys_charset_system(&vars, "character_set_system",
199
                                           (char *)my_charset_utf8_general_ci.name);
200 201 202 203 204 205 206 207 208 209 210 211 212
static sys_var_character_set_database
sys_character_set_database(&vars, "character_set_database",
                           sys_var::SESSION_VARIABLE_IN_BINLOG);
static sys_var_character_set_client
sys_character_set_client(&vars, "character_set_client",
                         &SV::character_set_client,
                         &default_charset_info,
                         sys_var::SESSION_VARIABLE_IN_BINLOG);
static sys_var_character_set_sv
sys_character_set_connection(&vars, "character_set_connection",
                             &SV::collation_connection,
                             &default_charset_info, 0,
                             sys_var::SESSION_VARIABLE_IN_BINLOG);
unknown's avatar
unknown committed
213 214 215 216 217 218 219
static sys_var_character_set_sv sys_character_set_results(&vars, "character_set_results",
                                        &SV::character_set_results,
                                        &default_charset_info, true);
static sys_var_character_set_sv sys_character_set_filesystem(&vars, "character_set_filesystem",
                                        &SV::character_set_filesystem,
                                        &character_set_filesystem);
static sys_var_thd_ulong	sys_completion_type(&vars, "completion_type",
unknown's avatar
unknown committed
220 221 222
					 &SV::completion_type,
					 check_completion_type,
					 fix_completion_type);
223 224 225 226 227 228 229 230 231 232 233 234
static sys_var_collation_sv
sys_collation_connection(&vars, "collation_connection",
                         &SV::collation_connection, &default_charset_info,
                         sys_var::SESSION_VARIABLE_IN_BINLOG);
static sys_var_collation_sv
sys_collation_database(&vars, "collation_database", &SV::collation_database,
                       &default_charset_info,
                       sys_var::SESSION_VARIABLE_IN_BINLOG);
static sys_var_collation_sv
sys_collation_server(&vars, "collation_server", &SV::collation_server,
                     &default_charset_info,
                     sys_var::SESSION_VARIABLE_IN_BINLOG);
unknown's avatar
unknown committed
235
static sys_var_long_ptr	sys_concurrent_insert(&vars, "concurrent_insert",
236
                                              &myisam_concurrent_insert);
unknown's avatar
unknown committed
237
static sys_var_long_ptr	sys_connect_timeout(&vars, "connect_timeout",
unknown's avatar
unknown committed
238
					    &connect_timeout);
239
static sys_var_const_os_str       sys_datadir(&vars, "datadir", mysql_real_data_home);
240 241 242 243 244 245 246 247 248 249 250 251 252

static sys_var_thd_ulong sys_deadlock_search_depth_short(&vars,
                                "deadlock_search_depth_short",
                                 &SV::wt_deadlock_search_depth_short);
static sys_var_thd_ulong sys_deadlock_search_depth_long(&vars,
                                "deadlock_search_depth_long",
                                 &SV::wt_deadlock_search_depth_long);
static sys_var_thd_ulong sys_deadlock_timeout_short(&vars,
                                "deadlock_timeout_short",
                                 &SV::wt_timeout_short);
static sys_var_thd_ulong sys_deadlock_timeout_long(&vars,
                                "deadlock_timeout_long",
                                 &SV::wt_timeout_long);
unknown's avatar
unknown committed
253
#ifndef DBUG_OFF
unknown's avatar
unknown committed
254
static sys_var_thd_dbug        sys_dbug(&vars, "debug");
unknown's avatar
unknown committed
255
#endif
unknown's avatar
unknown committed
256
static sys_var_enum		sys_delay_key_write(&vars, "delay_key_write",
257 258 259
					    &delay_key_write_options,
					    &delay_key_write_typelib,
					    fix_delay_key_write);
unknown's avatar
unknown committed
260
static sys_var_long_ptr	sys_delayed_insert_limit(&vars, "delayed_insert_limit",
unknown's avatar
unknown committed
261
						 &delayed_insert_limit);
unknown's avatar
unknown committed
262
static sys_var_long_ptr	sys_delayed_insert_timeout(&vars, "delayed_insert_timeout",
unknown's avatar
unknown committed
263
						   &delayed_insert_timeout);
unknown's avatar
unknown committed
264
static sys_var_long_ptr	sys_delayed_queue_size(&vars, "delayed_queue_size",
unknown's avatar
unknown committed
265
					       &delayed_queue_size);
266

267
#ifdef HAVE_EVENT_SCHEDULER
unknown's avatar
unknown committed
268
static sys_var_event_scheduler sys_event_scheduler(&vars, "event_scheduler");
269 270
#endif

271 272 273 274 275 276 277
static sys_var_const    sys_extra_port(&vars, "extra_port",
                                       OPT_GLOBAL, SHOW_INT,
                                       (uchar*) &mysqld_extra_port);
static sys_var_long_ptr	sys_extra_max_connections(&vars,
                                                  "extra_max_connections",
                                                  &extra_max_connections,
                                                  fix_max_connections);
unknown's avatar
unknown committed
278
static sys_var_long_ptr	sys_expire_logs_days(&vars, "expire_logs_days",
unknown's avatar
unknown committed
279
					     &expire_logs_days);
unknown's avatar
unknown committed
280 281
static sys_var_bool_ptr	sys_flush(&vars, "flush", &myisam_flush);
static sys_var_long_ptr	sys_flush_time(&vars, "flush_time", &flush_time);
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
static sys_var_str      sys_ft_boolean_syntax(&vars, "ft_boolean_syntax",
                                              sys_check_ftb_syntax,
                                              sys_update_ftb_syntax,
                                              sys_default_ftb_syntax,
                                              ft_boolean_syntax);
static sys_var_const    sys_ft_max_word_len(&vars, "ft_max_word_len",
                                            OPT_GLOBAL, SHOW_LONG,
                                            (uchar*) &ft_max_word_len);
static sys_var_const    sys_ft_min_word_len(&vars, "ft_min_word_len",
                                            OPT_GLOBAL, SHOW_LONG,
                                            (uchar*) &ft_min_word_len);
static sys_var_const    sys_ft_query_expansion_limit(&vars,
                                                     "ft_query_expansion_limit",
                                                     OPT_GLOBAL, SHOW_LONG,
                                                     (uchar*)
                                                     &ft_query_expansion_limit);
static sys_var_const    sys_ft_stopword_file(&vars, "ft_stopword_file",
                                             OPT_GLOBAL, SHOW_CHAR_PTR,
                                             (uchar*) &ft_stopword_file);
301 302 303 304 305

static sys_var_const    sys_ignore_builtin_innodb(&vars, "ignore_builtin_innodb",
                                                  OPT_GLOBAL, SHOW_BOOL,
                                                  (uchar*) &opt_ignore_builtin_innodb);

unknown's avatar
unknown committed
306
sys_var_str             sys_init_connect(&vars, "init_connect", 0,
307 308
                                         sys_update_init_connect,
                                         sys_default_init_connect,0);
309 310 311
static sys_var_const    sys_init_file(&vars, "init_file",
                                      OPT_GLOBAL, SHOW_CHAR_PTR,
                                      (uchar*) &opt_init_file);
unknown's avatar
unknown committed
312
sys_var_str             sys_init_slave(&vars, "init_slave", 0,
313 314
                                       sys_update_init_slave,
                                       sys_default_init_slave,0);
unknown's avatar
unknown committed
315
static sys_var_thd_ulong	sys_interactive_timeout(&vars, "interactive_timeout",
unknown's avatar
unknown committed
316
						&SV::net_interactive_timeout);
unknown's avatar
unknown committed
317
static sys_var_thd_ulong	sys_join_buffer_size(&vars, "join_buffer_size",
unknown's avatar
unknown committed
318
					     &SV::join_buff_size);
unknown's avatar
unknown committed
319 320
static sys_var_key_buffer_size	sys_key_buffer_size(&vars, "key_buffer_size");
static sys_var_key_cache_long  sys_key_cache_block_size(&vars, "key_cache_block_size",
unknown's avatar
unknown committed
321 322
						 offsetof(KEY_CACHE,
							  param_block_size));
unknown's avatar
unknown committed
323
static sys_var_key_cache_long	sys_key_cache_division_limit(&vars, "key_cache_division_limit",
unknown's avatar
unknown committed
324 325
						     offsetof(KEY_CACHE,
							      param_division_limit));
unknown's avatar
unknown committed
326
static sys_var_key_cache_long  sys_key_cache_age_threshold(&vars, "key_cache_age_threshold",
unknown's avatar
unknown committed
327 328
						     offsetof(KEY_CACHE,
							      param_age_threshold));
329 330 331 332 333 334 335 336 337 338 339 340
static sys_var_const    sys_language(&vars, "language",
                                     OPT_GLOBAL, SHOW_CHAR,
                                     (uchar*) language);
static sys_var_const    sys_large_files_support(&vars, "large_files_support",
                                                OPT_GLOBAL, SHOW_BOOL,
                                                (uchar*) &opt_large_files);
static sys_var_const    sys_large_page_size(&vars, "large_page_size",
                                            OPT_GLOBAL, SHOW_INT,
                                            (uchar*) &opt_large_page_size);
static sys_var_const    sys_large_pages(&vars, "large_pages",
                                        OPT_GLOBAL, SHOW_MY_BOOL,
                                        (uchar*) &opt_large_pages);
unknown's avatar
unknown committed
341
static sys_var_bool_ptr	sys_local_infile(&vars, "local_infile",
unknown's avatar
unknown committed
342
					 &opt_local_infile);
343 344 345 346 347 348 349 350
#ifdef HAVE_MLOCKALL
static sys_var_const    sys_locked_in_memory(&vars, "locked_in_memory",
                                             OPT_GLOBAL, SHOW_MY_BOOL,
                                             (uchar*) &locked_in_memory);
#endif
static sys_var_const    sys_log_bin(&vars, "log_bin",
                                    OPT_GLOBAL, SHOW_BOOL,
                                    (uchar*) &opt_bin_log);
unknown's avatar
unknown committed
351 352
static sys_var_trust_routine_creators
sys_trust_routine_creators(&vars, "log_bin_trust_routine_creators",
353
                           &trust_function_creators);
354
static sys_var_bool_ptr
unknown's avatar
unknown committed
355
sys_trust_function_creators(&vars, "log_bin_trust_function_creators",
356
                            &trust_function_creators);
357 358 359
static sys_var_const    sys_log_error(&vars, "log_error",
                                      OPT_GLOBAL, SHOW_CHAR,
                                      (uchar*) log_error_file);
unknown's avatar
unknown committed
360 361
static sys_var_bool_ptr
  sys_log_queries_not_using_indexes(&vars, "log_queries_not_using_indexes",
362
                                    &opt_log_queries_not_using_indexes);
unknown's avatar
unknown committed
363
static sys_var_thd_ulong	sys_log_warnings(&vars, "log_warnings", &SV::log_warnings);
364 365
static sys_var_microseconds	sys_var_long_query_time(&vars, "long_query_time",
                                                        &SV::long_query_time);
366 367 368
static sys_var_microseconds	sys_var_long_query_time2(&vars,
                                                         "log_slow_time",
                                                         &SV::long_query_time);
unknown's avatar
unknown committed
369
static sys_var_thd_bool	sys_low_priority_updates(&vars, "low_priority_updates",
unknown's avatar
unknown committed
370 371 372
						 &SV::low_priority_updates,
						 fix_low_priority_updates);
#ifndef TO_BE_DELETED	/* Alias for the low_priority_updates */
unknown's avatar
unknown committed
373
static sys_var_thd_bool	sys_sql_low_priority_updates(&vars, "sql_low_priority_updates",
unknown's avatar
unknown committed
374 375 376
						     &SV::low_priority_updates,
						     fix_low_priority_updates);
#endif
377 378 379 380 381 382 383 384 385 386
static sys_var_const    sys_lower_case_file_system(&vars,
                                                   "lower_case_file_system",
                                                   OPT_GLOBAL, SHOW_MY_BOOL,
                                                   (uchar*)
                                                   &lower_case_file_system);
static sys_var_const    sys_lower_case_table_names(&vars,
                                                   "lower_case_table_names",
                                                   OPT_GLOBAL, SHOW_INT,
                                                   (uchar*)
                                                   &lower_case_table_names);
387
static sys_var_thd_ulong_session_readonly sys_max_allowed_packet(&vars, "max_allowed_packet",
unknown's avatar
unknown committed
388
					       &SV::max_allowed_packet);
389 390
static sys_var_ulonglong_ptr sys_max_binlog_cache_size(&vars, "max_binlog_cache_size",
                                                       &max_binlog_cache_size);
unknown's avatar
unknown committed
391
static sys_var_long_ptr	sys_max_binlog_size(&vars, "max_binlog_size",
392 393
					    &max_binlog_size,
                                            fix_max_binlog_size);
unknown's avatar
unknown committed
394
static sys_var_long_ptr	sys_max_connections(&vars, "max_connections",
395 396
					    &max_connections,
                                            fix_max_connections);
unknown's avatar
unknown committed
397
static sys_var_long_ptr	sys_max_connect_errors(&vars, "max_connect_errors",
unknown's avatar
unknown committed
398
					       &max_connect_errors);
unknown's avatar
unknown committed
399
static sys_var_thd_ulong       sys_max_insert_delayed_threads(&vars, "max_insert_delayed_threads",
400 401 402
						       &SV::max_insert_delayed_threads,
                                                       check_max_delayed_threads,
                                                       fix_max_connections);
unknown's avatar
unknown committed
403
static sys_var_thd_ulong	sys_max_delayed_threads(&vars, "max_delayed_threads",
404
						&SV::max_insert_delayed_threads,
405 406
                                                check_max_delayed_threads,
                                                fix_max_connections);
unknown's avatar
unknown committed
407
static sys_var_thd_ulong	sys_max_error_count(&vars, "max_error_count",
408
					    &SV::max_error_count);
unknown's avatar
unknown committed
409
static sys_var_thd_ulonglong	sys_max_heap_table_size(&vars, "max_heap_table_size",
unknown's avatar
unknown committed
410
						&SV::max_heap_table_size);
411 412 413 414
static sys_var_thd_ulong sys_pseudo_thread_id(&vars, "pseudo_thread_id",
                                              &SV::pseudo_thread_id,
                                              check_pseudo_thread_id, 0,
                                              sys_var::SESSION_VARIABLE_IN_BINLOG);
unknown's avatar
unknown committed
415
static sys_var_thd_ha_rows	sys_max_join_size(&vars, "max_join_size",
unknown's avatar
unknown committed
416 417
					  &SV::max_join_size,
					  fix_max_join_size);
unknown's avatar
unknown committed
418
static sys_var_thd_ulong	sys_max_seeks_for_key(&vars, "max_seeks_for_key",
419
					      &SV::max_seeks_for_key);
unknown's avatar
unknown committed
420
static sys_var_thd_ulong   sys_max_length_for_sort_data(&vars, "max_length_for_sort_data",
421
                                                 &SV::max_length_for_sort_data);
unknown's avatar
unknown committed
422
#ifndef TO_BE_DELETED	/* Alias for max_join_size */
unknown's avatar
unknown committed
423
static sys_var_thd_ha_rows	sys_sql_max_join_size(&vars, "sql_max_join_size",
unknown's avatar
unknown committed
424 425 426
					      &SV::max_join_size,
					      fix_max_join_size);
#endif
427
static sys_var_long_ptr_global
unknown's avatar
unknown committed
428
sys_max_prepared_stmt_count(&vars, "max_prepared_stmt_count",
429 430
                            &max_prepared_stmt_count,
                            &LOCK_prepared_stmt_count);
unknown's avatar
unknown committed
431
static sys_var_long_ptr	sys_max_relay_log_size(&vars, "max_relay_log_size",
432 433
                                               &max_relay_log_size,
                                               fix_max_relay_log_size);
unknown's avatar
unknown committed
434
static sys_var_thd_ulong	sys_max_sort_length(&vars, "max_sort_length",
unknown's avatar
unknown committed
435
					    &SV::max_sort_length);
unknown's avatar
unknown committed
436
static sys_var_thd_ulong	sys_max_sp_recursion_depth(&vars, "max_sp_recursion_depth",
437
                                                   &SV::max_sp_recursion_depth);
unknown's avatar
unknown committed
438 439
static sys_var_max_user_conn   sys_max_user_connections(&vars, "max_user_connections");
static sys_var_thd_ulong	sys_max_tmp_tables(&vars, "max_tmp_tables",
unknown's avatar
unknown committed
440
					   &SV::max_tmp_tables);
unknown's avatar
unknown committed
441
static sys_var_long_ptr	sys_max_write_lock_count(&vars, "max_write_lock_count",
unknown's avatar
unknown committed
442
						 &max_write_lock_count);
443 444
static sys_var_thd_ulong       sys_min_examined_row_limit(&vars, "min_examined_row_limit",
                                                          &SV::min_examined_row_limit);
unknown's avatar
unknown committed
445
static sys_var_thd_ulong       sys_multi_range_count(&vars, "multi_range_count",
unknown's avatar
unknown committed
446
                                              &SV::multi_range_count);
unknown's avatar
unknown committed
447
static sys_var_long_ptr	sys_myisam_data_pointer_size(&vars, "myisam_data_pointer_size",
unknown's avatar
unknown committed
448
                                                    &myisam_data_pointer_size);
unknown's avatar
unknown committed
449
static sys_var_thd_ulonglong	sys_myisam_max_sort_file_size(&vars, "myisam_max_sort_file_size", &SV::myisam_max_sort_file_size, fix_myisam_max_sort_file_size, 1);
450 451 452 453
static sys_var_const sys_myisam_recover_options(&vars, "myisam_recover_options",
                                                OPT_GLOBAL, SHOW_CHAR_PTR,
                                                (uchar*)
                                                &myisam_recover_options_str);
unknown's avatar
unknown committed
454 455
static sys_var_thd_ulong       sys_myisam_repair_threads(&vars, "myisam_repair_threads", &SV::myisam_repair_threads);
static sys_var_thd_ulong	sys_myisam_sort_buffer_size(&vars, "myisam_sort_buffer_size", &SV::myisam_sort_buff_size);
unknown's avatar
unknown committed
456
static sys_var_bool_ptr	sys_myisam_use_mmap(&vars, "myisam_use_mmap",
unknown's avatar
unknown committed
457
                                            &opt_myisam_use_mmap);
458

unknown's avatar
unknown committed
459
static sys_var_thd_enum         sys_myisam_stats_method(&vars, "myisam_stats_method",
460 461 462 463
                                                &SV::myisam_stats_method,
                                                &myisam_stats_method_typelib,
                                                NULL);

464 465 466 467 468 469 470
#ifdef __NT__
/* purecov: begin inspected */
static sys_var_const            sys_named_pipe(&vars, "named_pipe",
                                               OPT_GLOBAL, SHOW_MY_BOOL,
                                               (uchar*) &opt_enable_named_pipe);
/* purecov: end */
#endif
471
static sys_var_thd_ulong_session_readonly sys_net_buffer_length(&vars, "net_buffer_length",
unknown's avatar
unknown committed
472
					      &SV::net_buffer_length);
unknown's avatar
unknown committed
473
static sys_var_thd_ulong	sys_net_read_timeout(&vars, "net_read_timeout",
unknown's avatar
unknown committed
474
					     &SV::net_read_timeout,
475
					     0, fix_net_read_timeout);
unknown's avatar
unknown committed
476
static sys_var_thd_ulong	sys_net_write_timeout(&vars, "net_write_timeout",
unknown's avatar
unknown committed
477
					      &SV::net_write_timeout,
478
					      0, fix_net_write_timeout);
unknown's avatar
unknown committed
479
static sys_var_thd_ulong	sys_net_retry_count(&vars, "net_retry_count",
480
					    &SV::net_retry_count,
481
					    0, fix_net_retry_count);
unknown's avatar
unknown committed
482
static sys_var_thd_bool	sys_new_mode(&vars, "new", &SV::new_mode);
unknown's avatar
unknown committed
483
static sys_var_bool_ptr_readonly sys_old_mode(&vars, "old",
unknown's avatar
unknown committed
484
                                       &global_system_variables.old_mode);
unknown's avatar
unknown committed
485 486 487 488
/* these two cannot be static */
sys_var_thd_bool                sys_old_alter_table(&vars, "old_alter_table",
                                            &SV::old_alter_table);
sys_var_thd_bool                sys_old_passwords(&vars, "old_passwords", &SV::old_passwords);
489 490 491 492
static sys_var_const            sys_open_files_limit(&vars, "open_files_limit",
                                                     OPT_GLOBAL, SHOW_LONG,
                                                     (uchar*)
                                                     &open_files_limit);
unknown's avatar
unknown committed
493
static sys_var_thd_ulong        sys_optimizer_prune_level(&vars, "optimizer_prune_level",
494
                                                  &SV::optimizer_prune_level);
unknown's avatar
unknown committed
495
static sys_var_thd_ulong        sys_optimizer_search_depth(&vars, "optimizer_search_depth",
496
                                                   &SV::optimizer_search_depth);
497 498
static sys_var_thd_optimizer_switch   sys_optimizer_switch(&vars, "optimizer_switch",
                                     &SV::optimizer_switch);
499 500 501
static sys_var_const            sys_pid_file(&vars, "pid_file",
                                             OPT_GLOBAL, SHOW_CHAR,
                                             (uchar*) pidfile_name);
502
static sys_var_const_os         sys_plugin_dir(&vars, "plugin_dir",
503 504 505 506 507
                                               OPT_GLOBAL, SHOW_CHAR,
                                               (uchar*) opt_plugin_dir);
static sys_var_const            sys_port(&vars, "port",
                                         OPT_GLOBAL, SHOW_INT,
                                         (uchar*) &mysqld_port);
unknown's avatar
unknown committed
508
static sys_var_thd_ulong        sys_preload_buff_size(&vars, "preload_buffer_size",
unknown's avatar
unknown committed
509
                                              &SV::preload_buff_size);
510 511 512 513
static sys_var_const            sys_protocol_version(&vars, "protocol_version",
                                                     OPT_GLOBAL, SHOW_INT,
                                                     (uchar*)
                                                     &protocol_version);
unknown's avatar
unknown committed
514
static sys_var_thd_ulong	sys_read_buff_size(&vars, "read_buffer_size",
unknown's avatar
unknown committed
515
					   &SV::read_buff_size);
unknown's avatar
unknown committed
516
static sys_var_opt_readonly	sys_readonly(&vars, "read_only", &opt_readonly);
517 518 519
static sys_var_bool_ptr	        sys_userstat(&vars, "userstat",
                                             &opt_userstat_running);

unknown's avatar
unknown committed
520
static sys_var_thd_ulong	sys_read_rnd_buff_size(&vars, "read_rnd_buffer_size",
unknown's avatar
unknown committed
521
					       &SV::read_rnd_buff_size);
unknown's avatar
unknown committed
522
static sys_var_thd_ulong	sys_div_precincrement(&vars, "div_precision_increment",
unknown's avatar
unknown committed
523
                                              &SV::div_precincrement);
unknown's avatar
unknown committed
524
static sys_var_long_ptr	sys_rpl_recovery_rank(&vars, "rpl_recovery_rank",
unknown's avatar
unknown committed
525
					      &rpl_recovery_rank);
unknown's avatar
unknown committed
526
static sys_var_long_ptr	sys_query_cache_size(&vars, "query_cache_size",
unknown's avatar
unknown committed
527 528
					     &query_cache_size,
					     fix_query_cache_size);
529

unknown's avatar
unknown committed
530
static sys_var_thd_ulong	sys_range_alloc_block_size(&vars, "range_alloc_block_size",
531
						   &SV::range_alloc_block_size);
unknown's avatar
unknown committed
532
static sys_var_thd_ulong	sys_query_alloc_block_size(&vars, "query_alloc_block_size",
533 534
						   &SV::query_alloc_block_size,
						   0, fix_thd_mem_root);
unknown's avatar
unknown committed
535
static sys_var_thd_ulong	sys_query_prealloc_size(&vars, "query_prealloc_size",
536 537
						&SV::query_prealloc_size,
						0, fix_thd_mem_root);
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
#ifdef HAVE_SMEM
/* purecov: begin tested */
static sys_var_const    sys_shared_memory(&vars, "shared_memory",
                                          OPT_GLOBAL, SHOW_MY_BOOL,
                                          (uchar*)
                                          &opt_enable_shared_memory);
static sys_var_const    sys_shared_memory_base_name(&vars,
                                                    "shared_memory_base_name",
                                                    OPT_GLOBAL, SHOW_CHAR_PTR,
                                                    (uchar*)
                                                    &shared_memory_base_name);
/* purecov: end */
#endif
static sys_var_const    sys_skip_external_locking(&vars,
                                                  "skip_external_locking",
                                                  OPT_GLOBAL, SHOW_MY_BOOL,
                                                  (uchar*)
                                                  &my_disable_locking);
static sys_var_const    sys_skip_networking(&vars, "skip_networking",
                                            OPT_GLOBAL, SHOW_BOOL,
                                            (uchar*) &opt_disable_networking);
static sys_var_const    sys_skip_show_database(&vars, "skip_show_database",
                                            OPT_GLOBAL, SHOW_BOOL,
                                            (uchar*) &opt_skip_show_db);
562

563 564 565
static sys_var_const    sys_socket(&vars, "socket",
                                   OPT_GLOBAL, SHOW_CHAR_PTR,
                                   (uchar*) &mysqld_unix_port);
566

567 568 569 570 571 572 573 574 575 576
#ifdef HAVE_THR_SETCONCURRENCY
/* purecov: begin tested */
static sys_var_const    sys_thread_concurrency(&vars, "thread_concurrency",
                                               OPT_GLOBAL, SHOW_LONG,
                                               (uchar*) &concurrency);
/* purecov: end */
#endif
static sys_var_const    sys_thread_stack(&vars, "thread_stack",
                                         OPT_GLOBAL, SHOW_LONG,
                                         (uchar*) &my_thread_stack_size);
577
static sys_var_readonly_os      sys_tmpdir(&vars, "tmpdir", OPT_GLOBAL, SHOW_CHAR, get_tmpdir);
unknown's avatar
unknown committed
578
static sys_var_thd_ulong	sys_trans_alloc_block_size(&vars, "transaction_alloc_block_size",
579 580
						   &SV::trans_alloc_block_size,
						   0, fix_trans_mem_root);
unknown's avatar
unknown committed
581
static sys_var_thd_ulong	sys_trans_prealloc_size(&vars, "transaction_prealloc_size",
582 583
						&SV::trans_prealloc_size,
						0, fix_trans_mem_root);
unknown's avatar
unknown committed
584 585 586 587
sys_var_enum_const        sys_thread_handling(&vars, "thread_handling",
                                              &SV::thread_handling,
                                              &thread_handling_typelib,
                                              NULL);
588

unknown's avatar
unknown committed
589
#ifdef HAVE_QUERY_CACHE
unknown's avatar
unknown committed
590
static sys_var_long_ptr	sys_query_cache_limit(&vars, "query_cache_limit",
unknown's avatar
unknown committed
591
					      &query_cache.query_cache_limit);
unknown's avatar
unknown committed
592
static sys_var_long_ptr        sys_query_cache_min_res_unit(&vars, "query_cache_min_res_unit",
593 594
						     &query_cache_min_res_unit,
						     fix_query_cache_min_res_unit);
unknown's avatar
unknown committed
595
static sys_var_thd_enum	sys_query_cache_type(&vars, "query_cache_type",
unknown's avatar
unknown committed
596 597
					     &SV::query_cache_type,
					     &query_cache_type_typelib);
unknown's avatar
unknown committed
598 599
static sys_var_thd_bool
sys_query_cache_wlock_invalidate(&vars, "query_cache_wlock_invalidate",
600
				 &SV::query_cache_wlock_invalidate);
unknown's avatar
unknown committed
601
#endif /* HAVE_QUERY_CACHE */
unknown's avatar
unknown committed
602
static sys_var_bool_ptr	sys_secure_auth(&vars, "secure_auth", &opt_secure_auth);
603
static sys_var_const_str_ptr sys_secure_file_priv(&vars, "secure_file_priv",
604
                                             &opt_secure_file_priv);
unknown's avatar
unknown committed
605 606
static sys_var_long_ptr	sys_server_id(&vars, "server_id", &server_id, fix_server_id);
static sys_var_bool_ptr	sys_slave_compressed_protocol(&vars, "slave_compressed_protocol",
607
						      &opt_slave_compressed_protocol);
608 609 610 611 612
static sys_var_set_slave_mode slave_exec_mode(&vars,
                                              "slave_exec_mode",
                                              &slave_exec_mode_options,
                                              &slave_exec_mode_typelib,
                                              0);
unknown's avatar
unknown committed
613
static sys_var_long_ptr	sys_slow_launch_time(&vars, "slow_launch_time",
unknown's avatar
unknown committed
614
					     &slow_launch_time);
unknown's avatar
unknown committed
615
static sys_var_thd_ulong	sys_sort_buffer(&vars, "sort_buffer_size",
unknown's avatar
unknown committed
616
					&SV::sortbuff_size);
617 618 619 620 621 622
/*
  sql_mode should *not* have binlog_mode=SESSION_VARIABLE_IN_BINLOG:
  even though it is written to the binlog, the slave ignores the
  MODE_NO_DIR_IN_CREATE variable, so slave's value differs from
  master's (see log_event.cc: Query_log_event::do_apply_event()).
*/
unknown's avatar
unknown committed
623
static sys_var_thd_sql_mode    sys_sql_mode(&vars, "sql_mode",
624
                                            &SV::sql_mode);
625 626 627
#ifdef HAVE_OPENSSL
extern char *opt_ssl_ca, *opt_ssl_capath, *opt_ssl_cert, *opt_ssl_cipher,
            *opt_ssl_key;
628 629 630 631 632
static sys_var_const_os_str_ptr	sys_ssl_ca(&vars, "ssl_ca", &opt_ssl_ca);
static sys_var_const_os_str_ptr	sys_ssl_capath(&vars, "ssl_capath", &opt_ssl_capath);
static sys_var_const_os_str_ptr	sys_ssl_cert(&vars, "ssl_cert", &opt_ssl_cert);
static sys_var_const_os_str_ptr	sys_ssl_cipher(&vars, "ssl_cipher", &opt_ssl_cipher);
static sys_var_const_os_str_ptr	sys_ssl_key(&vars, "ssl_key", &opt_ssl_key);
633
#else
634 635 636 637 638
static sys_var_const_os_str	sys_ssl_ca(&vars, "ssl_ca", NULL);
static sys_var_const_os_str	sys_ssl_capath(&vars, "ssl_capath", NULL);
static sys_var_const_os_str	sys_ssl_cert(&vars, "ssl_cert", NULL);
static sys_var_const_os_str	sys_ssl_cipher(&vars, "ssl_cipher", NULL);
static sys_var_const_os_str	sys_ssl_key(&vars, "ssl_key", NULL);
639
#endif
unknown's avatar
unknown committed
640 641
static sys_var_thd_enum
sys_updatable_views_with_limit(&vars, "updatable_views_with_limit",
642 643
                               &SV::updatable_views_with_limit,
                               &updatable_views_with_limit_typelib);
unknown's avatar
VIEW  
unknown committed
644

unknown's avatar
unknown committed
645 646 647 648 649 650
static sys_var_thd_table_type  sys_table_type(&vars, "table_type",
				       &SV::table_plugin);
static sys_var_thd_storage_engine sys_storage_engine(&vars, "storage_engine",
				       &SV::table_plugin);
static sys_var_bool_ptr	sys_sync_frm(&vars, "sync_frm", &opt_sync_frm);
static sys_var_const_str	sys_system_time_zone(&vars, "system_time_zone",
651
                                             system_time_zone);
unknown's avatar
unknown committed
652
static sys_var_long_ptr	sys_table_def_size(&vars, "table_definition_cache",
unknown's avatar
unknown committed
653
                                           &table_def_size);
unknown's avatar
unknown committed
654
static sys_var_long_ptr	sys_table_cache_size(&vars, "table_open_cache",
unknown's avatar
unknown committed
655
					     &table_cache_size);
unknown's avatar
unknown committed
656
static sys_var_long_ptr	sys_table_lock_wait_timeout(&vars, "table_lock_wait_timeout",
657
                                                    &table_lock_wait_timeout);
658 659 660 661 662 663

#if defined(ENABLED_DEBUG_SYNC)
/* Debug Sync Facility. Implemented in debug_sync.cc. */
static sys_var_debug_sync sys_debug_sync(&vars, "debug_sync");
#endif /* defined(ENABLED_DEBUG_SYNC) */

unknown's avatar
unknown committed
664
static sys_var_long_ptr	sys_thread_cache_size(&vars, "thread_cache_size",
unknown's avatar
unknown committed
665
					      &thread_cache_size);
unknown's avatar
unknown committed
666
#if HAVE_POOL_OF_THREADS == 1
667 668
static sys_var_long_ptr sys_thread_pool_size(&vars, "thread_pool_size",
                                             &thread_pool_size);
unknown's avatar
unknown committed
669
#endif
unknown's avatar
unknown committed
670
static sys_var_thd_enum	sys_tx_isolation(&vars, "tx_isolation",
unknown's avatar
unknown committed
671 672
					 &SV::tx_isolation,
					 &tx_isolation_typelib,
673 674
					 fix_tx_isolation,
					 check_tx_isolation);
unknown's avatar
unknown committed
675
static sys_var_thd_ulonglong	sys_tmp_table_size(&vars, "tmp_table_size",
unknown's avatar
unknown committed
676
					   &SV::tmp_table_size);
unknown's avatar
unknown committed
677
static sys_var_bool_ptr  sys_timed_mutexes(&vars, "timed_mutexes",
unknown's avatar
unknown committed
678
                                    &timed_mutexes);
unknown's avatar
unknown committed
679 680
static sys_var_const_str	sys_version(&vars, "version", server_version);
static sys_var_const_str	sys_version_comment(&vars, "version_comment",
681
                                            MYSQL_COMPILATION_COMMENT);
unknown's avatar
unknown committed
682
static sys_var_const_str	sys_version_compile_machine(&vars, "version_compile_machine",
683
                                                    MACHINE_TYPE);
unknown's avatar
unknown committed
684
static sys_var_const_str	sys_version_compile_os(&vars, "version_compile_os",
685
                                               SYSTEM_TYPE);
unknown's avatar
unknown committed
686
static sys_var_thd_ulong	sys_net_wait_timeout(&vars, "wait_timeout",
unknown's avatar
unknown committed
687
					     &SV::net_wait_timeout);
unknown's avatar
unknown committed
688

unknown's avatar
unknown committed
689
/* Condition pushdown to storage engine */
unknown's avatar
unknown committed
690 691
static sys_var_thd_bool
sys_engine_condition_pushdown(&vars, "engine_condition_pushdown",
unknown's avatar
unknown committed
692 693
			      &SV::engine_condition_pushdown);

694
#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
695
/* ndb thread specific variable settings */
unknown's avatar
unknown committed
696 697
static sys_var_thd_ulong
sys_ndb_autoincrement_prefetch_sz(&vars, "ndb_autoincrement_prefetch_sz",
698
				  &SV::ndb_autoincrement_prefetch_sz);
unknown's avatar
unknown committed
699 700
static sys_var_thd_bool
sys_ndb_force_send(&vars, "ndb_force_send", &SV::ndb_force_send);
unknown's avatar
unknown committed
701
#ifdef HAVE_NDB_BINLOG
unknown's avatar
unknown committed
702 703
static sys_var_long_ptr
sys_ndb_report_thresh_binlog_epoch_slip(&vars, "ndb_report_thresh_binlog_epoch_slip",
unknown's avatar
unknown committed
704
                                        &ndb_report_thresh_binlog_epoch_slip);
unknown's avatar
unknown committed
705 706
static sys_var_long_ptr
sys_ndb_report_thresh_binlog_mem_usage(&vars, "ndb_report_thresh_binlog_mem_usage",
unknown's avatar
unknown committed
707 708
                                       &ndb_report_thresh_binlog_mem_usage);
#endif
unknown's avatar
unknown committed
709 710 711 712 713 714
static sys_var_thd_bool
sys_ndb_use_exact_count(&vars, "ndb_use_exact_count", &SV::ndb_use_exact_count);
static sys_var_thd_bool
sys_ndb_use_transactions(&vars, "ndb_use_transactions", &SV::ndb_use_transactions);
static sys_var_long_ptr
sys_ndb_cache_check_time(&vars, "ndb_cache_check_time", &ndb_cache_check_time);
715 716
static sys_var_const_str
sys_ndb_connectstring(&vars, "ndb_connectstring", opt_ndb_constrbuf);
unknown's avatar
unknown committed
717 718
static sys_var_thd_bool
sys_ndb_index_stat_enable(&vars, "ndb_index_stat_enable",
719
                          &SV::ndb_index_stat_enable);
unknown's avatar
unknown committed
720 721
static sys_var_thd_ulong
sys_ndb_index_stat_cache_entries(&vars, "ndb_index_stat_cache_entries",
722
                                 &SV::ndb_index_stat_cache_entries);
unknown's avatar
unknown committed
723 724
static sys_var_thd_ulong
sys_ndb_index_stat_update_freq(&vars, "ndb_index_stat_update_freq",
725
                               &SV::ndb_index_stat_update_freq);
unknown's avatar
unknown committed
726 727 728 729
static sys_var_long_ptr
sys_ndb_extra_logging(&vars, "ndb_extra_logging", &ndb_extra_logging);
static sys_var_thd_bool
sys_ndb_use_copying_alter_table(&vars, "ndb_use_copying_alter_table", &SV::ndb_use_copying_alter_table);
730
#endif //WITH_NDBCLUSTER_STORAGE_ENGINE
731 732 733

/* Time/date/datetime formats */

unknown's avatar
unknown committed
734
static sys_var_thd_date_time_format sys_time_format(&vars, "time_format",
735
					     &SV::time_format,
736
					     MYSQL_TIMESTAMP_TIME);
unknown's avatar
unknown committed
737
static sys_var_thd_date_time_format sys_date_format(&vars, "date_format",
738
					     &SV::date_format,
739
					     MYSQL_TIMESTAMP_DATE);
unknown's avatar
unknown committed
740
static sys_var_thd_date_time_format sys_datetime_format(&vars, "datetime_format",
741
						 &SV::datetime_format,
742
						 MYSQL_TIMESTAMP_DATETIME);
743 744

/* Variables that are bits in THD */
unknown's avatar
unknown committed
745

unknown's avatar
unknown committed
746
sys_var_thd_bit sys_autocommit(&vars, "autocommit", 0,
747 748 749
                               set_option_autocommit,
                               OPTION_NOT_AUTOCOMMIT,
                               1);
unknown's avatar
unknown committed
750
static sys_var_thd_bit	sys_big_tables(&vars, "big_tables", 0,
unknown's avatar
unknown committed
751 752 753
				       set_option_bit,
				       OPTION_BIG_TABLES);
#ifndef TO_BE_DELETED	/* Alias for big_tables */
unknown's avatar
unknown committed
754
static sys_var_thd_bit	sys_sql_big_tables(&vars, "sql_big_tables", 0,
unknown's avatar
unknown committed
755 756 757
					   set_option_bit,
					   OPTION_BIG_TABLES);
#endif
unknown's avatar
unknown committed
758
static sys_var_thd_bit	sys_big_selects(&vars, "sql_big_selects", 0,
unknown's avatar
unknown committed
759
					set_option_bit,
760
					OPTION_BIG_SELECTS);
unknown's avatar
unknown committed
761
static sys_var_thd_bit	sys_log_off(&vars, "sql_log_off",
762
				    check_log_update,
unknown's avatar
unknown committed
763 764
				    set_option_bit,
				    OPTION_LOG_OFF);
unknown's avatar
unknown committed
765
static sys_var_thd_bit	sys_log_update(&vars, "sql_log_update",
766
                                       check_log_update,
unknown's avatar
unknown committed
767
				       set_log_update,
768
				       OPTION_BIN_LOG);
unknown's avatar
unknown committed
769
static sys_var_thd_bit	sys_log_binlog(&vars, "sql_log_bin",
770
                                       check_log_update,
771
                                       set_option_log_bin_bit,
772
				       OPTION_BIN_LOG);
unknown's avatar
unknown committed
773
static sys_var_thd_bit	sys_sql_warnings(&vars, "sql_warnings", 0,
unknown's avatar
unknown committed
774 775
					 set_option_bit,
					 OPTION_WARNINGS);
unknown's avatar
unknown committed
776
static sys_var_thd_bit	sys_sql_notes(&vars, "sql_notes", 0,
777
					 set_option_bit,
778
					 OPTION_SQL_NOTES);
unknown's avatar
unknown committed
779
static sys_var_thd_bit	sys_auto_is_null(&vars, "sql_auto_is_null", 0,
unknown's avatar
unknown committed
780
					 set_option_bit,
781 782
                                         OPTION_AUTO_IS_NULL, 0,
                                         sys_var::SESSION_VARIABLE_IN_BINLOG);
unknown's avatar
unknown committed
783
static sys_var_thd_bit	sys_safe_updates(&vars, "sql_safe_updates", 0,
unknown's avatar
unknown committed
784 785
					 set_option_bit,
					 OPTION_SAFE_UPDATES);
unknown's avatar
unknown committed
786
static sys_var_thd_bit	sys_buffer_results(&vars, "sql_buffer_result", 0,
unknown's avatar
unknown committed
787 788
					   set_option_bit,
					   OPTION_BUFFER_RESULT);
unknown's avatar
unknown committed
789
static sys_var_thd_bit	sys_quote_show_create(&vars, "sql_quote_show_create", 0,
unknown's avatar
unknown committed
790 791
					      set_option_bit,
					      OPTION_QUOTE_SHOW_CREATE);
unknown's avatar
unknown committed
792
static sys_var_thd_bit	sys_foreign_key_checks(&vars, "foreign_key_checks", 0,
793 794
					       set_option_bit,
					       OPTION_NO_FOREIGN_KEY_CHECKS,
795
                                               1, sys_var::SESSION_VARIABLE_IN_BINLOG);
unknown's avatar
unknown committed
796
static sys_var_thd_bit	sys_unique_checks(&vars, "unique_checks", 0,
797 798
					  set_option_bit,
					  OPTION_RELAXED_UNIQUE_CHECKS,
799 800
                                          1,
                                          sys_var::SESSION_VARIABLE_IN_BINLOG);
801
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
802 803
static sys_var_thd_bit  sys_profiling(&vars, "profiling", NULL, 
                                      set_option_bit,
804
                                      ulonglong(OPTION_PROFILING));
805
static sys_var_thd_ulong	sys_profiling_history_size(&vars, "profiling_history_size",
806 807
					      &SV::profiling_history_size);
#endif
808

unknown's avatar
unknown committed
809 810
/* Local state variables */

unknown's avatar
unknown committed
811
static sys_var_thd_ha_rows	sys_select_limit(&vars, "sql_select_limit",
unknown's avatar
unknown committed
812
						 &SV::select_limit);
813 814 815 816 817 818 819 820 821 822 823
static sys_var_timestamp sys_timestamp(&vars, "timestamp",
                                       sys_var::SESSION_VARIABLE_IN_BINLOG);
static sys_var_last_insert_id
sys_last_insert_id(&vars, "last_insert_id",
                   sys_var::SESSION_VARIABLE_IN_BINLOG);
/*
  identity is an alias for last_insert_id(), so that we are compatible
  with Sybase
*/
static sys_var_last_insert_id
sys_identity(&vars, "identity", sys_var::SESSION_VARIABLE_IN_BINLOG);
unknown's avatar
unknown committed
824

825 826
static sys_var_thd_lc_time_names
sys_lc_time_names(&vars, "lc_time_names", sys_var::SESSION_VARIABLE_IN_BINLOG);
unknown's avatar
unknown committed
827

828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847
/*
  insert_id should *not* be marked as written to the binlog (i.e., it
  should *not* have binlog_status==SESSION_VARIABLE_IN_BINLOG),
  because we want any statement that refers to insert_id explicitly to
  be unsafe.  (By "explicitly", we mean using @@session.insert_id,
  whereas insert_id is used "implicitly" when NULL value is inserted
  into an auto_increment column).

  We want statements referring explicitly to @@session.insert_id to be
  unsafe, because insert_id is modified internally by the slave sql
  thread when NULL values are inserted in an AUTO_INCREMENT column.
  This modification interfers with the value of the
  @@session.insert_id variable if @@session.insert_id is referred
  explicitly by an insert statement (as is seen by executing "SET
  @@session.insert_id=0; CREATE TABLE t (a INT, b INT KEY
  AUTO_INCREMENT); INSERT INTO t(a) VALUES (@@session.insert_id);" in
  statement-based logging mode: t will be different on master and
  slave).
*/
static sys_var_insert_id sys_insert_id(&vars, "insert_id");
unknown's avatar
unknown committed
848
static sys_var_readonly		sys_error_count(&vars, "error_count",
849 850 851
						OPT_SESSION,
						SHOW_LONG,
						get_error_count);
unknown's avatar
unknown committed
852
static sys_var_readonly		sys_warning_count(&vars, "warning_count",
853 854 855 856
						  OPT_SESSION,
						  SHOW_LONG,
						  get_warning_count);

857 858 859 860
static sys_var_rand_seed1 sys_rand_seed1(&vars, "rand_seed1",
                                         sys_var::SESSION_VARIABLE_IN_BINLOG);
static sys_var_rand_seed2 sys_rand_seed2(&vars, "rand_seed2",
                                         sys_var::SESSION_VARIABLE_IN_BINLOG);
unknown's avatar
unknown committed
861

unknown's avatar
unknown committed
862
static sys_var_thd_ulong        sys_default_week_format(&vars, "default_week_format",
863
					                &SV::default_week_format);
unknown's avatar
unknown committed
864

unknown's avatar
unknown committed
865
sys_var_thd_ulong               sys_group_concat_max_len(&vars, "group_concat_max_len",
unknown's avatar
unknown committed
866 867
                                                         &SV::group_concat_max_len);

868 869
sys_var_thd_time_zone sys_time_zone(&vars, "time_zone",
                                    sys_var::SESSION_VARIABLE_IN_BINLOG);
870

871 872 873 874 875 876 877 878 879 880 881 882 883 884
/* Unique variables for MariaDB */
static sys_var_thd_ulong  sys_log_slow_rate_limit(&vars,
                                                  "log_slow_rate_limit",
                                                  &SV::log_slow_rate_limit);
static sys_var_thd_set sys_log_slow_filter(&vars, "log_slow_filter",
                                           &SV::log_slow_filter,
                                           &log_slow_filter_typelib,
                                           QPLAN_VISIBLE_MASK,
                                           fix_sys_log_slow_filter);
static sys_var_thd_set sys_log_slow_verbosity(&vars,
                                              "log_slow_verbosity",
                                              &SV::log_slow_verbosity,
                                              &log_slow_verbosity_typelib);

885 886
/* Global read-only variable containing hostname */
static sys_var_const_str        sys_hostname(&vars, "hostname", glob_hostname);
887 888

#ifndef EMBEDDED_LIBRARY
889 890 891 892 893 894 895 896 897 898
static sys_var_const_str_ptr    sys_repl_report_host(&vars, "report_host", &report_host);
static sys_var_const_str_ptr    sys_repl_report_user(&vars, "report_user", &report_user);
static sys_var_const_str_ptr    sys_repl_report_password(&vars, "report_password", &report_password);

static uchar *slave_get_report_port(THD *thd)
{
  thd->sys_var_tmp.long_value= report_port;
  return (uchar*) &thd->sys_var_tmp.long_value;
}

unknown's avatar
unknown committed
899
static sys_var_readonly    sys_repl_report_port(&vars, "report_port", OPT_GLOBAL, SHOW_LONG, slave_get_report_port);
900

901
#endif
902

903
sys_var_thd_bool  sys_keep_files_on_create(&vars, "keep_files_on_create", 
unknown's avatar
unknown committed
904
                                           &SV::keep_files_on_create);
905 906
/* Read only variables */

unknown's avatar
unknown committed
907 908 909 910 911 912 913
static sys_var_have_variable sys_have_compress(&vars, "have_compress", &have_compress);
static sys_var_have_variable sys_have_crypt(&vars, "have_crypt", &have_crypt);
static sys_var_have_plugin sys_have_csv(&vars, "have_csv", C_STRING_WITH_LEN("csv"), MYSQL_STORAGE_ENGINE_PLUGIN);
static sys_var_have_variable sys_have_dlopen(&vars, "have_dynamic_loading", &have_dlopen);
static sys_var_have_variable sys_have_geometry(&vars, "have_geometry", &have_geometry);
static sys_var_have_plugin sys_have_innodb(&vars, "have_innodb", C_STRING_WITH_LEN("innodb"), MYSQL_STORAGE_ENGINE_PLUGIN);
static sys_var_have_plugin sys_have_ndbcluster(&vars, "have_ndbcluster", C_STRING_WITH_LEN("ndbcluster"), MYSQL_STORAGE_ENGINE_PLUGIN);
unknown's avatar
unknown committed
914 915
static sys_var_have_variable sys_have_openssl(&vars, "have_openssl", &have_ssl);
static sys_var_have_variable sys_have_ssl(&vars, "have_ssl", &have_ssl);
unknown's avatar
unknown committed
916 917
static sys_var_have_plugin sys_have_partition_db(&vars, "have_partitioning", C_STRING_WITH_LEN("partition"), MYSQL_STORAGE_ENGINE_PLUGIN);
static sys_var_have_variable sys_have_query_cache(&vars, "have_query_cache",
unknown's avatar
unknown committed
918
                                           &have_query_cache);
919
static sys_var_have_variable sys_have_community_features(&vars, "have_community_features", &have_community_features);
unknown's avatar
unknown committed
920 921
static sys_var_have_variable sys_have_rtree_keys(&vars, "have_rtree_keys", &have_rtree_keys);
static sys_var_have_variable sys_have_symlink(&vars, "have_symlink", &have_symlink);
922
/* Global read-only variable describing server license */
unknown's avatar
unknown committed
923
static sys_var_const_str	sys_license(&vars, "license", STRINGIFY_ARG(LICENSE));
924
/* Global variables which enable|disable logging */
unknown's avatar
unknown committed
925
static sys_var_log_state sys_var_general_log(&vars, "general_log", &opt_log,
926
                                      QUERY_LOG_GENERAL);
927 928 929
/* Synonym of "general_log" for consistency with SHOW VARIABLES output */
static sys_var_log_state sys_var_log(&vars, "log", &opt_log,
                                      QUERY_LOG_GENERAL);
unknown's avatar
unknown committed
930
static sys_var_log_state sys_var_slow_query_log(&vars, "slow_query_log", &opt_slow_log,
931
                                         QUERY_LOG_SLOW);
932 933 934
/* Synonym of "slow_query_log" for consistency with SHOW VARIABLES output */
static sys_var_log_state sys_var_log_slow(&vars, "log_slow_queries",
                                          &opt_slow_log, QUERY_LOG_SLOW);
unknown's avatar
unknown committed
935
sys_var_str sys_var_general_log_path(&vars, "general_log_file", sys_check_log_path,
936 937 938
				     sys_update_general_log_path,
				     sys_default_general_log_path,
				     opt_logname);
unknown's avatar
unknown committed
939
sys_var_str sys_var_slow_log_path(&vars, "slow_query_log_file", sys_check_log_path,
940 941 942
				  sys_update_slow_log_path, 
				  sys_default_slow_log_path,
				  opt_slow_logname);
unknown's avatar
unknown committed
943
static sys_var_log_output sys_var_log_output_state(&vars, "log_output", &log_output_options,
944 945
					    &log_output_typelib, 0);

946

947 948 949 950 951 952
bool sys_var::check(THD *thd, set_var *var)
{
  var->save_result.ulonglong_value= var->value->val_int();
  return 0;
}

953 954 955 956 957 958 959
bool sys_var_str::check(THD *thd, set_var *var)
{
  int res;
  if (!check_func)
    return 0;

  if ((res=(*check_func)(thd, var)) < 0)
960 961
    my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0),
             name, var->value->str_value.ptr());
962 963 964
  return res;
}

unknown's avatar
unknown committed
965 966 967 968
/*
  Functions to check and update variables
*/

unknown's avatar
unknown committed
969

970 971 972 973 974 975 976 977 978 979
/*
  Update variables 'init_connect, init_slave'.

  In case of 'DEFAULT' value
  (for example: 'set GLOBAL init_connect=DEFAULT')
  'var' parameter is NULL pointer.
*/

bool update_sys_var_str(sys_var_str *var_str, rw_lock_t *var_mutex,
			set_var *var)
unknown's avatar
unknown committed
980
{
981 982 983 984
  char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0);
  uint new_length= (var ? var->value->str_value.length() : 0);
  if (!old_value)
    old_value= (char*) "";
985
  if (!(res= my_strndup(old_value, new_length, MYF(0))))
986
    return 1;
unknown's avatar
unknown committed
987 988 989 990
  /*
    Replace the old value in such a way that the any thread using
    the value will work.
  */
991 992 993 994
  rw_wrlock(var_mutex);
  old_value= var_str->value;
  var_str->value= res;
  var_str->value_length= new_length;
995
  var_str->is_os_charset= FALSE;
996
  rw_unlock(var_mutex);
unknown's avatar
unknown committed
997 998 999 1000 1001
  my_free(old_value, MYF(MY_ALLOW_ZERO_PTR));
  return 0;
}


1002 1003 1004 1005 1006 1007
static bool sys_update_init_connect(THD *thd, set_var *var)
{
  return update_sys_var_str(&sys_init_connect, &LOCK_sys_init_connect, var);
}


unknown's avatar
unknown committed
1008 1009
static void sys_default_init_connect(THD* thd, enum_var_type type)
{
1010
  update_sys_var_str(&sys_init_connect, &LOCK_sys_init_connect, 0);
unknown's avatar
unknown committed
1011 1012 1013 1014 1015
}


static bool sys_update_init_slave(THD *thd, set_var *var)
{
1016
  return update_sys_var_str(&sys_init_slave, &LOCK_sys_init_slave, var);
unknown's avatar
unknown committed
1017 1018 1019 1020 1021
}


static void sys_default_init_slave(THD* thd, enum_var_type type)
{
1022
  update_sys_var_str(&sys_init_slave, &LOCK_sys_init_slave, 0);
unknown's avatar
unknown committed
1023 1024
}

1025 1026
static int sys_check_ftb_syntax(THD *thd,  set_var *var)
{
1027
  if (thd->security_ctx->master_access & SUPER_ACL)
1028
    return (ft_boolean_check_syntax_string((uchar*)
1029 1030
                                           var->value->str_value.c_ptr()) ?
            -1 : 0);
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041
  else
  {
    my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
    return 1;
  }
}

static bool sys_update_ftb_syntax(THD *thd, set_var * var)
{
  strmake(ft_boolean_syntax, var->value->str_value.c_ptr(),
	  sizeof(ft_boolean_syntax)-1);
1042 1043 1044 1045 1046

#ifdef HAVE_QUERY_CACHE
  query_cache.flush();
#endif /* HAVE_QUERY_CACHE */

1047 1048 1049 1050 1051
  return 0;
}

static void sys_default_ftb_syntax(THD *thd, enum_var_type type)
{
1052
  strmake(ft_boolean_syntax, def_ft_boolean_syntax,
1053 1054
	  sizeof(ft_boolean_syntax)-1);
}
unknown's avatar
unknown committed
1055

unknown's avatar
unknown committed
1056

unknown's avatar
unknown committed
1057
/**
unknown's avatar
unknown committed
1058
  If one sets the LOW_PRIORIY UPDATES flag, we also must change the
unknown's avatar
unknown committed
1059
  used lock type.
unknown's avatar
unknown committed
1060 1061 1062 1063
*/

static void fix_low_priority_updates(THD *thd, enum_var_type type)
{
1064 1065 1066 1067 1068
  if (type == OPT_GLOBAL)
    thr_upgraded_concurrent_insert_lock= 
      (global_system_variables.low_priority_updates ?
       TL_WRITE_LOW_PRIORITY : TL_WRITE);
  else
unknown's avatar
unknown committed
1069 1070 1071 1072 1073
    thd->update_lock_default= (thd->variables.low_priority_updates ?
			       TL_WRITE_LOW_PRIORITY : TL_WRITE);
}


1074 1075 1076 1077 1078 1079 1080
static void
fix_myisam_max_sort_file_size(THD *thd, enum_var_type type)
{
  myisam_max_temp_length=
    (my_off_t) global_system_variables.myisam_max_sort_file_size;
}

unknown's avatar
unknown committed
1081 1082
/**
  Set the OPTION_BIG_SELECTS flag if max_join_size == HA_POS_ERROR.
unknown's avatar
unknown committed
1083 1084 1085 1086 1087 1088
*/

static void fix_max_join_size(THD *thd, enum_var_type type)
{
  if (type != OPT_GLOBAL)
  {
1089
    if (thd->variables.max_join_size == HA_POS_ERROR)
unknown's avatar
unknown committed
1090 1091 1092 1093 1094
      thd->options|= OPTION_BIG_SELECTS;
    else
      thd->options&= ~OPTION_BIG_SELECTS;
  }
}
1095

unknown's avatar
unknown committed
1096

unknown's avatar
unknown committed
1097
/**
1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
  Can't change the 'next' tx_isolation while we are already in
  a transaction
*/
static int check_tx_isolation(THD *thd, set_var *var)
{
  if (var->type == OPT_DEFAULT && (thd->server_status & SERVER_STATUS_IN_TRANS))
  {
    my_error(ER_CANT_CHANGE_TX_ISOLATION, MYF(0));
    return 1;
  }
  return 0;
}

unknown's avatar
unknown committed
1111 1112
/*
  If one doesn't use the SESSION modifier, the isolation level
unknown's avatar
unknown committed
1113
  is only active for the next command.
unknown's avatar
unknown committed
1114 1115 1116 1117 1118 1119 1120 1121
*/
static void fix_tx_isolation(THD *thd, enum_var_type type)
{
  if (type == OPT_SESSION)
    thd->session_tx_isolation= ((enum_tx_isolation)
				thd->variables.tx_isolation);
}

1122 1123
static void fix_completion_type(THD *thd __attribute__((unused)),
				enum_var_type type __attribute__((unused))) {}
unknown's avatar
unknown committed
1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136

static int check_completion_type(THD *thd, set_var *var)
{
  longlong val= var->value->val_int();
  if (val < 0 || val > 2)
  {
    char buf[64];
    my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name, llstr(val, buf));
    return 1;
  }
  return 0;
}

unknown's avatar
unknown committed
1137 1138 1139 1140 1141

/*
  If we are changing the thread variable, we have to copy it to NET too
*/

unknown's avatar
SCRUM  
unknown committed
1142
#ifdef HAVE_REPLICATION
unknown's avatar
unknown committed
1143 1144 1145
static void fix_net_read_timeout(THD *thd, enum_var_type type)
{
  if (type != OPT_GLOBAL)
1146
    my_net_set_read_timeout(&thd->net, thd->variables.net_read_timeout);
unknown's avatar
unknown committed
1147 1148 1149 1150 1151 1152
}


static void fix_net_write_timeout(THD *thd, enum_var_type type)
{
  if (type != OPT_GLOBAL)
1153
    my_net_set_write_timeout(&thd->net, thd->variables.net_write_timeout);
unknown's avatar
unknown committed
1154 1155
}

1156 1157 1158 1159 1160
static void fix_net_retry_count(THD *thd, enum_var_type type)
{
  if (type != OPT_GLOBAL)
    thd->net.retry_count=thd->variables.net_retry_count;
}
unknown's avatar
SCRUM  
unknown committed
1161
#else /* HAVE_REPLICATION */
1162 1163
static void fix_net_read_timeout(THD *thd __attribute__((unused)),
				 enum_var_type type __attribute__((unused)))
1164
{}
1165 1166
static void fix_net_write_timeout(THD *thd __attribute__((unused)),
				  enum_var_type type __attribute__((unused)))
1167
{}
1168 1169
static void fix_net_retry_count(THD *thd __attribute__((unused)),
				enum_var_type type __attribute__((unused)))
1170
{}
unknown's avatar
SCRUM  
unknown committed
1171
#endif /* HAVE_REPLICATION */
1172

unknown's avatar
unknown committed
1173 1174 1175 1176

static void fix_query_cache_size(THD *thd, enum_var_type type)
{
#ifdef HAVE_QUERY_CACHE
1177 1178 1179 1180 1181 1182 1183 1184
  ulong new_cache_size= query_cache.resize(query_cache_size);

  /*
     Note: query_cache_size is a global variable reflecting the 
     requested cache size. See also query_cache_size_arg
  */

  if (query_cache_size != new_cache_size)
1185 1186
    push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
			ER_WARN_QC_RESIZE, ER(ER_WARN_QC_RESIZE),
1187 1188 1189
			query_cache_size, new_cache_size);
  
  query_cache_size= new_cache_size;
unknown's avatar
unknown committed
1190 1191 1192 1193
#endif
}


1194 1195 1196 1197 1198 1199 1200 1201 1202
#ifdef HAVE_QUERY_CACHE
static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type)
{
  query_cache_min_res_unit= 
    query_cache.set_min_res_unit(query_cache_min_res_unit);
}
#endif


1203
extern void fix_delay_key_write(THD *thd, enum_var_type type)
1204 1205 1206 1207
{
  switch ((enum_delay_key_write) delay_key_write_options) {
  case DELAY_KEY_WRITE_NONE:
    myisam_delay_key_write=0;
1208 1209 1210 1211
#ifdef WITH_MARIA_STORAGE_ENGINE
    maria_delay_key_write= 0;
#endif
    ha_open_options&= ~HA_OPEN_DELAY_KEY_WRITE;
1212 1213 1214
    break;
  case DELAY_KEY_WRITE_ON:
    myisam_delay_key_write=1;
1215 1216 1217 1218
#ifdef WITH_MARIA_STORAGE_ENGINE
    maria_delay_key_write= 1;
#endif
    ha_open_options&= ~HA_OPEN_DELAY_KEY_WRITE;
1219 1220 1221
    break;
  case DELAY_KEY_WRITE_ALL:
    myisam_delay_key_write=1;
1222 1223 1224
#ifdef WITH_MARIA_STORAGE_ENGINE
    maria_delay_key_write= 1;
#endif
1225 1226 1227 1228 1229
    ha_open_options|= HA_OPEN_DELAY_KEY_WRITE;
    break;
  }
}

1230 1231 1232 1233
bool sys_var_set::update(THD *thd, set_var *var)
{
  *value= var->save_result.ulong_value;
  return 0;
1234
}
1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301

uchar *sys_var_set::value_ptr(THD *thd, enum_var_type type,
                              LEX_STRING *base)
{
  char buff[256];
  String tmp(buff, sizeof(buff), &my_charset_latin1);
  ulong length;
  ulong val= *value;

  tmp.length(0);
  for (uint i= 0; val; val>>= 1, i++)
  {
    if (val & 1)
    {
      tmp.append(enum_names->type_names[i],
                 enum_names->type_lengths[i]);
      tmp.append(',');
    }
  }

  if ((length= tmp.length()))
    length--;
  return (uchar*) thd->strmake(tmp.ptr(), length);
}

void sys_var_set_slave_mode::set_default(THD *thd, enum_var_type type)
{
  slave_exec_mode_options= 0;
  bit_do_set(slave_exec_mode_options, SLAVE_EXEC_MODE_STRICT);
}

bool sys_var_set_slave_mode::check(THD *thd, set_var *var)
{
  bool rc=  sys_var_set::check(thd, var);
  if (!rc &&
      bit_is_set(var->save_result.ulong_value, SLAVE_EXEC_MODE_STRICT) == 1 &&
      bit_is_set(var->save_result.ulong_value, SLAVE_EXEC_MODE_IDEMPOTENT) == 1)
  {
    rc= true;
    my_error(ER_SLAVE_AMBIGOUS_EXEC_MODE, MYF(0), "");
  }
  return rc;
}

bool sys_var_set_slave_mode::update(THD *thd, set_var *var)
{
  bool rc;
  pthread_mutex_lock(&LOCK_global_system_variables);
  rc= sys_var_set::update(thd, var);
  pthread_mutex_unlock(&LOCK_global_system_variables);
  return rc;
}

void fix_slave_exec_mode(enum_var_type type)
{
  DBUG_ENTER("fix_slave_exec_mode");
  compile_time_assert(sizeof(slave_exec_mode_options) * CHAR_BIT
                      > SLAVE_EXEC_MODE_LAST_BIT - 1);
  if (bit_is_set(slave_exec_mode_options, SLAVE_EXEC_MODE_STRICT) == 1 &&
      bit_is_set(slave_exec_mode_options, SLAVE_EXEC_MODE_IDEMPOTENT) == 1)
  {
    sql_print_error("Ambiguous slave modes combination."
                    " STRICT will be used");
    bit_do_clear(slave_exec_mode_options, SLAVE_EXEC_MODE_IDEMPOTENT);
  }
  if (bit_is_set(slave_exec_mode_options, SLAVE_EXEC_MODE_IDEMPOTENT) == 0)
    bit_do_set(slave_exec_mode_options, SLAVE_EXEC_MODE_STRICT);
unknown's avatar
unknown committed
1302
  DBUG_VOID_RETURN;
1303
}
1304

Mats Kindahl's avatar
Mats Kindahl committed
1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319

bool sys_var_thd_binlog_format::check(THD *thd, set_var *var) {
  /*
    All variables that affect writing to binary log (either format or
    turning logging on and off) use the same checking. We call the
    superclass ::check function to assign the variable correctly, and
    then check the value.
   */
  bool result= sys_var_thd_enum::check(thd, var);
  if (!result)
    result= check_log_update(thd, var);
  return result;
}


1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332
bool sys_var_thd_binlog_format::is_readonly() const
{
  /*
    Under certain circumstances, the variable is read-only (unchangeable):
  */
  THD *thd= current_thd;
  /*
    If RBR and open temporary tables, their CREATE TABLE may not be in the
    binlog, so we can't toggle to SBR in this connection.
    The test below will also prevent SET GLOBAL, well it was not easy to test
    if global or not here.
    And this test will also prevent switching from RBR to RBR (a no-op which
    should not happen too often).
1333 1334 1335

    If we don't have row-based replication compiled in, the variable
    is always read-only.
1336 1337 1338 1339 1340 1341 1342 1343
  */
  if ((thd->variables.binlog_format == BINLOG_FORMAT_ROW) &&
      thd->temporary_tables)
  {
    my_error(ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR, MYF(0));
    return 1;
  }
  /*
unknown's avatar
unknown committed
1344
    if in a stored function/trigger, it's too late to change mode
1345
  */
unknown's avatar
unknown committed
1346
  if (thd->in_sub_stmt)
1347 1348
  {
    my_error(ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT, MYF(0));
unknown's avatar
unknown committed
1349
    return 1;
1350 1351 1352 1353
  }
  return sys_var_thd_enum::is_readonly();
}

unknown's avatar
unknown committed
1354

1355 1356 1357 1358 1359 1360
void fix_binlog_format_after_update(THD *thd, enum_var_type type)
{
  thd->reset_current_stmt_binlog_row_based();
}


1361
static void fix_max_binlog_size(THD *thd, enum_var_type type)
1362 1363 1364 1365 1366
{
  DBUG_ENTER("fix_max_binlog_size");
  DBUG_PRINT("info",("max_binlog_size=%lu max_relay_log_size=%lu",
                     max_binlog_size, max_relay_log_size));
  mysql_bin_log.set_max_size(max_binlog_size);
1367
#ifdef HAVE_REPLICATION
1368 1369
  if (!max_relay_log_size)
    active_mi->rli.relay_log.set_max_size(max_binlog_size);
unknown's avatar
unknown committed
1370
#endif
1371 1372 1373
  DBUG_VOID_RETURN;
}

1374
static void fix_max_relay_log_size(THD *thd, enum_var_type type)
1375 1376 1377 1378
{
  DBUG_ENTER("fix_max_relay_log_size");
  DBUG_PRINT("info",("max_binlog_size=%lu max_relay_log_size=%lu",
                     max_binlog_size, max_relay_log_size));
1379
#ifdef HAVE_REPLICATION
1380 1381
  active_mi->rli.relay_log.set_max_size(max_relay_log_size ?
                                        max_relay_log_size: max_binlog_size);
1382
#endif
1383 1384
  DBUG_VOID_RETURN;
}
1385

1386

1387 1388
static int check_max_delayed_threads(THD *thd, set_var *var)
{
unknown's avatar
unknown committed
1389
  longlong val= var->value->val_int();
1390
  if (var->type != OPT_GLOBAL && val != 0 &&
unknown's avatar
unknown committed
1391
      val != (longlong) global_system_variables.max_insert_delayed_threads)
1392 1393
  {
    char buf[64];
1394
    my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name, llstr(val, buf));
1395 1396 1397 1398 1399
    return 1;
  }
  return 0;
}

1400
static void fix_max_connections(THD *thd, enum_var_type type)
1401
{
1402
#ifndef EMBEDDED_LIBRARY
1403
  resize_thr_alarm(max_connections + extra_max_connections +
1404
		   global_system_variables.max_insert_delayed_threads + 10);
1405
#endif
1406 1407 1408 1409 1410 1411
}


static void fix_thd_mem_root(THD *thd, enum_var_type type)
{
  if (type != OPT_GLOBAL)
unknown's avatar
unknown committed
1412
    reset_root_defaults(thd->mem_root,
1413 1414 1415 1416 1417 1418 1419
                        thd->variables.query_alloc_block_size,
                        thd->variables.query_prealloc_size);
}


static void fix_trans_mem_root(THD *thd, enum_var_type type)
{
1420
#ifdef USING_TRANSACTIONS
1421 1422 1423 1424
  if (type != OPT_GLOBAL)
    reset_root_defaults(&thd->transaction.mem_root,
                        thd->variables.trans_alloc_block_size,
                        thd->variables.trans_prealloc_size);
1425
#endif
1426 1427
}

1428

1429 1430 1431
static void fix_server_id(THD *thd, enum_var_type type)
{
  server_id_supplied = 1;
1432
  thd->server_id= server_id;
1433
}
1434

1435

1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448
/**
  Throw warning (error in STRICT mode) if value for variable needed bounding.
  Only call from check(), not update(), because an error in update() would be
  bad mojo. Plug-in interface also uses this.

  @param thd      thread handle
  @param fixed    did we have to correct the value? (throw warn/err if so)
  @param unsignd  is value's type unsigned?
  @param name     variable's name
  @param val      variable's value

  @retval         TRUE on error, FALSE otherwise (warning or OK)
 */
1449 1450
bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd,
                          const char *name, longlong val)
1451
{
1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471
  if (fixed)
  {
    char buf[22];

    if (unsignd)
      ullstr((ulonglong) val, buf);
    else
      llstr(val, buf);

    if (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES)
    {
      my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buf);
      return TRUE;
    }

    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
                        ER_TRUNCATED_WRONG_VALUE,
                        ER(ER_TRUNCATED_WRONG_VALUE), name, buf);
  }
  return FALSE;
1472 1473
}

1474 1475 1476 1477

/**
  check an unsigned user-supplied value for a systemvariable against bounds.

1478 1479 1480 1481 1482 1483 1484 1485 1486 1487
  TODO: This is a wrapper function to call clipping from within an update()
        function.  Calling bounds from within update() is fair game in theory,
        but we can only send warnings from in there, not errors, and besides,
        it violates our model of separating check from update phase.
        To avoid breaking out of the server with an ASSERT() in strict mode,
        we pretend we're not in strict mode when we go through here. Bug#43233
        was opened to remind us to replace this kludge with The Right Thing,
        which of course is to do the check in the actual check phase, and then
        throw an error or warning accordingly.

1488
  @param thd             thread handle
1489
  @param num             the value to limit
1490
  @param option_limits   the bounds-record, or NULL if none
1491
 */
1492
static void bound_unsigned(THD *thd, ulonglong *num,
1493 1494
                              const struct my_option *option_limits)
{
1495
  if (option_limits)
1496 1497 1498
  {
    my_bool   fixed     = FALSE;
    ulonglong unadjusted= *num;
1499

1500
    *num= getopt_ull_limit_value(unadjusted, option_limits, &fixed);
1501

1502 1503 1504 1505 1506 1507 1508 1509
    if (fixed)
    {
      ulong ssm= thd->variables.sql_mode;
      thd->variables.sql_mode&= ~MODE_STRICT_ALL_TABLES;
      throw_bounds_warning(thd, fixed, TRUE, option_limits->name, unadjusted);
      thd->variables.sql_mode= ssm;
    }
  }
1510 1511
}

1512 1513 1514 1515

/**
  Get unsigned system-variable.
  Negative value does not wrap around, but becomes zero.
1516 1517 1518
  Check user-supplied value for a systemvariable against bounds.
  If we needed to adjust the value, throw a warning or error depending
  on SQL-mode.
1519

1520 1521 1522
  @param thd             thread handle
  @param var             the system-variable to get
  @param user_max        a limit given with --maximum-variable-name=... or 0
1523
  @param var_type        function will bound on systems where necessary.
1524

1525
  @retval                TRUE on error, FALSE otherwise (warning or OK)
1526
 */
1527
static bool get_unsigned(THD *thd, set_var *var, ulonglong user_max,
1528
                         ulong var_type)
1529
{
1530 1531 1532
  int                     warnings= 0;
  ulonglong               unadjusted;
  const struct my_option *limits= var->var->option_limits;
1533
  struct my_option        fallback;
1534 1535

  /* get_unsigned() */
1536 1537 1538 1539 1540 1541
  if (var->value->unsigned_flag)
    var->save_result.ulonglong_value= (ulonglong) var->value->val_int();
  else
  {
    longlong v= var->value->val_int();
    var->save_result.ulonglong_value= (ulonglong) ((v < 0) ? 0 : v);
1542
    if (v < 0)
1543 1544 1545 1546 1547
    {
      warnings++;
      if (throw_bounds_warning(thd, TRUE, FALSE, var->var->name, v))
        return TRUE;  /* warning was promoted to error, give up */
    }
1548 1549
  }

1550
  unadjusted= var->save_result.ulonglong_value;
1551

1552
  /* max, if any */
1553

1554 1555 1556
  if ((user_max > 0) && (unadjusted > user_max))
  {
    var->save_result.ulonglong_value= user_max;
1557

1558 1559 1560 1561
    if ((warnings == 0) && throw_bounds_warning(thd, TRUE, TRUE,
                                                var->var->name,
                                                (longlong) unadjusted))
      return TRUE;
1562

1563 1564 1565
    warnings++;
  }

1566 1567 1568 1569 1570 1571 1572
  /*
    if the sysvar doesn't have a proper bounds record but the check
    function would like bounding to ULONG where its size differs from
    that of ULONGLONG, we make up a bogus limits record here and let
    the usual suspects handle the actual limiting.
  */

1573
  if (!limits && var_type != GET_ULL)
1574 1575
  {
    bzero(&fallback, sizeof(fallback));
1576
    fallback.var_type= var_type;
1577 1578 1579
    limits= &fallback;
  }

1580 1581 1582 1583 1584
  /* fix_unsigned() */
  if (limits)
  {
    my_bool   fixed;

1585 1586
    var->save_result.ulonglong_value= getopt_ull_limit_value(var->save_result.
                                                             ulonglong_value,
1587
                                                             limits, &fixed);
1588

1589 1590
    if ((warnings == 0) && throw_bounds_warning(thd, fixed, TRUE,
                                                var->var->name,
1591 1592 1593 1594 1595
                                                (longlong) unadjusted))
      return TRUE;
  }

  return FALSE;
1596 1597
}

1598

1599
sys_var_long_ptr::
unknown's avatar
unknown committed
1600
sys_var_long_ptr(sys_var_chain *chain, const char *name_arg, ulong *value_ptr_arg,
1601
                 sys_after_update_func after_update_arg)
unknown's avatar
unknown committed
1602
  :sys_var_long_ptr_global(chain, name_arg, value_ptr_arg,
1603 1604 1605 1606 1607
                           &LOCK_global_system_variables, after_update_arg)
{}


bool sys_var_long_ptr_global::check(THD *thd, set_var *var)
unknown's avatar
unknown committed
1608
{
1609
  return get_unsigned(thd, var, 0, GET_ULONG);
unknown's avatar
unknown committed
1610
}
1611

1612
bool sys_var_long_ptr_global::update(THD *thd, set_var *var)
unknown's avatar
unknown committed
1613
{
1614
  pthread_mutex_lock(guard);
1615
  *value= (ulong) var->save_result.ulonglong_value;
1616
  pthread_mutex_unlock(guard);
unknown's avatar
unknown committed
1617 1618 1619 1620
  return 0;
}


1621
void sys_var_long_ptr_global::set_default(THD *thd, enum_var_type type)
unknown's avatar
unknown committed
1622
{
1623
  my_bool not_used;
1624
  pthread_mutex_lock(guard);
1625 1626
  *value= (ulong) getopt_ull_limit_value((ulong) option_limits->def_value,
                                         option_limits, &not_used);
1627
  pthread_mutex_unlock(guard);
unknown's avatar
unknown committed
1628 1629 1630
}


1631 1632
bool sys_var_ulonglong_ptr::update(THD *thd, set_var *var)
{
1633
  ulonglong tmp= var->save_result.ulonglong_value;
1634
  pthread_mutex_lock(&LOCK_global_system_variables);
1635
  bound_unsigned(thd, &tmp, option_limits);
1636
  *value= (ulonglong) tmp;
1637
  pthread_mutex_unlock(&LOCK_global_system_variables);
1638 1639 1640 1641 1642 1643
  return 0;
}


void sys_var_ulonglong_ptr::set_default(THD *thd, enum_var_type type)
{
1644
  my_bool not_used;
1645
  pthread_mutex_lock(&LOCK_global_system_variables);
1646 1647
  *value= getopt_ull_limit_value((ulonglong) option_limits->def_value,
                                 option_limits, &not_used);
1648
  pthread_mutex_unlock(&LOCK_global_system_variables);
1649 1650 1651
}


unknown's avatar
unknown committed
1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664
bool sys_var_bool_ptr::update(THD *thd, set_var *var)
{
  *value= (my_bool) var->save_result.ulong_value;
  return 0;
}


void sys_var_bool_ptr::set_default(THD *thd, enum_var_type type)
{
  *value= (my_bool) option_limits->def_value;
}


1665 1666 1667 1668 1669 1670 1671
bool sys_var_enum::update(THD *thd, set_var *var)
{
  *value= (uint) var->save_result.ulong_value;
  return 0;
}


1672
uchar *sys_var_enum::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
1673
{
1674
  return (uchar*) enum_names->type_names[*value];
1675 1676
}

1677 1678 1679 1680 1681 1682
uchar *sys_var_enum_const::value_ptr(THD *thd, enum_var_type type,
                                     LEX_STRING *base)
{
  return (uchar*) enum_names->type_names[global_system_variables.*offset];
}

1683 1684
bool sys_var_thd_ulong::check(THD *thd, set_var *var)
{
1685
  if (get_unsigned(thd, var, max_system_variables.*offset, GET_ULONG))
1686
    return TRUE;
Tatiana A. Nurnberg's avatar
Tatiana A. Nurnberg committed
1687
  DBUG_ASSERT(var->save_result.ulonglong_value <= ULONG_MAX);
1688
  return ((check_func && (*check_func)(thd, var)));
1689
}
1690

unknown's avatar
unknown committed
1691 1692 1693
bool sys_var_thd_ulong::update(THD *thd, set_var *var)
{
  if (var->type == OPT_GLOBAL)
1694
    global_system_variables.*offset= (ulong) var->save_result.ulonglong_value;
unknown's avatar
unknown committed
1695
  else
1696
    thd->variables.*offset= (ulong) var->save_result.ulonglong_value;
1697

unknown's avatar
unknown committed
1698 1699 1700 1701 1702 1703 1704 1705
  return 0;
}


void sys_var_thd_ulong::set_default(THD *thd, enum_var_type type)
{
  if (type == OPT_GLOBAL)
  {
1706
    my_bool not_used;
unknown's avatar
unknown committed
1707
    /* We will not come here if option_limits is not set */
1708
    global_system_variables.*offset=
unknown's avatar
unknown committed
1709 1710
      (ulong) getopt_ull_limit_value((ulong) option_limits->def_value,
                                     option_limits, &not_used);
unknown's avatar
unknown committed
1711 1712 1713 1714 1715 1716
  }
  else
    thd->variables.*offset= global_system_variables.*offset;
}


1717
uchar *sys_var_thd_ulong::value_ptr(THD *thd, enum_var_type type,
1718
				   LEX_STRING *base)
unknown's avatar
unknown committed
1719 1720
{
  if (type == OPT_GLOBAL)
1721 1722
    return (uchar*) &(global_system_variables.*offset);
  return (uchar*) &(thd->variables.*offset);
unknown's avatar
unknown committed
1723 1724 1725
}


1726 1727
bool sys_var_thd_ha_rows::update(THD *thd, set_var *var)
{
1728
  ulonglong tmp= var->save_result.ulonglong_value;
1729 1730 1731 1732 1733

  /* Don't use bigger value than given with --maximum-variable-name=.. */
  if ((ha_rows) tmp > max_system_variables.*offset)
    tmp= max_system_variables.*offset;

1734
  bound_unsigned(thd, &tmp, option_limits);
1735

1736 1737 1738
  if (var->type == OPT_GLOBAL)
  {
    /* Lock is needed to make things safe on 32 bit systems */
unknown's avatar
unknown committed
1739
    pthread_mutex_lock(&LOCK_global_system_variables);
1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752
    global_system_variables.*offset= (ha_rows) tmp;
    pthread_mutex_unlock(&LOCK_global_system_variables);
  }
  else
    thd->variables.*offset= (ha_rows) tmp;
  return 0;
}


void sys_var_thd_ha_rows::set_default(THD *thd, enum_var_type type)
{
  if (type == OPT_GLOBAL)
  {
1753
    my_bool not_used;
1754 1755
    /* We will not come here if option_limits is not set */
    pthread_mutex_lock(&LOCK_global_system_variables);
1756 1757 1758
    global_system_variables.*offset=
      (ha_rows) getopt_ull_limit_value((ha_rows) option_limits->def_value,
                                       option_limits, &not_used);
1759 1760 1761 1762 1763 1764 1765
    pthread_mutex_unlock(&LOCK_global_system_variables);
  }
  else
    thd->variables.*offset= global_system_variables.*offset;
}


1766
uchar *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type,
1767
				     LEX_STRING *base)
1768 1769
{
  if (type == OPT_GLOBAL)
1770 1771
    return (uchar*) &(global_system_variables.*offset);
  return (uchar*) &(thd->variables.*offset);
1772 1773
}

1774 1775
bool sys_var_thd_ulonglong::check(THD *thd, set_var *var)
{
1776
  return get_unsigned(thd, var, max_system_variables.*offset, GET_ULL);
1777 1778
}

unknown's avatar
unknown committed
1779 1780 1781
bool sys_var_thd_ulonglong::update(THD *thd,  set_var *var)
{
  if (var->type == OPT_GLOBAL)
1782 1783 1784
  {
    /* Lock is needed to make things safe on 32 bit systems */
    pthread_mutex_lock(&LOCK_global_system_variables);
1785 1786
    global_system_variables.*offset= (ulonglong)
                                     var->save_result.ulonglong_value;
1787 1788
    pthread_mutex_unlock(&LOCK_global_system_variables);
  }
unknown's avatar
unknown committed
1789
  else
1790
    thd->variables.*offset= (ulonglong) var->save_result.ulonglong_value;
unknown's avatar
unknown committed
1791 1792 1793 1794 1795 1796 1797
  return 0;
}


void sys_var_thd_ulonglong::set_default(THD *thd, enum_var_type type)
{
  if (type == OPT_GLOBAL)
1798
  {
1799
    my_bool not_used;
1800
    pthread_mutex_lock(&LOCK_global_system_variables);
1801 1802 1803
    global_system_variables.*offset=
      getopt_ull_limit_value((ulonglong) option_limits->def_value,
                             option_limits, &not_used);
1804 1805
    pthread_mutex_unlock(&LOCK_global_system_variables);
  }
unknown's avatar
unknown committed
1806 1807 1808 1809 1810
  else
    thd->variables.*offset= global_system_variables.*offset;
}


1811
uchar *sys_var_thd_ulonglong::value_ptr(THD *thd, enum_var_type type,
1812
				       LEX_STRING *base)
unknown's avatar
unknown committed
1813 1814
{
  if (type == OPT_GLOBAL)
1815 1816
    return (uchar*) &(global_system_variables.*offset);
  return (uchar*) &(thd->variables.*offset);
unknown's avatar
unknown committed
1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838
}


bool sys_var_thd_bool::update(THD *thd,  set_var *var)
{
  if (var->type == OPT_GLOBAL)
    global_system_variables.*offset= (my_bool) var->save_result.ulong_value;
  else
    thd->variables.*offset= (my_bool) var->save_result.ulong_value;
  return 0;
}


void sys_var_thd_bool::set_default(THD *thd,  enum_var_type type)
{
  if (type == OPT_GLOBAL)
    global_system_variables.*offset= (my_bool) option_limits->def_value;
  else
    thd->variables.*offset= global_system_variables.*offset;
}


1839
uchar *sys_var_thd_bool::value_ptr(THD *thd, enum_var_type type,
1840
				  LEX_STRING *base)
unknown's avatar
unknown committed
1841 1842
{
  if (type == OPT_GLOBAL)
1843 1844
    return (uchar*) &(global_system_variables.*offset);
  return (uchar*) &(thd->variables.*offset);
unknown's avatar
unknown committed
1845 1846 1847
}


1848
bool sys_var::check_enum(THD *thd, set_var *var, const TYPELIB *enum_names)
unknown's avatar
unknown committed
1849
{
unknown's avatar
unknown committed
1850
  char buff[STRING_BUFFER_USUAL_SIZE];
1851
  const char *value;
1852
  String str(buff, sizeof(buff) - 1, system_charset_info), *res;
unknown's avatar
unknown committed
1853 1854 1855 1856 1857

  if (var->value->result_type() == STRING_RESULT)
  {
    if (!(res=var->value->val_str(&str)) ||
	((long) (var->save_result.ulong_value=
1858 1859
		 (ulong) find_type(enum_names, res->ptr(),
				   res->length(),1)-1)) < 0)
unknown's avatar
unknown committed
1860
    {
1861
      value= res ? res->c_ptr() : "NULL";
unknown's avatar
unknown committed
1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878
      goto err;
    }
  }
  else
  {
    ulonglong tmp=var->value->val_int();
    if (tmp >= enum_names->count)
    {
      llstr(tmp,buff);
      value=buff;				// Wrong value is here
      goto err;
    }
    var->save_result.ulong_value= (ulong) tmp;	// Save for update
  }
  return 0;

err:
1879
  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, value);
unknown's avatar
unknown committed
1880 1881 1882
  return 1;
}

1883 1884 1885 1886 1887 1888
/**
   Check vality of set

   Note that this sets 'save_result.ulong_value' for the update function,
   which means that we don't need a separate sys_var::update() function
*/
1889 1890 1891

bool sys_var::check_set(THD *thd, set_var *var, TYPELIB *enum_names)
{
1892
  bool not_used;
1893
  char buff[256], *error= 0;
1894
  uint error_len= 0;
1895
  String str(buff, sizeof(buff) - 1, system_charset_info), *res;
1896 1897 1898 1899

  if (var->value->result_type() == STRING_RESULT)
  {
    if (!(res= var->value->val_str(&str)))
1900
    {
unknown's avatar
unknown committed
1901
      strmov(buff, "NULL");
1902
      goto err;
1903
    }
1904

1905
    if (!m_allow_empty_value && res->length() == 0)
1906 1907 1908 1909 1910
    {
      buff[0]= 0;
      goto err;
    }

unknown's avatar
unknown committed
1911
    var->save_result.ulong_value= ((ulong)
1912
				   find_set(enum_names, res->ptr(),
1913 1914 1915
					    res->length(),
                                            NULL,
                                            &error, &error_len,
unknown's avatar
unknown committed
1916
					    &not_used));
1917 1918
    if (error_len)
    {
1919
      strmake(buff, error, min(sizeof(buff) - 1, error_len));
1920 1921 1922 1923 1924 1925
      goto err;
    }
  }
  else
  {
    ulonglong tmp= var->value->val_int();
1926

1927
    if (!m_allow_empty_value && tmp == 0)
1928 1929 1930 1931 1932 1933 1934 1935 1936 1937
    {
      buff[0]= '0';
      buff[1]= 0;
      goto err;
    }

    /*
      For when the enum is made to contain 64 elements, as 1ULL<<64 is
      undefined, we guard with a "count<64" test.
    */
1938 1939
    if (unlikely((tmp >= ((ULL(1)) << enum_names->count)) &&
                 (enum_names->count < 64)))
1940 1941 1942 1943 1944 1945 1946 1947 1948
    {
      llstr(tmp, buff);
      goto err;
    }
    var->save_result.ulong_value= (ulong) tmp;  // Save for update
  }
  return 0;

err:
1949
  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buff);
1950 1951 1952 1953
  return 1;
}


1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996
/**
  Make string representation of set

  @param[in]  thd    thread handler
  @param[in]  val    sql_mode value
  @param[in]  names  names for the different bits
  @param[out] rep    Result string

  @return
    0 ok
    1 end of memory
*/

bool sys_var::make_set(THD *thd, ulonglong val, TYPELIB *names,
                       LEX_STRING *rep)
{
  /* Strings for typelib may be big; This is reallocated on demand */
  char buff[256];
  String tmp(buff, sizeof(buff) - 1, &my_charset_latin1);
  bool error= 0;

  tmp.length(0);
  for (uint i= 0; val; val>>= 1, i++)
  {
    if (val & 1)
    {
      error|= tmp.append(names->type_names[i],
                 names->type_lengths[i]);
      error|= tmp.append(',');
    }
  }

  if (tmp.length())
    tmp.length(tmp.length() - 1); /* trim the trailing comma */

  /* Allocate temporary copy of string */
  if (!(rep->str= thd->strmake(tmp.ptr(), tmp.length())))
    error= 1;
  rep->length= tmp.length();
  return error;                   /* Error in case of out of memory */
}


1997 1998 1999 2000 2001
CHARSET_INFO *sys_var::charset(THD *thd)
{
  return is_os_charset ? thd->variables.character_set_filesystem : 
    system_charset_info;
}
unknown's avatar
unknown committed
2002

2003

unknown's avatar
unknown committed
2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022
bool sys_var_thd_enum::update(THD *thd, set_var *var)
{
  if (var->type == OPT_GLOBAL)
    global_system_variables.*offset= var->save_result.ulong_value;
  else
    thd->variables.*offset= var->save_result.ulong_value;
  return 0;
}


void sys_var_thd_enum::set_default(THD *thd, enum_var_type type)
{
  if (type == OPT_GLOBAL)
    global_system_variables.*offset= (ulong) option_limits->def_value;
  else
    thd->variables.*offset= global_system_variables.*offset;
}


2023
uchar *sys_var_thd_enum::value_ptr(THD *thd, enum_var_type type,
2024
				  LEX_STRING *base)
unknown's avatar
unknown committed
2025 2026 2027 2028
{
  ulong tmp= ((type == OPT_GLOBAL) ?
	      global_system_variables.*offset :
	      thd->variables.*offset);
2029
  return (uchar*) enum_names->type_names[tmp];
unknown's avatar
unknown committed
2030 2031
}

2032 2033 2034 2035 2036 2037 2038 2039 2040 2041
uchar *sys_var_thd_set::value_ptr(THD *thd, enum_var_type type,
                                  LEX_STRING *base)
{
  LEX_STRING sql_mode;
  ulong val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
              thd->variables.*offset);
  (void) make_set(thd, val & visible_value_mask, enum_names, &sql_mode);
  return (uchar *) sql_mode.str;
}

2042 2043 2044 2045 2046
bool sys_var_thd_bit::check(THD *thd, set_var *var)
{
  return (check_enum(thd, var, &bool_typelib) ||
          (check_func && (*check_func)(thd, var)));
}
unknown's avatar
unknown committed
2047 2048 2049

bool sys_var_thd_bit::update(THD *thd, set_var *var)
{
2050
  int res= (*update_func)(thd, var);
unknown's avatar
unknown committed
2051 2052 2053 2054
  return res;
}


2055
uchar *sys_var_thd_bit::value_ptr(THD *thd, enum_var_type type,
2056
				 LEX_STRING *base)
unknown's avatar
unknown committed
2057 2058 2059 2060 2061 2062 2063
{
  /*
    If reverse is 0 (default) return 1 if bit is set.
    If reverse is 1, return 0 if bit is set
  */
  thd->sys_var_tmp.my_bool_value= ((thd->options & bit_flag) ?
				   !reverse : reverse);
2064
  return (uchar*) &thd->sys_var_tmp.my_bool_value;
unknown's avatar
unknown committed
2065 2066 2067
}


unknown's avatar
unknown committed
2068
/** Update a date_time format variable based on given value. */
2069 2070 2071 2072 2073 2074

void sys_var_thd_date_time_format::update2(THD *thd, enum_var_type type,
					   DATE_TIME_FORMAT *new_value)
{
  DATE_TIME_FORMAT *old;
  DBUG_ENTER("sys_var_date_time_format::update2");
2075
  DBUG_DUMP("positions", (uchar*) new_value->positions,
2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109
	    sizeof(new_value->positions));

  if (type == OPT_GLOBAL)
  {
    pthread_mutex_lock(&LOCK_global_system_variables);
    old= (global_system_variables.*offset);
    (global_system_variables.*offset)= new_value;
    pthread_mutex_unlock(&LOCK_global_system_variables);
  }
  else
  {
    old= (thd->variables.*offset);
    (thd->variables.*offset)= new_value;
  }
  my_free((char*) old, MYF(MY_ALLOW_ZERO_PTR));
  DBUG_VOID_RETURN;
}


bool sys_var_thd_date_time_format::update(THD *thd, set_var *var)
{
  DATE_TIME_FORMAT *new_value;
  /* We must make a copy of the last value to get it into normal memory */
  new_value= date_time_format_copy((THD*) 0,
				   var->save_result.date_time_format);
  if (!new_value)
    return 1;					// Out of memory
  update2(thd, var->type, new_value);		// Can't fail
  return 0;
}


bool sys_var_thd_date_time_format::check(THD *thd, set_var *var)
{
unknown's avatar
unknown committed
2110
  char buff[STRING_BUFFER_USUAL_SIZE];
2111
  String str(buff,sizeof(buff) - 1, system_charset_info), *res;
2112 2113 2114 2115 2116 2117 2118 2119
  DATE_TIME_FORMAT *format;

  if (!(res=var->value->val_str(&str)))
    res= &my_empty_string;

  if (!(format= date_time_format_make(date_time_type,
				      res->ptr(), res->length())))
  {
2120
    my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, res->c_ptr());
2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154
    return 1;
  }
  
  /*
    We must copy result to thread space to not get a memory leak if
    update is aborted
  */
  var->save_result.date_time_format= date_time_format_copy(thd, format);
  my_free((char*) format, MYF(0));
  return var->save_result.date_time_format == 0;
}


void sys_var_thd_date_time_format::set_default(THD *thd, enum_var_type type)
{
  DATE_TIME_FORMAT *res= 0;

  if (type == OPT_GLOBAL)
  {
    const char *format;
    if ((format= opt_date_time_formats[date_time_type]))
      res= date_time_format_make(date_time_type, format, strlen(format));
  }
  else
  {
    /* Make copy with malloc */
    res= date_time_format_copy((THD *) 0, global_system_variables.*offset);
  }

  if (res)					// Should always be true
    update2(thd, type, res);
}


2155
uchar *sys_var_thd_date_time_format::value_ptr(THD *thd, enum_var_type type,
2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167
					      LEX_STRING *base)
{
  if (type == OPT_GLOBAL)
  {
    char *res;
    /*
      We do a copy here just to be sure things will work even if someone
      is modifying the original string while the copy is accessed
      (Can't happen now in SQL SHOW, but this is a good safety for the future)
    */
    res= thd->strmake((global_system_variables.*offset)->format.str,
		      (global_system_variables.*offset)->format.length);
2168
    return (uchar*) res;
2169
  }
2170
  return (uchar*) (thd->variables.*offset)->format.str;
2171 2172 2173
}


2174 2175
typedef struct old_names_map_st
{
unknown's avatar
unknown committed
2176 2177 2178
  const char *old_name;
  const char *new_name;
} my_old_conv;
unknown's avatar
unknown committed
2179

unknown's avatar
unknown committed
2180 2181
static my_old_conv old_conv[]= 
{
2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192
  {	"cp1251_koi8"		,	"cp1251"	},
  {	"cp1250_latin2"		,	"cp1250"	},
  {	"kam_latin2"		,	"keybcs2"	},
  {	"mac_latin2"		,	"MacRoman"	},
  {	"macce_latin2"		,	"MacCE"		},
  {	"pc2_latin2"		,	"pclatin2"	},
  {	"vga_latin2"		,	"pclatin1"	},
  {	"koi8_cp1251"		,	"koi8r"		},
  {	"win1251ukr_koi8_ukr"	,	"win1251ukr"	},
  {	"koi8_ukr_win1251ukr"	,	"koi8u"		},
  {	NULL			,	NULL		}
unknown's avatar
unknown committed
2193
};
unknown's avatar
unknown committed
2194

unknown's avatar
unknown committed
2195
CHARSET_INFO *get_old_charset_by_name(const char *name)
unknown's avatar
unknown committed
2196
{
unknown's avatar
unknown committed
2197
  my_old_conv *conv;
unknown's avatar
unknown committed
2198
 
unknown's avatar
unknown committed
2199
  for (conv= old_conv; conv->old_name; conv++)
2200
  {
unknown's avatar
unknown committed
2201 2202
    if (!my_strcasecmp(&my_charset_latin1, name, conv->old_name))
      return get_charset_by_csname(conv->new_name, MY_CS_PRIMARY, MYF(0));
2203
  }
unknown's avatar
unknown committed
2204
  return NULL;
unknown's avatar
unknown committed
2205 2206
}

unknown's avatar
unknown committed
2207

2208
bool sys_var_collation::check(THD *thd, set_var *var)
unknown's avatar
unknown committed
2209 2210
{
  CHARSET_INFO *tmp;
2211
  LINT_INIT(tmp);
unknown's avatar
unknown committed
2212

2213
  if (var->value->result_type() == STRING_RESULT)
2214
  {
unknown's avatar
unknown committed
2215
    char buff[STRING_BUFFER_USUAL_SIZE];
2216
    String str(buff,sizeof(buff) - 1, system_charset_info), *res;
2217 2218
    if (!(res=var->value->val_str(&str)))
    {
2219
      my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL");
2220 2221 2222 2223
      return 1;
    }
    if (!(tmp=get_charset_by_name(res->c_ptr(),MYF(0))))
    {
2224
      my_error(ER_UNKNOWN_COLLATION, MYF(0), res->c_ptr());
2225 2226
      return 1;
    }
2227
  }
2228
  else // INT_RESULT
2229
  {
2230
    if (!(tmp=get_charset((int) var->value->val_int(),MYF(0))))
2231 2232
    {
      char buf[20];
2233
      int10_to_str((int) var->value->val_int(), buf, -10);
2234
      my_error(ER_UNKNOWN_COLLATION, MYF(0), buf);
2235 2236
      return 1;
    }
2237 2238 2239 2240 2241
  }
  var->save_result.charset= tmp;	// Save for update
  return 0;
}

2242

2243 2244 2245
bool sys_var_character_set::check(THD *thd, set_var *var)
{
  CHARSET_INFO *tmp;
2246
  LINT_INIT(tmp);
2247

2248 2249
  if (var->value->result_type() == STRING_RESULT)
  {
unknown's avatar
unknown committed
2250
    char buff[STRING_BUFFER_USUAL_SIZE];
2251
    String str(buff,sizeof(buff) - 1, system_charset_info), *res;
2252
    if (!(res=var->value->val_str(&str)))
2253
    {
2254 2255
      if (!nullable)
      {
2256
        my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL");
2257 2258 2259 2260 2261 2262 2263
        return 1;
      }
      tmp= NULL;
    }
    else if (!(tmp=get_charset_by_csname(res->c_ptr(),MY_CS_PRIMARY,MYF(0))) &&
             !(tmp=get_old_charset_by_name(res->c_ptr())))
    {
2264
      my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), res->c_ptr());
2265 2266 2267
      return 1;
    }
  }
2268
  else // INT_RESULT
unknown's avatar
unknown committed
2269
  {
2270
    if (!(tmp=get_charset((int) var->value->val_int(),MYF(0))))
2271 2272
    {
      char buf[20];
2273
      int10_to_str((int) var->value->val_int(), buf, -10);
2274 2275 2276
      my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), buf);
      return 1;
    }
unknown's avatar
unknown committed
2277 2278 2279 2280 2281
  }
  var->save_result.charset= tmp;	// Save for update
  return 0;
}

2282

2283
bool sys_var_character_set::update(THD *thd, set_var *var)
unknown's avatar
unknown committed
2284
{
2285
  ci_ptr(thd,var->type)[0]= var->save_result.charset;
unknown's avatar
unknown committed
2286
  thd->update_charset();
unknown's avatar
unknown committed
2287 2288 2289
  return 0;
}

2290

2291
uchar *sys_var_character_set::value_ptr(THD *thd, enum_var_type type,
2292
				       LEX_STRING *base)
unknown's avatar
unknown committed
2293
{
2294
  CHARSET_INFO *cs= ci_ptr(thd,type)[0];
2295
  return cs ? (uchar*) cs->csname : (uchar*) NULL;
unknown's avatar
unknown committed
2296 2297 2298
}


unknown's avatar
unknown committed
2299
void sys_var_character_set_sv::set_default(THD *thd, enum_var_type type)
2300
{
2301
  if (type == OPT_GLOBAL)
unknown's avatar
unknown committed
2302
    global_system_variables.*offset= *global_default;
2303
  else
unknown's avatar
unknown committed
2304 2305 2306 2307
  {
    thd->variables.*offset= global_system_variables.*offset;
    thd->update_charset();
  }
2308
}
unknown's avatar
unknown committed
2309
CHARSET_INFO **sys_var_character_set_sv::ci_ptr(THD *thd, enum_var_type type)
2310 2311
{
  if (type == OPT_GLOBAL)
unknown's avatar
unknown committed
2312
    return &(global_system_variables.*offset);
2313
  else
unknown's avatar
unknown committed
2314
    return &(thd->variables.*offset);
2315 2316
}

2317

2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332
bool sys_var_character_set_client::check(THD *thd, set_var *var)
{
  if (sys_var_character_set_sv::check(thd, var))
    return 1;
  /* Currently, UCS-2 cannot be used as a client character set */
  if (var->save_result.charset->mbminlen > 1)
  {
    my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, 
             var->save_result.charset->csname);
    return 1;
  }
  return 0;
}


2333 2334
CHARSET_INFO ** sys_var_character_set_database::ci_ptr(THD *thd,
						       enum_var_type type)
2335 2336
{
  if (type == OPT_GLOBAL)
2337
    return &global_system_variables.collation_database;
2338
  else
2339
    return &thd->variables.collation_database;
2340 2341
}

2342

2343 2344 2345
void sys_var_character_set_database::set_default(THD *thd, enum_var_type type)
{
 if (type == OPT_GLOBAL)
2346
    global_system_variables.collation_database= default_charset_info;
2347
  else
unknown's avatar
unknown committed
2348
  {
2349
    thd->variables.collation_database= thd->db_charset;
unknown's avatar
unknown committed
2350 2351
    thd->update_charset();
  }
2352 2353
}

2354

unknown's avatar
unknown committed
2355
bool sys_var_collation_sv::update(THD *thd, set_var *var)
2356 2357
{
  if (var->type == OPT_GLOBAL)
unknown's avatar
unknown committed
2358
    global_system_variables.*offset= var->save_result.charset;
2359
  else
unknown's avatar
unknown committed
2360
  {
unknown's avatar
unknown committed
2361
    thd->variables.*offset= var->save_result.charset;
unknown's avatar
unknown committed
2362 2363
    thd->update_charset();
  }
2364 2365 2366
  return 0;
}

2367

unknown's avatar
unknown committed
2368
void sys_var_collation_sv::set_default(THD *thd, enum_var_type type)
2369
{
unknown's avatar
unknown committed
2370 2371
  if (type == OPT_GLOBAL)
    global_system_variables.*offset= *global_default;
2372 2373
  else
  {
unknown's avatar
unknown committed
2374
    thd->variables.*offset= global_system_variables.*offset;
2375 2376 2377 2378 2379
    thd->update_charset();
  }
}


2380
uchar *sys_var_collation_sv::value_ptr(THD *thd, enum_var_type type,
2381
                                       LEX_STRING *base)
2382 2383
{
  CHARSET_INFO *cs= ((type == OPT_GLOBAL) ?
2384
		     global_system_variables.*offset : thd->variables.*offset);
2385
  return cs ? (uchar*) cs->name : (uchar*) "NULL";
2386 2387
}

2388

2389
LEX_STRING default_key_cache_base= {(char *) "default", 7 };
unknown's avatar
unknown committed
2390

unknown's avatar
unknown committed
2391
static KEY_CACHE zero_key_cache;
unknown's avatar
unknown committed
2392

unknown's avatar
unknown committed
2393
KEY_CACHE *get_key_cache(LEX_STRING *cache_name)
unknown's avatar
unknown committed
2394
{
2395 2396
  safe_mutex_assert_owner(&LOCK_global_system_variables);
  if (!cache_name || ! cache_name->length)
unknown's avatar
unknown committed
2397
    cache_name= &default_key_cache_base;
unknown's avatar
unknown committed
2398
  return ((KEY_CACHE*) find_named(&key_caches,
2399
                                  cache_name->str, cache_name->length, 0));
unknown's avatar
unknown committed
2400 2401
}

2402
uchar *sys_var_key_cache_param::value_ptr(THD *thd, enum_var_type type,
unknown's avatar
unknown committed
2403
					 LEX_STRING *base)
2404
{
unknown's avatar
unknown committed
2405
  KEY_CACHE *key_cache= get_key_cache(base);
unknown's avatar
unknown committed
2406 2407
  if (!key_cache)
    key_cache= &zero_key_cache;
2408
  return (uchar*) key_cache + offset ;
unknown's avatar
unknown committed
2409
}
2410

2411

2412 2413
bool sys_var_key_buffer_size::update(THD *thd, set_var *var)
{
2414
  ulonglong tmp= var->save_result.ulonglong_value;
unknown's avatar
unknown committed
2415
  LEX_STRING *base_name= &var->base;
unknown's avatar
unknown committed
2416
  KEY_CACHE *key_cache;
2417 2418 2419
  bool error= 0;

  /* If no basename, assume it's for the key cache named 'default' */
unknown's avatar
unknown committed
2420
  if (!base_name->length)
2421
    base_name= &default_key_cache_base;
2422 2423 2424

  pthread_mutex_lock(&LOCK_global_system_variables);
  key_cache= get_key_cache(base_name);
unknown's avatar
unknown committed
2425
                            
2426 2427
  if (!key_cache)
  {
2428
    /* Key cache didn't exists */
2429
    if (!tmp)					// Tried to delete cache
2430 2431 2432 2433 2434 2435
      goto end;					// Ok, nothing to do
    if (!(key_cache= create_key_cache(base_name->str, base_name->length)))
    {
      error= 1;
      goto end;
    }
2436
  }
2437 2438 2439 2440 2441 2442 2443 2444 2445

  /*
    Abort if some other thread is changing the key cache
    TODO: This should be changed so that we wait until the previous
    assignment is done and then do the new assign
  */
  if (key_cache->in_init)
    goto end;

unknown's avatar
unknown committed
2446
  if (!tmp)					// Zero size means delete
2447
  {
unknown's avatar
unknown committed
2448
    if (key_cache == dflt_key_cache)
2449 2450 2451 2452
    {
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
                          ER_WARN_CANT_DROP_DEFAULT_KEYCACHE,
                          ER(ER_WARN_CANT_DROP_DEFAULT_KEYCACHE));
2453
      goto end;					// Ignore default key cache
2454
    }
2455

unknown's avatar
unknown committed
2456
    if (key_cache->key_cache_inited)		// If initied
2457 2458
    {
      /*
2459 2460
	Move tables using this key cache to the default key cache
	and clear the old key cache.
2461
      */
2462
      NAMED_LIST *list; 
unknown's avatar
unknown committed
2463
      key_cache= (KEY_CACHE *) find_named(&key_caches, base_name->str,
2464
					      base_name->length, &list);
2465 2466
      key_cache->in_init= 1;
      pthread_mutex_unlock(&LOCK_global_system_variables);
unknown's avatar
unknown committed
2467
      error= reassign_keycache_tables(thd, key_cache, dflt_key_cache);
2468 2469
      pthread_mutex_lock(&LOCK_global_system_variables);
      key_cache->in_init= 0;
2470
    }
2471 2472 2473 2474 2475
    /*
      We don't delete the key cache as some running threads my still be
      in the key cache code with a pointer to the deleted (empty) key cache
    */
    goto end;
2476 2477
  }

2478
  bound_unsigned(thd, &tmp, option_limits);
2479
  key_cache->param_buff_size= (ulonglong) tmp;
2480

2481
  /* If key cache didn't exist initialize it, else resize it */
2482 2483 2484
  key_cache->in_init= 1;
  pthread_mutex_unlock(&LOCK_global_system_variables);

unknown's avatar
unknown committed
2485
  if (!key_cache->key_cache_inited)
2486
    error= (bool) (ha_init_key_cache("", key_cache));
unknown's avatar
unknown committed
2487
  else
2488
    error= (bool)(ha_resize_key_cache(key_cache));
2489

2490 2491
  pthread_mutex_lock(&LOCK_global_system_variables);
  key_cache->in_init= 0;  
2492

2493 2494 2495
end:
  pthread_mutex_unlock(&LOCK_global_system_variables);
  return error;
2496 2497
}

2498

unknown's avatar
unknown committed
2499 2500 2501 2502 2503 2504
/**
  @todo
  Abort if some other thread is changing the key cache.
  This should be changed so that we wait until the previous
  assignment is done and then do the new assign
*/
2505
bool sys_var_key_cache_long::update(THD *thd, set_var *var)
2506
{
2507
  ulonglong tmp= var->value->val_int();
2508
  LEX_STRING *base_name= &var->base;
2509 2510
  bool error= 0;

2511
  if (!base_name->length)
unknown's avatar
unknown committed
2512
    base_name= &default_key_cache_base;
2513 2514

  pthread_mutex_lock(&LOCK_global_system_variables);
unknown's avatar
unknown committed
2515
  KEY_CACHE *key_cache= get_key_cache(base_name);
2516

unknown's avatar
unknown committed
2517 2518
  if (!key_cache && !(key_cache= create_key_cache(base_name->str,
				                  base_name->length)))
2519 2520 2521 2522
  {
    error= 1;
    goto end;
  }
2523

2524 2525 2526 2527 2528 2529 2530 2531
  /*
    Abort if some other thread is changing the key cache
    TODO: This should be changed so that we wait until the previous
    assignment is done and then do the new assign
  */
  if (key_cache->in_init)
    goto end;

2532
  bound_unsigned(thd, &tmp, option_limits);
2533
  *((ulong*) (((char*) key_cache) + offset))= (ulong) tmp;
unknown's avatar
unknown committed
2534

2535 2536 2537 2538 2539
  /*
    Don't create a new key cache if it didn't exist
    (key_caches are created only when the user sets block_size)
  */
  key_cache->in_init= 1;
2540

2541
  pthread_mutex_unlock(&LOCK_global_system_variables);
2542

2543 2544 2545 2546 2547 2548 2549 2550
  error= (bool) (ha_resize_key_cache(key_cache));

  pthread_mutex_lock(&LOCK_global_system_variables);
  key_cache->in_init= 0;  

end:
  pthread_mutex_unlock(&LOCK_global_system_variables);
  return error;
2551 2552
}

2553

2554 2555
bool sys_var_log_state::update(THD *thd, set_var *var)
{
2556
  bool res;
2557 2558 2559 2560 2561
  if (this == &sys_var_log)
    WARN_DEPRECATED(thd, "7.0", "@@log", "'@@general_log'");
  else if (this == &sys_var_log_slow)
    WARN_DEPRECATED(thd, "7.0", "@@log_slow_queries", "'@@slow_query_log'");

2562 2563
  if (!var->save_result.ulong_value)
  {
2564 2565
    logger.deactivate_log_handler(thd, log_type);
    res= false;
2566
  }
2567 2568
  else
    res= logger.activate_log_handler(thd, log_type);
2569 2570 2571 2572 2573
  return res;
}

void sys_var_log_state::set_default(THD *thd, enum_var_type type)
{
2574 2575 2576 2577 2578
  if (this == &sys_var_log)
    WARN_DEPRECATED(thd, "7.0", "@@log", "'@@general_log'");
  else if (this == &sys_var_log_slow)
    WARN_DEPRECATED(thd, "7.0", "@@log_slow_queries", "'@@slow_query_log'");

2579 2580 2581 2582 2583 2584
  logger.deactivate_log_handler(thd, log_type);
}


static int  sys_check_log_path(THD *thd,  set_var *var)
{
2585
  char path[FN_REFLEN], buff[FN_REFLEN];
2586
  MY_STAT f_stat;
2587 2588
  String str(buff, sizeof(buff), system_charset_info), *res;
  const char *log_file_str;
2589 2590
  size_t path_length;

2591 2592 2593 2594
  if (!(res= var->value->val_str(&str)))
    goto err;

  log_file_str= res->c_ptr();
2595 2596
  bzero(&f_stat, sizeof(MY_STAT));

2597 2598 2599
  path_length= unpack_filename(path, log_file_str);

  if (!path_length)
2600
  {
2601 2602 2603
    /* File name is empty. */

    goto err;
2604
  }
2605 2606

  if (my_stat(path, &f_stat, MYF(0)))
2607 2608
  {
    /*
2609 2610
      A file system object exists. Check if argument is a file and we have
      'write' permission.
2611
    */
2612 2613 2614

    if (!MY_S_ISREG(f_stat.st_mode) ||
        !(f_stat.st_mode & MY_S_IWRITE))
2615
      goto err;
2616 2617

    return 0;
2618
  }
2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633

  /* Get dirname of the file path. */
  (void) dirname_part(path, log_file_str, &path_length);

  /* Dirname is empty if file path is relative. */
  if (!path_length)
    return 0;

  /*
    Check if directory exists and we have permission to create file and
    write to file.
  */
  if (my_access(path, (F_OK|W_OK)))
    goto err;

2634
  return 0;
2635 2636 2637 2638 2639

err:
  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), var->var->name, 
           res ? log_file_str : "NULL");
  return 1;
2640 2641 2642 2643 2644 2645 2646
}


bool update_sys_var_str_path(THD *thd, sys_var_str *var_str,
			     set_var *var, const char *log_ext,
			     bool log_state, uint log_type)
{
unknown's avatar
unknown committed
2647
  MYSQL_QUERY_LOG *file_log;
2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660
  char buff[FN_REFLEN];
  char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0);
  bool result= 0;
  uint str_length= (var ? var->value->str_value.length() : 0);

  switch (log_type) {
  case QUERY_LOG_SLOW:
    file_log= logger.get_slow_log_file_handler();
    break;
  case QUERY_LOG_GENERAL:
    file_log= logger.get_log_file_handler();
    break;
  default:
unknown's avatar
unknown committed
2661
    assert(0);                                  // Impossible
2662 2663 2664 2665 2666 2667 2668
  }

  if (!old_value)
  {
    old_value= make_default_log_name(buff, log_ext);
    str_length= strlen(old_value);
  }
2669
  if (!(res= my_strndup(old_value, str_length, MYF(MY_FAE+MY_WME))))
2670 2671 2672 2673 2674
  {
    result= 1;
    goto err;
  }

2675
  logger.lock_exclusive();
2676 2677 2678 2679

  if (file_log && log_state)
    file_log->close(0);
  if (file_log && log_state)
unknown's avatar
unknown committed
2680 2681 2682
  {
    switch (log_type) {
    case QUERY_LOG_SLOW:
2683
      file_log->open_slow_log(res);
unknown's avatar
unknown committed
2684 2685
      break;
    case QUERY_LOG_GENERAL:
2686
      file_log->open_query_log(res);
unknown's avatar
unknown committed
2687 2688 2689 2690 2691
      break;
    default:
      DBUG_ASSERT(0);
    }
  }
2692 2693

  logger.unlock();
2694 2695 2696 2697 2698 2699 2700

  /* update global variable */
  pthread_mutex_lock(&LOCK_global_system_variables);
  old_value= var_str->value;
  var_str->value= res;
  var_str->value_length= str_length;
  my_free(old_value, MYF(MY_ALLOW_ZERO_PTR));
2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739
  pthread_mutex_unlock(&LOCK_global_system_variables);

err:
  return result;
}


static bool sys_update_general_log_path(THD *thd, set_var * var)
{
  return update_sys_var_str_path(thd, &sys_var_general_log_path, 
				 var, ".log", opt_log, QUERY_LOG_GENERAL);
}


static void sys_default_general_log_path(THD *thd, enum_var_type type)
{
  (void) update_sys_var_str_path(thd, &sys_var_general_log_path,
				 0, ".log", opt_log, QUERY_LOG_GENERAL);
}


static bool sys_update_slow_log_path(THD *thd, set_var * var)
{
  return update_sys_var_str_path(thd, &sys_var_slow_log_path,
				 var, "-slow.log", opt_slow_log,
                                 QUERY_LOG_SLOW);
}


static void sys_default_slow_log_path(THD *thd, enum_var_type type)
{
  (void) update_sys_var_str_path(thd, &sys_var_slow_log_path,
				 0, "-slow.log", opt_slow_log,
                                 QUERY_LOG_SLOW);
}


bool sys_var_log_output::update(THD *thd, set_var *var)
{
2740
  logger.lock_exclusive();
2741 2742 2743 2744 2745 2746 2747 2748 2749 2750
  logger.init_slow_log(var->save_result.ulong_value);
  logger.init_general_log(var->save_result.ulong_value);
  *value= var->save_result.ulong_value;
  logger.unlock();
  return 0;
}


void sys_var_log_output::set_default(THD *thd, enum_var_type type)
{
2751 2752 2753 2754
  logger.lock_exclusive();
  logger.init_slow_log(LOG_FILE);
  logger.init_general_log(LOG_FILE);
  *value= LOG_FILE;
2755 2756 2757 2758
  logger.unlock();
}


2759
uchar *sys_var_log_output::value_ptr(THD *thd, enum_var_type type,
unknown's avatar
unknown committed
2760
                                    LEX_STRING *base)
2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779
{
  char buff[256];
  String tmp(buff, sizeof(buff), &my_charset_latin1);
  ulong length;
  ulong val= *value;

  tmp.length(0);
  for (uint i= 0; val; val>>= 1, i++)
  {
    if (val & 1)
    {
      tmp.append(log_output_typelib.type_names[i],
                 log_output_typelib.type_lengths[i]);
      tmp.append(',');
    }
  }

  if ((length= tmp.length()))
    length--;
2780
  return (uchar*) thd->strmake(tmp.ptr(), length);
2781 2782 2783
}


2784 2785 2786 2787
/*****************************************************************************
  Functions to handle SET NAMES and SET CHARACTER SET
*****************************************************************************/

unknown's avatar
unknown committed
2788
int set_var_collation_client::check(THD *thd)
2789
{
2790 2791 2792 2793 2794 2795 2796
  /* Currently, UCS-2 cannot be used as a client character set */
  if (character_set_client->mbminlen > 1)
  {
    my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "character_set_client",
             character_set_client->csname);
    return 1;
  }
2797 2798 2799
  return 0;
}

unknown's avatar
unknown committed
2800
int set_var_collation_client::update(THD *thd)
2801
{
2802 2803
  thd->variables.character_set_client= character_set_client;
  thd->variables.character_set_results= character_set_results;
unknown's avatar
unknown committed
2804
  thd->variables.collation_connection= collation_connection;
unknown's avatar
unknown committed
2805
  thd->update_charset();
unknown's avatar
unknown committed
2806 2807
  thd->protocol_text.init(thd);
  thd->protocol_binary.init(thd);
2808 2809 2810 2811 2812
  return 0;
}

/****************************************************************************/

unknown's avatar
unknown committed
2813 2814
bool sys_var_timestamp::update(THD *thd,  set_var *var)
{
2815
  thd->set_time((time_t) var->save_result.ulonglong_value);
unknown's avatar
unknown committed
2816 2817 2818 2819 2820 2821 2822 2823 2824 2825
  return 0;
}


void sys_var_timestamp::set_default(THD *thd, enum_var_type type)
{
  thd->user_time=0;
}


2826
uchar *sys_var_timestamp::value_ptr(THD *thd, enum_var_type type,
2827
				   LEX_STRING *base)
unknown's avatar
unknown committed
2828 2829
{
  thd->sys_var_tmp.long_value= (long) thd->start_time;
2830
  return (uchar*) &thd->sys_var_tmp.long_value;
unknown's avatar
unknown committed
2831 2832 2833 2834 2835
}


bool sys_var_last_insert_id::update(THD *thd, set_var *var)
{
2836 2837
  thd->first_successful_insert_id_in_prev_stmt= 
    var->save_result.ulonglong_value;
unknown's avatar
unknown committed
2838 2839 2840 2841
  return 0;
}


2842
uchar *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type,
2843
					LEX_STRING *base)
unknown's avatar
unknown committed
2844
{
2845 2846 2847 2848 2849 2850
  /*
    this tmp var makes it robust againt change of type of 
    read_first_successful_insert_id_in_prev_stmt().
  */
  thd->sys_var_tmp.ulonglong_value= 
    thd->read_first_successful_insert_id_in_prev_stmt();
2851
  return (uchar*) &thd->sys_var_tmp.ulonglong_value;
unknown's avatar
unknown committed
2852 2853 2854 2855 2856
}


bool sys_var_insert_id::update(THD *thd, set_var *var)
{
2857
  thd->force_one_auto_inc_interval(var->save_result.ulonglong_value);
unknown's avatar
unknown committed
2858 2859 2860 2861
  return 0;
}


2862
uchar *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type,
2863
				   LEX_STRING *base)
unknown's avatar
unknown committed
2864
{
2865 2866
  thd->sys_var_tmp.ulonglong_value= 
    thd->auto_inc_intervals_forced.minimum();
2867
  return (uchar*) &thd->sys_var_tmp.ulonglong_value;
unknown's avatar
unknown committed
2868
}
2869 2870


2871 2872
bool sys_var_rand_seed1::update(THD *thd, set_var *var)
{
2873
  thd->rand.seed1= (ulong) var->save_result.ulonglong_value;
2874 2875 2876 2877 2878
  return 0;
}

bool sys_var_rand_seed2::update(THD *thd, set_var *var)
{
2879
  thd->rand.seed2= (ulong) var->save_result.ulonglong_value;
2880 2881 2882 2883
  return 0;
}


2884 2885
bool sys_var_thd_time_zone::check(THD *thd, set_var *var)
{
2886
  char buff[MAX_TIME_ZONE_NAME_LENGTH];
2887 2888 2889
  String str(buff, sizeof(buff), &my_charset_latin1);
  String *res= var->value->val_str(&str);

2890
  if (!(var->save_result.time_zone= my_tz_find(thd, res)))
2891
  {
2892
    my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), res ? res->c_ptr() : "NULL");
2893 2894 2895 2896 2897 2898 2899 2900
    return 1;
  }
  return 0;
}


bool sys_var_thd_time_zone::update(THD *thd, set_var *var)
{
2901 2902 2903 2904 2905 2906 2907 2908 2909
  /* We are using Time_zone object found during check() phase. */
  if (var->type == OPT_GLOBAL)
  {
    pthread_mutex_lock(&LOCK_global_system_variables);
    global_system_variables.time_zone= var->save_result.time_zone;
    pthread_mutex_unlock(&LOCK_global_system_variables);
  }
  else
    thd->variables.time_zone= var->save_result.time_zone;
2910 2911 2912 2913
  return 0;
}


2914
uchar *sys_var_thd_time_zone::value_ptr(THD *thd, enum_var_type type,
2915 2916 2917 2918 2919 2920 2921
				       LEX_STRING *base)
{
  /* 
    We can use ptr() instead of c_ptr() here because String contaning
    time zone name is guaranteed to be zero ended.
  */
  if (type == OPT_GLOBAL)
2922
    return (uchar *)(global_system_variables.time_zone->get_name()->ptr());
2923
  else
2924 2925 2926 2927 2928 2929 2930 2931 2932 2933
  {
    /*
      This is an ugly fix for replication: we don't replicate properly queries
      invoking system variables' values to update tables; but
      CONVERT_TZ(,,@@session.time_zone) is so popular that we make it
      replicable (i.e. we tell the binlog code to store the session
      timezone). If it's the global value which was used we can't replicate
      (binlog code stores session value only).
    */
    thd->time_zone_used= 1;
2934
    return (uchar *)(thd->variables.time_zone->get_name()->ptr());
2935
  }
2936 2937 2938 2939 2940
}


void sys_var_thd_time_zone::set_default(THD *thd, enum_var_type type)
{
2941
 pthread_mutex_lock(&LOCK_global_system_variables);
2942 2943 2944 2945 2946
 if (type == OPT_GLOBAL)
 {
   if (default_tz_name)
   {
     String str(default_tz_name, &my_charset_latin1);
2947 2948 2949 2950
     /*
       We are guaranteed to find this time zone since its existence
       is checked during start-up.
     */
2951
     global_system_variables.time_zone= my_tz_find(thd, &str);
2952 2953 2954 2955 2956 2957
   }
   else
     global_system_variables.time_zone= my_tz_SYSTEM;
 }
 else
   thd->variables.time_zone= global_system_variables.time_zone;
2958
 pthread_mutex_unlock(&LOCK_global_system_variables);
2959 2960
}

2961 2962 2963 2964 2965 2966 2967 2968 2969

bool sys_var_max_user_conn::check(THD *thd, set_var *var)
{
  if (var->type == OPT_GLOBAL)
    return sys_var_thd::check(thd, var);
  else
  {
    /*
      Per-session values of max_user_connections can't be set directly.
2970
      May be we should have a separate error message for this?
2971 2972 2973 2974 2975 2976 2977 2978 2979 2980
    */
    my_error(ER_GLOBAL_VARIABLE, MYF(0), name);
    return TRUE;
  }
}

bool sys_var_max_user_conn::update(THD *thd, set_var *var)
{
  DBUG_ASSERT(var->type == OPT_GLOBAL);
  pthread_mutex_lock(&LOCK_global_system_variables);
2981
  max_user_connections= (uint)var->save_result.ulonglong_value;
2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995
  pthread_mutex_unlock(&LOCK_global_system_variables);
  return 0;
}


void sys_var_max_user_conn::set_default(THD *thd, enum_var_type type)
{
  DBUG_ASSERT(type == OPT_GLOBAL);
  pthread_mutex_lock(&LOCK_global_system_variables);
  max_user_connections= (ulong) option_limits->def_value;
  pthread_mutex_unlock(&LOCK_global_system_variables);
}


2996
uchar *sys_var_max_user_conn::value_ptr(THD *thd, enum_var_type type,
2997 2998 2999 3000
                                       LEX_STRING *base)
{
  if (type != OPT_GLOBAL &&
      thd->user_connect && thd->user_connect->user_resources.user_conn)
3001 3002
    return (uchar*) &(thd->user_connect->user_resources.user_conn);
  return (uchar*) &(max_user_connections);
3003 3004
}

3005

3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017
bool sys_var_thd_ulong_session_readonly::check(THD *thd, set_var *var)
{
  if (var->type != OPT_GLOBAL)
  {
    my_error(ER_VARIABLE_IS_READONLY, MYF(0), "SESSION", name, "GLOBAL");
    return TRUE;
  }

  return sys_var_thd_ulong::check(thd, var);
}


unknown's avatar
unknown committed
3018 3019
bool sys_var_thd_lc_time_names::check(THD *thd, set_var *var)
{
3020
  MY_LOCALE *locale_match;
unknown's avatar
unknown committed
3021

3022
  if (var->value->result_type() == INT_RESULT)
unknown's avatar
unknown committed
3023
  {
3024 3025 3026 3027 3028 3029 3030
    if (!(locale_match= my_locale_by_number((uint) var->value->val_int())))
    {
      char buf[20];
      int10_to_str((int) var->value->val_int(), buf, -10);
      my_printf_error(ER_UNKNOWN_ERROR, "Unknown locale: '%s'", MYF(0), buf);
      return 1;
    }
unknown's avatar
unknown committed
3031
  }
3032
  else // STRING_RESULT
unknown's avatar
unknown committed
3033
  {
3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047
    char buff[6]; 
    String str(buff, sizeof(buff), &my_charset_latin1), *res;
    if (!(res=var->value->val_str(&str)))
    {
      my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, "NULL");
      return 1;
    }
    const char *locale_str= res->c_ptr();
    if (!(locale_match= my_locale_by_name(locale_str)))
    {
      my_printf_error(ER_UNKNOWN_ERROR,
                      "Unknown locale: '%s'", MYF(0), locale_str);
      return 1;
    }
unknown's avatar
unknown committed
3048
  }
3049

3050 3051
  var->save_result.locale_value= locale_match;
  return 0;
unknown's avatar
unknown committed
3052 3053 3054 3055 3056
}


bool sys_var_thd_lc_time_names::update(THD *thd, set_var *var)
{
3057 3058 3059 3060
  if (var->type == OPT_GLOBAL)
    global_system_variables.lc_time_names= var->save_result.locale_value;
  else
    thd->variables.lc_time_names= var->save_result.locale_value;
unknown's avatar
unknown committed
3061 3062 3063 3064
  return 0;
}


3065
uchar *sys_var_thd_lc_time_names::value_ptr(THD *thd, enum_var_type type,
unknown's avatar
unknown committed
3066 3067
					  LEX_STRING *base)
{
3068
  return type == OPT_GLOBAL ?
3069 3070
                 (uchar *) global_system_variables.lc_time_names->name :
                 (uchar *) thd->variables.lc_time_names->name;
unknown's avatar
unknown committed
3071 3072 3073 3074 3075
}


void sys_var_thd_lc_time_names::set_default(THD *thd, enum_var_type type)
{
3076 3077 3078 3079
  if (type == OPT_GLOBAL)
    global_system_variables.lc_time_names= my_default_lc_time_names;
  else
    thd->variables.lc_time_names= global_system_variables.lc_time_names;
unknown's avatar
unknown committed
3080
}
3081

3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135
/*
  Handling of microseoncds given as seconds.part_seconds

  NOTES
    The argument to long query time is in seconds in decimal
    which is converted to ulonglong integer holding microseconds for storage.
    This is used for handling long_query_time
*/

bool sys_var_microseconds::update(THD *thd, set_var *var)
{
  double num= var->value->val_real();
  longlong microseconds;
  if (num > (double) option_limits->max_value)
    num= (double) option_limits->max_value;
  if (num < (double) option_limits->min_value)
    num= (double) option_limits->min_value;
  microseconds= (longlong) (num * 1000000.0 + 0.5);
  if (var->type == OPT_GLOBAL)
  {
    pthread_mutex_lock(&LOCK_global_system_variables);
    (global_system_variables.*offset)= microseconds;
    pthread_mutex_unlock(&LOCK_global_system_variables);
  }
  else
    thd->variables.*offset= microseconds;
  return 0;
}


void sys_var_microseconds::set_default(THD *thd, enum_var_type type)
{
  longlong microseconds= (longlong) (option_limits->def_value * 1000000.0);
  if (type == OPT_GLOBAL)
  {
    pthread_mutex_lock(&LOCK_global_system_variables);
    global_system_variables.*offset= microseconds;
    pthread_mutex_unlock(&LOCK_global_system_variables);
  }
  else
    thd->variables.*offset= microseconds;
}


uchar *sys_var_microseconds::value_ptr(THD *thd, enum_var_type type,
                                          LEX_STRING *base)
{
  thd->tmp_double_value= (double) ((type == OPT_GLOBAL) ?
                                   global_system_variables.*offset :
                                   thd->variables.*offset) / 1000000.0;
  return (uchar*) &thd->tmp_double_value;
}


unknown's avatar
unknown committed
3136 3137 3138 3139 3140 3141
/*
  Functions to update thd->options bits
*/

static bool set_option_bit(THD *thd, set_var *var)
{
3142 3143 3144
  sys_var_thd_bit *sys_var= ((sys_var_thd_bit*) var->var);
  if ((var->save_result.ulong_value != 0) == sys_var->reverse)
    thd->options&= ~sys_var->bit_flag;
unknown's avatar
unknown committed
3145
  else
3146
    thd->options|= sys_var->bit_flag;
unknown's avatar
unknown committed
3147 3148 3149
  return 0;
}

3150 3151 3152 3153 3154 3155 3156 3157 3158 3159
/*
  Functions to be only used to update thd->options OPTION_BIN_LOG bit
*/
static bool set_option_log_bin_bit(THD *thd, set_var *var)
{
  set_option_bit(thd, var);
  if (!thd->in_sub_stmt)
    thd->sql_log_bin_toplevel= thd->options & OPTION_BIN_LOG;
  return 0;
}
unknown's avatar
unknown committed
3160 3161 3162 3163 3164

static bool set_option_autocommit(THD *thd, set_var *var)
{
  /* The test is negative as the flag we use is NOT autocommit */

3165
  ulonglong org_options= thd->options;
unknown's avatar
unknown committed
3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176

  if (var->save_result.ulong_value != 0)
    thd->options&= ~((sys_var_thd_bit*) var->var)->bit_flag;
  else
    thd->options|= ((sys_var_thd_bit*) var->var)->bit_flag;

  if ((org_options ^ thd->options) & OPTION_NOT_AUTOCOMMIT)
  {
    if ((org_options & OPTION_NOT_AUTOCOMMIT))
    {
      /* We changed to auto_commit mode */
unknown's avatar
unknown committed
3177
      thd->options&= ~(ulonglong) (OPTION_BEGIN | OPTION_KEEP_LOG);
unknown's avatar
unknown committed
3178
      thd->transaction.all.modified_non_trans_table= FALSE;
unknown's avatar
unknown committed
3179 3180 3181 3182 3183 3184
      thd->server_status|= SERVER_STATUS_AUTOCOMMIT;
      if (ha_commit(thd))
	return 1;
    }
    else
    {
unknown's avatar
unknown committed
3185
      thd->transaction.all.modified_non_trans_table= FALSE;
unknown's avatar
unknown committed
3186 3187 3188 3189 3190 3191
      thd->server_status&= ~SERVER_STATUS_AUTOCOMMIT;
    }
  }
  return 0;
}

3192 3193 3194
static int check_log_update(THD *thd, set_var *var)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
3195
  if (!(thd->security_ctx->master_access & SUPER_ACL))
3196 3197 3198 3199 3200 3201 3202
  {
    my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
    return 1;
  }
#endif
  return 0;
}
unknown's avatar
unknown committed
3203 3204 3205

static bool set_log_update(THD *thd, set_var *var)
{
3206 3207 3208 3209 3210
  /*
    The update log is not supported anymore since 5.0.
    See sql/mysqld.cc/, comments in function init_server_components() for an
    explaination of the different warnings we send below
  */
3211

unknown's avatar
unknown committed
3212
  if (opt_sql_bin_update)
3213 3214 3215 3216 3217 3218 3219 3220 3221
  {
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
                 ER_UPDATE_LOG_DEPRECATED_TRANSLATED,
                 ER(ER_UPDATE_LOG_DEPRECATED_TRANSLATED));
  }
  else
    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
                 ER_UPDATE_LOG_DEPRECATED_IGNORED,
                 ER(ER_UPDATE_LOG_DEPRECATED_IGNORED));
unknown's avatar
unknown committed
3222 3223 3224 3225 3226
  set_option_bit(thd, var);
  return 0;
}


3227 3228 3229 3230
static int check_pseudo_thread_id(THD *thd, set_var *var)
{
  var->save_result.ulonglong_value= var->value->val_int();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
3231
  if (thd->security_ctx->master_access & SUPER_ACL)
3232 3233 3234 3235 3236 3237 3238 3239 3240 3241
    return 0;
  else
  {
    my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
    return 1;
  }
#else
  return 0;
#endif
}
3242

3243
static uchar *get_warning_count(THD *thd)
3244 3245 3246
{
  thd->sys_var_tmp.long_value=
    (thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_NOTE] +
3247
     thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR] +
3248
     thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_WARN]);
3249
  return (uchar*) &thd->sys_var_tmp.long_value;
3250 3251
}

3252
static uchar *get_error_count(THD *thd)
3253 3254 3255
{
  thd->sys_var_tmp.long_value= 
    thd->warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR];
3256
  return (uchar*) &thd->sys_var_tmp.long_value;
3257 3258
}

3259

unknown's avatar
unknown committed
3260 3261
/**
  Get the tmpdir that was specified or chosen by default.
3262

unknown's avatar
unknown committed
3263 3264 3265 3266 3267
  This is necessary because if the user does not specify a temporary
  directory via the command line, one is chosen based on the environment
  or system defaults.  But we can't just always use mysql_tmpdir, because
  that is actually a call to my_tmpdir() which cycles among possible
  temporary directories.
3268

unknown's avatar
unknown committed
3269
  @param thd		thread handle
3270

unknown's avatar
unknown committed
3271
  @retval
3272
    ptr		pointer to NUL-terminated string
unknown's avatar
unknown committed
3273
*/
3274
static uchar *get_tmpdir(THD *thd)
3275 3276
{
  if (opt_mysql_tmpdir)
3277 3278
    return (uchar *)opt_mysql_tmpdir;
  return (uchar*)mysql_tmpdir;
3279 3280
}

unknown's avatar
unknown committed
3281 3282 3283 3284 3285 3286 3287
/****************************************************************************
  Main handling of variables:
  - Initialisation
  - Searching during parsing
  - Update loop
****************************************************************************/

unknown's avatar
unknown committed
3288 3289 3290
/**
  Find variable name in option my_getopt structure used for
  command line args.
unknown's avatar
unknown committed
3291

unknown's avatar
unknown committed
3292 3293
  @param opt	option structure array to search in
  @param name	variable name
unknown's avatar
unknown committed
3294

unknown's avatar
unknown committed
3295
  @retval
unknown's avatar
unknown committed
3296
    0		Error
unknown's avatar
unknown committed
3297
  @retval
unknown's avatar
unknown committed
3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319
    ptr		pointer to option structure
*/

static struct my_option *find_option(struct my_option *opt, const char *name) 
{
  uint length=strlen(name);
  for (; opt->name; opt++)
  {
    if (!getopt_compare_strings(opt->name, name, length) &&
	!opt->name[length])
    {
      /*
	Only accept the option if one can set values through it.
	If not, there is no default value or limits in the option.
      */
      return (opt->value) ? opt : 0;
    }
  }
  return 0;
}


unknown's avatar
unknown committed
3320 3321
/**
  Return variable name and length for hashing of variables.
unknown's avatar
unknown committed
3322 3323
*/

3324 3325
static uchar *get_sys_var_length(const sys_var *var, size_t *length,
                                 my_bool first)
unknown's avatar
unknown committed
3326 3327
{
  *length= var->name_length;
3328
  return (uchar*) var->name;
unknown's avatar
unknown committed
3329 3330 3331 3332
}


/*
unknown's avatar
unknown committed
3333 3334 3335 3336 3337 3338 3339 3340 3341 3342
  Add variables to the dynamic hash of system variables
  
  SYNOPSIS
    mysql_add_sys_var_chain()
    first       Pointer to first system variable to add
    long_opt    (optional)command line arguments may be tied for limit checks.
  
  RETURN VALUES
    0           SUCCESS
    otherwise   FAILURE
unknown's avatar
unknown committed
3343 3344 3345
*/


unknown's avatar
unknown committed
3346
int mysql_add_sys_var_chain(sys_var *first, struct my_option *long_options)
unknown's avatar
unknown committed
3347
{
3348
  sys_var *var;
unknown's avatar
unknown committed
3349 3350 3351 3352
  
  /* A write lock should be held on LOCK_system_variables_hash */
  
  for (var= first; var; var= var->next)
unknown's avatar
unknown committed
3353
  {
3354
    var->name_length= strlen(var->name);
unknown's avatar
unknown committed
3355
    /* this fails if there is a conflicting variable name. see HASH_UNIQUE */
3356
    if (my_hash_insert(&system_variable_hash, (uchar*) var))
unknown's avatar
unknown committed
3357 3358 3359
      goto error;
    if (long_options)
      var->option_limits= find_option(long_options, var->name);
unknown's avatar
unknown committed
3360
  }
unknown's avatar
unknown committed
3361 3362 3363 3364
  return 0;

error:
  for (; first != var; first= first->next)
3365
    hash_delete(&system_variable_hash, (uchar*) first);
unknown's avatar
unknown committed
3366 3367
  return 1;
}
3368 3369
 
 
unknown's avatar
unknown committed
3370 3371
/*
  Remove variables to the dynamic hash of system variables
3372
   
unknown's avatar
unknown committed
3373 3374 3375
  SYNOPSIS
    mysql_del_sys_var_chain()
    first       Pointer to first system variable to remove
3376
   
unknown's avatar
unknown committed
3377 3378 3379 3380
  RETURN VALUES
    0           SUCCESS
    otherwise   FAILURE
*/
3381
 
unknown's avatar
unknown committed
3382 3383 3384
int mysql_del_sys_var_chain(sys_var *first)
{
  int result= 0;
3385
 
unknown's avatar
unknown committed
3386
  /* A write lock should be held on LOCK_system_variables_hash */
3387
   
unknown's avatar
unknown committed
3388
  for (sys_var *var= first; var; var= var->next)
3389
    result|= hash_delete(&system_variable_hash, (uchar*) var);
unknown's avatar
unknown committed
3390 3391 3392

  return result;
}
3393 3394
 
 
unknown's avatar
unknown committed
3395 3396 3397 3398
static int show_cmp(SHOW_VAR *a, SHOW_VAR *b)
{
  return strcmp(a->name, b->name);
}
3399 3400
 
 
unknown's avatar
unknown committed
3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416
/*
  Constructs an array of system variables for display to the user.
  
  SYNOPSIS
    enumerate_sys_vars()
    thd         current thread
    sorted      If TRUE, the system variables should be sorted
  
  RETURN VALUES
    pointer     Array of SHOW_VAR elements for display
    NULL        FAILURE
*/

SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted)
{
  int count= system_variable_hash.records, i;
3417
  int size= sizeof(SHOW_VAR) * (count + 1);
unknown's avatar
unknown committed
3418 3419 3420 3421
  SHOW_VAR *result= (SHOW_VAR*) thd->alloc(size);

  if (result)
  {
3422
    SHOW_VAR *show= result;
unknown's avatar
unknown committed
3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434

    for (i= 0; i < count; i++)
    {
      sys_var *var= (sys_var*) hash_element(&system_variable_hash, i);
      show->name= var->name;
      show->value= (char*) var;
      show->type= SHOW_SYS;
      show++;
    }

    /* sort into order */
    if (sorted)
3435
      my_qsort(result, count, sizeof(SHOW_VAR),
3436
               (qsort_cmp) show_cmp);
unknown's avatar
unknown committed
3437 3438 3439
    
    /* make last element empty */
    bzero(show, sizeof(SHOW_VAR));
unknown's avatar
unknown committed
3440
  }
unknown's avatar
unknown committed
3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460
  return result;
}


/*
  Initialize the system variables
  
  SYNOPSIS
    set_var_init()
  
  RETURN VALUES
    0           SUCCESS
    otherwise   FAILURE
*/

int set_var_init()
{
  uint count= 0;
  DBUG_ENTER("set_var_init");
  
3461
  for (sys_var *var=vars.first; var; var= var->next, count++) ;
unknown's avatar
unknown committed
3462 3463 3464 3465 3466 3467 3468 3469 3470

  if (hash_init(&system_variable_hash, system_charset_info, count, 0,
                0, (hash_get_key) get_sys_var_length, 0, HASH_UNIQUE))
    goto error;

  vars.last->next= NULL;
  if (mysql_add_sys_var_chain(vars.first, my_long_options))
    goto error;

unknown's avatar
unknown committed
3471 3472 3473 3474 3475 3476 3477
  /*
    Special cases
    Needed because MySQL can't find the limits for a variable it it has
    a different name than the command line option.
    As these variables are deprecated, this code will disappear soon...
  */
  sys_sql_max_join_size.option_limits= sys_max_join_size.option_limits;
unknown's avatar
unknown committed
3478 3479 3480 3481 3482 3483

  DBUG_RETURN(0);

error:
  fprintf(stderr, "failed to initialize system variables");
  DBUG_RETURN(1);
unknown's avatar
unknown committed
3484 3485 3486 3487 3488 3489 3490 3491 3492
}


void set_var_free()
{
  hash_free(&system_variable_hash);
}


unknown's avatar
unknown committed
3493 3494
/**
  Find a user set-table variable.
unknown's avatar
unknown committed
3495

unknown's avatar
unknown committed
3496 3497 3498 3499
  @param str	   Name of system variable to find
  @param length    Length of variable.  zero means that we should use strlen()
                   on the variable
  @param no_error  Refuse to emit an error, even if one occurred.
unknown's avatar
unknown committed
3500

unknown's avatar
unknown committed
3501
  @retval
unknown's avatar
unknown committed
3502
    pointer	pointer to variable definitions
unknown's avatar
unknown committed
3503
  @retval
unknown's avatar
unknown committed
3504 3505 3506
    0		Unknown variable (error message is given)
*/

unknown's avatar
unknown committed
3507
sys_var *intern_find_sys_var(const char *str, uint length, bool no_error)
unknown's avatar
unknown committed
3508
{
unknown's avatar
unknown committed
3509 3510 3511 3512 3513 3514 3515
  sys_var *var;

  /*
    This function is only called from the sql_plugin.cc.
    A lock on LOCK_system_variable_hash should be held
  */
  var= (sys_var*) hash_search(&system_variable_hash,
3516
			      (uchar*) str, length ? length : strlen(str));
unknown's avatar
unknown committed
3517
  if (!(var || no_error))
3518
    my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
unknown's avatar
unknown committed
3519

unknown's avatar
unknown committed
3520 3521 3522 3523
  return var;
}


unknown's avatar
unknown committed
3524 3525
/**
  Execute update of all variables.
unknown's avatar
unknown committed
3526

unknown's avatar
unknown committed
3527 3528
  First run a check of all variables that all updates will go ok.
  If yes, then execute all updates, returning an error if any one failed.
unknown's avatar
unknown committed
3529

unknown's avatar
unknown committed
3530 3531
  This should ensure that in all normal cases none all or variables are
  updated.
unknown's avatar
unknown committed
3532

unknown's avatar
unknown committed
3533 3534
  @param THD		Thread id
  @param var_list       List of variables to update
unknown's avatar
unknown committed
3535

unknown's avatar
unknown committed
3536
  @retval
unknown's avatar
unknown committed
3537
    0	ok
unknown's avatar
unknown committed
3538
  @retval
3539
    1	ERROR, message sent (normally no variables was updated)
unknown's avatar
unknown committed
3540
  @retval
3541
    -1  ERROR, message not sent
unknown's avatar
unknown committed
3542 3543
*/

3544
int sql_set_variables(THD *thd, List<set_var_base> *var_list)
unknown's avatar
unknown committed
3545
{
unknown's avatar
unknown committed
3546
  int error;
unknown's avatar
unknown committed
3547
  List_iterator_fast<set_var_base> it(*var_list);
unknown's avatar
unknown committed
3548
  DBUG_ENTER("sql_set_variables");
unknown's avatar
unknown committed
3549 3550 3551 3552

  set_var_base *var;
  while ((var=it++))
  {
unknown's avatar
unknown committed
3553
    if ((error= var->check(thd)))
3554
      goto err;
unknown's avatar
unknown committed
3555
  }
3556
  if (!(error= test(thd->is_error())))
3557 3558 3559 3560 3561
  {
    it.rewind();
    while ((var= it++))
      error|= var->update(thd);         // Returns 0, -1 or 1
  }
unknown's avatar
unknown committed
3562

3563 3564
err:
  free_underlaid_joins(thd, &thd->lex->select_lex);
unknown's avatar
unknown committed
3565
  DBUG_RETURN(error);
unknown's avatar
unknown committed
3566 3567 3568
}


unknown's avatar
unknown committed
3569 3570 3571 3572
/**
  Say if all variables set by a SET support the ONE_SHOT keyword
  (currently, only character set and collation do; later timezones
  will).
3573

unknown's avatar
unknown committed
3574
  @param var_list	List of variables to update
3575

unknown's avatar
unknown committed
3576
  @note
3577 3578
    It has a "not_" because it makes faster tests (no need to "!")

unknown's avatar
unknown committed
3579
  @retval
3580
    0	all variables of the list support ONE_SHOT
unknown's avatar
unknown committed
3581
  @retval
3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597
    1	at least one does not support ONE_SHOT
*/

bool not_all_support_one_shot(List<set_var_base> *var_list)
{
  List_iterator_fast<set_var_base> it(*var_list);
  set_var_base *var;
  while ((var= it++))
  {
    if (var->no_support_one_shot())
      return 1;
  }
  return 0;
}


unknown's avatar
unknown committed
3598 3599 3600 3601
/*****************************************************************************
  Functions to handle SET mysql_internal_variable=const_expr
*****************************************************************************/

3602
int set_var::check(THD *thd)
unknown's avatar
unknown committed
3603
{
3604 3605 3606 3607 3608
  if (var->is_readonly())
  {
    my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), var->name, "read only");
    return -1;
  }
unknown's avatar
unknown committed
3609 3610
  if (var->check_type(type))
  {
unknown's avatar
unknown committed
3611
    int err= type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE;
3612
    my_error(err, MYF(0), var->name);
3613
    return -1;
unknown's avatar
unknown committed
3614 3615 3616 3617 3618 3619 3620 3621
  }
  if ((type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL)))
    return 1;
  /* value is a NULL pointer if we are using SET ... = DEFAULT */
  if (!value)
  {
    if (var->check_default(type))
    {
3622
      my_error(ER_NO_DEFAULT, MYF(0), var->name);
3623
      return -1;
unknown's avatar
unknown committed
3624 3625 3626 3627
    }
    return 0;
  }

unknown's avatar
unknown committed
3628
  if ((!value->fixed &&
3629
       value->fix_fields(thd, &value)) || value->check_cols(1))
3630
    return -1;
unknown's avatar
unknown committed
3631 3632
  if (var->check_update_type(value->result_type()))
  {
3633
    my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), var->name);
3634
    return -1;
3635
  }
3636
  return var->check(thd, this) ? -1 : 0;
unknown's avatar
unknown committed
3637 3638 3639
}


unknown's avatar
unknown committed
3640 3641
/**
  Check variable, but without assigning value (used by PS).
unknown's avatar
unknown committed
3642

unknown's avatar
unknown committed
3643
  @param thd		thread handler
unknown's avatar
unknown committed
3644

unknown's avatar
unknown committed
3645
  @retval
unknown's avatar
unknown committed
3646
    0	ok
unknown's avatar
unknown committed
3647
  @retval
unknown's avatar
unknown committed
3648
    1	ERROR, message sent (normally no variables was updated)
unknown's avatar
unknown committed
3649 3650
  @retval
    -1   ERROR, message not sent
unknown's avatar
unknown committed
3651
*/
3652 3653 3654 3655
int set_var::light_check(THD *thd)
{
  if (var->check_type(type))
  {
unknown's avatar
unknown committed
3656
    int err= type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE;
3657
    my_error(err, MYF(0), var->name);
3658 3659
    return -1;
  }
unknown's avatar
unknown committed
3660
  if (type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL))
3661 3662
    return 1;

3663
  if (value && ((!value->fixed && value->fix_fields(thd, &value)) ||
unknown's avatar
unknown committed
3664
                value->check_cols(1)))
3665 3666 3667 3668
    return -1;
  return 0;
}

3669 3670
/**
  Update variable
3671

3672 3673 3674 3675 3676 3677 3678 3679 3680
  @param   thd    thread handler
  @returns 0|1    ok or	ERROR

  @note ERROR can be only due to abnormal operations involving
  the server's execution evironment such as
  out of memory, hard disk failure or the computer blows up.
  Consider set_var::check() method if there is a need to return
  an error due to logics.
*/
3681
int set_var::update(THD *thd)
unknown's avatar
unknown committed
3682 3683 3684 3685
{
  if (!value)
    var->set_default(thd, type);
  else if (var->update(thd, this))
3686
    return -1;				// should never happen
unknown's avatar
unknown committed
3687 3688 3689 3690 3691 3692 3693 3694 3695 3696
  if (var->after_update)
    (*var->after_update)(thd, type);
  return 0;
}


/*****************************************************************************
  Functions to handle SET @user_variable=const_expr
*****************************************************************************/

3697
int set_var_user::check(THD *thd)
unknown's avatar
unknown committed
3698
{
unknown's avatar
unknown committed
3699 3700
  /*
    Item_func_set_user_var can't substitute something else on its place =>
3701
    0 can be passed as last argument (reference on item)
unknown's avatar
unknown committed
3702
  */
3703
  return (user_var_item->fix_fields(thd, (Item**) 0) ||
3704
	  user_var_item->check(0)) ? -1 : 0;
unknown's avatar
unknown committed
3705 3706 3707
}


unknown's avatar
unknown committed
3708 3709
/**
  Check variable, but without assigning value (used by PS).
unknown's avatar
unknown committed
3710

unknown's avatar
unknown committed
3711
  @param thd		thread handler
unknown's avatar
unknown committed
3712

unknown's avatar
unknown committed
3713
  @retval
unknown's avatar
unknown committed
3714
    0	ok
unknown's avatar
unknown committed
3715
  @retval
unknown's avatar
unknown committed
3716
    1	ERROR, message sent (normally no variables was updated)
unknown's avatar
unknown committed
3717 3718
  @retval
    -1   ERROR, message not sent
unknown's avatar
unknown committed
3719
*/
3720 3721 3722 3723 3724 3725
int set_var_user::light_check(THD *thd)
{
  /*
    Item_func_set_user_var can't substitute something else on its place =>
    0 can be passed as last argument (reference on item)
  */
3726
  return (user_var_item->fix_fields(thd, (Item**) 0));
3727 3728 3729
}


3730
int set_var_user::update(THD *thd)
unknown's avatar
unknown committed
3731 3732 3733 3734
{
  if (user_var_item->update())
  {
    /* Give an error if it's not given already */
unknown's avatar
unknown committed
3735
    my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY), MYF(0));
3736
    return -1;
unknown's avatar
unknown committed
3737 3738 3739 3740 3741 3742 3743 3744 3745
  }
  return 0;
}


/*****************************************************************************
  Functions to handle SET PASSWORD
*****************************************************************************/

3746
int set_var_password::check(THD *thd)
unknown's avatar
unknown committed
3747
{
unknown's avatar
unknown committed
3748
#ifndef NO_EMBEDDED_ACCESS_CHECKS
unknown's avatar
unknown committed
3749
  if (!user->host.str)
3750
  {
3751
    DBUG_ASSERT(thd->security_ctx->priv_host);
3752
    if (*thd->security_ctx->priv_host != 0)
3753
    {
3754 3755
      user->host.str= (char *) thd->security_ctx->priv_host;
      user->host.length= strlen(thd->security_ctx->priv_host);
3756 3757 3758 3759 3760 3761 3762
    }
    else
    {
      user->host.str= (char *)"%";
      user->host.length= 1;
    }
  }
3763 3764 3765 3766 3767 3768
  if (!user->user.str)
  {
    DBUG_ASSERT(thd->security_ctx->priv_user);
    user->user.str= (char *) thd->security_ctx->priv_user;
    user->user.length= strlen(thd->security_ctx->priv_user);
  }
3769
  /* Returns 1 as the function sends error to client */
3770 3771
  return check_change_password(thd, user->host.str, user->user.str,
                               password, strlen(password)) ? 1 : 0;
3772
#else
unknown's avatar
unknown committed
3773 3774
  return 0;
#endif
unknown's avatar
unknown committed
3775 3776
}

3777
int set_var_password::update(THD *thd)
unknown's avatar
unknown committed
3778
{
unknown's avatar
unknown committed
3779
#ifndef NO_EMBEDDED_ACCESS_CHECKS
3780
  /* Returns 1 as the function sends error to client */
3781 3782
  return change_password(thd, user->host.str, user->user.str, password) ?
	  1 : 0;
unknown's avatar
unknown committed
3783 3784 3785
#else
  return 0;
#endif
unknown's avatar
unknown committed
3786 3787
}

3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805
/****************************************************************************
 Functions to handle log_slow_filter
****************************************************************************/
  
/* Ensure that the proper bits are set for easy test of logging */
static void fix_sys_log_slow_filter(THD *thd, enum_var_type type)
{
  /* Maintain everything with filters */
  opt_log_slow_admin_statements= 1;
  if (type == OPT_GLOBAL)
    global_system_variables.log_slow_filter=
      fix_log_slow_filter(global_system_variables.log_slow_filter);
  else
    thd->variables.log_slow_filter=
      fix_log_slow_filter(thd->variables.log_slow_filter);
}


3806 3807 3808 3809
/****************************************************************************
 Functions to handle table_type
****************************************************************************/

unknown's avatar
unknown committed
3810 3811
/* Based upon sys_var::check_enum() */

unknown's avatar
unknown committed
3812
bool sys_var_thd_storage_engine::check(THD *thd, set_var *var)
3813
{
unknown's avatar
unknown committed
3814
  char buff[STRING_BUFFER_USUAL_SIZE];
3815
  const char *value;
3816
  String str(buff, sizeof(buff) - 1, &my_charset_latin1), *res;
3817

unknown's avatar
unknown committed
3818
  var->save_result.plugin= NULL;
3819 3820
  if (var->value->result_type() == STRING_RESULT)
  {
3821
    LEX_STRING engine_name;
unknown's avatar
unknown committed
3822
    handlerton *hton;
3823
    if (!(res=var->value->val_str(&str)) ||
3824 3825 3826
        !(engine_name.str= (char *)res->ptr()) ||
        !(engine_name.length= res->length()) ||
	!(var->save_result.plugin= ha_resolve_by_name(thd, &engine_name)) ||
unknown's avatar
unknown committed
3827 3828
        !(hton= plugin_data(var->save_result.plugin, handlerton *)) ||
        ha_checktype(thd, ha_legacy_type(hton), 1, 0) != hton)
3829 3830 3831 3832 3833 3834
    {
      value= res ? res->c_ptr() : "NULL";
      goto err;
    }
    return 0;
  }
unknown's avatar
unknown committed
3835
  value= "unknown";
3836 3837

err:
3838
  my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), value);
unknown's avatar
unknown committed
3839
  return 1;
3840 3841
}

unknown's avatar
unknown committed
3842

3843
uchar *sys_var_thd_storage_engine::value_ptr(THD *thd, enum_var_type type,
unknown's avatar
unknown committed
3844
					    LEX_STRING *base)
3845
{
3846
  uchar* result;
unknown's avatar
unknown committed
3847
  handlerton *hton;
3848
  LEX_STRING *engine_name;
unknown's avatar
unknown committed
3849 3850 3851 3852
  plugin_ref plugin= thd->variables.*offset;
  if (type == OPT_GLOBAL)
    plugin= my_plugin_lock(thd, &(global_system_variables.*offset));
  hton= plugin_data(plugin, handlerton*);
3853
  engine_name= hton_name(hton);
3854
  result= (uchar *) thd->strmake(engine_name->str, engine_name->length);
unknown's avatar
unknown committed
3855 3856 3857
  if (type == OPT_GLOBAL)
    plugin_unlock(thd, plugin);
  return result;
3858 3859
}

unknown's avatar
unknown committed
3860

unknown's avatar
unknown committed
3861
void sys_var_thd_storage_engine::set_default(THD *thd, enum_var_type type)
3862
{
unknown's avatar
unknown committed
3863
  plugin_ref old_value, new_value, *value;
3864
  if (type == OPT_GLOBAL)
unknown's avatar
unknown committed
3865 3866 3867 3868
  {
    value= &(global_system_variables.*offset);
    new_value= ha_lock_engine(NULL, myisam_hton);
  }
3869
  else
unknown's avatar
unknown committed
3870 3871 3872 3873 3874 3875 3876 3877
  {
    value= &(thd->variables.*offset);
    new_value= my_plugin_lock(NULL, &(global_system_variables.*offset));
  }
  DBUG_ASSERT(new_value);
  old_value= *value;
  *value= new_value;
  plugin_unlock(NULL, old_value);
3878 3879
}

unknown's avatar
unknown committed
3880

unknown's avatar
unknown committed
3881
bool sys_var_thd_storage_engine::update(THD *thd, set_var *var)
3882
{
unknown's avatar
unknown committed
3883 3884 3885 3886 3887 3888 3889 3890 3891
  plugin_ref *value= &(global_system_variables.*offset), old_value;
   if (var->type != OPT_GLOBAL)
     value= &(thd->variables.*offset);
  old_value= *value;
  if (old_value != var->save_result.plugin)
  {
    *value= my_plugin_lock(NULL, &var->save_result.plugin);
    plugin_unlock(NULL, old_value);
  }
3892 3893 3894
  return 0;
}

unknown's avatar
unknown committed
3895 3896
void sys_var_thd_table_type::warn_deprecated(THD *thd)
{
3897
  WARN_DEPRECATED(thd, "6.0", "@@table_type", "'@@storage_engine'");
unknown's avatar
unknown committed
3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911
}

void sys_var_thd_table_type::set_default(THD *thd, enum_var_type type)
{
  warn_deprecated(thd);
  sys_var_thd_storage_engine::set_default(thd, type);
}

bool sys_var_thd_table_type::update(THD *thd, set_var *var)
{
  warn_deprecated(thd);
  return sys_var_thd_storage_engine::update(thd, var);
}

unknown's avatar
unknown committed
3912

3913 3914 3915
/****************************************************************************
 Functions to handle sql_mode
****************************************************************************/
3916

3917 3918 3919 3920 3921 3922
void fix_sql_mode_var(THD *thd, enum_var_type type)
{
  if (type == OPT_GLOBAL)
    global_system_variables.sql_mode=
      fix_sql_mode(global_system_variables.sql_mode);
  else
3923
  {
3924
    thd->variables.sql_mode= fix_sql_mode(thd->variables.sql_mode);
3925 3926 3927 3928 3929 3930 3931 3932
    /*
      Update thd->server_status
     */
    if (thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)
      thd->server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES;
    else
      thd->server_status&= ~SERVER_STATUS_NO_BACKSLASH_ESCAPES;
  }
3933 3934
}

unknown's avatar
unknown committed
3935
/** Map database specific bits to function bits. */
3936

3937 3938 3939 3940 3941 3942 3943 3944 3945
ulong fix_sql_mode(ulong sql_mode)
{
  /*
    Note that we dont set 
    MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | MODE_NO_FIELD_OPTIONS
    to allow one to get full use of MySQL in this mode.
  */

  if (sql_mode & MODE_ANSI)
3946
  {
3947
    sql_mode|= (MODE_REAL_AS_FLOAT | MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
3948 3949 3950 3951 3952 3953
		MODE_IGNORE_SPACE);
    /* 
      MODE_ONLY_FULL_GROUP_BY removed from ANSI mode because it is currently
      overly restrictive (see BUG#8510).
    */
  }
3954 3955 3956 3957
  if (sql_mode & MODE_ORACLE)
    sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
		MODE_IGNORE_SPACE |
		MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
3958
		MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER);
3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973
  if (sql_mode & MODE_MSSQL)
    sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
		MODE_IGNORE_SPACE |
		MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
		MODE_NO_FIELD_OPTIONS);
  if (sql_mode & MODE_POSTGRESQL)
    sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
		MODE_IGNORE_SPACE |
		MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
		MODE_NO_FIELD_OPTIONS);
  if (sql_mode & MODE_DB2)
    sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
		MODE_IGNORE_SPACE |
		MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
		MODE_NO_FIELD_OPTIONS);
3974
  if (sql_mode & MODE_MAXDB)
3975 3976 3977
    sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
		MODE_IGNORE_SPACE |
		MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
3978
		MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER);
3979
  if (sql_mode & MODE_MYSQL40)
3980
    sql_mode|= MODE_HIGH_NOT_PRECEDENCE;
3981
  if (sql_mode & MODE_MYSQL323)
3982
    sql_mode|= MODE_HIGH_NOT_PRECEDENCE;
unknown's avatar
unknown committed
3983 3984 3985
  if (sql_mode & MODE_TRADITIONAL)
    sql_mode|= (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES |
                MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
3986
                MODE_ERROR_FOR_DIVISION_BY_ZERO | MODE_NO_AUTO_CREATE_USER);
3987 3988
  return sql_mode;
}
3989 3990


3991 3992 3993 3994 3995 3996
bool
sys_var_thd_optimizer_switch::
symbolic_mode_representation(THD *thd, ulonglong val, LEX_STRING *rep)
{
  char buff[STRING_BUFFER_USUAL_SIZE*8];
  String tmp(buff, sizeof(buff), &my_charset_latin1);
3997 3998
  int i;
  ulonglong bit;
3999
  tmp.length(0);
4000 4001
 
  for (i= 0, bit=1; bit != OPTIMIZER_SWITCH_LAST; i++, bit= bit << 1)
4002
  {
4003 4004 4005 4006 4007
    tmp.append(optimizer_switch_typelib.type_names[i],
               optimizer_switch_typelib.type_lengths[i]);
    tmp.append('=');
    tmp.append((val & bit)? "on":"off");
    tmp.append(',');
4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031
  }

  if (tmp.length())
    tmp.length(tmp.length() - 1); /* trim the trailing comma */

  rep->str= thd->strmake(tmp.ptr(), tmp.length());

  rep->length= rep->str ? tmp.length() : 0;

  return rep->length != tmp.length();
}


uchar *sys_var_thd_optimizer_switch::value_ptr(THD *thd, enum_var_type type,
				               LEX_STRING *base)
{
  LEX_STRING opts;
  ulonglong val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
                  thd->variables.*offset);
  (void) symbolic_mode_representation(thd, val, &opts);
  return (uchar *) opts.str;
}


4032 4033 4034 4035 4036
/*
  Check (and actually parse) string representation of @@optimizer_switch.
*/

bool sys_var_thd_optimizer_switch::check(THD *thd, set_var *var)
4037
{
4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059
  bool not_used;
  char buff[STRING_BUFFER_USUAL_SIZE], *error= 0;
  uint error_len= 0;
  String str(buff, sizeof(buff), system_charset_info), *res;

  if (!(res= var->value->val_str(&str)))
  {
    strmov(buff, "NULL");
    goto err;
  }
  
  if (res->length() == 0)
  {
    buff[0]= 0;
    goto err;
  }

  var->save_result.ulong_value= 
    (ulong)find_set_from_flags(&optimizer_switch_typelib, 
                               optimizer_switch_typelib.count, 
                               thd->variables.optimizer_switch,
                               global_system_variables.optimizer_switch,
4060
                               res->c_ptr_safe(), res->length(), NULL,
4061 4062 4063 4064 4065 4066 4067 4068 4069 4070
                               &error, &error_len, &not_used);
  if (error_len)
  {
    strmake(buff, error, min(sizeof(buff) - 1, error_len));
    goto err;
  }
  return FALSE;
err:
  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buff);
  return TRUE;
4071 4072 4073
}


4074 4075 4076 4077 4078 4079 4080 4081
void sys_var_thd_optimizer_switch::set_default(THD *thd, enum_var_type type)
{
  if (type == OPT_GLOBAL)
    global_system_variables.*offset= OPTIMIZER_SWITCH_DEFAULT;
  else
    thd->variables.*offset= global_system_variables.*offset;
}

4082 4083 4084 4085
/****************************************************************************
  Named list handling
****************************************************************************/

4086
uchar* find_named(I_List<NAMED_LIST> *list, const char *name, uint length,
unknown's avatar
unknown committed
4087
		NAMED_LIST **found)
4088 4089 4090 4091 4092 4093
{
  I_List_iterator<NAMED_LIST> it(*list);
  NAMED_LIST *element;
  while ((element= it++))
  {
    if (element->cmp(name, length))
unknown's avatar
unknown committed
4094
    {
4095 4096
      if (found)
        *found= element;
4097
      return element->data;
unknown's avatar
unknown committed
4098
    }
4099 4100 4101 4102 4103
  }
  return 0;
}


4104
void delete_elements(I_List<NAMED_LIST> *list,
4105
		     void (*free_element)(const char *name, uchar*))
4106 4107
{
  NAMED_LIST *element;
unknown's avatar
unknown committed
4108
  DBUG_ENTER("delete_elements");
4109 4110
  while ((element= list->get()))
  {
4111
    (*free_element)(element->name, element->data);
4112 4113
    delete element;
  }
unknown's avatar
unknown committed
4114
  DBUG_VOID_RETURN;
4115 4116 4117 4118 4119
}


/* Key cache functions */

unknown's avatar
unknown committed
4120
static KEY_CACHE *create_key_cache(const char *name, uint length)
4121
{
unknown's avatar
unknown committed
4122
  KEY_CACHE *key_cache;
4123 4124 4125
  DBUG_ENTER("create_key_cache");
  DBUG_PRINT("enter",("name: %.*s", length, name));
  
unknown's avatar
unknown committed
4126
  if ((key_cache= (KEY_CACHE*) my_malloc(sizeof(KEY_CACHE),
4127
					     MYF(MY_ZEROFILL | MY_WME))))
unknown's avatar
unknown committed
4128
  {
4129
    if (!new NAMED_LIST(&key_caches, name, length, (uchar*) key_cache))
4130 4131
    {
      my_free((char*) key_cache, MYF(0));
unknown's avatar
unknown committed
4132
      key_cache= 0;
4133 4134 4135 4136 4137 4138 4139 4140 4141
    }
    else
    {
      /*
	Set default values for a key cache
	The values in dflt_key_cache_var is set by my_getopt() at startup

	We don't set 'buff_size' as this is used to enable the key cache
      */
unknown's avatar
unknown committed
4142 4143 4144
      key_cache->param_block_size=     dflt_key_cache_var.param_block_size;
      key_cache->param_division_limit= dflt_key_cache_var.param_division_limit;
      key_cache->param_age_threshold=  dflt_key_cache_var.param_age_threshold;
4145
    }
unknown's avatar
unknown committed
4146
  }
4147
  DBUG_RETURN(key_cache);
4148 4149 4150
}


unknown's avatar
unknown committed
4151
KEY_CACHE *get_or_create_key_cache(const char *name, uint length)
4152
{
unknown's avatar
unknown committed
4153
  LEX_STRING key_cache_name;
unknown's avatar
unknown committed
4154
  KEY_CACHE *key_cache;
4155

unknown's avatar
unknown committed
4156 4157
  key_cache_name.str= (char *) name;
  key_cache_name.length= length;
4158 4159
  pthread_mutex_lock(&LOCK_global_system_variables);
  if (!(key_cache= get_key_cache(&key_cache_name)))
4160
    key_cache= create_key_cache(name, length);
4161
  pthread_mutex_unlock(&LOCK_global_system_variables);
4162 4163 4164 4165
  return key_cache;
}


unknown's avatar
unknown committed
4166
void free_key_cache(const char *name, KEY_CACHE *key_cache)
4167
{
4168 4169
  ha_end_key_cache(key_cache);
  my_free((char*) key_cache, MYF(0));
unknown's avatar
unknown committed
4170 4171 4172
}


4173
bool process_key_caches(process_key_cache_t func)
4174
{
unknown's avatar
unknown committed
4175 4176
  I_List_iterator<NAMED_LIST> it(key_caches);
  NAMED_LIST *element;
4177

unknown's avatar
unknown committed
4178 4179
  while ((element= it++))
  {
unknown's avatar
unknown committed
4180
    KEY_CACHE *key_cache= (KEY_CACHE *) element->data;
4181
    func(element->name, key_cache);
unknown's avatar
unknown committed
4182 4183
  }
  return 0;
4184 4185
}

4186

4187 4188
void sys_var_trust_routine_creators::warn_deprecated(THD *thd)
{
4189
  WARN_DEPRECATED(thd, "6.0", "@@log_bin_trust_routine_creators",
4190
                      "'@@log_bin_trust_function_creators'");
4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204
}

void sys_var_trust_routine_creators::set_default(THD *thd, enum_var_type type)
{
  warn_deprecated(thd);
  sys_var_bool_ptr::set_default(thd, type);
}

bool sys_var_trust_routine_creators::update(THD *thd, set_var *var)
{
  warn_deprecated(thd);
  return sys_var_bool_ptr::update(thd, var);
}

unknown's avatar
unknown committed
4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252
bool sys_var_opt_readonly::update(THD *thd, set_var *var)
{
  bool result;

  DBUG_ENTER("sys_var_opt_readonly::update");

  /* Prevent self dead-lock */
  if (thd->locked_tables || thd->active_transaction())
  {
    my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
    DBUG_RETURN(true);
  }

  if (thd->global_read_lock)
  {
    /*
      This connection already holds the global read lock.
      This can be the case with:
      - FLUSH TABLES WITH READ LOCK
      - SET GLOBAL READ_ONLY = 1
    */
    result= sys_var_bool_ptr::update(thd, var);
    DBUG_RETURN(result);
  }

  /*
    Perform a 'FLUSH TABLES WITH READ LOCK'.
    This is a 3 step process:
    - [1] lock_global_read_lock()
    - [2] close_cached_tables()
    - [3] make_global_read_lock_block_commit()
    [1] prevents new connections from obtaining tables locked for write.
    [2] waits until all existing connections close their tables.
    [3] prevents transactions from being committed.
  */

  if (lock_global_read_lock(thd))
    DBUG_RETURN(true);

  /*
    This call will be blocked by any connection holding a READ or WRITE lock.
    Ideally, we want to wait only for pending WRITE locks, but since:
    con 1> LOCK TABLE T FOR READ;
    con 2> LOCK TABLE T FOR WRITE; (blocked by con 1)
    con 3> SET GLOBAL READ ONLY=1; (blocked by con 2)
    can cause to wait on a read lock, it's required for the client application
    to unlock everything, and acceptable for the server to wait on all locks.
  */
4253
  if ((result= close_cached_tables(thd, NULL, FALSE, TRUE, TRUE)))
unknown's avatar
unknown committed
4254 4255
    goto end_with_read_lock;

4256
  if ((result= make_global_read_lock_block_commit(thd)))
unknown's avatar
unknown committed
4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268
    goto end_with_read_lock;

  /* Change the opt_readonly system variable, safe because the lock is held */
  result= sys_var_bool_ptr::update(thd, var);

end_with_read_lock:
  /* Release the lock */
  unlock_global_read_lock(thd);
  DBUG_RETURN(result);
}


4269
#ifndef DBUG_OFF
unknown's avatar
unknown committed
4270 4271 4272 4273 4274 4275 4276 4277
/* even session variable here requires SUPER, because of -#o,file */
bool sys_var_thd_dbug::check(THD *thd, set_var *var)
{
  return check_global_access(thd, SUPER_ACL);
}

bool sys_var_thd_dbug::update(THD *thd, set_var *var)
{
4278 4279 4280
#ifndef DBUG_OFF
  const char *command= var ? var->value->str_value.c_ptr() : "";

unknown's avatar
unknown committed
4281
  if (var->type == OPT_GLOBAL)
4282
    DBUG_SET_INITIAL(command);
unknown's avatar
unknown committed
4283
  else
4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299
  {
    if (_db_is_pushed_())
    {
      /* We have already a local state done with DBUG_PUSH; Modify the state */
      DBUG_SET(command);
    }
    else
    {
      /*
        We are sharing the state with the global state;
        Create a local state for this thread.
      */
      DBUG_PUSH(command);
    }
  }
#endif
unknown's avatar
unknown committed
4300 4301 4302
  return 0;
}

4303

4304
uchar *sys_var_thd_dbug::value_ptr(THD *thd, enum_var_type type, LEX_STRING *b)
unknown's avatar
unknown committed
4305 4306 4307
{
  char buf[256];
  if (type == OPT_GLOBAL)
4308
  {
unknown's avatar
unknown committed
4309
    DBUG_EXPLAIN_INITIAL(buf, sizeof(buf));
4310
  }
unknown's avatar
unknown committed
4311
  else
4312
  {
unknown's avatar
unknown committed
4313
    DBUG_EXPLAIN(buf, sizeof(buf));
4314
  }
4315
  return (uchar*) thd->strdup(buf);
unknown's avatar
unknown committed
4316
}
4317 4318
#endif /* DBUG_OFF */

unknown's avatar
unknown committed
4319

4320
#ifdef HAVE_EVENT_SCHEDULER
4321 4322 4323 4324 4325
bool sys_var_event_scheduler::check(THD *thd, set_var *var)
{
  return check_enum(thd, var, &Events::var_typelib);
}

4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343
/*
   The update method of the global variable event_scheduler.
   If event_scheduler is switched from 0 to 1 then the scheduler main
   thread is resumed and if from 1 to 0 the scheduler thread is suspended

   SYNOPSIS
     sys_var_event_scheduler::update()
       thd  Thread context (unused)
       var  The new value

   Returns
     FALSE  OK
     TRUE   Error
*/

bool
sys_var_event_scheduler::update(THD *thd, set_var *var)
{
unknown's avatar
unknown committed
4344
  int res;
4345 4346
  /* here start the thread if not running. */
  DBUG_ENTER("sys_var_event_scheduler::update");
unknown's avatar
unknown committed
4347
  DBUG_PRINT("info", ("new_value: %d", (int) var->save_result.ulong_value));
4348

4349 4350 4351 4352
  enum Events::enum_opt_event_scheduler
    new_state=
    (enum Events::enum_opt_event_scheduler) var->save_result.ulong_value;

4353
  res= Events::switch_event_scheduler_state(new_state);
4354 4355 4356 4357 4358

  DBUG_RETURN((bool) res);
}


4359
uchar *sys_var_event_scheduler::value_ptr(THD *thd, enum_var_type type,
4360 4361
                                         LEX_STRING *base)
{
4362
  return (uchar *) Events::get_opt_event_scheduler_str();
4363
}
4364
#endif
4365

unknown's avatar
unknown committed
4366 4367 4368 4369
/****************************************************************************
  Used templates
****************************************************************************/

4370
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
unknown's avatar
unknown committed
4371
template class List<set_var_base>;
unknown's avatar
unknown committed
4372
template class List_iterator_fast<set_var_base>;
4373
template class I_List_iterator<NAMED_LIST>;
unknown's avatar
unknown committed
4374
#endif