MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
set_var.cc
1 /* Copyright (c) 2002, 2013 Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 /* variable declarations are in sys_vars.cc now !!! */
17 
18 #include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
19 #include "sql_class.h" // set_var.h: session_var_ptr
20 #include "set_var.h"
21 #include "sql_priv.h"
22 #include "unireg.h"
23 #include "mysqld.h" // lc_messages_dir
24 #include "sys_vars_shared.h"
25 #include "transaction.h"
26 #include "sql_locale.h" // my_locale_by_number,
27  // my_locale_by_name
28 #include "strfunc.h" // find_set_from_flags, find_set
29 #include "sql_parse.h" // check_global_access
30 #include "sql_table.h" // reassign_keycache_tables
31 #include "sql_time.h" // date_time_format_copy,
32  // date_time_format_make
33 #include "derror.h"
34 #include "tztime.h" // my_tz_find, my_tz_SYSTEM, struct Time_zone
35 #include "sql_acl.h" // SUPER_ACL
36 #include "sql_select.h" // free_underlaid_joins
37 #include "sql_show.h" // make_default_log_name, append_identifier
38 #include "sql_view.h" // updatable_views_with_limit_typelib
39 #include "lock.h" // lock_global_read_lock,
40  // make_global_read_lock_block_commit,
41  // unlock_global_read_lock
42 
43 static HASH system_variable_hash;
44 static PolyLock_mutex PLock_global_system_variables(&LOCK_global_system_variables);
45 
50 static uchar *get_sys_var_length(const sys_var *var, size_t *length,
51  my_bool first)
52 {
53  *length= var->name.length;
54  return (uchar*) var->name.str;
55 }
56 
57 sys_var_chain all_sys_vars = { NULL, NULL };
58 
59 int sys_var_init()
60 {
61  DBUG_ENTER("sys_var_init");
62 
63  /* Must be already initialized. */
64  DBUG_ASSERT(system_charset_info != NULL);
65 
66  if (my_hash_init(&system_variable_hash, system_charset_info, 100, 0,
67  0, (my_hash_get_key) get_sys_var_length, 0, HASH_UNIQUE))
68  goto error;
69 
70  if (mysql_add_sys_var_chain(all_sys_vars.first))
71  goto error;
72 
73  DBUG_RETURN(0);
74 
75 error:
76  fprintf(stderr, "failed to initialize System variables");
77  DBUG_RETURN(1);
78 }
79 
80 int sys_var_add_options(std::vector<my_option> *long_options, int parse_flags)
81 {
82  DBUG_ENTER("sys_var_add_options");
83 
84  for (sys_var *var=all_sys_vars.first; var; var= var->next)
85  {
86  if (var->register_option(long_options, parse_flags))
87  goto error;
88  }
89 
90  DBUG_RETURN(0);
91 
92 error:
93  fprintf(stderr, "failed to initialize System variables");
94  DBUG_RETURN(1);
95 }
96 
97 void sys_var_end()
98 {
99  DBUG_ENTER("sys_var_end");
100 
101  my_hash_free(&system_variable_hash);
102 
103  for (sys_var *var=all_sys_vars.first; var; var= var->next)
104  var->cleanup();
105 
106  DBUG_VOID_RETURN;
107 }
108 
135 sys_var::sys_var(sys_var_chain *chain, const char *name_arg,
136  const char *comment, int flags_arg, ptrdiff_t off,
137  int getopt_id, enum get_opt_arg_type getopt_arg_type,
138  SHOW_TYPE show_val_type_arg, longlong def_val,
139  PolyLock *lock, enum binlog_status_enum binlog_status_arg,
140  on_check_function on_check_func,
141  on_update_function on_update_func,
142  const char *substitute, int parse_flag) :
143  next(0),
144  binlog_status(binlog_status_arg),
145  flags(flags_arg), m_parse_flag(parse_flag), show_val_type(show_val_type_arg),
146  guard(lock), offset(off), on_check(on_check_func), on_update(on_update_func),
147  deprecation_substitute(substitute),
148  is_os_charset(FALSE)
149 {
150  /*
151  There is a limitation in handle_options() related to short options:
152  - either all short options should be declared when parsing in multiple stages,
153  - or none should be declared.
154  Because a lot of short options are used in the normal parsing phase
155  for mysqld, we enforce here that no short option is present
156  in the first (PARSE_EARLY) stage.
157  See handle_options() for details.
158  */
159  DBUG_ASSERT(parse_flag == PARSE_NORMAL || getopt_id <= 0 || getopt_id >= 255);
160 
161  name.str= name_arg; // ER_NO_DEFAULT relies on 0-termination of name_arg
162  name.length= strlen(name_arg); // and so does this.
163  DBUG_ASSERT(name.length <= NAME_CHAR_LEN);
164 
165  memset(&option, 0, sizeof(option));
166  option.name= name_arg;
167  option.id= getopt_id;
168  option.comment= comment;
169  option.arg_type= getopt_arg_type;
170  option.value= (uchar **)global_var_ptr();
171  option.def_value= def_val;
172 
173  if (chain->last)
174  chain->last->next= this;
175  else
176  chain->first= this;
177  chain->last= this;
178 }
179 
180 bool sys_var::update(THD *thd, set_var *var)
181 {
182  enum_var_type type= var->type;
183  if (type == OPT_GLOBAL || scope() == GLOBAL)
184  {
185  /*
186  Yes, both locks need to be taken before an update, just as
187  both are taken to get a value. If we'll take only 'guard' here,
188  then value_ptr() for strings won't be safe in SHOW VARIABLES anymore,
189  to make it safe we'll need value_ptr_unlock().
190  */
191  AutoWLock lock1(&PLock_global_system_variables);
192  AutoWLock lock2(guard);
193  return global_update(thd, var) ||
194  (on_update && on_update(this, thd, OPT_GLOBAL));
195  }
196  else
197  return session_update(thd, var) ||
198  (on_update && on_update(this, thd, OPT_SESSION));
199 }
200 
201 uchar *sys_var::session_value_ptr(THD *thd, LEX_STRING *base)
202 {
203  return session_var_ptr(thd);
204 }
205 
206 uchar *sys_var::global_value_ptr(THD *thd, LEX_STRING *base)
207 {
208  return global_var_ptr();
209 }
210 
211 bool sys_var::check(THD *thd, set_var *var)
212 {
213  if ((var->value && do_check(thd, var))
214  || (on_check && on_check(this, thd, var)))
215  {
216  if (!thd->is_error())
217  {
218  char buff[STRING_BUFFER_USUAL_SIZE];
219  String str(buff, sizeof(buff), system_charset_info), *res;
220 
221  if (!var->value)
222  {
223  str.set(STRING_WITH_LEN("DEFAULT"), &my_charset_latin1);
224  res= &str;
225  }
226  else if (!(res=var->value->val_str(&str)))
227  {
228  str.set(STRING_WITH_LEN("NULL"), &my_charset_latin1);
229  res= &str;
230  }
231  ErrConvString err(res);
232  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr());
233  }
234  return true;
235  }
236  return false;
237 }
238 
239 uchar *sys_var::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
240 {
241  if (type == OPT_GLOBAL || scope() == GLOBAL)
242  {
243  mysql_mutex_assert_owner(&LOCK_global_system_variables);
244  AutoRLock lock(guard);
245  return global_value_ptr(thd, base);
246  }
247  else
248  return session_value_ptr(thd, base);
249 }
250 
251 bool sys_var::set_default(THD *thd, set_var* var)
252 {
253  if (var->type == OPT_GLOBAL || scope() == GLOBAL)
254  global_save_default(thd, var);
255  else
256  session_save_default(thd, var);
257 
258  return check(thd, var) || update(thd, var);
259 }
260 
261 void sys_var::do_deprecated_warning(THD *thd)
262 {
263  if (deprecation_substitute != NULL)
264  {
265  char buf1[NAME_CHAR_LEN + 3];
266  strxnmov(buf1, sizeof(buf1)-1, "@@", name.str, 0);
267 
268  /*
269  if deprecation_substitute is an empty string,
270  there is no replacement for the syntax
271  */
272  uint errmsg= deprecation_substitute[0] == '\0'
273  ? ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT
274  : ER_WARN_DEPRECATED_SYNTAX;
275  if (thd)
276  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
277  ER_WARN_DEPRECATED_SYNTAX, ER(errmsg),
278  buf1, deprecation_substitute);
279  else
280  sql_print_warning(ER_DEFAULT(errmsg), buf1, deprecation_substitute);
281  }
282 }
283 
296 bool throw_bounds_warning(THD *thd, const char *name,
297  bool fixed, bool is_unsigned, longlong v)
298 {
299  if (fixed)
300  {
301  char buf[22];
302 
303  if (is_unsigned)
304  ullstr((ulonglong) v, buf);
305  else
306  llstr(v, buf);
307 
308  if (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES)
309  {
310  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buf);
311  return true;
312  }
313  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
314  ER_TRUNCATED_WRONG_VALUE,
315  ER(ER_TRUNCATED_WRONG_VALUE), name, buf);
316  }
317  return false;
318 }
319 
320 bool throw_bounds_warning(THD *thd, const char *name, bool fixed, double v)
321 {
322  if (fixed)
323  {
324  char buf[64];
325 
326  my_gcvt(v, MY_GCVT_ARG_DOUBLE, sizeof(buf) - 1, buf, NULL);
327 
328  if (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES)
329  {
330  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buf);
331  return true;
332  }
333  push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
334  ER_TRUNCATED_WRONG_VALUE,
335  ER(ER_TRUNCATED_WRONG_VALUE), name, buf);
336  }
337  return false;
338 }
339 
340 const CHARSET_INFO *sys_var::charset(THD *thd)
341 {
342  return is_os_charset ? thd->variables.character_set_filesystem :
343  system_charset_info;
344 }
345 
346 typedef struct old_names_map_st
347 {
348  const char *old_name;
349  const char *new_name;
350 } my_old_conv;
351 
352 static my_old_conv old_conv[]=
353 {
354  { "cp1251_koi8" , "cp1251" },
355  { "cp1250_latin2" , "cp1250" },
356  { "kam_latin2" , "keybcs2" },
357  { "mac_latin2" , "MacRoman" },
358  { "macce_latin2" , "MacCE" },
359  { "pc2_latin2" , "pclatin2" },
360  { "vga_latin2" , "pclatin1" },
361  { "koi8_cp1251" , "koi8r" },
362  { "win1251ukr_koi8_ukr" , "win1251ukr" },
363  { "koi8_ukr_win1251ukr" , "koi8u" },
364  { NULL , NULL }
365 };
366 
367 const CHARSET_INFO *get_old_charset_by_name(const char *name)
368 {
369  my_old_conv *conv;
370 
371  for (conv= old_conv; conv->old_name; conv++)
372  {
373  if (!my_strcasecmp(&my_charset_latin1, name, conv->old_name))
374  return get_charset_by_csname(conv->new_name, MY_CS_PRIMARY, MYF(0));
375  }
376  return NULL;
377 }
378 
379 /****************************************************************************
380  Main handling of variables:
381  - Initialisation
382  - Searching during parsing
383  - Update loop
384 ****************************************************************************/
385 
398 int mysql_add_sys_var_chain(sys_var *first)
399 {
400  sys_var *var;
401 
402  /* A write lock should be held on LOCK_system_variables_hash */
403 
404  for (var= first; var; var= var->next)
405  {
406  /* this fails if there is a conflicting variable name. see HASH_UNIQUE */
407  if (my_hash_insert(&system_variable_hash, (uchar*) var))
408  {
409  fprintf(stderr, "*** duplicate variable name '%s' ?\n", var->name.str);
410  goto error;
411  }
412  }
413  return 0;
414 
415 error:
416  for (; first != var; first= first->next)
417  my_hash_delete(&system_variable_hash, (uchar*) first);
418  return 1;
419 }
420 
421 
422 /*
423  Remove variables to the dynamic hash of system variables
424 
425  SYNOPSIS
426  mysql_del_sys_var_chain()
427  first Pointer to first system variable to remove
428 
429  RETURN VALUES
430  0 SUCCESS
431  otherwise FAILURE
432 */
433 
434 int mysql_del_sys_var_chain(sys_var *first)
435 {
436  int result= 0;
437 
438  /* A write lock should be held on LOCK_system_variables_hash */
439 
440  for (sys_var *var= first; var; var= var->next)
441  result|= my_hash_delete(&system_variable_hash, (uchar*) var);
442 
443  return result;
444 }
445 
446 
447 static int show_cmp(SHOW_VAR *a, SHOW_VAR *b)
448 {
449  return strcmp(a->name, b->name);
450 }
451 
452 
466 SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted, enum enum_var_type type)
467 {
468  int count= system_variable_hash.records, i;
469  int size= sizeof(SHOW_VAR) * (count + 1);
470  SHOW_VAR *result= (SHOW_VAR*) thd->alloc(size);
471 
472  if (result)
473  {
474  SHOW_VAR *show= result;
475 
476  for (i= 0; i < count; i++)
477  {
478  sys_var *var= (sys_var*) my_hash_element(&system_variable_hash, i);
479 
480  // don't show session-only variables in SHOW GLOBAL VARIABLES
481  if (type == OPT_GLOBAL && var->check_type(type))
482  continue;
483 
484  /* don't show non-visible variables */
485  if (var->not_visible())
486  continue;
487 
488  show->name= var->name.str;
489  show->value= (char*) var;
490  show->type= SHOW_SYS;
491  show++;
492  }
493 
494  /* sort into order */
495  if (sorted)
496  my_qsort(result, show-result, sizeof(SHOW_VAR),
497  (qsort_cmp) show_cmp);
498 
499  /* make last element empty */
500  memset(show, 0, sizeof(SHOW_VAR));
501  }
502  return result;
503 }
504 
518 sys_var *intern_find_sys_var(const char *str, uint length)
519 {
520  sys_var *var;
521 
522  /*
523  This function is only called from the sql_plugin.cc.
524  A lock on LOCK_system_variable_hash should be held
525  */
526  var= (sys_var*) my_hash_search(&system_variable_hash,
527  (uchar*) str, length ? length : strlen(str));
528 
529  /* Don't show non-visible variables. */
530  if (var && var->not_visible())
531  return NULL;
532 
533  return var;
534 }
535 
536 
557 int sql_set_variables(THD *thd, List<set_var_base> *var_list)
558 {
559  int error;
560  List_iterator_fast<set_var_base> it(*var_list);
561  DBUG_ENTER("sql_set_variables");
562 
563  set_var_base *var;
564  while ((var=it++))
565  {
566  if ((error= var->check(thd)))
567  goto err;
568  }
569  if (!(error= test(thd->is_error())))
570  {
571  it.rewind();
572  while ((var= it++))
573  error|= var->update(thd); // Returns 0, -1 or 1
574  }
575 
576 err:
577  free_underlaid_joins(thd, &thd->lex->select_lex);
578  DBUG_RETURN(error);
579 }
580 
581 /*****************************************************************************
582  Functions to handle SET mysql_internal_variable=const_expr
583 *****************************************************************************/
584 
595 int set_var::check(THD *thd)
596 {
597  var->do_deprecated_warning(thd);
598  if (var->is_readonly())
599  {
600  my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), var->name.str, "read only");
601  return -1;
602  }
603  if (var->check_type(type))
604  {
605  int err= type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE;
606  my_error(err, MYF(0), var->name.str);
607  return -1;
608  }
609  if ((type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL)))
610  return 1;
611  /* value is a NULL pointer if we are using SET ... = DEFAULT */
612  if (!value)
613  return 0;
614 
615  if ((!value->fixed &&
616  value->fix_fields(thd, &value)) || value->check_cols(1))
617  return -1;
618  if (var->check_update_type(value->result_type()))
619  {
620  my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), var->name.str);
621  return -1;
622  }
623  return var->check(thd, this) ? -1 : 0;
624 }
625 
626 
639 int set_var::light_check(THD *thd)
640 {
641  if (var->check_type(type))
642  {
643  int err= type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE;
644  my_error(err, MYF(0), var->name);
645  return -1;
646  }
647  if (type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL))
648  return 1;
649 
650  if (value && ((!value->fixed && value->fix_fields(thd, &value)) ||
651  value->check_cols(1)))
652  return -1;
653  return 0;
654 }
655 
668 int set_var::update(THD *thd)
669 {
670  return value ? var->update(thd, this) : var->set_default(thd, this);
671 }
672 
678 void set_var::print(THD *thd, String *str)
679 {
680  str->append(type == OPT_GLOBAL ? "GLOBAL " : "SESSION ");
681  if (base.length)
682  {
683  str->append(base.str, base.length);
684  str->append(STRING_WITH_LEN("."));
685  }
686  str->append(var->name.str,var->name.length);
687  str->append(STRING_WITH_LEN("="));
688  if (value)
689  value->print(str, QT_ORDINARY);
690  else
691  str->append(STRING_WITH_LEN("DEFAULT"));
692 }
693 
694 
695 /*****************************************************************************
696  Functions to handle SET @user_variable=const_expr
697 *****************************************************************************/
698 
699 int set_var_user::check(THD *thd)
700 {
701  /*
702  Item_func_set_user_var can't substitute something else on its place =>
703  0 can be passed as last argument (reference on item)
704  */
705  return (user_var_item->fix_fields(thd, (Item**) 0) ||
706  user_var_item->check(0)) ? -1 : 0;
707 }
708 
709 
723 {
724  /*
725  Item_func_set_user_var can't substitute something else on its place =>
726  0 can be passed as last argument (reference on item)
727  */
728  return (user_var_item->fix_fields(thd, (Item**) 0));
729 }
730 
731 
732 int set_var_user::update(THD *thd)
733 {
734  if (user_var_item->update())
735  {
736  /* Give an error if it's not given already */
737  my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY), MYF(0));
738  return -1;
739  }
740  return 0;
741 }
742 
743 
744 void set_var_user::print(THD *thd, String *str)
745 {
746  user_var_item->print_assignment(str, QT_ORDINARY);
747 }
748 
749 
750 /*****************************************************************************
751  Functions to handle SET PASSWORD
752 *****************************************************************************/
753 
766 {
767 #ifndef NO_EMBEDDED_ACCESS_CHECKS
768  if (!user->host.str)
769  {
770  DBUG_ASSERT(thd->security_ctx->priv_host);
771  user->host.str= (char *) thd->security_ctx->priv_host;
772  user->host.length= strlen(thd->security_ctx->priv_host);
773  }
774  /*
775  In case of anonymous user, user->user is set to empty string with length 0.
776  But there might be case when user->user.str could be NULL. For Ex:
777  "set password for current_user() = password('xyz');". In this case,
778  set user information as of the current user.
779  */
780  if (!user->user.str)
781  {
782  DBUG_ASSERT(thd->security_ctx->user);
783  user->user.str= (char *) thd->security_ctx->user;
784  user->user.length= strlen(thd->security_ctx->user);
785  }
786  /* Returns 1 as the function sends error to client */
787  return check_change_password(thd, user->host.str, user->user.str,
788  password, strlen(password)) ? 1 : 0;
789 #else
790  return 0;
791 #endif
792 }
793 
794 int set_var_password::update(THD *thd)
795 {
796 #ifndef NO_EMBEDDED_ACCESS_CHECKS
797  /* Returns 1 as the function sends error to client */
798  return change_password(thd, user->host.str, user->user.str, password) ?
799  1 : 0;
800 #else
801  return 0;
802 #endif
803 }
804 
805 void set_var_password::print(THD *thd, String *str)
806 {
807  if (user->user.str != NULL && user->user.length > 0)
808  {
809  str->append(STRING_WITH_LEN("PASSWORD FOR "));
810  append_identifier(thd, str, user->user.str, user->user.length);
811  if (user->host.str != NULL && user->host.length > 0)
812  {
813  str->append(STRING_WITH_LEN("@"));
814  append_identifier(thd, str, user->host.str, user->host.length);
815  }
816  str->append(STRING_WITH_LEN("="));
817  }
818  else
819  str->append(STRING_WITH_LEN("PASSWORD FOR CURRENT_USER()="));
820  str->append(STRING_WITH_LEN("<secret>"));
821 }
822 
823 /*****************************************************************************
824  Functions to handle SET NAMES and SET CHARACTER SET
825 *****************************************************************************/
826 
827 int set_var_collation_client::check(THD *thd)
828 {
829  /* Currently, UCS-2 cannot be used as a client character set */
830  if (!is_supported_parser_charset(character_set_client))
831  {
832  my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "character_set_client",
833  character_set_client->csname);
834  return 1;
835  }
836  return 0;
837 }
838 
839 int set_var_collation_client::update(THD *thd)
840 {
841  thd->variables.character_set_client= character_set_client;
842  thd->variables.character_set_results= character_set_results;
843  thd->variables.collation_connection= collation_connection;
844  thd->update_charset();
845  thd->protocol_text.init(thd);
846  thd->protocol_binary.init(thd);
847  return 0;
848 }
849 
850 void set_var_collation_client::print(THD *thd, String *str)
851 {
852  str->append((set_cs_flags & SET_CS_NAMES) ? "NAMES " : "CHARACTER SET ");
853  if (set_cs_flags & SET_CS_DEFAULT)
854  str->append("DEFAULT");
855  else
856  {
857  str->append("'");
858  str->append(character_set_client->csname);
859  str->append("'");
860  if (set_cs_flags & SET_CS_COLLATE)
861  {
862  str->append(" COLLATE '");
863  str->append(collation_connection->name);
864  str->append("'");
865  }
866  }
867 }