Mysql源码学习――打造专属语法(四)

2014-11-24 10:35:16 · 作者: · 浏览: 5
到symbols定义,在文件lex.h中,看到这个数组,我想大家就会了然了:

1

{ "SELECT", SYM(SELECT_SYM)},

这就是将SELECT字符串与SELECT_SYM关联的地方了,bingo!

我们再来捋一下SELECT解析的思路,词法分析解析到SELECT后,执行find_keyword去找是否是关键字,发现SELECT是关键字,

于是给yacc返回SELECT_SYM用于语法分析。note:如果我们想要加关键字,只需在sql_yacc.yy上面添加一个%token xxx,

然后在lex.h里面加入相应的字符串和SYM的对应即可。

下面看下@@version_comment这个系统变量如何解析的,首先给出其语法节点:

variable_aux:

...

| '@' 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();

}

;

这里便是查找系统变量的地方了:get_system_var,我们跟进去看下:

Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,

LEX_STRING component)

{

sys_var *var;

LEX_STRING *base_name, *component_name;

if (component.str)

{

base_name= &component;

component_name= &name;

}

else

{

base_name= &name;

component_name= &component; // Empty string

}

if (!(var= find_sys_var(thd, base_name->str, base_name->length)))

return 0;

if (component.str)

{

if (!var->is_struct())

{

my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), base_name->str);

return 0;

}

}

thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);

set_if_smaller(component_name->length, MAX_SYS_VAR_LENGTH);

return new Item_func_get_system_var(var, var_type, component_name,

NULL, 0);

}

由find_sys_var函数不断跟进去,我们跟到了set_var.cc,找到了如下定义:

1

static sys_var_chain vars = { NULL, NULL };

系统变量都会挂载在次链上。在文件中,搜索到了version_comment:

static sys_var_const_str sys_version_comment(&vars, "version_comment",

MYSQL_COMPILATION_COMMENT);

1

#define MYSQL_COMPILATION_COMMENT "Source distribution"

这便是将version_comment加载到vars的链表上。

OK,我们也来加一个自己的系统变量:

static sys_var_const_str sys_version_comment(&vars, "version_comment",

MYSQL_COMPILATION_COMMENT);

/**add by nocode */

static sys_var_const_str sys_version_comment_test(&vars, "nocode_test_sysvar",

MYSQL_COMPILATION_NOCODE_TEST_SYSVAR);

#define MYSQL_COMPILATION_COMMENT "Source distribution"

#define MYSQL_COMPILATION_NOCODE_TEST_SYSVAR "No code in heart" /*add by nocode*/

1

注释add by nocode的地方,即是新添加的系统变量和宏定义,我们的系统变量叫@@nocode_test_sysvar,其值为No code in heartOK,重新编译代码,执行SELECT语句,OK了。

mysql> select @@nocode_test_sysvar;

+----------------------+

| @@nocode_test_sysvar |

+----------------------+

| No code in heart |

+----------------------+

1 row in set (0.01 sec)

上面添加了一个系统变量,并没有修改语法文件sql_yacc.yy,为了加深理解,我们添加一个属于自己的语法:nocode语法,为了简单化实现,我们的目标很简单,在客户端输入no_code后显示字符串"MAKE BY NOCODE"。

定义关键字

首先在sql_yacc.yy文件中添加相应的SYMBOL

%token NO_SYM /* SQL-2003-R */

%token