1 /* Copyright (c) 2009, 2020, 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 /**
24   @file
25   Definitions of all server's session or global variables.
26 
27   How to add new variables:
28 
29   1. copy one of the existing variables, and edit the declaration.
30   2. if you need special behavior on assignment or additional checks
31      use ON_CHECK and ON_UPDATE callbacks.
32   3. *Don't* add new Sys_var classes or uncle Occam will come
33      with his razor to haunt you at nights
34 
35   Note - all storage engine variables (for example myisam_whatever)
36   should go into the corresponding storage engine sources
37   (for example in storage/myisam/ha_myisam.cc) !
38 */
39 
40 #include "sql/sys_vars.h"
41 
42 #include "my_config.h"
43 
44 #include <assert.h>
45 #include <limits.h>
46 #include <math.h>
47 #include <stdint.h>
48 #include <stdio.h>
49 #include <sys/stat.h>
50 #include <zlib.h>
51 #include <atomic>
52 #include <limits>
53 
54 #include "include/compression.h"
55 
56 #include "my_loglevel.h"
57 #include "mysql/components/services/log_builtins.h"
58 #include "mysql/components/services/log_shared.h"
59 #include "mysql_com.h"
60 #include "sql/protocol.h"
61 #include "sql/rpl_trx_tracking.h"
62 #ifdef HAVE_SYS_TIME_H
63 #include <sys/time.h>
64 #endif
65 #ifdef HAVE_UNISTD_H
66 #include <unistd.h>
67 #endif
68 #include <algorithm>
69 #include <map>
70 #include <utility>
71 
72 #include "ft_global.h"
73 #include "libbinlogevents/include/binlog_event.h"
74 #include "m_string.h"
75 #include "my_aes.h"  // my_aes_opmode_names
76 #include "my_command.h"
77 #include "my_compiler.h"
78 #include "my_dbug.h"
79 #include "my_dir.h"
80 #include "my_double2ulonglong.h"
81 #include "my_io.h"
82 #include "my_macros.h"
83 #include "my_sqlcommand.h"
84 #include "my_thread.h"
85 #include "my_thread_local.h"
86 #include "my_time.h"
87 #include "myisam.h"  // myisam_flush
88 #include "mysql/components/services/log_builtins.h"
89 #include "mysql/plugin_group_replication.h"
90 #include "mysql/psi/mysql_mutex.h"
91 #include "mysql_version.h"
92 #include "sql/auth/auth_acls.h"
93 #include "sql/auth/auth_common.h"  // validate_user_plugins
94 #include "sql/binlog.h"            // mysql_bin_log
95 #include "sql/clone_handler.h"
96 #include "sql/conn_handler/connection_handler_impl.h"  // Per_thread_connection_handler
97 #include "sql/conn_handler/connection_handler_manager.h"  // Connection_handler_manager
98 #include "sql/conn_handler/socket_connection.h"  // MY_BIND_ALL_ADDRESSES
99 #include "sql/derror.h"                          // read_texts
100 #include "sql/discrete_interval.h"
101 #include "sql/events.h"          // Events
102 #include "sql/hostname_cache.h"  // host_cache_resize
103 #include "sql/log.h"
104 #include "sql/log_event.h"  // MAX_MAX_ALLOWED_PACKET
105 #include "sql/mdl.h"
106 #include "sql/my_decimal.h"
107 #include "sql/opt_trace_context.h"
108 #include "sql/options_mysqld.h"
109 #include "sql/protocol_classic.h"
110 #include "sql/psi_memory_key.h"
111 #include "sql/query_options.h"
112 #include "sql/rpl_group_replication.h"  // is_group_replication_running
113 #include "sql/rpl_info_factory.h"       // Rpl_info_factory
114 #include "sql/rpl_info_handler.h"       // INFO_REPOSITORY_TABLE
115 #include "sql/rpl_log_encryption.h"
116 #include "sql/rpl_mi.h"                 // Master_info
117 #include "sql/rpl_msr.h"                // channel_map
118 #include "sql/rpl_mts_submode.h"        // MTS_PARALLEL_TYPE_DB_NAME
119 #include "sql/rpl_rli.h"                // Relay_log_info
120 #include "sql/rpl_slave.h"              // SLAVE_THD_TYPE
121 #include "sql/rpl_write_set_handler.h"  // transaction_write_set_hashing_algorithms
122 #include "sql/server_component/log_builtins_filter_imp.h"  // until we have pluggable variables
123 #include "sql/server_component/log_builtins_imp.h"
124 #include "sql/session_tracker.h"
125 #include "sql/sp_head.h"          // SP_PSI_STATEMENT_INFO_COUNT
126 #include "sql/sql_backup_lock.h"  // is_instance_backup_locked
127 #include "sql/sql_lex.h"
128 #include "sql/sql_locale.h"     // my_locale_by_number
129 #include "sql/sql_parse.h"      // killall_non_super_threads
130 #include "sql/sql_tmp_table.h"  // internal_tmp_mem_storage_engine_names
131 #include "sql/ssl_acceptor_context_operator.h"
132 #include "sql/system_variables.h"
133 #include "sql/table_cache.h"  // Table_cache_manager
134 #include "sql/transaction.h"  // trans_commit_stmt
135 #include "sql/transaction_info.h"
136 #include "sql/xa.h"
137 #include "template_utils.h"  // pointer_cast
138 #include "thr_lock.h"
139 #ifdef _WIN32
140 #include "sql/named_pipe.h"
141 #endif
142 
143 #ifdef WITH_LOCK_ORDER
144 #include "sql/debug_lock_order.h"
145 #endif /* WITH_LOCK_ORDER */
146 
147 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
148 #include "storage/perfschema/pfs_server.h"
149 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
150 
151 TYPELIB bool_typelib = {array_elements(bool_values) - 1, "", bool_values,
152                         nullptr};
153 
update_buffer_size(THD *,KEY_CACHE * key_cache,ptrdiff_t offset MY_ATTRIBUTE ((unused)),ulonglong new_value)154 static bool update_buffer_size(THD *, KEY_CACHE *key_cache,
155                                ptrdiff_t offset MY_ATTRIBUTE((unused)),
156                                ulonglong new_value) {
157   bool error = false;
158   DBUG_ASSERT(offset == offsetof(KEY_CACHE, param_buff_size));
159 
160   if (new_value == 0) {
161     if (key_cache == dflt_key_cache) {
162       my_error(ER_WARN_CANT_DROP_DEFAULT_KEYCACHE, MYF(0));
163       return true;
164     }
165 
166     if (key_cache->key_cache_inited)  // If initied
167     {
168       /*
169         Move tables using this key cache to the default key cache
170         and clear the old key cache.
171       */
172       key_cache->in_init = true;
173       mysql_mutex_unlock(&LOCK_global_system_variables);
174       key_cache->param_buff_size = 0;
175       ha_resize_key_cache(key_cache);
176       ha_change_key_cache(key_cache, dflt_key_cache);
177       /*
178         We don't delete the key cache as some running threads my still be in
179         the key cache code with a pointer to the deleted (empty) key cache
180       */
181       mysql_mutex_lock(&LOCK_global_system_variables);
182       key_cache->in_init = false;
183     }
184     return error;
185   }
186 
187   key_cache->param_buff_size = new_value;
188 
189   /* If key cache didn't exist initialize it, else resize it */
190   key_cache->in_init = true;
191   mysql_mutex_unlock(&LOCK_global_system_variables);
192 
193   if (!key_cache->key_cache_inited)
194     error = ha_init_key_cache(nullptr, key_cache);
195   else
196     error = ha_resize_key_cache(key_cache);
197 
198   mysql_mutex_lock(&LOCK_global_system_variables);
199   key_cache->in_init = false;
200 
201   return error;
202 }
203 
update_keycache_param(THD *,KEY_CACHE * key_cache,ptrdiff_t offset,ulonglong new_value)204 static bool update_keycache_param(THD *, KEY_CACHE *key_cache, ptrdiff_t offset,
205                                   ulonglong new_value) {
206   bool error = false;
207   DBUG_ASSERT(offset != offsetof(KEY_CACHE, param_buff_size));
208 
209   keycache_var(key_cache, offset) = new_value;
210 
211   key_cache->in_init = true;
212   mysql_mutex_unlock(&LOCK_global_system_variables);
213   error = ha_resize_key_cache(key_cache);
214 
215   mysql_mutex_lock(&LOCK_global_system_variables);
216   key_cache->in_init = false;
217 
218   return error;
219 }
220 
221 /**
222   Check if REPLICATION_APPLIER granted. Throw SQL error if not.
223 
224   Use this when setting session variables that are to be protected within
225   replication applier context.
226 
227   @note For compatibility we also accept SUPER.
228 
229   @retval true failure
230   @retval false success
231 
232   @param self the system variable to set value for
233   @param thd the session context
234   @param setv the SET operations metadata
235  */
check_session_admin_or_replication_applier(sys_var * self MY_ATTRIBUTE ((unused)),THD * thd,set_var * setv)236 static bool check_session_admin_or_replication_applier(
237     sys_var *self MY_ATTRIBUTE((unused)), THD *thd, set_var *setv) {
238   DBUG_ASSERT(self->scope() != sys_var::GLOBAL);
239   Security_context *sctx = thd->security_context();
240   if ((setv->type == OPT_SESSION || setv->type == OPT_DEFAULT) &&
241       !sctx->has_global_grant(STRING_WITH_LEN("REPLICATION_APPLIER")).first &&
242       !sctx->has_global_grant(STRING_WITH_LEN("SESSION_VARIABLES_ADMIN"))
243            .first &&
244       !sctx->has_global_grant(STRING_WITH_LEN("SYSTEM_VARIABLES_ADMIN"))
245            .first &&
246       !sctx->check_access(SUPER_ACL)) {
247     my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0),
248              "SUPER, SYSTEM_VARIABLES_ADMIN, SESSION_VARIABLES_ADMIN or "
249              "REPLICATION_APPLIER");
250     return true;
251   }
252   return false;
253 }
254 
255 /**
256   Check if SESSION_VARIABLES_ADMIN granted. Throw SQL error if not.
257 
258   Use this when setting session variables that are sensitive and should
259   be protected.
260 
261   We also accept SYSTEM_VARIABLES_ADMIN since it doesn't make a lot of
262   sense to be allowed to set the global variable and not the session ones.
263 
264   @note For compatibility we also accept SUPER.
265 
266   @retval true failure
267   @retval false success
268 
269   @param self the system variable to set value for
270   @param thd the session context
271   @param setv the SET operations metadata
272  */
check_session_admin(sys_var * self MY_ATTRIBUTE ((unused)),THD * thd,set_var * setv)273 static bool check_session_admin(sys_var *self MY_ATTRIBUTE((unused)), THD *thd,
274                                 set_var *setv) {
275   DBUG_ASSERT(self->scope() !=
276               sys_var::GLOBAL);  // don't abuse check_session_admin()
277   Security_context *sctx = thd->security_context();
278   if ((setv->type == OPT_SESSION || setv->type == OPT_DEFAULT) &&
279       !sctx->has_global_grant(STRING_WITH_LEN("SESSION_VARIABLES_ADMIN"))
280            .first &&
281       !sctx->has_global_grant(STRING_WITH_LEN("SYSTEM_VARIABLES_ADMIN"))
282            .first &&
283       !sctx->check_access(SUPER_ACL)) {
284     my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0),
285              "SUPER, SYSTEM_VARIABLES_ADMIN or SESSION_VARIABLES_ADMIN");
286     return true;
287   }
288   return false;
289 }
290 
291 /*
292   The rule for this file: everything should be 'static'. When a sys_var
293   variable or a function from this file is - in very rare cases - needed
294   elsewhere it should be explicitly declared 'export' here to show that it's
295   not a mistakenly forgotten 'static' keyword.
296 */
297 #define export /* not static */
298 
299 #ifdef WITH_LOCK_ORDER
300 
301 #define LO_TRAILING_PROPERTIES                                          \
302   NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(NULL), ON_UPDATE(NULL), NULL, \
303       sys_var::PARSE_EARLY
304 
305 static Sys_var_bool Sys_lo_enabled("lock_order", "Enable the lock order.",
306                                    READ_ONLY GLOBAL_VAR(lo_param.m_enabled),
307                                    CMD_LINE(OPT_ARG), DEFAULT(false),
308                                    LO_TRAILING_PROPERTIES);
309 
310 static Sys_var_charptr Sys_lo_out_dir("lock_order_output_directory",
311                                       "Lock order output directory.",
312                                       READ_ONLY GLOBAL_VAR(lo_param.m_out_dir),
313                                       CMD_LINE(OPT_ARG), IN_FS_CHARSET,
314                                       DEFAULT(nullptr), LO_TRAILING_PROPERTIES);
315 
316 static Sys_var_charptr Sys_lo_dep_1(
317     "lock_order_dependencies", "Lock order dependencies file.",
318     READ_ONLY GLOBAL_VAR(lo_param.m_dependencies_1), CMD_LINE(OPT_ARG),
319     IN_FS_CHARSET, DEFAULT(nullptr), LO_TRAILING_PROPERTIES);
320 
321 static Sys_var_charptr Sys_lo_dep_2(
322     "lock_order_extra_dependencies", "Lock order extra dependencies file.",
323     READ_ONLY GLOBAL_VAR(lo_param.m_dependencies_2), CMD_LINE(OPT_ARG),
324     IN_FS_CHARSET, DEFAULT(nullptr), LO_TRAILING_PROPERTIES);
325 
326 static Sys_var_bool Sys_lo_print_txt("lock_order_print_txt",
327                                      "Print the lock_order.txt file.",
328                                      READ_ONLY GLOBAL_VAR(lo_param.m_print_txt),
329                                      CMD_LINE(OPT_ARG), DEFAULT(false),
330                                      LO_TRAILING_PROPERTIES);
331 
332 static Sys_var_bool Sys_lo_trace_loop(
333     "lock_order_trace_loop", "Enable tracing for all loops.",
334     READ_ONLY GLOBAL_VAR(lo_param.m_trace_loop), CMD_LINE(OPT_ARG),
335     DEFAULT(false), LO_TRAILING_PROPERTIES);
336 
337 static Sys_var_bool Sys_lo_debug_loop(
338     "lock_order_debug_loop", "Enable debugging for all loops.",
339     READ_ONLY GLOBAL_VAR(lo_param.m_debug_loop), CMD_LINE(OPT_ARG),
340     DEFAULT(false), LO_TRAILING_PROPERTIES);
341 
342 static Sys_var_bool Sys_lo_trace_missing_arc(
343     "lock_order_trace_missing_arc", "Enable tracing for all missing arcs.",
344     READ_ONLY GLOBAL_VAR(lo_param.m_trace_missing_arc), CMD_LINE(OPT_ARG),
345     DEFAULT(true), LO_TRAILING_PROPERTIES);
346 
347 static Sys_var_bool Sys_lo_debug_missing_arc(
348     "lock_order_debug_missing_arc", "Enable debugging for all missing arcs.",
349     READ_ONLY GLOBAL_VAR(lo_param.m_debug_missing_arc), CMD_LINE(OPT_ARG),
350     DEFAULT(false), LO_TRAILING_PROPERTIES);
351 
352 static Sys_var_bool Sys_lo_trace_missing_unlock(
353     "lock_order_trace_missing_unlock", "Enable tracing for all missing unlocks",
354     READ_ONLY GLOBAL_VAR(lo_param.m_trace_missing_unlock), CMD_LINE(OPT_ARG),
355     DEFAULT(true), LO_TRAILING_PROPERTIES);
356 
357 static Sys_var_bool Sys_lo_debug_missing_unlock(
358     "lock_order_debug_missing_unlock",
359     "Enable debugging for all missing unlocks",
360     READ_ONLY GLOBAL_VAR(lo_param.m_debug_missing_unlock), CMD_LINE(OPT_ARG),
361     DEFAULT(false), LO_TRAILING_PROPERTIES);
362 
363 static Sys_var_bool Sys_lo_trace_missing_key(
364     "lock_order_trace_missing_key",
365     "Enable trace for missing performance schema keys",
366     READ_ONLY GLOBAL_VAR(lo_param.m_trace_missing_key), CMD_LINE(OPT_ARG),
367     DEFAULT(false), LO_TRAILING_PROPERTIES);
368 
369 static Sys_var_bool Sys_lo_debug_missing_key(
370     "lock_order_debug_missing_key",
371     "Enable debugging for missing performance schema keys",
372     READ_ONLY GLOBAL_VAR(lo_param.m_debug_missing_key), CMD_LINE(OPT_ARG),
373     DEFAULT(false), LO_TRAILING_PROPERTIES);
374 
375 #endif /* WITH_LOCK_ORDER */
376 
377 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
378 
379 #define PFS_TRAILING_PROPERTIES                                         \
380   NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(NULL), ON_UPDATE(NULL), NULL, \
381       sys_var::PARSE_EARLY
382 
383 static Sys_var_bool Sys_pfs_enabled("performance_schema",
384                                     "Enable the performance schema.",
385                                     READ_ONLY GLOBAL_VAR(pfs_param.m_enabled),
386                                     CMD_LINE(OPT_ARG), DEFAULT(true),
387                                     PFS_TRAILING_PROPERTIES);
388 
389 static Sys_var_charptr Sys_pfs_instrument(
390     "performance_schema_instrument",
391     "Default startup value for a performance schema instrument.",
392     READ_ONLY NOT_VISIBLE GLOBAL_VAR(pfs_param.m_pfs_instrument),
393     CMD_LINE(OPT_ARG, OPT_PFS_INSTRUMENT), IN_FS_CHARSET, DEFAULT(""),
394     PFS_TRAILING_PROPERTIES);
395 
396 static Sys_var_bool Sys_pfs_consumer_events_stages_current(
397     "performance_schema_consumer_events_stages_current",
398     "Default startup value for the events_stages_current consumer.",
399     READ_ONLY NOT_VISIBLE
400         GLOBAL_VAR(pfs_param.m_consumer_events_stages_current_enabled),
401     CMD_LINE(OPT_ARG), DEFAULT(false), PFS_TRAILING_PROPERTIES);
402 
403 static Sys_var_bool Sys_pfs_consumer_events_stages_history(
404     "performance_schema_consumer_events_stages_history",
405     "Default startup value for the events_stages_history consumer.",
406     READ_ONLY NOT_VISIBLE
407         GLOBAL_VAR(pfs_param.m_consumer_events_stages_history_enabled),
408     CMD_LINE(OPT_ARG), DEFAULT(false), PFS_TRAILING_PROPERTIES);
409 
410 static Sys_var_bool Sys_pfs_consumer_events_stages_history_long(
411     "performance_schema_consumer_events_stages_history_long",
412     "Default startup value for the events_stages_history_long consumer.",
413     READ_ONLY NOT_VISIBLE
414         GLOBAL_VAR(pfs_param.m_consumer_events_stages_history_long_enabled),
415     CMD_LINE(OPT_ARG), DEFAULT(false), PFS_TRAILING_PROPERTIES);
416 
417 static Sys_var_bool Sys_pfs_consumer_events_statements_current(
418     "performance_schema_consumer_events_statements_current",
419     "Default startup value for the events_statements_current consumer.",
420     READ_ONLY NOT_VISIBLE
421         GLOBAL_VAR(pfs_param.m_consumer_events_statements_current_enabled),
422     CMD_LINE(OPT_ARG), DEFAULT(true), PFS_TRAILING_PROPERTIES);
423 
424 static Sys_var_bool Sys_pfs_consumer_events_statements_history(
425     "performance_schema_consumer_events_statements_history",
426     "Default startup value for the events_statements_history consumer.",
427     READ_ONLY NOT_VISIBLE
428         GLOBAL_VAR(pfs_param.m_consumer_events_statements_history_enabled),
429     CMD_LINE(OPT_ARG), DEFAULT(true), PFS_TRAILING_PROPERTIES);
430 
431 static Sys_var_bool Sys_pfs_consumer_events_statements_history_long(
432     "performance_schema_consumer_events_statements_history_long",
433     "Default startup value for the events_statements_history_long consumer.",
434     READ_ONLY NOT_VISIBLE
435         GLOBAL_VAR(pfs_param.m_consumer_events_statements_history_long_enabled),
436     CMD_LINE(OPT_ARG), DEFAULT(false), PFS_TRAILING_PROPERTIES);
437 
438 static Sys_var_bool Sys_pfs_consumer_events_transactions_current(
439     "performance_schema_consumer_events_transactions_current",
440     "Default startup value for the events_transactions_current consumer.",
441     READ_ONLY NOT_VISIBLE
442         GLOBAL_VAR(pfs_param.m_consumer_events_transactions_current_enabled),
443     CMD_LINE(OPT_ARG), DEFAULT(true), PFS_TRAILING_PROPERTIES);
444 
445 static Sys_var_bool Sys_pfs_consumer_events_transactions_history(
446     "performance_schema_consumer_events_transactions_history",
447     "Default startup value for the events_transactions_history consumer.",
448     READ_ONLY NOT_VISIBLE
449         GLOBAL_VAR(pfs_param.m_consumer_events_transactions_history_enabled),
450     CMD_LINE(OPT_ARG), DEFAULT(true), PFS_TRAILING_PROPERTIES);
451 
452 static Sys_var_bool Sys_pfs_consumer_events_transactions_history_long(
453     "performance_schema_consumer_events_transactions_history_long",
454     "Default startup value for the events_transactions_history_long consumer.",
455     READ_ONLY NOT_VISIBLE GLOBAL_VAR(
456         pfs_param.m_consumer_events_transactions_history_long_enabled),
457     CMD_LINE(OPT_ARG), DEFAULT(false), PFS_TRAILING_PROPERTIES);
458 
459 static Sys_var_bool Sys_pfs_consumer_events_waits_current(
460     "performance_schema_consumer_events_waits_current",
461     "Default startup value for the events_waits_current consumer.",
462     READ_ONLY NOT_VISIBLE
463         GLOBAL_VAR(pfs_param.m_consumer_events_waits_current_enabled),
464     CMD_LINE(OPT_ARG), DEFAULT(false), PFS_TRAILING_PROPERTIES);
465 
466 static Sys_var_bool Sys_pfs_consumer_events_waits_history(
467     "performance_schema_consumer_events_waits_history",
468     "Default startup value for the events_waits_history consumer.",
469     READ_ONLY NOT_VISIBLE
470         GLOBAL_VAR(pfs_param.m_consumer_events_waits_history_enabled),
471     CMD_LINE(OPT_ARG), DEFAULT(false), PFS_TRAILING_PROPERTIES);
472 
473 static Sys_var_bool Sys_pfs_consumer_events_waits_history_long(
474     "performance_schema_consumer_events_waits_history_long",
475     "Default startup value for the events_waits_history_long consumer.",
476     READ_ONLY NOT_VISIBLE
477         GLOBAL_VAR(pfs_param.m_consumer_events_waits_history_long_enabled),
478     CMD_LINE(OPT_ARG), DEFAULT(false), PFS_TRAILING_PROPERTIES);
479 
480 static Sys_var_bool Sys_pfs_consumer_global_instrumentation(
481     "performance_schema_consumer_global_instrumentation",
482     "Default startup value for the global_instrumentation consumer.",
483     READ_ONLY NOT_VISIBLE
484         GLOBAL_VAR(pfs_param.m_consumer_global_instrumentation_enabled),
485     CMD_LINE(OPT_ARG), DEFAULT(true), PFS_TRAILING_PROPERTIES);
486 
487 static Sys_var_bool Sys_pfs_consumer_thread_instrumentation(
488     "performance_schema_consumer_thread_instrumentation",
489     "Default startup value for the thread_instrumentation consumer.",
490     READ_ONLY NOT_VISIBLE
491         GLOBAL_VAR(pfs_param.m_consumer_thread_instrumentation_enabled),
492     CMD_LINE(OPT_ARG), DEFAULT(true), PFS_TRAILING_PROPERTIES);
493 
494 static Sys_var_bool Sys_pfs_consumer_statement_digest(
495     "performance_schema_consumer_statements_digest",
496     "Default startup value for the statements_digest consumer.",
497     READ_ONLY NOT_VISIBLE
498         GLOBAL_VAR(pfs_param.m_consumer_statement_digest_enabled),
499     CMD_LINE(OPT_ARG), DEFAULT(true), PFS_TRAILING_PROPERTIES);
500 
501 static Sys_var_long Sys_pfs_events_waits_history_long_size(
502     "performance_schema_events_waits_history_long_size",
503     "Number of rows in EVENTS_WAITS_HISTORY_LONG."
504     " Use 0 to disable, -1 for automated sizing.",
505     READ_ONLY GLOBAL_VAR(pfs_param.m_events_waits_history_long_sizing),
506     CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024 * 1024),
507     DEFAULT(PFS_AUTOSIZE_VALUE), BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
508 
509 static Sys_var_long Sys_pfs_events_waits_history_size(
510     "performance_schema_events_waits_history_size",
511     "Number of rows per thread in EVENTS_WAITS_HISTORY."
512     " Use 0 to disable, -1 for automated sizing.",
513     READ_ONLY GLOBAL_VAR(pfs_param.m_events_waits_history_sizing),
514     CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024), DEFAULT(PFS_AUTOSIZE_VALUE),
515     BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
516 
517 static Sys_var_ulong Sys_pfs_max_cond_classes(
518     "performance_schema_max_cond_classes",
519     "Maximum number of condition instruments.",
520     READ_ONLY GLOBAL_VAR(pfs_param.m_cond_class_sizing), CMD_LINE(REQUIRED_ARG),
521     VALID_RANGE(0, 1024), DEFAULT(PFS_MAX_COND_CLASS), BLOCK_SIZE(1),
522     PFS_TRAILING_PROPERTIES);
523 
524 static Sys_var_long Sys_pfs_max_cond_instances(
525     "performance_schema_max_cond_instances",
526     "Maximum number of instrumented condition objects."
527     " Use 0 to disable, -1 for automated scaling.",
528     READ_ONLY GLOBAL_VAR(pfs_param.m_cond_sizing), CMD_LINE(REQUIRED_ARG),
529     VALID_RANGE(-1, 1024 * 1024), DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1),
530     PFS_TRAILING_PROPERTIES);
531 
532 static Sys_var_long Sys_pfs_max_program_instances(
533     "performance_schema_max_program_instances",
534     "Maximum number of instrumented programs."
535     " Use 0 to disable, -1 for automated scaling.",
536     READ_ONLY GLOBAL_VAR(pfs_param.m_program_sizing), CMD_LINE(REQUIRED_ARG),
537     VALID_RANGE(-1, 1024 * 1024), DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1),
538     PFS_TRAILING_PROPERTIES);
539 
540 static constexpr int num_prepared_stmt_limit = 4 * 1024 * 1024;
541 
542 static Sys_var_long Sys_pfs_max_prepared_stmt_instances(
543     "performance_schema_max_prepared_statements_instances",
544     "Maximum number of instrumented prepared statements."
545     " Use 0 to disable, -1 for automated scaling.",
546     READ_ONLY GLOBAL_VAR(pfs_param.m_prepared_stmt_sizing),
547     CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, num_prepared_stmt_limit),
548     DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
549 
550 static Sys_var_ulong Sys_pfs_max_file_classes(
551     "performance_schema_max_file_classes",
552     "Maximum number of file instruments.",
553     READ_ONLY GLOBAL_VAR(pfs_param.m_file_class_sizing), CMD_LINE(REQUIRED_ARG),
554     VALID_RANGE(0, 1024), DEFAULT(PFS_MAX_FILE_CLASS), BLOCK_SIZE(1),
555     PFS_TRAILING_PROPERTIES);
556 
557 static Sys_var_ulong Sys_pfs_max_file_handles(
558     "performance_schema_max_file_handles",
559     "Maximum number of opened instrumented files.",
560     READ_ONLY GLOBAL_VAR(pfs_param.m_file_handle_sizing),
561     CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024 * 1024),
562     DEFAULT(PFS_MAX_FILE_HANDLE), BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
563 
564 static Sys_var_long Sys_pfs_max_file_instances(
565     "performance_schema_max_file_instances",
566     "Maximum number of instrumented files."
567     " Use 0 to disable, -1 for automated scaling.",
568     READ_ONLY GLOBAL_VAR(pfs_param.m_file_sizing), CMD_LINE(REQUIRED_ARG),
569     VALID_RANGE(-1, 1024 * 1024), DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1),
570     PFS_TRAILING_PROPERTIES);
571 
572 static Sys_var_long Sys_pfs_max_sockets(
573     "performance_schema_max_socket_instances",
574     "Maximum number of opened instrumented sockets."
575     " Use 0 to disable, -1 for automated scaling.",
576     READ_ONLY GLOBAL_VAR(pfs_param.m_socket_sizing), CMD_LINE(REQUIRED_ARG),
577     VALID_RANGE(-1, 1024 * 1024), DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1),
578     PFS_TRAILING_PROPERTIES);
579 
580 static Sys_var_ulong Sys_pfs_max_socket_classes(
581     "performance_schema_max_socket_classes",
582     "Maximum number of socket instruments.",
583     READ_ONLY GLOBAL_VAR(pfs_param.m_socket_class_sizing),
584     CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024), DEFAULT(PFS_MAX_SOCKET_CLASS),
585     BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
586 
587 static Sys_var_ulong Sys_pfs_max_mutex_classes(
588     "performance_schema_max_mutex_classes",
589     "Maximum number of mutex instruments.",
590     READ_ONLY GLOBAL_VAR(pfs_param.m_mutex_class_sizing),
591     CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024), DEFAULT(PFS_MAX_MUTEX_CLASS),
592     BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
593 
594 static Sys_var_long Sys_pfs_max_mutex_instances(
595     "performance_schema_max_mutex_instances",
596     "Maximum number of instrumented MUTEX objects."
597     " Use 0 to disable, -1 for automated scaling.",
598     READ_ONLY GLOBAL_VAR(pfs_param.m_mutex_sizing), CMD_LINE(REQUIRED_ARG),
599     VALID_RANGE(-1, 100 * 1024 * 1024), DEFAULT(PFS_AUTOSCALE_VALUE),
600     BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
601 
602 static Sys_var_ulong Sys_pfs_max_rwlock_classes(
603     "performance_schema_max_rwlock_classes",
604     "Maximum number of rwlock instruments.",
605     READ_ONLY GLOBAL_VAR(pfs_param.m_rwlock_class_sizing),
606     CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024), DEFAULT(PFS_MAX_RWLOCK_CLASS),
607     BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
608 
609 static Sys_var_long Sys_pfs_max_rwlock_instances(
610     "performance_schema_max_rwlock_instances",
611     "Maximum number of instrumented RWLOCK objects."
612     " Use 0 to disable, -1 for automated scaling.",
613     READ_ONLY GLOBAL_VAR(pfs_param.m_rwlock_sizing), CMD_LINE(REQUIRED_ARG),
614     VALID_RANGE(-1, 100 * 1024 * 1024), DEFAULT(PFS_AUTOSCALE_VALUE),
615     BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
616 
617 static Sys_var_long Sys_pfs_max_table_handles(
618     "performance_schema_max_table_handles",
619     "Maximum number of opened instrumented tables."
620     " Use 0 to disable, -1 for automated scaling.",
621     READ_ONLY GLOBAL_VAR(pfs_param.m_table_sizing), CMD_LINE(REQUIRED_ARG),
622     VALID_RANGE(-1, 1024 * 1024), DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1),
623     PFS_TRAILING_PROPERTIES);
624 
625 static Sys_var_long Sys_pfs_max_table_instances(
626     "performance_schema_max_table_instances",
627     "Maximum number of instrumented tables."
628     " Use 0 to disable, -1 for automated scaling.",
629     READ_ONLY GLOBAL_VAR(pfs_param.m_table_share_sizing),
630     CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024 * 1024),
631     DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
632 
633 static Sys_var_long Sys_pfs_max_table_lock_stat(
634     "performance_schema_max_table_lock_stat",
635     "Maximum number of lock statistics for instrumented tables."
636     " Use 0 to disable, -1 for automated scaling.",
637     READ_ONLY GLOBAL_VAR(pfs_param.m_table_lock_stat_sizing),
638     CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024 * 1024),
639     DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
640 
641 static Sys_var_long Sys_pfs_max_index_stat(
642     "performance_schema_max_index_stat",
643     "Maximum number of index statistics for instrumented tables."
644     " Use 0 to disable, -1 for automated scaling.",
645     READ_ONLY GLOBAL_VAR(pfs_param.m_index_stat_sizing), CMD_LINE(REQUIRED_ARG),
646     VALID_RANGE(-1, 1024 * 1024), DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1),
647     PFS_TRAILING_PROPERTIES);
648 
649 static Sys_var_ulong Sys_pfs_max_thread_classes(
650     "performance_schema_max_thread_classes",
651     "Maximum number of thread instruments.",
652     READ_ONLY GLOBAL_VAR(pfs_param.m_thread_class_sizing),
653     CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024), DEFAULT(PFS_MAX_THREAD_CLASS),
654     BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
655 
656 static Sys_var_long Sys_pfs_max_thread_instances(
657     "performance_schema_max_thread_instances",
658     "Maximum number of instrumented threads."
659     " Use 0 to disable, -1 for automated scaling.",
660     READ_ONLY GLOBAL_VAR(pfs_param.m_thread_sizing), CMD_LINE(REQUIRED_ARG),
661     VALID_RANGE(-1, 1024 * 1024), DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1),
662     PFS_TRAILING_PROPERTIES);
663 
664 static Sys_var_long Sys_pfs_setup_actors_size(
665     "performance_schema_setup_actors_size",
666     "Maximum number of rows in SETUP_ACTORS."
667     " Use 0 to disable, -1 for automated scaling.",
668     READ_ONLY GLOBAL_VAR(pfs_param.m_setup_actor_sizing),
669     CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024 * 1024),
670     DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
671 
672 static Sys_var_long Sys_pfs_setup_objects_size(
673     "performance_schema_setup_objects_size",
674     "Maximum number of rows in SETUP_OBJECTS."
675     " Use 0 to disable, -1 for automated scaling.",
676     READ_ONLY GLOBAL_VAR(pfs_param.m_setup_object_sizing),
677     CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024 * 1024),
678     DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
679 
680 static Sys_var_long Sys_pfs_accounts_size(
681     "performance_schema_accounts_size",
682     "Maximum number of instrumented user@host accounts."
683     " Use 0 to disable, -1 for automated scaling.",
684     READ_ONLY GLOBAL_VAR(pfs_param.m_account_sizing), CMD_LINE(REQUIRED_ARG),
685     VALID_RANGE(-1, 1024 * 1024), DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1),
686     PFS_TRAILING_PROPERTIES);
687 
688 static Sys_var_long Sys_pfs_hosts_size(
689     "performance_schema_hosts_size",
690     "Maximum number of instrumented hosts."
691     " Use 0 to disable, -1 for automated scaling.",
692     READ_ONLY GLOBAL_VAR(pfs_param.m_host_sizing), CMD_LINE(REQUIRED_ARG),
693     VALID_RANGE(-1, 1024 * 1024), DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1),
694     PFS_TRAILING_PROPERTIES);
695 
696 static Sys_var_long Sys_pfs_users_size(
697     "performance_schema_users_size",
698     "Maximum number of instrumented users."
699     " Use 0 to disable, -1 for automated scaling.",
700     READ_ONLY GLOBAL_VAR(pfs_param.m_user_sizing), CMD_LINE(REQUIRED_ARG),
701     VALID_RANGE(-1, 1024 * 1024), DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1),
702     PFS_TRAILING_PROPERTIES);
703 
704 static Sys_var_ulong Sys_pfs_max_stage_classes(
705     "performance_schema_max_stage_classes",
706     "Maximum number of stage instruments.",
707     READ_ONLY GLOBAL_VAR(pfs_param.m_stage_class_sizing),
708     CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024), DEFAULT(PFS_MAX_STAGE_CLASS),
709     BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
710 
711 static Sys_var_long Sys_pfs_events_stages_history_long_size(
712     "performance_schema_events_stages_history_long_size",
713     "Number of rows in EVENTS_STAGES_HISTORY_LONG."
714     " Use 0 to disable, -1 for automated sizing.",
715     READ_ONLY GLOBAL_VAR(pfs_param.m_events_stages_history_long_sizing),
716     CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024 * 1024),
717     DEFAULT(PFS_AUTOSIZE_VALUE), BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
718 
719 static Sys_var_long Sys_pfs_events_stages_history_size(
720     "performance_schema_events_stages_history_size",
721     "Number of rows per thread in EVENTS_STAGES_HISTORY."
722     " Use 0 to disable, -1 for automated sizing.",
723     READ_ONLY GLOBAL_VAR(pfs_param.m_events_stages_history_sizing),
724     CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024), DEFAULT(PFS_AUTOSIZE_VALUE),
725     BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
726 
727 /**
728   Variable performance_schema_max_statement_classes.
729   The default number of statement classes is the sum of:
730   - COM_END for all regular "statement/com/...",
731   - 1 for "statement/com/new_packet", for unknown enum_server_command
732   - 1 for "statement/com/Error", for invalid enum_server_command
733   - SQLCOM_END for all regular "statement/sql/...",
734   - 1 for "statement/sql/error", for invalid enum_sql_command.
735   - SP_PSI_STATEMENT_INFO_COUNT for "statement/sp/...".
736   - CLONE_PSI_STATEMENT_COUNT for "statement/clone/...".
737   - 1 for "statement/rpl/relay_log", for replicated statements.
738   - 1 for "statement/scheduler/event", for scheduled events.
739 */
740 static Sys_var_ulong Sys_pfs_max_statement_classes(
741     "performance_schema_max_statement_classes",
742     "Maximum number of statement instruments.",
743     READ_ONLY GLOBAL_VAR(pfs_param.m_statement_class_sizing),
744     CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 256),
745     DEFAULT((ulong)SQLCOM_END + (ulong)COM_END + 5 +
746             SP_PSI_STATEMENT_INFO_COUNT + CLONE_PSI_STATEMENT_COUNT),
747     BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
748 
749 static Sys_var_long Sys_pfs_events_statements_history_long_size(
750     "performance_schema_events_statements_history_long_size",
751     "Number of rows in EVENTS_STATEMENTS_HISTORY_LONG."
752     " Use 0 to disable, -1 for automated sizing.",
753     READ_ONLY GLOBAL_VAR(pfs_param.m_events_statements_history_long_sizing),
754     CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024 * 1024),
755     DEFAULT(PFS_AUTOSIZE_VALUE), BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
756 
757 static Sys_var_long Sys_pfs_events_statements_history_size(
758     "performance_schema_events_statements_history_size",
759     "Number of rows per thread in EVENTS_STATEMENTS_HISTORY."
760     " Use 0 to disable, -1 for automated sizing.",
761     READ_ONLY GLOBAL_VAR(pfs_param.m_events_statements_history_sizing),
762     CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024), DEFAULT(PFS_AUTOSIZE_VALUE),
763     BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
764 
765 static Sys_var_ulong Sys_pfs_statement_stack_size(
766     "performance_schema_max_statement_stack",
767     "Number of rows per thread in EVENTS_STATEMENTS_CURRENT.",
768     READ_ONLY GLOBAL_VAR(pfs_param.m_statement_stack_sizing),
769     CMD_LINE(REQUIRED_ARG), VALID_RANGE(1, 256),
770     DEFAULT(PFS_STATEMENTS_STACK_SIZE), BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
771 
772 static Sys_var_ulong Sys_pfs_max_memory_classes(
773     "performance_schema_max_memory_classes",
774     "Maximum number of memory pool instruments.",
775     READ_ONLY GLOBAL_VAR(pfs_param.m_memory_class_sizing),
776     CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024), DEFAULT(PFS_MAX_MEMORY_CLASS),
777     BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
778 
779 static Sys_var_long Sys_pfs_digest_size(
780     "performance_schema_digests_size",
781     "Size of the statement digest."
782     " Use 0 to disable, -1 for automated sizing.",
783     READ_ONLY GLOBAL_VAR(pfs_param.m_digest_sizing), CMD_LINE(REQUIRED_ARG),
784     VALID_RANGE(-1, 1024 * 1024), DEFAULT(PFS_AUTOSIZE_VALUE), BLOCK_SIZE(1),
785     PFS_TRAILING_PROPERTIES);
786 
787 static Sys_var_long Sys_pfs_events_transactions_history_long_size(
788     "performance_schema_events_transactions_history_long_size",
789     "Number of rows in EVENTS_TRANSACTIONS_HISTORY_LONG."
790     " Use 0 to disable, -1 for automated sizing.",
791     READ_ONLY GLOBAL_VAR(pfs_param.m_events_transactions_history_long_sizing),
792     CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024 * 1024),
793     DEFAULT(PFS_AUTOSIZE_VALUE), BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
794 
795 static Sys_var_long Sys_pfs_events_transactions_history_size(
796     "performance_schema_events_transactions_history_size",
797     "Number of rows per thread in EVENTS_TRANSACTIONS_HISTORY."
798     " Use 0 to disable, -1 for automated sizing.",
799     READ_ONLY GLOBAL_VAR(pfs_param.m_events_transactions_history_sizing),
800     CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024), DEFAULT(PFS_AUTOSIZE_VALUE),
801     BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
802 
803 static Sys_var_long Sys_pfs_max_digest_length(
804     "performance_schema_max_digest_length",
805     "Maximum length considered for digest text, when stored in "
806     "performance_schema tables.",
807     READ_ONLY GLOBAL_VAR(pfs_param.m_max_digest_length), CMD_LINE(REQUIRED_ARG),
808     VALID_RANGE(0, 1024 * 1024), DEFAULT(1024), BLOCK_SIZE(1),
809     PFS_TRAILING_PROPERTIES);
810 
811 static Sys_var_ulong Sys_pfs_max_digest_sample_age(
812     "performance_schema_max_digest_sample_age",
813     "The time in seconds after which a previous query sample is considered old."
814     " When the value is 0, queries are sampled once."
815     " When the value is greater than zero, queries are re sampled if the"
816     " last sample is more than performance_schema_max_digest_sample_age "
817     "seconds old.",
818     GLOBAL_VAR(pfs_param.m_max_digest_sample_age), CMD_LINE(REQUIRED_ARG),
819     VALID_RANGE(0, 1024 * 1024), DEFAULT(60), BLOCK_SIZE(1),
820     PFS_TRAILING_PROPERTIES);
821 
822 static Sys_var_long Sys_pfs_connect_attrs_size(
823     "performance_schema_session_connect_attrs_size",
824     "Size of session attribute string buffer per thread."
825     " Use 0 to disable, -1 for automated sizing.",
826     READ_ONLY GLOBAL_VAR(pfs_param.m_session_connect_attrs_sizing),
827     CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 1024 * 1024),
828     DEFAULT(PFS_AUTOSIZE_VALUE), BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
829 
830 static Sys_var_long Sys_pfs_max_metadata_locks(
831     "performance_schema_max_metadata_locks",
832     "Maximum number of metadata locks."
833     " Use 0 to disable, -1 for automated scaling.",
834     READ_ONLY GLOBAL_VAR(pfs_param.m_metadata_lock_sizing),
835     CMD_LINE(REQUIRED_ARG), VALID_RANGE(-1, 100 * 1024 * 1024),
836     DEFAULT(PFS_AUTOSCALE_VALUE), BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
837 
838 static Sys_var_long Sys_pfs_max_sql_text_length(
839     "performance_schema_max_sql_text_length",
840     "Maximum length of displayed sql text.",
841     READ_ONLY GLOBAL_VAR(pfs_param.m_max_sql_text_length),
842     CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 1024 * 1024), DEFAULT(1024),
843     BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
844 
845 static Sys_var_long Sys_pfs_error_size(
846     "performance_schema_error_size", "Number of server errors instrumented.",
847     READ_ONLY GLOBAL_VAR(pfs_param.m_error_sizing), CMD_LINE(REQUIRED_ARG),
848     VALID_RANGE(0, 1024 * 1024), DEFAULT(PFS_MAX_GLOBAL_SERVER_ERRORS),
849     BLOCK_SIZE(1), PFS_TRAILING_PROPERTIES);
850 
851 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
852 
853 static Sys_var_ulong Sys_auto_increment_increment(
854     "auto_increment_increment",
855     "Auto-increment columns are incremented by this",
856     HINT_UPDATEABLE SESSION_VAR(auto_increment_increment), CMD_LINE(OPT_ARG),
857     VALID_RANGE(1, 65535), DEFAULT(1), BLOCK_SIZE(1), NO_MUTEX_GUARD,
858     IN_BINLOG);
859 
860 static Sys_var_ulong Sys_auto_increment_offset(
861     "auto_increment_offset",
862     "Offset added to Auto-increment columns. Used when "
863     "auto-increment-increment != 1",
864     HINT_UPDATEABLE SESSION_VAR(auto_increment_offset), CMD_LINE(OPT_ARG),
865     VALID_RANGE(1, 65535), DEFAULT(1), BLOCK_SIZE(1), NO_MUTEX_GUARD,
866     IN_BINLOG);
867 
868 static Sys_var_bool Sys_windowing_use_high_precision(
869     "windowing_use_high_precision",
870     "For SQL window functions, determines whether to enable inversion "
871     "optimization for moving window frames also for floating values.",
872     HINT_UPDATEABLE SESSION_VAR(windowing_use_high_precision),
873     CMD_LINE(OPT_ARG), DEFAULT(true));
874 
875 static Sys_var_uint Sys_cte_max_recursion_depth(
876     "cte_max_recursion_depth",
877     "Abort a recursive common table expression "
878     "if it does more than this number of iterations.",
879     HINT_UPDATEABLE SESSION_VAR(cte_max_recursion_depth),
880     CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, UINT_MAX32), DEFAULT(1000),
881     BLOCK_SIZE(1));
882 
883 static Sys_var_bool Sys_automatic_sp_privileges(
884     "automatic_sp_privileges",
885     "Creating and dropping stored procedures alters ACLs",
886     GLOBAL_VAR(sp_automatic_privileges), CMD_LINE(OPT_ARG), DEFAULT(true));
887 
888 static Sys_var_ulong Sys_back_log(
889     "back_log",
890     "The number of outstanding connection requests "
891     "MySQL can have. This comes into play when the main MySQL thread "
892     "gets very many connection requests in a very short time",
893     READ_ONLY GLOBAL_VAR(back_log), CMD_LINE(REQUIRED_ARG),
894     VALID_RANGE(0, 65535), DEFAULT(0), BLOCK_SIZE(1));
895 
896 static Sys_var_charptr Sys_basedir(
897     "basedir",
898     "Path to installation directory. All paths are "
899     "usually resolved relative to this",
900     READ_ONLY NON_PERSIST GLOBAL_VAR(mysql_home_ptr),
901     CMD_LINE(REQUIRED_ARG, 'b'), IN_FS_CHARSET, DEFAULT(nullptr));
902 
903 static Sys_var_charptr Sys_default_authentication_plugin(
904     "default_authentication_plugin",
905     "The default authentication plugin "
906     "used by the server to hash the password.",
907     READ_ONLY NON_PERSIST GLOBAL_VAR(default_auth_plugin),
908     CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET, DEFAULT("caching_sha2_password"));
909 
910 static PolyLock_mutex Plock_default_password_lifetime(
911     &LOCK_default_password_lifetime);
912 static Sys_var_uint Sys_default_password_lifetime(
913     "default_password_lifetime",
914     "The number of days after which the "
915     "password will expire.",
916     GLOBAL_VAR(default_password_lifetime), CMD_LINE(REQUIRED_ARG),
917     VALID_RANGE(0, UINT_MAX16), DEFAULT(0), BLOCK_SIZE(1),
918     &Plock_default_password_lifetime);
919 
920 static Sys_var_charptr Sys_my_bind_addr(
921     "bind_address",
922     "IP address(es) to bind to. Syntax: address[,address]...,"
923     " where address can be an IPv4 address, IPv6 address,"
924     " host name or one of the wildcard values *, ::, 0.0.0.0."
925     " In case more than one address is specified in a"
926     " comma-separated list, wildcard values are not allowed."
927     " Every address can have optional network namespace separated"
928     " by the delimiter / from the address value. E.g., the following value"
929     " 192.168.1.1/red,172.16.1.1/green,193.168.1.1 specifies three IP"
930     " addresses to listen for incoming TCP connections two of that have"
931     " to be placed in corresponding namespaces: the address 192.168.1.1"
932     " must be placed into the namespace red and the address 172.16.1.1"
933     " must be placed into the namespace green. Using of network namespace"
934     " requires its support from underlying Operating System. Attempt to specify"
935     " a network namespace for a platform that doesn't support it results in"
936     " error during socket creation.",
937     READ_ONLY NON_PERSIST GLOBAL_VAR(my_bind_addr_str), CMD_LINE(REQUIRED_ARG),
938     IN_FS_CHARSET, DEFAULT(MY_BIND_ALL_ADDRESSES));
939 
940 static Sys_var_charptr Sys_admin_addr(
941     "admin_address",
942     "IP address to bind to for service connection. Address can be an IPv4"
943     " address, IPv6 address, or host name. Wildcard values *, ::, 0.0.0.0"
944     " are not allowed. Address value can have following optional network"
945     " namespace separated by the delimiter / from the address value."
946     " E.g., the following value 192.168.1.1/red specifies IP addresses to"
947     " listen for incoming TCP connections that have to be placed into"
948     " the namespace 'red'. Using of network namespace requires its support"
949     " from underlying Operating System. Attempt to specify a network namespace"
950     " for a platform that doesn't support it results in error during socket"
951     " creation.",
952     READ_ONLY NON_PERSIST GLOBAL_VAR(my_admin_bind_addr_str),
953     CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET, DEFAULT(nullptr));
954 
955 static Sys_var_uint Sys_admin_port(
956     "admin_port",
957     "Port number to use for service connection,"
958     " built-in default (" STRINGIFY_ARG(MYSQL_ADMIN_PORT) ")",
959     READ_ONLY NON_PERSIST GLOBAL_VAR(mysqld_admin_port), CMD_LINE(REQUIRED_ARG),
960     VALID_RANGE(0, 65535), DEFAULT(MYSQL_ADMIN_PORT), BLOCK_SIZE(1));
961 
962 static Sys_var_bool Sys_use_separate_thread_for_admin(
963     "create_admin_listener_thread",
964     "Use a dedicated thread for listening incoming connections on admin"
965     " interface",
966     READ_ONLY NON_PERSIST GLOBAL_VAR(listen_admin_interface_in_separate_thread),
967     CMD_LINE(OPT_ARG), DEFAULT(false));
968 
969 static Sys_var_bool Sys_password_require_current(
970     "password_require_current",
971     "Current password is needed to be specified in order to change it",
972     GLOBAL_VAR(password_require_current), CMD_LINE(OPT_ARG), DEFAULT(false));
973 
974 /**
975   Checks,
976   if there exists at least a partial revoke on a database at the time
977   of turning OFF the system variable "@@partial_revokes". If it does then
978   throw error.
979   if there exists at least a DB grant with wildcard entry at the time of
980   turning ON the system variable "@@partial_revokes". If it does then
981   throw error.
982 
983   @retval true failure
984   @retval false success
985 
986   @param self the system variable to set value for
987   @param thd the session context
988   @param setv the SET operations metadata
989 */
check_partial_revokes(sys_var * self,THD * thd,set_var * setv)990 static bool check_partial_revokes(sys_var *self, THD *thd, set_var *setv) {
991   if (is_partial_revoke_exists(thd) && setv->save_result.ulonglong_value == 0) {
992     my_error(ER_PARTIAL_REVOKES_EXIST, MYF(0), self->name.str);
993     return true;
994   }
995   return false;
996 }
997 
998 /** Sets the changed value to the corresponding atomic system variable */
partial_revokes_update(sys_var *,THD *,enum_var_type)999 static bool partial_revokes_update(sys_var *, THD *, enum_var_type) {
1000   set_mysqld_partial_revokes(opt_partial_revokes);
1001   return false;
1002 }
1003 
1004 static Sys_var_bool Sys_partial_revokes(
1005     "partial_revokes",
1006     "Access of database objects can be restricted, "
1007     "even if user has global privileges granted.",
1008     GLOBAL_VAR(opt_partial_revokes), CMD_LINE(OPT_ARG),
1009     DEFAULT(DEFAULT_PARTIAL_REVOKES), NO_MUTEX_GUARD, IN_BINLOG,
1010     ON_CHECK(check_partial_revokes), ON_UPDATE(partial_revokes_update), nullptr,
1011     sys_var::PARSE_EARLY);
1012 
fix_binlog_cache_size(sys_var *,THD * thd,enum_var_type)1013 static bool fix_binlog_cache_size(sys_var *, THD *thd, enum_var_type) {
1014   check_binlog_cache_size(thd);
1015   return false;
1016 }
1017 
fix_binlog_stmt_cache_size(sys_var *,THD * thd,enum_var_type)1018 static bool fix_binlog_stmt_cache_size(sys_var *, THD *thd, enum_var_type) {
1019   check_binlog_stmt_cache_size(thd);
1020   return false;
1021 }
1022 
1023 static Sys_var_ulong Sys_binlog_cache_size(
1024     "binlog_cache_size",
1025     "The size of the transactional cache for "
1026     "updates to transactional engines for the binary log. "
1027     "If you often use transactions containing many statements, "
1028     "you can increase this to get more performance",
1029     GLOBAL_VAR(binlog_cache_size), CMD_LINE(REQUIRED_ARG),
1030     VALID_RANGE(IO_SIZE, ULONG_MAX), DEFAULT(32768), BLOCK_SIZE(IO_SIZE),
1031     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
1032     ON_UPDATE(fix_binlog_cache_size));
1033 
1034 static Sys_var_ulong Sys_binlog_stmt_cache_size(
1035     "binlog_stmt_cache_size",
1036     "The size of the statement cache for "
1037     "updates to non-transactional engines for the binary log. "
1038     "If you often use statements updating a great number of rows, "
1039     "you can increase this to get more performance",
1040     GLOBAL_VAR(binlog_stmt_cache_size), CMD_LINE(REQUIRED_ARG),
1041     VALID_RANGE(IO_SIZE, ULONG_MAX), DEFAULT(32768), BLOCK_SIZE(IO_SIZE),
1042     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
1043     ON_UPDATE(fix_binlog_stmt_cache_size));
1044 
1045 static Sys_var_int32 Sys_binlog_max_flush_queue_time(
1046     "binlog_max_flush_queue_time",
1047     "The maximum time that the binary log group commit will keep reading"
1048     " transactions before it flush the transactions to the binary log (and"
1049     " optionally sync, depending on the value of sync_binlog).",
1050     GLOBAL_VAR(opt_binlog_max_flush_queue_time),
1051     CMD_LINE(REQUIRED_ARG, OPT_BINLOG_MAX_FLUSH_QUEUE_TIME),
1052     VALID_RANGE(0, 100000), DEFAULT(0), BLOCK_SIZE(1), NO_MUTEX_GUARD,
1053     NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(nullptr), DEPRECATED_VAR(""));
1054 
1055 static Sys_var_long Sys_binlog_group_commit_sync_delay(
1056     "binlog_group_commit_sync_delay",
1057     "The number of microseconds the server waits for the "
1058     "binary log group commit sync queue to fill before "
1059     "continuing. Default: 0. Min: 0. Max: 1000000.",
1060     GLOBAL_VAR(opt_binlog_group_commit_sync_delay), CMD_LINE(REQUIRED_ARG),
1061     VALID_RANGE(0, 1000000 /* max 1 sec */), DEFAULT(0), BLOCK_SIZE(1),
1062     NO_MUTEX_GUARD, NOT_IN_BINLOG);
1063 
1064 static Sys_var_ulong Sys_binlog_group_commit_sync_no_delay_count(
1065     "binlog_group_commit_sync_no_delay_count",
1066     "If there are this many transactions in the commit sync "
1067     "queue and the server is waiting for more transactions "
1068     "to be enqueued (as set using --binlog-group-commit-sync-delay), "
1069     "the commit procedure resumes.",
1070     GLOBAL_VAR(opt_binlog_group_commit_sync_no_delay_count),
1071     CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 100000 /* max connections */),
1072     DEFAULT(0), BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG);
1073 
check_outside_trx(sys_var *,THD * thd,set_var * var)1074 static bool check_outside_trx(sys_var *, THD *thd, set_var *var) {
1075   if (thd->in_active_multi_stmt_transaction()) {
1076     my_error(ER_VARIABLE_NOT_SETTABLE_IN_TRANSACTION, MYF(0),
1077              var->var->name.str);
1078     return true;
1079   }
1080   if (!thd->owned_gtid_is_empty()) {
1081     char buf[Gtid::MAX_TEXT_LENGTH + 1];
1082     if (thd->owned_gtid.sidno > 0)
1083       thd->owned_gtid.to_string(thd->owned_sid, buf);
1084     else
1085       strcpy(buf, "ANONYMOUS");
1086     my_error(ER_CANT_SET_VARIABLE_WHEN_OWNING_GTID, MYF(0), var->var->name.str,
1087              buf);
1088     return true;
1089   }
1090   return false;
1091 }
1092 
check_session_admin_outside_trx_outside_sf(sys_var * self,THD * thd,set_var * var)1093 static bool check_session_admin_outside_trx_outside_sf(sys_var *self, THD *thd,
1094                                                        set_var *var) {
1095   if (thd->in_sub_stmt) {
1096     my_error(ER_VARIABLE_NOT_SETTABLE_IN_SF_OR_TRIGGER, MYF(0),
1097              var->var->name.str);
1098     return true;
1099   }
1100   if (check_outside_trx(self, thd, var)) return true;
1101   if (self->scope() != sys_var::GLOBAL)
1102     return check_session_admin(self, thd, var);
1103   return false;
1104 }
1105 
check_explicit_defaults_for_timestamp(sys_var * self,THD * thd,set_var * var)1106 static bool check_explicit_defaults_for_timestamp(sys_var *self, THD *thd,
1107                                                   set_var *var) {
1108   // Deprecation warning if switching OFF explicit_defaults_for_timestamp
1109   if (thd->variables.explicit_defaults_for_timestamp) {
1110     if (!var->save_result.ulonglong_value)
1111       push_warning_printf(thd, Sql_condition::SL_WARNING,
1112                           ER_WARN_DEPRECATED_SYNTAX,
1113                           ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT),
1114                           self->name.str);
1115   }
1116   if (thd->in_sub_stmt) {
1117     my_error(ER_VARIABLE_NOT_SETTABLE_IN_SF_OR_TRIGGER, MYF(0),
1118              var->var->name.str);
1119     return true;
1120   }
1121   if (thd->in_active_multi_stmt_transaction()) {
1122     my_error(ER_VARIABLE_NOT_SETTABLE_IN_TRANSACTION, MYF(0),
1123              var->var->name.str);
1124     return true;
1125   }
1126   return false;
1127 }
1128 
1129 /**
1130   Check-function to @@GTID_NEXT system variable.
1131 
1132   @param self   a pointer to the sys_var, i.e. gtid_next
1133   @param thd    a reference to THD object
1134   @param var    a pointer to the set_var created by the parser.
1135 
1136   @return @c false if the change is allowed, otherwise @c true.
1137 */
1138 
check_gtid_next(sys_var * self,THD * thd,set_var * var)1139 static bool check_gtid_next(sys_var *self, THD *thd, set_var *var) {
1140   bool is_prepared_trx =
1141       thd->get_transaction()->xid_state()->has_state(XID_STATE::XA_PREPARED);
1142 
1143   if (thd->in_sub_stmt) {
1144     my_error(ER_VARIABLE_NOT_SETTABLE_IN_SF_OR_TRIGGER, MYF(0),
1145              var->var->name.str);
1146     return true;
1147   }
1148   if (!is_prepared_trx && thd->in_active_multi_stmt_transaction()) {
1149     my_error(ER_VARIABLE_NOT_SETTABLE_IN_TRANSACTION, MYF(0),
1150              var->var->name.str);
1151     return true;
1152   }
1153   return check_session_admin_or_replication_applier(self, thd, var);
1154 }
1155 
check_session_admin_outside_trx_outside_sf_outside_sp(sys_var * self,THD * thd,set_var * var)1156 static bool check_session_admin_outside_trx_outside_sf_outside_sp(
1157     sys_var *self, THD *thd, set_var *var) {
1158   if (check_session_admin_outside_trx_outside_sf(self, thd, var)) return true;
1159   if (thd->lex->sphead) {
1160     my_error(ER_VARIABLE_NOT_SETTABLE_IN_SP, MYF(0), var->var->name.str);
1161     return true;
1162   }
1163   return false;
1164 }
1165 
binlog_format_check(sys_var * self,THD * thd,set_var * var)1166 static bool binlog_format_check(sys_var *self, THD *thd, set_var *var) {
1167   if (check_session_admin(self, thd, var)) return true;
1168 
1169   if (var->type == OPT_GLOBAL || var->type == OPT_PERSIST) {
1170     /*
1171       SET @@global.binlog_format and SET @@persist.binlog_format must be
1172       disallowed if any replication channel has open temporary table(s).
1173       Otherwise DROP TEMPORARY TABLE is written into binary log on slave
1174       (which disobeys the simple rule: When @@session.binlog_format=
1175        ROW/MIXED, the server must not write CREATE/DROP TEMPORARY TABLE
1176       to the binary log) in the following case:
1177         slave> SET @@global.binlog_format=STATEMENT;
1178         slave> START SLAVE;
1179         master> CREATE TEMPORARY TABLE t1(a INT);
1180         slave> [wait for t1 to replicate]
1181         slave> STOP SLAVE;
1182         slave> SET @@global.binlog_format=ROW / SET @@persist.binlog_format=ROW
1183         master> DROP TEMPORARY TABLE t1;
1184         slave> START SLAVE;
1185       Note: SET @@persist_only.binlog_format is not disallowed if any
1186       replication channel has temporary table(s), since unlike PERSIST,
1187       PERSIST_ONLY does not modify the runtime global system variable value.
1188 
1189       SET @@global.binlog_format and SET @@persist.binlog_format must be
1190       disallowed if any replication channel applier is running, because
1191       SET @@global.binlog_format does not take effect when any replication
1192       channel applier is running. SET @@global.binlog_format takes effect
1193       on the channel until its applier is (re)starting.
1194       Note: SET @@persist_only.binlog_format is not disallowed if any
1195       replication channel applier is running, since unlike PERSIST,
1196       PERSIST_ONLY does not modify the runtime global system variable value.
1197     */
1198     enum_slave_channel_status slave_channel_status =
1199         has_any_slave_channel_open_temp_table_or_is_its_applier_running();
1200     if (slave_channel_status == SLAVE_CHANNEL_APPLIER_IS_RUNNING) {
1201       my_error(ER_RUNNING_APPLIER_PREVENTS_SWITCH_GLOBAL_BINLOG_FORMAT, MYF(0));
1202       return true;
1203     } else if (slave_channel_status == SLAVE_CHANNEL_HAS_OPEN_TEMPORARY_TABLE) {
1204       my_error(ER_TEMP_TABLE_PREVENTS_SWITCH_GLOBAL_BINLOG_FORMAT, MYF(0));
1205       return true;
1206     }
1207   }
1208 
1209   if (!var->is_global_persist()) {
1210     /*
1211       SET @@session.binlog_format must be disallowed if the session has open
1212       temporary table(s). Otherwise DROP TEMPORARY TABLE is written into
1213       binary log (which disobeys the simple rule: When
1214       @@session.binlog_format=ROW/MIXED, the server must not write
1215       CREATE/DROP TEMPORARY TABLE to the binary log) in the following case:
1216         SET @@session.binlog_format=STATEMENT;
1217         CREATE TEMPORARY TABLE t1 (a INT);
1218         SET @@session.binlog_format=ROW;
1219         DROP TEMPORARY TABLE t1;
1220       And more, if binlog_format=ROW/MIXED and the session has open temporary
1221       table(s), these CREATE TEMPORARY TABLE are not written into the binlog,
1222       so we can not switch to STATEMENT.
1223     */
1224     if (thd->temporary_tables) {
1225       my_error(ER_TEMP_TABLE_PREVENTS_SWITCH_SESSION_BINLOG_FORMAT, MYF(0));
1226       return true;
1227     }
1228 
1229     /*
1230       if in a stored function/trigger, it's too late to change mode
1231     */
1232     if (thd->in_sub_stmt) {
1233       my_error(ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT, MYF(0));
1234       return true;
1235     }
1236     /*
1237       Make the session variable 'binlog_format' read-only inside a transaction.
1238     */
1239     if (thd->in_active_multi_stmt_transaction()) {
1240       my_error(ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT, MYF(0));
1241       return true;
1242     }
1243   }
1244 
1245   /*
1246     If moving to statement format, and binlog_row_value_options is set,
1247     generate a warning.
1248   */
1249   if (var->save_result.ulonglong_value == BINLOG_FORMAT_STMT) {
1250     if ((var->is_global_persist() &&
1251          global_system_variables.binlog_row_value_options != 0) ||
1252         (!var->is_global_persist() &&
1253          thd->variables.binlog_row_value_options != 0)) {
1254       push_warning_printf(thd, Sql_condition::SL_WARNING,
1255                           ER_WARN_BINLOG_PARTIAL_UPDATES_DISABLED,
1256                           ER_THD(thd, ER_WARN_BINLOG_PARTIAL_UPDATES_DISABLED),
1257                           "binlog_format=STATEMENT", "PARTIAL_JSON");
1258     }
1259   }
1260 
1261   return false;
1262 }
1263 
fix_binlog_format_after_update(sys_var *,THD * thd,enum_var_type type)1264 static bool fix_binlog_format_after_update(sys_var *, THD *thd,
1265                                            enum_var_type type) {
1266   if (type == OPT_SESSION) thd->reset_current_stmt_binlog_format_row();
1267   return false;
1268 }
1269 
prevent_global_rbr_exec_mode_idempotent(sys_var * self,THD *,set_var * var)1270 static bool prevent_global_rbr_exec_mode_idempotent(sys_var *self, THD *,
1271                                                     set_var *var) {
1272   if (var->is_global_persist()) {
1273     my_error(ER_LOCAL_VARIABLE, MYF(0), self->name.str);
1274     return true;
1275   }
1276   return false;
1277 }
1278 
1279 static Sys_var_test_flag Sys_core_file("core_file",
1280                                        "write a core-file on crashes",
1281                                        TEST_CORE_ON_SIGNAL);
1282 
1283 static Sys_var_enum Sys_binlog_format(
1284     "binlog_format",
1285     "What form of binary logging the master will "
1286     "use: either ROW for row-based binary logging, STATEMENT "
1287     "for statement-based binary logging, or MIXED. MIXED is statement-"
1288     "based binary logging except for those statements where only row-"
1289     "based is correct: those which involve user-defined functions (i.e. "
1290     "UDFs) or the UUID() function; for those, row-based binary logging is "
1291     "automatically used. If NDBCLUSTER is enabled and binlog-format is "
1292     "MIXED, the format switches to row-based and back implicitly per each "
1293     "query accessing an NDBCLUSTER table",
1294     SESSION_VAR(binlog_format), CMD_LINE(REQUIRED_ARG, OPT_BINLOG_FORMAT),
1295     binlog_format_names, DEFAULT(BINLOG_FORMAT_ROW), NO_MUTEX_GUARD,
1296     NOT_IN_BINLOG, ON_CHECK(binlog_format_check),
1297     ON_UPDATE(fix_binlog_format_after_update));
1298 
1299 static const char *rbr_exec_mode_names[] = {"STRICT", "IDEMPOTENT", nullptr};
1300 static Sys_var_enum rbr_exec_mode(
1301     "rbr_exec_mode",
1302     "Modes for how row events should be executed. Legal values "
1303     "are STRICT (default) and IDEMPOTENT. In IDEMPOTENT mode, "
1304     "the server will not throw errors for operations that are idempotent. "
1305     "In STRICT mode, server will throw errors for the operations that "
1306     "cause a conflict.",
1307     SESSION_VAR(rbr_exec_mode_options), NO_CMD_LINE, rbr_exec_mode_names,
1308     DEFAULT(RBR_EXEC_MODE_STRICT), NO_MUTEX_GUARD, NOT_IN_BINLOG,
1309     ON_CHECK(prevent_global_rbr_exec_mode_idempotent), ON_UPDATE(nullptr));
1310 
check_binlog_row_image(sys_var * self MY_ATTRIBUTE ((unused)),THD * thd,set_var * var)1311 static bool check_binlog_row_image(sys_var *self MY_ATTRIBUTE((unused)),
1312                                    THD *thd, set_var *var) {
1313   DBUG_TRACE;
1314   if (check_session_admin(self, thd, var)) return true;
1315   if (var->save_result.ulonglong_value == BINLOG_ROW_IMAGE_FULL) {
1316     if ((var->is_global_persist() &&
1317          global_system_variables.binlog_row_value_options != 0) ||
1318         (!var->is_global_persist() &&
1319          thd->variables.binlog_row_value_options != 0)) {
1320       push_warning_printf(
1321           thd, Sql_condition::SL_WARNING,
1322           ER_WARN_BINLOG_PARTIAL_UPDATES_SUGGESTS_PARTIAL_IMAGES,
1323           ER_THD(thd, ER_WARN_BINLOG_PARTIAL_UPDATES_SUGGESTS_PARTIAL_IMAGES),
1324           "binlog_row_image=FULL", "PARTIAL_JSON");
1325     }
1326   }
1327   return false;
1328 }
1329 
1330 static const char *binlog_row_image_names[] = {"MINIMAL", "NOBLOB", "FULL",
1331                                                NullS};
1332 static Sys_var_enum Sys_binlog_row_image(
1333     "binlog_row_image",
1334     "Controls whether rows should be logged in 'FULL', 'NOBLOB' or "
1335     "'MINIMAL' formats. 'FULL', means that all columns in the before "
1336     "and after image are logged. 'NOBLOB', means that mysqld avoids logging "
1337     "blob columns whenever possible (e.g. blob column was not changed or "
1338     "is not part of primary key). 'MINIMAL', means that a PK equivalent (PK "
1339     "columns or full row if there is no PK in the table) is logged in the "
1340     "before image, and only changed columns are logged in the after image. "
1341     "(Default: FULL).",
1342     SESSION_VAR(binlog_row_image), CMD_LINE(REQUIRED_ARG),
1343     binlog_row_image_names, DEFAULT(BINLOG_ROW_IMAGE_FULL), NO_MUTEX_GUARD,
1344     NOT_IN_BINLOG, ON_CHECK(check_binlog_row_image), ON_UPDATE(nullptr));
1345 
1346 static const char *binlog_row_metadata_names[] = {"MINIMAL", "FULL", NullS};
1347 static Sys_var_enum Sys_binlog_row_metadata(
1348     "binlog_row_metadata",
1349     "Controls whether metadata is logged using FULL or MINIMAL format. "
1350     "FULL causes all metadata to be logged; MINIMAL means that only "
1351     "metadata actually required by slave is logged. Default: MINIMAL.",
1352     GLOBAL_VAR(binlog_row_metadata), CMD_LINE(REQUIRED_ARG),
1353     binlog_row_metadata_names, DEFAULT(BINLOG_ROW_METADATA_MINIMAL),
1354     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(nullptr));
1355 
check_binlog_trx_compression(sys_var * self MY_ATTRIBUTE ((unused)),THD * thd,set_var * var)1356 static bool check_binlog_trx_compression(sys_var *self MY_ATTRIBUTE((unused)),
1357                                          THD *thd, set_var *var) {
1358   DBUG_TRACE;
1359   if (check_session_admin(self, thd, var)) return true;
1360 
1361   if (!var->is_global_persist() && thd->in_active_multi_stmt_transaction()) {
1362     my_error(ER_VARIABLE_NOT_SETTABLE_IN_TRANSACTION, MYF(0),
1363              var->var->name.str);
1364     return true;
1365   }
1366   return false;
1367 }
1368 
1369 static Sys_var_bool Sys_binlog_trx_compression(
1370     "binlog_transaction_compression",
1371     "Whether to compress transactions or not. Transactions are compressed "
1372     "using the ZSTD compression algorythm.",
1373     SESSION_VAR(binlog_trx_compression), CMD_LINE(OPT_ARG), DEFAULT(false),
1374     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_binlog_trx_compression));
1375 
1376 #include "libbinlogevents/include/compression/zstd.h"
1377 static Sys_var_uint Sys_binlog_transaction_compression_level_zstd(
1378     "binlog_transaction_compression_level_zstd",
1379     "Specifies the transaction compression level for ZSTD "
1380     "transaction compression in the binary log.",
1381     SESSION_VAR(binlog_trx_compression_level_zstd), CMD_LINE(REQUIRED_ARG),
1382     VALID_RANGE(1, 22),
1383     DEFAULT(binary_log::transaction::compression::Zstd_comp::
1384                 DEFAULT_COMPRESSION_LEVEL),
1385     BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG,
1386     ON_CHECK(check_binlog_trx_compression), ON_UPDATE(NULL));
1387 
on_session_track_gtids_update(sys_var *,THD * thd,enum_var_type)1388 static bool on_session_track_gtids_update(sys_var *, THD *thd, enum_var_type) {
1389   thd->session_tracker.get_tracker(SESSION_GTIDS_TRACKER)->update(thd);
1390   return false;
1391 }
1392 
1393 static const char *session_track_gtids_names[] = {"OFF", "OWN_GTID",
1394                                                   "ALL_GTIDS", NullS};
1395 static Sys_var_enum Sys_session_track_gtids(
1396     "session_track_gtids",
1397     "Controls the amount of global transaction ids to be "
1398     "included in the response packet sent by the server."
1399     "(Default: OFF).",
1400     SESSION_VAR(session_track_gtids), CMD_LINE(REQUIRED_ARG),
1401     session_track_gtids_names, DEFAULT(OFF), NO_MUTEX_GUARD, NOT_IN_BINLOG,
1402     ON_CHECK(check_outside_trx), ON_UPDATE(on_session_track_gtids_update));
1403 
binlog_direct_check(sys_var * self,THD * thd,set_var * var)1404 static bool binlog_direct_check(sys_var *self, THD *thd, set_var *var) {
1405   if (check_session_admin(self, thd, var)) return true;
1406 
1407   if (var->is_global_persist()) return false;
1408 
1409   /*
1410     Makes the session variable 'binlog_direct_non_transactional_updates'
1411     read-only if within a procedure, trigger or function.
1412   */
1413   if (thd->in_sub_stmt) {
1414     my_error(ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_DIRECT, MYF(0));
1415     return true;
1416   }
1417   /*
1418     Makes the session variable 'binlog_direct_non_transactional_updates'
1419     read-only inside a transaction.
1420   */
1421   if (thd->in_active_multi_stmt_transaction()) {
1422     my_error(ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_DIRECT, MYF(0));
1423     return true;
1424   }
1425 
1426   return false;
1427 }
1428 
1429 static Sys_var_bool Sys_binlog_direct(
1430     "binlog_direct_non_transactional_updates",
1431     "Causes updates to non-transactional engines using statement format to "
1432     "be written directly to binary log. Before using this option make sure "
1433     "that there are no dependencies between transactional and "
1434     "non-transactional tables such as in the statement INSERT INTO t_myisam "
1435     "SELECT * FROM t_innodb; otherwise, slaves may diverge from the master.",
1436     SESSION_VAR(binlog_direct_non_trans_update), CMD_LINE(OPT_ARG),
1437     DEFAULT(false), NO_MUTEX_GUARD, NOT_IN_BINLOG,
1438     ON_CHECK(binlog_direct_check));
1439 
1440 /**
1441   This variable is read only to users. It can be enabled or disabled
1442   only at mysqld startup. This variable is used by User thread and
1443   as well as by replication slave applier thread to apply relay_log.
1444   Slave applier thread enables/disables this option based on
1445   relay_log's from replication master versions. There is possibility of
1446   slave applier thread and User thread to have different setting for
1447   explicit_defaults_for_timestamp, hence this options is defined as
1448   SESSION_VAR rather than GLOBAL_VAR.
1449 */
1450 static Sys_var_bool Sys_explicit_defaults_for_timestamp(
1451     "explicit_defaults_for_timestamp",
1452     "This option causes CREATE TABLE to create all TIMESTAMP columns "
1453     "as NULL with DEFAULT NULL attribute, Without this option, "
1454     "TIMESTAMP columns are NOT NULL and have implicit DEFAULT clauses. "
1455     "The old behavior is deprecated. "
1456     "The variable can only be set by users having the SUPER privilege.",
1457     SESSION_VAR(explicit_defaults_for_timestamp), CMD_LINE(OPT_ARG),
1458     DEFAULT(true), NO_MUTEX_GUARD, NOT_IN_BINLOG,
1459     ON_CHECK(check_explicit_defaults_for_timestamp));
1460 
repository_check(sys_var * self,THD * thd,set_var * var,SLAVE_THD_TYPE thread_mask)1461 static bool repository_check(sys_var *self, THD *thd, set_var *var,
1462                              SLAVE_THD_TYPE thread_mask) {
1463   bool ret = false;
1464   if (check_session_admin_outside_trx_outside_sf(self, thd, var)) return true;
1465   Master_info *mi;
1466   int running = 0;
1467   const char *msg = nullptr;
1468   bool rpl_info_option = static_cast<uint>(var->save_result.ulonglong_value);
1469 
1470   /* don't convert if the repositories are same */
1471   if (rpl_info_option == (thread_mask == SLAVE_THD_IO ? opt_mi_repository_id
1472                                                       : opt_rli_repository_id))
1473     return false;
1474 
1475   channel_map.wrlock();
1476 
1477   /* Repository conversion not possible, when multiple channels exist */
1478   if (channel_map.get_num_instances(true) > 1) {
1479     msg = "Repository conversion is possible when only default channel exists";
1480     my_error(ER_CHANGE_RPL_INFO_REPOSITORY_FAILURE, MYF(0), msg);
1481     channel_map.unlock();
1482     return true;
1483   }
1484 
1485   mi = channel_map.get_default_channel_mi();
1486 
1487   if (mi != nullptr) {
1488     mi->channel_wrlock();
1489     lock_slave_threads(mi);
1490     init_thread_mask(&running, mi, false);
1491     if (!running) {
1492       switch (thread_mask) {
1493         case SLAVE_THD_IO:
1494           if (Rpl_info_factory::change_mi_repository(
1495                   mi, static_cast<uint>(var->save_result.ulonglong_value),
1496                   &msg)) {
1497             ret = true;
1498             my_error(ER_CHANGE_RPL_INFO_REPOSITORY_FAILURE, MYF(0), msg);
1499           }
1500           break;
1501         case SLAVE_THD_SQL:
1502           mts_recovery_groups(mi->rli);
1503           if (!mi->rli->is_mts_recovery()) {
1504             if (Rpl_info_factory::reset_workers(mi->rli) ||
1505                 Rpl_info_factory::change_rli_repository(
1506                     mi->rli,
1507                     static_cast<uint>(var->save_result.ulonglong_value),
1508                     &msg)) {
1509               ret = true;
1510               my_error(ER_CHANGE_RPL_INFO_REPOSITORY_FAILURE, MYF(0), msg);
1511             }
1512           } else
1513             LogErr(WARNING_LEVEL, ER_RPL_REPO_HAS_GAPS);
1514           break;
1515         default:
1516           assert(0);
1517           break;
1518       }
1519     } else {
1520       ret = true;
1521       my_error(ER_SLAVE_CHANNEL_MUST_STOP, MYF(0), mi->get_channel());
1522     }
1523     unlock_slave_threads(mi);
1524     mi->channel_unlock();
1525   }
1526   channel_map.unlock();
1527   return ret;
1528 }
1529 
relay_log_info_repository_check(sys_var * self,THD * thd,set_var * var)1530 static bool relay_log_info_repository_check(sys_var *self, THD *thd,
1531                                             set_var *var) {
1532   return repository_check(self, thd, var, SLAVE_THD_SQL);
1533 }
1534 
master_info_repository_check(sys_var * self,THD * thd,set_var * var)1535 static bool master_info_repository_check(sys_var *self, THD *thd,
1536                                          set_var *var) {
1537   return repository_check(self, thd, var, SLAVE_THD_IO);
1538 }
1539 
relay_log_info_repository_update(sys_var *,THD * thd,enum_var_type)1540 static bool relay_log_info_repository_update(sys_var *, THD *thd,
1541                                              enum_var_type) {
1542   if (opt_rli_repository_id == INFO_REPOSITORY_FILE) {
1543     push_warning_printf(
1544         thd, Sql_condition::SL_WARNING, ER_WARN_DEPRECATED_SYNTAX,
1545         ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX), "FILE", "'TABLE'");
1546   }
1547   return false;
1548 }
1549 
master_info_repository_update(sys_var *,THD * thd,enum_var_type)1550 static bool master_info_repository_update(sys_var *, THD *thd, enum_var_type) {
1551   if (opt_mi_repository_id == INFO_REPOSITORY_FILE) {
1552     push_warning_printf(
1553         thd, Sql_condition::SL_WARNING, ER_WARN_DEPRECATED_SYNTAX,
1554         ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX), "FILE", "'TABLE'");
1555   }
1556   return false;
1557 }
1558 
1559 static const char *repository_names[] = {"FILE", "TABLE",
1560 #ifndef DBUG_OFF
1561                                          "DUMMY",
1562 #endif
1563                                          nullptr};
1564 
1565 ulong opt_mi_repository_id = INFO_REPOSITORY_TABLE;
1566 static Sys_var_enum Sys_mi_repository(
1567     "master_info_repository",
1568     "Defines the type of the repository for the master information.",
1569     GLOBAL_VAR(opt_mi_repository_id), CMD_LINE(REQUIRED_ARG), repository_names,
1570     DEFAULT(INFO_REPOSITORY_TABLE), NO_MUTEX_GUARD, NOT_IN_BINLOG,
1571     ON_CHECK(master_info_repository_check),
1572     ON_UPDATE(master_info_repository_update));
1573 
1574 ulong opt_rli_repository_id = INFO_REPOSITORY_TABLE;
1575 static Sys_var_enum Sys_rli_repository(
1576     "relay_log_info_repository",
1577     "Defines the type of the repository for the relay log information "
1578     "and associated workers.",
1579     GLOBAL_VAR(opt_rli_repository_id), CMD_LINE(REQUIRED_ARG), repository_names,
1580     DEFAULT(INFO_REPOSITORY_TABLE), NO_MUTEX_GUARD, NOT_IN_BINLOG,
1581     ON_CHECK(relay_log_info_repository_check),
1582     ON_UPDATE(relay_log_info_repository_update));
1583 
1584 static Sys_var_bool Sys_binlog_rows_query(
1585     "binlog_rows_query_log_events",
1586     "Allow writing of Rows_query_log events into binary log.",
1587     SESSION_VAR(binlog_rows_query_log_events), CMD_LINE(OPT_ARG),
1588     DEFAULT(false), NO_MUTEX_GUARD, NOT_IN_BINLOG,
1589     ON_CHECK(check_session_admin));
1590 
1591 static Sys_var_bool Sys_binlog_order_commits(
1592     "binlog_order_commits",
1593     "Issue internal commit calls in the same order as transactions are"
1594     " written to the binary log. Default is to order commits.",
1595     GLOBAL_VAR(opt_binlog_order_commits), CMD_LINE(OPT_ARG), DEFAULT(true));
1596 
1597 static Sys_var_ulong Sys_bulk_insert_buff_size(
1598     "bulk_insert_buffer_size",
1599     "Size of tree cache used in bulk "
1600     "insert optimisation. Note that this is a limit per thread!",
1601     HINT_UPDATEABLE SESSION_VAR(bulk_insert_buff_size), CMD_LINE(REQUIRED_ARG),
1602     VALID_RANGE(0, ULONG_MAX), DEFAULT(8192 * 1024), BLOCK_SIZE(1),
1603     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_session_admin));
1604 
1605 static Sys_var_charptr Sys_character_sets_dir(
1606     "character_sets_dir", "Directory where character sets are",
1607     READ_ONLY NON_PERSIST GLOBAL_VAR(charsets_dir), CMD_LINE(REQUIRED_ARG),
1608     IN_FS_CHARSET, DEFAULT(nullptr));
1609 
check_not_null(sys_var *,THD *,set_var * var)1610 static bool check_not_null(sys_var *, THD *, set_var *var) {
1611   return var->value && var->value->is_null();
1612 }
1613 
1614 /**
1615   Check storage engine is not empty and log warning.
1616 
1617   Checks if default_storage_engine or default_tmp_storage_engine is set
1618   empty and return true. This method also logs warning if the
1619   storage engine set is a disabled storage engine specified in
1620   disabled_storage_engines.
1621 
1622   @param self    pointer to system variable object.
1623   @param thd     Connection handle.
1624   @param var     pointer to set variable object.
1625 
1626   @return  true if the set variable is empty.
1627            false if the set variable is not empty.
1628 */
check_storage_engine(sys_var * self,THD * thd,set_var * var)1629 static bool check_storage_engine(sys_var *self, THD *thd, set_var *var) {
1630   if (check_not_null(self, thd, var)) return true;
1631 
1632   if (!opt_initialize && !opt_noacl) {
1633     char buff[STRING_BUFFER_USUAL_SIZE];
1634     String str(buff, sizeof(buff), system_charset_info), *res;
1635     LEX_CSTRING se_name;
1636 
1637     if (var->value) {
1638       res = var->value->val_str(&str);
1639       lex_cstring_set(&se_name, res->ptr());
1640     } else {
1641       // Use the default value defined by sys_var.
1642       lex_cstring_set(&se_name,
1643                       pointer_cast<const char *>(
1644                           down_cast<Sys_var_plugin *>(self)->global_value_ptr(
1645                               thd, nullptr)));
1646     }
1647 
1648     plugin_ref plugin;
1649     if ((plugin = ha_resolve_by_name(nullptr, &se_name, false))) {
1650       handlerton *hton = plugin_data<handlerton *>(plugin);
1651       if (ha_is_storage_engine_disabled(hton))
1652         LogErr(WARNING_LEVEL, ER_DISABLED_STORAGE_ENGINE_AS_DEFAULT,
1653                self->name.str, se_name.str);
1654       plugin_unlock(nullptr, plugin);
1655     }
1656   }
1657   return false;
1658 }
1659 
check_charset(sys_var *,THD * thd,set_var * var)1660 static bool check_charset(sys_var *, THD *thd, set_var *var) {
1661   if (!var->value) return false;
1662 
1663   char buff[STRING_BUFFER_USUAL_SIZE];
1664   if (var->value->result_type() == STRING_RESULT) {
1665     String str(buff, sizeof(buff), system_charset_info), *res;
1666     if (!(res = var->value->val_str(&str)))
1667       var->save_result.ptr = nullptr;
1668     else {
1669       ErrConvString err(res); /* Get utf8 '\0' terminated string */
1670       if (!(var->save_result.ptr =
1671                 get_charset_by_csname(err.ptr(), MY_CS_PRIMARY, MYF(0))) &&
1672           !(var->save_result.ptr = get_old_charset_by_name(err.ptr()))) {
1673         my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), err.ptr());
1674         return true;
1675       }
1676       warn_on_deprecated_charset(
1677           thd, static_cast<const CHARSET_INFO *>(var->save_result.ptr),
1678           err.ptr());
1679     }
1680   } else  // INT_RESULT
1681   {
1682     int csno = (int)var->value->val_int();
1683     if (!(var->save_result.ptr = get_charset(csno, MYF(0)))) {
1684       my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), llstr(csno, buff));
1685       return true;
1686     }
1687     warn_on_deprecated_charset(
1688         thd, static_cast<const CHARSET_INFO *>(var->save_result.ptr),
1689         static_cast<const CHARSET_INFO *>(var->save_result.ptr)->name);
1690   }
1691   return false;
1692 }
check_charset_not_null(sys_var * self,THD * thd,set_var * var)1693 static bool check_charset_not_null(sys_var *self, THD *thd, set_var *var) {
1694   return check_charset(self, thd, var) || check_not_null(self, thd, var);
1695 }
1696 
1697 namespace {
1698 struct Get_name {
Get_name__anon9d05e1790111::Get_name1699   explicit Get_name(const CHARSET_INFO *ci) : m_ci(ci) {}
get_name__anon9d05e1790111::Get_name1700   const uchar *get_name() const {
1701     return pointer_cast<const uchar *>(m_ci->name);
1702   }
1703   const CHARSET_INFO *m_ci;
1704 };
1705 
1706 struct Get_csname {
Get_csname__anon9d05e1790111::Get_csname1707   explicit Get_csname(const CHARSET_INFO *ci) : m_ci(ci) {}
get_name__anon9d05e1790111::Get_csname1708   const uchar *get_name() const {
1709     return pointer_cast<const uchar *>(m_ci->csname);
1710   }
1711   const CHARSET_INFO *m_ci;
1712 };
1713 
1714 }  // namespace
1715 
1716 static CHARSET_INFO *charset_system_default = &my_charset_utf8_general_ci;
1717 
1718 static Sys_var_struct<CHARSET_INFO, Get_csname> Sys_character_set_system(
1719     "character_set_system",
1720     "The character set used by the server "
1721     "for storing identifiers",
1722     READ_ONLY NON_PERSIST GLOBAL_VAR(system_charset_info), NO_CMD_LINE,
1723     DEFAULT(&charset_system_default));
1724 
1725 static Sys_var_struct<CHARSET_INFO, Get_csname> Sys_character_set_server(
1726     "character_set_server", "The default character set",
1727     SESSION_VAR(collation_server), NO_CMD_LINE, DEFAULT(&default_charset_info),
1728     NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_charset_not_null));
1729 
check_charset_db(sys_var * self,THD * thd,set_var * var)1730 static bool check_charset_db(sys_var *self, THD *thd, set_var *var) {
1731   if (check_session_admin(self, thd, var)) return true;
1732   if (check_charset_not_null(self, thd, var)) return true;
1733   if (!var->value)  // = DEFAULT
1734     var->save_result.ptr = thd->db_charset;
1735   return false;
1736 }
update_deprecated(sys_var * self,THD * thd,enum_var_type)1737 static bool update_deprecated(sys_var *self, THD *thd, enum_var_type) {
1738   push_warning_printf(
1739       thd, Sql_condition::SL_WARNING, ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT,
1740       ER_THD(thd, ER_WARN_DEPRECATED_SYSVAR_UPDATE), self->name.str);
1741   return false;
1742 }
1743 static Sys_var_struct<CHARSET_INFO, Get_csname> Sys_character_set_database(
1744     "character_set_database", " The character set used by the default database",
1745     SESSION_VAR(collation_database), NO_CMD_LINE,
1746     DEFAULT(&default_charset_info), NO_MUTEX_GUARD, IN_BINLOG,
1747     ON_CHECK(check_charset_db), ON_UPDATE(update_deprecated));
1748 
check_cs_client(sys_var * self,THD * thd,set_var * var)1749 static bool check_cs_client(sys_var *self, THD *thd, set_var *var) {
1750   if (check_charset_not_null(self, thd, var)) return true;
1751 
1752   // We don't currently support any variable-width character set with a minumum
1753   // length greater than 1. If we ever do, we have to revisit
1754   // is_supported_parser_charset(). See Item_func_statement_digest::val_str()
1755   // and Item_func_statement_digest_text::val_str().
1756   return (static_cast<const CHARSET_INFO *>(var->save_result.ptr))->mbminlen >
1757          1;
1758 }
fix_thd_charset(sys_var *,THD * thd,enum_var_type type)1759 static bool fix_thd_charset(sys_var *, THD *thd, enum_var_type type) {
1760   if (type == OPT_SESSION) thd->update_charset();
1761   return false;
1762 }
1763 static Sys_var_struct<CHARSET_INFO, Get_csname> Sys_character_set_client(
1764     "character_set_client",
1765     "The character set for statements "
1766     "that arrive from the client",
1767     SESSION_VAR(character_set_client), NO_CMD_LINE,
1768     DEFAULT(&default_charset_info), NO_MUTEX_GUARD, IN_BINLOG,
1769     ON_CHECK(check_cs_client), ON_UPDATE(fix_thd_charset));
1770 
1771 static Sys_var_struct<CHARSET_INFO, Get_csname> Sys_character_set_connection(
1772     "character_set_connection",
1773     "The character set used for "
1774     "literals that do not have a character set introducer and for "
1775     "number-to-string conversion",
1776     SESSION_VAR(collation_connection), NO_CMD_LINE,
1777     DEFAULT(&default_charset_info), NO_MUTEX_GUARD, IN_BINLOG,
1778     ON_CHECK(check_charset_not_null), ON_UPDATE(fix_thd_charset));
1779 
1780 static Sys_var_struct<CHARSET_INFO, Get_csname> Sys_character_set_results(
1781     "character_set_results",
1782     "The character set used for returning "
1783     "query results to the client",
1784     SESSION_VAR(character_set_results), NO_CMD_LINE,
1785     DEFAULT(&default_charset_info), NO_MUTEX_GUARD, NOT_IN_BINLOG,
1786     ON_CHECK(check_charset));
1787 
check_cs_filesystem(sys_var * self,THD * thd,set_var * var)1788 static bool check_cs_filesystem(sys_var *self, THD *thd, set_var *var) {
1789   if (check_session_admin(self, thd, var)) return true;
1790   if (check_charset_not_null(self, thd, var)) return true;
1791 
1792   return false;
1793 }
1794 
1795 static Sys_var_struct<CHARSET_INFO, Get_csname> Sys_character_set_filesystem(
1796     "character_set_filesystem", "The filesystem character set",
1797     SESSION_VAR(character_set_filesystem), NO_CMD_LINE,
1798     DEFAULT(&character_set_filesystem), NO_MUTEX_GUARD, NOT_IN_BINLOG,
1799     ON_CHECK(check_cs_filesystem), ON_UPDATE(fix_thd_charset));
1800 
1801 static const char *completion_type_names[] = {"NO_CHAIN", "CHAIN", "RELEASE",
1802                                               nullptr};
1803 static Sys_var_enum Sys_completion_type(
1804     "completion_type",
1805     "The transaction completion type, one of "
1806     "NO_CHAIN, CHAIN, RELEASE",
1807     SESSION_VAR(completion_type), CMD_LINE(REQUIRED_ARG), completion_type_names,
1808     DEFAULT(0));
1809 
check_collation_not_null(sys_var * self,THD * thd,set_var * var)1810 static bool check_collation_not_null(sys_var *self, THD *thd, set_var *var) {
1811   if (!var->value) return false;
1812 
1813   char buff[STRING_BUFFER_USUAL_SIZE];
1814   if (var->value->result_type() == STRING_RESULT) {
1815     String str(buff, sizeof(buff), system_charset_info), *res;
1816     if (!(res = var->value->val_str(&str)))
1817       var->save_result.ptr = nullptr;
1818     else {
1819       ErrConvString err(res); /* Get utf8 '\0'-terminated string */
1820       if (!(var->save_result.ptr = get_charset_by_name(err.ptr(), MYF(0)))) {
1821         my_error(ER_UNKNOWN_COLLATION, MYF(0), err.ptr());
1822         return true;
1823       }
1824     }
1825   } else  // INT_RESULT
1826   {
1827     int csno = (int)var->value->val_int();
1828     if (!(var->save_result.ptr = get_charset(csno, MYF(0)))) {
1829       my_error(ER_UNKNOWN_COLLATION, MYF(0), llstr(csno, buff));
1830       return true;
1831     }
1832   }
1833   if (var->save_result.ptr) {
1834     warn_on_deprecated_collation(
1835         thd, static_cast<const CHARSET_INFO *>(var->save_result.ptr));
1836   }
1837 
1838   return check_not_null(self, thd, var);
1839 }
1840 static Sys_var_struct<CHARSET_INFO, Get_name> Sys_collation_connection(
1841     "collation_connection",
1842     "The collation of the connection "
1843     "character set",
1844     SESSION_VAR(collation_connection), NO_CMD_LINE,
1845     DEFAULT(&default_charset_info), NO_MUTEX_GUARD, IN_BINLOG,
1846     ON_CHECK(check_collation_not_null), ON_UPDATE(fix_thd_charset));
1847 
check_collation_db(sys_var * self,THD * thd,set_var * var)1848 static bool check_collation_db(sys_var *self, THD *thd, set_var *var) {
1849   if (check_collation_not_null(self, thd, var)) return true;
1850   if (!var->value)  // = DEFAULT
1851     var->save_result.ptr = thd->db_charset;
1852   return false;
1853 }
1854 static Sys_var_struct<CHARSET_INFO, Get_name> Sys_collation_database(
1855     "collation_database",
1856     "The collation of the database "
1857     "character set",
1858     SESSION_VAR(collation_database), NO_CMD_LINE,
1859     DEFAULT(&default_charset_info), NO_MUTEX_GUARD, IN_BINLOG,
1860     ON_CHECK(check_collation_db), ON_UPDATE(update_deprecated));
1861 
1862 static Sys_var_struct<CHARSET_INFO, Get_name> Sys_collation_server(
1863     "collation_server", "The server default collation",
1864     SESSION_VAR(collation_server), NO_CMD_LINE, DEFAULT(&default_charset_info),
1865     NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_collation_not_null));
1866 
1867 static const char *concurrent_insert_names[] = {"NEVER", "AUTO", "ALWAYS",
1868                                                 nullptr};
1869 static Sys_var_enum Sys_concurrent_insert(
1870     "concurrent_insert",
1871     "Use concurrent insert with MyISAM. Possible "
1872     "values are NEVER, AUTO, ALWAYS",
1873     GLOBAL_VAR(myisam_concurrent_insert), CMD_LINE(OPT_ARG),
1874     concurrent_insert_names, DEFAULT(1));
1875 
1876 static Sys_var_ulong Sys_connect_timeout(
1877     "connect_timeout",
1878     "The number of seconds the mysqld server is waiting for a connect "
1879     "packet before responding with 'Bad handshake'",
1880     GLOBAL_VAR(connect_timeout), CMD_LINE(REQUIRED_ARG),
1881     VALID_RANGE(2, LONG_TIMEOUT), DEFAULT(CONNECT_TIMEOUT), BLOCK_SIZE(1));
1882 
1883 static Sys_var_ulong Sys_information_schema_stats_expiry(
1884     "information_schema_stats_expiry",
1885     "The number of seconds after which mysqld server will fetch "
1886     "data from storage engine and replace the data in cache.",
1887     SESSION_VAR(information_schema_stats_expiry), CMD_LINE(REQUIRED_ARG),
1888     VALID_RANGE(0, LONG_TIMEOUT), DEFAULT(24 * 60 * 60), BLOCK_SIZE(1));
1889 
1890 static Sys_var_charptr Sys_datadir(
1891     "datadir", "Path to the database root directory",
1892     READ_ONLY NON_PERSIST GLOBAL_VAR(mysql_real_data_home_ptr),
1893     CMD_LINE(REQUIRED_ARG, 'h'), IN_FS_CHARSET, DEFAULT(mysql_real_data_home));
1894 
1895 #ifndef DBUG_OFF
1896 static Sys_var_dbug Sys_dbug("debug", "Debug log", sys_var::SESSION,
1897                              CMD_LINE(OPT_ARG, '#'), DEFAULT(""),
1898                              NO_MUTEX_GUARD, NOT_IN_BINLOG,
1899                              ON_CHECK(check_session_admin));
1900 #endif
1901 
1902 /**
1903   @todo
1904     When updating myisam_delay_key_write, we should do a 'flush tables'
1905     of all MyISAM tables to ensure that they are reopen with the
1906     new attribute.
1907 */
fix_delay_key_write(sys_var *,THD *,enum_var_type)1908 export bool fix_delay_key_write(sys_var *, THD *, enum_var_type) {
1909   switch (delay_key_write_options) {
1910     case DELAY_KEY_WRITE_NONE:
1911       myisam_delay_key_write = false;
1912       break;
1913     case DELAY_KEY_WRITE_ON:
1914       myisam_delay_key_write = true;
1915       break;
1916     case DELAY_KEY_WRITE_ALL:
1917       myisam_delay_key_write = true;
1918       ha_open_options |= HA_OPEN_DELAY_KEY_WRITE;
1919       break;
1920   }
1921   return false;
1922 }
1923 static const char *delay_key_write_names[] = {"OFF", "ON", "ALL", NullS};
1924 static Sys_var_enum Sys_delay_key_write(
1925     "delay_key_write", "Type of DELAY_KEY_WRITE",
1926     GLOBAL_VAR(delay_key_write_options), CMD_LINE(OPT_ARG),
1927     delay_key_write_names, DEFAULT(DELAY_KEY_WRITE_ON), NO_MUTEX_GUARD,
1928     NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(fix_delay_key_write));
1929 
1930 static Sys_var_ulong Sys_delayed_insert_limit(
1931     "delayed_insert_limit",
1932     "After inserting delayed_insert_limit rows, the INSERT DELAYED "
1933     "handler will check if there are any SELECT statements pending. "
1934     "If so, it allows these to execute before continuing. "
1935     "This variable is deprecated along with INSERT DELAYED.",
1936     GLOBAL_VAR(delayed_insert_limit), CMD_LINE(REQUIRED_ARG),
1937     VALID_RANGE(1, ULONG_MAX), DEFAULT(DELAYED_LIMIT), BLOCK_SIZE(1),
1938     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(nullptr),
1939     DEPRECATED_VAR(""));
1940 
1941 static Sys_var_ulong Sys_delayed_insert_timeout(
1942     "delayed_insert_timeout",
1943     "How long a INSERT DELAYED thread should wait for INSERT statements "
1944     "before terminating. "
1945     "This variable is deprecated along with INSERT DELAYED.",
1946     GLOBAL_VAR(delayed_insert_timeout), CMD_LINE(REQUIRED_ARG),
1947     VALID_RANGE(1, LONG_TIMEOUT), DEFAULT(DELAYED_WAIT_TIMEOUT), BLOCK_SIZE(1),
1948     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(nullptr),
1949     DEPRECATED_VAR(""));
1950 
1951 static Sys_var_ulong Sys_delayed_queue_size(
1952     "delayed_queue_size",
1953     "What size queue (in rows) should be allocated for handling INSERT "
1954     "DELAYED. If the queue becomes full, any client that does INSERT "
1955     "DELAYED will wait until there is room in the queue again. "
1956     "This variable is deprecated along with INSERT DELAYED.",
1957     GLOBAL_VAR(delayed_queue_size), CMD_LINE(REQUIRED_ARG),
1958     VALID_RANGE(1, ULONG_MAX), DEFAULT(DELAYED_QUEUE_SIZE), BLOCK_SIZE(1),
1959     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(nullptr),
1960     DEPRECATED_VAR(""));
1961 
1962 static const char *event_scheduler_names[] = {"OFF", "ON", "DISABLED", NullS};
event_scheduler_check(sys_var *,THD *,set_var * var)1963 static bool event_scheduler_check(sys_var *, THD *, set_var *var) {
1964   /* DISABLED is only accepted on the command line */
1965   if (var->save_result.ulonglong_value == Events::EVENTS_DISABLED) return true;
1966   if (Events::opt_event_scheduler == Events::EVENTS_DISABLED) {
1967     my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
1968              "--event-scheduler=DISABLED or --skip-grant-tables");
1969     return true;
1970   }
1971   return false;
1972 }
event_scheduler_update(sys_var *,THD *,enum_var_type)1973 static bool event_scheduler_update(sys_var *, THD *, enum_var_type) {
1974   int err_no = 0;
1975   ulong opt_event_scheduler_value = Events::opt_event_scheduler;
1976   mysql_mutex_unlock(&LOCK_global_system_variables);
1977   /*
1978     Events::start() is heavyweight. In particular it creates a new THD,
1979     which takes LOCK_global_system_variables internally.
1980     Thus we have to release it here.
1981     We need to re-take it before returning, though.
1982 
1983     Note that since we release LOCK_global_system_variables before calling
1984     start/stop, there is a possibility that the server variable
1985     can become out of sync with the real event scheduler state.
1986 
1987     This can happen with two concurrent statments if the first gets
1988     interrupted after start/stop but before retaking
1989     LOCK_global_system_variables. However, this problem should be quite
1990     rare and it's difficult to avoid it without opening up possibilities
1991     for deadlocks. See bug#51160.
1992   */
1993   bool ret = opt_event_scheduler_value == Events::EVENTS_ON
1994                  ? Events::start(&err_no)
1995                  : Events::stop();
1996   mysql_mutex_lock(&LOCK_global_system_variables);
1997   if (ret) {
1998     Events::opt_event_scheduler = Events::EVENTS_OFF;
1999     my_error(ER_EVENT_SET_VAR_ERROR, MYF(0), err_no);
2000   }
2001   return ret;
2002 }
2003 
2004 static Sys_var_enum Sys_event_scheduler(
2005     "event_scheduler",
2006     "Enable the event scheduler. Possible values are "
2007     "ON, OFF, and DISABLED (keep the event scheduler completely "
2008     "deactivated, it cannot be activated run-time)",
2009     GLOBAL_VAR(Events::opt_event_scheduler), CMD_LINE(OPT_ARG),
2010     event_scheduler_names, DEFAULT(Events::EVENTS_ON), NO_MUTEX_GUARD,
2011     NOT_IN_BINLOG, ON_CHECK(event_scheduler_check),
2012     ON_UPDATE(event_scheduler_update));
2013 
check_expire_logs_days(sys_var *,THD *,set_var * var)2014 static bool check_expire_logs_days(sys_var *, THD *, set_var *var) {
2015   ulonglong expire_logs_days_value = var->save_result.ulonglong_value;
2016 
2017   if (expire_logs_days_value && binlog_expire_logs_seconds) {
2018     my_error(ER_BINLOG_EXPIRE_LOG_DAYS_AND_SECS_USED_TOGETHER, MYF(0));
2019     return true;
2020   }
2021   return false;
2022 }
2023 
check_expire_logs_seconds(sys_var *,THD *,set_var * var)2024 static bool check_expire_logs_seconds(sys_var *, THD *, set_var *var) {
2025   ulonglong expire_logs_seconds_value = var->save_result.ulonglong_value;
2026 
2027   if (expire_logs_days && expire_logs_seconds_value) {
2028     my_error(ER_EXPIRE_LOGS_DAYS_IGNORED, MYF(0));
2029     return true;
2030   }
2031   return false;
2032 }
2033 
2034 static Sys_var_ulong Sys_expire_logs_days(
2035     "expire_logs_days",
2036     "If non-zero, binary logs will be purged after expire_logs_days "
2037     "days; If this option alone is set on the command line or in a "
2038     "configuration file, it overrides the default value for "
2039     "binlog-expire-logs-seconds. If both options are set to nonzero values, "
2040     "binlog-expire-logs-seconds takes priority. Possible purges happen at "
2041     "startup and at binary log rotation.",
2042     GLOBAL_VAR(expire_logs_days), CMD_LINE(REQUIRED_ARG, OPT_EXPIRE_LOGS_DAYS),
2043     VALID_RANGE(0, 99), DEFAULT(0), BLOCK_SIZE(1), NO_MUTEX_GUARD,
2044     NOT_IN_BINLOG, ON_CHECK(check_expire_logs_days), ON_UPDATE(nullptr),
2045     DEPRECATED_VAR("binlog_expire_logs_seconds"));
2046 
2047 static Sys_var_ulong Sys_binlog_expire_logs_seconds(
2048     "binlog_expire_logs_seconds",
2049     "If non-zero, binary logs will be purged after binlog_expire_logs_seconds"
2050     " seconds; If both this option and expire_logs_days are set to non-zero"
2051     "  values, this option takes priority. Purges happen at"
2052     " startup and at binary log rotation.",
2053     GLOBAL_VAR(binlog_expire_logs_seconds),
2054     CMD_LINE(REQUIRED_ARG, OPT_BINLOG_EXPIRE_LOGS_SECONDS),
2055     VALID_RANGE(0, 0xFFFFFFFF), DEFAULT(2592000), BLOCK_SIZE(1), NO_MUTEX_GUARD,
2056     NOT_IN_BINLOG, ON_CHECK(check_expire_logs_seconds), ON_UPDATE(nullptr));
2057 
2058 static Sys_var_bool Sys_flush(
2059     "flush", "Flush MyISAM tables to disk between SQL commands",
2060     GLOBAL_VAR(myisam_flush), CMD_LINE(OPT_ARG), DEFAULT(false));
2061 
2062 static Sys_var_ulong Sys_flush_time(
2063     "flush_time",
2064     "A dedicated thread is created to flush all tables at the "
2065     "given interval",
2066     GLOBAL_VAR(flush_time), CMD_LINE(REQUIRED_ARG),
2067     VALID_RANGE(0, LONG_TIMEOUT), DEFAULT(0), BLOCK_SIZE(1));
2068 
check_ftb_syntax(sys_var *,THD *,set_var * var)2069 static bool check_ftb_syntax(sys_var *, THD *, set_var *var) {
2070   return ft_boolean_check_syntax_string(
2071       (uchar *)(var->save_result.string_value.str));
2072 }
2073 /// @todo make SESSION_VAR (usability enhancement and a fix for a race
2074 /// condition)
2075 static Sys_var_charptr Sys_ft_boolean_syntax(
2076     "ft_boolean_syntax",
2077     "List of operators for "
2078     "MATCH ... AGAINST ( ... IN BOOLEAN MODE)",
2079     GLOBAL_VAR(ft_boolean_syntax), CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET,
2080     DEFAULT(DEFAULT_FTB_SYNTAX), NO_MUTEX_GUARD, NOT_IN_BINLOG,
2081     ON_CHECK(check_ftb_syntax));
2082 
2083 static Sys_var_ulong Sys_ft_max_word_len(
2084     "ft_max_word_len",
2085     "The maximum length of the word to be included in a FULLTEXT index. "
2086     "Note: FULLTEXT indexes must be rebuilt after changing this variable",
2087     READ_ONLY GLOBAL_VAR(ft_max_word_len), CMD_LINE(REQUIRED_ARG),
2088     VALID_RANGE(10, HA_FT_MAXCHARLEN), DEFAULT(HA_FT_MAXCHARLEN),
2089     BLOCK_SIZE(1));
2090 
2091 static Sys_var_ulong Sys_ft_min_word_len(
2092     "ft_min_word_len",
2093     "The minimum length of the word to be included in a FULLTEXT index. "
2094     "Note: FULLTEXT indexes must be rebuilt after changing this variable",
2095     READ_ONLY GLOBAL_VAR(ft_min_word_len), CMD_LINE(REQUIRED_ARG),
2096     VALID_RANGE(1, HA_FT_MAXCHARLEN), DEFAULT(4), BLOCK_SIZE(1));
2097 
2098 /// @todo make it an updatable SESSION_VAR
2099 static Sys_var_ulong Sys_ft_query_expansion_limit(
2100     "ft_query_expansion_limit",
2101     "Number of best matches to use for query expansion",
2102     READ_ONLY GLOBAL_VAR(ft_query_expansion_limit), CMD_LINE(REQUIRED_ARG),
2103     VALID_RANGE(0, 1000), DEFAULT(20), BLOCK_SIZE(1));
2104 
2105 static Sys_var_charptr Sys_ft_stopword_file(
2106     "ft_stopword_file", "Use stopwords from this file instead of built-in list",
2107     READ_ONLY NON_PERSIST GLOBAL_VAR(ft_stopword_file), CMD_LINE(REQUIRED_ARG),
2108     IN_FS_CHARSET, DEFAULT(nullptr));
2109 
check_init_string(sys_var *,THD *,set_var * var)2110 static bool check_init_string(sys_var *, THD *, set_var *var) {
2111   if (var->save_result.string_value.str == nullptr) {
2112     var->save_result.string_value.str = const_cast<char *>("");
2113     var->save_result.string_value.length = 0;
2114   }
2115   return false;
2116 }
2117 static PolyLock_rwlock PLock_sys_init_connect(&LOCK_sys_init_connect);
2118 static Sys_var_lexstring Sys_init_connect(
2119     "init_connect",
2120     "Command(s) that are executed for each "
2121     "new connection",
2122     GLOBAL_VAR(opt_init_connect), CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET,
2123     DEFAULT(""), &PLock_sys_init_connect, NOT_IN_BINLOG,
2124     ON_CHECK(check_init_string));
2125 
2126 static Sys_var_charptr Sys_init_file(
2127     "init_file", "Read SQL commands from this file at startup",
2128     READ_ONLY NON_PERSIST GLOBAL_VAR(opt_init_file), CMD_LINE(REQUIRED_ARG),
2129     IN_FS_CHARSET, DEFAULT(nullptr));
2130 
2131 static PolyLock_rwlock PLock_sys_init_slave(&LOCK_sys_init_slave);
2132 static Sys_var_lexstring Sys_init_slave(
2133     "init_slave",
2134     "Command(s) that are executed by a slave server "
2135     "each time the SQL thread starts",
2136     GLOBAL_VAR(opt_init_slave), CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET,
2137     DEFAULT(""), &PLock_sys_init_slave, NOT_IN_BINLOG,
2138     ON_CHECK(check_init_string));
2139 
2140 static Sys_var_ulong Sys_interactive_timeout(
2141     "interactive_timeout",
2142     "The number of seconds the server waits for activity on an interactive "
2143     "connection before closing it",
2144     SESSION_VAR(net_interactive_timeout), CMD_LINE(REQUIRED_ARG),
2145     VALID_RANGE(1, LONG_TIMEOUT), DEFAULT(NET_WAIT_TIMEOUT), BLOCK_SIZE(1));
2146 
2147 static Sys_var_ulong Sys_join_buffer_size(
2148     "join_buffer_size", "The size of the buffer that is used for full joins",
2149     HINT_UPDATEABLE SESSION_VAR(join_buff_size), CMD_LINE(REQUIRED_ARG),
2150     VALID_RANGE(128, ULONG_MAX), DEFAULT(256 * 1024), BLOCK_SIZE(128));
2151 
2152 static Sys_var_keycache Sys_key_buffer_size(
2153     "key_buffer_size",
2154     "The size of the buffer used for "
2155     "index blocks for MyISAM tables. Increase this to get better index "
2156     "handling (for all reads and multiple writes) to as much as you can "
2157     "afford",
2158     KEYCACHE_VAR(param_buff_size), CMD_LINE(REQUIRED_ARG, OPT_KEY_BUFFER_SIZE),
2159     VALID_RANGE(0, SIZE_T_MAX), DEFAULT(KEY_CACHE_SIZE), BLOCK_SIZE(IO_SIZE),
2160     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
2161     ON_UPDATE(update_buffer_size));
2162 
2163 static Sys_var_keycache Sys_key_cache_block_size(
2164     "key_cache_block_size", "The default size of key cache blocks",
2165     KEYCACHE_VAR(param_block_size),
2166     CMD_LINE(REQUIRED_ARG, OPT_KEY_CACHE_BLOCK_SIZE),
2167     VALID_RANGE(512, 1024 * 16), DEFAULT(KEY_CACHE_BLOCK_SIZE), BLOCK_SIZE(512),
2168     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
2169     ON_UPDATE(update_keycache_param));
2170 
2171 static Sys_var_keycache Sys_key_cache_division_limit(
2172     "key_cache_division_limit",
2173     "The minimum percentage of warm blocks in key cache",
2174     KEYCACHE_VAR(param_division_limit),
2175     CMD_LINE(REQUIRED_ARG, OPT_KEY_CACHE_DIVISION_LIMIT), VALID_RANGE(1, 100),
2176     DEFAULT(100), BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG,
2177     ON_CHECK(nullptr), ON_UPDATE(update_keycache_param));
2178 
2179 static Sys_var_keycache Sys_key_cache_age_threshold(
2180     "key_cache_age_threshold",
2181     "This characterizes the number of "
2182     "hits a hot block has to be untouched until it is considered aged "
2183     "enough to be downgraded to a warm block. This specifies the "
2184     "percentage ratio of that number of hits to the total number of "
2185     "blocks in key cache",
2186     KEYCACHE_VAR(param_age_threshold),
2187     CMD_LINE(REQUIRED_ARG, OPT_KEY_CACHE_AGE_THRESHOLD),
2188     VALID_RANGE(100, ULONG_MAX), DEFAULT(300), BLOCK_SIZE(100), NO_MUTEX_GUARD,
2189     NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(update_keycache_param));
2190 
2191 static Sys_var_bool Sys_large_files_support(
2192     "large_files_support",
2193     "Whether mysqld was compiled with options for large file support",
2194     READ_ONLY NON_PERSIST GLOBAL_VAR(opt_large_files), NO_CMD_LINE,
2195     DEFAULT(sizeof(my_off_t) > 4));
2196 
2197 static Sys_var_uint Sys_large_page_size(
2198     "large_page_size",
2199     "If large page support is enabled, this shows the size of memory pages",
2200     READ_ONLY NON_PERSIST GLOBAL_VAR(opt_large_page_size), NO_CMD_LINE,
2201     VALID_RANGE(0, UINT_MAX), DEFAULT(0), BLOCK_SIZE(1));
2202 
2203 static Sys_var_bool Sys_large_pages("large_pages",
2204                                     "Enable support for large pages",
2205                                     READ_ONLY GLOBAL_VAR(opt_large_pages),
2206                                     IF_WIN(NO_CMD_LINE, CMD_LINE(OPT_ARG)),
2207                                     DEFAULT(false));
2208 
2209 static Sys_var_charptr Sys_language(
2210     "lc_messages_dir", "Directory where error messages are",
2211     READ_ONLY NON_PERSIST GLOBAL_VAR(lc_messages_dir_ptr),
2212     CMD_LINE(REQUIRED_ARG, OPT_LC_MESSAGES_DIRECTORY), IN_FS_CHARSET,
2213     DEFAULT(nullptr));
2214 
2215 static Sys_var_bool Sys_local_infile("local_infile",
2216                                      "Enable LOAD DATA LOCAL INFILE",
2217                                      GLOBAL_VAR(opt_local_infile),
2218                                      CMD_LINE(OPT_ARG), DEFAULT(false));
2219 
2220 static Sys_var_ulong Sys_lock_wait_timeout(
2221     "lock_wait_timeout",
2222     "Timeout in seconds to wait for a lock before returning an error.",
2223     HINT_UPDATEABLE SESSION_VAR(lock_wait_timeout), CMD_LINE(REQUIRED_ARG),
2224     VALID_RANGE(1, LONG_TIMEOUT), DEFAULT(LONG_TIMEOUT), BLOCK_SIZE(1));
2225 
2226 #ifdef HAVE_MLOCKALL
2227 static Sys_var_bool Sys_locked_in_memory(
2228     "locked_in_memory", "Whether mysqld was locked in memory with --memlock",
2229     READ_ONLY NON_PERSIST GLOBAL_VAR(locked_in_memory), NO_CMD_LINE,
2230     DEFAULT(false));
2231 #endif
2232 
2233 /* this says NO_CMD_LINE, as command-line option takes a string, not a bool */
2234 static Sys_var_bool Sys_log_bin("log_bin", "Whether the binary log is enabled",
2235                                 READ_ONLY NON_PERSIST GLOBAL_VAR(opt_bin_log),
2236                                 NO_CMD_LINE, DEFAULT(true));
2237 
transaction_write_set_check(sys_var * self,THD * thd,set_var * var)2238 static bool transaction_write_set_check(sys_var *self, THD *thd, set_var *var) {
2239   if (check_session_admin(self, thd, var)) return true;
2240   // Can't change the algorithm when group replication is enabled.
2241   if (is_group_replication_running()) {
2242     my_message(
2243         ER_GROUP_REPLICATION_RUNNING,
2244         "The write set algorithm cannot be changed when Group replication"
2245         " is running.",
2246         MYF(0));
2247     return true;
2248   }
2249 
2250   if ((var->is_global_persist()) &&
2251       global_system_variables.binlog_format != BINLOG_FORMAT_ROW) {
2252     my_error(ER_PREVENTS_VARIABLE_WITHOUT_RBR, MYF(0), var->var->name.str);
2253     return true;
2254   }
2255 
2256   if (var->type == OPT_SESSION &&
2257       thd->variables.binlog_format != BINLOG_FORMAT_ROW) {
2258     my_error(ER_PREVENTS_VARIABLE_WITHOUT_RBR, MYF(0), var->var->name.str);
2259     return true;
2260   }
2261   /*
2262     if in a stored function/trigger, it's too late to change
2263   */
2264   if (thd->in_sub_stmt) {
2265     my_error(ER_VARIABLE_NOT_SETTABLE_IN_TRANSACTION, MYF(0),
2266              var->var->name.str);
2267     return true;
2268   }
2269   /*
2270     Make the session variable 'transaction_write_set_extraction' read-only
2271     inside a transaction.
2272   */
2273   if (thd->in_active_multi_stmt_transaction()) {
2274     my_error(ER_VARIABLE_NOT_SETTABLE_IN_TRANSACTION, MYF(0),
2275              var->var->name.str);
2276     return true;
2277   }
2278   /*
2279     Disallow changing variable 'transaction_write_set_extraction' while
2280     binlog_transaction_dependency_tracking is different from COMMIT_ORDER.
2281   */
2282   if (mysql_bin_log.m_dependency_tracker.m_opt_tracking_mode !=
2283       DEPENDENCY_TRACKING_COMMIT_ORDER) {
2284     my_error(ER_WRONG_USAGE, MYF(0),
2285              "transaction_write_set_extraction (changed)",
2286              "binlog_transaction_dependency_tracking (!= COMMIT_ORDER)");
2287     return true;
2288   }
2289 
2290   return false;
2291 }
2292 
2293 static Sys_var_enum Sys_extract_write_set(
2294     "transaction_write_set_extraction",
2295     "This option is used to let the server know when to "
2296     "extract the write set which will be used for various purposes. ",
2297     SESSION_VAR(transaction_write_set_extraction), CMD_LINE(OPT_ARG),
2298     transaction_write_set_hashing_algorithms, DEFAULT(HASH_ALGORITHM_XXHASH64),
2299     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(transaction_write_set_check),
2300     ON_UPDATE(nullptr));
2301 
2302 static Sys_var_ulong Sys_rpl_stop_slave_timeout(
2303     "rpl_stop_slave_timeout",
2304     "Timeout in seconds to wait for slave to stop before returning a "
2305     "warning.",
2306     GLOBAL_VAR(rpl_stop_slave_timeout), CMD_LINE(REQUIRED_ARG),
2307     VALID_RANGE(2, LONG_TIMEOUT), DEFAULT(LONG_TIMEOUT), BLOCK_SIZE(1));
2308 
2309 static Sys_var_enum Sys_binlog_error_action(
2310     "binlog_error_action",
2311     "When statements cannot be written to the binary log due to a fatal "
2312     "error, the server can either ignore the error and let the master "
2313     "continue, or abort.",
2314     GLOBAL_VAR(binlog_error_action), CMD_LINE(REQUIRED_ARG),
2315     binlog_error_action_list, DEFAULT(ABORT_SERVER));
2316 
2317 static Sys_var_bool Sys_trust_function_creators(
2318     "log_bin_trust_function_creators",
2319     "If set to FALSE (the default), then when --log-bin is used, creation "
2320     "of a stored function (or trigger) is allowed only to users having the "
2321     "SUPER privilege and only if this stored function (trigger) may not "
2322     "break binary logging. Note that if ALL connections to this server "
2323     "ALWAYS use row-based binary logging, the security issues do not "
2324     "exist and the binary logging cannot break, so you can safely set "
2325     "this to TRUE",
2326     GLOBAL_VAR(trust_function_creators), CMD_LINE(OPT_ARG), DEFAULT(false));
2327 
2328 static Sys_var_bool Sys_check_proxy_users(
2329     "check_proxy_users",
2330     "If set to FALSE (the default), then proxy user identity will not be "
2331     "mapped for authentication plugins which support mapping from grant "
2332     "tables.  When set to TRUE, users associated with authentication "
2333     "plugins which signal proxy user mapping should be done according to "
2334     "GRANT PROXY privilege definition.",
2335     GLOBAL_VAR(check_proxy_users), CMD_LINE(OPT_ARG), DEFAULT(false));
2336 
2337 static Sys_var_bool Sys_mysql_native_password_proxy_users(
2338     "mysql_native_password_proxy_users",
2339     "If set to FALSE (the default), then the mysql_native_password "
2340     "plugin will not signal for authenticated users to be checked for "
2341     "mapping "
2342     "to proxy users.  When set to TRUE, the plugin will flag associated "
2343     "authenticated accounts to be mapped to proxy users when the server "
2344     "option "
2345     "check_proxy_users is enabled.",
2346     GLOBAL_VAR(mysql_native_password_proxy_users), CMD_LINE(OPT_ARG),
2347     DEFAULT(false));
2348 
2349 static Sys_var_bool Sys_sha256_password_proxy_users(
2350     "sha256_password_proxy_users",
2351     "If set to FALSE (the default), then the sha256_password authentication "
2352     "plugin will not signal for authenticated users to be checked for "
2353     "mapping "
2354     "to proxy users.  When set to TRUE, the plugin will flag associated "
2355     "authenticated accounts to be mapped to proxy users when the server "
2356     "option "
2357     "check_proxy_users is enabled.",
2358     GLOBAL_VAR(sha256_password_proxy_users), CMD_LINE(OPT_ARG), DEFAULT(false));
2359 
check_log_bin_use_v1_row_events(sys_var *,THD * thd,set_var * var)2360 static bool check_log_bin_use_v1_row_events(sys_var *, THD *thd, set_var *var) {
2361   if (var->save_result.ulonglong_value == 1 &&
2362       global_system_variables.binlog_row_value_options != 0)
2363     push_warning_printf(thd, Sql_condition::SL_WARNING,
2364                         ER_WARN_BINLOG_V1_ROW_EVENTS_DISABLED,
2365                         ER_THD(thd, ER_WARN_BINLOG_V1_ROW_EVENTS_DISABLED),
2366                         "binlog_row_value_options=PARTIAL_JSON");
2367   return false;
2368 }
2369 
2370 static Sys_var_bool Sys_log_bin_use_v1_row_events(
2371     "log_bin_use_v1_row_events",
2372     "If equal to 1 then version 1 row events are written to a row based "
2373     "binary log.  If equal to 0, then the latest version of events are "
2374     "written.  "
2375     "This option is useful during some upgrades.",
2376     NON_PERSIST GLOBAL_VAR(log_bin_use_v1_row_events),
2377     CMD_LINE(OPT_ARG, OPT_LOG_BIN_USE_V1_ROW_EVENTS), DEFAULT(false),
2378     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_log_bin_use_v1_row_events),
2379     ON_UPDATE(nullptr), DEPRECATED_VAR(""));
2380 
2381 static Sys_var_charptr Sys_log_error(
2382     "log_error", "Error log file",
2383     READ_ONLY NON_PERSIST GLOBAL_VAR(log_error_dest),
2384     CMD_LINE(OPT_ARG, OPT_LOG_ERROR), IN_FS_CHARSET,
2385     DEFAULT(disabled_my_option), NO_MUTEX_GUARD, NOT_IN_BINLOG,
2386     ON_CHECK(nullptr), ON_UPDATE(nullptr), nullptr, sys_var::PARSE_EARLY);
2387 
check_log_error_services(sys_var * self,THD * thd,set_var * var)2388 static bool check_log_error_services(sys_var *self, THD *thd, set_var *var) {
2389   // test whether syntax is OK and services exist
2390   size_t pos;
2391 
2392   if (var->save_result.string_value.str == nullptr) return true;
2393 
2394   if (log_builtins_error_stack(var->save_result.string_value.str, true, &pos) <
2395       0) {
2396     push_warning_printf(
2397         thd, Sql_condition::SL_WARNING, ER_CANT_SET_ERROR_LOG_SERVICE,
2398         ER_THD(thd, ER_CANT_SET_ERROR_LOG_SERVICE), self->name.str,
2399         &((char *)var->save_result.string_value.str)[pos]);
2400     return true;
2401   } else if (strlen(var->save_result.string_value.str) < 1) {
2402     push_warning_printf(
2403         thd, Sql_condition::SL_WARNING, ER_EMPTY_PIPELINE_FOR_ERROR_LOG_SERVICE,
2404         ER_THD(thd, ER_EMPTY_PIPELINE_FOR_ERROR_LOG_SERVICE), self->name.str);
2405   }
2406 
2407   return false;
2408 }
2409 
fix_log_error_services(sys_var * self MY_ATTRIBUTE ((unused)),THD * thd,enum_var_type type MY_ATTRIBUTE ((unused)))2410 static bool fix_log_error_services(sys_var *self MY_ATTRIBUTE((unused)),
2411                                    THD *thd,
2412                                    enum_var_type type MY_ATTRIBUTE((unused))) {
2413   // syntax is OK and services exist; try to initialize them!
2414   size_t pos;
2415   if (log_builtins_error_stack(opt_log_error_services, false, &pos) < 0) {
2416     if (pos < strlen(opt_log_error_services)) /* purecov: begin inspected */
2417       push_warning_printf(
2418           thd, Sql_condition::SL_WARNING, ER_CANT_START_ERROR_LOG_SERVICE,
2419           ER_THD(thd, ER_CANT_START_ERROR_LOG_SERVICE), self->name.str,
2420           &((char *)opt_log_error_services)[pos]);
2421     return true; /* purecov: end */
2422   }
2423 
2424   return false;
2425 }
2426 
2427 static Sys_var_charptr Sys_log_error_services(
2428     "log_error_services",
2429     "Services that should be called when an error event is received",
2430     PERSIST_AS_READONLY GLOBAL_VAR(opt_log_error_services),
2431     CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET,
2432     DEFAULT(LOG_ERROR_SERVICES_DEFAULT), NO_MUTEX_GUARD, NOT_IN_BINLOG,
2433     ON_CHECK(check_log_error_services), ON_UPDATE(fix_log_error_services));
2434 
check_log_error_suppression_list(sys_var * self,THD * thd,set_var * var)2435 static bool check_log_error_suppression_list(sys_var *self, THD *thd,
2436                                              set_var *var) {
2437   int i;
2438 
2439   if (var->save_result.string_value.str == nullptr) return true;
2440 
2441   if ((i = log_builtins_filter_parse_suppression_list(
2442            var->save_result.string_value.str, false)) < 0) {
2443     push_warning_printf(
2444         thd, Sql_condition::SL_WARNING, ER_CANT_SET_ERROR_SUPPRESSION_LIST,
2445         ER_THD(thd, ER_CANT_SET_ERROR_SUPPRESSION_LIST), self->name.str,
2446         &((char *)var->save_result.string_value.str)[-(i + 1)]);
2447     return true;
2448   }
2449 
2450   return false;
2451 }
2452 
fix_log_error_suppression_list(sys_var * self MY_ATTRIBUTE ((unused)),THD * thd MY_ATTRIBUTE ((unused)),enum_var_type type MY_ATTRIBUTE ((unused)))2453 static bool fix_log_error_suppression_list(
2454     sys_var *self MY_ATTRIBUTE((unused)), THD *thd MY_ATTRIBUTE((unused)),
2455     enum_var_type type MY_ATTRIBUTE((unused))) {
2456   // syntax is OK and errcodes have messages; try to make filter rules for
2457   // them!
2458   int rr = log_builtins_filter_parse_suppression_list(
2459       opt_log_error_suppression_list, true);
2460   return (rr < 0) ? true : false;
2461 }
2462 
2463 static Sys_var_charptr Sys_log_error_suppression_list(
2464     "log_error_suppression_list",
2465     "Comma-separated list of error-codes. Error messages corresponding to "
2466     "these codes will not be included in the error log. Only events with a "
2467     "severity of Warning or Information can be suppressed; events with "
2468     "System "
2469     "or Error severity will always be included. Requires the filter "
2470     "\'log_filter_internal\' to be set in @@global.log_error_services, which "
2471     "is the default.",
2472     PERSIST_AS_READONLY GLOBAL_VAR(opt_log_error_suppression_list),
2473     CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET, DEFAULT(""), NO_MUTEX_GUARD,
2474     NOT_IN_BINLOG, ON_CHECK(check_log_error_suppression_list),
2475     ON_UPDATE(fix_log_error_suppression_list));
2476 
2477 static Sys_var_bool Sys_log_queries_not_using_indexes(
2478     "log_queries_not_using_indexes",
2479     "Log queries that are executed without benefit of any index to the "
2480     "slow log if it is open",
2481     GLOBAL_VAR(opt_log_queries_not_using_indexes), CMD_LINE(OPT_ARG),
2482     DEFAULT(false));
2483 
2484 static Sys_var_bool Sys_log_slow_admin_statements(
2485     "log_slow_admin_statements",
2486     "Log slow OPTIMIZE, ANALYZE, ALTER and other administrative statements "
2487     "to "
2488     "the slow log if it is open.",
2489     GLOBAL_VAR(opt_log_slow_admin_statements), CMD_LINE(OPT_ARG),
2490     DEFAULT(false));
2491 
2492 static Sys_var_bool Sys_log_slow_slave_statements(
2493     "log_slow_slave_statements",
2494     "Log slow statements executed by slave thread to the slow log if it is "
2495     "open.",
2496     GLOBAL_VAR(opt_log_slow_slave_statements), CMD_LINE(OPT_ARG),
2497     DEFAULT(false));
2498 
update_log_throttle_queries_not_using_indexes(sys_var *,THD * thd,enum_var_type)2499 static bool update_log_throttle_queries_not_using_indexes(sys_var *, THD *thd,
2500                                                           enum_var_type) {
2501   // Check if we should print a summary of any suppressed lines to the slow
2502   // log now since opt_log_throttle_queries_not_using_indexes was changed.
2503   log_throttle_qni.flush(thd);
2504   return false;
2505 }
2506 
2507 static Sys_var_ulong Sys_log_throttle_queries_not_using_indexes(
2508     "log_throttle_queries_not_using_indexes",
2509     "Log at most this many 'not using index' warnings per minute to the "
2510     "slow log. Any further warnings will be condensed into a single "
2511     "summary line. A value of 0 disables throttling. "
2512     "Option has no effect unless --log_queries_not_using_indexes is set.",
2513     GLOBAL_VAR(opt_log_throttle_queries_not_using_indexes),
2514     CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, ULONG_MAX), DEFAULT(0),
2515     BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
2516     ON_UPDATE(update_log_throttle_queries_not_using_indexes));
2517 
update_log_error_verbosity(sys_var *,THD *,enum_var_type)2518 static bool update_log_error_verbosity(sys_var *, THD *, enum_var_type) {
2519   return (log_builtins_filter_update_verbosity(log_error_verbosity) < 0);
2520 }
2521 
2522 static Sys_var_ulong Sys_log_error_verbosity(
2523     "log_error_verbosity",
2524     "How detailed the error log should be. "
2525     "1, log errors only. "
2526     "2, log errors and warnings. "
2527     "3, log errors, warnings, and notes. "
2528     "Messages sent to the client are unaffected by this setting.",
2529     PERSIST_AS_READONLY GLOBAL_VAR(log_error_verbosity), CMD_LINE(REQUIRED_ARG),
2530     VALID_RANGE(1, 3), DEFAULT(2), BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG,
2531     ON_CHECK(nullptr), ON_UPDATE(update_log_error_verbosity));
2532 
2533 static Sys_var_enum Sys_log_timestamps(
2534     "log_timestamps",
2535     "UTC to timestamp log files in zulu time, for more concise timestamps "
2536     "and easier correlation of logs from servers from multiple time zones, "
2537     "or SYSTEM to use the system's local time. "
2538     "This affects only log files, not log tables, as the timestamp columns "
2539     "of the latter can be converted at will.",
2540     GLOBAL_VAR(opt_log_timestamps), CMD_LINE(REQUIRED_ARG),
2541     timestamp_type_names, DEFAULT(0), NO_MUTEX_GUARD, NOT_IN_BINLOG);
2542 
2543 static Sys_var_bool Sys_log_statements_unsafe_for_binlog(
2544     "log_statements_unsafe_for_binlog",
2545     "Log statements considered unsafe when using statement based binary "
2546     "logging.",
2547     GLOBAL_VAR(opt_log_unsafe_statements), CMD_LINE(OPT_ARG), DEFAULT(true));
2548 
update_cached_long_query_time(sys_var *,THD * thd,enum_var_type type)2549 static bool update_cached_long_query_time(sys_var *, THD *thd,
2550                                           enum_var_type type) {
2551   if (type == OPT_SESSION)
2552     thd->variables.long_query_time =
2553         double2ulonglong(thd->variables.long_query_time_double * 1e6);
2554   else
2555     global_system_variables.long_query_time =
2556         double2ulonglong(global_system_variables.long_query_time_double * 1e6);
2557   return false;
2558 }
2559 
2560 static Sys_var_double Sys_long_query_time(
2561     "long_query_time",
2562     "Log all queries that have taken more than long_query_time seconds "
2563     "to execute to file. The argument will be treated as a decimal value "
2564     "with microsecond precision",
2565     SESSION_VAR(long_query_time_double), CMD_LINE(REQUIRED_ARG),
2566     VALID_RANGE(0, LONG_TIMEOUT), DEFAULT(10), NO_MUTEX_GUARD, NOT_IN_BINLOG,
2567     ON_CHECK(nullptr), ON_UPDATE(update_cached_long_query_time));
2568 
fix_low_prio_updates(sys_var *,THD * thd,enum_var_type type)2569 static bool fix_low_prio_updates(sys_var *, THD *thd, enum_var_type type) {
2570   if (type == OPT_SESSION) {
2571     thd->update_lock_default =
2572         (thd->variables.low_priority_updates ? TL_WRITE_LOW_PRIORITY
2573                                              : TL_WRITE);
2574     thd->insert_lock_default =
2575         (thd->variables.low_priority_updates ? TL_WRITE_LOW_PRIORITY
2576                                              : TL_WRITE_CONCURRENT_INSERT);
2577   } else
2578     thr_upgraded_concurrent_insert_lock =
2579         (global_system_variables.low_priority_updates ? TL_WRITE_LOW_PRIORITY
2580                                                       : TL_WRITE);
2581   return false;
2582 }
2583 static Sys_var_bool Sys_low_priority_updates(
2584     "low_priority_updates",
2585     "INSERT/DELETE/UPDATE has lower priority than selects",
2586     SESSION_VAR(low_priority_updates), CMD_LINE(OPT_ARG), DEFAULT(false),
2587     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
2588     ON_UPDATE(fix_low_prio_updates));
2589 
2590 static Sys_var_bool Sys_lower_case_file_system(
2591     "lower_case_file_system",
2592     "Case sensitivity of file names on the file system where the "
2593     "data directory is located",
2594     READ_ONLY NON_PERSIST GLOBAL_VAR(lower_case_file_system), NO_CMD_LINE,
2595     DEFAULT(false));
2596 
2597 static Sys_var_uint Sys_lower_case_table_names(
2598     "lower_case_table_names",
2599     "If set to 1 table names are stored in lowercase on disk and table "
2600     "names will be case-insensitive.  Should be set to 2 if you are using "
2601     "a case insensitive file system",
2602     READ_ONLY GLOBAL_VAR(lower_case_table_names),
2603     CMD_LINE(OPT_ARG, OPT_LOWER_CASE_TABLE_NAMES), VALID_RANGE(0, 2),
2604 #ifdef FN_NO_CASE_SENSE
2605     DEFAULT(1),
2606 #else
2607     DEFAULT(0),
2608 #endif
2609     BLOCK_SIZE(1));
2610 
session_readonly(sys_var * self,THD *,set_var * var)2611 static bool session_readonly(sys_var *self, THD *, set_var *var) {
2612   if (var->is_global_persist()) return false;
2613   my_error(ER_VARIABLE_IS_READONLY, MYF(0), "SESSION", self->name.str,
2614            "GLOBAL");
2615   return true;
2616 }
2617 
check_max_allowed_packet(sys_var * self,THD * thd,set_var * var)2618 static bool check_max_allowed_packet(sys_var *self, THD *thd, set_var *var) {
2619   longlong val;
2620   if (session_readonly(self, thd, var)) return true;
2621 
2622   val = var->save_result.ulonglong_value;
2623   if (val < (longlong)global_system_variables.net_buffer_length) {
2624     push_warning_printf(thd, Sql_condition::SL_WARNING, WARN_OPTION_BELOW_LIMIT,
2625                         ER_THD(thd, WARN_OPTION_BELOW_LIMIT),
2626                         "max_allowed_packet", "net_buffer_length");
2627   }
2628   return false;
2629 }
2630 
2631 static Sys_var_ulong Sys_max_allowed_packet(
2632     "max_allowed_packet",
2633     "Max packet length to send to or receive from the server",
2634     SESSION_VAR(max_allowed_packet), CMD_LINE(REQUIRED_ARG),
2635     VALID_RANGE(1024, 1024 * 1024 * 1024), DEFAULT(64 * 1024 * 1024),
2636     BLOCK_SIZE(1024), NO_MUTEX_GUARD, NOT_IN_BINLOG,
2637     ON_CHECK(check_max_allowed_packet));
2638 
2639 static Sys_var_ulong Sys_slave_max_allowed_packet(
2640     "slave_max_allowed_packet",
2641     "The maximum packet length to sent successfully from the master to "
2642     "slave.",
2643     GLOBAL_VAR(slave_max_allowed_packet), CMD_LINE(REQUIRED_ARG),
2644     VALID_RANGE(1024, MAX_MAX_ALLOWED_PACKET), DEFAULT(MAX_MAX_ALLOWED_PACKET),
2645     BLOCK_SIZE(1024));
2646 
2647 static Sys_var_ulonglong Sys_max_binlog_cache_size(
2648     "max_binlog_cache_size", "Sets the total size of the transactional cache",
2649     GLOBAL_VAR(max_binlog_cache_size), CMD_LINE(REQUIRED_ARG),
2650     VALID_RANGE(IO_SIZE, ULLONG_MAX), DEFAULT((ULLONG_MAX / IO_SIZE) * IO_SIZE),
2651     BLOCK_SIZE(IO_SIZE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
2652     ON_UPDATE(fix_binlog_cache_size));
2653 
2654 static Sys_var_ulonglong Sys_max_binlog_stmt_cache_size(
2655     "max_binlog_stmt_cache_size", "Sets the total size of the statement cache",
2656     GLOBAL_VAR(max_binlog_stmt_cache_size), CMD_LINE(REQUIRED_ARG),
2657     VALID_RANGE(IO_SIZE, ULLONG_MAX), DEFAULT((ULLONG_MAX / IO_SIZE) * IO_SIZE),
2658     BLOCK_SIZE(IO_SIZE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
2659     ON_UPDATE(fix_binlog_stmt_cache_size));
2660 
fix_max_binlog_size(sys_var *,THD *,enum_var_type)2661 static bool fix_max_binlog_size(sys_var *, THD *, enum_var_type) {
2662   mysql_bin_log.set_max_size(max_binlog_size);
2663   /*
2664     For multisource replication, this max size is set to all relay logs
2665     per channel. So, run through them
2666   */
2667   if (!max_relay_log_size) {
2668     Master_info *mi = nullptr;
2669 
2670     channel_map.wrlock();
2671     for (mi_map::iterator it = channel_map.begin(); it != channel_map.end();
2672          it++) {
2673       mi = it->second;
2674       if (mi != nullptr) mi->rli->relay_log.set_max_size(max_binlog_size);
2675     }
2676     channel_map.unlock();
2677   }
2678   return false;
2679 }
2680 static Sys_var_ulong Sys_max_binlog_size(
2681     "max_binlog_size",
2682     "Binary log will be rotated automatically when the size exceeds this "
2683     "value. Will also apply to relay logs if max_relay_log_size is 0",
2684     GLOBAL_VAR(max_binlog_size), CMD_LINE(REQUIRED_ARG),
2685     VALID_RANGE(IO_SIZE, 1024 * 1024L * 1024L), DEFAULT(1024 * 1024L * 1024L),
2686     BLOCK_SIZE(IO_SIZE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
2687     ON_UPDATE(fix_max_binlog_size));
2688 
2689 static Sys_var_ulong Sys_max_connections(
2690     "max_connections", "The number of simultaneous clients allowed",
2691     GLOBAL_VAR(max_connections), CMD_LINE(REQUIRED_ARG), VALID_RANGE(1, 100000),
2692     DEFAULT(MAX_CONNECTIONS_DEFAULT), BLOCK_SIZE(1), NO_MUTEX_GUARD,
2693     NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(nullptr), nullptr,
2694     /* max_connections is used as a sizing hint by the performance schema. */
2695     sys_var::PARSE_EARLY);
2696 
2697 static Sys_var_ulong Sys_max_connect_errors(
2698     "max_connect_errors",
2699     "If there is more than this number of interrupted connections from "
2700     "a host this host will be blocked from further connections",
2701     GLOBAL_VAR(max_connect_errors), CMD_LINE(REQUIRED_ARG),
2702     VALID_RANGE(1, ULONG_MAX), DEFAULT(100), BLOCK_SIZE(1));
2703 
2704 static Sys_var_long Sys_max_digest_length(
2705     "max_digest_length", "Maximum length considered for digest text.",
2706     READ_ONLY GLOBAL_VAR(max_digest_length), CMD_LINE(REQUIRED_ARG),
2707     VALID_RANGE(0, 1024 * 1024), DEFAULT(1024), BLOCK_SIZE(1));
2708 
check_max_delayed_threads(sys_var *,THD *,set_var * var)2709 static bool check_max_delayed_threads(sys_var *, THD *, set_var *var) {
2710   return (!var->is_global_persist()) && var->save_result.ulonglong_value != 0 &&
2711          var->save_result.ulonglong_value !=
2712              global_system_variables.max_insert_delayed_threads;
2713 }
2714 
2715 // Alias for max_delayed_threads
2716 static Sys_var_ulong Sys_max_insert_delayed_threads(
2717     "max_insert_delayed_threads",
2718     "Don't start more than this number of threads to handle INSERT "
2719     "DELAYED statements. If set to zero INSERT DELAYED will be not used. "
2720     "This variable is deprecated along with INSERT DELAYED.",
2721     SESSION_VAR(max_insert_delayed_threads), NO_CMD_LINE, VALID_RANGE(0, 16384),
2722     DEFAULT(20), BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG,
2723     ON_CHECK(check_max_delayed_threads), ON_UPDATE(nullptr),
2724     DEPRECATED_VAR(""));
2725 
2726 static Sys_var_ulong Sys_max_delayed_threads(
2727     "max_delayed_threads",
2728     "Don't start more than this number of threads to handle INSERT "
2729     "DELAYED statements. If set to zero INSERT DELAYED will be not used. "
2730     "This variable is deprecated along with INSERT DELAYED.",
2731     SESSION_VAR(max_insert_delayed_threads), CMD_LINE(REQUIRED_ARG),
2732     VALID_RANGE(0, 16384), DEFAULT(20), BLOCK_SIZE(1), NO_MUTEX_GUARD,
2733     NOT_IN_BINLOG, ON_CHECK(check_max_delayed_threads), ON_UPDATE(nullptr),
2734     DEPRECATED_VAR(""));
2735 
2736 static Sys_var_ulong Sys_max_error_count(
2737     "max_error_count", "Max number of errors/warnings to store for a statement",
2738     HINT_UPDATEABLE SESSION_VAR(max_error_count), CMD_LINE(REQUIRED_ARG),
2739     VALID_RANGE(0, 65535), DEFAULT(DEFAULT_ERROR_COUNT), BLOCK_SIZE(1));
2740 
2741 static Sys_var_ulonglong Sys_max_heap_table_size(
2742     "max_heap_table_size",
2743     "Don't allow creation of heap tables bigger than this",
2744     HINT_UPDATEABLE SESSION_VAR(max_heap_table_size), CMD_LINE(REQUIRED_ARG),
2745     VALID_RANGE(16384, (ulonglong) ~(intptr)0), DEFAULT(16 * 1024 * 1024),
2746     BLOCK_SIZE(1024));
2747 
2748 // relies on DBUG_ASSERT(sizeof(my_thread_id) == 4);
2749 static Sys_var_uint Sys_pseudo_thread_id(
2750     "pseudo_thread_id", "This variable is for internal server use",
2751     SESSION_ONLY(pseudo_thread_id), NO_CMD_LINE, VALID_RANGE(0, UINT_MAX32),
2752     DEFAULT(0), BLOCK_SIZE(1), NO_MUTEX_GUARD, IN_BINLOG,
2753     ON_CHECK(check_session_admin));
2754 
fix_max_join_size(sys_var * self,THD * thd,enum_var_type type)2755 static bool fix_max_join_size(sys_var *self, THD *thd, enum_var_type type) {
2756   System_variables *sv = (self->is_global_persist(type))
2757                              ? &global_system_variables
2758                              : &thd->variables;
2759   if (sv->max_join_size == HA_POS_ERROR)
2760     sv->option_bits |= OPTION_BIG_SELECTS;
2761   else
2762     sv->option_bits &= ~OPTION_BIG_SELECTS;
2763   return false;
2764 }
2765 static Sys_var_harows Sys_max_join_size(
2766     "max_join_size",
2767     "Joins that are probably going to read more than max_join_size "
2768     "records return an error",
2769     HINT_UPDATEABLE SESSION_VAR(max_join_size), CMD_LINE(REQUIRED_ARG),
2770     VALID_RANGE(1, HA_POS_ERROR), DEFAULT(HA_POS_ERROR), BLOCK_SIZE(1),
2771     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
2772     ON_UPDATE(fix_max_join_size));
2773 
2774 static Sys_var_ulong Sys_max_seeks_for_key(
2775     "max_seeks_for_key",
2776     "Limit assumed max number of seeks when looking up rows based on a key",
2777     HINT_UPDATEABLE SESSION_VAR(max_seeks_for_key), CMD_LINE(REQUIRED_ARG),
2778     VALID_RANGE(1, ULONG_MAX), DEFAULT(ULONG_MAX), BLOCK_SIZE(1));
2779 
2780 static Sys_var_ulong Sys_max_length_for_sort_data(
2781     "max_length_for_sort_data",
2782     "This variable is deprecated and will be removed in a future release.",
2783     HINT_UPDATEABLE SESSION_VAR(max_length_for_sort_data),
2784     CMD_LINE(REQUIRED_ARG), VALID_RANGE(4, 8192 * 1024L), DEFAULT(4096),
2785     BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
2786     ON_UPDATE(nullptr), DEPRECATED_VAR(""));
2787 
2788 static Sys_var_ulong Sys_max_points_in_geometry(
2789     "max_points_in_geometry", "Maximum number of points in a geometry",
2790     HINT_UPDATEABLE SESSION_VAR(max_points_in_geometry), CMD_LINE(OPT_ARG),
2791     VALID_RANGE(3, 1024 * 1024L), DEFAULT(64 * 1024), BLOCK_SIZE(1));
2792 
2793 static PolyLock_mutex PLock_prepared_stmt_count(&LOCK_prepared_stmt_count);
2794 
2795 static Sys_var_ulong Sys_max_prepared_stmt_count(
2796     "max_prepared_stmt_count",
2797     "Maximum number of prepared statements in the server",
2798     GLOBAL_VAR(max_prepared_stmt_count), CMD_LINE(REQUIRED_ARG),
2799     VALID_RANGE(0, num_prepared_stmt_limit), DEFAULT(16382), BLOCK_SIZE(1),
2800     &PLock_prepared_stmt_count, NOT_IN_BINLOG, ON_CHECK(nullptr),
2801     ON_UPDATE(nullptr), nullptr,
2802     /* max_prepared_stmt_count is used as a sizing hint by the performance
2803        schema. */
2804     sys_var::PARSE_EARLY);
2805 
fix_max_relay_log_size(sys_var *,THD *,enum_var_type)2806 static bool fix_max_relay_log_size(sys_var *, THD *, enum_var_type) {
2807   Master_info *mi = nullptr;
2808 
2809   channel_map.wrlock();
2810   for (mi_map::iterator it = channel_map.begin(); it != channel_map.end();
2811        it++) {
2812     mi = it->second;
2813 
2814     if (mi != nullptr)
2815       mi->rli->relay_log.set_max_size(max_relay_log_size ? max_relay_log_size
2816                                                          : max_binlog_size);
2817   }
2818   channel_map.unlock();
2819   return false;
2820 }
2821 static Sys_var_ulong Sys_max_relay_log_size(
2822     "max_relay_log_size",
2823     "If non-zero: relay log will be rotated automatically when the "
2824     "size exceeds this value; if zero: when the size "
2825     "exceeds max_binlog_size",
2826     GLOBAL_VAR(max_relay_log_size), CMD_LINE(REQUIRED_ARG),
2827     VALID_RANGE(0, 1024L * 1024 * 1024), DEFAULT(0), BLOCK_SIZE(IO_SIZE),
2828     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
2829     ON_UPDATE(fix_max_relay_log_size));
2830 
2831 static Sys_var_ulong Sys_max_sort_length(
2832     "max_sort_length",
2833     "The number of bytes to use when sorting long values with PAD SPACE "
2834     "collations (only the first max_sort_length bytes of each value are "
2835     "used; the rest are ignored)",
2836     HINT_UPDATEABLE SESSION_VAR(max_sort_length), CMD_LINE(REQUIRED_ARG),
2837     VALID_RANGE(4, 8192 * 1024L), DEFAULT(1024), BLOCK_SIZE(1));
2838 
2839 static Sys_var_ulong Sys_max_sp_recursion_depth(
2840     "max_sp_recursion_depth", "Maximum stored procedure recursion depth",
2841     SESSION_VAR(max_sp_recursion_depth), CMD_LINE(OPT_ARG), VALID_RANGE(0, 255),
2842     DEFAULT(0), BLOCK_SIZE(1));
2843 
2844 // non-standard session_value_ptr() here
2845 static Sys_var_max_user_conn Sys_max_user_connections(
2846     "max_user_connections",
2847     "The maximum number of active connections for a single user "
2848     "(0 = no limit)",
2849     SESSION_VAR(max_user_connections), CMD_LINE(REQUIRED_ARG),
2850     VALID_RANGE(0, UINT_MAX), DEFAULT(0), BLOCK_SIZE(1), NO_MUTEX_GUARD,
2851     NOT_IN_BINLOG, ON_CHECK(session_readonly));
2852 
2853 static Sys_var_ulong Sys_max_write_lock_count(
2854     "max_write_lock_count",
2855     "After this many write locks, allow some read locks to run in between",
2856     GLOBAL_VAR(max_write_lock_count), CMD_LINE(REQUIRED_ARG),
2857     VALID_RANGE(1, ULONG_MAX), DEFAULT(ULONG_MAX), BLOCK_SIZE(1));
2858 
2859 static Sys_var_ulong Sys_min_examined_row_limit(
2860     "min_examined_row_limit",
2861     "Don't write queries to slow log that examine fewer rows "
2862     "than that",
2863     SESSION_VAR(min_examined_row_limit), CMD_LINE(REQUIRED_ARG),
2864     VALID_RANGE(0, ULONG_MAX), DEFAULT(0), BLOCK_SIZE(1));
2865 
2866 #ifdef _WIN32
2867 static Sys_var_bool Sys_named_pipe("named_pipe", "Enable the named pipe (NT)",
2868                                    READ_ONLY NON_PERSIST
2869                                        GLOBAL_VAR(opt_enable_named_pipe),
2870                                    CMD_LINE(OPT_ARG), DEFAULT(false));
2871 
2872 static PolyLock_rwlock PLock_named_pipe_full_access_group(
2873     &LOCK_named_pipe_full_access_group);
check_named_pipe_full_access_group(sys_var * self,THD * thd,set_var * var)2874 static bool check_named_pipe_full_access_group(sys_var *self, THD *thd,
2875                                                set_var *var) {
2876   if (!var->value) return false;  // DEFAULT is ok
2877 
2878   if (!is_valid_named_pipe_full_access_group(
2879           var->save_result.string_value.str)) {
2880     my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), self->name.str,
2881              var->save_result.string_value.str);
2882     return true;
2883   }
2884   return false;
2885 }
fix_named_pipe_full_access_group(sys_var *,THD *,enum_var_type)2886 static bool fix_named_pipe_full_access_group(sys_var *, THD *, enum_var_type) {
2887   return update_named_pipe_full_access_group(named_pipe_full_access_group);
2888 }
2889 static Sys_var_charptr Sys_named_pipe_full_access_group(
2890     "named_pipe_full_access_group",
2891     "Name of Windows group granted full access to the named pipe",
2892     GLOBAL_VAR(named_pipe_full_access_group),
2893     CMD_LINE(REQUIRED_ARG, OPT_NAMED_PIPE_FULL_ACCESS_GROUP), IN_FS_CHARSET,
2894     DEFAULT(DEFAULT_NAMED_PIPE_FULL_ACCESS_GROUP),
2895     &PLock_named_pipe_full_access_group, NOT_IN_BINLOG,
2896     ON_CHECK(check_named_pipe_full_access_group),
2897     ON_UPDATE(fix_named_pipe_full_access_group));
2898 #endif
2899 
check_net_buffer_length(sys_var * self,THD * thd,set_var * var)2900 static bool check_net_buffer_length(sys_var *self, THD *thd, set_var *var) {
2901   longlong val;
2902   if (session_readonly(self, thd, var)) return true;
2903 
2904   val = var->save_result.ulonglong_value;
2905   if (val > (longlong)global_system_variables.max_allowed_packet) {
2906     push_warning_printf(thd, Sql_condition::SL_WARNING, WARN_OPTION_BELOW_LIMIT,
2907                         ER_THD(thd, WARN_OPTION_BELOW_LIMIT),
2908                         "max_allowed_packet", "net_buffer_length");
2909   }
2910   return false;
2911 }
2912 static Sys_var_ulong Sys_net_buffer_length(
2913     "net_buffer_length", "Buffer length for TCP/IP and socket communication",
2914     SESSION_VAR(net_buffer_length), CMD_LINE(REQUIRED_ARG),
2915     VALID_RANGE(1024, 1024 * 1024), DEFAULT(16384), BLOCK_SIZE(1024),
2916     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_net_buffer_length));
2917 
fix_net_read_timeout(sys_var * self,THD * thd,enum_var_type type)2918 static bool fix_net_read_timeout(sys_var *self, THD *thd, enum_var_type type) {
2919   if (!self->is_global_persist(type)) {
2920     // net_buffer_length is a specific property for the classic protocols
2921     if (!thd->is_classic_protocol()) {
2922       my_error(ER_PLUGGABLE_PROTOCOL_COMMAND_NOT_SUPPORTED, MYF(0));
2923       return true;
2924     }
2925     my_net_set_read_timeout(thd->get_protocol_classic()->get_net(),
2926                             thd->variables.net_read_timeout);
2927   }
2928   return false;
2929 }
2930 static Sys_var_ulong Sys_net_read_timeout(
2931     "net_read_timeout",
2932     "Number of seconds to wait for more data from a connection before "
2933     "aborting the read",
2934     SESSION_VAR(net_read_timeout), CMD_LINE(REQUIRED_ARG),
2935     VALID_RANGE(1, LONG_TIMEOUT), DEFAULT(NET_READ_TIMEOUT), BLOCK_SIZE(1),
2936     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
2937     ON_UPDATE(fix_net_read_timeout));
2938 
fix_net_write_timeout(sys_var * self,THD * thd,enum_var_type type)2939 static bool fix_net_write_timeout(sys_var *self, THD *thd, enum_var_type type) {
2940   if (!self->is_global_persist(type)) {
2941     // net_read_timeout is a specific property for the classic protocols
2942     if (!thd->is_classic_protocol()) {
2943       my_error(ER_PLUGGABLE_PROTOCOL_COMMAND_NOT_SUPPORTED, MYF(0));
2944       return true;
2945     }
2946     my_net_set_write_timeout(thd->get_protocol_classic()->get_net(),
2947                              thd->variables.net_write_timeout);
2948   }
2949   return false;
2950 }
2951 static Sys_var_ulong Sys_net_write_timeout(
2952     "net_write_timeout",
2953     "Number of seconds to wait for a block to be written to a connection "
2954     "before aborting the write",
2955     SESSION_VAR(net_write_timeout), CMD_LINE(REQUIRED_ARG),
2956     VALID_RANGE(1, LONG_TIMEOUT), DEFAULT(NET_WRITE_TIMEOUT), BLOCK_SIZE(1),
2957     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
2958     ON_UPDATE(fix_net_write_timeout));
2959 
fix_net_retry_count(sys_var * self,THD * thd,enum_var_type type)2960 static bool fix_net_retry_count(sys_var *self, THD *thd, enum_var_type type) {
2961   if (!self->is_global_persist(type)) {
2962     // net_write_timeout is a specific property for the classic protocols
2963     if (!thd->is_classic_protocol()) {
2964       my_error(ER_PLUGGABLE_PROTOCOL_COMMAND_NOT_SUPPORTED, MYF(0));
2965       return true;
2966     }
2967     thd->get_protocol_classic()->get_net()->retry_count =
2968         thd->variables.net_retry_count;
2969   }
2970   return false;
2971 }
2972 static Sys_var_ulong Sys_net_retry_count(
2973     "net_retry_count",
2974     "If a read on a communication port is interrupted, retry this "
2975     "many times before giving up",
2976     SESSION_VAR(net_retry_count), CMD_LINE(REQUIRED_ARG),
2977     VALID_RANGE(1, ULONG_MAX), DEFAULT(MYSQLD_NET_RETRY_COUNT), BLOCK_SIZE(1),
2978     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
2979     ON_UPDATE(fix_net_retry_count));
2980 
2981 static Sys_var_bool Sys_new_mode("new",
2982                                  "Use very new possible \"unsafe\" functions",
2983                                  SESSION_VAR(new_mode), CMD_LINE(OPT_ARG, 'n'),
2984                                  DEFAULT(false));
2985 
2986 static Sys_var_bool Sys_old_mode("old", "Use compatible behavior",
2987                                  READ_ONLY GLOBAL_VAR(old_mode),
2988                                  CMD_LINE(OPT_ARG), DEFAULT(false));
2989 
2990 static Sys_var_bool Sys_old_alter_table("old_alter_table",
2991                                         "Use old, non-optimized alter table",
2992                                         SESSION_VAR(old_alter_table),
2993                                         CMD_LINE(OPT_ARG), DEFAULT(false));
2994 
2995 static Sys_var_ulong Sys_open_files_limit(
2996     "open_files_limit",
2997     "If this is not 0, then mysqld will use this value to reserve file "
2998     "descriptors to use with setrlimit(). If this value is 0 then mysqld "
2999     "will reserve max_connections*5 or max_connections + table_open_cache*2 "
3000     "(whichever is larger) number of file descriptors",
3001     READ_ONLY GLOBAL_VAR(open_files_limit), CMD_LINE(REQUIRED_ARG),
3002     VALID_RANGE(0, OS_FILE_LIMIT), DEFAULT(0), BLOCK_SIZE(1), NO_MUTEX_GUARD,
3003     NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(nullptr), nullptr,
3004     /* open_files_limit is used as a sizing hint by the performance schema. */
3005     sys_var::PARSE_EARLY);
3006 
3007 /// @todo change to enum
3008 static Sys_var_ulong Sys_optimizer_prune_level(
3009     "optimizer_prune_level",
3010     "Controls the heuristic(s) applied during query optimization to prune "
3011     "less-promising partial plans from the optimizer search space. "
3012     "Meaning: 0 - do not apply any heuristic, thus perform exhaustive "
3013     "search; 1 - prune plans based on number of retrieved rows",
3014     HINT_UPDATEABLE SESSION_VAR(optimizer_prune_level), CMD_LINE(REQUIRED_ARG),
3015     VALID_RANGE(0, 1), DEFAULT(1), BLOCK_SIZE(1));
3016 
3017 static Sys_var_ulong Sys_optimizer_search_depth(
3018     "optimizer_search_depth",
3019     "Maximum depth of search performed by the query optimizer. Values "
3020     "larger than the number of relations in a query result in better "
3021     "query plans, but take longer to compile a query. Values smaller "
3022     "than the number of tables in a relation result in faster "
3023     "optimization, but may produce very bad query plans. If set to 0, "
3024     "the system will automatically pick a reasonable value",
3025     HINT_UPDATEABLE SESSION_VAR(optimizer_search_depth), CMD_LINE(REQUIRED_ARG),
3026     VALID_RANGE(0, MAX_TABLES + 1), DEFAULT(MAX_TABLES + 1), BLOCK_SIZE(1));
3027 
3028 static Sys_var_ulong Sys_range_optimizer_max_mem_size(
3029     "range_optimizer_max_mem_size",
3030     "Maximum amount of memory used by the range optimizer "
3031     "to allocate predicates during range analysis. "
3032     "The larger the number, more memory may be consumed during "
3033     "range analysis. If the value is too low to completed range "
3034     "optimization of a query, index range scan will not be "
3035     "considered for this query. A value of 0 means range optimizer "
3036     "does not have any cap on memory. ",
3037     HINT_UPDATEABLE SESSION_VAR(range_optimizer_max_mem_size),
3038     CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, ULONG_MAX), DEFAULT(8388608),
3039     BLOCK_SIZE(1));
3040 
limit_parser_max_mem_size(sys_var *,THD * thd,set_var * var)3041 static bool limit_parser_max_mem_size(sys_var *, THD *thd, set_var *var) {
3042   if (var->is_global_persist()) return false;
3043   ulonglong val = var->save_result.ulonglong_value;
3044   if (val > global_system_variables.parser_max_mem_size) {
3045     if (thd->security_context()->check_access(SUPER_ACL)) return false;
3046     var->save_result.ulonglong_value =
3047         global_system_variables.parser_max_mem_size;
3048     return throw_bounds_warning(thd, "parser_max_mem_size",
3049                                 true,  // fixed
3050                                 true,  // is_unsigned
3051                                 val);
3052   }
3053   return false;
3054 }
3055 
3056 constexpr size_t max_mem_sz = std::numeric_limits<size_t>::max();
3057 
3058 static Sys_var_ulonglong Sys_histogram_generation_max_mem_size(
3059     "histogram_generation_max_mem_size",
3060     "Maximum amount of memory available for generating histograms",
3061     SESSION_VAR(histogram_generation_max_mem_size), CMD_LINE(REQUIRED_ARG),
3062     VALID_RANGE(1000000, max_mem_sz), DEFAULT(20000000), BLOCK_SIZE(1),
3063     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_session_admin),
3064     ON_UPDATE(nullptr));
3065 
3066 /*
3067   Need at least 400Kb to get through bootstrap.
3068   Need at least 8Mb to get through mtr check testcase, which does
3069     SELECT * FROM INFORMATION_SCHEMA.VIEWS
3070 */
3071 static Sys_var_ulonglong Sys_parser_max_mem_size(
3072     "parser_max_mem_size", "Maximum amount of memory available to the parser",
3073     SESSION_VAR(parser_max_mem_size), CMD_LINE(REQUIRED_ARG),
3074     VALID_RANGE(10 * 1000 * 1000, max_mem_sz), DEFAULT(max_mem_sz),
3075     BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG,
3076     ON_CHECK(limit_parser_max_mem_size), ON_UPDATE(nullptr));
3077 
3078 /*
3079   There is no call on Sys_var_integer::do_check() for 'set xxx=default';
3080   The predefined default for parser_max_mem_size is "infinite".
3081   Update it in case we have seen option maximum-parser-max-mem-size
3082   Also update global_system_variables, so 'SELECT parser_max_mem_size'
3083   reports correct data.
3084 */
update_parser_max_mem_size()3085 export void update_parser_max_mem_size() {
3086   const ulonglong max_max = max_system_variables.parser_max_mem_size;
3087   if (max_max == max_mem_sz) return;
3088   // In case parser-max-mem-size is also set:
3089   const ulonglong new_val =
3090       std::min(max_max, global_system_variables.parser_max_mem_size);
3091   Sys_parser_max_mem_size.update_default(new_val);
3092   global_system_variables.parser_max_mem_size = new_val;
3093 }
3094 
3095 /**
3096   @note
3097   @b BEWARE! These must have the same order as the \#defines in sql_const.h!
3098 */
3099 static const char *optimizer_switch_names[] = {
3100     "index_merge",
3101     "index_merge_union",
3102     "index_merge_sort_union",
3103     "index_merge_intersection",
3104     "engine_condition_pushdown",
3105     "index_condition_pushdown",
3106     "mrr",
3107     "mrr_cost_based",
3108     "block_nested_loop",
3109     "batched_key_access",
3110     "materialization",
3111     "semijoin",
3112     "loosescan",
3113     "firstmatch",
3114     "duplicateweedout",
3115     "subquery_materialization_cost_based",
3116     "use_index_extensions",
3117     "condition_fanout_filter",
3118     "derived_merge",
3119     "use_invisible_indexes",
3120     "skip_scan",
3121     "hash_join",
3122     "subquery_to_derived",
3123     "prefer_ordering_index",
3124     "default",
3125     NullS};
3126 static Sys_var_flagset Sys_optimizer_switch(
3127     "optimizer_switch",
3128     "optimizer_switch=option=val[,option=val...], where option is one of "
3129     "{index_merge, index_merge_union, index_merge_sort_union, "
3130     "index_merge_intersection, engine_condition_pushdown, "
3131     "index_condition_pushdown, mrr, mrr_cost_based"
3132     ", materialization, semijoin, loosescan, firstmatch, duplicateweedout,"
3133     " subquery_materialization_cost_based, skip_scan,"
3134     " block_nested_loop, batched_key_access, use_index_extensions,"
3135     " condition_fanout_filter, derived_merge, hash_join,"
3136     " subquery_to_derived, prefer_ordering_index} and val is one of "
3137     "{on, off, default}",
3138     HINT_UPDATEABLE SESSION_VAR(optimizer_switch), CMD_LINE(REQUIRED_ARG),
3139     optimizer_switch_names, DEFAULT(OPTIMIZER_SWITCH_DEFAULT), NO_MUTEX_GUARD,
3140     NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(nullptr));
3141 
3142 static Sys_var_bool Sys_var_end_markers_in_json(
3143     "end_markers_in_json",
3144     "In JSON output (\"EXPLAIN FORMAT=JSON\" and optimizer trace), "
3145     "if variable is set to 1, repeats the structure's key (if it has one) "
3146     "near the closing bracket",
3147     HINT_UPDATEABLE SESSION_VAR(end_markers_in_json), CMD_LINE(OPT_ARG),
3148     DEFAULT(false));
3149 
3150 static Sys_var_flagset Sys_optimizer_trace(
3151     "optimizer_trace",
3152     "Controls tracing of the Optimizer:"
3153     " optimizer_trace=option=val[,option=val...], where option is one of"
3154     " {enabled, one_line}"
3155     " and val is one of {on, default}",
3156     SESSION_VAR(optimizer_trace), CMD_LINE(REQUIRED_ARG),
3157     Opt_trace_context::flag_names, DEFAULT(Opt_trace_context::FLAG_DEFAULT));
3158 // @see set_var::is_var_optimizer_trace()
3159 export sys_var *Sys_optimizer_trace_ptr = &Sys_optimizer_trace;
3160 
3161 /**
3162   Note how "misc" is not here: it is not accessible to the user; disabling
3163   "misc" would disable the top object, which would make an empty trace.
3164 */
3165 static Sys_var_flagset Sys_optimizer_trace_features(
3166     "optimizer_trace_features",
3167     "Enables/disables tracing of selected features of the Optimizer:"
3168     " optimizer_trace_features=option=val[,option=val...], where option is "
3169     "one "
3170     "of"
3171     " {greedy_search, range_optimizer, dynamic_range, repeated_subselect}"
3172     " and val is one of {on, off, default}",
3173     SESSION_VAR(optimizer_trace_features), CMD_LINE(REQUIRED_ARG),
3174     Opt_trace_context::feature_names,
3175     DEFAULT(Opt_trace_context::default_features));
3176 
3177 /** Delete all old optimizer traces */
optimizer_trace_update(sys_var *,THD * thd,enum_var_type)3178 static bool optimizer_trace_update(sys_var *, THD *thd, enum_var_type) {
3179   thd->opt_trace.reset();
3180   return false;
3181 }
3182 
3183 static Sys_var_long Sys_optimizer_trace_offset(
3184     "optimizer_trace_offset",
3185     "Offset of first optimizer trace to show; see manual",
3186     SESSION_VAR(optimizer_trace_offset), CMD_LINE(REQUIRED_ARG),
3187     VALID_RANGE(LONG_MIN, LONG_MAX), DEFAULT(-1), BLOCK_SIZE(1), NO_MUTEX_GUARD,
3188     NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(optimizer_trace_update));
3189 
3190 static Sys_var_long Sys_optimizer_trace_limit(
3191     "optimizer_trace_limit", "Maximum number of shown optimizer traces",
3192     SESSION_VAR(optimizer_trace_limit), CMD_LINE(REQUIRED_ARG),
3193     VALID_RANGE(0, LONG_MAX), DEFAULT(1), BLOCK_SIZE(1), NO_MUTEX_GUARD,
3194     NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(optimizer_trace_update));
3195 
3196 static Sys_var_ulong Sys_optimizer_trace_max_mem_size(
3197     "optimizer_trace_max_mem_size",
3198     "Maximum allowed cumulated size of stored optimizer traces",
3199     SESSION_VAR(optimizer_trace_max_mem_size), CMD_LINE(REQUIRED_ARG),
3200     VALID_RANGE(0, ULONG_MAX), DEFAULT(1024 * 1024), BLOCK_SIZE(1));
3201 
3202 static Sys_var_charptr Sys_pid_file(
3203     "pid_file", "Pid file used by safe_mysqld",
3204     READ_ONLY NON_PERSIST GLOBAL_VAR(pidfile_name_ptr), CMD_LINE(REQUIRED_ARG),
3205     IN_FS_CHARSET, DEFAULT(pidfile_name));
3206 
3207 static Sys_var_charptr Sys_plugin_dir(
3208     "plugin_dir", "Directory for plugins",
3209     READ_ONLY NON_PERSIST GLOBAL_VAR(opt_plugin_dir_ptr),
3210     CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET, DEFAULT(nullptr));
3211 
3212 static Sys_var_uint Sys_port(
3213     "port",
3214     "Port number to use for connection or 0 to default to, "
3215     "my.cnf, $MYSQL_TCP_PORT, "
3216 #if MYSQL_PORT_DEFAULT == 0
3217     "/etc/services, "
3218 #endif
3219     "built-in default (" STRINGIFY_ARG(MYSQL_PORT) "), whatever comes first",
3220     READ_ONLY NON_PERSIST GLOBAL_VAR(mysqld_port), CMD_LINE(REQUIRED_ARG, 'P'),
3221     VALID_RANGE(0, 65535), DEFAULT(0), BLOCK_SIZE(1));
3222 
3223 static Sys_var_ulong Sys_preload_buff_size(
3224     "preload_buffer_size",
3225     "The size of the buffer that is allocated when preloading indexes",
3226     SESSION_VAR(preload_buff_size), CMD_LINE(REQUIRED_ARG),
3227     VALID_RANGE(1024, 1024 * 1024 * 1024), DEFAULT(32768), BLOCK_SIZE(1));
3228 
3229 static Sys_var_uint Sys_protocol_version(
3230     "protocol_version",
3231     "The version of the client/server protocol used by the MySQL server",
3232     READ_ONLY NON_PERSIST GLOBAL_VAR(protocol_version), NO_CMD_LINE,
3233     VALID_RANGE(0, ~0), DEFAULT(PROTOCOL_VERSION), BLOCK_SIZE(1));
3234 
3235 static Sys_var_proxy_user Sys_proxy_user(
3236     "proxy_user", "The proxy user account name used when logging in",
3237     IN_SYSTEM_CHARSET);
3238 
3239 static Sys_var_external_user Sys_external_user(
3240     "external_user", "The external user account used when logging in",
3241     IN_SYSTEM_CHARSET);
3242 
3243 static Sys_var_ulong Sys_read_buff_size(
3244     "read_buffer_size",
3245     "Each thread that does a sequential scan allocates a buffer of "
3246     "this size for each table it scans. If you do many sequential scans, "
3247     "you may want to increase this value",
3248     HINT_UPDATEABLE SESSION_VAR(read_buff_size), CMD_LINE(REQUIRED_ARG),
3249     VALID_RANGE(IO_SIZE * 2, INT_MAX32), DEFAULT(128 * 1024),
3250     BLOCK_SIZE(IO_SIZE));
3251 
check_read_only(sys_var *,THD * thd,set_var *)3252 static bool check_read_only(sys_var *, THD *thd, set_var *) {
3253   /* Prevent self dead-lock */
3254   if (thd->locked_tables_mode || thd->in_active_multi_stmt_transaction()) {
3255     my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
3256     return true;
3257   }
3258   return false;
3259 }
3260 
check_require_secure_transport(sys_var *,THD *,set_var * var MY_ATTRIBUTE ((unused)))3261 static bool check_require_secure_transport(
3262     sys_var *, THD *, set_var *var MY_ATTRIBUTE((unused))) {
3263 #if !defined(_WIN32)
3264   /*
3265     always allow require_secure_transport to be enabled on
3266     Linux, as socket is secure.
3267   */
3268   return false;
3269 #else
3270   /*
3271     check whether SSL or shared memory transports are enabled before
3272     turning require_secure_transport ON, otherwise no connections will
3273     be allowed on Windows.
3274   */
3275 
3276   if (!var->save_result.ulonglong_value) return false;
3277   if (have_ssl() || opt_enable_shared_memory) return false;
3278   /* reject if SSL and shared memory are both disabled: */
3279   my_error(ER_NO_SECURE_TRANSPORTS_CONFIGURED, MYF(0));
3280   return true;
3281 
3282 #endif
3283 }
3284 
fix_read_only(sys_var * self,THD * thd,enum_var_type)3285 static bool fix_read_only(sys_var *self, THD *thd, enum_var_type) {
3286   bool result = true;
3287   bool new_read_only = read_only;  // make a copy before releasing a mutex
3288   DBUG_TRACE;
3289 
3290   if (read_only == false || read_only == opt_readonly) {
3291     if (opt_super_readonly && !read_only) {
3292       opt_super_readonly = false;
3293       super_read_only = false;
3294     }
3295     opt_readonly = read_only;
3296     return false;
3297   }
3298 
3299   if (check_read_only(self, thd, nullptr))  // just in case
3300     goto end;
3301 
3302   if (thd->global_read_lock.is_acquired()) {
3303     /*
3304       This connection already holds the global read lock.
3305       This can be the case with:
3306       - FLUSH TABLES WITH READ LOCK
3307       - SET GLOBAL READ_ONLY = 1
3308     */
3309     if (opt_super_readonly && !read_only) {
3310       opt_super_readonly = false;
3311       super_read_only = false;
3312     }
3313     opt_readonly = read_only;
3314     return false;
3315   }
3316 
3317   /*
3318     READ_ONLY=1 prevents write locks from being taken on tables and
3319     blocks transactions from committing. We therefore should make sure
3320     that no such events occur while setting the read_only variable.
3321     This is a 2 step process:
3322     [1] lock_global_read_lock()
3323       Prevents connections from obtaining new write locks on
3324       tables. Note that we can still have active rw transactions.
3325     [2] make_global_read_lock_block_commit()
3326       Prevents transactions from committing.
3327   */
3328 
3329   read_only = opt_readonly;
3330   mysql_mutex_unlock(&LOCK_global_system_variables);
3331 
3332   if (thd->global_read_lock.lock_global_read_lock(thd))
3333     goto end_with_mutex_unlock;
3334 
3335   if ((result = thd->global_read_lock.make_global_read_lock_block_commit(thd)))
3336     goto end_with_read_lock;
3337 
3338   /* Change the opt_readonly system variable, safe because the lock is held */
3339   opt_readonly = new_read_only;
3340 
3341   result = false;
3342 
3343 end_with_read_lock:
3344   /* Release the lock */
3345   thd->global_read_lock.unlock_global_read_lock(thd);
3346 end_with_mutex_unlock:
3347   mysql_mutex_lock(&LOCK_global_system_variables);
3348 end:
3349   read_only = opt_readonly;
3350   return result;
3351 }
3352 
fix_super_read_only(sys_var *,THD * thd,enum_var_type type)3353 static bool fix_super_read_only(sys_var *, THD *thd, enum_var_type type) {
3354   DBUG_TRACE;
3355 
3356   /* return if no changes: */
3357   if (super_read_only == opt_super_readonly) return false;
3358 
3359   /* return immediately if turning super_read_only OFF: */
3360   if (super_read_only == false) {
3361     opt_super_readonly = false;
3362     return false;
3363   }
3364   bool result = true;
3365   bool new_super_read_only =
3366       super_read_only; /* make a copy before releasing a mutex */
3367 
3368   /* set read_only to ON if it is OFF, letting fix_read_only()
3369      handle its own locking needs
3370   */
3371   if (!opt_readonly) {
3372     read_only = true;
3373     if ((result = fix_read_only(nullptr, thd, type))) goto end;
3374   }
3375 
3376   /* if we already have global read lock, set super_read_only
3377      and return immediately:
3378   */
3379   if (thd->global_read_lock.is_acquired()) {
3380     opt_super_readonly = super_read_only;
3381     return false;
3382   }
3383 
3384   /* now we're turning ON super_read_only: */
3385   super_read_only = opt_super_readonly;
3386   mysql_mutex_unlock(&LOCK_global_system_variables);
3387 
3388   if (thd->global_read_lock.lock_global_read_lock(thd))
3389     goto end_with_mutex_unlock;
3390 
3391   if ((result = thd->global_read_lock.make_global_read_lock_block_commit(thd)))
3392     goto end_with_read_lock;
3393   opt_super_readonly = new_super_read_only;
3394   result = false;
3395 
3396 end_with_read_lock:
3397   /* Release the lock */
3398   thd->global_read_lock.unlock_global_read_lock(thd);
3399 end_with_mutex_unlock:
3400   mysql_mutex_lock(&LOCK_global_system_variables);
3401 end:
3402   super_read_only = opt_super_readonly;
3403   return result;
3404 }
3405 
3406 static Sys_var_bool Sys_require_secure_transport(
3407     "require_secure_transport",
3408     "When this option is enabled, connections attempted using insecure "
3409     "transport will be rejected.  Secure transports are SSL/TLS, "
3410     "Unix socket or Shared Memory (on Windows).",
3411     GLOBAL_VAR(opt_require_secure_transport), CMD_LINE(OPT_ARG), DEFAULT(false),
3412     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_require_secure_transport),
3413     ON_UPDATE(nullptr));
3414 
3415 /**
3416   The read_only boolean is always equal to the opt_readonly boolean except
3417   during fix_read_only(); when that function is entered, opt_readonly is
3418   the pre-update value and read_only is the post-update value.
3419   fix_read_only() compares them and runs needed operations for the
3420   transition (especially when transitioning from false to true) and
3421   synchronizes both booleans in the end.
3422 */
3423 static Sys_var_bool Sys_readonly(
3424     "read_only",
3425     "Make all non-temporary tables read-only, with the exception for "
3426     "replication (slave) threads and users with the SUPER privilege",
3427     GLOBAL_VAR(read_only), CMD_LINE(OPT_ARG), DEFAULT(false), NO_MUTEX_GUARD,
3428     NOT_IN_BINLOG, ON_CHECK(check_read_only), ON_UPDATE(fix_read_only));
3429 
3430 /**
3431 Setting super_read_only to ON triggers read_only to also be set to ON.
3432 */
3433 static Sys_var_bool Sys_super_readonly(
3434     "super_read_only",
3435     "Make all non-temporary tables read-only, with the exception for "
3436     "replication (slave) threads.  Users with the SUPER privilege are "
3437     "affected, unlike read_only.  Setting super_read_only to ON "
3438     "also sets read_only to ON.",
3439     GLOBAL_VAR(super_read_only), CMD_LINE(OPT_ARG), DEFAULT(false),
3440     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
3441     ON_UPDATE(fix_super_read_only));
3442 
3443 // Small lower limit to be able to test MRR
3444 static Sys_var_ulong Sys_read_rnd_buff_size(
3445     "read_rnd_buffer_size",
3446     "When reading rows in sorted order after a sort, the rows are read "
3447     "through this buffer to avoid a disk seeks",
3448     HINT_UPDATEABLE SESSION_VAR(read_rnd_buff_size), CMD_LINE(REQUIRED_ARG),
3449     VALID_RANGE(1, INT_MAX32), DEFAULT(256 * 1024), BLOCK_SIZE(1));
3450 
3451 static Sys_var_ulong Sys_div_precincrement(
3452     "div_precision_increment",
3453     "Precision of the result of '/' "
3454     "operator will be increased on that value",
3455     HINT_UPDATEABLE SESSION_VAR(div_precincrement), CMD_LINE(REQUIRED_ARG),
3456     VALID_RANGE(0, DECIMAL_MAX_SCALE), DEFAULT(4), BLOCK_SIZE(1));
3457 
3458 static Sys_var_uint Sys_eq_range_index_dive_limit(
3459     "eq_range_index_dive_limit",
3460     "The optimizer will use existing index statistics instead of "
3461     "doing index dives for equality ranges if the number of equality "
3462     "ranges for the index is larger than or equal to this number. "
3463     "If set to 0, index dives are always used.",
3464     HINT_UPDATEABLE SESSION_VAR(eq_range_index_dive_limit),
3465     CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, UINT_MAX32), DEFAULT(200),
3466     BLOCK_SIZE(1));
3467 
3468 static Sys_var_ulong Sys_range_alloc_block_size(
3469     "range_alloc_block_size",
3470     "Allocation block size for storing ranges during optimization",
3471     HINT_UPDATEABLE SESSION_VAR(range_alloc_block_size), CMD_LINE(REQUIRED_ARG),
3472     VALID_RANGE(RANGE_ALLOC_BLOCK_SIZE, UINT32_MAX),
3473     DEFAULT(RANGE_ALLOC_BLOCK_SIZE), BLOCK_SIZE(1024));
3474 
fix_thd_mem_root(sys_var * self,THD * thd,enum_var_type type)3475 static bool fix_thd_mem_root(sys_var *self, THD *thd, enum_var_type type) {
3476   if (!self->is_global_persist(type))
3477     thd->mem_root->set_block_size(thd->variables.query_alloc_block_size);
3478   return false;
3479 }
3480 static Sys_var_ulong Sys_query_alloc_block_size(
3481     "query_alloc_block_size",
3482     "Allocation block size for query parsing and execution",
3483     SESSION_VAR(query_alloc_block_size), CMD_LINE(REQUIRED_ARG),
3484     VALID_RANGE(1024, UINT_MAX32), DEFAULT(QUERY_ALLOC_BLOCK_SIZE),
3485     BLOCK_SIZE(1024), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
3486     ON_UPDATE(fix_thd_mem_root));
3487 
3488 static Sys_var_ulong Sys_query_prealloc_size(
3489     "query_prealloc_size", "Persistent buffer for query parsing and execution",
3490     SESSION_VAR(query_prealloc_size), CMD_LINE(REQUIRED_ARG),
3491     VALID_RANGE(QUERY_ALLOC_PREALLOC_SIZE, ULONG_MAX),
3492     DEFAULT(QUERY_ALLOC_PREALLOC_SIZE), BLOCK_SIZE(1024), NO_MUTEX_GUARD,
3493     NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(fix_thd_mem_root));
3494 
3495 #if defined(_WIN32)
3496 static Sys_var_bool Sys_shared_memory(
3497     "shared_memory", "Enable the shared memory",
3498     READ_ONLY NON_PERSIST GLOBAL_VAR(opt_enable_shared_memory),
3499     CMD_LINE(OPT_ARG), DEFAULT(false));
3500 
3501 static Sys_var_charptr Sys_shared_memory_base_name(
3502     "shared_memory_base_name", "Base name of shared memory",
3503     READ_ONLY NON_PERSIST GLOBAL_VAR(shared_memory_base_name),
3504     CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET, DEFAULT(0));
3505 #endif
3506 
3507 // this has to be NO_CMD_LINE as the command-line option has a different name
3508 static Sys_var_bool Sys_skip_external_locking(
3509     "skip_external_locking", "Don't use system (external) locking",
3510     READ_ONLY NON_PERSIST GLOBAL_VAR(my_disable_locking), NO_CMD_LINE,
3511     DEFAULT(true));
3512 
3513 static Sys_var_bool Sys_skip_networking(
3514     "skip_networking", "Don't allow connection with TCP/IP",
3515     READ_ONLY NON_PERSIST GLOBAL_VAR(opt_disable_networking), CMD_LINE(OPT_ARG),
3516     DEFAULT(false));
3517 
3518 static Sys_var_bool Sys_skip_name_resolve(
3519     "skip_name_resolve",
3520     "Don't resolve hostnames. All hostnames are IP's or 'localhost'.",
3521     READ_ONLY GLOBAL_VAR(opt_skip_name_resolve),
3522     CMD_LINE(OPT_ARG, OPT_SKIP_RESOLVE), DEFAULT(false));
3523 
3524 static Sys_var_bool Sys_skip_show_database(
3525     "skip_show_database", "Don't allow 'SHOW DATABASE' commands",
3526     READ_ONLY GLOBAL_VAR(opt_skip_show_db), CMD_LINE(OPT_ARG), DEFAULT(false));
3527 
3528 static Sys_var_charptr Sys_socket(
3529     "socket", "Socket file to use for connection",
3530     READ_ONLY NON_PERSIST GLOBAL_VAR(mysqld_unix_port), CMD_LINE(REQUIRED_ARG),
3531     IN_FS_CHARSET, DEFAULT(nullptr));
3532 
3533 static Sys_var_ulong Sys_thread_stack(
3534     "thread_stack", "The stack size for each thread",
3535     READ_ONLY GLOBAL_VAR(my_thread_stack_size), CMD_LINE(REQUIRED_ARG),
3536 #if defined(__clang__) && defined(HAVE_UBSAN)
3537     // DEFAULT_THREAD_STACK is multiplied by 3 for clang/UBSAN
3538     // We need to increase the minimum value as well.
3539     VALID_RANGE(DEFAULT_THREAD_STACK / 2, ULONG_MAX),
3540 #else
3541     VALID_RANGE(128 * 1024, ULONG_MAX),
3542 #endif
3543     DEFAULT(DEFAULT_THREAD_STACK), BLOCK_SIZE(1024));
3544 
3545 static Sys_var_charptr Sys_tmpdir(
3546     "tmpdir",
3547     "Path for temporary files. Several paths may "
3548     "be specified, separated by a "
3549 #if defined(_WIN32)
3550     "semicolon (;)"
3551 #else
3552     "colon (:)"
3553 #endif
3554     ", in this case they are used in a round-robin fashion",
3555     READ_ONLY NON_PERSIST GLOBAL_VAR(opt_mysql_tmpdir),
3556     CMD_LINE(REQUIRED_ARG, 't'), IN_FS_CHARSET, DEFAULT(nullptr));
3557 
fix_trans_mem_root(sys_var * self,THD * thd,enum_var_type type)3558 static bool fix_trans_mem_root(sys_var *self, THD *thd, enum_var_type type) {
3559   if (!self->is_global_persist(type))
3560     thd->get_transaction()->init_mem_root_defaults(
3561         thd->variables.trans_alloc_block_size,
3562         thd->variables.trans_prealloc_size);
3563   return false;
3564 }
3565 static Sys_var_ulong Sys_trans_alloc_block_size(
3566     "transaction_alloc_block_size",
3567     "Allocation block size for transactions to be stored in binary log",
3568     SESSION_VAR(trans_alloc_block_size), CMD_LINE(REQUIRED_ARG),
3569     VALID_RANGE(1024, 128 * 1024), DEFAULT(QUERY_ALLOC_BLOCK_SIZE),
3570     BLOCK_SIZE(1024), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
3571     ON_UPDATE(fix_trans_mem_root));
3572 
3573 static Sys_var_ulong Sys_trans_prealloc_size(
3574     "transaction_prealloc_size",
3575     "Persistent buffer for transactions to be stored in binary log",
3576     SESSION_VAR(trans_prealloc_size), CMD_LINE(REQUIRED_ARG),
3577     VALID_RANGE(1024, 128 * 1024), DEFAULT(TRANS_ALLOC_PREALLOC_SIZE),
3578     BLOCK_SIZE(1024), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
3579     ON_UPDATE(fix_trans_mem_root));
3580 
3581 static const char *thread_handling_names[] = {
3582     "one-thread-per-connection", "no-threads", "loaded-dynamically", nullptr};
3583 static Sys_var_enum Sys_thread_handling(
3584     "thread_handling",
3585     "Define threads usage for handling queries, one of "
3586     "one-thread-per-connection, no-threads, loaded-dynamically",
3587     READ_ONLY GLOBAL_VAR(Connection_handler_manager::thread_handling),
3588     CMD_LINE(REQUIRED_ARG), thread_handling_names, DEFAULT(0));
3589 
3590 static Sys_var_charptr Sys_secure_file_priv(
3591     "secure_file_priv",
3592     "Limit LOAD DATA, SELECT ... OUTFILE, and LOAD_FILE() to files "
3593     "within specified directory",
3594     READ_ONLY NON_PERSIST GLOBAL_VAR(opt_secure_file_priv),
3595     CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET,
3596     DEFAULT(DEFAULT_SECURE_FILE_PRIV_DIR));
3597 
fix_server_id(sys_var *,THD * thd,enum_var_type)3598 static bool fix_server_id(sys_var *, THD *thd, enum_var_type) {
3599   // server_id is 'MYSQL_PLUGIN_IMPORT ulong'
3600   // So we cast here, rather than change its type.
3601   server_id_supplied = true;
3602   thd->server_id = static_cast<uint32>(server_id);
3603   return false;
3604 }
3605 static Sys_var_ulong Sys_server_id(
3606     "server_id",
3607     "Uniquely identifies the server instance in the community of "
3608     "replication partners",
3609     GLOBAL_VAR(server_id), CMD_LINE(REQUIRED_ARG, OPT_SERVER_ID),
3610     VALID_RANGE(0, UINT_MAX32), DEFAULT(1), BLOCK_SIZE(1), NO_MUTEX_GUARD,
3611     NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(fix_server_id));
3612 
3613 static Sys_var_charptr Sys_server_uuid(
3614     "server_uuid", "Uniquely identifies the server instance in the universe",
3615     READ_ONLY NON_PERSIST GLOBAL_VAR(server_uuid_ptr), NO_CMD_LINE,
3616     IN_FS_CHARSET, DEFAULT(server_uuid));
3617 
3618 static Sys_var_uint Sys_server_id_bits(
3619     "server_id_bits", "Set number of significant bits in server-id",
3620     GLOBAL_VAR(opt_server_id_bits), CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 32),
3621     DEFAULT(32), BLOCK_SIZE(1));
3622 
3623 static Sys_var_int32 Sys_regexp_time_limit(
3624     "regexp_time_limit",
3625     "Timeout for regular expressions matches, in steps of the match "
3626     "engine, typically on the order of milliseconds.",
3627     GLOBAL_VAR(opt_regexp_time_limit), CMD_LINE(REQUIRED_ARG),
3628     VALID_RANGE(0, INT32_MAX), DEFAULT(32), BLOCK_SIZE(1));
3629 
3630 static Sys_var_int32 Sys_regexp_stack_limit(
3631     "regexp_stack_limit", "Stack size limit for regular expressions matches",
3632     GLOBAL_VAR(opt_regexp_stack_limit), CMD_LINE(REQUIRED_ARG),
3633     VALID_RANGE(0, INT32_MAX), DEFAULT(8000000), BLOCK_SIZE(1));
3634 
3635 static Sys_var_bool Sys_slave_compressed_protocol(
3636     "slave_compressed_protocol", "Use compression on master/slave protocol",
3637     GLOBAL_VAR(opt_slave_compressed_protocol), CMD_LINE(OPT_ARG),
3638     DEFAULT(false));
3639 
3640 static const char *slave_exec_mode_names[] = {"STRICT", "IDEMPOTENT", nullptr};
3641 static Sys_var_enum Slave_exec_mode(
3642     "slave_exec_mode",
3643     "Modes for how replication events should be executed. Legal values "
3644     "are STRICT (default) and IDEMPOTENT. In IDEMPOTENT mode, "
3645     "replication will not stop for operations that are idempotent. "
3646     "In STRICT mode, replication will stop on any unexpected difference "
3647     "between the master and the slave",
3648     GLOBAL_VAR(slave_exec_mode_options), CMD_LINE(REQUIRED_ARG),
3649     slave_exec_mode_names, DEFAULT(RBR_EXEC_MODE_STRICT));
3650 
3651 const char *slave_type_conversions_name[] = {
3652     "ALL_LOSSY", "ALL_NON_LOSSY", "ALL_UNSIGNED", "ALL_SIGNED", nullptr};
3653 static Sys_var_set Slave_type_conversions(
3654     "slave_type_conversions",
3655     "Set of slave type conversions that are enabled. Legal values are:"
3656     " ALL_LOSSY to enable lossy conversions,"
3657     " ALL_NON_LOSSY to enable non-lossy conversions,"
3658     " ALL_UNSIGNED to treat all integer column type data to be unsigned "
3659     "values, and"
3660     " ALL_SIGNED to treat all integer column type data to be signed values."
3661     " Default treatment is ALL_SIGNED. If ALL_SIGNED and ALL_UNSIGNED both "
3662     "are"
3663     " specified, ALL_SIGNED will take higher priority than ALL_UNSIGNED."
3664     " If the variable is assigned the empty set, no conversions are"
3665     " allowed and it is expected that the types match exactly.",
3666     GLOBAL_VAR(slave_type_conversions_options), CMD_LINE(REQUIRED_ARG),
3667     slave_type_conversions_name, DEFAULT(0));
3668 
3669 static Sys_var_bool Sys_slave_sql_verify_checksum(
3670     "slave_sql_verify_checksum",
3671     "Force checksum verification of replication events after reading them "
3672     "from relay log. Note: Events are always checksum-verified by slave on "
3673     "receiving them from the network before writing them to the relay "
3674     "log. Enabled by default.",
3675     GLOBAL_VAR(opt_slave_sql_verify_checksum), CMD_LINE(OPT_ARG),
3676     DEFAULT(true));
3677 
check_not_null_not_empty(sys_var * self,THD * thd,set_var * var)3678 static bool check_not_null_not_empty(sys_var *self, THD *thd, set_var *var) {
3679   String str, *res;
3680   /* null value is not allowed */
3681   if (check_not_null(self, thd, var)) return true;
3682 
3683   /** empty value ('') is not allowed */
3684   res = var->value ? var->value->val_str(&str) : nullptr;
3685   if (res && res->is_empty()) return true;
3686 
3687   return false;
3688 }
3689 
check_slave_stopped(sys_var * self,THD * thd,set_var * var)3690 static bool check_slave_stopped(sys_var *self, THD *thd, set_var *var) {
3691   bool result = false;
3692   Master_info *mi = nullptr;
3693 
3694   if (check_not_null_not_empty(self, thd, var)) return true;
3695 
3696   channel_map.wrlock();
3697 
3698   for (mi_map::iterator it = channel_map.begin(); it != channel_map.end();
3699        it++) {
3700     mi = it->second;
3701     if (mi) {
3702       mysql_mutex_lock(&mi->rli->run_lock);
3703       if (mi->rli->slave_running) {
3704         my_error(ER_SLAVE_SQL_THREAD_MUST_STOP, MYF(0));
3705         result = true;
3706       }
3707       mysql_mutex_unlock(&mi->rli->run_lock);
3708     }
3709   }
3710   channel_map.unlock();
3711   return result;
3712 }
3713 
3714 static const char *slave_rows_search_algorithms_names[] = {
3715     "TABLE_SCAN", "INDEX_SCAN", "HASH_SCAN", nullptr};
3716 static Sys_var_set Slave_rows_search_algorithms(
3717     "slave_rows_search_algorithms",
3718     "Set of searching algorithms that the slave will use while "
3719     "searching for records from the storage engine to either "
3720     "updated or deleted them. Possible values are: INDEX_SCAN, "
3721     "TABLE_SCAN and HASH_SCAN. Any combination is allowed, and "
3722     "the slave will always pick the most suitable algorithm for "
3723     "any given scenario. "
3724     "(Default: INDEX_SCAN, HASH_SCAN).",
3725     GLOBAL_VAR(slave_rows_search_algorithms_options),
3726     CMD_LINE(REQUIRED_ARG, OPT_SLAVE_ROWS_SEARCH_ALGORITHMS),
3727     slave_rows_search_algorithms_names,
3728     DEFAULT(SLAVE_ROWS_INDEX_SCAN | SLAVE_ROWS_HASH_SCAN), NO_MUTEX_GUARD,
3729     NOT_IN_BINLOG, ON_CHECK(check_not_null_not_empty), ON_UPDATE(nullptr),
3730     DEPRECATED_VAR(""));
3731 
3732 static const char *mts_parallel_type_names[] = {"DATABASE", "LOGICAL_CLOCK",
3733                                                 nullptr};
3734 static Sys_var_enum Mts_parallel_type(
3735     "slave_parallel_type",
3736     "Specifies if the slave will use database partitioning "
3737     "or information from master to parallelize transactions."
3738     "(Default: DATABASE).",
3739     PERSIST_AS_READONLY GLOBAL_VAR(mts_parallel_option), CMD_LINE(REQUIRED_ARG),
3740     mts_parallel_type_names, DEFAULT(MTS_PARALLEL_TYPE_DB_NAME), NO_MUTEX_GUARD,
3741     NOT_IN_BINLOG, ON_CHECK(check_slave_stopped), ON_UPDATE(nullptr));
3742 
check_binlog_transaction_dependency_tracking(sys_var *,THD *,set_var * var)3743 static bool check_binlog_transaction_dependency_tracking(sys_var *, THD *,
3744                                                          set_var *var) {
3745   if (global_system_variables.transaction_write_set_extraction ==
3746           HASH_ALGORITHM_OFF &&
3747       var->save_result.ulonglong_value != DEPENDENCY_TRACKING_COMMIT_ORDER) {
3748     my_error(ER_WRONG_USAGE, MYF(0),
3749              "binlog_transaction_dependency_tracking (!= COMMIT_ORDER)",
3750              "transaction_write_set_extraction (= OFF)");
3751 
3752     return true;
3753   }
3754   return false;
3755 }
3756 
update_binlog_transaction_dependency_tracking(sys_var *,THD *,enum_var_type)3757 static bool update_binlog_transaction_dependency_tracking(sys_var *, THD *,
3758                                                           enum_var_type) {
3759   /*
3760     m_opt_tracking_mode is read and written in an atomic way based
3761     on the value of m_opt_tracking_mode_value that is associated
3762     with the sys_var variable.
3763   */
3764   set_mysqld_opt_tracking_mode();
3765 
3766   /*
3767     the writeset_history_start needs to be set to 0 whenever there is a
3768     change in the transaction dependency source so that WS and COMMIT
3769     transition smoothly.
3770   */
3771   mysql_bin_log.m_dependency_tracker.tracking_mode_changed();
3772   return false;
3773 }
3774 
3775 static PolyLock_mutex PLock_slave_trans_dep_tracker(
3776     &LOCK_slave_trans_dep_tracker);
3777 static const char *opt_binlog_transaction_dependency_tracking_names[] = {
3778     "COMMIT_ORDER", "WRITESET", "WRITESET_SESSION", NullS};
3779 static Sys_var_enum Binlog_transaction_dependency_tracking(
3780     "binlog_transaction_dependency_tracking",
3781     "Selects the source of dependency information from which to "
3782     "assess which transactions can be executed in parallel by the "
3783     "slave's multi-threaded applier. "
3784     "Possible values are COMMIT_ORDER, WRITESET and WRITESET_SESSION.",
3785     GLOBAL_VAR(mysql_bin_log.m_dependency_tracker.m_opt_tracking_mode_value),
3786     CMD_LINE(REQUIRED_ARG), opt_binlog_transaction_dependency_tracking_names,
3787     DEFAULT(DEPENDENCY_TRACKING_COMMIT_ORDER), &PLock_slave_trans_dep_tracker,
3788     NOT_IN_BINLOG, ON_CHECK(check_binlog_transaction_dependency_tracking),
3789     ON_UPDATE(update_binlog_transaction_dependency_tracking));
3790 static Sys_var_ulong Binlog_transaction_dependency_history_size(
3791     "binlog_transaction_dependency_history_size",
3792     "Maximum number of rows to keep in the writeset history.",
3793     GLOBAL_VAR(mysql_bin_log.m_dependency_tracker.get_writeset()
3794                    ->m_opt_max_history_size),
3795     CMD_LINE(REQUIRED_ARG, 0), VALID_RANGE(1, 1000000), DEFAULT(25000),
3796     BLOCK_SIZE(1), &PLock_slave_trans_dep_tracker, NOT_IN_BINLOG,
3797     ON_CHECK(nullptr), ON_UPDATE(nullptr));
3798 
3799 static Sys_var_bool Sys_slave_preserve_commit_order(
3800     "slave_preserve_commit_order",
3801     "Force slave workers to make commits in the same order as on the master. "
3802     "Disabled by default.",
3803     PERSIST_AS_READONLY GLOBAL_VAR(opt_slave_preserve_commit_order),
3804     CMD_LINE(OPT_ARG, OPT_SLAVE_PRESERVE_COMMIT_ORDER), DEFAULT(false),
3805     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_slave_stopped),
3806     ON_UPDATE(nullptr));
3807 
global_update(THD *,set_var * var)3808 bool Sys_var_charptr::global_update(THD *, set_var *var) {
3809   char *new_val, *ptr = var->save_result.string_value.str;
3810   size_t len = var->save_result.string_value.length;
3811   if (ptr) {
3812     new_val = (char *)my_memdup(key_memory_Sys_var_charptr_value, ptr, len + 1,
3813                                 MYF(MY_WME));
3814     if (!new_val) return true;
3815     new_val[len] = 0;
3816   } else
3817     new_val = nullptr;
3818   if (flags & ALLOCATED) my_free(global_var(char *));
3819   flags |= ALLOCATED;
3820   global_var(char *) = new_val;
3821   return false;
3822 }
3823 
global_update(THD * thd,set_var * var)3824 bool Sys_var_enum_binlog_checksum::global_update(THD *thd, set_var *var) {
3825   bool check_purge = false;
3826 
3827   /*
3828     SET binlog_checksome command should ignore 'read-only' and
3829     'super_read_only' options so that it can update 'mysql.gtid_executed'
3830     replication repository table.
3831   */
3832   thd->set_skip_readonly_check();
3833   mysql_mutex_lock(mysql_bin_log.get_log_lock());
3834   if (mysql_bin_log.is_open()) {
3835     bool alg_changed =
3836         (binlog_checksum_options != (uint)var->save_result.ulonglong_value);
3837     if (alg_changed)
3838       mysql_bin_log.checksum_alg_reset =
3839           (uint8)var->save_result.ulonglong_value;
3840     mysql_bin_log.rotate(true, &check_purge);
3841     if (alg_changed)
3842       mysql_bin_log.checksum_alg_reset =
3843           binary_log::BINLOG_CHECKSUM_ALG_UNDEF;  // done
3844   } else {
3845     binlog_checksum_options =
3846         static_cast<ulong>(var->save_result.ulonglong_value);
3847   }
3848   DBUG_ASSERT(binlog_checksum_options == var->save_result.ulonglong_value);
3849   DBUG_ASSERT(mysql_bin_log.checksum_alg_reset ==
3850               binary_log::BINLOG_CHECKSUM_ALG_UNDEF);
3851   mysql_mutex_unlock(mysql_bin_log.get_log_lock());
3852 
3853   if (check_purge) mysql_bin_log.purge();
3854 
3855   return false;
3856 }
3857 
session_update(THD * thd,set_var * var)3858 bool Sys_var_gtid_next::session_update(THD *thd, set_var *var) {
3859   DBUG_TRACE;
3860   char buf[Gtid::MAX_TEXT_LENGTH + 1];
3861   // Get the value
3862   String str(buf, sizeof(buf), &my_charset_latin1);
3863   char *res = nullptr;
3864   if (!var->value) {
3865     // set session gtid_next= default
3866     DBUG_ASSERT(var->save_result.string_value.str);
3867     DBUG_ASSERT(var->save_result.string_value.length);
3868     res = var->save_result.string_value.str;
3869   } else if (var->value->val_str(&str))
3870     res = var->value->val_str(&str)->c_ptr_safe();
3871   if (!res) {
3872     my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, "NULL");
3873     return true;
3874   }
3875   global_sid_lock->rdlock();
3876   Gtid_specification spec;
3877   if (spec.parse(global_sid_map, res) != RETURN_STATUS_OK) {
3878     global_sid_lock->unlock();
3879     return true;
3880   }
3881 
3882   bool ret = set_gtid_next(thd, spec);
3883   // set_gtid_next releases global_sid_lock
3884   return ret;
3885 }
3886 
3887 #ifdef HAVE_GTID_NEXT_LIST
session_update(THD * thd,set_var * var)3888 bool Sys_var_gtid_set::session_update(THD *thd, set_var *var) {
3889   DBUG_TRACE;
3890   Gtid_set_or_null *gsn = (Gtid_set_or_null *)session_var_ptr(thd);
3891   char *value = var->save_result.string_value.str;
3892   if (value == NULL)
3893     gsn->set_null();
3894   else {
3895     Gtid_set *gs = gsn->set_non_null(global_sid_map);
3896     if (gs == NULL) {
3897       my_error(ER_OUT_OF_RESOURCES, MYF(0));  // allocation failed
3898       return true;
3899     }
3900     /*
3901       If string begins with '+', add to the existing set, otherwise
3902       replace existing set.
3903     */
3904     while (isspace(*value)) value++;
3905     if (*value == '+')
3906       value++;
3907     else
3908       gs->clear();
3909     // Add specified set of groups to Gtid_set.
3910     global_sid_lock->rdlock();
3911     enum_return_status ret = gs->add_gtid_text(value);
3912     global_sid_lock->unlock();
3913     if (ret != RETURN_STATUS_OK) {
3914       gsn->set_null();
3915       return true;
3916     }
3917   }
3918   return false;
3919 }
3920 #endif  // HAVE_GTID_NEXT_LIST
3921 
3922 /**
3923   This function shall issue a deprecation warning
3924   if the new gtid mode is set to GTID_MODE_ON and
3925   there is at least one replication channel with
3926   IGNORE_SERVER_IDS configured (i.e., not empty).
3927 
3928   The caller must have acquired a lock on the
3929   channel_map object before calling this function.
3930 
3931   The warning emitted is: ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT .
3932 
3933   @param thd The current session thread context.
3934   @param oldmode The old value of @@global.gtid_mode.
3935   @param newmode The new value for @@global.gtid_mode.
3936 
3937 */
issue_deprecation_warnings_gtid_mode(THD * thd,Gtid_mode::value_type oldmode MY_ATTRIBUTE ((unused)),Gtid_mode::value_type newmode)3938 static void issue_deprecation_warnings_gtid_mode(
3939     THD *thd, Gtid_mode::value_type oldmode MY_ATTRIBUTE((unused)),
3940     Gtid_mode::value_type newmode) {
3941   channel_map.assert_some_lock();
3942 
3943   /*
3944     Check that if changing to gtid_mode=on no channel is configured
3945     to ignore server ids. If it is, issue a deprecation warning.
3946   */
3947   if (newmode == Gtid_mode::ON) {
3948     for (mi_map::iterator it = channel_map.begin(); it != channel_map.end();
3949          it++) {
3950       Master_info *mi = it->second;
3951       if (mi != nullptr && mi->is_ignore_server_ids_configured()) {
3952         push_warning_printf(
3953             thd, Sql_condition::SL_WARNING, ER_WARN_DEPRECATED_SYNTAX,
3954             ER_THD(thd, ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT),
3955             "CHANGE MASTER TO ... IGNORE_SERVER_IDS='...' "
3956             "(when @@GLOBAL.GTID_MODE = ON)");
3957 
3958         break;  // Only push one warning
3959       }
3960     }
3961   }
3962 }
3963 
3964 /**
3965   This function shall be called whenever the global scope
3966   of gtid_mode var is updated.
3967 
3968   It checks some preconditions and also emits deprecation
3969   warnings conditionally when changing the value.
3970 
3971   Deprecation warnings are emitted after error conditions
3972   have been checked and only if there is no error raised.
3973 */
global_update(THD * thd,set_var * var)3974 bool Sys_var_gtid_mode::global_update(THD *thd, set_var *var) {
3975   DBUG_TRACE;
3976   bool ret = true;
3977 
3978   /*
3979     SET binlog_checksome command should ignore 'read-only' and
3980     'super_read_only' options so that it can update 'mysql.gtid_executed'
3981     replication repository table.
3982   */
3983   thd->set_skip_readonly_check();
3984   /*
3985     Hold lock_log so that:
3986     - other transactions are not flushed while gtid_mode is changed;
3987     - gtid_mode is not changed while some other thread is rotating
3988     the binlog.
3989 
3990     Hold channel_map lock so that:
3991     - gtid_mode is not changed during the execution of some
3992     replication command; particularly CHANGE MASTER. CHANGE MASTER
3993     checks if GTID_MODE is compatible with AUTO_POSITION, and
3994     later it actually updates the in-memory structure for
3995     AUTO_POSITION.  If gtid_mode was changed between these calls,
3996     auto_position could be set incompatible with gtid_mode.
3997 
3998     Hold global_sid_lock.wrlock so that:
3999     - other transactions cannot acquire ownership of any gtid.
4000 
4001     Hold Gtid_mode::lock so that all places that don't want to hold
4002     any of the other locks, but want to read gtid_mode, don't need
4003     to take the other locks.
4004   */
4005 
4006   auto new_gtid_mode =
4007       static_cast<Gtid_mode::value_type>(var->save_result.ulonglong_value);
4008 
4009   if (Gtid_mode::lock.trywrlock()) {
4010     my_error(ER_CANT_SET_GTID_MODE, MYF(0), Gtid_mode::to_string(new_gtid_mode),
4011              "there is a concurrent operation that disallows changes to "
4012              "@@GLOBAL.GTID_MODE");
4013     return ret;
4014   }
4015 
4016   channel_map.wrlock();
4017   mysql_mutex_lock(mysql_bin_log.get_log_lock());
4018   global_sid_lock->wrlock();
4019   int lock_count = 4;
4020 
4021   auto old_gtid_mode = global_gtid_mode.get();
4022   DBUG_ASSERT(new_gtid_mode <= Gtid_mode::ON);
4023 
4024   DBUG_PRINT("info", ("old_gtid_mode=%d new_gtid_mode=%d", old_gtid_mode,
4025                       new_gtid_mode));
4026 
4027   if (new_gtid_mode == old_gtid_mode) goto end;
4028 
4029   // Can only change one step at a time.
4030   /*
4031    Change gtid_mode value without checking for one step change during
4032    server startup.
4033   */
4034   if (mysqld_server_started &&
4035       abs((int)new_gtid_mode - (int)old_gtid_mode) > 1) {
4036     my_error(ER_GTID_MODE_CAN_ONLY_CHANGE_ONE_STEP_AT_A_TIME, MYF(0));
4037     goto err;
4038   }
4039 
4040   // Not allowed with slave_sql_skip_counter
4041   DBUG_PRINT("info", ("sql_slave_skip_counter=%d", sql_slave_skip_counter));
4042   if (new_gtid_mode == Gtid_mode::ON && sql_slave_skip_counter > 0) {
4043     my_error(ER_CANT_SET_GTID_MODE, MYF(0), "ON",
4044              "@@GLOBAL.SQL_SLAVE_SKIP_COUNTER is greater than zero");
4045     goto err;
4046   }
4047 
4048   if (new_gtid_mode != Gtid_mode::ON && replicate_same_server_id &&
4049       opt_log_slave_updates && opt_bin_log) {
4050     std::stringstream ss;
4051 
4052     ss << "replicate_same_server_id is set together with log_slave_updates"
4053        << " and log_bin. Thus, any anonymous transactions"
4054        << " would circulate infinitely in case this server is part of a"
4055        << " circular replication topology";
4056 
4057     my_error(ER_CANT_SET_GTID_MODE, MYF(0), Gtid_mode::to_string(new_gtid_mode),
4058              ss.str().c_str());
4059     goto err;
4060   }
4061 
4062   // Cannot set OFF when some channel uses AUTO_POSITION.
4063   if (new_gtid_mode == Gtid_mode::OFF) {
4064     for (mi_map::iterator it = channel_map.begin(); it != channel_map.end();
4065          it++) {
4066       Master_info *mi = it->second;
4067       DBUG_PRINT("info", ("auto_position for channel '%s' is %d",
4068                           mi->get_channel(), mi->is_auto_position()));
4069       if (mi != nullptr && mi->is_auto_position()) {
4070         char buf[1024];
4071         snprintf(buf, sizeof(buf),
4072                  "replication channel '%.192s' is configured "
4073                  "in AUTO_POSITION mode. Execute "
4074                  "CHANGE MASTER TO MASTER_AUTO_POSITION = 0 "
4075                  "FOR CHANNEL '%.192s' before you set "
4076                  "@@GLOBAL.GTID_MODE = OFF.",
4077                  mi->get_channel(), mi->get_channel());
4078         my_error(ER_CANT_SET_GTID_MODE, MYF(0), "OFF", buf);
4079         goto err;
4080       }
4081     }
4082   }
4083 
4084   // Can't set GTID_MODE != ON when group replication is enabled.
4085   if (is_group_replication_running()) {
4086     DBUG_ASSERT(old_gtid_mode == Gtid_mode::ON);
4087     DBUG_ASSERT(new_gtid_mode == Gtid_mode::ON_PERMISSIVE);
4088     my_error(ER_CANT_SET_GTID_MODE, MYF(0), Gtid_mode::to_string(new_gtid_mode),
4089              "group replication requires @@GLOBAL.GTID_MODE=ON");
4090     goto err;
4091   }
4092 
4093   // Compatible with ongoing transactions.
4094   DBUG_PRINT("info", ("anonymous_ownership_count=%d owned_gtids->is_empty=%d",
4095                       gtid_state->get_anonymous_ownership_count(),
4096                       gtid_state->get_owned_gtids()->is_empty()));
4097   gtid_state->get_owned_gtids()->dbug_print("global owned_gtids");
4098   if (new_gtid_mode == Gtid_mode::ON &&
4099       gtid_state->get_anonymous_ownership_count() > 0) {
4100     my_error(ER_CANT_SET_GTID_MODE, MYF(0), "ON",
4101              "there are ongoing, anonymous transactions. Before "
4102              "setting @@GLOBAL.GTID_MODE = ON, wait until "
4103              "SHOW STATUS LIKE 'ANONYMOUS_TRANSACTION_COUNT' "
4104              "shows zero on all servers. Then wait for all "
4105              "existing, anonymous transactions to replicate to "
4106              "all slaves, and then execute "
4107              "SET @@GLOBAL.GTID_MODE = ON on all servers. "
4108              "See the Manual for details");
4109     goto err;
4110   }
4111 
4112   if (new_gtid_mode == Gtid_mode::OFF &&
4113       !gtid_state->get_owned_gtids()->is_empty()) {
4114     my_error(ER_CANT_SET_GTID_MODE, MYF(0), "OFF",
4115              "there are ongoing transactions that have a GTID. "
4116              "Before you set @@GLOBAL.GTID_MODE = OFF, wait "
4117              "until SELECT @@GLOBAL.GTID_OWNED is empty on all "
4118              "servers. Then wait for all GTID-transactions to "
4119              "replicate to all servers, and then execute "
4120              "SET @@GLOBAL.GTID_MODE = OFF on all servers. "
4121              "See the Manual for details");
4122     goto err;
4123   }
4124 
4125   // Compatible with ongoing GTID-violating transactions
4126   DBUG_PRINT("info",
4127              ("automatic_gtid_violating_transaction_count=%d",
4128               gtid_state->get_automatic_gtid_violating_transaction_count()));
4129   if (new_gtid_mode >= Gtid_mode::ON_PERMISSIVE &&
4130       gtid_state->get_automatic_gtid_violating_transaction_count() > 0) {
4131     my_error(ER_CANT_SET_GTID_MODE, MYF(0), "ON_PERMISSIVE",
4132              "there are ongoing transactions that use "
4133              "GTID_NEXT = 'AUTOMATIC', which violate GTID "
4134              "consistency. Adjust your workload to be "
4135              "GTID-consistent before setting "
4136              "@@GLOBAL.GTID_MODE = ON_PERMISSIVE. "
4137              "See the Manual for "
4138              "@@GLOBAL.ENFORCE_GTID_CONSISTENCY for details");
4139     goto err;
4140   }
4141 
4142   // Compatible with ENFORCE_GTID_CONSISTENCY.
4143   if (new_gtid_mode == Gtid_mode::ON &&
4144       get_gtid_consistency_mode() != GTID_CONSISTENCY_MODE_ON) {
4145     my_error(ER_CANT_SET_GTID_MODE, MYF(0), "ON",
4146              "ENFORCE_GTID_CONSISTENCY is not ON");
4147     goto err;
4148   }
4149 
4150   // Can't set GTID_MODE=OFF with ongoing calls to
4151   // WAIT_FOR_EXECUTED_GTID_SET or
4152   // WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS.
4153   DBUG_PRINT("info",
4154              ("gtid_wait_count=%d", gtid_state->get_gtid_wait_count() > 0));
4155   if (new_gtid_mode == Gtid_mode::OFF &&
4156       gtid_state->get_gtid_wait_count() > 0) {
4157     my_error(ER_CANT_SET_GTID_MODE, MYF(0), "OFF",
4158              "there are ongoing calls to "
4159              "WAIT_FOR_EXECUTED_GTID_SET or "
4160              "WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS. Before you set "
4161              "@@GLOBAL.GTID_MODE = OFF, ensure that no other "
4162              "client is waiting for GTID-transactions to be "
4163              "committed");
4164     goto err;
4165   }
4166 
4167   // Update the mode
4168   global_var(ulong) = new_gtid_mode;
4169   global_gtid_mode.set(new_gtid_mode);
4170   global_sid_lock->unlock();
4171   lock_count = 3;
4172 
4173   // Generate note in log
4174   LogErr(SYSTEM_LEVEL, ER_CHANGED_GTID_MODE,
4175          Gtid_mode::to_string(old_gtid_mode),
4176          Gtid_mode::to_string(new_gtid_mode));
4177 
4178   // Rotate
4179   {
4180     bool dont_care = false;
4181     if (mysql_bin_log.rotate(true, &dont_care)) goto err;
4182   }
4183 
4184 end:
4185   /* handle deprecations warning */
4186   issue_deprecation_warnings_gtid_mode(thd, old_gtid_mode, new_gtid_mode);
4187 
4188   ret = false;
4189 err:
4190   DBUG_ASSERT(lock_count >= 0);
4191   DBUG_ASSERT(lock_count <= 4);
4192   if (lock_count == 4) global_sid_lock->unlock();
4193   mysql_mutex_unlock(mysql_bin_log.get_log_lock());
4194   channel_map.unlock();
4195   Gtid_mode::lock.unlock();
4196   return ret;
4197 }
4198 
global_update(THD * thd,set_var * var)4199 bool Sys_var_enforce_gtid_consistency::global_update(THD *thd, set_var *var) {
4200   DBUG_TRACE;
4201   bool ret = true;
4202 
4203   /*
4204     Hold global_sid_lock.wrlock so that other transactions cannot
4205     acquire ownership of any gtid.
4206   */
4207   global_sid_lock->wrlock();
4208 
4209   DBUG_PRINT("info", ("var->save_result.ulonglong_value=%llu",
4210                       var->save_result.ulonglong_value));
4211   enum_gtid_consistency_mode new_mode =
4212       (enum_gtid_consistency_mode)var->save_result.ulonglong_value;
4213   enum_gtid_consistency_mode old_mode = get_gtid_consistency_mode();
4214   auto gtid_mode = global_gtid_mode.get();
4215 
4216   DBUG_ASSERT(new_mode <= GTID_CONSISTENCY_MODE_WARN);
4217 
4218   DBUG_PRINT("info", ("old enforce_gtid_consistency=%d "
4219                       "new enforce_gtid_consistency=%d "
4220                       "gtid_mode=%d ",
4221                       old_mode, new_mode, gtid_mode));
4222 
4223   if (new_mode == old_mode) goto end;
4224 
4225   // Can't turn off GTID-consistency when GTID_MODE=ON.
4226   if (new_mode != GTID_CONSISTENCY_MODE_ON && gtid_mode == Gtid_mode::ON) {
4227     my_error(ER_GTID_MODE_ON_REQUIRES_ENFORCE_GTID_CONSISTENCY_ON, MYF(0));
4228     goto err;
4229   }
4230   // If there are ongoing GTID-violating transactions, and we are
4231   // moving from OFF->ON, WARN->ON, or OFF->WARN, generate warning
4232   // or error accordingly.
4233   if (new_mode == GTID_CONSISTENCY_MODE_ON ||
4234       (old_mode == GTID_CONSISTENCY_MODE_OFF &&
4235        new_mode == GTID_CONSISTENCY_MODE_WARN)) {
4236     DBUG_PRINT("info",
4237                ("automatic_gtid_violating_transaction_count=%d "
4238                 "anonymous_gtid_violating_transaction_count=%d",
4239                 gtid_state->get_automatic_gtid_violating_transaction_count(),
4240                 gtid_state->get_anonymous_gtid_violating_transaction_count()));
4241     if (gtid_state->get_automatic_gtid_violating_transaction_count() > 0 ||
4242         gtid_state->get_anonymous_gtid_violating_transaction_count() > 0) {
4243       if (new_mode == GTID_CONSISTENCY_MODE_ON) {
4244         my_error(
4245             ER_CANT_ENFORCE_GTID_CONSISTENCY_WITH_ONGOING_GTID_VIOLATING_TX,
4246             MYF(0));
4247         goto err;
4248       } else {
4249         push_warning(
4250             thd, Sql_condition::SL_WARNING,
4251             ER_ENFORCE_GTID_CONSISTENCY_WARN_WITH_ONGOING_GTID_VIOLATING_TX,
4252             ER_THD(
4253                 thd,
4254                 ER_ENFORCE_GTID_CONSISTENCY_WARN_WITH_ONGOING_GTID_VIOLATING_TX));
4255       }
4256     }
4257   }
4258 
4259   // Update the mode
4260   global_var(ulong) = new_mode;
4261 
4262   // Generate note in log
4263   LogErr(INFORMATION_LEVEL, ER_CHANGED_ENFORCE_GTID_CONSISTENCY,
4264          get_gtid_consistency_mode_string(old_mode),
4265          get_gtid_consistency_mode_string(new_mode));
4266 
4267 end:
4268   ret = false;
4269 err:
4270   global_sid_lock->unlock();
4271   return ret;
4272 }
4273 
4274 static Sys_var_enum_binlog_checksum Binlog_checksum_enum(
4275     "binlog_checksum",
4276     "Type of BINLOG_CHECKSUM_ALG. Include checksum for "
4277     "log events in the binary log. Possible values are NONE and CRC32; "
4278     "default is CRC32.",
4279     GLOBAL_VAR(binlog_checksum_options), CMD_LINE(REQUIRED_ARG),
4280     binlog_checksum_type_names, DEFAULT(binary_log::BINLOG_CHECKSUM_ALG_CRC32),
4281     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_outside_trx));
4282 
4283 static Sys_var_bool Sys_master_verify_checksum(
4284     "master_verify_checksum",
4285     "Force checksum verification of logged events in binary log before "
4286     "sending them to slaves or printing them in output of SHOW BINLOG "
4287     "EVENTS. "
4288     "Disabled by default.",
4289     GLOBAL_VAR(opt_master_verify_checksum), CMD_LINE(OPT_ARG), DEFAULT(false));
4290 
4291 static Sys_var_ulong Sys_slow_launch_time(
4292     "slow_launch_time",
4293     "If creating the thread takes longer than this value (in seconds), "
4294     "the Slow_launch_threads counter will be incremented",
4295     GLOBAL_VAR(slow_launch_time), CMD_LINE(REQUIRED_ARG),
4296     VALID_RANGE(0, LONG_TIMEOUT), DEFAULT(2), BLOCK_SIZE(1));
4297 
4298 static Sys_var_ulong Sys_sort_buffer(
4299     "sort_buffer_size",
4300     "Each thread that needs to do a sort allocates a buffer of this size",
4301     HINT_UPDATEABLE SESSION_VAR(sortbuff_size), CMD_LINE(REQUIRED_ARG),
4302     VALID_RANGE(MIN_SORT_MEMORY, ULONG_MAX), DEFAULT(DEFAULT_SORT_MEMORY),
4303     BLOCK_SIZE(1));
4304 
4305 /**
4306   Check sql modes strict_mode, 'NO_ZERO_DATE', 'NO_ZERO_IN_DATE' and
4307   'ERROR_FOR_DIVISION_BY_ZERO' are used together. If only subset of it
4308   is set then warning is reported.
4309 
4310   @param sql_mode sql mode.
4311   @param thd      Current thread
4312 */
check_sub_modes_of_strict_mode(sql_mode_t & sql_mode,THD * thd)4313 static void check_sub_modes_of_strict_mode(sql_mode_t &sql_mode, THD *thd) {
4314   const sql_mode_t strict_modes =
4315       (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES);
4316 
4317   const sql_mode_t new_strict_submodes =
4318       (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
4319        MODE_ERROR_FOR_DIVISION_BY_ZERO);
4320 
4321   const sql_mode_t strict_modes_set = (sql_mode & strict_modes);
4322   const sql_mode_t new_strict_submodes_set = (sql_mode & new_strict_submodes);
4323 
4324   if (((strict_modes_set | new_strict_submodes_set) != 0) &&
4325       ((new_strict_submodes_set != new_strict_submodes) ||
4326        (strict_modes_set == 0))) {
4327     if (thd)
4328       push_warning(thd, Sql_condition::SL_WARNING, ER_SQL_MODE_MERGED,
4329                    ER_THD(thd, ER_SQL_MODE_MERGED));
4330     else
4331       LogErr(WARNING_LEVEL, ER_SQL_MODE_MERGED_WITH_STRICT_MODE);
4332   }
4333 }
4334 
expand_sql_mode(sql_mode_t sql_mode,THD * thd)4335 export sql_mode_t expand_sql_mode(sql_mode_t sql_mode, THD *thd) {
4336   if (sql_mode & MODE_ANSI) {
4337     /*
4338       Note that we dont set
4339       MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | MODE_NO_FIELD_OPTIONS
4340       to allow one to get full use of MySQL in this mode.
4341     */
4342     sql_mode |= (MODE_REAL_AS_FLOAT | MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
4343                  MODE_IGNORE_SPACE | MODE_ONLY_FULL_GROUP_BY);
4344   }
4345   if (sql_mode & MODE_TRADITIONAL)
4346     sql_mode |= (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES |
4347                  MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
4348                  MODE_ERROR_FOR_DIVISION_BY_ZERO | MODE_NO_ENGINE_SUBSTITUTION);
4349 
4350   check_sub_modes_of_strict_mode(sql_mode, thd);
4351   return sql_mode;
4352 }
check_sql_mode(sys_var *,THD * thd,set_var * var)4353 static bool check_sql_mode(sys_var *, THD *thd, set_var *var) {
4354   sql_mode_t candidate_mode =
4355       expand_sql_mode(var->save_result.ulonglong_value, thd);
4356 
4357   if (candidate_mode & ~(MODE_ALLOWED_MASK | MODE_IGNORED_MASK)) {
4358     my_error(ER_UNSUPPORTED_SQL_MODE, MYF(0),
4359              candidate_mode & ~(MODE_ALLOWED_MASK | MODE_IGNORED_MASK));
4360     return true;  // mode seems never supported before
4361   }
4362 
4363   if (candidate_mode & ~MODE_ALLOWED_MASK) {
4364     if (thd->variables.pseudo_slave_mode &&  // (1)
4365         thd->lex->sphead == nullptr) {       // (2)
4366       /*
4367         (1): catch the auto-generated SET SQL_MODE calls in the output of
4368              mysqlbinlog,
4369         (2): but ignore the other ones (e.g. nested SET SQL_MODE calls in
4370              SBR-invoked trigger calls).
4371       */
4372       push_warning_printf(
4373           thd, Sql_condition::SL_WARNING, ER_WARN_REMOVED_SQL_MODE,
4374           ER_THD(thd, ER_WARN_REMOVED_SQL_MODE),
4375           static_cast<uint>(candidate_mode & ~MODE_ALLOWED_MASK));
4376       // ignore obsolete mode flags in case this is an old mysqlbinlog:
4377       candidate_mode &= MODE_ALLOWED_MASK;
4378     } else {
4379       my_error(ER_UNSUPPORTED_SQL_MODE, MYF(0),
4380                candidate_mode & ~MODE_ALLOWED_MASK);
4381       return true;  // error on obsolete mode flags
4382     }
4383   }
4384 
4385   if (candidate_mode & MODE_PAD_CHAR_TO_FULL_LENGTH) {
4386     push_warning_printf(
4387         thd, Sql_condition::SL_WARNING, ER_WARN_DEPRECATED_SQLMODE,
4388         ER_THD(thd, ER_WARN_DEPRECATED_SQLMODE), "PAD_CHAR_TO_FULL_LENGTH");
4389   }
4390 
4391   var->save_result.ulonglong_value = candidate_mode;
4392   return false;
4393 }
fix_sql_mode(sys_var * self,THD * thd,enum_var_type type)4394 static bool fix_sql_mode(sys_var *self, THD *thd, enum_var_type type) {
4395   if (!self->is_global_persist(type)) {
4396     /* Update thd->server_status */
4397     if (thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)
4398       thd->server_status |= SERVER_STATUS_NO_BACKSLASH_ESCAPES;
4399     else
4400       thd->server_status &= ~SERVER_STATUS_NO_BACKSLASH_ESCAPES;
4401   }
4402   return false;
4403 }
4404 /*
4405   WARNING: When adding new SQL modes don't forget to update the
4406   tables definitions that stores it's value (ie: mysql.event, mysql.routines,
4407   mysql.triggers)
4408 */
4409 static const char *sql_mode_names[] = {"REAL_AS_FLOAT",
4410                                        "PIPES_AS_CONCAT",
4411                                        "ANSI_QUOTES",
4412                                        "IGNORE_SPACE",
4413                                        "NOT_USED",
4414                                        "ONLY_FULL_GROUP_BY",
4415                                        "NO_UNSIGNED_SUBTRACTION",
4416                                        "NO_DIR_IN_CREATE",
4417                                        "NOT_USED_9",
4418                                        "NOT_USED_10",
4419                                        "NOT_USED_11",
4420                                        "NOT_USED_12",
4421                                        "NOT_USED_13",
4422                                        "NOT_USED_14",
4423                                        "NOT_USED_15",
4424                                        "NOT_USED_16",
4425                                        "NOT_USED_17",
4426                                        "NOT_USED_18",
4427                                        "ANSI",
4428                                        "NO_AUTO_VALUE_ON_ZERO",
4429                                        "NO_BACKSLASH_ESCAPES",
4430                                        "STRICT_TRANS_TABLES",
4431                                        "STRICT_ALL_TABLES",
4432                                        "NO_ZERO_IN_DATE",
4433                                        "NO_ZERO_DATE",
4434                                        "ALLOW_INVALID_DATES",
4435                                        "ERROR_FOR_DIVISION_BY_ZERO",
4436                                        "TRADITIONAL",
4437                                        "NOT_USED_29",
4438                                        "HIGH_NOT_PRECEDENCE",
4439                                        "NO_ENGINE_SUBSTITUTION",
4440                                        "PAD_CHAR_TO_FULL_LENGTH",
4441                                        "TIME_TRUNCATE_FRACTIONAL",
4442                                        nullptr};
sql_mode_string_representation(THD * thd,sql_mode_t sql_mode,LEX_STRING * ls)4443 export bool sql_mode_string_representation(THD *thd, sql_mode_t sql_mode,
4444                                            LEX_STRING *ls) {
4445   set_to_string(thd, ls, sql_mode, sql_mode_names);
4446   return ls->str == nullptr;
4447 }
sql_mode_quoted_string_representation(THD * thd,sql_mode_t sql_mode,LEX_STRING * ls)4448 export bool sql_mode_quoted_string_representation(THD *thd, sql_mode_t sql_mode,
4449                                                   LEX_STRING *ls) {
4450   set_to_string(thd, ls, sql_mode, sql_mode_names, true);
4451   return ls->str == nullptr;
4452 }
4453 /*
4454   sql_mode should *not* be IN_BINLOG: even though it is written to the binlog,
4455   the slave ignores the MODE_NO_DIR_IN_CREATE variable, so slave's value
4456   differs from master's (see log_event.cc: Query_log_event::do_apply_event()).
4457 */
4458 static Sys_var_set Sys_sql_mode(
4459     "sql_mode",
4460     "Syntax: sql-mode=mode[,mode[,mode...]]. See the manual for the "
4461     "complete list of valid sql modes",
4462     HINT_UPDATEABLE SESSION_VAR(sql_mode), CMD_LINE(REQUIRED_ARG),
4463     sql_mode_names,
4464     DEFAULT(MODE_NO_ENGINE_SUBSTITUTION | MODE_ONLY_FULL_GROUP_BY |
4465             MODE_STRICT_TRANS_TABLES | MODE_NO_ZERO_IN_DATE |
4466             MODE_NO_ZERO_DATE | MODE_ERROR_FOR_DIVISION_BY_ZERO),
4467     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_sql_mode),
4468     ON_UPDATE(fix_sql_mode));
4469 
4470 static Sys_var_ulong Sys_max_execution_time(
4471     "max_execution_time",
4472     "Kill SELECT statement that takes over the specified number of "
4473     "milliseconds",
4474     HINT_UPDATEABLE SESSION_VAR(max_execution_time), CMD_LINE(REQUIRED_ARG),
4475     VALID_RANGE(0, ULONG_MAX), DEFAULT(0), BLOCK_SIZE(1));
4476 
update_fips_mode(sys_var *,THD *,enum_var_type)4477 static bool update_fips_mode(sys_var *, THD *, enum_var_type) {
4478   char ssl_err_string[OPENSSL_ERROR_LENGTH] = {'\0'};
4479   if (set_fips_mode(opt_ssl_fips_mode, ssl_err_string) != 1) {
4480     opt_ssl_fips_mode = get_fips_mode();
4481     my_error(ER_SSL_FIPS_MODE_ERROR, MYF(0), "Openssl is not fips enabled");
4482     return true;
4483   } else {
4484     return false;
4485   }
4486 }
4487 
4488 static const char *ssl_fips_mode_names[] = {"OFF", "ON", "STRICT", nullptr};
4489 static Sys_var_enum Sys_ssl_fips_mode(
4490     "ssl_fips_mode",
4491     "SSL FIPS mode (applies only for OpenSSL); "
4492     "permitted values are: OFF, ON, STRICT",
4493     GLOBAL_VAR(opt_ssl_fips_mode), CMD_LINE(REQUIRED_ARG, OPT_SSL_FIPS_MODE),
4494     ssl_fips_mode_names, DEFAULT(0), NO_MUTEX_GUARD, NOT_IN_BINLOG,
4495     ON_CHECK(nullptr), ON_UPDATE(update_fips_mode), nullptr);
4496 
4497 static Sys_var_bool Sys_auto_generate_certs(
4498     "auto_generate_certs",
4499     "Auto generate SSL certificates at server startup if --ssl is set to "
4500     "ON and none of the other SSL system variables are specified and "
4501     "certificate/key files are not present in data directory.",
4502     READ_ONLY NON_PERSIST GLOBAL_VAR(opt_auto_generate_certs),
4503     CMD_LINE(OPT_ARG), DEFAULT(true), NO_MUTEX_GUARD, NOT_IN_BINLOG,
4504     ON_CHECK(nullptr), ON_UPDATE(nullptr), nullptr);
4505 
4506 // why ENUM and not BOOL ?
4507 static const char *updatable_views_with_limit_names[] = {"NO", "YES", nullptr};
4508 static Sys_var_enum Sys_updatable_views_with_limit(
4509     "updatable_views_with_limit",
4510     "YES = Don't issue an error message (warning only) if a VIEW without "
4511     "presence of a key of the underlying table is used in queries with a "
4512     "LIMIT clause for updating. NO = Prohibit update of a VIEW, which "
4513     "does not contain a key of the underlying table and the query uses "
4514     "a LIMIT clause (usually get from GUI tools)",
4515     HINT_UPDATEABLE SESSION_VAR(updatable_views_with_limit),
4516     CMD_LINE(REQUIRED_ARG), updatable_views_with_limit_names, DEFAULT(true));
4517 
4518 static char *system_time_zone_ptr;
4519 static Sys_var_charptr Sys_system_time_zone(
4520     "system_time_zone", "The server system time zone",
4521     READ_ONLY NON_PERSIST GLOBAL_VAR(system_time_zone_ptr), NO_CMD_LINE,
4522     IN_FS_CHARSET, DEFAULT(system_time_zone));
4523 
4524 static Sys_var_ulong Sys_table_def_size(
4525     "table_definition_cache", "The number of cached table definitions",
4526     GLOBAL_VAR(table_def_size),
4527     CMD_LINE(REQUIRED_ARG, OPT_TABLE_DEFINITION_CACHE),
4528     VALID_RANGE(TABLE_DEF_CACHE_MIN, 512 * 1024),
4529     DEFAULT(TABLE_DEF_CACHE_DEFAULT), BLOCK_SIZE(1), NO_MUTEX_GUARD,
4530     NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(nullptr), nullptr,
4531     /* table_definition_cache is used as a sizing hint by the performance
4532        schema. */
4533     sys_var::PARSE_EARLY);
4534 
4535 static Sys_var_ulong Sys_schema_def_size(
4536     "schema_definition_cache", "The number of cached schema definitions",
4537     GLOBAL_VAR(schema_def_size), CMD_LINE(REQUIRED_ARG),
4538     VALID_RANGE(SCHEMA_DEF_CACHE_MIN, 512 * 1024),
4539     DEFAULT(SCHEMA_DEF_CACHE_DEFAULT), BLOCK_SIZE(1));
4540 
4541 static Sys_var_ulong Sys_tablespace_def_size(
4542     "tablespace_definition_cache",
4543     "The number of cached tablespace definitions",
4544     GLOBAL_VAR(tablespace_def_size), CMD_LINE(REQUIRED_ARG),
4545     VALID_RANGE(TABLESPACE_DEF_CACHE_MIN, 512 * 1024),
4546     DEFAULT(TABLESPACE_DEF_CACHE_DEFAULT), BLOCK_SIZE(1));
4547 
4548 static Sys_var_ulong Sys_stored_program_def_size(
4549     "stored_program_definition_cache",
4550     "The number of cached stored program definitions",
4551     GLOBAL_VAR(stored_program_def_size), CMD_LINE(REQUIRED_ARG),
4552     VALID_RANGE(STORED_PROGRAM_DEF_CACHE_MIN, 512 * 1024),
4553     DEFAULT(STORED_PROGRAM_DEF_CACHE_DEFAULT), BLOCK_SIZE(1));
4554 
fix_table_cache_size(sys_var *,THD *,enum_var_type)4555 static bool fix_table_cache_size(sys_var *, THD *, enum_var_type) {
4556   /*
4557     table_open_cache parameter is a soft limit for total number of objects
4558     in all table cache instances. Once this value is updated we need to
4559     update value of a per-instance soft limit on table cache size.
4560   */
4561   table_cache_size_per_instance = table_cache_size / table_cache_instances;
4562   return false;
4563 }
4564 
4565 static Sys_var_ulong Sys_table_cache_size(
4566     "table_open_cache",
4567     "The number of cached open tables "
4568     "(total for all table cache instances)",
4569     GLOBAL_VAR(table_cache_size), CMD_LINE(REQUIRED_ARG),
4570     VALID_RANGE(1, 512 * 1024), DEFAULT(TABLE_OPEN_CACHE_DEFAULT),
4571     BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
4572     ON_UPDATE(fix_table_cache_size), nullptr,
4573     /* table_open_cache is used as a sizing hint by the performance schema. */
4574     sys_var::PARSE_EARLY);
4575 
4576 static Sys_var_ulong Sys_table_cache_instances(
4577     "table_open_cache_instances", "The number of table cache instances",
4578     READ_ONLY GLOBAL_VAR(table_cache_instances), CMD_LINE(REQUIRED_ARG),
4579     VALID_RANGE(1, Table_cache_manager::MAX_TABLE_CACHES),
4580     DEFAULT(Table_cache_manager::DEFAULT_MAX_TABLE_CACHES), BLOCK_SIZE(1),
4581     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(nullptr),
4582     nullptr,
4583     /*
4584       table_open_cache is used as a sizing hint by the performance schema,
4585       and 'table_open_cache' is a prefix of 'table_open_cache_instances'.
4586       Is is better to keep these options together, to avoid confusing
4587       handle_options() with partial name matches.
4588     */
4589     sys_var::PARSE_EARLY);
4590 
4591 /**
4592   Modify the thread size cache size.
4593 */
4594 
modify_thread_cache_size(sys_var *,THD *,enum_var_type)4595 static inline bool modify_thread_cache_size(sys_var *, THD *, enum_var_type) {
4596   if (Connection_handler_manager::thread_handling ==
4597       Connection_handler_manager::SCHEDULER_ONE_THREAD_PER_CONNECTION) {
4598     Per_thread_connection_handler::modify_thread_cache_size(
4599         Per_thread_connection_handler::max_blocked_pthreads);
4600   }
4601   return false;
4602 }
4603 
4604 static Sys_var_ulong Sys_thread_cache_size(
4605     "thread_cache_size", "How many threads we should keep in a cache for reuse",
4606     GLOBAL_VAR(Per_thread_connection_handler::max_blocked_pthreads),
4607     CMD_LINE(REQUIRED_ARG, OPT_THREAD_CACHE_SIZE), VALID_RANGE(0, 16384),
4608     DEFAULT(0), BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, nullptr,
4609     ON_UPDATE(modify_thread_cache_size));
4610 
4611 /**
4612   Function to check if the 'next' transaction isolation level
4613   can be changed.
4614 
4615   @param[in] thd    Thread handler.
4616   @param[in] var    A pointer to set_var holding the specified list of
4617                     system variable names.
4618 
4619   @retval   false   Success.
4620   @retval   true    Error.
4621 */
check_transaction_isolation(sys_var *,THD * thd,set_var * var)4622 static bool check_transaction_isolation(sys_var *, THD *thd, set_var *var) {
4623   if (var->type == OPT_DEFAULT &&
4624       (thd->in_active_multi_stmt_transaction() || thd->in_sub_stmt)) {
4625     DBUG_ASSERT(thd->in_multi_stmt_transaction_mode() || thd->in_sub_stmt);
4626     my_error(ER_CANT_CHANGE_TX_CHARACTERISTICS, MYF(0));
4627     return true;
4628   }
4629   return false;
4630 }
4631 
4632 /**
4633   This function sets the session variable thd->variables.transaction_isolation
4634   to reflect changes to @@session.transaction_isolation.
4635 
4636   @param[in] thd    Thread handler.
4637   @param[in] var    A pointer to the set_var.
4638 
4639   @retval   false   Success.
4640   @retval   true    Error.
4641 */
session_update(THD * thd,set_var * var)4642 bool Sys_var_transaction_isolation::session_update(THD *thd, set_var *var) {
4643   if (var->type == OPT_SESSION && Sys_var_enum::session_update(thd, var))
4644     return true;
4645   if (var->type == OPT_DEFAULT ||
4646       !(thd->in_active_multi_stmt_transaction() || thd->in_sub_stmt)) {
4647     /*
4648       Update the isolation level of the next transaction.
4649       I.e. if one did:
4650       COMMIT;
4651       SET SESSION ISOLATION LEVEL ...
4652       BEGIN; <-- this transaction has the new isolation
4653       Note, that in case of:
4654       COMMIT;
4655       SET TRANSACTION ISOLATION LEVEL ...
4656       SET SESSION ISOLATION LEVEL ...
4657       BEGIN; <-- the session isolation level is used, not the
4658       result of SET TRANSACTION statement.
4659 
4660       When we are in a trigger/function the transaction is already
4661       started. Adhering to above behavior, the SET TRANSACTION would
4662       fail when run from within trigger/function. And SET SESSION
4663       TRANSACTION would always succeed making the characteristics
4664       effective for the next transaction that starts.
4665      */
4666     enum_tx_isolation tx_isol;
4667     tx_isol = (enum_tx_isolation)var->save_result.ulonglong_value;
4668     bool one_shot = (var->type == OPT_DEFAULT);
4669     return set_tx_isolation(thd, tx_isol, one_shot);
4670   }
4671   return false;
4672 }
4673 
4674 // NO_CMD_LINE
4675 static Sys_var_transaction_isolation Sys_transaction_isolation(
4676     "transaction_isolation", "Default transaction isolation level",
4677     UNTRACKED_DEFAULT SESSION_VAR(transaction_isolation), NO_CMD_LINE,
4678     tx_isolation_names, DEFAULT(ISO_REPEATABLE_READ), NO_MUTEX_GUARD,
4679     NOT_IN_BINLOG, ON_CHECK(check_transaction_isolation));
4680 
4681 /**
4682   Function to check if the state of 'transaction_read_only' can be changed.
4683   The state cannot be changed if there is already a transaction in progress.
4684 
4685   @param[in] thd    Thread handler
4686   @param[in] var    A pointer to set_var holding the specified list of
4687                     system variable names.
4688 
4689   @retval   false   Success.
4690   @retval   true    Error.
4691 */
check_transaction_read_only(sys_var *,THD * thd,set_var * var)4692 static bool check_transaction_read_only(sys_var *, THD *thd, set_var *var) {
4693   if (var->type == OPT_DEFAULT &&
4694       (thd->in_active_multi_stmt_transaction() || thd->in_sub_stmt)) {
4695     DBUG_ASSERT(thd->in_multi_stmt_transaction_mode() || thd->in_sub_stmt);
4696     my_error(ER_CANT_CHANGE_TX_CHARACTERISTICS, MYF(0));
4697     return true;
4698   }
4699   return false;
4700 }
4701 
4702 /**
4703   This function sets the session variable thd->variables.transaction_read_only
4704   to reflect changes to @@session.transaction_read_only.
4705 
4706   @param[in] thd    Thread handler.
4707   @param[in] var    A pointer to the set_var.
4708 
4709   @retval   false   Success.
4710 */
session_update(THD * thd,set_var * var)4711 bool Sys_var_transaction_read_only::session_update(THD *thd, set_var *var) {
4712   if (var->type == OPT_SESSION && Sys_var_bool::session_update(thd, var))
4713     return true;
4714   if (var->type == OPT_DEFAULT ||
4715       !(thd->in_active_multi_stmt_transaction() || thd->in_sub_stmt)) {
4716     // @see Sys_var_transaction_isolation::session_update() above for the
4717     // rules.
4718     thd->tx_read_only = var->save_result.ulonglong_value;
4719 
4720     if (thd->variables.session_track_transaction_info > TX_TRACK_NONE) {
4721       TX_TRACKER_GET(tst);
4722 
4723       if (var->type == OPT_DEFAULT)
4724         tst->set_read_flags(thd,
4725                             thd->tx_read_only ? TX_READ_ONLY : TX_READ_WRITE);
4726       else
4727         tst->set_read_flags(thd, TX_READ_INHERIT);
4728     }
4729   }
4730   return false;
4731 }
4732 
4733 static Sys_var_transaction_read_only Sys_transaction_read_only(
4734     "transaction_read_only",
4735     "Set default transaction access mode to read only.",
4736     UNTRACKED_DEFAULT SESSION_VAR(transaction_read_only), NO_CMD_LINE,
4737     DEFAULT(0), NO_MUTEX_GUARD, NOT_IN_BINLOG,
4738     ON_CHECK(check_transaction_read_only));
4739 
4740 static Sys_var_ulonglong Sys_tmp_table_size(
4741     "tmp_table_size",
4742     "If an internal in-memory temporary table in the MEMORY storage engine "
4743     "exceeds this size, MySQL will automatically convert it to an on-disk "
4744     "table",
4745     HINT_UPDATEABLE SESSION_VAR(tmp_table_size), CMD_LINE(REQUIRED_ARG),
4746     VALID_RANGE(1024, (ulonglong) ~(intptr)0), DEFAULT(16 * 1024 * 1024),
4747     BLOCK_SIZE(1));
4748 
4749 static char *server_version_ptr;
4750 static Sys_var_version Sys_version(
4751     "version", "Server version",
4752     READ_ONLY NON_PERSIST GLOBAL_VAR(server_version_ptr), NO_CMD_LINE,
4753     IN_SYSTEM_CHARSET, DEFAULT(server_version));
4754 
4755 static char *server_version_comment_ptr;
4756 static Sys_var_charptr Sys_version_comment(
4757     "version_comment", "version_comment",
4758     READ_ONLY NON_PERSIST GLOBAL_VAR(server_version_comment_ptr), NO_CMD_LINE,
4759     IN_SYSTEM_CHARSET, DEFAULT(MYSQL_COMPILATION_COMMENT_SERVER));
4760 
4761 static char *server_version_compile_machine_ptr;
4762 static Sys_var_charptr Sys_version_compile_machine(
4763     "version_compile_machine", "version_compile_machine",
4764     READ_ONLY NON_PERSIST GLOBAL_VAR(server_version_compile_machine_ptr),
4765     NO_CMD_LINE, IN_SYSTEM_CHARSET, DEFAULT(MACHINE_TYPE));
4766 
4767 static char *server_version_compile_os_ptr;
4768 static Sys_var_charptr Sys_version_compile_os(
4769     "version_compile_os", "version_compile_os",
4770     READ_ONLY NON_PERSIST GLOBAL_VAR(server_version_compile_os_ptr),
4771     NO_CMD_LINE, IN_SYSTEM_CHARSET, DEFAULT(SYSTEM_TYPE));
4772 
4773 static const char *server_version_compile_zlib_ptr = ZLIB_VERSION;
4774 static Sys_var_charptr Sys_version_compile_zlib(
4775     "version_compile_zlib", "version_compile_zlib",
4776     READ_ONLY NON_PERSIST GLOBAL_VAR(server_version_compile_zlib_ptr),
4777     NO_CMD_LINE, IN_SYSTEM_CHARSET, DEFAULT(ZLIB_VERSION));
4778 
4779 static Sys_var_ulong Sys_net_wait_timeout(
4780     "wait_timeout",
4781     "The number of seconds the server waits for activity on a "
4782     "connection before closing it",
4783     SESSION_VAR(net_wait_timeout), CMD_LINE(REQUIRED_ARG),
4784     VALID_RANGE(1, IF_WIN(INT_MAX32 / 1000, LONG_TIMEOUT)),
4785     DEFAULT(NET_WAIT_TIMEOUT), BLOCK_SIZE(1));
4786 
4787 static Sys_var_plugin Sys_default_storage_engine(
4788     "default_storage_engine", "The default storage engine for new tables",
4789     SESSION_VAR(table_plugin), NO_CMD_LINE, MYSQL_STORAGE_ENGINE_PLUGIN,
4790     DEFAULT(&default_storage_engine), NO_MUTEX_GUARD, NOT_IN_BINLOG,
4791     ON_CHECK(check_storage_engine));
4792 
4793 const char *internal_tmp_mem_storage_engine_names[] = {"MEMORY", "TempTable",
4794                                                        nullptr};
4795 static Sys_var_enum Sys_internal_tmp_mem_storage_engine(
4796     "internal_tmp_mem_storage_engine",
4797     "The default storage engine for in-memory internal temporary tables.",
4798     HINT_UPDATEABLE SESSION_VAR(internal_tmp_mem_storage_engine),
4799     CMD_LINE(REQUIRED_ARG), internal_tmp_mem_storage_engine_names,
4800     DEFAULT(TMP_TABLE_TEMPTABLE));
4801 
4802 static Sys_var_ulonglong Sys_temptable_max_ram(
4803     "temptable_max_ram",
4804     "Maximum amount of memory (in bytes) the TempTable storage engine is "
4805     "allowed to allocate from the main memory (RAM) before starting to "
4806     "store data on disk.",
4807     GLOBAL_VAR(temptable_max_ram), CMD_LINE(REQUIRED_ARG),
4808     VALID_RANGE(2 << 20 /* 2 MiB */, ULLONG_MAX), DEFAULT(1 << 30 /* 1 GiB */),
4809     BLOCK_SIZE(1));
4810 
4811 static Sys_var_bool Sys_temptable_use_mmap("temptable_use_mmap",
4812                                            "Use mmap files for temptables",
4813                                            GLOBAL_VAR(temptable_use_mmap),
4814                                            CMD_LINE(OPT_ARG), DEFAULT(true));
4815 
4816 static Sys_var_plugin Sys_default_tmp_storage_engine(
4817     "default_tmp_storage_engine",
4818     "The default storage engine for new explicit temporary tables",
4819     HINT_UPDATEABLE SESSION_VAR(temp_table_plugin), NO_CMD_LINE,
4820     MYSQL_STORAGE_ENGINE_PLUGIN, DEFAULT(&default_tmp_storage_engine),
4821     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_storage_engine));
4822 
4823 #if defined(ENABLED_DEBUG_SYNC)
4824 /*
4825   Variable can be set for the session only.
4826 
4827   This could be changed later. Then we need to have a global array of
4828   actions in addition to the thread local ones. SET GLOBAL would
4829   manage the global array, SET [SESSION] the local array. A sync point
4830   would need to look for a local and a global action. Setting and
4831   executing of global actions need to be protected by a mutex.
4832 
4833   The purpose of global actions could be to allow synchronizing with
4834   connectionless threads that cannot execute SET statements.
4835 */
4836 static Sys_var_debug_sync Sys_debug_sync("debug_sync", "Debug Sync Facility",
4837                                          sys_var::ONLY_SESSION, NO_CMD_LINE,
4838                                          DEFAULT(nullptr), NO_MUTEX_GUARD,
4839                                          NOT_IN_BINLOG,
4840                                          ON_CHECK(check_session_admin));
4841 #endif /* defined(ENABLED_DEBUG_SYNC) */
4842 
fix_autocommit(sys_var * self,THD * thd,enum_var_type type)4843 static bool fix_autocommit(sys_var *self, THD *thd, enum_var_type type) {
4844   if (self->is_global_persist(type)) {
4845     if (global_system_variables.option_bits & OPTION_AUTOCOMMIT)
4846       global_system_variables.option_bits &= ~OPTION_NOT_AUTOCOMMIT;
4847     else
4848       global_system_variables.option_bits |= OPTION_NOT_AUTOCOMMIT;
4849     return false;
4850   }
4851 
4852   if (thd->variables.option_bits & OPTION_AUTOCOMMIT &&
4853       thd->variables.option_bits &
4854           OPTION_NOT_AUTOCOMMIT) {  // activating autocommit
4855 
4856     if (trans_commit_stmt(thd) || trans_commit(thd)) {
4857       thd->variables.option_bits &= ~OPTION_AUTOCOMMIT;
4858       return true;
4859     }
4860     /*
4861       Don't close thread tables or release metadata locks: if we do so, we
4862       risk releasing locks/closing tables of expressions used to assign
4863       other variables, as in:
4864       set @var=my_stored_function1(), @@autocommit=1, @var2=(select max(a)
4865       from my_table), ...
4866       The locks will be released at statement end anyway, as SET
4867       statement that assigns autocommit is marked to commit
4868       transaction implicitly at the end (@sa stmt_causes_implicitcommit()).
4869     */
4870     thd->variables.option_bits &= ~(OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
4871     thd->get_transaction()->reset_unsafe_rollback_flags(
4872         Transaction_ctx::SESSION);
4873     thd->server_status |= SERVER_STATUS_AUTOCOMMIT;
4874     return false;
4875   }
4876 
4877   if (!(thd->variables.option_bits & OPTION_AUTOCOMMIT) &&
4878       !(thd->variables.option_bits &
4879         OPTION_NOT_AUTOCOMMIT)) {  // disabling autocommit
4880 
4881     thd->get_transaction()->reset_unsafe_rollback_flags(
4882         Transaction_ctx::SESSION);
4883     thd->server_status &= ~SERVER_STATUS_AUTOCOMMIT;
4884     thd->variables.option_bits |= OPTION_NOT_AUTOCOMMIT;
4885     return false;
4886   }
4887 
4888   return false;  // autocommit value wasn't changed
4889 }
4890 static Sys_var_bit Sys_autocommit("autocommit", "autocommit",
4891                                   SESSION_VAR(option_bits), NO_CMD_LINE,
4892                                   OPTION_AUTOCOMMIT, DEFAULT(true),
4893                                   NO_MUTEX_GUARD, NOT_IN_BINLOG,
4894                                   ON_CHECK(nullptr), ON_UPDATE(fix_autocommit));
4895 export sys_var *Sys_autocommit_ptr = &Sys_autocommit;  // for sql_yacc.yy
4896 
4897 static Sys_var_bool Sys_big_tables(
4898     "big_tables",
4899     "Allow big result sets by saving all "
4900     "temporary sets on file (Solves most 'table full' errors)",
4901     HINT_UPDATEABLE SESSION_VAR(big_tables), CMD_LINE(OPT_ARG), DEFAULT(false));
4902 
4903 static Sys_var_bit Sys_big_selects("sql_big_selects", "sql_big_selects",
4904                                    HINT_UPDATEABLE SESSION_VAR(option_bits),
4905                                    NO_CMD_LINE, OPTION_BIG_SELECTS,
4906                                    DEFAULT(false));
4907 
4908 static Sys_var_bit Sys_log_off("sql_log_off", "sql_log_off",
4909                                SESSION_VAR(option_bits), NO_CMD_LINE,
4910                                OPTION_LOG_OFF, DEFAULT(false), NO_MUTEX_GUARD,
4911                                NOT_IN_BINLOG, ON_CHECK(check_session_admin));
4912 
4913 /**
4914   This function sets the session variable thd->variables.sql_log_bin
4915   to reflect changes to @@session.sql_log_bin.
4916 
4917   @param     thd    Current thread
4918   @param[in] type   The type either session or global.
4919 
4920   @return @c false.
4921 */
fix_sql_log_bin_after_update(sys_var *,THD * thd,enum_var_type type MY_ATTRIBUTE ((unused)))4922 static bool fix_sql_log_bin_after_update(
4923     sys_var *, THD *thd, enum_var_type type MY_ATTRIBUTE((unused))) {
4924   DBUG_ASSERT(type == OPT_SESSION);
4925 
4926   if (thd->variables.sql_log_bin)
4927     thd->variables.option_bits |= OPTION_BIN_LOG;
4928   else
4929     thd->variables.option_bits &= ~OPTION_BIN_LOG;
4930 
4931   return false;
4932 }
4933 
4934 /**
4935   This function checks if the sql_log_bin can be changed,
4936   what is possible if:
4937     - the user is a super user;
4938     - the set is not called from within a function/trigger;
4939     - there is no on-going transaction.
4940 
4941   @param     thd    Current thread
4942   @param[in] self   A pointer to the sys_var, i.e. Sys_log_binlog.
4943   @param[in] var    A pointer to the set_var created by the parser.
4944 
4945   @return @c false if the change is allowed, otherwise @c true.
4946 */
check_sql_log_bin(sys_var * self,THD * thd,set_var * var)4947 static bool check_sql_log_bin(sys_var *self, THD *thd, set_var *var) {
4948   if (check_session_admin(self, thd, var)) return true;
4949 
4950   if (var->is_global_persist()) return true;
4951 
4952   /* If in a stored function/trigger, it's too late to change sql_log_bin. */
4953   if (thd->in_sub_stmt) {
4954     my_error(ER_STORED_FUNCTION_PREVENTS_SWITCH_SQL_LOG_BIN, MYF(0));
4955     return true;
4956   }
4957   /* Make the session variable 'sql_log_bin' read-only inside a transaction.
4958    */
4959   if (thd->in_active_multi_stmt_transaction()) {
4960     my_error(ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_SQL_LOG_BIN, MYF(0));
4961     return true;
4962   }
4963 
4964   return false;
4965 }
4966 
4967 static Sys_var_bool Sys_log_binlog(
4968     "sql_log_bin", "Controls whether logging to the binary log is done",
4969     SESSION_ONLY(sql_log_bin), NO_CMD_LINE, DEFAULT(true), NO_MUTEX_GUARD,
4970     NOT_IN_BINLOG, ON_CHECK(check_sql_log_bin),
4971     ON_UPDATE(fix_sql_log_bin_after_update));
4972 
4973 static Sys_var_bit Sys_transaction_allow_batching(
4974     "transaction_allow_batching", "transaction_allow_batching",
4975     SESSION_ONLY(option_bits), NO_CMD_LINE, OPTION_ALLOW_BATCH, DEFAULT(false));
4976 
4977 static Sys_var_bit Sys_sql_warnings("sql_warnings", "sql_warnings",
4978                                     SESSION_VAR(option_bits), NO_CMD_LINE,
4979                                     OPTION_WARNINGS, DEFAULT(false));
4980 
4981 static Sys_var_bit Sys_sql_notes("sql_notes", "sql_notes",
4982                                  SESSION_VAR(option_bits), NO_CMD_LINE,
4983                                  OPTION_SQL_NOTES, DEFAULT(true));
4984 
4985 static Sys_var_bit Sys_auto_is_null("sql_auto_is_null", "sql_auto_is_null",
4986                                     HINT_UPDATEABLE SESSION_VAR(option_bits),
4987                                     NO_CMD_LINE, OPTION_AUTO_IS_NULL,
4988                                     DEFAULT(false), NO_MUTEX_GUARD, IN_BINLOG);
4989 
4990 static Sys_var_bit Sys_safe_updates("sql_safe_updates", "sql_safe_updates",
4991                                     HINT_UPDATEABLE SESSION_VAR(option_bits),
4992                                     NO_CMD_LINE, OPTION_SAFE_UPDATES,
4993                                     DEFAULT(false));
4994 
4995 static Sys_var_bit Sys_buffer_results("sql_buffer_result", "sql_buffer_result",
4996                                       HINT_UPDATEABLE SESSION_VAR(option_bits),
4997                                       NO_CMD_LINE, OPTION_BUFFER_RESULT,
4998                                       DEFAULT(false));
4999 
5000 static Sys_var_bit Sys_quote_show_create("sql_quote_show_create",
5001                                          "sql_quote_show_create",
5002                                          SESSION_VAR(option_bits), NO_CMD_LINE,
5003                                          OPTION_QUOTE_SHOW_CREATE,
5004                                          DEFAULT(true));
5005 
5006 static Sys_var_bit Sys_foreign_key_checks(
5007     "foreign_key_checks", "foreign_key_checks",
5008     HINT_UPDATEABLE SESSION_VAR(option_bits), NO_CMD_LINE,
5009     REVERSE(OPTION_NO_FOREIGN_KEY_CHECKS), DEFAULT(true), NO_MUTEX_GUARD,
5010     IN_BINLOG);
5011 
5012 static Sys_var_bit Sys_unique_checks("unique_checks", "unique_checks",
5013                                      HINT_UPDATEABLE SESSION_VAR(option_bits),
5014                                      NO_CMD_LINE,
5015                                      REVERSE(OPTION_RELAXED_UNIQUE_CHECKS),
5016                                      DEFAULT(true), NO_MUTEX_GUARD, IN_BINLOG);
5017 
5018 #ifdef ENABLED_PROFILING
5019 static Sys_var_bit Sys_profiling("profiling", "profiling",
5020                                  SESSION_VAR(option_bits), NO_CMD_LINE,
5021                                  OPTION_PROFILING, DEFAULT(false),
5022                                  NO_MUTEX_GUARD, NOT_IN_BINLOG,
5023                                  ON_CHECK(nullptr), ON_UPDATE(nullptr),
5024                                  DEPRECATED_VAR(""));
5025 
5026 static Sys_var_ulong Sys_profiling_history_size(
5027     "profiling_history_size", "Limit of query profiling memory",
5028     SESSION_VAR(profiling_history_size), CMD_LINE(REQUIRED_ARG),
5029     VALID_RANGE(0, 100), DEFAULT(15), BLOCK_SIZE(1), NO_MUTEX_GUARD,
5030     NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(nullptr), DEPRECATED_VAR(""));
5031 #endif
5032 
5033 static Sys_var_harows Sys_select_limit(
5034     "sql_select_limit",
5035     "The maximum number of rows to return from SELECT statements",
5036     HINT_UPDATEABLE SESSION_VAR(select_limit), NO_CMD_LINE,
5037     VALID_RANGE(0, HA_POS_ERROR), DEFAULT(HA_POS_ERROR), BLOCK_SIZE(1));
5038 
update_timestamp(THD * thd,set_var * var)5039 static bool update_timestamp(THD *thd, set_var *var) {
5040   if (var->value) {
5041     double intpart;
5042     double fractpart = modf(var->save_result.double_value, &intpart);
5043     double micros = fractpart * 1000000.0;
5044     // Double multiplication, and conversion to integral may yield
5045     // 1000000 rather than 999999.
5046     struct timeval tmp;
5047     tmp.tv_sec = llrint(intpart);
5048     tmp.tv_usec = std::min(llrint(micros), 999999LL);
5049     thd->set_time(&tmp);
5050   } else  // SET timestamp=DEFAULT
5051   {
5052     thd->user_time.tv_sec = 0;
5053     thd->user_time.tv_usec = 0;
5054   }
5055   return false;
5056 }
read_timestamp(THD * thd)5057 static double read_timestamp(THD *thd) {
5058   return (double)thd->start_time.tv_sec +
5059          (double)thd->start_time.tv_usec / 1000000;
5060 }
5061 
check_timestamp(sys_var *,THD *,set_var * var)5062 static bool check_timestamp(sys_var *, THD *, set_var *var) {
5063   double val;
5064 
5065   if (!var->value) return false;
5066 
5067   val = var->save_result.double_value;
5068   if (val != 0 &&  // this is how you set the default value
5069       (val < TIMESTAMP_MIN_VALUE || val > TIMESTAMP_MAX_VALUE)) {
5070     ErrConvString prm(val);
5071     my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "timestamp", prm.ptr());
5072     return true;
5073   }
5074   return false;
5075 }
5076 
5077 static Sys_var_session_special_double Sys_timestamp(
5078     "timestamp", "Set the time for this client",
5079     HINT_UPDATEABLE sys_var::ONLY_SESSION, NO_CMD_LINE, VALID_RANGE(0, 0),
5080     BLOCK_SIZE(1), NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_timestamp),
5081     ON_UPDATE(update_timestamp), ON_READ(read_timestamp));
5082 
update_last_insert_id(THD * thd,set_var * var)5083 static bool update_last_insert_id(THD *thd, set_var *var) {
5084   if (!var->value) {
5085     my_error(ER_NO_DEFAULT, MYF(0), var->var->name.str);
5086     return true;
5087   }
5088   thd->first_successful_insert_id_in_prev_stmt =
5089       var->save_result.ulonglong_value;
5090   return false;
5091 }
read_last_insert_id(THD * thd)5092 static ulonglong read_last_insert_id(THD *thd) {
5093   return thd->read_first_successful_insert_id_in_prev_stmt();
5094 }
5095 static Sys_var_session_special Sys_last_insert_id(
5096     "last_insert_id", "The value to be returned from LAST_INSERT_ID()",
5097     sys_var::ONLY_SESSION, NO_CMD_LINE, VALID_RANGE(0, ULLONG_MAX),
5098     BLOCK_SIZE(1), NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(nullptr),
5099     ON_UPDATE(update_last_insert_id), ON_READ(read_last_insert_id));
5100 
5101 // alias for last_insert_id(), Sybase-style
5102 static Sys_var_session_special Sys_identity(
5103     "identity", "Synonym for the last_insert_id variable",
5104     sys_var::ONLY_SESSION, NO_CMD_LINE, VALID_RANGE(0, ULLONG_MAX),
5105     BLOCK_SIZE(1), NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(nullptr),
5106     ON_UPDATE(update_last_insert_id), ON_READ(read_last_insert_id));
5107 
5108 /*
5109   insert_id should *not* be marked as written to the binlog (i.e., it
5110   should *not* be IN_BINLOG), because we want any statement that
5111   refers to insert_id explicitly to be unsafe.  (By "explicitly", we
5112   mean using @@session.insert_id, whereas insert_id is used
5113   "implicitly" when NULL value is inserted into an auto_increment
5114   column).
5115 
5116   We want statements referring explicitly to @@session.insert_id to be
5117   unsafe, because insert_id is modified internally by the slave sql
5118   thread when NULL values are inserted in an AUTO_INCREMENT column.
5119   This modification interfers with the value of the
5120   @@session.insert_id variable if @@session.insert_id is referred
5121   explicitly by an insert statement (as is seen by executing "SET
5122   @@session.insert_id=0; CREATE TABLE t (a INT, b INT KEY
5123   AUTO_INCREMENT); INSERT INTO t(a) VALUES (@@session.insert_id);" in
5124   statement-based logging mode: t will be different on master and
5125   slave).
5126 */
update_insert_id(THD * thd,set_var * var)5127 static bool update_insert_id(THD *thd, set_var *var) {
5128   if (!var->value) {
5129     my_error(ER_NO_DEFAULT, MYF(0), var->var->name.str);
5130     return true;
5131   }
5132   thd->force_one_auto_inc_interval(var->save_result.ulonglong_value);
5133   return false;
5134 }
5135 
read_insert_id(THD * thd)5136 static ulonglong read_insert_id(THD *thd) {
5137   return thd->auto_inc_intervals_forced.minimum();
5138 }
5139 static Sys_var_session_special Sys_insert_id(
5140     "insert_id",
5141     "The value to be used by the following INSERT "
5142     "or ALTER TABLE statement when inserting an AUTO_INCREMENT value",
5143     HINT_UPDATEABLE sys_var::ONLY_SESSION, NO_CMD_LINE,
5144     VALID_RANGE(0, ULLONG_MAX), BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG,
5145     ON_CHECK(nullptr), ON_UPDATE(update_insert_id), ON_READ(read_insert_id));
5146 
update_rand_seed1(THD * thd,set_var * var)5147 static bool update_rand_seed1(THD *thd, set_var *var) {
5148   if (!var->value) {
5149     my_error(ER_NO_DEFAULT, MYF(0), var->var->name.str);
5150     return true;
5151   }
5152   thd->rand.seed1 = (ulong)var->save_result.ulonglong_value;
5153   return false;
5154 }
read_rand_seed(THD *)5155 static ulonglong read_rand_seed(THD *) { return 0; }
5156 static Sys_var_session_special Sys_rand_seed1(
5157     "rand_seed1",
5158     "Sets the internal state of the RAND() "
5159     "generator for replication purposes",
5160     sys_var::ONLY_SESSION, NO_CMD_LINE, VALID_RANGE(0, ULONG_MAX),
5161     BLOCK_SIZE(1), NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(nullptr),
5162     ON_UPDATE(update_rand_seed1), ON_READ(read_rand_seed));
5163 
update_rand_seed2(THD * thd,set_var * var)5164 static bool update_rand_seed2(THD *thd, set_var *var) {
5165   if (!var->value) {
5166     my_error(ER_NO_DEFAULT, MYF(0), var->var->name.str);
5167     return true;
5168   }
5169   thd->rand.seed2 = (ulong)var->save_result.ulonglong_value;
5170   return false;
5171 }
5172 static Sys_var_session_special Sys_rand_seed2(
5173     "rand_seed2",
5174     "Sets the internal state of the RAND() "
5175     "generator for replication purposes",
5176     sys_var::ONLY_SESSION, NO_CMD_LINE, VALID_RANGE(0, ULONG_MAX),
5177     BLOCK_SIZE(1), NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(nullptr),
5178     ON_UPDATE(update_rand_seed2), ON_READ(read_rand_seed));
5179 
read_error_count(THD * thd)5180 static ulonglong read_error_count(THD *thd) {
5181   return thd->get_stmt_da()->error_count(thd);
5182 }
5183 // this really belongs to the SHOW STATUS
5184 static Sys_var_session_special Sys_error_count(
5185     "error_count",
5186     "The number of errors that resulted from the "
5187     "last statement that generated messages",
5188     READ_ONLY sys_var::ONLY_SESSION, NO_CMD_LINE, VALID_RANGE(0, ULLONG_MAX),
5189     BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
5190     ON_UPDATE(nullptr), ON_READ(read_error_count));
5191 
read_warning_count(THD * thd)5192 static ulonglong read_warning_count(THD *thd) {
5193   return thd->get_stmt_da()->warn_count(thd);
5194 }
5195 // this really belongs to the SHOW STATUS
5196 static Sys_var_session_special Sys_warning_count(
5197     "warning_count",
5198     "The number of errors, warnings, and notes "
5199     "that resulted from the last statement that generated messages",
5200     READ_ONLY sys_var::ONLY_SESSION, NO_CMD_LINE, VALID_RANGE(0, ULLONG_MAX),
5201     BLOCK_SIZE(1), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
5202     ON_UPDATE(nullptr), ON_READ(read_warning_count));
5203 
5204 static Sys_var_ulong Sys_default_week_format(
5205     "default_week_format", "The default week format used by WEEK() functions",
5206     SESSION_VAR(default_week_format), CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, 7),
5207     DEFAULT(0), BLOCK_SIZE(1));
5208 
5209 static Sys_var_ulong Sys_group_concat_max_len(
5210     "group_concat_max_len",
5211     "The maximum length of the result of function  GROUP_CONCAT()",
5212     HINT_UPDATEABLE SESSION_VAR(group_concat_max_len), CMD_LINE(REQUIRED_ARG),
5213     VALID_RANGE(4, ULONG_MAX), DEFAULT(1024), BLOCK_SIZE(1));
5214 
5215 static char *glob_hostname_ptr;
5216 static Sys_var_charptr Sys_hostname(
5217     "hostname", "Server host name",
5218     READ_ONLY NON_PERSIST GLOBAL_VAR(glob_hostname_ptr), NO_CMD_LINE,
5219     IN_FS_CHARSET, DEFAULT(glob_hostname));
5220 
5221 static Sys_var_charptr Sys_repl_report_host(
5222     "report_host",
5223     "Hostname or IP of the slave to be reported to the master during "
5224     "slave registration. Will appear in the output of SHOW SLAVE HOSTS. "
5225     "Leave unset if you do not want the slave to register itself with the "
5226     "master. Note that it is not sufficient for the master to simply read "
5227     "the IP of the slave off the socket once the slave connects. Due to "
5228     "NAT and other routing issues, that IP may not be valid for connecting "
5229     "to the slave from the master or other hosts",
5230     READ_ONLY GLOBAL_VAR(report_host), CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET,
5231     DEFAULT(nullptr));
5232 
5233 static Sys_var_charptr Sys_repl_report_user(
5234     "report_user",
5235     "The account user name of the slave to be reported to the master "
5236     "during slave registration",
5237     READ_ONLY GLOBAL_VAR(report_user), CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET,
5238     DEFAULT(nullptr));
5239 
5240 static Sys_var_charptr Sys_repl_report_password(
5241     "report_password",
5242     "The account password of the slave to be reported to the master "
5243     "during slave registration",
5244     READ_ONLY GLOBAL_VAR(report_password), CMD_LINE(REQUIRED_ARG),
5245     IN_FS_CHARSET, DEFAULT(nullptr));
5246 
5247 static Sys_var_uint Sys_repl_report_port(
5248     "report_port",
5249     "Port for connecting to slave reported to the master during slave "
5250     "registration. Set it only if the slave is listening on a non-default "
5251     "port or if you have a special tunnel from the master or other clients "
5252     "to the slave. If not sure, leave this option unset",
5253     READ_ONLY GLOBAL_VAR(report_port), CMD_LINE(REQUIRED_ARG),
5254     VALID_RANGE(0, 65535), DEFAULT(0), BLOCK_SIZE(1));
5255 
5256 static Sys_var_bool Sys_keep_files_on_create(
5257     "keep_files_on_create",
5258     "Don't overwrite stale .MYD and .MYI even if no directory is specified",
5259     SESSION_VAR(keep_files_on_create), CMD_LINE(OPT_ARG), DEFAULT(false));
5260 
5261 static char *license;
5262 static Sys_var_charptr Sys_license("license",
5263                                    "The type of license the server has",
5264                                    READ_ONLY NON_PERSIST GLOBAL_VAR(license),
5265                                    NO_CMD_LINE, IN_SYSTEM_CHARSET,
5266                                    DEFAULT(STRINGIFY_ARG(LICENSE)));
5267 
check_log_path(sys_var * self,THD *,set_var * var)5268 static bool check_log_path(sys_var *self, THD *, set_var *var) {
5269   if (!var->value) return false;  // DEFAULT is ok
5270 
5271   if (!var->save_result.string_value.str) return true;
5272 
5273   if (!is_valid_log_name(var->save_result.string_value.str,
5274                          var->save_result.string_value.length)) {
5275     my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), self->name.str,
5276              var->save_result.string_value.str);
5277     return true;
5278   }
5279 
5280   if (var->save_result.string_value.length > FN_REFLEN) {  // path is too long
5281     my_error(ER_PATH_LENGTH, MYF(0), self->name.str);
5282     return true;
5283   }
5284 
5285   char path[FN_REFLEN];
5286   size_t path_length = unpack_filename(path, var->save_result.string_value.str);
5287 
5288   if (!path_length) return true;
5289 
5290   if (!is_filename_allowed(var->save_result.string_value.str,
5291                            var->save_result.string_value.length, true)) {
5292     my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), self->name.str,
5293              var->save_result.string_value.str);
5294     return true;
5295   }
5296 
5297   MY_STAT f_stat;
5298 
5299   if (my_stat(path, &f_stat, MYF(0))) {
5300     if (!MY_S_ISREG(f_stat.st_mode) || !(f_stat.st_mode & MY_S_IWRITE))
5301       return true;  // not a regular writable file
5302     return false;
5303   }
5304 
5305   (void)dirname_part(path, var->save_result.string_value.str, &path_length);
5306 
5307   if (var->save_result.string_value.length - path_length >=
5308       FN_LEN) {  // filename is too long
5309     my_error(ER_PATH_LENGTH, MYF(0), self->name.str);
5310     return true;
5311   }
5312 
5313   if (!path_length)  // no path is good path (remember, relative to datadir)
5314     return false;
5315 
5316   if (my_access(path, (F_OK | W_OK))) return true;  // directory is not writable
5317 
5318   return false;
5319 }
5320 
fix_general_log_file(sys_var *,THD *,enum_var_type)5321 static bool fix_general_log_file(sys_var *, THD *, enum_var_type) {
5322   bool res;
5323 
5324   if (!opt_general_logname)  // SET ... = DEFAULT
5325   {
5326     char buff[FN_REFLEN];
5327     opt_general_logname = my_strdup(
5328         key_memory_LOG_name, make_query_log_name(buff, QUERY_LOG_GENERAL),
5329         MYF(MY_FAE + MY_WME));
5330     if (!opt_general_logname) return true;
5331   }
5332 
5333   res = query_logger.set_log_file(QUERY_LOG_GENERAL);
5334 
5335   if (opt_general_log) {
5336     mysql_mutex_unlock(&LOCK_global_system_variables);
5337 
5338     if (!res)
5339       res = query_logger.reopen_log_file(QUERY_LOG_GENERAL);
5340     else
5341       query_logger.deactivate_log_handler(QUERY_LOG_GENERAL);
5342 
5343     mysql_mutex_lock(&LOCK_global_system_variables);
5344   }
5345 
5346   if (res) opt_general_log = false;
5347 
5348   return res;
5349 }
5350 
5351 static Sys_var_charptr Sys_general_log_path(
5352     "general_log_file", "Log connections and queries to given file",
5353     GLOBAL_VAR(opt_general_logname), CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET,
5354     DEFAULT(nullptr), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_log_path),
5355     ON_UPDATE(fix_general_log_file));
5356 
fix_slow_log_file(sys_var *,THD * thd MY_ATTRIBUTE ((unused)),enum_var_type)5357 static bool fix_slow_log_file(sys_var *, THD *thd MY_ATTRIBUTE((unused)),
5358                               enum_var_type) {
5359   bool res;
5360 
5361   DEBUG_SYNC(thd, "log_fix_slow_log_holds_sysvar_lock");
5362 
5363   if (!opt_slow_logname)  // SET ... = DEFAULT
5364   {
5365     char buff[FN_REFLEN];
5366     opt_slow_logname = my_strdup(key_memory_LOG_name,
5367                                  make_query_log_name(buff, QUERY_LOG_SLOW),
5368                                  MYF(MY_FAE + MY_WME));
5369     if (!opt_slow_logname) return true;
5370   }
5371 
5372   res = query_logger.set_log_file(QUERY_LOG_SLOW);
5373 
5374   DEBUG_SYNC(thd, "log_fix_slow_log_released_logger_lock");
5375 
5376   if (opt_slow_log) {
5377     mysql_mutex_unlock(&LOCK_global_system_variables);
5378 
5379     DEBUG_SYNC(thd, "log_fix_slow_log_released_sysvar_lock");
5380 
5381     if (!res)
5382       res = query_logger.reopen_log_file(QUERY_LOG_SLOW);
5383     else
5384       query_logger.deactivate_log_handler(QUERY_LOG_SLOW);
5385 
5386     mysql_mutex_lock(&LOCK_global_system_variables);
5387   }
5388 
5389   if (res) opt_slow_log = false;
5390 
5391   return res;
5392 }
5393 static Sys_var_charptr Sys_slow_log_path(
5394     "slow_query_log_file",
5395     "Log slow queries to given log file. "
5396     "Defaults logging to hostname-slow.log. Must be enabled to activate "
5397     "other slow log options",
5398     GLOBAL_VAR(opt_slow_logname), CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET,
5399     DEFAULT(nullptr), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_log_path),
5400     ON_UPDATE(fix_slow_log_file));
5401 
5402 static Sys_var_have Sys_have_compress(
5403     "have_compress", "have_compress",
5404     READ_ONLY NON_PERSIST GLOBAL_VAR(have_compress), NO_CMD_LINE);
5405 
5406 static Sys_var_have Sys_have_dlopen(
5407     "have_dynamic_loading", "have_dynamic_loading",
5408     READ_ONLY NON_PERSIST GLOBAL_VAR(have_dlopen), NO_CMD_LINE);
5409 
5410 static Sys_var_have Sys_have_geometry(
5411     "have_geometry", "have_geometry",
5412     READ_ONLY NON_PERSIST GLOBAL_VAR(have_geometry), NO_CMD_LINE);
5413 
have_ssl_func(THD * thd MY_ATTRIBUTE ((unused)))5414 static SHOW_COMP_OPTION have_ssl_func(THD *thd MY_ATTRIBUTE((unused))) {
5415   return have_ssl() ? SHOW_OPTION_YES : SHOW_OPTION_DISABLED;
5416 }
5417 
5418 enum SHOW_COMP_OPTION Sys_var_have_func::dummy_;
5419 
5420 static Sys_var_have_func Sys_have_openssl("have_openssl", "have_openssl",
5421                                           have_ssl_func);
5422 
5423 static Sys_var_have Sys_have_profiling(
5424     "have_profiling", "have_profiling",
5425     READ_ONLY NON_PERSIST GLOBAL_VAR(have_profiling), NO_CMD_LINE,
5426     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(nullptr),
5427     DEPRECATED_VAR(""));
5428 
5429 static Sys_var_have Sys_have_query_cache(
5430     "have_query_cache",
5431     "have_query_cache. "
5432     "This variable is deprecated and will be removed in a future release.",
5433     READ_ONLY NON_PERSIST GLOBAL_VAR(have_query_cache), NO_CMD_LINE,
5434     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(nullptr),
5435     DEPRECATED_VAR(""));
5436 
5437 static Sys_var_have Sys_have_rtree_keys(
5438     "have_rtree_keys", "have_rtree_keys",
5439     READ_ONLY NON_PERSIST GLOBAL_VAR(have_rtree_keys), NO_CMD_LINE);
5440 
5441 static Sys_var_have_func Sys_have_ssl("have_ssl", "have_ssl", have_ssl_func);
5442 
5443 static Sys_var_have Sys_have_symlink(
5444     "have_symlink", "have_symlink",
5445     READ_ONLY NON_PERSIST GLOBAL_VAR(have_symlink), NO_CMD_LINE);
5446 
5447 static Sys_var_have Sys_have_statement_timeout(
5448     "have_statement_timeout", "have_statement_timeout",
5449     READ_ONLY NON_PERSIST GLOBAL_VAR(have_statement_timeout), NO_CMD_LINE);
5450 
fix_general_log_state(sys_var *,THD * thd,enum_var_type)5451 static bool fix_general_log_state(sys_var *, THD *thd, enum_var_type) {
5452   bool new_state = opt_general_log, res = false;
5453 
5454   if (query_logger.is_log_file_enabled(QUERY_LOG_GENERAL) == new_state)
5455     return false;
5456 
5457   mysql_mutex_unlock(&LOCK_global_system_variables);
5458 
5459   if (!new_state) {
5460     query_logger.deactivate_log_handler(QUERY_LOG_GENERAL);
5461   } else {
5462     res = query_logger.activate_log_handler(thd, QUERY_LOG_GENERAL);
5463   }
5464 
5465   mysql_mutex_lock(&LOCK_global_system_variables);
5466 
5467   if (res) opt_general_log = false;
5468 
5469   return res;
5470 }
5471 static Sys_var_bool Sys_general_log(
5472     "general_log",
5473     "Log connections and queries to a table or log file. "
5474     "Defaults to logging to a file hostname.log, "
5475     "or if --log-output=TABLE is used, to a table mysql.general_log.",
5476     GLOBAL_VAR(opt_general_log), CMD_LINE(OPT_ARG), DEFAULT(false),
5477     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
5478     ON_UPDATE(fix_general_log_state));
5479 
5480 static Sys_var_bool Sys_log_raw(
5481     "log_raw",
5482     "Log to general log before any rewriting of the query. For use in "
5483     "debugging, not production as sensitive information may be logged.",
5484     GLOBAL_VAR(opt_general_log_raw), CMD_LINE(OPT_ARG), DEFAULT(false),
5485     NO_MUTEX_GUARD, NOT_IN_BINLOG);
5486 
fix_slow_log_state(sys_var *,THD * thd,enum_var_type)5487 static bool fix_slow_log_state(sys_var *, THD *thd, enum_var_type) {
5488   bool new_state = opt_slow_log, res = false;
5489 
5490   if (query_logger.is_log_file_enabled(QUERY_LOG_SLOW) == new_state)
5491     return false;
5492 
5493   mysql_mutex_unlock(&LOCK_global_system_variables);
5494 
5495   if (!new_state) {
5496     query_logger.deactivate_log_handler(QUERY_LOG_SLOW);
5497   } else {
5498     res = query_logger.activate_log_handler(thd, QUERY_LOG_SLOW);
5499   }
5500 
5501   mysql_mutex_lock(&LOCK_global_system_variables);
5502 
5503   if (res) opt_slow_log = false;
5504 
5505   return res;
5506 }
5507 static Sys_var_bool Sys_slow_query_log(
5508     "slow_query_log",
5509     "Log slow queries to a table or log file. Defaults logging to a file "
5510     "hostname-slow.log or a table mysql.slow_log if --log-output=TABLE is "
5511     "used. Must be enabled to activate other slow log options",
5512     GLOBAL_VAR(opt_slow_log), CMD_LINE(OPT_ARG), DEFAULT(false), NO_MUTEX_GUARD,
5513     NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(fix_slow_log_state));
5514 
check_slow_log_extra(sys_var *,THD * thd,set_var *)5515 static bool check_slow_log_extra(sys_var *, THD *thd, set_var *) {
5516   // If FILE is not one of the log-targets, succeed but warn!
5517   if (!(log_output_options & LOG_FILE))
5518     push_warning(
5519         thd, Sql_condition::SL_WARNING,
5520         ER_SLOW_LOG_MODE_IGNORED_WHEN_NOT_LOGGING_TO_FILE,
5521         ER_THD(thd, ER_SLOW_LOG_MODE_IGNORED_WHEN_NOT_LOGGING_TO_FILE));
5522 
5523   return false;
5524 }
5525 
5526 static Sys_var_bool Sys_slow_log_extra(
5527     "log_slow_extra",
5528     "Print more attributes to the slow query log file. Has no effect on "
5529     "logging to table.",
5530     GLOBAL_VAR(opt_log_slow_extra), CMD_LINE(OPT_ARG), DEFAULT(false),
5531     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_slow_log_extra),
5532     ON_UPDATE(nullptr));
5533 
check_not_empty_set(sys_var *,THD *,set_var * var)5534 static bool check_not_empty_set(sys_var *, THD *, set_var *var) {
5535   return var->save_result.ulonglong_value == 0;
5536 }
fix_log_output(sys_var *,THD *,enum_var_type)5537 static bool fix_log_output(sys_var *, THD *, enum_var_type) {
5538   query_logger.set_handlers(static_cast<uint>(log_output_options));
5539   return false;
5540 }
5541 
5542 static const char *log_output_names[] = {"NONE", "FILE", "TABLE", nullptr};
5543 
5544 static Sys_var_set Sys_log_output(
5545     "log_output",
5546     "Syntax: log-output=value[,value...], "
5547     "where \"value\" could be TABLE, FILE or NONE",
5548     GLOBAL_VAR(log_output_options), CMD_LINE(REQUIRED_ARG), log_output_names,
5549     DEFAULT(LOG_FILE), NO_MUTEX_GUARD, NOT_IN_BINLOG,
5550     ON_CHECK(check_not_empty_set), ON_UPDATE(fix_log_output));
5551 
5552 static Sys_var_bool Sys_log_slave_updates(
5553     "log_slave_updates",
5554     "Tells the slave to log the updates from "
5555     "the slave thread to the binary log.",
5556     READ_ONLY GLOBAL_VAR(opt_log_slave_updates),
5557     CMD_LINE(OPT_ARG, OPT_LOG_SLAVE_UPDATES), DEFAULT(1));
5558 
5559 static Sys_var_charptr Sys_relay_log(
5560     "relay_log", "The location and name to use for relay logs",
5561     READ_ONLY NON_PERSIST GLOBAL_VAR(opt_relay_logname), CMD_LINE(REQUIRED_ARG),
5562     IN_FS_CHARSET, DEFAULT(nullptr));
5563 
5564 /*
5565   Uses NO_CMD_LINE since the --relay-log-index option set
5566   opt_relaylog_index_name variable and computes a value for the
5567   relay_log_index variable.
5568 */
5569 static Sys_var_charptr Sys_relay_log_index(
5570     "relay_log_index",
5571     "The location and name to use for the file "
5572     "that keeps a list of the last relay logs",
5573     READ_ONLY NON_PERSIST GLOBAL_VAR(relay_log_index), NO_CMD_LINE,
5574     IN_FS_CHARSET, DEFAULT(nullptr));
5575 
5576 /*
5577   Uses NO_CMD_LINE since the --log-bin-index option set
5578   opt_binlog_index_name variable and computes a value for the
5579   log_bin_index variable.
5580 */
5581 static Sys_var_charptr Sys_binlog_index(
5582     "log_bin_index", "File that holds the names for last binary log files.",
5583     READ_ONLY NON_PERSIST GLOBAL_VAR(log_bin_index), NO_CMD_LINE, IN_FS_CHARSET,
5584     DEFAULT(nullptr));
5585 
5586 static Sys_var_charptr Sys_relay_log_basename(
5587     "relay_log_basename",
5588     "The full path of the relay log file names, excluding the extension.",
5589     READ_ONLY NON_PERSIST GLOBAL_VAR(relay_log_basename), NO_CMD_LINE,
5590     IN_FS_CHARSET, DEFAULT(nullptr));
5591 
5592 static Sys_var_charptr Sys_log_bin_basename(
5593     "log_bin_basename",
5594     "The full path of the binary log file names, excluding the extension.",
5595     READ_ONLY NON_PERSIST GLOBAL_VAR(log_bin_basename), NO_CMD_LINE,
5596     IN_FS_CHARSET, DEFAULT(nullptr));
5597 
5598 static Sys_var_charptr Sys_relay_log_info_file(
5599     "relay_log_info_file",
5600     "The location and name of the file that "
5601     "remembers where the SQL replication thread is in the relay logs",
5602     READ_ONLY NON_PERSIST GLOBAL_VAR(relay_log_info_file),
5603     CMD_LINE(REQUIRED_ARG, OPT_RELAY_LOG_INFO_FILE), IN_FS_CHARSET,
5604     DEFAULT(nullptr), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
5605     ON_UPDATE(nullptr), DEPRECATED_VAR(""));
5606 
5607 static Sys_var_bool Sys_relay_log_purge(
5608     "relay_log_purge",
5609     "if disabled - do not purge relay logs. "
5610     "if enabled - purge them as soon as they are no more needed",
5611     GLOBAL_VAR(relay_log_purge), CMD_LINE(OPT_ARG), DEFAULT(true));
5612 
5613 static Sys_var_bool Sys_relay_log_recovery(
5614     "relay_log_recovery",
5615     "Enables automatic relay log recovery "
5616     "right after the database startup, which means that the IO Thread "
5617     "starts re-fetching from the master right after the last transaction "
5618     "processed",
5619     READ_ONLY GLOBAL_VAR(relay_log_recovery), CMD_LINE(OPT_ARG),
5620     DEFAULT(false));
5621 
5622 static Sys_var_ulong Sys_rpl_read_size(
5623     "rpl_read_size",
5624     "The size for reads done from the binlog and relay log. "
5625     "It must be a multiple of 4kb. Making it larger might help with IO "
5626     "stalls while reading these files when they are not in the OS buffer "
5627     "cache",
5628     GLOBAL_VAR(rpl_read_size), CMD_LINE(REQUIRED_ARG),
5629     VALID_RANGE(IO_SIZE * 2, ULONG_MAX), DEFAULT(IO_SIZE * 2),
5630     BLOCK_SIZE(IO_SIZE));
5631 
5632 static Sys_var_bool Sys_slave_allow_batching(
5633     "slave_allow_batching", "Allow slave to batch requests",
5634     GLOBAL_VAR(opt_slave_allow_batching), CMD_LINE(OPT_ARG), DEFAULT(false));
5635 
5636 static Sys_var_charptr Sys_slave_load_tmpdir(
5637     "slave_load_tmpdir",
5638     "The location where the slave should put "
5639     "its temporary files when replicating a LOAD DATA INFILE command",
5640     READ_ONLY NON_PERSIST GLOBAL_VAR(slave_load_tmpdir), CMD_LINE(REQUIRED_ARG),
5641     IN_FS_CHARSET, DEFAULT(nullptr));
5642 
fix_slave_net_timeout(sys_var *,THD * thd,enum_var_type)5643 static bool fix_slave_net_timeout(sys_var *, THD *thd, enum_var_type) {
5644   DEBUG_SYNC(thd, "fix_slave_net_timeout");
5645   Master_info *mi;
5646 
5647   /* @TODO: slave net timeout is for all channels, but does this make
5648            sense?
5649    */
5650 
5651   /*
5652    Here we have lock on LOCK_global_system_variables and we need
5653     lock on channel_map lock. In START_SLAVE handler, we take these
5654     two locks in different order. This can lead to DEADLOCKs. See
5655     BUG#14236151 for more details.
5656    So we release lock on LOCK_global_system_variables before acquiring
5657     lock on channel_map lock. But this could lead to isolation issues
5658     between multiple setters. Hence introducing secondary guard
5659     for this global variable and releasing the lock here and acquiring
5660     locks back again at the end of this function.
5661    */
5662   mysql_mutex_unlock(&LOCK_slave_net_timeout);
5663   mysql_mutex_unlock(&LOCK_global_system_variables);
5664   channel_map.wrlock();
5665 
5666   for (mi_map::iterator it = channel_map.begin(); it != channel_map.end();
5667        it++) {
5668     mi = it->second;
5669 
5670     DBUG_PRINT("info", ("slave_net_timeout=%u mi->heartbeat_period=%.3f",
5671                         slave_net_timeout, (mi ? mi->heartbeat_period : 0.0)));
5672     if (mi != nullptr && slave_net_timeout < mi->heartbeat_period)
5673       push_warning(thd, Sql_condition::SL_WARNING,
5674                    ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX,
5675                    ER_THD(thd, ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE_MAX));
5676   }
5677 
5678   channel_map.unlock();
5679   mysql_mutex_lock(&LOCK_global_system_variables);
5680   mysql_mutex_lock(&LOCK_slave_net_timeout);
5681   return false;
5682 }
5683 static PolyLock_mutex PLock_slave_net_timeout(&LOCK_slave_net_timeout);
5684 static Sys_var_uint Sys_slave_net_timeout(
5685     "slave_net_timeout",
5686     "Number of seconds to wait for more data "
5687     "from a master/slave connection before aborting the read",
5688     GLOBAL_VAR(slave_net_timeout), CMD_LINE(REQUIRED_ARG),
5689     VALID_RANGE(1, LONG_TIMEOUT), DEFAULT(SLAVE_NET_TIMEOUT), BLOCK_SIZE(1),
5690     &PLock_slave_net_timeout, NOT_IN_BINLOG, ON_CHECK(nullptr),
5691     ON_UPDATE(fix_slave_net_timeout));
5692 
check_slave_skip_counter(sys_var *,THD *,set_var *)5693 static bool check_slave_skip_counter(sys_var *, THD *, set_var *) {
5694   /*
5695     @todo: move this check into the set function and hold the lock on
5696     Gtid_mode::lock until the operation has completed, so that we are
5697     sure a concurrent connection does not change gtid_mode between
5698     check and fix.
5699   */
5700   if (global_gtid_mode.get() == Gtid_mode::ON) {
5701     my_error(ER_SQL_SLAVE_SKIP_COUNTER_NOT_SETTABLE_IN_GTID_MODE, MYF(0));
5702     return true;
5703   }
5704 
5705   return false;
5706 }
5707 
5708 static PolyLock_mutex PLock_sql_slave_skip_counter(
5709     &LOCK_sql_slave_skip_counter);
5710 static Sys_var_uint Sys_slave_skip_counter(
5711     "sql_slave_skip_counter", "sql_slave_skip_counter",
5712     GLOBAL_VAR(sql_slave_skip_counter), NO_CMD_LINE, VALID_RANGE(0, UINT_MAX),
5713     DEFAULT(0), BLOCK_SIZE(1), &PLock_sql_slave_skip_counter, NOT_IN_BINLOG,
5714     ON_CHECK(check_slave_skip_counter));
5715 
5716 static Sys_var_charptr Sys_slave_skip_errors(
5717     "slave_skip_errors",
5718     "Tells the slave thread to continue "
5719     "replication when a query event returns an error from the "
5720     "provided list",
5721     READ_ONLY GLOBAL_VAR(opt_slave_skip_errors), CMD_LINE(REQUIRED_ARG),
5722     IN_SYSTEM_CHARSET, DEFAULT(nullptr));
5723 
5724 static Sys_var_ulonglong Sys_relay_log_space_limit(
5725     "relay_log_space_limit", "Maximum space to use for all relay logs",
5726     READ_ONLY GLOBAL_VAR(relay_log_space_limit), CMD_LINE(REQUIRED_ARG),
5727     VALID_RANGE(0, ULONG_MAX), DEFAULT(0), BLOCK_SIZE(1));
5728 
5729 static Sys_var_uint Sys_sync_relaylog_period(
5730     "sync_relay_log",
5731     "Synchronously flush relay log to disk after "
5732     "every #th event. Use 0 to disable synchronous flushing",
5733     GLOBAL_VAR(sync_relaylog_period), CMD_LINE(REQUIRED_ARG),
5734     VALID_RANGE(0, UINT_MAX), DEFAULT(10000), BLOCK_SIZE(1));
5735 
5736 static Sys_var_uint Sys_sync_relayloginfo_period(
5737     "sync_relay_log_info",
5738     "Synchronously flush relay log info "
5739     "to disk after every #th transaction. Use 0 to disable "
5740     "synchronous flushing",
5741     GLOBAL_VAR(sync_relayloginfo_period), CMD_LINE(REQUIRED_ARG),
5742     VALID_RANGE(0, UINT_MAX), DEFAULT(10000), BLOCK_SIZE(1));
5743 
5744 static Sys_var_uint Sys_checkpoint_mts_period(
5745     "slave_checkpoint_period",
5746     "Gather workers' activities to "
5747     "Update progress status of Multi-threaded slave and flush "
5748     "the relay log info to disk after every #th milli-seconds.",
5749     GLOBAL_VAR(opt_mts_checkpoint_period), CMD_LINE(REQUIRED_ARG),
5750 #ifndef DBUG_OFF
5751     VALID_RANGE(0, UINT_MAX), DEFAULT(300), BLOCK_SIZE(1));
5752 #else
5753     VALID_RANGE(1, UINT_MAX), DEFAULT(300), BLOCK_SIZE(1));
5754 #endif /* DBUG_OFF */
5755 
5756 static Sys_var_uint Sys_checkpoint_mts_group(
5757     "slave_checkpoint_group",
5758     "Maximum number of processed transactions by Multi-threaded slave "
5759     "before a checkpoint operation is called to update progress status.",
5760     GLOBAL_VAR(opt_mts_checkpoint_group), CMD_LINE(REQUIRED_ARG),
5761 #ifndef DBUG_OFF
5762     VALID_RANGE(1, MTS_MAX_BITS_IN_GROUP), DEFAULT(512), BLOCK_SIZE(1));
5763 #else
5764     VALID_RANGE(32, MTS_MAX_BITS_IN_GROUP), DEFAULT(512), BLOCK_SIZE(8));
5765 #endif /* DBUG_OFF */
5766 
5767 static Sys_var_uint Sys_sync_binlog_period(
5768     "sync_binlog",
5769     "Synchronously flush binary log to disk after"
5770     " every #th write to the file. Use 0 to disable synchronous"
5771     " flushing",
5772     GLOBAL_VAR(sync_binlog_period), CMD_LINE(REQUIRED_ARG),
5773     VALID_RANGE(0, UINT_MAX), DEFAULT(1), BLOCK_SIZE(1));
5774 
5775 static Sys_var_uint Sys_sync_masterinfo_period(
5776     "sync_master_info",
5777     "Synchronously flush master info to disk "
5778     "after every #th event. Use 0 to disable synchronous flushing",
5779     GLOBAL_VAR(sync_masterinfo_period), CMD_LINE(REQUIRED_ARG),
5780     VALID_RANGE(0, UINT_MAX), DEFAULT(10000), BLOCK_SIZE(1));
5781 
5782 static Sys_var_ulonglong Sys_var_original_commit_timestamp(
5783     "original_commit_timestamp",
5784     "The time when the current transaction was committed on the originating "
5785     "replication master, measured in microseconds since the epoch.",
5786     SESSION_ONLY(original_commit_timestamp), NO_CMD_LINE,
5787     VALID_RANGE(0, MAX_COMMIT_TIMESTAMP_VALUE),
5788     DEFAULT(MAX_COMMIT_TIMESTAMP_VALUE), BLOCK_SIZE(1), NO_MUTEX_GUARD,
5789     IN_BINLOG, ON_CHECK(check_session_admin_or_replication_applier));
5790 
5791 static Sys_var_ulong Sys_slave_trans_retries(
5792     "slave_transaction_retries",
5793     "Number of times the slave SQL "
5794     "thread will retry a transaction in case it failed with a deadlock "
5795     "or elapsed lock wait timeout, before giving up and stopping",
5796     GLOBAL_VAR(slave_trans_retries), CMD_LINE(REQUIRED_ARG),
5797     VALID_RANGE(0, ULONG_MAX), DEFAULT(10), BLOCK_SIZE(1));
5798 
5799 static Sys_var_ulong Sys_slave_parallel_workers(
5800     "slave_parallel_workers",
5801     "Number of worker threads for executing events in parallel ",
5802     PERSIST_AS_READONLY GLOBAL_VAR(opt_mts_slave_parallel_workers),
5803     CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, MTS_MAX_WORKERS), DEFAULT(0),
5804     BLOCK_SIZE(1));
5805 
5806 static Sys_var_ulonglong Sys_mts_pending_jobs_size_max(
5807     "slave_pending_jobs_size_max",
5808     "Max size of Slave Worker queues holding not yet applied events. "
5809     "The least possible value must be not less than the master side "
5810     "max_allowed_packet.",
5811     GLOBAL_VAR(opt_mts_pending_jobs_size_max), CMD_LINE(REQUIRED_ARG),
5812     VALID_RANGE(1024, (ulonglong) ~(intptr)0), DEFAULT(128 * 1024 * 1024),
5813     BLOCK_SIZE(1024), ON_CHECK(nullptr));
5814 
check_locale(sys_var * self,THD * thd,set_var * var)5815 static bool check_locale(sys_var *self, THD *thd, set_var *var) {
5816   if (!var->value) return false;
5817 
5818   MY_LOCALE *locale;
5819   char buff[STRING_BUFFER_USUAL_SIZE];
5820   if (var->value->result_type() == INT_RESULT) {
5821     int lcno = (int)var->value->val_int();
5822     if (!(locale = my_locale_by_number(lcno))) {
5823       my_error(ER_UNKNOWN_LOCALE, MYF(0), llstr(lcno, buff));
5824       return true;
5825     }
5826     if (check_not_null(self, thd, var)) return true;
5827   } else  // STRING_RESULT
5828   {
5829     String str(buff, sizeof(buff), system_charset_info), *res;
5830     if (!(res = var->value->val_str(&str)))
5831       return true;
5832     else if (!(locale = my_locale_by_name(thd, res->ptr(), res->length()))) {
5833       ErrConvString err(res);
5834       my_error(ER_UNKNOWN_LOCALE, MYF(0), err.ptr());
5835       return true;
5836     }
5837   }
5838 
5839   var->save_result.ptr = locale;
5840 
5841   if (!locale->errmsgs->is_loaded()) {
5842     mysql_mutex_lock(&LOCK_error_messages);
5843     if (!locale->errmsgs->is_loaded() && locale->errmsgs->read_texts()) {
5844       push_warning_printf(thd, Sql_condition::SL_WARNING, ER_UNKNOWN_ERROR,
5845                           "Can't process error message file for locale '%s'",
5846                           locale->name);
5847       mysql_mutex_unlock(&LOCK_error_messages);
5848       return true;
5849     }
5850     mysql_mutex_unlock(&LOCK_error_messages);
5851   }
5852   return false;
5853 }
5854 
5855 namespace {
5856 struct Get_locale_name {
Get_locale_name__anon9d05e1790211::Get_locale_name5857   explicit Get_locale_name(const MY_LOCALE *ml) : m_ml(ml) {}
get_name__anon9d05e1790211::Get_locale_name5858   const uchar *get_name() const {
5859     return pointer_cast<const uchar *>(m_ml->name);
5860   }
5861   const MY_LOCALE *m_ml;
5862 };
5863 }  // namespace
5864 
5865 static Sys_var_struct<MY_LOCALE, Get_locale_name> Sys_lc_messages(
5866     "lc_messages", "Set the language used for the error messages",
5867     SESSION_VAR(lc_messages), NO_CMD_LINE, DEFAULT(&my_default_lc_messages),
5868     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_locale));
5869 
5870 static Sys_var_struct<MY_LOCALE, Get_locale_name> Sys_lc_time_names(
5871     "lc_time_names",
5872     "Set the language used for the month "
5873     "names and the days of the week",
5874     SESSION_VAR(lc_time_names), NO_CMD_LINE, DEFAULT(&my_default_lc_time_names),
5875     NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_locale));
5876 
5877 static Sys_var_tz Sys_time_zone("time_zone", "time_zone",
5878                                 HINT_UPDATEABLE SESSION_VAR(time_zone),
5879                                 NO_CMD_LINE, DEFAULT(&default_tz),
5880                                 NO_MUTEX_GUARD, IN_BINLOG);
5881 
fix_host_cache_size(sys_var *,THD *,enum_var_type)5882 static bool fix_host_cache_size(sys_var *, THD *, enum_var_type) {
5883   hostname_cache_resize(host_cache_size);
5884   return false;
5885 }
5886 
5887 static Sys_var_uint Sys_host_cache_size(
5888     "host_cache_size",
5889     "How many host names should be cached to avoid resolving.",
5890     GLOBAL_VAR(host_cache_size), CMD_LINE(REQUIRED_ARG, OPT_HOST_CACHE_SIZE),
5891     VALID_RANGE(0, 65536), DEFAULT(HOST_CACHE_SIZE), BLOCK_SIZE(1),
5892     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
5893     ON_UPDATE(fix_host_cache_size));
5894 
5895 const Sys_var_multi_enum::ALIAS enforce_gtid_consistency_aliases[] = {
5896     {"OFF", 0},   {"ON", 1},   {"WARN", 2},
5897     {"FALSE", 0}, {"TRUE", 1}, {nullptr, 0}};
5898 static Sys_var_enforce_gtid_consistency Sys_enforce_gtid_consistency(
5899     "enforce_gtid_consistency",
5900     "Prevents execution of statements that would be impossible to log "
5901     "in a transactionally safe manner. Currently, the disallowed "
5902     "statements include CREATE TEMPORARY TABLE inside transactions, "
5903     "all updates to non-transactional tables, and CREATE TABLE ... SELECT.",
5904     PERSIST_AS_READONLY GLOBAL_VAR(_gtid_consistency_mode),
5905     CMD_LINE(OPT_ARG, OPT_ENFORCE_GTID_CONSISTENCY),
5906     enforce_gtid_consistency_aliases, 3,
5907     DEFAULT(3 /*position of "FALSE" in enforce_gtid_consistency_aliases*/),
5908     DEFAULT(GTID_CONSISTENCY_MODE_ON), NO_MUTEX_GUARD, NOT_IN_BINLOG,
5909     ON_CHECK(check_session_admin_outside_trx_outside_sf_outside_sp));
fixup_enforce_gtid_consistency_command_line(char * value_arg)5910 const char *fixup_enforce_gtid_consistency_command_line(char *value_arg) {
5911   return Sys_enforce_gtid_consistency.fixup_command_line(value_arg);
5912 }
5913 
5914 static Sys_var_bool Sys_binlog_gtid_simple_recovery(
5915     "binlog_gtid_simple_recovery",
5916     "If this option is enabled, the server does not open more than "
5917     "two binary logs when initializing GTID_PURGED and "
5918     "GTID_EXECUTED, either during server restart or when binary "
5919     "logs are being purged. Enabling this option is useful when "
5920     "the server has already generated many binary logs without "
5921     "GTID events (e.g., having GTID_MODE = OFF). Note: If this "
5922     "option is enabled, GLOBAL.GTID_EXECUTED and "
5923     "GLOBAL.GTID_PURGED may be initialized wrongly in two cases: "
5924     "(1) All binary logs were generated by MySQL 5.7.5 or older, "
5925     "and GTID_MODE was ON for some binary logs but OFF for the "
5926     "newest binary log. (2) The oldest existing binary log was "
5927     "generated by MySQL 5.7.5 or older, and SET GTID_PURGED was "
5928     "issued after the oldest binary log was generated. If a wrong "
5929     "set is computed in one of case (1) or case (2), it will "
5930     "remain wrong even if the server is later restarted with this "
5931     "option disabled.",
5932     READ_ONLY GLOBAL_VAR(binlog_gtid_simple_recovery), CMD_LINE(OPT_ARG),
5933     DEFAULT(true));
5934 
5935 static Sys_var_ulong Sys_sp_cache_size(
5936     "stored_program_cache",
5937     "The soft upper limit for number of cached stored routines for "
5938     "one connection.",
5939     GLOBAL_VAR(stored_program_cache_size), CMD_LINE(REQUIRED_ARG),
5940     VALID_RANGE(16, 512 * 1024), DEFAULT(256), BLOCK_SIZE(1));
5941 
check_pseudo_slave_mode(sys_var * self,THD * thd,set_var * var)5942 static bool check_pseudo_slave_mode(sys_var *self, THD *thd, set_var *var) {
5943   if (check_session_admin_or_replication_applier(self, thd, var)) return true;
5944   if (check_outside_trx(self, thd, var)) return true;
5945   longlong previous_val = thd->variables.pseudo_slave_mode;
5946   longlong val = (longlong)var->save_result.ulonglong_value;
5947   bool rli_fake = false;
5948 
5949   rli_fake = thd->rli_fake ? true : false;
5950 
5951   if (rli_fake) {
5952     if (!val) {
5953       thd->rli_fake->end_info();
5954       delete thd->rli_fake;
5955       thd->rli_fake = nullptr;
5956     } else if (previous_val && val)
5957       goto ineffective;
5958     else if (!previous_val && val)
5959       push_warning(thd, Sql_condition::SL_WARNING, ER_WRONG_VALUE_FOR_VAR,
5960                    "'pseudo_slave_mode' is already ON.");
5961   } else {
5962     if (!previous_val && !val)
5963       goto ineffective;
5964     else if (previous_val && !val)
5965       push_warning(thd, Sql_condition::SL_WARNING, ER_WRONG_VALUE_FOR_VAR,
5966                    "Slave applier execution mode not active, "
5967                    "statement ineffective.");
5968   }
5969   goto end;
5970 
5971 ineffective:
5972   push_warning(thd, Sql_condition::SL_WARNING, ER_WRONG_VALUE_FOR_VAR,
5973                "'pseudo_slave_mode' change was ineffective.");
5974 
5975 end:
5976   return false;
5977 }
5978 static Sys_var_bool Sys_pseudo_slave_mode(
5979     "pseudo_slave_mode",
5980     "SET pseudo_slave_mode= 0,1 are commands that mysqlbinlog "
5981     "adds to beginning and end of binary log dumps. While zero "
5982     "value indeed disables, the actual enabling of the slave "
5983     "applier execution mode is done implicitly when a "
5984     "Format_description_event is sent through the session.",
5985     SESSION_ONLY(pseudo_slave_mode), NO_CMD_LINE, DEFAULT(false),
5986     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_pseudo_slave_mode));
5987 
5988 #ifdef HAVE_GTID_NEXT_LIST
check_gtid_next_list(sys_var * self,THD * thd,set_var * var)5989 static bool check_gtid_next_list(sys_var *self, THD *thd, set_var *var) {
5990   DBUG_TRACE;
5991   my_error(ER_NOT_SUPPORTED_YET, MYF(0), "GTID_NEXT_LIST");
5992   if (check_session_admin_outside_trx_outside_sf_outside_sp(self, thd, var))
5993     return true;
5994   /*
5995     @todo: move this check into the set function and hold the lock on
5996     Gtid_mode::lock until the operation has completed, so that we are
5997     sure a concurrent connection does not change gtid_mode between
5998     check and fix - if we ever implement this variable.
5999   */
6000   if (global_gtid_mode.get() == Gtid_mode::OFF &&
6001       var->save_result.string_value.str != NULL)
6002     my_error(ER_CANT_SET_GTID_NEXT_LIST_TO_NON_NULL_WHEN_GTID_MODE_IS_OFF,
6003              MYF(0));
6004   return false;
6005 }
6006 
update_gtid_next_list(sys_var * self,THD * thd,enum_var_type type)6007 static bool update_gtid_next_list(sys_var *self, THD *thd, enum_var_type type) {
6008   DBUG_ASSERT(type == OPT_SESSION);
6009   if (thd->get_gtid_next_list() != NULL)
6010     return gtid_acquire_ownership_multiple(thd) != 0 ? true : false;
6011   return false;
6012 }
6013 
6014 static Sys_var_gtid_set Sys_gtid_next_list(
6015     "gtid_next_list",
6016     "Before re-executing a transaction that contains multiple "
6017     "Global Transaction Identifiers, this variable must be set "
6018     "to the set of all re-executed transactions.",
6019     SESSION_ONLY(gtid_next_list), NO_CMD_LINE, DEFAULT(NULL), NO_MUTEX_GUARD,
6020     NOT_IN_BINLOG, ON_CHECK(check_gtid_next_list),
6021     ON_UPDATE(update_gtid_next_list));
6022 export sys_var *Sys_gtid_next_list_ptr = &Sys_gtid_next_list;
6023 #endif  // HAVE_GTID_NEXT_LIST
6024 
6025 static Sys_var_gtid_next Sys_gtid_next(
6026     "gtid_next",
6027     "Specifies the Global Transaction Identifier for the following "
6028     "transaction.",
6029     SESSION_ONLY(gtid_next), NO_CMD_LINE, DEFAULT("AUTOMATIC"), NO_MUTEX_GUARD,
6030     NOT_IN_BINLOG, ON_CHECK(check_gtid_next));
6031 export sys_var *Sys_gtid_next_ptr = &Sys_gtid_next;
6032 
6033 static Sys_var_gtid_executed Sys_gtid_executed(
6034     "gtid_executed",
6035     "The global variable contains the set of GTIDs in the "
6036     "binary log. The session variable contains the set of GTIDs "
6037     "in the current, ongoing transaction.");
6038 
check_gtid_purged(sys_var * self,THD * thd,set_var * var)6039 static bool check_gtid_purged(sys_var *self, THD *thd, set_var *var) {
6040   DBUG_TRACE;
6041 
6042   /*
6043     GTID_PURGED must not be set / updated when GR is running (it goes against
6044     the whole purpose of update everywhere replication).
6045   */
6046   if (is_group_replication_running()) {
6047     my_error(ER_UPDATE_GTID_PURGED_WITH_GR, MYF(0));
6048     return true;
6049   }
6050 
6051   if (!var->value ||
6052       check_session_admin_outside_trx_outside_sf_outside_sp(self, thd, var))
6053     return true;
6054 
6055   if (var->value->result_type() != STRING_RESULT ||
6056       !var->save_result.string_value.str)
6057     return true;
6058 
6059   return false;
6060 }
6061 
global_update(THD * thd,set_var * var)6062 bool Sys_var_gtid_purged::global_update(THD *thd, set_var *var) {
6063   DBUG_TRACE;
6064   bool error = false;
6065 
6066   global_sid_lock->wrlock();
6067 
6068   /*
6069     ensures the commit of the transaction started when saving the
6070     purged gtid set in the table
6071   */
6072   thd->lex->autocommit = true;
6073 
6074   /*
6075     SET GITD_PURGED command should ignore 'read-only' and 'super_read_only'
6076     options so that it can update 'mysql.gtid_executed' replication repository
6077     table.
6078   */
6079   thd->set_skip_readonly_check();
6080   char *previous_gtid_executed = nullptr, *previous_gtid_purged = nullptr,
6081        *current_gtid_executed = nullptr, *current_gtid_purged = nullptr;
6082   gtid_state->get_executed_gtids()->to_string(&previous_gtid_executed);
6083   gtid_state->get_lost_gtids()->to_string(&previous_gtid_purged);
6084   Gtid_set gtid_set(global_sid_map, global_sid_lock);
6085   bool starts_with_plus = false;
6086   enum_return_status ret = gtid_set.add_gtid_text(
6087       var->save_result.string_value.str, nullptr, &starts_with_plus);
6088 
6089   if (ret != RETURN_STATUS_OK) {
6090     error = true;
6091     goto end;
6092   }
6093   ret = gtid_state->add_lost_gtids(&gtid_set, starts_with_plus);
6094   if (ret != RETURN_STATUS_OK) {
6095     error = true;
6096     goto end;
6097   }
6098   gtid_state->get_executed_gtids()->to_string(&current_gtid_executed);
6099   gtid_state->get_lost_gtids()->to_string(&current_gtid_purged);
6100 
6101   // Log messages saying that GTID_PURGED and GTID_EXECUTED were changed.
6102   LogErr(SYSTEM_LEVEL, ER_GTID_PURGED_WAS_UPDATED, previous_gtid_purged,
6103          current_gtid_purged);
6104   LogErr(SYSTEM_LEVEL, ER_GTID_EXECUTED_WAS_UPDATED, previous_gtid_executed,
6105          current_gtid_executed);
6106 
6107 end:
6108   global_sid_lock->unlock();
6109   my_free(previous_gtid_executed);
6110   my_free(previous_gtid_purged);
6111   my_free(current_gtid_executed);
6112   my_free(current_gtid_purged);
6113   return error;
6114 }
6115 
6116 Gtid_set *gtid_purged;
6117 static Sys_var_gtid_purged Sys_gtid_purged(
6118     "gtid_purged",
6119     "The set of GTIDs that existed in previous, purged binary logs.",
6120     GLOBAL_VAR(gtid_purged), NO_CMD_LINE, DEFAULT(nullptr), NO_MUTEX_GUARD,
6121     NOT_IN_BINLOG, ON_CHECK(check_gtid_purged));
6122 export sys_var *Sys_gtid_purged_ptr = &Sys_gtid_purged;
6123 
6124 static Sys_var_gtid_owned Sys_gtid_owned(
6125     "gtid_owned",
6126     "The global variable lists all GTIDs owned by all threads. "
6127     "The session variable lists all GTIDs owned by the current thread.");
6128 
6129 static Sys_var_gtid_mode Sys_gtid_mode(
6130     "gtid_mode",
6131     "Controls whether Global Transaction Identifiers (GTIDs) are "
6132     "enabled. Can be OFF, OFF_PERMISSIVE, ON_PERMISSIVE, or ON. OFF "
6133     "means that no transaction has a GTID. OFF_PERMISSIVE means that "
6134     "new transactions (committed in a client session using "
6135     "GTID_NEXT='AUTOMATIC') are not assigned any GTID, and "
6136     "replicated transactions are allowed to have or not have a "
6137     "GTID. ON_PERMISSIVE means that new transactions are assigned a "
6138     "GTID, and replicated transactions are allowed to have or not "
6139     "have a GTID. ON means that all transactions have a GTID. "
6140     "ON is required on a master before any slave can use "
6141     "MASTER_AUTO_POSITION=1. To safely switch from OFF to ON, first "
6142     "set all servers to OFF_PERMISSIVE, then set all servers to "
6143     "ON_PERMISSIVE, then wait for all transactions without a GTID to "
6144     "be replicated and executed on all servers, and finally set all "
6145     "servers to GTID_MODE = ON.",
6146     PERSIST_AS_READONLY GLOBAL_VAR(Gtid_mode::sysvar_mode),
6147     CMD_LINE(REQUIRED_ARG), Gtid_mode::names, DEFAULT(Gtid_mode::DEFAULT),
6148     NO_MUTEX_GUARD, NOT_IN_BINLOG,
6149     ON_CHECK(check_session_admin_outside_trx_outside_sf_outside_sp));
6150 
6151 static Sys_var_uint Sys_gtid_executed_compression_period(
6152     "gtid_executed_compression_period",
6153     "When binlog is disabled, "
6154     "a background thread wakes up to compress the gtid_executed table "
6155     "every gtid_executed_compression_period transactions, as a "
6156     "special case, if variable is 0, the thread never wakes up "
6157     "to compress the gtid_executed table.",
6158     GLOBAL_VAR(gtid_executed_compression_period), CMD_LINE(OPT_ARG),
6159     VALID_RANGE(0, UINT_MAX32), DEFAULT(1000), BLOCK_SIZE(1));
6160 
6161 static Sys_var_bool Sys_disconnect_on_expired_password(
6162     "disconnect_on_expired_password",
6163     "Give clients that don't signal password expiration support execution "
6164     "time "
6165     "error(s) instead of connection error",
6166     READ_ONLY GLOBAL_VAR(disconnect_on_expired_password), CMD_LINE(OPT_ARG),
6167     DEFAULT(true));
6168 
6169 static Sys_var_bool Sys_validate_user_plugins(
6170     "validate_user_plugins",
6171     "Turns on additional validation of authentication plugins assigned "
6172     "to user accounts. ",
6173     READ_ONLY NOT_VISIBLE GLOBAL_VAR(validate_user_plugins), CMD_LINE(OPT_ARG),
6174     DEFAULT(true), NO_MUTEX_GUARD, NOT_IN_BINLOG);
6175 
6176 static Sys_var_enum Sys_block_encryption_mode(
6177     "block_encryption_mode", "mode for AES_ENCRYPT/AES_DECRYPT",
6178     SESSION_VAR(my_aes_mode), CMD_LINE(REQUIRED_ARG), my_aes_opmode_names,
6179     DEFAULT(my_aes_128_ecb));
6180 
check_track_session_sys_vars(sys_var *,THD * thd,set_var * var)6181 static bool check_track_session_sys_vars(sys_var *, THD *thd, set_var *var) {
6182   DBUG_TRACE;
6183   return thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)
6184       ->check(thd, var);
6185   return false;
6186 }
6187 
update_track_session_sys_vars(sys_var *,THD * thd,enum_var_type type)6188 static bool update_track_session_sys_vars(sys_var *, THD *thd,
6189                                           enum_var_type type) {
6190   DBUG_TRACE;
6191   /* Populate map only for session variable. */
6192   if (type == OPT_SESSION)
6193     return thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)
6194         ->update(thd);
6195   return false;
6196 }
6197 
6198 static Sys_var_charptr Sys_track_session_sys_vars(
6199     "session_track_system_variables",
6200     "Track changes in registered system variables.",
6201     SESSION_VAR(track_sysvars_ptr), CMD_LINE(REQUIRED_ARG), IN_FS_CHARSET,
6202     DEFAULT("time_zone,autocommit,character_set_client,character_set_results,"
6203             "character_set_connection"),
6204     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_track_session_sys_vars),
6205     ON_UPDATE(update_track_session_sys_vars));
6206 
update_session_track_schema(sys_var *,THD * thd,enum_var_type)6207 static bool update_session_track_schema(sys_var *, THD *thd, enum_var_type) {
6208   DBUG_TRACE;
6209   return thd->session_tracker.get_tracker(CURRENT_SCHEMA_TRACKER)->update(thd);
6210 }
6211 
6212 static Sys_var_bool Sys_session_track_schema(
6213     "session_track_schema", "Track changes to the 'default schema'.",
6214     SESSION_VAR(session_track_schema), CMD_LINE(OPT_ARG), DEFAULT(true),
6215     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
6216     ON_UPDATE(update_session_track_schema));
6217 
update_session_track_tx_info(sys_var *,THD * thd,enum_var_type)6218 static bool update_session_track_tx_info(sys_var *, THD *thd, enum_var_type) {
6219   DBUG_TRACE;
6220   TX_TRACKER_GET(tst);
6221   return tst->update(thd);
6222 }
6223 
6224 static const char *session_track_transaction_info_names[] = {
6225     "OFF", "STATE", "CHARACTERISTICS", NullS};
6226 
6227 static Sys_var_enum Sys_session_track_transaction_info(
6228     "session_track_transaction_info",
6229     "Track changes to the transaction attributes. OFF to disable; "
6230     "STATE to track just transaction state (Is there an active transaction? "
6231     "Does it have any data? etc.); CHARACTERISTICS to track transaction "
6232     "state "
6233     "and report all statements needed to start a transaction with the same "
6234     "characteristics (isolation level, read only/read write, snapshot - "
6235     "but not any work done / data modified within the transaction).",
6236     SESSION_VAR(session_track_transaction_info), CMD_LINE(REQUIRED_ARG),
6237     session_track_transaction_info_names, DEFAULT(OFF), NO_MUTEX_GUARD,
6238     NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(update_session_track_tx_info));
6239 
update_session_track_state_change(sys_var *,THD * thd,enum_var_type)6240 static bool update_session_track_state_change(sys_var *, THD *thd,
6241                                               enum_var_type) {
6242   DBUG_TRACE;
6243   return thd->session_tracker.get_tracker(SESSION_STATE_CHANGE_TRACKER)
6244       ->update(thd);
6245 }
6246 
6247 static Sys_var_bool Sys_session_track_state_change(
6248     "session_track_state_change", "Track changes to the 'session state'.",
6249     SESSION_VAR(session_track_state_change), CMD_LINE(OPT_ARG), DEFAULT(false),
6250     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
6251     ON_UPDATE(update_session_track_state_change));
6252 
handle_offline_mode(sys_var *,THD * thd,enum_var_type)6253 static bool handle_offline_mode(sys_var *, THD *thd, enum_var_type) {
6254   DBUG_TRACE;
6255   DEBUG_SYNC(thd, "after_lock_offline_mode_acquire");
6256 
6257   if (mysqld_offline_mode()) {
6258     // Unlock the global system varaible lock as kill holds LOCK_thd_data.
6259     mysql_mutex_unlock(&LOCK_global_system_variables);
6260     killall_non_super_threads(thd);
6261     mysql_mutex_lock(&LOCK_global_system_variables);
6262   }
6263 
6264   return false;
6265 }
6266 
6267 static Sys_var_bool Sys_offline_mode(
6268     "offline_mode", "Make the server into offline mode",
6269     GLOBAL_VAR(offline_mode), CMD_LINE(OPT_ARG), DEFAULT(false), NO_MUTEX_GUARD,
6270     NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(handle_offline_mode));
6271 
6272 static Sys_var_bool Sys_avoid_temporal_upgrade(
6273     "avoid_temporal_upgrade",
6274     "When this option is enabled, the pre-5.6.4 temporal types are "
6275     "not upgraded to the new format for ALTER TABLE requests "
6276     "ADD/CHANGE/MODIFY"
6277     " COLUMN, ADD INDEX or FORCE operation. "
6278     "This variable is deprecated and will be removed in a future release.",
6279     GLOBAL_VAR(avoid_temporal_upgrade),
6280     CMD_LINE(OPT_ARG, OPT_AVOID_TEMPORAL_UPGRADE), DEFAULT(false),
6281     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(nullptr),
6282     DEPRECATED_VAR(""));
6283 
6284 static Sys_var_bool Sys_show_old_temporals(
6285     "show_old_temporals",
6286     "When this option is enabled, the pre-5.6.4 temporal types will "
6287     "be marked in the 'SHOW CREATE TABLE' and 'INFORMATION_SCHEMA.COLUMNS' "
6288     "table as a comment in COLUMN_TYPE field. "
6289     "This variable is deprecated and will be removed in a future release.",
6290     SESSION_VAR(show_old_temporals), CMD_LINE(OPT_ARG, OPT_SHOW_OLD_TEMPORALS),
6291     DEFAULT(false), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
6292     ON_UPDATE(nullptr), DEPRECATED_VAR(""));
6293 
6294 static Sys_var_charptr Sys_disabled_storage_engines(
6295     "disabled_storage_engines",
6296     "Limit CREATE TABLE for the storage engines listed",
6297     READ_ONLY GLOBAL_VAR(opt_disabled_storage_engines), CMD_LINE(REQUIRED_ARG),
6298     IN_SYSTEM_CHARSET, DEFAULT(""));
6299 
6300 static Sys_var_bool Sys_persisted_globals_load(
6301     PERSISTED_GLOBALS_LOAD,
6302     "When this option is enabled, config file mysqld-auto.cnf is read "
6303     "and applied to server, else this file is ignored even if present.",
6304     READ_ONLY NON_PERSIST GLOBAL_VAR(persisted_globals_load), CMD_LINE(OPT_ARG),
6305     DEFAULT(true), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
6306     ON_UPDATE(nullptr));
6307 
sysvar_check_authid_string(sys_var *,THD * thd,set_var * var)6308 static bool sysvar_check_authid_string(sys_var *, THD *thd, set_var *var) {
6309   /*
6310     Since mandatory_roles is similar to a GRANT role statement without a
6311     GRANT ADMIN privilege, setting this variable requires both the
6312     ROLE_ADMIN and the SYSTEM_VARIABLES_ADMIN.
6313   */
6314   Security_context *sctx = thd->security_context();
6315   DBUG_ASSERT(sctx != nullptr);
6316   if (sctx && !sctx->has_global_grant(STRING_WITH_LEN("ROLE_ADMIN")).first) {
6317     my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0),
6318              "SYSTEM_VARIABLES_ADMIN or SUPER privileges, as well as the "
6319              "ROLE_ADMIN");
6320     /* No privilege access error */
6321     return true;
6322   }
6323   if (var->save_result.string_value.str == nullptr) {
6324     var->save_result.string_value.str = const_cast<char *>("");
6325     var->save_result.string_value.length = 0;
6326   }
6327   return check_authorization_id_string(thd, var->save_result.string_value);
6328 }
6329 
sysvar_update_mandatory_roles(sys_var *,THD *,enum_var_type)6330 static bool sysvar_update_mandatory_roles(sys_var *, THD *, enum_var_type) {
6331   update_mandatory_roles();
6332   return false;
6333 }
6334 
6335 static PolyLock_mutex PLock_sys_mandatory_roles(&LOCK_mandatory_roles);
6336 static Sys_var_lexstring Sys_mandatory_roles(
6337     "mandatory_roles",
6338     "All the specified roles are always considered granted to every user and "
6339     "they"
6340     " can't be revoked. Mandatory roles still require activation unless they "
6341     "are made into "
6342     "default roles. The granted roles will not be visible in the "
6343     "mysql.role_edges"
6344     " table.",
6345     GLOBAL_VAR(opt_mandatory_roles), CMD_LINE(REQUIRED_ARG), IN_SYSTEM_CHARSET,
6346     DEFAULT(""), &PLock_sys_mandatory_roles, NOT_IN_BINLOG,
6347     ON_CHECK(sysvar_check_authid_string),
6348     ON_UPDATE(sysvar_update_mandatory_roles));
6349 
6350 static Sys_var_bool Sys_always_activate_granted_roles(
6351     "activate_all_roles_on_login",
6352     "Automatically set all granted roles as active after the user has "
6353     "authenticated successfully.",
6354     GLOBAL_VAR(opt_always_activate_granted_roles), CMD_LINE(OPT_ARG),
6355     DEFAULT(false), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr),
6356     ON_UPDATE(nullptr));
6357 
6358 static PolyLock_mutex plock_sys_password_history(&LOCK_password_history);
6359 static Sys_var_uint Sys_password_history(
6360     "password_history",
6361     "The number of old passwords to check in the history."
6362     " Set to 0 (the default) to turn the checks off",
6363     GLOBAL_VAR(global_password_history), CMD_LINE(REQUIRED_ARG),
6364     VALID_RANGE(0, UINT_MAX32), DEFAULT(0), BLOCK_SIZE(1),
6365     &plock_sys_password_history);
6366 
6367 static PolyLock_mutex plock_sys_password_reuse_interval(
6368     &LOCK_password_reuse_interval);
6369 static Sys_var_uint Sys_password_reuse_interval(
6370     "password_reuse_interval",
6371     "The minimum number of days that need to pass before a password can "
6372     "be reused. Set to 0 (the default) to turn the checks off",
6373     GLOBAL_VAR(global_password_reuse_interval), CMD_LINE(REQUIRED_ARG),
6374     VALID_RANGE(0, UINT_MAX32), DEFAULT(0), BLOCK_SIZE(1),
6375     &plock_sys_password_reuse_interval);
6376 
check_resultset_metadata(sys_var *,THD * thd,set_var * var)6377 static bool check_resultset_metadata(sys_var *, THD *thd, set_var *var) {
6378   /*
6379     Set @@resultset_metadata to the value other than FULL only if
6380     the client supports it.
6381   */
6382   if (var->save_result.ulonglong_value != RESULTSET_METADATA_FULL &&
6383       !thd->get_protocol()->has_client_capability(
6384           CLIENT_OPTIONAL_RESULTSET_METADATA)) {
6385     my_error(ER_CLIENT_DOES_NOT_SUPPORT, MYF(0), "optional metadata transfer");
6386     return true;
6387   }
6388   return false;
6389 }
6390 
6391 static const char *resultset_metadata_names[] = {"NONE", "FULL", NullS};
6392 
6393 static Sys_var_enum Sys_resultset_metadata(
6394     "resultset_metadata",
6395     "Controls what meatadata the server will send to the client: "
6396     "either FULL (default) for all metadata, NONE for no metadata.",
6397     SESSION_ONLY(resultset_metadata), NO_CMD_LINE, resultset_metadata_names,
6398     DEFAULT(static_cast<ulong>(RESULTSET_METADATA_FULL)), NO_MUTEX_GUARD,
6399     NOT_IN_BINLOG, ON_CHECK(check_resultset_metadata), ON_UPDATE(nullptr));
6400 
check_binlog_row_value_options(sys_var * self,THD * thd,set_var * var)6401 static bool check_binlog_row_value_options(sys_var *self, THD *thd,
6402                                            set_var *var) {
6403   DBUG_TRACE;
6404   if (check_session_admin_outside_trx_outside_sf_outside_sp(self, thd, var))
6405     return true;
6406   if (var->save_result.ulonglong_value != 0) {
6407     const char *msg = nullptr;
6408     int code = ER_WARN_BINLOG_PARTIAL_UPDATES_DISABLED;
6409     if (!mysql_bin_log.is_open())
6410       msg = "the binary log is closed";
6411     else if (!var->is_global_persist()) {
6412       if (!thd->variables.sql_log_bin)
6413         msg = "the binary log is disabled";
6414       else if (thd->variables.binlog_format == BINLOG_FORMAT_STMT)
6415         msg = "binlog_format=STATEMENT";
6416       else if (log_bin_use_v1_row_events) {
6417         msg = "binlog_row_value_options=PARTIAL_JSON";
6418         code = ER_WARN_BINLOG_V1_ROW_EVENTS_DISABLED;
6419       } else if (thd->variables.binlog_row_image == BINLOG_ROW_IMAGE_FULL) {
6420         msg = "binlog_row_image=FULL";
6421         code = ER_WARN_BINLOG_PARTIAL_UPDATES_SUGGESTS_PARTIAL_IMAGES;
6422       }
6423     } else {
6424       if (global_system_variables.binlog_format == BINLOG_FORMAT_STMT)
6425         msg = "binlog_format=STATEMENT";
6426       else if (log_bin_use_v1_row_events) {
6427         msg = "binlog_row_value_options=PARTIAL_JSON";
6428         code = ER_WARN_BINLOG_V1_ROW_EVENTS_DISABLED;
6429       } else if (global_system_variables.binlog_row_image ==
6430                  BINLOG_ROW_IMAGE_FULL) {
6431         msg = "binlog_row_image=FULL";
6432         code = ER_WARN_BINLOG_PARTIAL_UPDATES_SUGGESTS_PARTIAL_IMAGES;
6433       }
6434     }
6435     if (msg) {
6436       switch (code) {
6437         case ER_WARN_BINLOG_PARTIAL_UPDATES_DISABLED:
6438           push_warning_printf(
6439               thd, Sql_condition::SL_WARNING, code,
6440               ER_THD(thd, ER_WARN_BINLOG_PARTIAL_UPDATES_DISABLED), msg,
6441               "PARTIAL_JSON");
6442           break;
6443         case ER_WARN_BINLOG_PARTIAL_UPDATES_SUGGESTS_PARTIAL_IMAGES:
6444           push_warning_printf(
6445               thd, Sql_condition::SL_WARNING, code,
6446               ER_THD(thd,
6447                      ER_WARN_BINLOG_PARTIAL_UPDATES_SUGGESTS_PARTIAL_IMAGES),
6448               msg, "PARTIAL_JSON");
6449           break;
6450         case ER_WARN_BINLOG_V1_ROW_EVENTS_DISABLED:
6451           push_warning_printf(
6452               thd, Sql_condition::SL_WARNING, code,
6453               ER_THD(thd, ER_WARN_BINLOG_V1_ROW_EVENTS_DISABLED), msg);
6454           break;
6455         default:
6456           DBUG_ASSERT(0); /* purecov: deadcode */
6457       }
6458     }
6459   }
6460 
6461   return false;
6462 }
6463 
6464 const char *binlog_row_value_options_names[] = {"PARTIAL_JSON", nullptr};
6465 static Sys_var_set Sys_binlog_row_value_options(
6466     "binlog_row_value_options",
6467     "When set to PARTIAL_JSON, this option enables a space-efficient "
6468     "row-based binary log format for UPDATE statements that modify a "
6469     "JSON value using only the functions JSON_SET, JSON_REPLACE, and "
6470     "JSON_REMOVE. For such updates, only the modified parts of the "
6471     "JSON document are included in the binary log, so small changes of "
6472     "big documents may need significantly less space.",
6473     SESSION_VAR(binlog_row_value_options), CMD_LINE(REQUIRED_ARG),
6474     binlog_row_value_options_names, DEFAULT(0), NO_MUTEX_GUARD, NOT_IN_BINLOG,
6475     ON_CHECK(check_binlog_row_value_options));
6476 
check_keyring_access(sys_var *,THD * thd,set_var *)6477 static bool check_keyring_access(sys_var *, THD *thd, set_var *) {
6478   if (!thd->security_context()->check_access(SUPER_ACL) &&
6479       !(thd->security_context()
6480             ->has_global_grant(STRING_WITH_LEN("ENCRYPTION_KEY_ADMIN"))
6481             .first)) {
6482     my_error(ER_KEYRING_ACCESS_DENIED_ERROR, MYF(0),
6483              "SUPER or ENCRYPTION_KEY_ADMIN");
6484     return true;
6485   }
6486   return false;
6487 }
6488 
6489 /**
6490   This is a mutex used to protect global variable @@keyring_operations.
6491 */
6492 static PolyLock_mutex PLock_keyring_operations(&LOCK_keyring_operations);
6493 /**
6494   This variable provides access to keyring service APIs. When this variable
6495   is disabled calls to keyring_key_generate(), keyring_key_store() and
6496   keyring_key_remove() will report error until this variable is enabled.
6497   This variable is protected under a mutex named PLock_keyring_operations.
6498   To access this variable you must first set this mutex.
6499 
6500   @sa PLock_keyring_operations
6501 */
6502 static Sys_var_bool Sys_keyring_operations(
6503     "keyring_operations",
6504     "This variable provides access to keyring service APIs. When this "
6505     "option is disabled calls to keyring_key_generate(), keyring_key_store() "
6506     "and keyring_key_remove() will report error until this variable is "
6507     "enabled.",
6508     NON_PERSIST GLOBAL_VAR(opt_keyring_operations), NO_CMD_LINE, DEFAULT(true),
6509     &PLock_keyring_operations, NOT_IN_BINLOG, ON_CHECK(check_keyring_access),
6510     ON_UPDATE(nullptr));
6511 
check_default_collation_for_utf8mb4(sys_var * self,THD * thd,set_var * var)6512 static bool check_default_collation_for_utf8mb4(sys_var *self, THD *thd,
6513                                                 set_var *var) {
6514   if (check_collation_not_null(self, thd, var)) {
6515     return true;
6516   }
6517 
6518   if (!var->value)
6519     var->save_result.ptr = reinterpret_cast<void *>(self->get_default());
6520 
6521   auto cs = static_cast<const CHARSET_INFO *>(var->save_result.ptr);
6522   if (cs == &my_charset_utf8mb4_0900_ai_ci ||
6523       cs == &my_charset_utf8mb4_general_ci)
6524     return false;
6525 
6526   my_error(ER_INVALID_DEFAULT_UTF8MB4_COLLATION, MYF(0), cs->name);
6527   return true;
6528 }
6529 
6530 static Sys_var_struct<CHARSET_INFO, Get_name> Sys_default_collation_for_utf8mb4(
6531     "default_collation_for_utf8mb4",
6532     "Controls default collation for utf8mb4 while replicating implicit "
6533     "utf8mb4 collations.",
6534     SESSION_VAR(default_collation_for_utf8mb4), NO_CMD_LINE,
6535     DEFAULT(&my_charset_utf8mb4_0900_ai_ci), NO_MUTEX_GUARD, IN_BINLOG,
6536     ON_CHECK(check_default_collation_for_utf8mb4),
6537     ON_UPDATE(update_deprecated));
6538 
6539 static Sys_var_bool Sys_show_create_table_verbosity(
6540     "show_create_table_verbosity",
6541     "When this option is enabled, it increases the verbosity of "
6542     "'SHOW CREATE TABLE'.",
6543     SESSION_VAR(show_create_table_verbosity), CMD_LINE(OPT_ARG), DEFAULT(false),
6544     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(nullptr));
6545 
6546 static const char *use_secondary_engine_values[] = {"OFF", "ON", "FORCED",
6547                                                     nullptr};
6548 static Sys_var_enum Sys_use_secondary_engine(
6549     "use_secondary_engine",
6550     "Controls preparation of SELECT statements against secondary storage "
6551     "engine. Valid values: OFF/ON/FORCED. OFF = Prepare only against primary "
6552     "storage engine. ON = First prepare against secondary storage engine, "
6553     "reprepare against primary storage engine if error. FORCED = Prepare all "
6554     "SELECT statements referencing one or more base tables only against "
6555     "secondary storage engine.",
6556     HINT_UPDATEABLE SESSION_ONLY(use_secondary_engine), NO_CMD_LINE,
6557     use_secondary_engine_values, DEFAULT(SECONDARY_ENGINE_ON), NO_MUTEX_GUARD,
6558     NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(nullptr));
6559 
6560 /**
6561   Cost threshold for executing queries in a secondary storage engine. Only
6562   queries that have an estimated cost above this value will be attempted
6563   executed in a secondary storage engine.
6564 
6565   Secondary storage engines are meant to accelerate queries that would otherwise
6566   take a relatively long time to execute. If a secondary storage engine accepts
6567   a query, it is assumed that it will be able to accelerate it. However, if the
6568   estimated cost of the query is low, the query will execute fast in the primary
6569   engine too, so there is little to gain by offloading the query to the
6570   secondary engine.
6571 
6572   The default value aims to avoid use of secondary storage engines for queries
6573   that could be executed by the primary engine in a few tenths of seconds or
6574   less, and attempt to use secondary storage engines for queries would take
6575   seconds or more.
6576 */
6577 static Sys_var_double Sys_secondary_engine_cost_threshold(
6578     "secondary_engine_cost_threshold",
6579     "Controls which statements to consider for execution in a secondary "
6580     "storage engine. Only statements that have a cost estimate higher than "
6581     "this value will be attempted executed in a secondary storage engine.",
6582     HINT_UPDATEABLE SESSION_VAR(secondary_engine_cost_threshold),
6583     CMD_LINE(OPT_ARG), VALID_RANGE(0, DBL_MAX), DEFAULT(100000), NO_MUTEX_GUARD,
6584     NOT_IN_BINLOG, ON_CHECK(nullptr), ON_UPDATE(nullptr));
6585 
6586 static Sys_var_bool Sys_sql_require_primary_key{
6587     "sql_require_primary_key",
6588     "When set, tables must be created with a primary key, and an existing "
6589     "primary key cannot be removed with 'ALTER TABLE'. Attempts to do so "
6590     "will result in an error.",
6591     HINT_UPDATEABLE SESSION_VAR(sql_require_primary_key),
6592     CMD_LINE(OPT_ARG),
6593     DEFAULT(false),
6594     NO_MUTEX_GUARD,
6595     IN_BINLOG,
6596     ON_CHECK(check_session_admin)};
6597 
6598 static Sys_var_charptr Sys_sys_variables_admin_subject(
6599     PERSIST_ONLY_ADMIN_X509_SUBJECT,
6600     "The client peer certificate name required to enable setting all "
6601     "system variables via SET PERSIST[_ONLY]",
6602     READ_ONLY NON_PERSIST GLOBAL_VAR(sys_var_persist_only_admin_x509_subject),
6603     CMD_LINE(OPT_ARG), IN_SYSTEM_CHARSET, DEFAULT(""));
6604 
6605 static Sys_var_ulong Sys_binlog_row_event_max_size(
6606     "binlog_row_event_max_size",
6607     "The maximum size of a row-based binary log event in bytes. Rows will be "
6608     "grouped into events smaller than this size if possible. "
6609     "The value has to be a multiple of 256.",
6610     READ_ONLY GLOBAL_VAR(binlog_row_event_max_size), CMD_LINE(REQUIRED_ARG),
6611     VALID_RANGE(256, ULONG_MAX), DEFAULT(8192), BLOCK_SIZE(256));
6612 
check_group_replication_consistency(sys_var * self,THD * thd,set_var * var)6613 static bool check_group_replication_consistency(sys_var *self, THD *thd,
6614                                                 set_var *var) {
6615   if (var->type == OPT_GLOBAL || var->type == OPT_PERSIST) {
6616     Security_context *sctx = thd->security_context();
6617     if (!sctx->check_access(SUPER_ACL) &&
6618         !sctx->has_global_grant(STRING_WITH_LEN("GROUP_REPLICATION_ADMIN"))
6619              .first) {
6620       my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0),
6621                "SUPER or GROUP_REPLICATION_ADMIN");
6622       return true;
6623     }
6624   }
6625 
6626   return check_outside_trx(self, thd, var);
6627 }
6628 
6629 static const char *group_replication_consistency_names[] = {
6630     "EVENTUAL", "BEFORE_ON_PRIMARY_FAILOVER", "BEFORE",
6631     "AFTER",    "BEFORE_AND_AFTER",           NullS};
6632 
6633 static Sys_var_enum Sys_group_replication_consistency(
6634     "group_replication_consistency",
6635     "Transaction consistency guarantee, possible values: EVENTUAL, "
6636     "BEFORE_ON_PRIMARY_FAILOVER, BEFORE, AFTER, BEFORE_AND_AFTER",
6637     SESSION_VAR(group_replication_consistency), CMD_LINE(OPT_ARG),
6638     group_replication_consistency_names,
6639     DEFAULT(GROUP_REPLICATION_CONSISTENCY_EVENTUAL), NO_MUTEX_GUARD,
6640     NOT_IN_BINLOG, ON_CHECK(check_group_replication_consistency),
6641     ON_UPDATE(nullptr));
6642 
check_binlog_encryption_admin(sys_var *,THD * thd,set_var *)6643 static bool check_binlog_encryption_admin(sys_var *, THD *thd, set_var *) {
6644   DBUG_TRACE;
6645   if (!thd->security_context()->check_access(SUPER_ACL) &&
6646       !(thd->security_context()
6647             ->has_global_grant(STRING_WITH_LEN("BINLOG_ENCRYPTION_ADMIN"))
6648             .first)) {
6649     my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0),
6650              "SUPER or BINLOG_ENCRYPTION_ADMIN");
6651     return true;
6652   }
6653   return false;
6654 }
6655 
global_update(THD * thd,set_var * var)6656 bool Sys_var_binlog_encryption::global_update(THD *thd, set_var *var) {
6657   DBUG_TRACE;
6658 
6659   /* No-op if trying to set to current value */
6660   bool new_value = var->save_result.ulonglong_value;
6661   if (new_value == rpl_encryption.is_enabled()) return false;
6662 
6663   DEBUG_SYNC(thd, "after_locking_global_sys_var_set_binlog_enc");
6664   /* We unlock in following statement to avoid deadlock involving following
6665    * conditions.
6666    * ------------------------------------------------------------------------
6667    * Thread 1 (START SLAVE)  has locked channel_map and waiting for cond_wait
6668    * that is supposed to be done by Thread 2.
6669    *
6670    * Thread 2 (handle_slave_io) is supposed to signal Thread 1 but waiting to
6671    * lock LOCK_global_system_variables.
6672    *
6673    * Thread 3 (SET GLOBAL binlog_encryption=ON|OFF) has locked
6674    * LOCK_global_system_variables and waiting for channel_map.
6675    */
6676   mysql_mutex_unlock(&LOCK_global_system_variables);
6677   /* Set the option new value */
6678   bool res = false;
6679   if (new_value)
6680     res = rpl_encryption.enable(thd);
6681   else
6682     rpl_encryption.disable(thd);
6683   mysql_mutex_lock(&LOCK_global_system_variables);
6684   return res;
6685 }
6686 
6687 static Sys_var_binlog_encryption Sys_binlog_encryption(
6688     "binlog_encryption", "Enable/disable binary and relay logs encryption.",
6689     GLOBAL_VAR(rpl_encryption.get_enabled_var()), CMD_LINE(OPT_ARG),
6690     DEFAULT(false), NO_MUTEX_GUARD, NOT_IN_BINLOG,
6691     ON_CHECK(check_binlog_encryption_admin));
6692 
6693 static Sys_var_bool Sys_binlog_rotate_encryption_master_key_at_startup(
6694     "binlog_rotate_encryption_master_key_at_startup",
6695     "Force binlog encryption master key rotation at startup",
6696     READ_ONLY GLOBAL_VAR(
6697         rpl_encryption.get_master_key_rotation_at_startup_var()),
6698     CMD_LINE(OPT_ARG), DEFAULT(false), NO_MUTEX_GUARD, NOT_IN_BINLOG);
6699 
6700 static Sys_var_uint Sys_original_server_version(
6701     "original_server_version",
6702     "The version of the server where the transaction was originally executed",
6703     SESSION_ONLY(original_server_version), NO_CMD_LINE,
6704     VALID_RANGE(0, UNDEFINED_SERVER_VERSION), DEFAULT(UNDEFINED_SERVER_VERSION),
6705     BLOCK_SIZE(1), NO_MUTEX_GUARD, IN_BINLOG,
6706     ON_CHECK(check_session_admin_or_replication_applier));
6707 
6708 static Sys_var_uint Sys_immediate_server_version(
6709     "immediate_server_version",
6710     "The server version of the immediate server in the replication topology",
6711     SESSION_ONLY(immediate_server_version), NO_CMD_LINE,
6712     VALID_RANGE(0, UNDEFINED_SERVER_VERSION), DEFAULT(UNDEFINED_SERVER_VERSION),
6713     BLOCK_SIZE(1), NO_MUTEX_GUARD, IN_BINLOG,
6714     ON_CHECK(check_session_admin_or_replication_applier));
6715 
check_set_default_table_encryption_access(sys_var * self MY_ATTRIBUTE ((unused)),THD * thd,set_var * var)6716 static bool check_set_default_table_encryption_access(
6717     sys_var *self MY_ATTRIBUTE((unused)), THD *thd, set_var *var) {
6718   DBUG_EXECUTE_IF("skip_table_encryption_admin_check_for_set",
6719                   { return false; });
6720   if ((var->type == OPT_GLOBAL || var->type == OPT_PERSIST) &&
6721       is_group_replication_running()) {
6722     my_message(ER_GROUP_REPLICATION_RUNNING,
6723                "The default_table_encryption option cannot be changed when "
6724                "Group replication is running.",
6725                MYF(0));
6726     return true;
6727   }
6728 
6729   // Should own one of SUPER or both (SYSTEM_VARIABLES_ADMIN and
6730   // TABLE_ENCRYPTION_ADMIN), unless this is the session option and
6731   // the value is unchanged.
6732   longlong previous_val = thd->variables.default_table_encryption;
6733   longlong val = (longlong)var->save_result.ulonglong_value;
6734   if ((!var->is_global_persist() && val == previous_val) ||
6735       thd->security_context()->check_access(SUPER_ACL) ||
6736       (thd->security_context()
6737            ->has_global_grant(STRING_WITH_LEN("SYSTEM_VARIABLES_ADMIN"))
6738            .first &&
6739        thd->security_context()
6740            ->has_global_grant(STRING_WITH_LEN("TABLE_ENCRYPTION_ADMIN"))
6741            .first)) {
6742     return false;
6743   }
6744 
6745   my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0),
6746            "SUPER or SYSTEM_VARIABLES_ADMIN and TABLE_ENCRYPTION_ADMIN");
6747   return true;
6748 }
6749 
6750 static Sys_var_bool Sys_default_table_encryption(
6751     "default_table_encryption",
6752     "Database and tablespace are created with this default encryption property "
6753     "unless the user specifies an explicit encryption property.",
6754     HINT_UPDATEABLE SESSION_VAR(default_table_encryption), CMD_LINE(OPT_ARG),
6755     DEFAULT(false), NO_MUTEX_GUARD, IN_BINLOG,
6756     ON_CHECK(check_set_default_table_encryption_access), ON_UPDATE(nullptr));
6757 
check_set_table_encryption_privilege_access(sys_var *,THD * thd,set_var *)6758 static bool check_set_table_encryption_privilege_access(sys_var *, THD *thd,
6759                                                         set_var *) {
6760   DBUG_EXECUTE_IF("skip_table_encryption_admin_check_for_set",
6761                   { return false; });
6762   if (!thd->security_context()->check_access(SUPER_ACL)) {
6763     my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER");
6764     return true;
6765   }
6766   return false;
6767 }
6768 
6769 static Sys_var_bool Sys_table_encryption_privilege_check(
6770     "table_encryption_privilege_check",
6771     "Indicates if server enables privilege check when user tries to use "
6772     "non-default value for CREATE DATABASE or CREATE TABLESPACE or when "
6773     "user tries to do CREATE TABLE with ENCRYPTION option which deviates "
6774     "from per-database default.",
6775     GLOBAL_VAR(opt_table_encryption_privilege_check), CMD_LINE(OPT_ARG),
6776     DEFAULT(false), NO_MUTEX_GUARD, NOT_IN_BINLOG,
6777     ON_CHECK(check_set_table_encryption_privilege_access), ON_UPDATE(nullptr));
6778 
6779 static Sys_var_bool Sys_var_print_identified_with_as_hex(
6780     "print_identified_with_as_hex",
6781     "SHOW CREATE USER will print the AS clause as HEX if it contains "
6782     "non-prinable characters",
6783     SESSION_VAR(print_identified_with_as_hex), CMD_LINE(OPT_ARG),
6784     DEFAULT(false));
6785 
6786 /**
6787    Session only flag to skip printing secondary engine in SHOW CREATE
6788    TABLE.
6789 
6790    @sa store_create_info
6791 */
6792 static Sys_var_bool Sys_var_show_create_table_skip_secondary_engine(
6793     "show_create_table_skip_secondary_engine",
6794     "SHOW CREATE TABLE will skip SECONDARY_ENGINE when printing the table "
6795     "definition",
6796     SESSION_ONLY(show_create_table_skip_secondary_engine), NO_CMD_LINE,
6797     DEFAULT(false));
6798 
6799 static Sys_var_uint Sys_generated_random_password_length(
6800     "generated_random_password_length",
6801     "Determines the length randomly generated passwords in CREATE USER-,"
6802     "SET PASSWORD- or ALTER USER statements",
6803     SESSION_VAR(generated_random_password_length), CMD_LINE(REQUIRED_ARG),
6804     VALID_RANGE(5, 255), DEFAULT(20), BLOCK_SIZE(1), NO_MUTEX_GUARD, IN_BINLOG,
6805     ON_CHECK(nullptr));
6806 
check_set_protocol_compression_algorithms(sys_var *,THD *,set_var * var)6807 static bool check_set_protocol_compression_algorithms(sys_var *, THD *,
6808                                                       set_var *var) {
6809   if (!(var->save_result.string_value.str)) return true;
6810   return validate_compression_attributes(var->save_result.string_value.str,
6811                                          std::string(), true);
6812 }
6813 
6814 static Sys_var_charptr Sys_protocol_compression_algorithms(
6815     "protocol_compression_algorithms",
6816     "List of compression algorithms supported by server. Supported values "
6817     "are any combination of zlib, zstd, uncompressed. Command line clients "
6818     "may use the --compression-algorithms flag to specify a set of algorithms, "
6819     "and the connection will use an algorithm supported by both client and "
6820     "server. It picks zlib if both client and server support it; otherwise it "
6821     "picks zstd if both support it; otherwise it picks uncompressed if both "
6822     "support it; otherwise it fails.",
6823     GLOBAL_VAR(opt_protocol_compression_algorithms), CMD_LINE(REQUIRED_ARG),
6824     IN_FS_CHARSET,
6825     DEFAULT(const_cast<char *>(PROTOCOL_COMPRESSION_DEFAULT_VALUE)),
6826     NO_MUTEX_GUARD, NOT_IN_BINLOG,
6827     ON_CHECK(check_set_protocol_compression_algorithms), ON_UPDATE(nullptr));
6828 
check_set_require_row_format(sys_var *,THD * thd,set_var * var)6829 static bool check_set_require_row_format(sys_var *, THD *thd, set_var *var) {
6830   /*
6831    Should own SUPER or SYSTEM_VARIABLES_ADMIN or SESSION_VARIABLES_ADMIN
6832    when the value is changing to NO, no privileges are needed to set to YES
6833   */
6834   longlong previous_val = thd->variables.require_row_format;
6835   longlong val = (longlong)var->save_result.ulonglong_value;
6836   DBUG_ASSERT(!var->is_global_persist());
6837 
6838   // if it was true and we are changing it
6839   if (previous_val && val != previous_val) {
6840     if (thd->security_context()->check_access(SUPER_ACL) ||
6841         thd->security_context()
6842             ->has_global_grant(STRING_WITH_LEN("SYSTEM_VARIABLES_ADMIN"))
6843             .first ||
6844         thd->security_context()
6845             ->has_global_grant(STRING_WITH_LEN("SESSION_VARIABLES_ADMIN"))
6846             .first)
6847       return false;
6848 
6849     my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0),
6850              "SUPER or SYSTEM_VARIABLES_ADMIN or SESSION_VARIABLES_ADMIN");
6851     return true;
6852   }
6853   return false;
6854 }
6855 
6856 /**
6857    Session only flag to limit the application of queries to row based events
6858    and DDLs with the exception of temporary table creation/deletion
6859 */
6860 static Sys_var_bool Sys_var_require_row_format(
6861     "require_row_format",
6862     "Limit the application of queries to row based events "
6863     "and DDLs with the exception of temporary table creation/deletion.",
6864     SESSION_ONLY(require_row_format), NO_CMD_LINE, DEFAULT(false),
6865     NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_set_require_row_format));
6866