if (add_item_to_list(thd, item))
MYSQL_YYABORT;
(thd->lex->current_select->with_wild)++;
}
;
select_item:
remember_name select_item2 remember_end select_alias
{
THD *thd= YYTHD;
DBUG_ASSERT($1 < $3);
if (add_item_to_list(thd, $2))
MYSQL_YYABORT;
if ($4.str)
{
if (Lex->sql_command == SQLCOM_CREATE_VIEW &&
check_column_name($4.str))
{
my_error(ER_WRONG_COLUMN_NAME, MYF(0), $4.str);
MYSQL_YYABORT;
}
$2->is_autogenerated_name= FALSE;
$2->set_name($4.str, $4.length, system_charset_info);
}
else if (!$2->name)
{
$2->set_name($1, (uint) ($3 - $1), thd->charset());
}
}
;
variable:
'@'
{
if (! Lex->parsing_options.allows_variable)
{
my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
MYSQL_YYABORT;
}
}
variable_aux
{
$$= $3;
}
;
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);
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();
}
;
下面我们仔细的来看一下整个SELECT语法节点的执行流程:
query->verb_clause->statement->select->select_init->select_init2->select_part2->select_item_list->select_item…->variable
语法是自上而下的,实际的解析过程是自下而上的匹配过程。词法分析首先yacc送来SELECT关键字,上一节说过为什么SELECT是关键字呢?
我们看下sql_yacc.yy,可以找到如下一个定义:
%token SELECT_SYM /* SQL-2003-R */
这里其实是定义了一个宏SELECT_SYM,代表一个关键字,宏定义如下:
#define SELECT_SYM 687
那么字符串"SELECT"和SELECT_SYM是如何联系在一起的呢?我们回头看下MYSQLlex中的find_keyword这个函数:
static int find_keyword(Lex_input_stream *lip, uint len, bool function)
{
const char *tok= lip->get_tok_start();
SYMBOL *symbol= get_hash_symbol(tok, len, function);
if (symbol)
{
lip->yylval->symbol.symbol=symbol;
lip->yylval->symbol.str= (char*) tok;
lip->yylval->symbol.length=len;
if ((symbol->tok == NOT_SYM) &&