• 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")
  • 相关阅读:
    适合 C++ 新手学习的开源项目——在 GitHub 学编程
    原生JS封装常用函数
    C# 将excel文件导入到SqlServer数据库
    热配置的部署以及容易失败原因
    连接真机开发安卓(Android)移动app MUI框架 添加购物车等——混合式开发(四)
    标志寄存器06 零基础入门学习汇编语言59
    指针07 零基础入门学习C语言47
    标志寄存器05 零基础入门学习汇编语言58
    标志寄存器03 零基础入门学习汇编语言56
    标志寄存器04 零基础入门学习汇编语言57
  • 原文地址:https://www.cnblogs.com/xpchild/p/3730079.html
Copyright © 2020-2023  润新知