W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
EXPLAIN
的FDW例程ANALYZE
的FDW例程IMPORT FOREIGN SCHEMA
的 FDW 例程FDW處理器函數(shù)返回一個(gè)palloc過的FdwRoutine
結(jié)構(gòu),它包含下文描述的回調(diào)函數(shù)的指針。掃描相關(guān)的函數(shù)是必需的,剩下的是可選的。
FdwRoutine
結(jié)構(gòu)類型被聲明在src/include/foreign/fdwapi.h
中,可以查看它來獲得額外的信息。
void
GetForeignRelSize(PlannerInfo *root,
RelOptInfo *baserel,
Oid foreigntableid);
獲取一個(gè)外部表的關(guān)系尺寸估計(jì)。在對(duì)一個(gè)掃描外部表的查詢進(jìn)行規(guī)劃的開頭將調(diào)用該函數(shù)。root
是規(guī)劃器的關(guān)于該查詢的全局信息;baserel
是規(guī)劃器的關(guān)于該表的信息;foreigntableid
是外部表在pg_class
中的 OID (foreigntableid
可以從規(guī)劃器的數(shù)據(jù)結(jié)構(gòu)中獲得,但是為了減少工作量,這里直接顯式地將它傳遞給函數(shù))。
這個(gè)函數(shù)應(yīng)該更新baserel->rows
為表掃描根據(jù)限制條件完成了過濾后將返回的預(yù)期行數(shù)。 baserel->rows
的初始值只是一個(gè)常數(shù)的默認(rèn)估計(jì)值,應(yīng)該盡可能把它替換掉。 如果該函數(shù)能夠計(jì)算出一個(gè)平均結(jié)果行寬度的更好的估計(jì)值,該函數(shù)也可能選擇更新baserel->width
。 (初始值基于列數(shù)據(jù)類型和最后一個(gè)
ANALYZE
測(cè)量的列平均寬度值。) 此外,如果該函數(shù)能夠更好地計(jì)算出外部表的總行數(shù),則該函數(shù)可以更新baserel->tuples
。 (初始值來自pg_class
。reltuples
表示最后一次ANALYZE
看到的總行數(shù)。)
更多信息請(qǐng)見第 56.4 節(jié)。
void
GetForeignPaths(PlannerInfo *root,
RelOptInfo *baserel,
Oid foreigntableid);
為一個(gè)外部表上的掃描創(chuàng)建可能的訪問路徑。這個(gè)函數(shù)在查詢規(guī)劃過程中被調(diào)用。參數(shù)和GetForeignRelSize
相同,后者已經(jīng)被調(diào)用過了。
這個(gè)函數(shù)必須為外部表上的掃描生成至少一個(gè)訪問路徑(ForeignPath
節(jié)點(diǎn)),并且必須調(diào)用add_path
把每一個(gè)這樣的路徑加入到baserel->pathlist
中。我們推薦使用create_foreignscan_path
來建立ForeignPath
節(jié)點(diǎn)。該函數(shù)可以生成多個(gè)訪問路徑,例如一個(gè)具有合法
pathkeys
的路徑表示一個(gè)預(yù)排序好的結(jié)果。每一個(gè)反問路徑必須包含代價(jià)估計(jì),并且能包含任何FDW的私有信息,這種信息被用來標(biāo)識(shí)想要使用的指定掃描方法。
更多信息請(qǐng)見第 56.4 節(jié)。
ForeignScan *
GetForeignPlan(PlannerInfo *root,
RelOptInfo *baserel,
Oid foreigntableid,
ForeignPath *best_path,
List *tlist,
List *scan_clauses,
Plan *outer_plan);
從選擇的外部訪問路徑創(chuàng)建一個(gè)ForeignScan
計(jì)劃節(jié)點(diǎn)。這個(gè)函數(shù)在查詢規(guī)劃的末尾被調(diào)用。參數(shù)和GetForeignRelSize
的一樣,外加選中的ForeignPath
(在前面由GetForeignPaths
、GetForeignJoinPaths
或者
GetForeignUpperPaths
產(chǎn)生)、被計(jì)劃節(jié)點(diǎn)發(fā)出的目標(biāo)列表以及計(jì)劃節(jié)點(diǎn)強(qiáng)制的限制子句以及被RecheckForeignScan
執(zhí)行的復(fù)查所使用的ForeignScan
的外子計(jì)劃(如果該路徑是用于一個(gè)連接而非基本關(guān)系,則foreigntableid
是InvalidOid
)。
這個(gè)函數(shù)必須創(chuàng)建并返回一個(gè)ForeignScan
計(jì)劃節(jié)點(diǎn),我們對(duì)劍使用make_foreignscan
來建立ForeignScan
節(jié)點(diǎn)。
更多信息見第 56.4 節(jié)。
void
BeginForeignScan(ForeignScanState *node,
int eflags);
開始執(zhí)行一個(gè)外部掃描。這個(gè)函數(shù)在執(zhí)行器啟動(dòng)階段被調(diào)用。它應(yīng)該執(zhí)行任何在掃描能夠開始之前需要完成的初始化工作,但是并不開始執(zhí)行真正的掃描(會(huì)在第一次調(diào)用IterateForeignScan
時(shí)完成)。ForeignScanState
節(jié)點(diǎn)已經(jīng)被創(chuàng)建好了,但是它的fdw_state
域仍然為 NULL。關(guān)于要被掃描的表的信息可以通過
ForeignScanState
節(jié)點(diǎn)訪問(特殊地,從底層的ForeignScan
計(jì)劃節(jié)點(diǎn),它包含任何由GetForeignPlan
提供的FDW私有信息)。eflags
包含描述執(zhí)行器對(duì)該計(jì)劃節(jié)點(diǎn)操作模式的標(biāo)志位。
注意當(dāng)(eflags & EXEC_FLAG_EXPLAIN_ONLY)
為真時(shí),這個(gè)函數(shù)不應(yīng)該執(zhí)行任何外部可見的動(dòng)作;它應(yīng)當(dāng)只做最少的事情來創(chuàng)建對(duì)ExplainForeignScan
和EndForeignScan
有效的節(jié)點(diǎn)狀態(tài)。
TupleTableSlot *
IterateForeignScan(ForeignScanState *node);
從外部源獲得一行,將它放在一個(gè)元組表槽中返回(節(jié)點(diǎn)的ScanTupleSlot
應(yīng)當(dāng)被用于此目的)。如果沒有更多的行可用則返回 NULL。元組表槽設(shè)施允許一個(gè)物理的或者虛擬的元組被返回;在大部分情況下出于性能的考慮會(huì)傾向于選擇后者。注意這是在一個(gè)短期存在的內(nèi)存上下文中被調(diào)用的,該內(nèi)存上下文會(huì)在調(diào)用之間被重置。如果你需要長(zhǎng)期存在的存儲(chǔ),請(qǐng)?jiān)?code class="function">BeginForeignScan中創(chuàng)建內(nèi)存上下文,或者使用節(jié)點(diǎn)的
EState
中的es_query_cxt
。
如果提供了fdw_scan_tlist
目標(biāo)列表,被返回的行必須匹配它,如果沒有提供則它們必須匹配被掃描的外部表的行類型。如果選擇優(yōu)化掉不需要的列,你應(yīng)該在那些列的位置上插入控制或者生成一個(gè)忽略了那些列的fdw_scan_tlist
列表。
注意PostgreSQL的執(zhí)行器并不在乎被返回的行是否違背了定義在該外部表上的任何約束 — 但是規(guī)劃器會(huì)在乎這一點(diǎn),并且如果在外部表中有可見行不滿足一個(gè)約束,規(guī)劃器可能會(huì)錯(cuò)誤地優(yōu)化查詢。如果當(dāng)用戶已經(jīng)聲明一個(gè)約束應(yīng)該為真時(shí)它卻被違背,最合適的處理可能是產(chǎn)生一個(gè)錯(cuò)誤(就像在數(shù)據(jù)類型失配的情況下所作的那樣)。
void
ReScanForeignScan(ForeignScanState *node);
從頭開始重啟一個(gè)掃描。注意掃描所依賴的任何參數(shù)可能已經(jīng)改變了值,因此新掃描不一定會(huì)返回完全相同的行。
void
EndForeignScan(ForeignScanState *node);
結(jié)束掃描并釋放資源。通常釋放palloc過的內(nèi)存并不重要,但是打開的文件和到遠(yuǎn)程服務(wù)器的連接等應(yīng)該被清理。
如果一個(gè) FDW 支持遠(yuǎn)程執(zhí)行外部連接(而不是先把兩個(gè)表的數(shù)據(jù)取到本地然后做本地連接),它應(yīng)該提供這個(gè)回調(diào)函數(shù):
void
GetForeignJoinPaths(PlannerInfo *root,
RelOptInfo *joinrel,
RelOptInfo *outerrel,
RelOptInfo *innerrel,
JoinType jointype,
JoinPathExtraData *extra);
它為兩個(gè)(或更多)同屬于一臺(tái)外部服務(wù)器的外部表的連接創(chuàng)建可能的訪問路徑。這個(gè)可選的函數(shù)會(huì)在查詢規(guī)劃過程中被調(diào)用。 和GetForeignPaths
一樣,這個(gè)函數(shù)應(yīng)該為提供的joinrel
生成ForeignPath
路徑(用 create_foreign_join_path
構(gòu)建它們),并且調(diào)用
add_path
把這些路徑加入到該連接應(yīng)該考慮的路徑集合中。但是和GetForeignPaths
不一樣的是,不需要這個(gè)函數(shù)產(chǎn)生最少一個(gè)路徑,因?yàn)樯婕氨镜剡B接的路徑總是可用的。
注意為相同的連接關(guān)系將會(huì)重復(fù)地調(diào)用這個(gè)函數(shù)用來生成內(nèi)外關(guān)系的不同組合。FDW 需要負(fù)責(zé)最小化其中重復(fù)的工作。
如果一個(gè)ForeignPath
路徑被選中用于該連接,它將在整個(gè)連接處理中存在,為其中的成分表和子連接產(chǎn)生的路徑將不會(huì)被使用。后續(xù)對(duì)該連接路徑的處理大部分和掃描單個(gè)外部表的路徑一樣。一點(diǎn)不同是ForeignScan
計(jì)劃節(jié)點(diǎn)的scanrelid
應(yīng)該被設(shè)置為零,因?yàn)樗硎镜牟皇菃蝹€(gè)關(guān)系,而是用ForeignScan
節(jié)點(diǎn)的
fs_relids
域來表示被連接的關(guān)系集合(后一個(gè)域會(huì)被核心規(guī)劃器代碼自動(dòng)設(shè)置,不需要由 FDW 填充)。另一點(diǎn)不同是,由于一個(gè)遠(yuǎn)程連接的列列表無法在系統(tǒng)目錄中找到,F(xiàn)DW 必須用一個(gè)合適的TargetEntry
節(jié)點(diǎn)列表來填充fdw_scan_tlist
,表示運(yùn)行時(shí)它返回的元組中提供的列的集合。
更多信息請(qǐng)見第 56.4 節(jié)。
如果一個(gè) FDW 支持執(zhí)行遠(yuǎn)程的掃描/連接后處理,例如遠(yuǎn)程聚集,那么它應(yīng)該提供這個(gè)回調(diào)函數(shù):
void
GetForeignUpperPaths(PlannerInfo *root,
UpperRelationKind stage,
RelOptInfo *input_rel,
RelOptInfo *output_rel,
void *extra);
為上層關(guān)系處理創(chuàng)建可能的訪問路徑,這是規(guī)劃器針對(duì)所有掃描/連接后查詢處理的術(shù)語,例如聚集、窗口函數(shù)、排序和表更新。在查詢規(guī)劃期間會(huì)調(diào)用這個(gè)可選的函數(shù)。當(dāng)前,只有當(dāng)該查詢中涉及的所有基本關(guān)系都屬于同一個(gè) FDW 時(shí)才會(huì)調(diào)用這個(gè)函數(shù)。 這個(gè)函數(shù)應(yīng)該為 FDW 知道如何遠(yuǎn)程執(zhí)行的任何掃描/連接后處理生成ForeignPath
路徑(用 create_foreign_upper_path
構(gòu)建它們),并且調(diào)用
add_path
把這些路徑加入到上層關(guān)系中。就GetForeignJoinPaths
來說,并不要求這個(gè)函數(shù)在創(chuàng)建任何路徑時(shí)都能成功,因?yàn)槁窂娇偸怯锌赡苌婕暗奖镜靥幚怼?/p>
stage
參數(shù)表示當(dāng)前正在考慮的是哪一個(gè)掃描/連接后處理步驟。output_rel
是接收表示這一個(gè)步驟的路徑的上層關(guān)系,而input_rel
是表示這個(gè)步驟輸入的關(guān)系。 extra
參數(shù)提供額外的細(xì)節(jié),當(dāng)前只會(huì)為UPPERREL_PARTIAL_GROUP_AGG
或者
UPPERREL_GROUP_AGG
設(shè)置它,這種情況下它會(huì)指向一個(gè)GroupPathExtraData
結(jié)構(gòu);或者對(duì)于 UPPERREL_FINAL
, 在某種情況下它指向一個(gè)FinalPathExtraData
結(jié)構(gòu)。(注意被加入到output_rel
中的
ForeignPath
路徑通常對(duì)input_rel
的路徑?jīng)]有直接的依賴,因?yàn)樗鼈兊奶幚肀徽J(rèn)為是在外部處理的。不過,檢查為前一個(gè)處理步驟生成的路徑有助于避免冗余的規(guī)劃工作)。
更多信息請(qǐng)見第 56.4 節(jié)。
如果一個(gè)FDW支持可寫的外部表,根據(jù)FDW的需要和功能它應(yīng)該提供某些或者全部下列回調(diào)函數(shù):
void
AddForeignUpdateTargets(Query *parsetree,
RangeTblEntry *target_rte,
Relation target_relation);
UPDATE
和DELETE
操作是在之前由表掃描函數(shù)取出的行上被執(zhí)行的。FDW可能需要額外的信息(例如一個(gè)行ID或主鍵列的值)來保證它能夠找到要更新或刪除的準(zhǔn)確行。要支持這些要求,這個(gè)函數(shù)可以項(xiàng)列列表中增加額外的隱藏或“junk”的目標(biāo)列,它們?cè)谝粋€(gè)UPDATE
或
DELETE
期間會(huì)被從外部表中獲取。
要做到這一點(diǎn),向parsetree->targetList
中增加TargetEntry
項(xiàng),它們包含要被獲取的額外值的表達(dá)式。每一個(gè)這樣的項(xiàng)必須被標(biāo)記為resjunk
= true
,并且必須有一個(gè)可區(qū)分的resname
用于在執(zhí)行期間標(biāo)識(shí)它。請(qǐng)避免使用匹配
ctid
、N
wholerow
或wholerow
的名字,因?yàn)楹诵南到y(tǒng)可能會(huì)生成使用這些名字的junk列。如果額外的表達(dá)式比簡(jiǎn)單的Var更加復(fù)雜,在把它們加入到目標(biāo)列表之前必須把它們用N
eval_const_expressions
進(jìn)行處理。
盡管這個(gè)函數(shù)在規(guī)劃過程中被調(diào)用,但所提供的信息與其他規(guī)劃例程可用的信息有點(diǎn)區(qū)別。parsetree
是UPDATE
或DELETE
命令的分析樹,而target_rte
和target_relation
描述目標(biāo)外部表。
如果AddForeignUpdateTargets
指針被設(shè)置為NULL
,則不會(huì)有額外的目標(biāo)表達(dá)式被加入(這將使得我們不可能實(shí)現(xiàn)DELETE
操作,而UPDATE
則還有可能是可行的,前提是FDW依賴一個(gè)未改變的主鍵來標(biāo)識(shí)行)。
List *
PlanForeignModify(PlannerInfo *root,
ModifyTable *plan,
Index resultRelation,
int subplan_index);
執(zhí)行外部表上插入、更新或刪除所需的任何附加規(guī)劃動(dòng)作。這個(gè)函數(shù)生成FDW私有信息,該信息將被附加到執(zhí)行該更新動(dòng)作的ModifyTable
計(jì)劃節(jié)點(diǎn)。這個(gè)私有信息的形式必須是一個(gè)List
,并將會(huì)在執(zhí)行階段被傳遞給BeginForeignModify
。
root
是規(guī)劃器關(guān)于該查詢的全局信息。plan
是ModifyTable
計(jì)劃節(jié)點(diǎn),它除了fdwPrivLists
域之外是完整的。resultRelation
通過目標(biāo)外部表的范圍表索引來標(biāo)識(shí)它。
subplan_index
標(biāo)識(shí)這是ModifyTable
計(jì)劃節(jié)點(diǎn)的哪個(gè)目標(biāo),從零開始計(jì)數(shù);如果你希望索引到plan->plans
或其他plan
節(jié)點(diǎn)的子結(jié)構(gòu)中,請(qǐng)使用它。
更多信息見第 56.4 節(jié)。
如果PlanForeignModify
指針被設(shè)置為NULL
,則不會(huì)有額外的計(jì)劃時(shí)動(dòng)作被執(zhí)行,并且傳遞給BeginForeignModify
的fdw_private
列表也將為 NIL。
void
BeginForeignModify(ModifyTableState *mtstate,
ResultRelInfo *rinfo,
List *fdw_private,
int subplan_index,
int eflags);
開始執(zhí)行一個(gè)外部表修改操作。這個(gè)例程在執(zhí)行器啟動(dòng)期間被調(diào)用。它應(yīng)該執(zhí)行任何先于實(shí)際表修改的初始化工作。隨后,ExecForeignInsert
、ExecForeignUpdate
或ExecForeignDelete
將被為每一個(gè)將被插入、更新或刪除的元組調(diào)用。
mtstate
是要被執(zhí)行的ModifyTable
計(jì)劃節(jié)點(diǎn)的狀態(tài)信息;通過這個(gè)結(jié)構(gòu)可以得到關(guān)于規(guī)劃和執(zhí)行階段的全局?jǐn)?shù)據(jù)。rinfo
是描述目標(biāo)外部表的ResultRelInfo
結(jié)構(gòu)(ResultRelInfo
的
ri_FdwState
域用于FDW來存儲(chǔ)它在此操作中需要的任何私有狀態(tài))。fdw_private
包含PlanForeignModify
生成的私有數(shù)據(jù)。subplan_index
標(biāo)識(shí)這是ModifyTable
計(jì)劃節(jié)點(diǎn)的哪個(gè)目標(biāo)。eflags
包含描述執(zhí)行器對(duì)該計(jì)劃節(jié)點(diǎn)操作模式的標(biāo)志位。
注意當(dāng)(eflags & EXEC_FLAG_EXPLAIN_ONLY)
為真,這個(gè)函數(shù)不應(yīng)執(zhí)行任何外部可見的動(dòng)作;它只應(yīng)該做最少的工作來創(chuàng)建ExplainForeignModify
和EndForeignModify
可用的節(jié)點(diǎn)狀態(tài)。
如果BeginForeignModify
指針被設(shè)置為NULL
,在執(zhí)行器啟動(dòng)期間將不會(huì)采取任何動(dòng)作。
TupleTableSlot *
ExecForeignInsert(EState *estate,
ResultRelInfo *rinfo,
TupleTableSlot *slot,
TupleTableSlot *planSlot);
插入一個(gè)元組到外部表。estate
是查詢的全局執(zhí)行狀態(tài)。rinfo
是描述目標(biāo)外部表的ResultRelInfo
結(jié)構(gòu)。slot
包含要被插入的元組;它將匹配外部表的行類型定義。planSlot
包含由
ModifyTable
計(jì)劃節(jié)點(diǎn)的子計(jì)劃生成的元組;它與slot
不同,它可能包含額外的“junk”列(INSERT
情況通常不關(guān)心planSlot
,但是為了完整性還是在這里提供它)。
返回值可以是一個(gè)包含實(shí)際被插入的數(shù)據(jù)的槽(這可能會(huì)和所提供的數(shù)據(jù)不同,例如一個(gè)觸發(fā)器動(dòng)作的結(jié)果),或者為 NULL 表示實(shí)際沒有插入行(還是觸發(fā)器的結(jié)果)。被傳入的slot
可以被重用于這個(gè)目的。
在返回槽中的數(shù)據(jù)只有在INSERT
語句具有一個(gè)RETURNING
子句或包括一個(gè)視圖WITH CHECK OPTION
; 或者如果外部表具有一個(gè)AFTER ROW
觸發(fā)器時(shí)才被使用。 觸發(fā)器要求所有的列,但是 FDW 應(yīng)該選擇優(yōu)化成根據(jù)RETURNING
子句的內(nèi)容或
WITH CHECK OPTION
約束返回某些或全部列。 不管怎樣,某些槽必須被返回來指示成功,或者查詢報(bào)告的行計(jì)數(shù)將會(huì)是錯(cuò)誤的。
如果ExecForeignInsert
指針被設(shè)置為NULL
,嘗試向外部表插入將會(huì)失敗并報(bào)告一個(gè)錯(cuò)誤消息。
請(qǐng)注意,在外表上將路由元組插入外表分區(qū)或執(zhí)行 COPY FROM
時(shí)也會(huì)調(diào)用此函數(shù),在這種情況下,它的調(diào)用方式與INSERT
中的情況有所不同。 請(qǐng)參閱下面所述的允許 FDW 支持的回調(diào)函數(shù)。
TupleTableSlot *
ExecForeignUpdate(EState *estate,
ResultRelInfo *rinfo,
TupleTableSlot *slot,
TupleTableSlot *planSlot);
更新外部表中的一個(gè)元組。estate
是查詢的全局執(zhí)行狀態(tài)。rinfo
是描述目標(biāo)外部表的ResultRelInfo
結(jié)構(gòu)。slot
包含元組的新數(shù)據(jù);它將匹配外部表的行類型定義。planSlot
包含由
ModifyTable
計(jì)劃節(jié)點(diǎn)的子計(jì)劃生成的元組;它與slot
不同,它可能包含額外的“junk”列(INSERT
情況通常不關(guān)心planSlot
,但是為了完整性還是在這里提供它)。特殊地,任何AddForeignUpdateTargets
所要求的junk列在這個(gè)槽中都是有效的。
返回值可以是一個(gè)包含實(shí)際被更新的數(shù)據(jù)的槽(這可能會(huì)和所提供的數(shù)據(jù)不同,例如一個(gè)觸發(fā)器動(dòng)作的結(jié)果),或者為 NULL 表示實(shí)際沒有更新行(還是觸發(fā)器的結(jié)果)。被傳入的slot
可以被重用于這個(gè)目的。
在返回槽中的數(shù)據(jù)只有在UPDATE
語句具有一個(gè)RETURNING
子句或者包括一個(gè)視圖WITH CHECK OPTION
;或者如果外部表具有一個(gè)AFTER ROW
觸發(fā)器時(shí)才被使用。 觸發(fā)器要求所有的列,但是 FDW 應(yīng)該選擇優(yōu)化成根據(jù)RETURNING
子句的內(nèi)容或
WITH CHECK OPTION
約束返回某些或全部列。 不管怎樣,某些槽必須被返回來指示成功,或者查詢報(bào)告的行計(jì)數(shù)將會(huì)是錯(cuò)誤的。
如果ExecForeignUpdate
指針被設(shè)置為NULL
,嘗試更新外部表將會(huì)失敗并報(bào)告一個(gè)錯(cuò)誤消息。
TupleTableSlot *
ExecForeignDelete(EState *estate,
ResultRelInfo *rinfo,
TupleTableSlot *slot,
TupleTableSlot *planSlot);
從外部表刪除一個(gè)元組。estate
是查詢的全局執(zhí)行狀態(tài)。rinfo
是描述目標(biāo)外部表的ResultRelInfo
結(jié)構(gòu)。slot
在調(diào)用時(shí)不包含任何有用的東西,但是可以被用于保持被返回的元組。planSlot
包含由
ModifyTable
計(jì)劃節(jié)點(diǎn)的子計(jì)劃生成的元組;特殊地,它將攜帶AddForeignUpdateTargets
所要求的任意垃圾列。垃圾列被用來標(biāo)識(shí)要被刪除的元組。
返回值可以是一個(gè)包含實(shí)際被刪除的數(shù)據(jù)的槽(這可能會(huì)和所提供的數(shù)據(jù)不同,例如一個(gè)觸發(fā)器動(dòng)作的結(jié)果),或者為 NULL 表示實(shí)際沒有刪除行(還是觸發(fā)器的結(jié)果)。被傳入的slot
可以被重用于這個(gè)目的。
在返回槽中的數(shù)據(jù)只有在DELETE
查詢具有一個(gè)RETURNING
子句或者外部表具有一個(gè)AFTER ROW
觸發(fā)器時(shí)才被使用。觸發(fā)器要求所有的列,但是 FDW 應(yīng)該選擇優(yōu)化成根據(jù)RETURNING
子句的內(nèi)容返回某些或全部列。不管怎樣,某些槽必須被返回來指示成功,或者查詢報(bào)告的行計(jì)數(shù)將會(huì)是錯(cuò)誤的。
如果ExecForeignDelete
指針被設(shè)置為NULL
,嘗試從外部表中刪除將會(huì)失敗并報(bào)告一個(gè)錯(cuò)誤消息。
void
EndForeignModify(EState *estate,
ResultRelInfo *rinfo);
結(jié)束表更新并釋放資源。通常釋放palloc的內(nèi)存并不重要,但是打開的文件和到遠(yuǎn)程服務(wù)器的連接等應(yīng)當(dāng)被清除。
如果EndForeignModify
指針被設(shè)置為NULL
,在執(zhí)行器關(guān)閉期間不會(huì)采取任何動(dòng)作。
被INSERT
或者COPY FROM
插入到分區(qū)表中的元組會(huì)被路由到分區(qū)。如果一個(gè)FDW支持可路由的外部表分區(qū),它還應(yīng)該提供下面的回調(diào)函數(shù)。當(dāng)在外部表上執(zhí)行COPY FROM
時(shí),也會(huì)調(diào)用這些函數(shù)。
void
BeginForeignInsert(ModifyTableState *mtstate,
ResultRelInfo *rinfo);
開始在外部表上執(zhí)行插入操作。當(dāng)外部表被選中作為元組路由的分區(qū)以及COPY FROM
命令中指定的目標(biāo)時(shí),在第一個(gè)元組被插入到該外部表之前會(huì)調(diào)用這個(gè)例程。它應(yīng)該執(zhí)行實(shí)際插入之前所需的任何初始化工作。隨后,為每一個(gè)被插入到該外部表的元組都將調(diào)用ExecForeignInsert
。
mtstate
是正在被執(zhí)行的ModifyTable
計(jì)劃節(jié)點(diǎn)的總體狀態(tài),通過這個(gè)結(jié)構(gòu)可以得到有關(guān)計(jì)劃和執(zhí)行的全局?jǐn)?shù)據(jù)。rinfo
是描述目標(biāo)外部表的ResultRelInfo
結(jié)構(gòu)(對(duì)于FDW,ResultRelInfo
的
ri_FdwState
字段用來存放這個(gè)操作所需要的私有狀態(tài))。
當(dāng)這個(gè)例程被一個(gè)COPY FROM
命令調(diào)用時(shí),不會(huì)提供mtstate
中與計(jì)劃相關(guān)的全局?jǐn)?shù)據(jù),并且后續(xù)為每個(gè)插入元組調(diào)用的ExecForeignInsert
的planSlot
參數(shù)為NULL
,不管該外部表是為元組路由選中的分區(qū)還是命令中指定的目標(biāo)。
如果BeginForeignInsert
指針被設(shè)置為NULL
,則不會(huì)采取初始化動(dòng)作。
請(qǐng)注意如果 FDW 不支持在外表上的可路由外表分區(qū)和/或執(zhí)行 COPY FROM
,這個(gè)函數(shù)或 ExecForeignInsert
后續(xù)的調(diào)用必須根據(jù)需要發(fā)出錯(cuò)誤。
void
EndForeignInsert(EState *estate,
ResultRelInfo *rinfo);
結(jié)束插入操作并且釋放資源。通常釋放palloc的內(nèi)存并不重要,但是打開的文件和與遠(yuǎn)程服務(wù)器的連接應(yīng)該被清除。
如果EndForeignInsert
指針被設(shè)置為NULL
,則不會(huì)采取終止動(dòng)作。
int
IsForeignRelUpdatable(Relation rel);
報(bào)告指定的外部表支持哪些更新操作。返回值應(yīng)該是一個(gè)規(guī)則事件編號(hào)的位掩碼,它指示了哪些操作被外部表支持,它使用CmdType
枚舉,即: (1 << CMD_UPDATE) = 4
表示UPDATE
、 (1 << CMD_INSERT) = 8
表示
INSERT
以及 (1 << CMD_DELETE) = 16
表示DELETE
。
如果IsForeignRelUpdatable
指針被設(shè)置為NULL
,而FDW提供了ExecForeignInsert
、ExecForeignUpdate
或ExecForeignDelete
,則外部表分別被假定為可插入、可更新或可刪除。只有在FDW支持某些表是可更新的而某些不是可更新的時(shí)候,才需要這個(gè)函數(shù)(即便如此,也允許在執(zhí)行例程中拋出一個(gè)錯(cuò)誤而不是在這個(gè)函數(shù)中檢查。但是,這個(gè)函數(shù)被用來決定顯示在
information_schema
視圖中的可更新性)。
一些對(duì)于外部表的插入、更新和刪除可以通過實(shí)現(xiàn)另一組接口來優(yōu)化。普通的插入、更新和刪除接口會(huì)從遠(yuǎn)程服務(wù)器取得行,然后一次修改其中一行。在某些情況下,這種逐行的方式是必要的,但是可能效率不高。 如果有可能讓外部服務(wù)器判斷哪些行可以直接修改而無需先檢索它們,并且沒有本地結(jié)構(gòu)會(huì)影響該操作(行級(jí)本地觸發(fā)器,存儲(chǔ)生成的列, 或 來自父視圖的WITH CHECK OPTION
約束。 那么可以讓整個(gè)操作在遠(yuǎn)程服務(wù)器上執(zhí)行。下面介紹的接口能讓這種做法變成可能。
bool
PlanDirectModify(PlannerInfo *root,
ModifyTable *plan,
Index resultRelation,
int subplan_index);
決定在遠(yuǎn)程服務(wù)器上執(zhí)行直接修改是否安全。如果安全,執(zhí)行所需的規(guī)劃動(dòng)作然后返回true
。否則返回false
。這個(gè)可選的函數(shù)在查詢規(guī)劃期間被調(diào)用。如果這個(gè)函數(shù)成功,在執(zhí)行階段將會(huì)調(diào)用BeginDirectModify
、IterateDirectModify
和
EndDirectModify
。否則,對(duì)表的修改將采用上文描述的表更新函數(shù)來執(zhí)行。參數(shù)和PlanForeignModify
的相同。
要在遠(yuǎn)程服務(wù)器上執(zhí)行直接修改,這個(gè)函數(shù)必須用一個(gè)ForeignScan
計(jì)劃節(jié)點(diǎn)(它在遠(yuǎn)程服務(wù)器上執(zhí)行直接修改)重寫目標(biāo)子計(jì)劃。ForeignScan
的operation
域必須被合適地設(shè)置為CmdType
枚舉值,即CMD_UPDATE
表示
UPDATE
、CMD_INSERT
表示INSERT
而CMD_DELETE
表示DELETE
。
更多信息請(qǐng)見第 56.4 節(jié)。
如果PlanDirectModify
指針被設(shè)置為NULL
,不會(huì)嘗試在遠(yuǎn)程服務(wù)器上執(zhí)行直接修改。
void
BeginDirectModify(ForeignScanState *node,
int eflags);
準(zhǔn)備在遠(yuǎn)程服務(wù)器上執(zhí)行一次直接修改。這個(gè)函數(shù)會(huì)在執(zhí)行器啟動(dòng)時(shí)被調(diào)用。它應(yīng)該執(zhí)行直接修改所需的任何初始化工作(應(yīng)該在第一次IterateDirectModify
調(diào)用之前完成)。ForeignScanState
節(jié)點(diǎn)已經(jīng)被創(chuàng)建,但是它的fdw_state
域仍然為 NULL。有關(guān)要被修改的表的信息可以通過
ForeignScanState
節(jié)點(diǎn)(具體地,從底層的ForeignScan
計(jì)劃節(jié)點(diǎn),它包含了PlanDirectModify
提供的 FDW-私有信息)訪問。eflags
包含描述執(zhí)行器對(duì)于這個(gè)計(jì)劃節(jié)點(diǎn)操作模式的標(biāo)志位。
注意當(dāng)(eflags & EXEC_FLAG_EXPLAIN_ONLY)
為真時(shí),這個(gè)函數(shù)不應(yīng)該執(zhí)行任何外部可見的動(dòng)作。它應(yīng)當(dāng)只做最少的工作讓該節(jié)點(diǎn)狀態(tài)對(duì)ExplainDirectModify
和EndDirectModify
有效。
如果BeginDirectModify
指針被設(shè)置為NULL
,不會(huì)嘗試在遠(yuǎn)程服務(wù)器上執(zhí)行直接修改。
TupleTableSlot *
IterateDirectModify(ForeignScanState *node);
當(dāng)INSERT
、UPDATE
或者DELETE
查詢沒有RETURNING
子句時(shí),完成遠(yuǎn)程服務(wù)器上的直接修改后返回 NULL。當(dāng)查詢有該子句時(shí),取出一個(gè)包含RETURNING
計(jì)算所需數(shù)據(jù)的結(jié)果,用一個(gè)元組表槽返回它(節(jié)點(diǎn)的
ScanTupleSlot
應(yīng)被用于這一目的)。實(shí)際被插入、更新或者刪除的數(shù)據(jù)必須被存儲(chǔ)在該節(jié)點(diǎn)的EState
的es_result_relation_info->ri_projectReturning->pi_exprContext->ecxt_scantuple
中。如果沒有更多行可用,則返回 NULL。注意這個(gè)函數(shù)會(huì)在一個(gè)短期生存的內(nèi)存上下文中被調(diào)用,該上下文會(huì)在兩次調(diào)用之間被重置。如果需要一個(gè)長(zhǎng)期存在的存儲(chǔ),可以在
BeginDirectModify
中創(chuàng)建一個(gè)內(nèi)存上下文,或者使用該節(jié)點(diǎn)的EState
中的es_query_cxt
。
如果提供了fdw_scan_tlist
目標(biāo)列表,則被返回的行必須匹配它。否則,被返回的行必須匹配被更新的外部表的行類型。如果選擇優(yōu)化掉RETURNING
計(jì)算不需要的列,應(yīng)該在這些列的位置上插入空值,或者生成一個(gè)忽略這些列的fdw_scan_tlist
列表。
不管該查詢是否具有RETURNING
子句,查詢所報(bào)告的行計(jì)數(shù)必須由 FDW 本身增加。當(dāng)查詢沒有該子句時(shí),F(xiàn)DW 還必須為EXPLAIN ANALYZE
情況下的ForeignScanState
節(jié)點(diǎn)增加行計(jì)數(shù)。
如果IterateDirectModify
指針被設(shè)置為NULL
,不會(huì)嘗試在遠(yuǎn)程服務(wù)器上執(zhí)行直接修改。
void
EndDirectModify(ForeignScanState *node);
在遠(yuǎn)程服務(wù)器上的直接修改后進(jìn)行清理。通常釋放用 palloc 分配的內(nèi)存并不重要,但是諸如打開的文件和到遠(yuǎn)程服務(wù)器的連接應(yīng)該被清除。
如果EndDirectModify
指針被設(shè)置為NULL
,不會(huì)嘗試在遠(yuǎn)程服務(wù)器上執(zhí)行直接修改。
如果一個(gè) FDW 希望支持后期行鎖定(如第 56.5 節(jié)中所述),它必須提供下列回調(diào)函數(shù):
RowMarkType
GetForeignRowMarkType(RangeTblEntry *rte,
LockClauseStrength strength);
報(bào)告要對(duì)一個(gè)外部表使用哪個(gè)行標(biāo)記選項(xiàng)。rte
是該表的RangeTblEntry
節(jié)點(diǎn),而strength
描述FOR UPDATE/SHARE
子句(如果有)所要求的鎖長(zhǎng)度。結(jié)果必須是RowMarkType
枚舉類型的一個(gè)成員。
這個(gè)函數(shù)在查詢規(guī)劃期間會(huì)為每一個(gè)出現(xiàn)在UPDATE
、DELETE
或者SELECT FOR UPDATE/SHARE
查詢中的外部表調(diào)用,并且該外部表不是UPDATE
和DELETE
的目標(biāo)。
如果GetForeignRowMarkType
指針被設(shè)置為NULL
,將總是使用ROW_MARK_COPY
選項(xiàng)(這意味著將不會(huì)調(diào)用RefetchForeignRow
,因此也不必提供它)。
更多信息請(qǐng)見第 56.5 節(jié)。
void
RefetchForeignRow(EState *estate,
ExecRowMark *erm,
Datum rowid,
TupleTableSlot *slot,
bool *updated);
從外部表中重新取得一個(gè)元組槽,如有必要先鎖定它。estate
是該查詢的全局執(zhí)行狀態(tài)。erm
是描述目標(biāo)外部表以及要獲取的行鎖類型(如果有)的ExecRowMark
結(jié)構(gòu)。rowid
標(biāo)識(shí)要取得的元組。 slot
在調(diào)用時(shí)不包含有用內(nèi)容,但可用于保存返回的元組。
updated
是一個(gè)輸出參數(shù)。
此函數(shù)應(yīng)將元組存儲(chǔ)到提供的槽中,或者在無法獲得行鎖時(shí)清除該槽。 要獲得的行鎖由erm->markType
定義,它是之前由GetForeignRowMarkType
返回的值(ROW_MARK_REFERENCE
標(biāo)識(shí)只重新取得元組但不獲得任何鎖,這個(gè)例程將不會(huì)看到ROW_MARK_COPY
)。
此外,如果取得的是一個(gè)更新過的版本而不是之前獲得的同一版本,*updated
應(yīng)被設(shè)置為true
(如果 FDW 無法確定這一點(diǎn),推薦總是返回true
)。
注意在默認(rèn)情況下,獲取行鎖失敗應(yīng)該導(dǎo)致產(chǎn)生錯(cuò)誤。如果erm->waitPolicy
指定了SKIP LOCKED
,只有返回空槽才是合適的。
rowid
是要被重新取得的行之前讀到的ctid
值。盡管rowid
值被作為Datum
傳遞,但是目前它只能被讀作tid
。選擇該函數(shù) API 是希望未來能允許其他的行 ID 數(shù)據(jù)類型。
如果RefetchForeignRow
指針被設(shè)置為NULL
,重新取得行的嘗試將會(huì)失敗并伴隨有一個(gè)錯(cuò)誤消息。
更多信息請(qǐng)見第 56.5 節(jié)。
bool
RecheckForeignScan(ForeignScanState *node, TupleTableSlot *slot);
重新檢查之前返回的元組是否仍然匹配相關(guān)的掃描和連接條件,并且可能提供該元組的一個(gè)修改版本。對(duì)于不執(zhí)行連接下推的外部數(shù)據(jù)包裝器,通常把這設(shè)置為NULL
并且恰當(dāng)?shù)卦O(shè)置fdw_recheck_quals
會(huì)更方便。不過當(dāng)外部連接被下推時(shí),把與所有基表相關(guān)的檢查重新應(yīng)用在結(jié)果元組上是不夠的,即便所有需要的屬性都存在也是如此,因?yàn)槠ヅ淠硞€(gè)條件失敗可能會(huì)導(dǎo)致某些屬性變成 NULL,而不是沒有元組被返回。
RecheckForeignScan
能夠重新檢查條件,并且在它們?nèi)匀粷M足時(shí)返回真,否則返回假,但是它也能夠在提供的槽中存儲(chǔ)一個(gè)替換元組。
要實(shí)現(xiàn)連接下推,外部數(shù)據(jù)包裝器通常將構(gòu)造一個(gè)可替代的本地連接計(jì)劃,它只被用來做重新檢查。這將變成ForeignScan
的外子計(jì)劃。在需要一次重新檢查時(shí),這個(gè)子計(jì)劃可以被執(zhí)行并且結(jié)果元組可以被存儲(chǔ)在槽中。這個(gè)計(jì)劃不需要效率很高,因?yàn)椴粫?huì)有基表返回超過一行。例如,它可以把所有的連接實(shí)現(xiàn)為嵌套循環(huán)。函數(shù)GetExistingLocalJoinPath
可以被用來在已有的路徑中搜索合適的本地連接路徑,它可以被用作替換的本地連接計(jì)劃。
GetExistingLocalJoinPath
會(huì)在指定連接關(guān)系的路徑列表中搜索一個(gè)非參數(shù)化路徑(如果沒有找到這樣的路徑,它會(huì)返回 NULL,這種情況下外部數(shù)據(jù)包裝器可以自行構(gòu)造本地路徑或者可以選擇不為這個(gè)連接創(chuàng)建訪問路徑)。
EXPLAIN
的FDW例程void
ExplainForeignScan(ForeignScanState *node,
ExplainState *es);
為一個(gè)外部表掃描打印額外的EXPLAIN
輸出。這個(gè)函數(shù)可以調(diào)用ExplainPropertyText
和相關(guān)函數(shù)來向EXPLAIN
輸出中增加域。es
中的標(biāo)志域可以被用來決定什么將被打印,并且ForeignScanState
節(jié)點(diǎn)的狀態(tài)可以被檢查來為
EXPLAIN ANALYZE
提供運(yùn)行時(shí)統(tǒng)計(jì)數(shù)據(jù)。
如果ExplainForeignScan
指針被設(shè)置為NULL
,在EXPLAIN
期間不會(huì)打印任何額外的信息。
void
ExplainForeignModify(ModifyTableState *mtstate,
ResultRelInfo *rinfo,
List *fdw_private,
int subplan_index,
struct ExplainState *es);
為一個(gè)外部表更新打印額外的EXPLAIN
輸出。這個(gè)函數(shù)可以調(diào)用ExplainPropertyText
和相關(guān)函數(shù)來向EXPLAIN
輸出中增加域。es
中的標(biāo)志域可以被用來決定什么將被打印,并且ModifyTableState
節(jié)點(diǎn)的狀態(tài)可以被檢查來為
EXPLAIN ANALYZE
提供運(yùn)行時(shí)統(tǒng)計(jì)數(shù)據(jù)。前四個(gè)參數(shù)和BeginForeignModify
相同。
如果ExplainForeignModify
指針被設(shè)置為NULL
,在EXPLAIN
期間不會(huì)打印任何額外的信息。
void
ExplainDirectModify(ForeignScanState *node,
ExplainState *es);
為遠(yuǎn)程服務(wù)器上的直接修改打印額外的EXPLAIN
輸出。這個(gè)函數(shù)可以調(diào)用ExplainPropertyText
和相關(guān)函數(shù)來為EXPLAIN
輸出增加域。es
中的標(biāo)志域可以被用來判斷要打印什么,并且在EXPLAIN ANALYZE
情況中可以觀察
ForeignScanState
節(jié)點(diǎn)的狀態(tài)來提供運(yùn)行時(shí)統(tǒng)計(jì)信息。
如果ExplainDirectModify
指針被設(shè)置為NULL
,EXPLAIN
期間不會(huì)打印出額外的信息。
ANALYZE
的FDW例程bool
AnalyzeForeignTable(Relation relation,
AcquireSampleRowsFunc *func,
BlockNumber *totalpages);
當(dāng)ANALYZE被執(zhí)行在一個(gè)外部表上時(shí)會(huì)調(diào)用這個(gè)函數(shù)。如果FDW可以為這個(gè)外部表收集統(tǒng)計(jì)信息,它會(huì)返回true
并提供一個(gè)函數(shù)指針,該函數(shù)將將從func
中的表上收集采樣行,外加
totalpages
中頁(yè)面中的表尺寸估計(jì)值。否則,返回false
。
如果FDW不支持為任何表收集統(tǒng)計(jì)信息,AnalyzeForeignTable
指針可以被設(shè)置為NULL
。
如果提供,采樣收集函數(shù)必須具有簽名
int
AcquireSampleRowsFunc(Relation relation,
int elevel,
HeapTuple *rows,
int targrows,
double *totalrows,
double *totaldeadrows);
應(yīng)該從該表上收集最多targrows
行的一個(gè)隨機(jī)采樣并將它存放到調(diào)用者提供的rows
數(shù)組中。實(shí)際被收集的行的數(shù)量必須被返回。另外,將表中有效行和死亡行的總數(shù)存儲(chǔ)到輸出參數(shù)totalrows
和totaldeadrows
中(如果FDW沒有死亡行的概念,將
totaldeadrows
設(shè)置為 0 )。
IMPORT FOREIGN SCHEMA
的 FDW 例程List *
ImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid);
取得一個(gè)外部表創(chuàng)建命令的列表。在執(zhí)行IMPORT FOREIGN SCHEMA時(shí)會(huì)調(diào)用這個(gè)函數(shù),并且會(huì)把該語句的解析樹以及要使用的外部服務(wù)器的 OID 傳遞給它。它應(yīng)該返回一個(gè) C 字符串的列表,每一個(gè)必須包含一個(gè)CREATE FOREIGN TABLE命令。這些命令將被核心服務(wù)器所解析和執(zhí)行。
在ImportForeignSchemaStmt
結(jié)構(gòu)中,remote_schema
是要從其中導(dǎo)入這些表的遠(yuǎn)程模式的名稱。list_type
標(biāo)識(shí)如何過濾表名:FDW_IMPORT_SCHEMA_ALL
表示該遠(yuǎn)程模式中的所有表都應(yīng)該被導(dǎo)入(這種情況下
table_list
為空),FDW_IMPORT_SCHEMA_LIMIT_TO
表示只包括table_list
中列出的表,而FDW_IMPORT_SCHEMA_EXCEPT
則表示排除table_list
中列出的表。options
是一個(gè)用于該導(dǎo)入處理的選項(xiàng)列表。選項(xiàng)的含義由
FDW 決定。例如,一個(gè) FDW 可以用一個(gè)選項(xiàng)來定義是否應(yīng)該導(dǎo)入列的NOT NULL
屬性。這些選項(xiàng)不需要與那些 FDW 支持的數(shù)據(jù)庫(kù)對(duì)象選項(xiàng)有什么關(guān)系。
FDW 可能會(huì)忽略ImportForeignSchemaStmt
的local_schema
域,因?yàn)楹诵姆?wù)器會(huì)自動(dòng)地向解析好的CREATE FOREIGN TABLE
命令中插入本地模式的名稱。
FDW 也不必?fù)?dān)心實(shí)現(xiàn)list_type
以及table_list
所指定的過濾,因?yàn)楹诵姆?wù)器將自動(dòng)根據(jù)那些選項(xiàng)跳過為被排除的表所返回的命令。不過,起初就避免為被排除的表創(chuàng)建命令當(dāng)然更好。函數(shù)IsImportableForeignTable()
可以用來測(cè)試一個(gè)給定的外部表名是否能通過該過濾器。
如果 FDW 不支持導(dǎo)入表定義,ImportForeignSchema
指針可以被設(shè)置為NULL
。
ForeignScan
節(jié)點(diǎn)可以選擇支持并行執(zhí)行。一個(gè)并行的ForeignScan
將在多個(gè)進(jìn)程中被執(zhí)行并且在相互合作的進(jìn)程中每一個(gè)元組必須只被返回一次。要做到這樣,進(jìn)程可以通過動(dòng)態(tài)共享內(nèi)存的固定尺寸塊來協(xié)作。并不保證在每一個(gè)進(jìn)程中這部份共享內(nèi)存都被映射到相同的地址,因此不能包含指針。下面的函數(shù)通常都是可選的,但是如果要支持并行執(zhí)行就必須提供其中的大部分。
bool
IsForeignScanParallelSafe(PlannerInfo *root, RelOptInfo *rel,
RangeTblEntry *rte);
測(cè)試一個(gè)掃描是否可以在一個(gè)并行工作者中被執(zhí)行。只有當(dāng)規(guī)劃器相信可以使用并行計(jì)劃時(shí)才會(huì)調(diào)用這個(gè)函數(shù),如果該掃描在并行工作者中可以安全運(yùn)行這個(gè)函數(shù)應(yīng)該返回真。如果遠(yuǎn)程數(shù)據(jù)源具有事務(wù)語義,情況通常都不是這樣,除非工作者到數(shù)據(jù)的連接能夠以某種方式共享與領(lǐng)導(dǎo)者相同的事務(wù)環(huán)境。
如果沒有定義這個(gè)函數(shù),則假定該掃描必須被放置在并行領(lǐng)導(dǎo)者中。注意返回真并不意味著該掃描本身可以被并行完成,只是說明該掃描可以在一個(gè)并行工作者中執(zhí)行。因此,即便當(dāng)不支持并行執(zhí)行時(shí),定義這個(gè)方法也是有用的。
Size
EstimateDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt);
估算并行操作所需的動(dòng)態(tài)共享內(nèi)存的數(shù)量。這可能比實(shí)際要用的數(shù)量更大,但是絕不能更小。返回值的單位是字節(jié)。這個(gè)函數(shù)是可選的,并且在不需要時(shí)可以省略。但是如果它被省略,接下來的三個(gè)函數(shù)也必須被省略,因?yàn)椴粫?huì)為FDW分配共享內(nèi)存。
void
InitializeDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt,
void *coordinate);
初始化并行操作所需的動(dòng)態(tài)共享內(nèi)存。coordinate
指向一塊共享內(nèi)存區(qū)域,其尺寸等于EstimateDSMForeignScan
的返回值。這個(gè)函數(shù)是可選的,并且在不需要時(shí)可以省略。
void
ReInitializeDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt,
void *coordinate);
當(dāng)外部掃描計(jì)劃將要被重新掃描時(shí),重新初始化并行操作所要求的動(dòng)態(tài)共享內(nèi)存。這個(gè)函數(shù)是可選的,并且在不需要時(shí)可以省略。推薦的措施是這個(gè)函數(shù)只重置共享狀態(tài),而ReScanForeignScan
函數(shù)僅重置本地狀態(tài)。當(dāng)前,這個(gè)函數(shù)將在ReScanForeignScan
之前被調(diào)用,但是最好不要依賴于這種順序。
void
InitializeWorkerForeignScan(ForeignScanState *node, shm_toc *toc,
void *coordinate);
基于領(lǐng)導(dǎo)者在InitializeDSMForeignScan
期間建立的共享狀態(tài)初始化并行工作者的本地狀態(tài)。這個(gè)函數(shù)是可選的,并且在不需要時(shí)可以省略。
void
ShutdownForeignScan(ForeignScanState *node);
在預(yù)見到節(jié)點(diǎn)將不會(huì)被執(zhí)行完時(shí)釋放資源。這個(gè)函數(shù)不會(huì)在所有的情況中執(zhí)行,有時(shí)會(huì)在沒有先調(diào)用這個(gè)函數(shù)之前調(diào)用EndForeignScan
。由于在這個(gè)回調(diào)被調(diào)用之后并行查詢使用的DSM段將被銷毀,希望在DMS段消失前采取某種行動(dòng)的外部數(shù)據(jù)包裝器應(yīng)該實(shí)現(xiàn)這個(gè)方法。
List *
ReparameterizeForeignPathByChild(PlannerInfo *root, List *fdw_private,
RelOptInfo *child_rel);
在把一個(gè)由給定子關(guān)系child_rel
的最頂層父關(guān)系參數(shù)化的路徑轉(zhuǎn)換成由該子關(guān)系參數(shù)化的路徑時(shí)會(huì)調(diào)用這個(gè)函數(shù)。該函數(shù)被用于重新參數(shù)化任意路徑或者轉(zhuǎn)化一個(gè)ForeignPath
的給定fdw_private
成員中保存的任意表達(dá)式節(jié)點(diǎn)。該回調(diào)可能會(huì)根據(jù)需要使用reparameterize_path_by_child
、
adjust_appendrel_attrs
或者adjust_appendrel_attrs_multilevel
。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: