cleanup: string sys_var types
Merge sys_var_charptr with sys_var_charptr_base, as well as merge Sys_var_session_lexstring into Sys_var_lexstring. Also refactored update methods of sys_var_charptr accordingly. Because the class is more generic, session_update() calls sys_var_charptr::session_update() which does not assume a buffer field associated with THD, but instead call strdup/free, we get rid of THD::default_master_connection_buff accordingly. This also makes THD smaller by ~192 bytes, and there can be many thousands of concurrent THDs.
This commit is contained in:
parent
d16817c477
commit
6151bde48c
10
mysql-test/suite/sys_vars/r/mdev_15935.result
Normal file
10
mysql-test/suite/sys_vars/r/mdev_15935.result
Normal file
@ -0,0 +1,10 @@
|
||||
#
|
||||
# test cleanup of sys_var classes
|
||||
#
|
||||
set global init_connect=".................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................";
|
||||
ERROR HY000: String '......................................................................' is too long for init_connect (should be no longer than 2000)
|
||||
set global ft_boolean_syntax=".................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................";
|
||||
ERROR HY000: String '......................................................................' is too long for ft_boolean_syntax (should be no longer than 2000)
|
||||
#
|
||||
# end of test mdev_15935
|
||||
#
|
13
mysql-test/suite/sys_vars/t/mdev_15935.test
Normal file
13
mysql-test/suite/sys_vars/t/mdev_15935.test
Normal file
@ -0,0 +1,13 @@
|
||||
--echo #
|
||||
--echo # test cleanup of sys_var classes
|
||||
--echo #
|
||||
|
||||
--let $long_string=`select repeat('.', 2001)`
|
||||
--error ER_WRONG_STRING_LENGTH
|
||||
eval set global init_connect="$long_string";
|
||||
--error ER_WRONG_STRING_LENGTH
|
||||
eval set global ft_boolean_syntax="$long_string";
|
||||
|
||||
--echo #
|
||||
--echo # end of test mdev_15935
|
||||
--echo #
|
@ -1235,10 +1235,7 @@ void THD::init()
|
||||
avoid temporary tables replication failure.
|
||||
*/
|
||||
variables.pseudo_thread_id= thread_id;
|
||||
variables.default_master_connection.str= default_master_connection_buff;
|
||||
::strmake(default_master_connection_buff,
|
||||
global_system_variables.default_master_connection.str,
|
||||
variables.default_master_connection.length);
|
||||
|
||||
mysql_mutex_unlock(&LOCK_global_system_variables);
|
||||
|
||||
user_time.val= start_time= start_time_sec_part= 0;
|
||||
|
@ -3750,7 +3750,6 @@ public:
|
||||
This is used for taging error messages in the log files.
|
||||
*/
|
||||
LEX_CSTRING connection_name;
|
||||
char default_master_connection_buff[MAX_CONNECTION_NAME+1];
|
||||
uint8 password; /* 0, 1 or 2 */
|
||||
uint8 failed_com_change_user;
|
||||
bool slave_thread;
|
||||
|
@ -3279,6 +3279,9 @@ void plugin_thdvar_init(THD *thd)
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
thd->session_tracker.sysvars.deinit(thd);
|
||||
#endif
|
||||
my_free((char*) thd->variables.default_master_connection.str);
|
||||
thd->variables.default_master_connection.str= 0;
|
||||
thd->variables.default_master_connection.length= 0;
|
||||
|
||||
thd->variables= global_system_variables;
|
||||
|
||||
@ -3301,6 +3304,11 @@ void plugin_thdvar_init(THD *thd)
|
||||
intern_plugin_unlock(NULL, old_enforced_table_plugin);
|
||||
mysql_mutex_unlock(&LOCK_plugin);
|
||||
|
||||
thd->variables.default_master_connection.str=
|
||||
my_strndup(key_memory_Sys_var_charptr_value,
|
||||
global_system_variables.default_master_connection.str,
|
||||
global_system_variables.default_master_connection.length,
|
||||
MYF(MY_WME | MY_THREAD_SPECIFIC));
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
thd->session_tracker.sysvars.init(thd);
|
||||
#endif
|
||||
@ -3372,6 +3380,9 @@ void plugin_thdvar_cleanup(THD *thd)
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
thd->session_tracker.sysvars.deinit(thd);
|
||||
#endif
|
||||
my_free((char*) thd->variables.default_master_connection.str);
|
||||
thd->variables.default_master_connection.str= 0;
|
||||
thd->variables.default_master_connection.length= 0;
|
||||
|
||||
mysql_mutex_lock(&LOCK_plugin);
|
||||
|
||||
|
@ -1346,12 +1346,11 @@ static bool check_master_connection(sys_var *self, THD *thd, set_var *var)
|
||||
return false;
|
||||
}
|
||||
|
||||
static Sys_var_session_lexstring Sys_default_master_connection(
|
||||
static Sys_var_lexstring Sys_default_master_connection(
|
||||
"default_master_connection",
|
||||
"Master connection to use for all slave variables and slave commands",
|
||||
SESSION_ONLY(default_master_connection),
|
||||
NO_CMD_LINE,
|
||||
DEFAULT(""), MAX_CONNECTION_NAME, ON_CHECK(check_master_connection));
|
||||
SESSION_ONLY(default_master_connection), NO_CMD_LINE, DEFAULT(""),
|
||||
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_master_connection));
|
||||
#endif
|
||||
|
||||
static Sys_var_charptr_fscs Sys_init_file(
|
||||
|
193
sql/sys_vars.inl
193
sql/sys_vars.inl
@ -492,14 +492,18 @@ public:
|
||||
Backing store: char*
|
||||
|
||||
@note
|
||||
This class supports only GLOBAL variables, because THD on destruction
|
||||
does not destroy individual members of SV, there's no way to free
|
||||
allocated string variables for every thread.
|
||||
|
||||
Note that the memory management for SESSION_VAR's is manual, the
|
||||
value must be strdup'ed in THD::init() and freed in
|
||||
plugin_thdvar_cleanup(). TODO: it should be done automatically when
|
||||
we'll have more session string variables to justify it. Maybe some
|
||||
kind of a loop over all variables, like sys_var_end() in set_var.cc?
|
||||
*/
|
||||
class Sys_var_charptr_base: public sys_var
|
||||
class Sys_var_charptr: public sys_var
|
||||
{
|
||||
const size_t max_length= 2000;
|
||||
public:
|
||||
Sys_var_charptr_base(const char *name_arg,
|
||||
Sys_var_charptr(const char *name_arg,
|
||||
const char *comment, int flag_args, ptrdiff_t off, size_t size,
|
||||
CMD_LINE getopt,
|
||||
const char *def_val, PolyLock *lock=0,
|
||||
@ -519,8 +523,9 @@ public:
|
||||
*/
|
||||
option.var_type|= (flags & ALLOCATED) ? GET_STR_ALLOC : GET_STR;
|
||||
global_var(const char*)= def_val;
|
||||
SYSVAR_ASSERT(size == sizeof(char *));
|
||||
}
|
||||
void cleanup()
|
||||
void cleanup() override
|
||||
{
|
||||
if (flags & ALLOCATED)
|
||||
{
|
||||
@ -558,17 +563,26 @@ public:
|
||||
|
||||
return false;
|
||||
}
|
||||
bool do_check(THD *thd, set_var *var)
|
||||
{ return do_string_check(thd, var, charset(thd)); }
|
||||
bool session_update(THD *thd, set_var *var)= 0;
|
||||
char *global_update_prepare(THD *thd, set_var *var)
|
||||
bool do_check(THD *thd, set_var *var) override
|
||||
{
|
||||
if (do_string_check(thd, var, charset(thd)))
|
||||
return true;
|
||||
if (var->save_result.string_value.length > max_length)
|
||||
{
|
||||
my_error(ER_WRONG_STRING_LENGTH, MYF(0), var->save_result.string_value.str,
|
||||
name.str, (int) max_length);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
char *update_prepare(set_var *var, myf my_flags)
|
||||
{
|
||||
char *new_val, *ptr= var->save_result.string_value.str;
|
||||
size_t len=var->save_result.string_value.length;
|
||||
if (ptr)
|
||||
{
|
||||
new_val= (char*)my_memdup(key_memory_Sys_var_charptr_value,
|
||||
ptr, len+1, MYF(MY_WME));
|
||||
ptr, len+1, my_flags);
|
||||
if (!new_val) return 0;
|
||||
new_val[len]=0;
|
||||
}
|
||||
@ -576,6 +590,13 @@ public:
|
||||
new_val= 0;
|
||||
return new_val;
|
||||
}
|
||||
bool session_update(THD *thd, set_var *var) override
|
||||
{
|
||||
char *new_val= update_prepare(var, MYF(MY_WME | MY_THREAD_SPECIFIC));
|
||||
my_free(session_var(thd, char*));
|
||||
session_var(thd, char*)= new_val;
|
||||
return (new_val == 0 && var->save_result.string_value.str != 0);
|
||||
}
|
||||
void global_update_finish(char *new_val)
|
||||
{
|
||||
if (flags & ALLOCATED)
|
||||
@ -583,14 +604,19 @@ public:
|
||||
flags|= ALLOCATED;
|
||||
global_var(char*)= new_val;
|
||||
}
|
||||
bool global_update(THD *thd, set_var *var)
|
||||
bool global_update(THD *thd, set_var *var) override
|
||||
{
|
||||
char *new_val= global_update_prepare(thd, var);
|
||||
char *new_val= update_prepare(var, MYF(MY_WME));
|
||||
global_update_finish(new_val);
|
||||
return (new_val == 0 && var->save_result.string_value.str != 0);
|
||||
}
|
||||
void session_save_default(THD *thd, set_var *var)= 0;
|
||||
void global_save_default(THD *thd, set_var *var)
|
||||
void session_save_default(THD *, set_var *var) override
|
||||
{
|
||||
var->save_result.string_value.str= global_var(char*);
|
||||
var->save_result.string_value.length=
|
||||
strlen(var->save_result.string_value.str);
|
||||
}
|
||||
void global_save_default(THD *, set_var *var) override
|
||||
{
|
||||
char *ptr= (char*)(intptr)option.def_value;
|
||||
var->save_result.string_value.str= ptr;
|
||||
@ -598,35 +624,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class Sys_var_charptr: public Sys_var_charptr_base
|
||||
{
|
||||
public:
|
||||
Sys_var_charptr(const char *name_arg,
|
||||
const char *comment, int flag_args, ptrdiff_t off, size_t size,
|
||||
CMD_LINE getopt,
|
||||
const char *def_val, PolyLock *lock=0,
|
||||
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
|
||||
on_check_function on_check_func=0,
|
||||
on_update_function on_update_func=0,
|
||||
const char *substitute=0) :
|
||||
Sys_var_charptr_base(name_arg, comment, flag_args, off, size, getopt,
|
||||
def_val, lock, binlog_status_arg,
|
||||
on_check_func, on_update_func, substitute)
|
||||
{
|
||||
SYSVAR_ASSERT(scope() == GLOBAL);
|
||||
SYSVAR_ASSERT(size == sizeof(char *));
|
||||
}
|
||||
|
||||
bool session_update(THD *thd, set_var *var)
|
||||
{
|
||||
DBUG_ASSERT(FALSE);
|
||||
return true;
|
||||
}
|
||||
void session_save_default(THD *thd, set_var *var)
|
||||
{ DBUG_ASSERT(FALSE); }
|
||||
};
|
||||
|
||||
|
||||
class Sys_var_charptr_fscs: public Sys_var_charptr
|
||||
{
|
||||
using Sys_var_charptr::Sys_var_charptr;
|
||||
@ -637,23 +634,22 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
class Sys_var_sesvartrack: public Sys_var_charptr_base
|
||||
class Sys_var_sesvartrack: public Sys_var_charptr
|
||||
{
|
||||
public:
|
||||
Sys_var_sesvartrack(const char *name_arg,
|
||||
const char *comment,
|
||||
CMD_LINE getopt,
|
||||
const char *def_val, PolyLock *lock= 0) :
|
||||
Sys_var_charptr_base(name_arg, comment,
|
||||
SESSION_VAR(session_track_system_variables),
|
||||
getopt, def_val, lock,
|
||||
VARIABLE_NOT_IN_BINLOG, 0, 0, 0)
|
||||
Sys_var_charptr(name_arg, comment,
|
||||
SESSION_VAR(session_track_system_variables),
|
||||
getopt, def_val, lock,
|
||||
VARIABLE_NOT_IN_BINLOG, 0, 0, 0)
|
||||
{}
|
||||
bool do_check(THD *thd, set_var *var)
|
||||
{
|
||||
if (Sys_var_charptr_base::do_check(thd, var) ||
|
||||
if (Sys_var_charptr::do_string_check(thd, var, charset(thd)) ||
|
||||
sysvartrack_validate_value(thd, var->save_result.string_value.str,
|
||||
var->save_result.string_value.length))
|
||||
return TRUE;
|
||||
@ -661,7 +657,7 @@ public:
|
||||
}
|
||||
bool global_update(THD *thd, set_var *var)
|
||||
{
|
||||
char *new_val= global_update_prepare(thd, var);
|
||||
char *new_val= update_prepare(var, MYF(MY_WME));
|
||||
if (new_val)
|
||||
{
|
||||
if (sysvartrack_global_update(thd, new_val,
|
||||
@ -858,7 +854,19 @@ public:
|
||||
Backing store: LEX_CSTRING
|
||||
|
||||
@note
|
||||
Behaves exactly as Sys_var_charptr, only the backing store is different.
|
||||
Behaves exactly as Sys_var_charptr, only the backing store is
|
||||
different.
|
||||
|
||||
Note that for global variables handle_options() only sets the
|
||||
pointer, whereas the length must be updated manually to match, which
|
||||
is done in mysqld.cc. See e.g. opt_init_connect. TODO: it should be
|
||||
done automatically when we'll have more Sys_var_lexstring variables
|
||||
to justify it. Maybe some kind of a loop over all variables, like
|
||||
sys_var_end() in set_var.cc?
|
||||
|
||||
Note that as a subclass of Sys_var_charptr, the memory management
|
||||
for session Sys_var_lexstring's is manual too, see notes of
|
||||
Sys_var_charptr and for example default_master_connection.
|
||||
*/
|
||||
class Sys_var_lexstring: public Sys_var_charptr
|
||||
{
|
||||
@ -886,88 +894,15 @@ public:
|
||||
global_var(LEX_CSTRING).length= var->save_result.string_value.length;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
A LEX_CSTRING stored only in thd->variables
|
||||
Only to be used for small buffers
|
||||
*/
|
||||
|
||||
class Sys_var_session_lexstring: public sys_var
|
||||
{
|
||||
size_t max_length;
|
||||
public:
|
||||
Sys_var_session_lexstring(const char *name_arg,
|
||||
const char *comment, int flag_args,
|
||||
ptrdiff_t off, size_t size, CMD_LINE getopt,
|
||||
const char *def_val, size_t max_length_arg,
|
||||
on_check_function on_check_func=0,
|
||||
on_update_function on_update_func=0)
|
||||
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
|
||||
getopt.arg_type, SHOW_CHAR, (intptr)def_val,
|
||||
0, VARIABLE_NOT_IN_BINLOG, on_check_func, on_update_func,
|
||||
0),max_length(max_length_arg)
|
||||
{
|
||||
option.var_type|= GET_STR;
|
||||
SYSVAR_ASSERT(scope() == ONLY_SESSION)
|
||||
*const_cast<SHOW_TYPE*>(&show_val_type)= SHOW_LEX_STRING;
|
||||
}
|
||||
bool do_check(THD *thd, set_var *var)
|
||||
{
|
||||
char buff[STRING_BUFFER_USUAL_SIZE];
|
||||
String str(buff, sizeof(buff), system_charset_info), *res;
|
||||
|
||||
if (!(res=var->value->val_str(&str)))
|
||||
{
|
||||
var->save_result.string_value.str= 0; /* NULL */
|
||||
var->save_result.string_value.length= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (res->length() > max_length)
|
||||
{
|
||||
my_error(ER_WRONG_STRING_LENGTH, MYF(0),
|
||||
res->ptr(), name.str, (int) max_length);
|
||||
return true;
|
||||
}
|
||||
var->save_result.string_value.str= thd->strmake(res->ptr(),
|
||||
res->length());
|
||||
var->save_result.string_value.length= res->length();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool session_update(THD *thd, set_var *var)
|
||||
{
|
||||
LEX_CSTRING *tmp= &session_var(thd, LEX_CSTRING);
|
||||
tmp->length= var->save_result.string_value.length;
|
||||
/* Store as \0 terminated string (just to be safe) */
|
||||
strmake((char*) tmp->str, var->save_result.string_value.str, tmp->length);
|
||||
if (Sys_var_charptr::session_update(thd, var))
|
||||
return true;
|
||||
session_var(thd, LEX_CSTRING).length= var->save_result.string_value.length;
|
||||
return false;
|
||||
}
|
||||
bool global_update(THD *thd, set_var *var)
|
||||
{
|
||||
DBUG_ASSERT(FALSE);
|
||||
return false;
|
||||
}
|
||||
void session_save_default(THD *thd, set_var *var)
|
||||
{
|
||||
char *ptr= (char*)(intptr)option.def_value;
|
||||
var->save_result.string_value.str= ptr;
|
||||
var->save_result.string_value.length= strlen(ptr);
|
||||
}
|
||||
void global_save_default(THD *thd, set_var *var)
|
||||
{
|
||||
DBUG_ASSERT(FALSE);
|
||||
}
|
||||
const uchar *global_value_ptr(THD *thd, const LEX_CSTRING *base) const
|
||||
{
|
||||
DBUG_ASSERT(FALSE);
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
/**
|
||||
@@session.debug_dbug and @@global.debug_dbug variables.
|
||||
|
Loading…
x
Reference in New Issue
Block a user