MySQL源码 解析器

  sql请求发送到server端,需要经过解析器生成内部的数据结构对象,以方便进行优化和生成执行计划。解析器主要做了两件事情,词法分析和语法分析。
词法和语法分析:mysql使用lex词法分析器,yacc语法分析器进行分析,最后保存到lex对象结构中。
 
例如:     select id, name from xpchild where id=1
 
1. 在mysql_parse函数中使用lex_start初始化thd->lex对象,然后调用yacc中的MYSQLparse函数进行词法和语法分析。
      sql_yacc.cc是yacc在编译后生成出来的源文件,而在sql_yacc.yy文件中定义了大量的语法规则。下面找到select的语法定义。
 
2. 语法解析部分:
  根据词法分析器的分析后的结果,应用下面的语法规则
  
 %token  SELECT_SYM

     select:
          select_init
          {
            LEX *lex= Lex;
            lex->sql_command= SQLCOM_SELECT;
          };

     select_item_list:
          select_item_list , select_item
        | select_item
        | *
          {
            THD *thd= YYTHD;
            Item *item= new (thd->mem_root) Item_field(&thd->lex->current_select->context,NULL, NULL, "*");
            if (item == NULL)
              MYSQL_YYABORT;
            if (add_item_to_list(thd, item))
              MYSQL_YYABORT;
            (thd->lex->current_select->with_wild)++;
          };

where_clause:
          /* empty */  { Select->where= 0; }
        | WHERE
          {
            Select->parsing_place= IN_WHERE;
          }
          expr
          {
            SELECT_LEX *select= Select;
            select->where= $3;
            select->parsing_place= NO_MATTER;
            if ($3)
              $3->top_level_item();
          };
可以看到,上面的sql语句被解析出来的几个部分:(保存在lex结构中)
     1. sql_command=SQLCOM_SELECT;
     2. where子句:select_lex->where
     3. table列表:select_lex->table_list
     4. 字段列表:select_lex->item_list
具体内容:
     1.  table_list 
  
     (gdb) print select_lex->table_list  
     $33 = {
            <Sql_alloc> = {<No data fields>},
                 members of SQL_I_List<TABLE_LIST>:
                 elements = 1,
                 first = 0x8ca04818,
                 next = 0x8ca04818
  只有一个table, db = 0x8ca04bc8 "test", table_name = 0x8ca047f0 "xpchild"
 
  2.   where
          (gdb) print select_lex->where->type()
                    $32 = Item::FUNC_ITEM
          (gdb) p select_lex->where)->args))->type()
                    $30 = Item::FIELD_ITEM
          (gdb) p select_lex->where)->args++))->type()
                    $29 = Item::INT_ITEM

    结构如下:

where
     |-->FUNC_ITEM
         |-->FIELD_ITEM("id")
         |-->INT_ITEM(1)

  3.   item_list

          (gdb) print *(Item_field*)(select_lex->item_list->first->info)
                         name = 0x8ca04758 "id",
          (gdb) print *(Item_field*)(select_lex->item_list->first->next->info)
                          name = 0x8cb047f8 "name", 

    结构如下:

item_list:
     |-->Item_field("id")
     |-->Item_field("name")

 

MySQL源码 解析器,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。