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.
|
avoid temporary tables replication failure.
|
||||||
*/
|
*/
|
||||||
variables.pseudo_thread_id= thread_id;
|
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);
|
mysql_mutex_unlock(&LOCK_global_system_variables);
|
||||||
|
|
||||||
user_time.val= start_time= start_time_sec_part= 0;
|
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.
|
This is used for taging error messages in the log files.
|
||||||
*/
|
*/
|
||||||
LEX_CSTRING connection_name;
|
LEX_CSTRING connection_name;
|
||||||
char default_master_connection_buff[MAX_CONNECTION_NAME+1];
|
|
||||||
uint8 password; /* 0, 1 or 2 */
|
uint8 password; /* 0, 1 or 2 */
|
||||||
uint8 failed_com_change_user;
|
uint8 failed_com_change_user;
|
||||||
bool slave_thread;
|
bool slave_thread;
|
||||||
|
@ -3279,6 +3279,9 @@ void plugin_thdvar_init(THD *thd)
|
|||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
thd->session_tracker.sysvars.deinit(thd);
|
thd->session_tracker.sysvars.deinit(thd);
|
||||||
#endif
|
#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;
|
thd->variables= global_system_variables;
|
||||||
|
|
||||||
@ -3301,6 +3304,11 @@ void plugin_thdvar_init(THD *thd)
|
|||||||
intern_plugin_unlock(NULL, old_enforced_table_plugin);
|
intern_plugin_unlock(NULL, old_enforced_table_plugin);
|
||||||
mysql_mutex_unlock(&LOCK_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
|
#ifndef EMBEDDED_LIBRARY
|
||||||
thd->session_tracker.sysvars.init(thd);
|
thd->session_tracker.sysvars.init(thd);
|
||||||
#endif
|
#endif
|
||||||
@ -3372,6 +3380,9 @@ void plugin_thdvar_cleanup(THD *thd)
|
|||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
thd->session_tracker.sysvars.deinit(thd);
|
thd->session_tracker.sysvars.deinit(thd);
|
||||||
#endif
|
#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);
|
mysql_mutex_lock(&LOCK_plugin);
|
||||||
|
|
||||||
|
@ -1346,12 +1346,11 @@ static bool check_master_connection(sys_var *self, THD *thd, set_var *var)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Sys_var_session_lexstring Sys_default_master_connection(
|
static Sys_var_lexstring Sys_default_master_connection(
|
||||||
"default_master_connection",
|
"default_master_connection",
|
||||||
"Master connection to use for all slave variables and slave commands",
|
"Master connection to use for all slave variables and slave commands",
|
||||||
SESSION_ONLY(default_master_connection),
|
SESSION_ONLY(default_master_connection), NO_CMD_LINE, DEFAULT(""),
|
||||||
NO_CMD_LINE,
|
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_master_connection));
|
||||||
DEFAULT(""), MAX_CONNECTION_NAME, ON_CHECK(check_master_connection));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static Sys_var_charptr_fscs Sys_init_file(
|
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*
|
Backing store: char*
|
||||||
|
|
||||||
@note
|
@note
|
||||||
This class supports only GLOBAL variables, because THD on destruction
|
|
||||||
does not destroy individual members of SV, there's no way to free
|
Note that the memory management for SESSION_VAR's is manual, the
|
||||||
allocated string variables for every thread.
|
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:
|
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,
|
const char *comment, int flag_args, ptrdiff_t off, size_t size,
|
||||||
CMD_LINE getopt,
|
CMD_LINE getopt,
|
||||||
const char *def_val, PolyLock *lock=0,
|
const char *def_val, PolyLock *lock=0,
|
||||||
@ -519,8 +523,9 @@ public:
|
|||||||
*/
|
*/
|
||||||
option.var_type|= (flags & ALLOCATED) ? GET_STR_ALLOC : GET_STR;
|
option.var_type|= (flags & ALLOCATED) ? GET_STR_ALLOC : GET_STR;
|
||||||
global_var(const char*)= def_val;
|
global_var(const char*)= def_val;
|
||||||
|
SYSVAR_ASSERT(size == sizeof(char *));
|
||||||
}
|
}
|
||||||
void cleanup()
|
void cleanup() override
|
||||||
{
|
{
|
||||||
if (flags & ALLOCATED)
|
if (flags & ALLOCATED)
|
||||||
{
|
{
|
||||||
@ -558,17 +563,26 @@ public:
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool do_check(THD *thd, set_var *var)
|
bool do_check(THD *thd, set_var *var) override
|
||||||
{ return do_string_check(thd, var, charset(thd)); }
|
{
|
||||||
bool session_update(THD *thd, set_var *var)= 0;
|
if (do_string_check(thd, var, charset(thd)))
|
||||||
char *global_update_prepare(THD *thd, set_var *var)
|
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;
|
char *new_val, *ptr= var->save_result.string_value.str;
|
||||||
size_t len=var->save_result.string_value.length;
|
size_t len=var->save_result.string_value.length;
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
new_val= (char*)my_memdup(key_memory_Sys_var_charptr_value,
|
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;
|
if (!new_val) return 0;
|
||||||
new_val[len]=0;
|
new_val[len]=0;
|
||||||
}
|
}
|
||||||
@ -576,6 +590,13 @@ public:
|
|||||||
new_val= 0;
|
new_val= 0;
|
||||||
return new_val;
|
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)
|
void global_update_finish(char *new_val)
|
||||||
{
|
{
|
||||||
if (flags & ALLOCATED)
|
if (flags & ALLOCATED)
|
||||||
@ -583,14 +604,19 @@ public:
|
|||||||
flags|= ALLOCATED;
|
flags|= ALLOCATED;
|
||||||
global_var(char*)= new_val;
|
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);
|
global_update_finish(new_val);
|
||||||
return (new_val == 0 && var->save_result.string_value.str != 0);
|
return (new_val == 0 && var->save_result.string_value.str != 0);
|
||||||
}
|
}
|
||||||
void session_save_default(THD *thd, set_var *var)= 0;
|
void session_save_default(THD *, set_var *var) override
|
||||||
void global_save_default(THD *thd, set_var *var)
|
{
|
||||||
|
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;
|
char *ptr= (char*)(intptr)option.def_value;
|
||||||
var->save_result.string_value.str= ptr;
|
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
|
class Sys_var_charptr_fscs: public Sys_var_charptr
|
||||||
{
|
{
|
||||||
using Sys_var_charptr::Sys_var_charptr;
|
using Sys_var_charptr::Sys_var_charptr;
|
||||||
@ -637,23 +634,22 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
class Sys_var_sesvartrack: public Sys_var_charptr_base
|
class Sys_var_sesvartrack: public Sys_var_charptr
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Sys_var_sesvartrack(const char *name_arg,
|
Sys_var_sesvartrack(const char *name_arg,
|
||||||
const char *comment,
|
const char *comment,
|
||||||
CMD_LINE getopt,
|
CMD_LINE getopt,
|
||||||
const char *def_val, PolyLock *lock= 0) :
|
const char *def_val, PolyLock *lock= 0) :
|
||||||
Sys_var_charptr_base(name_arg, comment,
|
Sys_var_charptr(name_arg, comment,
|
||||||
SESSION_VAR(session_track_system_variables),
|
SESSION_VAR(session_track_system_variables),
|
||||||
getopt, def_val, lock,
|
getopt, def_val, lock,
|
||||||
VARIABLE_NOT_IN_BINLOG, 0, 0, 0)
|
VARIABLE_NOT_IN_BINLOG, 0, 0, 0)
|
||||||
{}
|
{}
|
||||||
bool do_check(THD *thd, set_var *var)
|
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,
|
sysvartrack_validate_value(thd, var->save_result.string_value.str,
|
||||||
var->save_result.string_value.length))
|
var->save_result.string_value.length))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -661,7 +657,7 @@ public:
|
|||||||
}
|
}
|
||||||
bool global_update(THD *thd, set_var *var)
|
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 (new_val)
|
||||||
{
|
{
|
||||||
if (sysvartrack_global_update(thd, new_val,
|
if (sysvartrack_global_update(thd, new_val,
|
||||||
@ -858,7 +854,19 @@ public:
|
|||||||
Backing store: LEX_CSTRING
|
Backing store: LEX_CSTRING
|
||||||
|
|
||||||
@note
|
@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
|
class Sys_var_lexstring: public Sys_var_charptr
|
||||||
{
|
{
|
||||||
@ -886,88 +894,15 @@ public:
|
|||||||
global_var(LEX_CSTRING).length= var->save_result.string_value.length;
|
global_var(LEX_CSTRING).length= var->save_result.string_value.length;
|
||||||
return false;
|
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)
|
bool session_update(THD *thd, set_var *var)
|
||||||
{
|
{
|
||||||
LEX_CSTRING *tmp= &session_var(thd, LEX_CSTRING);
|
if (Sys_var_charptr::session_update(thd, var))
|
||||||
tmp->length= var->save_result.string_value.length;
|
return true;
|
||||||
/* Store as \0 terminated string (just to be safe) */
|
session_var(thd, LEX_CSTRING).length= var->save_result.string_value.length;
|
||||||
strmake((char*) tmp->str, var->save_result.string_value.str, tmp->length);
|
|
||||||
return false;
|
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
|
#ifndef DBUG_OFF
|
||||||
/**
|
/**
|
||||||
@@session.debug_dbug and @@global.debug_dbug variables.
|
@@session.debug_dbug and @@global.debug_dbug variables.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user