《flex&bison》之sql解析

        大概上半年接了一本《深入理解MySQL》,看了個一知半解吧!這裏不得不說這本書有點貪大求全了。什麼存儲引擎、sql解析、查詢優化等等的內容都涉及。如果領悟能力高的話,可能對數據庫有一種全局的把握。不然的話還是需要看看其他資料了。當時不懂sql編譯原理(其實現在也不懂,這貨太愁銀了),以爲sql解析應該是一個簡單的事情。畢竟不需要生成最終機器代碼嘛,其實不然呀!舉個例子吧,使用flex和bison爲ANSI C和SQL構建編譯器。MySQL的SQL語法文件有一萬多行,而ANSI C就幾百行。我頓時感覺事情不是我想的那樣了。SQL也不是吃素的呀!前面一直在啃《flex&bison》,雖說是講工具的使用,但是畢竟是編譯呀!尤其對我這樣的原理愛好者,簡直好折磨。不過一知半解怎麼也比眼前一抹黑要好。
        在MySQL中,SQL語法分析器的輸出是語法樹;而在《flex&bison》中,分析器的輸出是逆波蘭式代碼。不過大同小異吧,作用其實是一樣的。這書裏面主要實現了select語句,作者說select是SQL中最複雜的語句了,想想也是,數據庫的最大的作用不就是提供查詢服務嘛!
select_stmt: SELECT select_opts select_expr_list
                        { emit("SELECTNODATA %d %d", $2, $3); } ;
    | SELECT select_opts select_expr_list
     FROM table_references
     opt_where opt_groupby opt_having opt_orderby opt_limit
     opt_into_list { emit("SELECT %d %d %d", $2, $3, $5); } ;
;
        上面這段語法規則算是select語句的頂層規則了。第一個有不規則就不用看了,算是一個特例了。我們主要研究第二個規則。首先,SELECT是一個終結符,直接匹配select關鍵字;select_opts是一些查詢的選項;select_expr_list是查詢的目標。因爲bison使用的是LALR(1)分析法,這是一個使用最左規約的方法。所以這個語法分析器分析出來的SQL是最後執行SELECT操作了。當然這並不一定,因爲SQL解析可以有很多實現。我看網上的資料,很多情況下SELECT操作並不是最後執行的。 然後table_references是一個比較複雜的非終結符號。SQL支持SELECT嵌套,也就是說table_references可以是一個SELECT語句的執行結果。這可以在規則文件中明顯的看出來。
table_references:    table_reference { $$ = 1; }
    | table_references ',' table_reference { $$ = $1 + 1; }
    ;

table_reference:  table_factor
  | join_table
;

table_factor:
    NAME opt_as_alias index_hint { emit("TABLE %s", $1); free($1); }
  | NAME '.' NAME opt_as_alias index_hint { emit("TABLE %s.%s", $1, $3);
                               free($1); free($3); }
  | table_subquery opt_as NAME { emit("SUBQUERYAS %s", $3); free($3); }
  | '(' table_references ')' { emit("TABLEREFERENCES %d", $2); }
  ;
  
table_subquery: '(' select_stmt ')' { emit("SUBQUERY"); }
       具體的邏輯就是table_references-->table_reference-->table_factor-->table_subquery-->( select_stmt )。

發佈了49 篇原創文章 · 獲贊 11 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章