40.3. 分析器階段

分析器階段含兩個部分:

40.3.1. 分析器

分析器必須檢查(以純 ASCII 文本方式到來的)查詢字串的語法。 如果語法正確,則建立一個分析樹並將之傳回, 否則,返回一個錯誤。實現分析器和詞法器我們使用了著名的 Unix 工具 lexyacc

詞法器在文件 scan.l裡定義,負責識別標識符SQL 關鍵字等。 對於發現的每個關鍵字或者標識符都會生成一個記號並且傳遞給分析器。

分析器在文件 gram.y 裡定義並且包含一套語法規則和觸發規則時執行的動作。 動作代碼(實際上是 C 代碼)用於建立分析樹。

文件 scan.llex 轉換成 C 源文件 scan.cgram.yyacc 轉換成 gram.c。 在完成這些轉換後,一個通用的 C 編譯器就可以用於建立分析器。 千萬不要對生成的 C 源文件做修改,因為下一次調用 lexyacc 時會把它們覆蓋。

注意: 上面提到的轉換和編譯是使用跟隨 PostgreSQL 發佈的 makefiles 自動完成的。

yacc 或者 gram.y 裡的語法規則的詳細描述超出本文的範圍。 有很多關於 lexyacc的書籍和文件。您在開始研究 gram.y 裡給出的語法之前,您應該對 yacc 很熟悉,否則您是看不懂那裡面的內容,理解不了發生了什麼事情的。

40.3.2. 轉換處理

分析器截斷只使用和 SQL 語法結構相關的固定規則建立一個分析樹。 它不會查找任何系統資料表,因此就不可能理解請求查詢裡面的詳細的語意。 在分析器技術之後,轉換處理接受分析器傳過來的分析樹然後做進一步處理, 解析那些理解查詢中引用了哪個資料表,哪個函數以及哪個操作符的語意。所生成的資料表示這個訊息的資料結構叫做查詢樹

把裸分析和語意分析分成兩個過程的原因是系統資料表查找只能在一個交易中進行, 而我們不想在一接收到查詢字串就發起一個交易。 裸分析階段已經足夠可以標識交易控制命令(BEGINROLLBACK,等), 並且這些東西不用任何進一步的分析就可以執行。一旦我們知道我們正在處理一個真正 的查詢(比如SELECT 或者 UPDATE), 我們就可以發起一個交易了(如果我們還沒開始這麼一個)。只有這個時候可以調用轉換處理。

轉換處理生成的查詢樹結構上在很大程度上類似於裸分析樹,但是在細節上有很多區別。 比如,在分析樹裡的 FuncCall 節點代資料表那些看上去像函數調用的東西。 根據引用的名字是一個普通函數還是一個聚集函數, 這個可能被轉換成一個 FuncExpr 或者一個 Aggref 節點。 同樣,有關字串和資料表達式結果的具體資料類型也添加到查詢樹中。