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, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 /* variable declarations are in sys_vars.cc now !!! */
24
25 #include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
26 #include "sql_class.h" // set_var.h: session_var_ptr
27 #include "set_var.h"
28 #include "sql_priv.h"
29 #include "unireg.h"
30 #include "mysqld.h" // lc_messages_dir
31 #include "sys_vars_shared.h"
32 #include "transaction.h"
33 #include "sql_locale.h" // my_locale_by_number,
34 // my_locale_by_name
35 #include "strfunc.h" // find_set_from_flags, find_set
36 #include "sql_parse.h" // check_global_access
37 #include "sql_table.h" // reassign_keycache_tables
38 #include "sql_time.h" // date_time_format_copy,
39 // date_time_format_make
40 #include "derror.h"
41 #include "tztime.h" // my_tz_find, my_tz_SYSTEM, struct Time_zone
42 #include "sql_acl.h" // SUPER_ACL
43 #include "sql_select.h" // free_underlaid_joins
44 #include "sql_show.h" // make_default_log_name, append_identifier
45 #include "sql_view.h" // updatable_views_with_limit_typelib
46 #include "lock.h" // lock_global_read_lock,
47 // make_global_read_lock_block_commit,
48 // unlock_global_read_lock
49
50 static HASH system_variable_hash;
51 static PolyLock_mutex PLock_global_system_variables(&LOCK_global_system_variables);
52
53 /**
54 Return variable name and length for hashing of variables.
55 */
56
get_sys_var_length(const sys_var * var,size_t * length,my_bool first)57 static uchar *get_sys_var_length(const sys_var *var, size_t *length,
58 my_bool first)
59 {
60 *length= var->name.length;
61 return (uchar*) var->name.str;
62 }
63
64 sys_var_chain all_sys_vars = { NULL, NULL };
65
sys_var_init()66 int sys_var_init()
67 {
68 DBUG_ENTER("sys_var_init");
69
70 /* Must be already initialized. */
71 DBUG_ASSERT(system_charset_info != NULL);
72
73 if (my_hash_init(&system_variable_hash, system_charset_info, 100, 0,
74 0, (my_hash_get_key) get_sys_var_length, 0, HASH_UNIQUE))
75 goto error;
76
77 if (mysql_add_sys_var_chain(all_sys_vars.first))
78 goto error;
79
80 DBUG_RETURN(0);
81
82 error:
83 fprintf(stderr, "failed to initialize System variables");
84 DBUG_RETURN(1);
85 }
86
sys_var_add_options(std::vector<my_option> * long_options,int parse_flags)87 int sys_var_add_options(std::vector<my_option> *long_options, int parse_flags)
88 {
89 DBUG_ENTER("sys_var_add_options");
90
91 for (sys_var *var=all_sys_vars.first; var; var= var->next)
92 {
93 if (var->register_option(long_options, parse_flags))
94 goto error;
95 }
96
97 DBUG_RETURN(0);
98
99 error:
100 fprintf(stderr, "failed to initialize System variables");
101 DBUG_RETURN(1);
102 }
103
sys_var_end()104 void sys_var_end()
105 {
106 DBUG_ENTER("sys_var_end");
107
108 my_hash_free(&system_variable_hash);
109
110 for (sys_var *var=all_sys_vars.first; var; var= var->next)
111 var->cleanup();
112
113 DBUG_VOID_RETURN;
114 }
115
116 /**
117 sys_var constructor
118
119 @param chain variables are linked into chain for mysql_add_sys_var_chain()
120 @param name_arg the name of the variable. Must be 0-terminated and exist
121 for the liftime of the sys_var object. @sa my_option::name
122 @param comment shown in mysqld --help, @sa my_option::comment
123 @param flags_arg or'ed flag_enum values
124 @param off offset of the global variable value from the
125 &global_system_variables.
126 @param getopt_id -1 for no command-line option, otherwise @sa my_option::id
127 @param getopt_arg_type @sa my_option::arg_type
128 @param show_val_type_arg what value_ptr() returns for sql_show.cc
129 @param def_val default value, @sa my_option::def_value
130 @param lock mutex or rw_lock that protects the global variable
131 *in addition* to LOCK_global_system_variables.
132 @param binlog_status_enum @sa binlog_status_enum
133 @param on_check_func a function to be called at the end of sys_var::check,
134 put your additional checks here
135 @param on_update_func a function to be called at the end of sys_var::update,
136 any post-update activity should happen here
137 @param substitute If non-NULL, this variable is deprecated and the
138 string describes what one should use instead. If an empty string,
139 the variable is deprecated but no replacement is offered.
140 @param parse_flag either PARSE_EARLY or PARSE_NORMAL
141 */
sys_var(sys_var_chain * chain,const char * name_arg,const char * comment,int flags_arg,ptrdiff_t off,int getopt_id,enum get_opt_arg_type getopt_arg_type,SHOW_TYPE show_val_type_arg,longlong def_val,PolyLock * lock,enum binlog_status_enum binlog_status_arg,on_check_function on_check_func,on_update_function on_update_func,const char * substitute,int parse_flag)142 sys_var::sys_var(sys_var_chain *chain, const char *name_arg,
143 const char *comment, int flags_arg, ptrdiff_t off,
144 int getopt_id, enum get_opt_arg_type getopt_arg_type,
145 SHOW_TYPE show_val_type_arg, longlong def_val,
146 PolyLock *lock, enum binlog_status_enum binlog_status_arg,
147 on_check_function on_check_func,
148 on_update_function on_update_func,
149 const char *substitute, int parse_flag) :
150 next(0),
151 binlog_status(binlog_status_arg),
152 flags(flags_arg), m_parse_flag(parse_flag), show_val_type(show_val_type_arg),
153 guard(lock), offset(off), on_check(on_check_func), on_update(on_update_func),
154 deprecation_substitute(substitute),
155 is_os_charset(FALSE)
156 {
157 /*
158 There is a limitation in handle_options() related to short options:
159 - either all short options should be declared when parsing in multiple stages,
160 - or none should be declared.
161 Because a lot of short options are used in the normal parsing phase
162 for mysqld, we enforce here that no short option is present
163 in the first (PARSE_EARLY) stage.
164 See handle_options() for details.
165 */
166 DBUG_ASSERT(parse_flag == PARSE_NORMAL || getopt_id <= 0 || getopt_id >= 255);
167
168 name.str= name_arg; // ER_NO_DEFAULT relies on 0-termination of name_arg
169 name.length= strlen(name_arg); // and so does this.
170 DBUG_ASSERT(name.length <= NAME_CHAR_LEN);
171
172 memset(&option, 0, sizeof(option));
173 option.name= name_arg;
174 option.id= getopt_id;
175 option.comment= comment;
176 option.arg_type= getopt_arg_type;
177 option.value= (uchar **)global_var_ptr();
178 option.def_value= def_val;
179
180 if (chain->last)
181 chain->last->next= this;
182 else
183 chain->first= this;
184 chain->last= this;
185 }
186
update(THD * thd,set_var * var)187 bool sys_var::update(THD *thd, set_var *var)
188 {
189 enum_var_type type= var->type;
190 if (type == OPT_GLOBAL || scope() == GLOBAL)
191 {
192 /*
193 Yes, both locks need to be taken before an update, just as
194 both are taken to get a value. If we'll take only 'guard' here,
195 then value_ptr() for strings won't be safe in SHOW VARIABLES anymore,
196 to make it safe we'll need value_ptr_unlock().
197 */
198 AutoWLock lock1(&PLock_global_system_variables);
199 AutoWLock lock2(guard);
200 return global_update(thd, var) ||
201 (on_update && on_update(this, thd, OPT_GLOBAL));
202 }
203 else
204 return session_update(thd, var) ||
205 (on_update && on_update(this, thd, OPT_SESSION));
206 }
207
session_value_ptr(THD * thd,LEX_STRING * base)208 uchar *sys_var::session_value_ptr(THD *thd, LEX_STRING *base)
209 {
210 return session_var_ptr(thd);
211 }
212
global_value_ptr(THD * thd,LEX_STRING * base)213 uchar *sys_var::global_value_ptr(THD *thd, LEX_STRING *base)
214 {
215 return global_var_ptr();
216 }
217
check(THD * thd,set_var * var)218 bool sys_var::check(THD *thd, set_var *var)
219 {
220 if ((var->value && do_check(thd, var))
221 || (on_check && on_check(this, thd, var)))
222 {
223 if (!thd->is_error())
224 {
225 char buff[STRING_BUFFER_USUAL_SIZE];
226 String str(buff, sizeof(buff), system_charset_info), *res;
227
228 if (!var->value)
229 {
230 str.set(STRING_WITH_LEN("DEFAULT"), &my_charset_latin1);
231 res= &str;
232 }
233 else if (!(res=var->value->val_str(&str)))
234 {
235 str.set(STRING_WITH_LEN("NULL"), &my_charset_latin1);
236 res= &str;
237 }
238 ErrConvString err(res);
239 my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr());
240 }
241 return true;
242 }
243 return false;
244 }
245
value_ptr(THD * thd,enum_var_type type,LEX_STRING * base)246 uchar *sys_var::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
247 {
248 if (type == OPT_GLOBAL || scope() == GLOBAL)
249 {
250 mysql_mutex_assert_owner(&LOCK_global_system_variables);
251 AutoRLock lock(guard);
252 return global_value_ptr(thd, base);
253 }
254 else
255 return session_value_ptr(thd, base);
256 }
257
set_default(THD * thd,set_var * var)258 bool sys_var::set_default(THD *thd, set_var* var)
259 {
260 if (var->type == OPT_GLOBAL || scope() == GLOBAL)
261 global_save_default(thd, var);
262 else
263 session_save_default(thd, var);
264
265 return check(thd, var) || update(thd, var);
266 }
267
do_deprecated_warning(THD * thd)268 void sys_var::do_deprecated_warning(THD *thd)
269 {
270 if (deprecation_substitute != NULL)
271 {
272 char buf1[NAME_CHAR_LEN + 3];
273 strxnmov(buf1, sizeof(buf1)-1, "@@", name.str, 0);
274
275 /*
276 if deprecation_substitute is an empty string,
277 there is no replacement for the syntax
278 */
279 uint errmsg= deprecation_substitute[0] == '\0'
280 ? ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT
281 : ER_WARN_DEPRECATED_SYNTAX;
282 if (thd)
283 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
284 ER_WARN_DEPRECATED_SYNTAX, ER(errmsg),
285 buf1, deprecation_substitute);
286 else
287 sql_print_warning(ER_DEFAULT(errmsg), buf1, deprecation_substitute);
288 }
289 }
290
291 /**
292 Throw warning (error in STRICT mode) if value for variable needed bounding.
293 Plug-in interface also uses this.
294
295 @param thd thread handle
296 @param name variable's name
297 @param fixed did we have to correct the value? (throw warn/err if so)
298 @param is_unsigned is value's type unsigned?
299 @param v variable's value
300
301 @retval true on error, false otherwise (warning or ok)
302 */
throw_bounds_warning(THD * thd,const char * name,bool fixed,bool is_unsigned,longlong v)303 bool throw_bounds_warning(THD *thd, const char *name,
304 bool fixed, bool is_unsigned, longlong v)
305 {
306 if (fixed)
307 {
308 char buf[22];
309
310 if (is_unsigned)
311 ullstr((ulonglong) v, buf);
312 else
313 llstr(v, buf);
314
315 if (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES)
316 {
317 my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buf);
318 return true;
319 }
320 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
321 ER_TRUNCATED_WRONG_VALUE,
322 ER(ER_TRUNCATED_WRONG_VALUE), name, buf);
323 }
324 return false;
325 }
326
throw_bounds_warning(THD * thd,const char * name,bool fixed,double v)327 bool throw_bounds_warning(THD *thd, const char *name, bool fixed, double v)
328 {
329 if (fixed)
330 {
331 char buf[64];
332
333 my_gcvt(v, MY_GCVT_ARG_DOUBLE, sizeof(buf) - 1, buf, NULL);
334
335 if (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES)
336 {
337 my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buf);
338 return true;
339 }
340 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
341 ER_TRUNCATED_WRONG_VALUE,
342 ER(ER_TRUNCATED_WRONG_VALUE), name, buf);
343 }
344 return false;
345 }
346
charset(THD * thd)347 const CHARSET_INFO *sys_var::charset(THD *thd)
348 {
349 return is_os_charset ? thd->variables.character_set_filesystem :
350 system_charset_info;
351 }
352
353 typedef struct old_names_map_st
354 {
355 const char *old_name;
356 const char *new_name;
357 } my_old_conv;
358
359 static my_old_conv old_conv[]=
360 {
361 { "cp1251_koi8" , "cp1251" },
362 { "cp1250_latin2" , "cp1250" },
363 { "kam_latin2" , "keybcs2" },
364 { "mac_latin2" , "MacRoman" },
365 { "macce_latin2" , "MacCE" },
366 { "pc2_latin2" , "pclatin2" },
367 { "vga_latin2" , "pclatin1" },
368 { "koi8_cp1251" , "koi8r" },
369 { "win1251ukr_koi8_ukr" , "win1251ukr" },
370 { "koi8_ukr_win1251ukr" , "koi8u" },
371 { NULL , NULL }
372 };
373
get_old_charset_by_name(const char * name)374 const CHARSET_INFO *get_old_charset_by_name(const char *name)
375 {
376 my_old_conv *conv;
377
378 for (conv= old_conv; conv->old_name; conv++)
379 {
380 if (!my_strcasecmp(&my_charset_latin1, name, conv->old_name))
381 return get_charset_by_csname(conv->new_name, MY_CS_PRIMARY, MYF(0));
382 }
383 return NULL;
384 }
385
386 /****************************************************************************
387 Main handling of variables:
388 - Initialisation
389 - Searching during parsing
390 - Update loop
391 ****************************************************************************/
392
393 /**
394 Add variables to the dynamic hash of system variables
395
396 @param first Pointer to first system variable to add
397
398 @retval
399 0 SUCCESS
400 @retval
401 otherwise FAILURE
402 */
403
404
mysql_add_sys_var_chain(sys_var * first)405 int mysql_add_sys_var_chain(sys_var *first)
406 {
407 sys_var *var;
408
409 /* A write lock should be held on LOCK_system_variables_hash */
410
411 for (var= first; var; var= var->next)
412 {
413 /* this fails if there is a conflicting variable name. see HASH_UNIQUE */
414 if (my_hash_insert(&system_variable_hash, (uchar*) var))
415 {
416 fprintf(stderr, "*** duplicate variable name '%s' ?\n", var->name.str);
417 goto error;
418 }
419 }
420 return 0;
421
422 error:
423 for (; first != var; first= first->next)
424 my_hash_delete(&system_variable_hash, (uchar*) first);
425 return 1;
426 }
427
428
429 /*
430 Remove variables to the dynamic hash of system variables
431
432 SYNOPSIS
433 mysql_del_sys_var_chain()
434 first Pointer to first system variable to remove
435
436 RETURN VALUES
437 0 SUCCESS
438 otherwise FAILURE
439 */
440
mysql_del_sys_var_chain(sys_var * first)441 int mysql_del_sys_var_chain(sys_var *first)
442 {
443 int result= 0;
444
445 /* A write lock should be held on LOCK_system_variables_hash */
446
447 for (sys_var *var= first; var; var= var->next)
448 result|= my_hash_delete(&system_variable_hash, (uchar*) var);
449
450 return result;
451 }
452
453
show_cmp(SHOW_VAR * a,SHOW_VAR * b)454 static int show_cmp(SHOW_VAR *a, SHOW_VAR *b)
455 {
456 return strcmp(a->name, b->name);
457 }
458
459
460 /**
461 Constructs an array of system variables for display to the user.
462
463 @param thd current thread
464 @param sorted If TRUE, the system variables should be sorted
465 @param type OPT_GLOBAL or OPT_SESSION for SHOW GLOBAL|SESSION VARIABLES
466
467 @retval
468 pointer Array of SHOW_VAR elements for display
469 @retval
470 NULL FAILURE
471 */
472
enumerate_sys_vars(THD * thd,bool sorted,enum enum_var_type type)473 SHOW_VAR* enumerate_sys_vars(THD *thd, bool sorted, enum enum_var_type type)
474 {
475 int count= system_variable_hash.records, i;
476 int size= sizeof(SHOW_VAR) * (count + 1);
477 SHOW_VAR *result= (SHOW_VAR*) thd->alloc(size);
478
479 if (result)
480 {
481 SHOW_VAR *show= result;
482
483 for (i= 0; i < count; i++)
484 {
485 sys_var *var= (sys_var*) my_hash_element(&system_variable_hash, i);
486 const my_bool *hidden=
487 getopt_constraint_get_hidden_value(var->name.str, var->name.length,
488 FALSE);
489
490 if (hidden && *hidden)
491 continue;
492
493 // don't show session-only variables in SHOW GLOBAL VARIABLES
494 if (type == OPT_GLOBAL && var->check_type(type))
495 continue;
496
497 /* don't show non-visible variables */
498 if (var->not_visible())
499 continue;
500
501 show->name= var->name.str;
502 show->value= (char*) var;
503 show->type= SHOW_SYS;
504 show++;
505 }
506
507 /* sort into order */
508 if (sorted)
509 my_qsort(result, show-result, sizeof(SHOW_VAR),
510 (qsort_cmp) show_cmp);
511
512 /* make last element empty */
513 memset(show, 0, sizeof(SHOW_VAR));
514 }
515 return result;
516 }
517
518 /**
519 Find a user set-table variable.
520
521 @param str Name of system variable to find
522 @param length Length of variable. zero means that we should use strlen()
523 on the variable
524
525 @retval
526 pointer pointer to variable definitions
527 @retval
528 0 Unknown variable (error message is given)
529 */
530
intern_find_sys_var(const char * str,uint length)531 sys_var *intern_find_sys_var(const char *str, uint length)
532 {
533 sys_var *var;
534
535 /*
536 This function is only called from the sql_plugin.cc.
537 A lock on LOCK_system_variable_hash should be held
538 */
539 var= (sys_var*) my_hash_search(&system_variable_hash,
540 (uchar*) str, length ? length : strlen(str));
541
542 /* Don't show non-visible variables. */
543 if (var && var->not_visible())
544 return NULL;
545
546 return var;
547 }
548
549
550 /**
551 Execute update of all variables.
552
553 First run a check of all variables that all updates will go ok.
554 If yes, then execute all updates, returning an error if any one failed.
555
556 This should ensure that in all normal cases none all or variables are
557 updated.
558
559 @param THD Thread id
560 @param var_list List of variables to update
561 @param free_joins Whether to free subselect joins if any. They are
562 freed by default, except for SET STATEMENT ... FOR ...
563 processing
564
565 @retval
566 0 ok
567 @retval
568 1 ERROR, message sent (normally no variables was updated)
569 @retval
570 -1 ERROR, message not sent
571 */
572
sql_set_variables(THD * thd,List<set_var_base> * var_list,bool free_joins)573 int sql_set_variables(THD *thd, List<set_var_base> *var_list, bool free_joins)
574 {
575 int error;
576 List_iterator_fast<set_var_base> it(*var_list);
577 DBUG_ENTER("sql_set_variables");
578
579 set_var_base *var;
580 while ((var=it++))
581 {
582 if ((error= var->check(thd)))
583 goto err;
584 }
585 if (!(error= MY_TEST(thd->is_error())))
586 {
587 it.rewind();
588 while ((var= it++))
589 error|= var->update(thd); // Returns 0, -1 or 1
590 }
591
592 err:
593 if (free_joins)
594 free_underlaid_joins(thd, &thd->lex->select_lex);
595 DBUG_RETURN(error);
596 }
597
598 /*****************************************************************************
599 Functions to handle SET mysql_internal_variable=const_expr
600 *****************************************************************************/
601
602 /**
603 Verify that the supplied value is correct.
604
605 @param thd Thread handler
606
607 @return status code
608 @retval -1 Failure
609 @retval 0 Success
610 */
611
check(THD * thd)612 int set_var::check(THD *thd)
613 {
614 var->do_deprecated_warning(thd);
615 if (var->is_readonly())
616 {
617 my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0), var->name.str, "read only");
618 return -1;
619 }
620 if (var->check_type(type))
621 {
622 int err= type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE;
623 my_error(err, MYF(0), var->name.str);
624 return -1;
625 }
626 if (!acl_is_utility_user(thd->security_ctx->priv_user,
627 thd->security_ctx->get_host()->ptr(),
628 thd->security_ctx->get_ip()->ptr())
629 && (type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL)))
630 return 1;
631 /* value is a NULL pointer if we are using SET ... = DEFAULT */
632 if (!value)
633 return 0;
634
635 if ((!value->fixed &&
636 value->fix_fields(thd, &value)) || value->check_cols(1))
637 return -1;
638 if (var->check_update_type(value->result_type()))
639 {
640 my_error(ER_WRONG_TYPE_FOR_VAR, MYF(0), var->name.str);
641 return -1;
642 }
643 return var->check(thd, this) ? -1 : 0;
644 }
645
646
647 /**
648 Check variable, but without assigning value (used by PS).
649
650 @param thd thread handler
651
652 @retval
653 0 ok
654 @retval
655 1 ERROR, message sent (normally no variables was updated)
656 @retval
657 -1 ERROR, message not sent
658 */
light_check(THD * thd)659 int set_var::light_check(THD *thd)
660 {
661 if (var->check_type(type))
662 {
663 int err= type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE;
664 my_error(err, MYF(0), var->name);
665 return -1;
666 }
667 if (type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL))
668 return 1;
669
670 if (value && ((!value->fixed && value->fix_fields(thd, &value)) ||
671 value->check_cols(1)))
672 return -1;
673 return 0;
674 }
675
676 /**
677 Update variable
678
679 @param thd thread handler
680 @returns 0|1 ok or ERROR
681
682 @note ERROR can be only due to abnormal operations involving
683 the server's execution evironment such as
684 out of memory, hard disk failure or the computer blows up.
685 Consider set_var::check() method if there is a need to return
686 an error due to logics.
687 */
update(THD * thd)688 int set_var::update(THD *thd)
689 {
690 return value ? var->update(thd, this) : var->set_default(thd, this);
691 }
692
693 /**
694 Self-print assignment
695
696 @param str string buffer to append the partial assignment to
697 */
print(THD * thd,String * str)698 void set_var::print(THD *thd, String *str)
699 {
700 str->append(type == OPT_GLOBAL ? "GLOBAL " : "SESSION ");
701 if (base.length)
702 {
703 str->append(base.str, base.length);
704 str->append(STRING_WITH_LEN("."));
705 }
706 str->append(var->name.str,var->name.length);
707 str->append(STRING_WITH_LEN("="));
708 if (value)
709 value->print(str, QT_ORDINARY);
710 else
711 str->append(STRING_WITH_LEN("DEFAULT"));
712 }
713
714
715 /*****************************************************************************
716 Functions to handle SET @user_variable=const_expr
717 *****************************************************************************/
718
check(THD * thd)719 int set_var_user::check(THD *thd)
720 {
721 /*
722 Item_func_set_user_var can't substitute something else on its place =>
723 0 can be passed as last argument (reference on item)
724 */
725 return (user_var_item->fix_fields(thd, (Item**) 0) ||
726 user_var_item->check(0)) ? -1 : 0;
727 }
728
729
730 /**
731 Check variable, but without assigning value (used by PS).
732
733 @param thd thread handler
734
735 @retval
736 0 ok
737 @retval
738 1 ERROR, message sent (normally no variables was updated)
739 @retval
740 -1 ERROR, message not sent
741 */
light_check(THD * thd)742 int set_var_user::light_check(THD *thd)
743 {
744 /*
745 Item_func_set_user_var can't substitute something else on its place =>
746 0 can be passed as last argument (reference on item)
747 */
748 return (user_var_item->fix_fields(thd, (Item**) 0));
749 }
750
751
update(THD * thd)752 int set_var_user::update(THD *thd)
753 {
754 if (user_var_item->update())
755 {
756 /* Give an error if it's not given already */
757 my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY), MYF(0));
758 return -1;
759 }
760 return 0;
761 }
762
763
print(THD * thd,String * str)764 void set_var_user::print(THD *thd, String *str)
765 {
766 user_var_item->print_assignment(str, QT_ORDINARY);
767 }
768
769
770 /*****************************************************************************
771 Functions to handle SET PASSWORD
772 *****************************************************************************/
773
774 /**
775 Check the validity of the SET PASSWORD request
776
777 User name and no host is used for SET PASSWORD =
778 No user name and no host used for SET PASSWORD for CURRENT_USER() =
779
780 @param thd The current thread
781 @return status code
782 @retval 0 failure
783 @retval 1 success
784 */
check(THD * thd)785 int set_var_password::check(THD *thd)
786 {
787 #ifndef NO_EMBEDDED_ACCESS_CHECKS
788 if (!user->host.str)
789 {
790 DBUG_ASSERT(thd->security_ctx->priv_host);
791 user->host.str= (char *) thd->security_ctx->priv_host;
792 user->host.length= strlen(thd->security_ctx->priv_host);
793 }
794 /*
795 In case of anonymous user, user->user is set to empty string with length 0.
796 But there might be case when user->user.str could be NULL. For Ex:
797 "set password for current_user() = password('xyz');". In this case,
798 set user information as of the current user.
799 */
800 if (!user->user.str)
801 {
802 DBUG_ASSERT(thd->security_ctx->user);
803 user->user.str= (char *) thd->security_ctx->user;
804 user->user.length= strlen(thd->security_ctx->user);
805 }
806 /* Returns 1 as the function sends error to client */
807 return check_change_password(thd, user->host.str, user->user.str,
808 password, strlen(password)) ? 1 : 0;
809 #else
810 return 0;
811 #endif
812 }
813
update(THD * thd)814 int set_var_password::update(THD *thd)
815 {
816 #ifndef NO_EMBEDDED_ACCESS_CHECKS
817 /* Returns 1 as the function sends error to client */
818 return change_password(thd, user->host.str, user->user.str, password) ?
819 1 : 0;
820 #else
821 return 0;
822 #endif
823 }
824
print(THD * thd,String * str)825 void set_var_password::print(THD *thd, String *str)
826 {
827 if (user->user.str != NULL && user->user.length > 0)
828 {
829 str->append(STRING_WITH_LEN("PASSWORD FOR "));
830 append_identifier(thd, str, user->user.str, user->user.length);
831 if (user->host.str != NULL && user->host.length > 0)
832 {
833 str->append(STRING_WITH_LEN("@"));
834 append_identifier(thd, str, user->host.str, user->host.length);
835 }
836 str->append(STRING_WITH_LEN("="));
837 }
838 else
839 str->append(STRING_WITH_LEN("PASSWORD FOR CURRENT_USER()="));
840 str->append(STRING_WITH_LEN("<secret>"));
841 }
842
843 /*****************************************************************************
844 Functions to handle SET NAMES and SET CHARACTER SET
845 *****************************************************************************/
846
check(THD * thd)847 int set_var_collation_client::check(THD *thd)
848 {
849 /* Currently, UCS-2 cannot be used as a client character set */
850 if (!is_supported_parser_charset(character_set_client))
851 {
852 my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "character_set_client",
853 character_set_client->csname);
854 return 1;
855 }
856 return 0;
857 }
858
update(THD * thd)859 int set_var_collation_client::update(THD *thd)
860 {
861 thd->variables.character_set_client= character_set_client;
862 thd->variables.character_set_results= character_set_results;
863 thd->variables.collation_connection= collation_connection;
864 thd->update_charset();
865 thd->protocol_text.init(thd);
866 thd->protocol_binary.init(thd);
867 return 0;
868 }
869
print(THD * thd,String * str)870 void set_var_collation_client::print(THD *thd, String *str)
871 {
872 str->append((set_cs_flags & SET_CS_NAMES) ? "NAMES " : "CHARACTER SET ");
873 if (set_cs_flags & SET_CS_DEFAULT)
874 str->append("DEFAULT");
875 else
876 {
877 str->append("'");
878 str->append(character_set_client->csname);
879 str->append("'");
880 if (set_cs_flags & SET_CS_COLLATE)
881 {
882 str->append(" COLLATE '");
883 str->append(collation_connection->name);
884 str->append("'");
885 }
886 }
887 }
888