MySQL內核源碼解讀-SQL解析一

本文是基於MySQL5.7.22進行分析
1. SQL整體執行流程圖
MySQL內核源碼解讀-SQL解析一
經過上面圖,能夠從全局上了解SQL語句執行流程以及與其餘模塊交互html

1.1 SQL查詢執行流程
MySQL內核源碼解讀-SQL解析一
MySQL內核源碼解讀-SQL解析一sql

2. 語法解析
2.1 編程語言知識回顧
在介紹具體的MySQL數據庫解析SQL以前,先來回歸一下編程語言的知識點數據庫

  1. 形式語言(Formal language)
    形式語言是用精確的數學或機器可處理的公式定義的語言,我的理解形式語言就是符號化的語言,好比編程語言(C C++ JAVA PYTHON),都是定義一組符號來描述映射人的思惟邏輯的,符號化的語言的好處就是可以準確表達,不會產生二義性.
  2. 文法(grammar)
    當咱們要描述一種語言時,須要給出這種語言的全部句子,當句子的數目是有限可數時,就要都列出來;當句子是一個無窮集,也就是無限不可數時,就要給出能夠表示它們的結構的描述方法或者說,句子的組成規則。這種規則就是文法。即從形式上用於描述和規定結構的稱爲文法(或者說語法), 也能夠理解爲指怎麼由一堆符號組成一個有含義的句子的規則和協議
  3. 上下文無關文法(context-free grammar)(數學描述)
    一個四元數組G=(VN,VT,S,P):
    VN:非空有限的非終結符集合VT:非空有限的終結符集
    S:開始符號P:產生式集合
    其中,VN∩VT=∅,S∈VN
    P中產生式通常形式爲A→α|β,其中A∈VN,α,β∈(VN∪VT)*
    大寫字母表示非終結符,小寫字母表示終結符,α、β、γ等表明由 終結符和非終結符號的並集的閉包 中的元素 組成的符號串
    上下文無關文法取名爲「上下文無關」的緣由就是由於字符A總能夠被字串α或β自由替換,而無需考慮字符A出現的上下文
  4. 終結符(terminal symbol )
    終結符是一個形式語言的基本符號。就是說,它們能在一個形式語法的推導規則的輸入或輸出字符串存在,並且它們不能被分解成更小的單位。能夠理解爲產生式推導到何時中止呢,推導到終止符爲止.
  5. 非終結符(nonterminal symbol)
    非終結符是能夠被取代的符號。一個形式文法中必須有一個起始符號;這個起始符號屬於非終結符的集合。在上下文無關文法中,每一個推導規則的左邊只能有一個非終結符而不能有兩個以上的非終結符或終結符。
  6. 巴科斯範式(BNF: Backus-Naur Form)
    以美國人巴科斯(Backus)和丹麥人諾爾(Naur)的名字命名的一種形式化的語法表示方法,用來描述語法的一種形式體系,是一種典型的元語言。又稱巴科斯-諾爾形式(Backus-Naur form)。它不只能嚴格地表示語法規則,並且所描述的語法是與上下文無關的。它具備語法簡單,表示明確,便於語法分析和編譯的特色。
    編程語言的文法除了數學化的描述,還須要在在實際生產中易於描述的符號化語言,BNF就是用來描述上下文無關文法的符號化的語言.

2.2 概念與bison
2.1章節說明的概念跟bison又是一種什麼關係呢?
bison是屬於 GNU 項目的一個語法分析器生成器。
bison可以將上下文無文法解釋成語法分析表,因爲兼容yacc,而yacc是BNF進行描述文法規則的, 因此能夠理解爲bison可以解析以BNF描述上下文無關文法的語法分析器生成器.
2.3 MySQL與bison
MySQL使用bison做爲其解析SQL語句的語法分析器.
2.4 SQL解析相關文件及關聯
(1) 相關文件
SQL詞法解析文件:
sql/sql_lex.h、sql/lex_token.h、sql/lex.h、sql/lex_symbol.h
sql/gen_lex_token.cc、sql/sql_lex.cc
SQL語法解析文件:
sql/sql_yacc.yy、sql/sql_yacc.cc、sql/sql_yacc.h
SQL語句的hint語法解析文件:
sql/sql_hints.yy、sql/sql_hints.yy.cc編程

(2) 語法解析
MySQL內核源碼解讀-SQL解析一
3. sql/sql_yacc.yy
3.1 sql_yacc.yy描述
sql_yacc.cc規定了SQL語句語法規則,定義了SQL語句的關鍵字.
3.2 sql_yacc.yy文件結構bootstrap

%{
Prologue
%}數組

Bison declarations閉包

%%
Grammar rules
%%編程語言

Epilogueide

  1. Prologue部分包括宏定義和在語法規則動做中使用的函數和變量的聲明. 這些將複製到分析器文件的開頭以便先於yyparse的定義. 你可使用#include'來從頭文件獲取聲明. 若是你不須要任何的C聲明, 能夠省略這個部分的括號分隔符%{'和`%}', 這部分被BISON原封不動地複製到輸出的.C文件中
  2. Bison declatations部分包含了定義終結符和非終結符的聲明,優先級等等
  3. Grammar Rules部分包含了一個或多個Bison語法規則, 在這裏至少應該有一個語法規則,而且第一個%%, 絕對不能省略,解釋它在文件的最開頭.
  4. 就像Prologue部分被複制到開頭同樣,Epilogue部分被逐字地複製到分析器文件的結尾. 若是你想放一些代碼卻不必放在yyparse的定義以前,這裏是最方便的地方. 若是最後一部分爲空,你能夠省略分隔它的分隔符%%.

3.2 sql_yacc.yy文件解析
3.2.1 Prologue部分
該部分包含了C語言的頭文件,宏定義,該部分主要聲明和定義了2個關鍵函數,以下:
int yylex(void yylval, void yythd);詞法解析函數的聲明
void MYSQLerror(YYLTYPE , THD thd, const char *s);語法分析錯誤函數的定義。函數

3.2.2 Bison declatations部分
本部分與prologue部分使用 %% 進行分隔

MySQL內核源碼解讀-SQL解析一
MySQL內核源碼解讀-SQL解析一
3.2.3 Grammar Rules部分
本部分與Bison declatations部分,使用 %% 進行分隔
MySQL內核源碼解讀-SQL解析一
例子分析:
Bison產生式: result: components…;
下面的例子就是一個產生式
query是產生式的左端, 冒號後面是產生式的右端, | 表明或的意思, {}當query產生式推出右端狀況的時候所執行的動做,一個產生式結束要是 ;
其中, query verb_clause 都是非終止符, END_OF_INPUT 是終止符, 也就是說產生式推導到終止符就中止推導.
即query->END_OF_INPUT | verb_clause | verb_clause END_OF_INPUT
query:

  1. END_OF_INPUT
  2. { THD *thd= YYTHD;
  3. if (!thd->bootstrap &&!thd->m_parser_state->has_comment())
  4. {
  5. my_message(ER_EMPTY_QUERY, ER(ER_EMPTY_QUERY), MYF(0));
  6. MYSQL_YYABORT;
  7. }
  8. thd->lex->sql_command= SQLCOM_EMPTY_QUERY;
  9. YYLIP->found_semicolon= NULL;
  10. }
  11. | verb_clause
  12. { Lex_input_stream *lip = YYLIP;
  13. if (YYTHD->get_protocol()->has_client_capability(CLIENT_MULTI_QUERIE S)&& lip->multi_statements && !lip->eof())
  14. {
  15. lip->next_state= MY_LEX_END;
  16. lip->found_semicolon= lip->get_ptr();
  17. }
  18. else
  19. { lip->found_semicolon= NULL;}
  20. }
  21. ';'
  22. opt_end_of_input
  23. |verb_clause END_OF_INPUT
  24. {YYLIP->found_semicolon= NULL;}

參考資料

  1. 《lex與yacc》(第二版)
  2. 《flex與bison》(第二版)
  3. Bison操做手冊
    http://www.gnu.org/software/bison/manual/bison.html

本文由京東商城數據庫技術部傅志宇提供。

相關文章
相關標籤/搜索