以下语句
select @@read_buffer_size;
mysql最终是如何解析的呢?
yacc的归纳过程如下:
select_item——>remember_name
expr remember_end
select_alias——>expr——>bool_pri——>predicate——>bit_expr——>simple_expr——>variable——>variable_aux
variable_aux:
ident_or_text SET_VAR expr
{
Item_func_set_user_var *item;
$$= item=
new (YYTHD->mem_root) Item_func_set_user_var($1, $3, false);
if ($$ == NULL)
MYSQL_YYABORT;
LEX *lex= Lex;
lex->uncacheable(UNCACHEABLE_RAND);
lex->set_var_list.push_back(item);
}
| ident_or_text
{
$$= new (YYTHD->mem_root) Item_func_get_user_var($1);
if ($$ == NULL)
MYSQL_YYABORT;
LEX *lex= Lex;
lex->uncacheable(UNCACHEABLE_RAND);
}
|'@' opt_var_ident_type ident_or_text opt_component
{
/* disallow "SELECT @@global.global.variable" */
if ($3.str && $4.str && check_reserved_words(&$3))
{
my_parse_error(ER(ER_SYNTAX_ERROR));
MYSQL_YYABORT;
}
if (!($$= get_system_var(YYTHD, $2, $3, $4)))
MYSQL_YYABORT;
if (!((Item_func_get_system_var*) $$)->is_written_to_binlog())
Lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_VARIABLE);
}
;
get_system_var函数用来查找系统变量,返回结果是item类型,因为select中的字段的类型是item的子类
Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
LEX_STRING component)
内部调用find_sys_var不查找系统变量
sys_var *find_sys_var(THD *thd, const char *str, uint length)
{
sys_var *var;
sys_var_pluginvar *pi= NULL;
plugin_ref plugin;
DBUG_ENTER("find_sys_var");
mysql_mutex_lock(&LOCK_plugin);
mysql_rwlock_rdlock(&LOCK_system_variables_hash);
if ((var= intern_find_sys_var(str, length)) &&
(pi= var->cast_pluginvar()))
{
mysql_rwlock_unlock(&LOCK_system_variables_hash);
LEX *lex= thd ? thd->lex : 0;
if (!(plugin= my_intern_plugin_lock(lex, plugin_int_to_ref(pi->plugin))))
var= NULL; /* failed to lock it, it must be uninstalling */
else
if (!(plugin_state(plugin) & PLUGIN_IS_READY))
{
/* initialization not completed */
var= NULL;
intern_plugin_unlock(lex, plugin);
}
}
else
mysql_rwlock_unlock(&LOCK_system_variables_hash);
mysql_mutex_unlock(&LOCK_plugin);
if (!var)
my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
DBUG_RETURN(var);
}
find_sys_var调用intern_find_sys_var查找系统变量
sys_var *intern_find_sys_var(const char *str, uint length)
{
sys_var *var;
/*
This function is only called from the sql_plugin.cc.
A lock on LOCK_system_variable_hash should be held
*/
var= (sys_var*) my_hash_search(&system_variable_hash,
(uchar*) str, length ? length : strlen(str));
/* Don't show non-visible variables. */
if (var && var->not_visible())
return NULL;
return var;
}
即所有的系统变量定义在文件:sql/sys_vars_shared.h文件中
extern sys_var_chain all_sys_vars;
这个变量在何时赋值进行初始的呢?
我们来看如何声明一个变量:打开文件sql/sys_vars.cc,查看变量performance_schema的声明
static Sys_var_mybool Sys_pfs_enabled(
"performance_schema",
"Enable the performance schema.",
READ_ONLY GLOBAL_VAR(pfs_param.m_enabled),
CMD_LINE(OPT_ARG), DEFAULT(TRUE),
PFS_TRAILING_PROPERTIES);
这里performance_schema系统变量用类Sys_var_mybool 表示,看这个类的构造函数
class Sys_var_mybool: public Sys_var_typelib
{
public:
Sys_var_mybool(const char *name_arg,
const char *comment, int flag_args, ptrdiff_t off, size_t size,
CMD_LINE getopt,
my_bool 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,
int parse_flag= PARSE_NORMAL)
: Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
SHOW_MY_BOOL, bool_values, def_val, lock,
binlog_status_arg, on_check_func, on_update_func,
substitute, parse_flag)
{
……
这个类继承自Sys_var_typelib,再看这个类的构造函数
Sys_var_typelib(const char *name_arg,
const char *comment, int flag_args, ptrdiff_t off,
CMD_LINE getopt,
SHOW_TYPE show_val_type_arg, const char *values[],
ulonglong def_val, PolyLock *lock,
enum binlog_status_enum binlog_status_arg,
on_check_function on_check_func, on_update_function on_update_func,
const char *substitute, int parse_flag= PARSE_NORMAL)
:sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
getopt.arg_type, show_val_type_arg, def_val, lock,
binlog_status_arg, on_check_func,
on_update_func, substitute, parse_flag)
而Sys_var_typelib又继承自sys_var类,这个时候把all_sys_vars这个全局变量的指针传到sys_var的构造函数中
最后看sys_var类的构造函数
sys_var::sys_var(sys_var_chain *chain, const char *name_arg,
const char *comment, int flags_arg, ptrdiff_t off,
int getopt_id, enum get_opt_arg_type getopt_arg_type,
SHOW_TYPE show_val_type_arg, longlong def_val,
PolyLock *lock, enum binlog_status_enum binlog_status_arg,
on_check_function on_check_func,
on_update_function on_update_func,
const char *substitute, int parse_flag) :
next(0),
binlog_status(binlog_status_arg),
flags(flags_arg), m_parse_flag(parse_flag), show_val_type(show_val_type_arg),
guard(lock), offset(off), on_check(on_check_func), on_update(on_update_func),
deprecation_substitute(substitute),
is_os_charset(FALSE)
{
/*
There is a limitation in handle_options() related to short options:
- either all short options should be declared when parsing in multiple stages,
- or none should be declared.
Because a lot of short options are used in the normal parsing phase
for mysqld, we enforce here that no short option is present
in the first (PARSE_EARLY) stage.
See handle_options() for details.
*/
DBUG_ASSERT(parse_flag == PARSE_NORMAL || getopt_id <= 0 || getopt_id >= 255);
name.str= name_arg; // ER_NO_DEFAULT relies on 0-termination of name_arg
name.length= strlen(name_arg); // and so does this.
DBUG_ASSERT(name.length <= NAME_CHAR_LEN);
memset(&option, 0, sizeof(option));
option.name= name_arg;
option.id= getopt_id;
option.comment= comment;
option.arg_type= getopt_arg_type;
option.value= (uchar **)global_var_ptr();
option.def_value= def_val;
if (chain->last)
chain->last->next= this;
else
chain->first= this;
chain->last= this;
}
这里会把新声明的系统变量加到all_sys_vars这个全局变量所指向的链表中
整个类的层次如下,Sys_var_mybool——Sys_var_typelib——sys_var,其中在sys_var这个类中实现将所有系统变量加入到链表中的功能
而添加系统变量调用mysql_add_sys_var_chain来完成的