?
本文檔使用 PHP中文網(wǎng)手冊(cè) 發(fā)布
分析器階段含兩個(gè)部分:
1.在gram.y和scan.l里 定義的分析器(parser)是 使用 Unix 工具bison 和flex創(chuàng)建的
轉(zhuǎn)換處理(transformation process) 對(duì)分析器返回的數(shù)據(jù)結(jié)構(gòu)進(jìn)行修改和增補(bǔ)。
分析器必須檢查(以純 ASCII 文本方式到來(lái)的)查詢字符串的語(yǔ)法。 如果語(yǔ)法正確,則創(chuàng)建一個(gè)分析樹(parse tree)并將之傳回, 否則,返回一個(gè)錯(cuò)誤。 實(shí)現(xiàn)分析器和詞法器使用了著名的 Unix 工具bison 和flex.
詞法器(lexer)在文件scan.l里定義, 負(fù)責(zé)識(shí)別標(biāo)識(shí)符(identifiers) 和 SQL 關(guān)鍵字(SQL key words)等。 對(duì)于發(fā)現(xiàn)的每個(gè)關(guān)鍵字或者標(biāo)識(shí)符都會(huì)生成一個(gè)記號(hào)并且傳遞給分析器。
分析器在文件gram.y里定義 并且包含一套語(yǔ)法規(guī)則(grammar rules) 和觸發(fā)規(guī)則(actions)時(shí)執(zhí)行的動(dòng)作。 動(dòng)作代碼(實(shí)際上是 C 代碼)用于建立分析樹。
文件 scan.l 用flex轉(zhuǎn)換成 C 源文件scan.c, 而gram.y用bison 轉(zhuǎn)換成gram.c。 在完成這些轉(zhuǎn)換后,一個(gè)通用的 C 編譯器就可以用于創(chuàng)建分析器。 千萬(wàn)不要對(duì)生成的 C 源文件做修改,因?yàn)橄乱淮握{(diào)用flex 或bison時(shí)會(huì)把它們覆蓋。
Note: 上面提到的轉(zhuǎn)換和編譯是使用跟隨 PostgreSQL 發(fā)布的 makefiles自動(dòng)完成的。
對(duì)bison或者gram.y里 的語(yǔ)法規(guī)則的詳細(xì)描述超出本文的范圍。 有很多關(guān)于flex和bison的書籍和文檔。 你在開始研究gram.y里給出的語(yǔ)法之前應(yīng)該對(duì)bison很熟悉, 否則你是看不懂那里面的內(nèi)容,理解不了發(fā)生了什么事情的。
分析器階段只使用和 SQL 語(yǔ)法結(jié)構(gòu)相關(guān)的固定規(guī)則創(chuàng)建一個(gè)分析樹。 它不會(huì)查找任何系統(tǒng)表,因此就不可能理解請(qǐng)求查詢里面的詳細(xì)的語(yǔ)意。 在分析器技術(shù)之后,轉(zhuǎn)換處理接受分析器(transformation process) 傳過(guò)來(lái)的分析樹然后做進(jìn)一步處理, 解析哪些查詢中引用了哪個(gè)表、哪個(gè)函數(shù)、哪個(gè)操作符的語(yǔ)意。 所生成的表示這個(gè)信息的數(shù)據(jù)結(jié)構(gòu)叫做查詢樹(query tree)。
把裸分析和語(yǔ)意分析分成兩個(gè)過(guò)程的原因是系統(tǒng)表查找只能在一個(gè)事務(wù)中進(jìn)行, 而不想在一接收到查詢字符串就發(fā)起一個(gè)事務(wù)。 裸分析階段已經(jīng)足夠可以標(biāo)識(shí)事務(wù)控制命令(BEGIN,ROLLBACK等), 并且這些東西不用任何進(jìn)一步的分析就可以執(zhí)行。 一旦知道正在處理一個(gè)真正的查詢(比如SELECT或UPDATE), 就可以發(fā)起一個(gè)事務(wù)了(如果還沒(méi)開始這么一個(gè))。 只有這個(gè)時(shí)候可以調(diào)用轉(zhuǎn)換處理。
轉(zhuǎn)換處理生成的查詢樹結(jié)構(gòu)上在很大程度上類似于裸分析樹,但是在細(xì)節(jié)上有很多區(qū)別。 比如,在分析樹里的FuncCall節(jié)點(diǎn)代表那些看上去像函數(shù)調(diào)用的東西。 根據(jù)引用的名字是一個(gè)普通函數(shù)還是一個(gè)聚集函數(shù), 這個(gè)可能被轉(zhuǎn)換成一個(gè)FuncExpr或Aggref節(jié)點(diǎn)。 同樣,有關(guān)字段和表達(dá)式結(jié)果的具體數(shù)據(jù)類型也添加到查詢樹中。