上一篇博文我們閱讀了postgresql中查詢分析模塊的源碼。查詢分析模塊對前臺送來的命令進(jìn)行詞法分析、語法分析和語義分析后獲得對應(yīng)的查詢樹(Query)。在獲得查詢樹之后,程序開始對查詢樹進(jìn)行查詢重寫處理。

這一篇文章我們進(jìn)入查詢重寫模塊源碼的閱讀。還記得上一篇文章的那張函數(shù)調(diào)用關(guān)系圖么?不記得沒關(guān)系,我再放一遍。

上次的查詢分析模塊走了1~7這些步驟。而查詢重寫模塊即如上圖的標(biāo)記所示,函數(shù)pg_rewrite_query是進(jìn)行查詢重寫處理的入口函數(shù)。該函數(shù)定義在src/backend/tcop/postgres.c中。

函數(shù)pg_rewrite_query的參數(shù)就是查詢分析模塊的返回值(Query)。查詢重寫模塊使用規(guī)則系統(tǒng)判斷是否要對查詢樹進(jìn)行重寫。如果查詢樹中每個對象(或者說目標(biāo))被定義了轉(zhuǎn)換規(guī)則,那么程序就會使用該規(guī)則重寫查詢樹。這部分的源碼大部分都在src/backend/rewrite文件夾下。

下面將首先介紹查詢重寫模塊中使用的規(guī)則系統(tǒng),在此基礎(chǔ)上介紹查詢重寫源碼的調(diào)用路徑。


1.規(guī)則系統(tǒng)

毫不夸張地說,規(guī)則系統(tǒng)是查詢重寫模塊的核心內(nèi)容,該模塊正是根據(jù)規(guī)則系統(tǒng)中描述的規(guī)則來決定如何對一個查詢樹進(jìn)行重寫。規(guī)則系統(tǒng)由一些列的規(guī)則組成。這些規(guī)則都存儲在系統(tǒng)表pg_rewrite中。該表的結(jié)構(gòu)如下圖所示。每一條記錄即為一條規(guī)則。

其中每個屬性的意義如下:

屬性名        類型            描述
oid         oid             行標(biāo)識符(隱藏屬性; 必須明確選擇)
rulename    name            規(guī)則名稱
ev_class    oid             使用這條規(guī)則的表名稱
ev_type     char            規(guī)則適用的事件類型:1 = SELECT, 2 = UPDATE, 3 = INSERT, 4 = DELETE ev_enabled char 控制規(guī)則在哪個session_replication_role模塊觸發(fā)。 O = 規(guī)則在 "origin""local" 模塊觸發(fā), D = 規(guī)則被禁用, R = 規(guī)則在 "replica" 模塊觸發(fā), A = 規(guī)則總是觸發(fā)。
is_instead  bool            如果該規(guī)則是INSTEAD規(guī)則,那么為真
ev_qual     pg_node_tree    規(guī)則的資格條件的表達(dá)式樹(以nodeToString()形式存在)
ev_action   pg_node_tree    規(guī)則動作的查詢樹(以nodeToString()形式存在)

由此我