307 lines
12 KiB
C++
307 lines
12 KiB
C++
/* Copyright (c) 2021, 2024, Oracle and/or its affiliates.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License, version 2.0,
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is designed to work with certain software (including
|
|
but not limited to OpenSSL) that is licensed under separate terms,
|
|
as designated in a particular file or component or in included license
|
|
documentation. The authors of MySQL hereby grant you an additional
|
|
permission to link the program and your derivative works with the
|
|
separately licensed software that they have either included with
|
|
the program or referenced in the documentation.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License, version 2.0, for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
|
|
|
#include "sql/server_component/mysql_system_variable_update_imp.h"
|
|
|
|
#include <string.h>
|
|
#include <string_view>
|
|
|
|
#include <mysql/components/minimal_chassis.h>
|
|
#include <mysql/components/service_implementation.h>
|
|
#include <mysql/components/services/log_builtins.h>
|
|
#include <mysql/components/services/mysql_string.h>
|
|
#include <mysql/psi/mysql_rwlock.h>
|
|
#include <sql/mysqld.h>
|
|
#include <sql/set_var.h>
|
|
#include <sql/sql_class.h>
|
|
#include <sql/sql_lex.h>
|
|
#include <sql/sql_list.h>
|
|
#include <sql/sys_vars_shared.h>
|
|
#include <sql_string.h>
|
|
#include "sql/auth/auth_acls.h"
|
|
#include "sql/auth/sql_security_ctx.h"
|
|
#include "sql/item_func.h" // Item_func_set_user_var
|
|
#include "sql/server_component/set_variables_helper.h"
|
|
#include "storing_auto_thd.h"
|
|
|
|
/**
|
|
Return the system variable type given a type name.
|
|
*/
|
|
static enum_var_type sysvar_type(const char *type_name) {
|
|
if (type_name) {
|
|
if (!strcmp(type_name, "GLOBAL"))
|
|
return OPT_GLOBAL;
|
|
else if (!strcmp(type_name, "SESSION"))
|
|
return OPT_SESSION;
|
|
else if (!strcmp(type_name, "PERSIST"))
|
|
return OPT_PERSIST;
|
|
else if (!strcmp(type_name, "PERSIST_ONLY"))
|
|
return OPT_PERSIST_ONLY;
|
|
}
|
|
return OPT_DEFAULT;
|
|
}
|
|
|
|
/**
|
|
This is an internal method that handles preparation tasks common for
|
|
all system variable update service APIs:
|
|
- creates temporary THD for an operation, if needed
|
|
- validates that SESSION type is not used with temporary THD
|
|
|
|
@param hlp Execution context handle.
|
|
@param variable_type One of GLOBAL, SESSION, PERSIST, PERSIST_ONLY.
|
|
For any other value (including NULL), GLOBAL is
|
|
assumed. SESSION is not supported for a temporary THD.
|
|
@param variable_name MySQL string of the variable name.
|
|
@param var_type Reference to output variable type enumeration (avoids parsing
|
|
type multiple times).
|
|
@retval FALSE Success
|
|
@retval TRUE Failure, error set
|
|
*/
|
|
static bool prepare_thread_and_validate(Set_variables_helper &hlp,
|
|
const char *variable_type,
|
|
my_h_string variable_name,
|
|
enum_var_type &var_type) {
|
|
var_type = sysvar_type(variable_type);
|
|
if (var_type == OPT_DEFAULT) var_type = OPT_GLOBAL;
|
|
|
|
/* Use either the THD provided or create a temporary one */
|
|
if (hlp.is_auto_thd()) {
|
|
/* A session variable update for a temporary THD has no effect
|
|
and is not supported. */
|
|
if (var_type == OPT_SESSION) {
|
|
String *name = reinterpret_cast<String *>(variable_name);
|
|
LogErr(ERROR_LEVEL, ER_TMP_SESSION_FOR_VAR, name->c_ptr_safe());
|
|
return true;
|
|
}
|
|
/*
|
|
Set a temporary lock wait timeout before updating the system variable.
|
|
Some system variables, such as super-read-only, can be blocked by other
|
|
locks during the update. Should that happen, we don't want to be holding
|
|
LOCK_system_variables_hash.
|
|
*/
|
|
hlp.get_thd()->variables.lock_wait_timeout = 5;
|
|
}
|
|
// success
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
Common system variable update code (used by different variable value types).
|
|
|
|
@param hlp An execution context
|
|
@param var_type Enum type matching one of GLOBAL, SESSION, PERSIST,
|
|
PERSIST_ONLY.
|
|
@param variable_base MySQL string of the variable prefix, NULL if none.
|
|
@param variable_name MySQL string of the variable name.
|
|
@param variable_value Pointer to Item object storing the value of the correct
|
|
@retval false Success
|
|
@retval true Failure, error set
|
|
*/
|
|
static bool common_system_variable_update_set(Set_variables_helper &hlp,
|
|
enum_var_type var_type,
|
|
my_h_string variable_base,
|
|
my_h_string variable_name,
|
|
Item *variable_value) {
|
|
/* Cannot set system variable when server is shutting down. */
|
|
rwlock_scoped_lock rdlock(&LOCK_server_shutting_down, false, __FILE__,
|
|
__LINE__);
|
|
if (server_shutting_down) return true;
|
|
|
|
String *base = reinterpret_cast<String *>(variable_base);
|
|
String *name = reinterpret_cast<String *>(variable_name);
|
|
|
|
if (hlp.add_variable(base ? base->ptr() : nullptr, base ? base->length() : 0,
|
|
name->ptr(), name->length(), variable_value, var_type))
|
|
return true;
|
|
|
|
return hlp.execute();
|
|
}
|
|
|
|
/**
|
|
Implementation for the
|
|
@ref mysql_service_mysql_system_variable_update_string_t service.
|
|
|
|
Sets the value of a system variable to a new value specified in
|
|
variable_value. Works only for system variables taking unsigned string values.
|
|
May generate an SQL error that it stores into the current THD (if available).
|
|
|
|
@param hthd THD session handle. If NULL, then a temporary THD will be created
|
|
and then deleted.
|
|
@param variable_type One of GLOBAL, SESSION, PERSIST, PERSIST_ONLY.
|
|
For any other value (including NULL), GLOBAL is
|
|
assumed. SESSION is not supported for a temporary THD.
|
|
@param variable_base MySQL string of the variable prefix, NULL if none.
|
|
@param variable_name MySQL string of the variable name.
|
|
@param variable_value MySQL string value to pass to the variable.
|
|
@retval FALSE Success
|
|
@retval TRUE Failure, error set
|
|
@sa @ref mysql_service_mysql_system_variable_update_string_t
|
|
*/
|
|
DEFINE_BOOL_METHOD(mysql_system_variable_update_imp::set_string,
|
|
(MYSQL_THD hthd, const char *variable_type,
|
|
my_h_string variable_base, my_h_string variable_name,
|
|
my_h_string variable_value)) {
|
|
try {
|
|
enum_var_type var_type;
|
|
Set_variables_helper hlp(static_cast<THD *>(hthd));
|
|
|
|
if (variable_value == nullptr) return true;
|
|
|
|
if (prepare_thread_and_validate(hlp, variable_type, variable_name,
|
|
var_type))
|
|
return true;
|
|
|
|
String *value = reinterpret_cast<String *>(variable_value);
|
|
Item *value_str = new (hlp.get_thd()->mem_root)
|
|
Item_string(value->c_ptr_safe(), value->length(), value->charset());
|
|
|
|
return common_system_variable_update_set(hlp, var_type, variable_base,
|
|
variable_name, value_str);
|
|
} catch (...) {
|
|
mysql_components_handle_std_exception(__func__);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
Sets the value of a system variable to a new signed integer value.
|
|
|
|
Works only for system variables taking integer or compatible values.
|
|
Passing non-NULL THD means that the operation will be executed within the
|
|
scope of existing transaction, thus any operation side effects impacting
|
|
transaction itself (for example it may generate an SQL error that it stores
|
|
into the current THD). If using existing THD, security context of the thread
|
|
is checked to make sure that required privileges exist. Passing NULL makes a
|
|
temporary THD created as a execution context (and destroyed afterwards), i.e.
|
|
no impacts on existing transactions. It doesn't make sense to change SESSION
|
|
variable on a temporary THD, so this operation will generate error.
|
|
|
|
@param hthd thread session handle. if NULL a temporary one will be created
|
|
and then deleted.
|
|
@param variable_type One of GLOBAL, SESSION, PERSIST, PERSIST_ONLY.
|
|
For any other value (including NULL), GLOBAL is
|
|
assumed. SESSION is not supported for a temporary THD.
|
|
@param variable_base a mysql string of the variable name prefix. NULL if
|
|
none
|
|
@param variable_name MySQL string of the variable name
|
|
@param variable_value long long to set as value
|
|
@retval FALSE success
|
|
@retval TRUE failure, error set. For error info, see THD if supplied.
|
|
*/
|
|
DEFINE_BOOL_METHOD(mysql_system_variable_update_imp::set_signed,
|
|
(MYSQL_THD hthd, const char *variable_type,
|
|
my_h_string variable_base, my_h_string variable_name,
|
|
long long variable_value)) {
|
|
try {
|
|
enum_var_type var_type;
|
|
Set_variables_helper hlp(static_cast<THD *>(hthd));
|
|
|
|
if (prepare_thread_and_validate(hlp, variable_type, variable_name,
|
|
var_type))
|
|
return true;
|
|
|
|
Item *value_num = new (hlp.get_thd()->mem_root) Item_int(variable_value);
|
|
|
|
return common_system_variable_update_set(hlp, var_type, variable_base,
|
|
variable_name, value_num);
|
|
} catch (...) {
|
|
mysql_components_handle_std_exception(__func__);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
Sets the value of a system variable to a new unsigned integer value.
|
|
|
|
Same analysis as for mysql_system_variable_update_integer::set_signed
|
|
applies here as well.
|
|
|
|
@param hthd thread session handle. if NULL a temporary one will be created
|
|
and then deleted.
|
|
@param variable_type One of GLOBAL, SESSION, PERSIST, PERSIST_ONLY.
|
|
For any other value (including NULL), GLOBAL is
|
|
assumed. SESSION is not supported for a temporary THD.
|
|
@param variable_base a mysql string of the variable name prefix. NULL if
|
|
none
|
|
@param variable_name MySQL string of the variable name
|
|
@param variable_value unsigned long long to set as value
|
|
@retval FALSE success
|
|
@retval TRUE failure, error set. For error info, see THD if supplied.
|
|
*/
|
|
DEFINE_BOOL_METHOD(mysql_system_variable_update_imp::set_unsigned,
|
|
(MYSQL_THD hthd, const char *variable_type,
|
|
my_h_string variable_base, my_h_string variable_name,
|
|
unsigned long long variable_value)) {
|
|
try {
|
|
enum_var_type var_type;
|
|
Set_variables_helper hlp(static_cast<THD *>(hthd));
|
|
|
|
if (prepare_thread_and_validate(hlp, variable_type, variable_name,
|
|
var_type))
|
|
return true;
|
|
|
|
Item *value_num = new (hlp.get_thd()->mem_root) Item_uint(variable_value);
|
|
|
|
return common_system_variable_update_set(hlp, var_type, variable_base,
|
|
variable_name, value_num);
|
|
} catch (...) {
|
|
mysql_components_handle_std_exception(__func__);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
Sets the value of a system variable to its default value.
|
|
|
|
Same analysis as for mysql_system_variable_update_integer::set_signed
|
|
applies here as well.
|
|
|
|
@param hthd thread session handle. if NULL a temporary one will be created
|
|
and then removed.
|
|
@param variable_type One of GLOBAL, SESSION, PERSIST, PERSIST_ONLY.
|
|
For any other value (including NULL), GLOBAL is
|
|
assumed. SESSION is not supported for a temporary THD.
|
|
@param variable_base a mysql string of the variable name prefix. NULL if
|
|
none
|
|
@param variable_name MySQL string of the variable name
|
|
@retval FALSE success
|
|
@retval TRUE failure, error set. For error info, see THD if supplied.
|
|
*/
|
|
DEFINE_BOOL_METHOD(mysql_system_variable_update_imp::set_default,
|
|
(MYSQL_THD hthd, const char *variable_type,
|
|
my_h_string variable_base, my_h_string variable_name)) {
|
|
try {
|
|
enum_var_type var_type;
|
|
Set_variables_helper hlp(static_cast<THD *>(hthd));
|
|
|
|
if (prepare_thread_and_validate(hlp, variable_type, variable_name,
|
|
var_type))
|
|
return true;
|
|
|
|
return common_system_variable_update_set(hlp, var_type, variable_base,
|
|
variable_name, nullptr);
|
|
} catch (...) {
|
|
mysql_components_handle_std_exception(__func__);
|
|
}
|
|
return true;
|
|
}
|