# 57.2.外部数据包装回调例程

57.2.1. 用于扫描外部表的FDW例程

57.2.2. 扫描外部联接的FDW例程

57.2.3. 用于规划扫描后/连接处理的FDW例程

57.2.4. 用于更新外部表的FDW例程

57.2.5. 用于截断

57.2.6. 用于行锁定的FDW例程

57.2.7. 用于解释

57.2.8. 用于分析

57.2.9. 用于导入外部模式

57.2.10. 用于并行执行的FDW例程

57.2.11. 用于异步执行的FDW例程

57.2.12. 用于路径重新参数化的FDW例程

FDW handler函数返回palloc'dFDW路线包含指向下面描述的回调函数的指针的结构。扫描相关功能是必需的,其余功能是可选的。

这个FDW路线结构类型在中声明src/include/foreign/fdwapi。H,有关更多详细信息,请参见。

# 57.2.1.用于扫描外部表的FDW例程

void
GetForeignRelSize(PlannerInfo *root,
                  RelOptInfo *baserel,
                  Oid foreigntableid);

获取外部表的关系大小估计值。这是在扫描外部表的查询计划开始时调用的。是规划师关于查询的全局信息;巴塞雷尔是规划师关于该表的信息;和外国人是吗pg_类外国桌子的老字号。(外国人可以从planner数据结构中获取,但它是显式传递的,以节省工作量。)

此函数应该更新baserel->rows在考虑限制quals完成的筛选后,表扫描返回的预期行数。初始值baserel->rows这只是一个恒定的默认估计值,如果可能的话,应该将其替换。该功能也可以选择更新baserel->宽度如果它能更好地估计平均结果行宽度。(初始值基于列数据类型和最后一个列测量的列平均宽度值。)分析)此外,此功能可能会更新baserel->tuples如果它能够更好地估计外部表的总行数。(初始值来自pg_类.重元组它表示上一个分析; 会的-1如果没有分析已经在这张外国桌子上完成了。)

看见第57.4节了解更多信息。

void
GetForeignPaths(PlannerInfo *root,
                RelOptInfo *baserel,
                Oid foreigntableid);

为外部表上的扫描创建可能的访问路径。这在查询规划期间调用。参数与的相同GetForeignRelSize,这已经被称为。

此函数必须至少生成一条访问路径(外国人节点)进行扫描,并且必须调用添加路径将每个这样的路径添加到baserel->pathlist.建议使用创建_foreign扫描_路径建造外国人节点。该功能可以生成多个访问路径,例如,具有有效访问权限的路径路径键表示预先排序的结果。每个访问路径必须包含成本估算,并且可以包含识别特定扫描方法所需的任何FDW私有信息。

看见第57.4节了解更多信息。

ForeignScan *
GetForeignPlan(PlannerInfo *root,
               RelOptInfo *baserel,
               Oid foreigntableid,
               ForeignPath *best_path,
               List *tlist,
               List *scan_clauses,
               Plan *outer_plan);

创建一个外国扫描从选定的外部访问路径规划节点。这在查询计划结束时调用。参数为GetForeignRelSize,加上所选的外国人(以前由获得外国路径, GetForeignJoinPath获得外国优先权),计划节点要发出的目标列表,计划节点要执行的限制条款,以及外国扫描,用于由外国扫描(如果路径用于连接而不是基关系,外国人残疾人.)

此函数必须创建并返回外国扫描计划节点;建议使用进行国外扫描建造外国扫描节点。

看见第57.4节了解更多信息。

void
BeginForeignScan(ForeignScanState *node,
                 int eflags);

开始执行外部扫描。这在executor启动期间调用。它应该在扫描开始之前执行所需的任何初始化,但不应该开始执行实际的扫描(这应该在第一次调用迭代扫描).这个外国节点已创建,但其fdw_州字段仍然为空。有关要扫描的表的信息可通过外国节点(尤其是从底层外国扫描“计划”节点,其中包含由获取国外计划). eflags包含描述此计划节点的执行器操作模式的标志位。

注意,当(仅适用于eflags和EXEC标志)如果是真的,此功能不应执行任何外部可见的操作;它应该只执行使节点状态对其有效所需的最低限度解释外国扫描EndForeignScan.

TupleTableSlot *
IterateForeignScan(ForeignScanState *node);

从外部源获取一行,并将其返回到元组表槽(节点的ScanTupleSlot应用于此目的)。如果没有更多行可用,则返回NULL。元组表插槽基础设施允许返回物理元组或虚拟元组;在大多数情况下,从性能角度来看,后一种选择更可取。请注意,这是在短期内存上下文中调用的,在调用之间将重置该上下文。在内存中创建一个内存上下文开始信息扫描如果您需要寿命更长的存储,或使用查询节点的大片私有土地.

返回的行必须与fdw_扫描列表如果提供了目标列表,则它们必须与正在扫描的外部表的行类型匹配。如果选择优化不需要的提取列,则应在这些列位置插入空值,或者生成一个fdw_扫描列表省略这些列的列表。

请注意,PostgreSQL的executor不关心返回的行是否违反外部表上定义的任何约束,但planner会关心,如果外部表中存在不满足声明约束的可见行,则可能会错误地优化查询。如果在用户声明约束应为true时违反了约束,则可能需要引发错误(就像在数据类型不匹配的情况下需要做的那样)。

void
ReScanForeignScan(ForeignScanState *node);

从头开始重新启动扫描。请注意,扫描所依赖的任何参数的值都可能已更改,因此新扫描不一定返回完全相同的行。

void
EndForeignScan(ForeignScanState *node);

结束扫描并释放资源。释放palloc的内存通常并不重要,但例如,应该清理打开的文件和与远程服务器的连接。

# 57.2.2.扫描外部联接的FDW例程

如果FDW支持远程执行外部联接(而不是通过获取两个表的数据并在本地执行联接),它应该提供以下回调函数:

void
GetForeignJoinPaths(PlannerInfo *root,
                    RelOptInfo *joinrel,
                    RelOptInfo *outerrel,
                    RelOptInfo *innerrel,
                    JoinType jointype,
                    JoinPathExtraData *extra);

为属于同一外部服务器的两个(或多个)外部表的联接创建可能的访问路径。在查询计划期间调用此可选函数。就像获得外国路径,此函数应生成外国人所提供数据的路径细木工(使用创建外部连接路径来建造它们),然后打电话给添加路径将这些路径添加到为联接考虑的路径集。但不像获得外国路径,此函数不必成功创建至少一条路径,因为涉及局部连接的路径总是可能的。

注意,对于相同的连接关系,该函数将被重复调用,内部和外部关系的组合不同;FDW有责任尽量减少重复工作。

如果外国人为连接选择路径,它将代表整个连接过程;将不使用为组件表和辅助联接生成的路径。连接路径的后续处理过程与扫描单个外部表的路径的处理过程大致相同。一个区别是斯坎雷利德结果如何外国扫描计划节点应该设置为零,因为它不代表单个关系;取而代之的是F_relids领域外国扫描节点表示已联接的关系集。(后一个字段由core planner代码自动设置,无需由FDW填写。)另一个区别是,由于无法从系统目录中找到远程联接的列列表,因此FDW必须填充fdw_扫描列表有一份合适的目标中心节点,表示它将在运行时在返回的元组中提供的列集。

看见第57.4节了解更多信息。

# 57.2.3.用于规划扫描后/连接处理的FDW例程

如果FDW支持执行远程扫描后/连接处理,例如远程聚合,则它应提供以下回调函数:

void
GetForeignUpperPaths(PlannerInfo *root,
                     UpperRelationKind stage,
                     RelOptInfo *input_rel,
                     RelOptInfo *output_rel,
                     void *extra);

为用户创建可能的访问路径上等亲属处理,这是planner对所有扫描后/连接查询处理的术语,例如聚合、窗口函数、排序和表更新。在查询计划期间调用此可选函数。目前,只有当查询中涉及的所有基关系都属于同一个FDW时,才会调用它。此函数应生成外国人FDW知道如何远程执行的任何扫描后/连接处理的路径(使用创建外部路径来建造它们),然后打电话给添加路径将这些路径添加到指定的上关系。就像GetForeignJoinPath,此函数不必成功创建任何路径,因为涉及本地处理的路径总是可能的。

这个阶段参数标识当前正在考虑的扫描后/连接步骤。输出_rel应接收代表该步骤计算的路径的上关系,以及输入_rel表示此步骤的输入的关系。这个额外的参数提供了其他详细信息,目前,该参数仅为UPPERREL_PARTIAL_GROUP_AGGUPPERREL_GROUP_AGG,在这种情况下,它指向GroupPathExtraData结构还是为了UPPERREL_决赛,在这种情况下,它指向最后一个特斯拉达结构(注意外国人添加到输出_rel通常不会直接依赖于输入_rel,因为它们的处理预计将在外部完成。但是,检查之前为上一个处理步骤生成的路径有助于避免重复的规划工作。)

看见第57.4节了解更多信息。

# 57.2.4.用于更新外部表的FDW例程

如果FDW支持可写外部表,则应根据FDW的需要和功能提供以下部分或全部回调函数:

void
AddForeignUpdateTargets(PlannerInfo *root,
                        Index rtindex,
                        RangeTblEntry *target_rte,
                        Relation target_relation);

使现代化删去对以前由表扫描函数获取的行执行操作。FDW可能需要额外的信息,例如行ID或主键列的值,以确保它能够识别要更新或删除的确切行。为了支持这一点,此函数可以向列表中添加额外的隐藏或“垃圾”目标列,这些列将在查询期间从外部表中检索使现代化删去.

为此,构建一个变量表示所需的额外值,并将其传递给添加_行_标识_变量,以及“垃圾”列的名称。(如果需要多个列,可以多次执行此操作。)必须为每个不同的列选择一个不同的列名称变量你需要,除了变量除了瓦诺字段可以而且应该共享一个列名。核心系统使用垃圾列名片状为了一张桌子片状ctidctid*N*对于ctid, 大杂烩整整一排变量带有变形金刚 = 记录大杂烩*N*整整一排变量具有变形金刚等于表中声明的行类型。在可能的情况下重新使用这些名称(planner将合并对相同垃圾列的重复请求)。如果除此之外还需要其他类型的垃圾列,那么最好选择一个以扩展名为前缀的名称,以避免与其他FDW冲突。

如果AddForeignUpdateTargets指针设置为无效的,不添加额外的目标表达式。(这将使其无法实施删去不过是行动使现代化如果FDW依赖一个不变的主键来标识行,那么它仍然是可行的。)

List *
PlanForeignModify(PlannerInfo *root,
                  ModifyTable *plan,
                  Index resultRelation,
                  int subplan_index);

对外部表执行插入、更新或删除所需的任何其他计划操作。此函数用于生成FDW专用信息,该信息将附加到可修改执行更新操作的计划节点。这些私人信息必须以列表,并将交付给开始修改在执行阶段。

是规划师关于查询的全局信息。计划是吗可修改计划节点,除了FDWPrivList领域结果相关通过范围表索引标识目标外部表。子计划指数确定目标的可修改计划节点,从零开始计数;如果要索引到的每个目标关系子结构,请使用此选项计划节点。

看见第57.4节了解更多信息。

如果PlanForeignModify指针设置为无效的,没有采取额外的计划时间行动二等兵名单已送交开始修改将是零。

void
BeginForeignModify(ModifyTableState *mtstate,
                   ResultRelInfo *rinfo,
                   List *fdw_private,
                   int subplan_index,
                   int eflags);

开始执行外部表修改操作。在执行器启动期间调用此例程。它应该在实际修改表之前执行所需的任何初始化。随后ExecForeignInsert/ExecForeignBatchInsert, ExecForeignUpdateExecForeignDelete将调用以插入、更新或删除元组。

mtstate是整个系统的状态可修改正在执行的计划节点;有关计划和执行状态的全局数据可通过此结构获得。林福是吗结果林福描述目标外部表的结构。(小标题)里夫达斯特领域结果林福可供FDW存储此操作所需的任何私有状态。)二等兵包含由生成的私有数据PlanForeignModify,如果有的话。子计划指数确定目标的可修改这是计划节点。eflags包含描述此计划节点的执行器操作模式的标志位。

注意,当(仅适用于eflags和EXEC标志)如果是真的,此功能不应执行任何外部可见的操作;它应该只执行使节点状态对其有效所需的最低限度解释外国修改EndForeignModify.

如果开始修改指针设置为无效的,执行器启动期间未采取任何措施。

TupleTableSlot *
ExecForeignInsert(EState *estate,
                  ResultRelInfo *rinfo,
                  TupleTableSlot *slot,
                  TupleTableSlot *planSlot);

在外部表中插入一个元组。大片私有土地是查询的全局执行状态。林福是吗结果林福描述目标外部表的结构。狭槽包含要插入的元组;它将匹配外部表的行类型定义。平面槽包含由可修改计划节点的子计划;它不同于狭槽可能包含额外的“垃圾”列。(小标题)平面槽通常情况下,它对插入案例,但为完整性提供。)

返回值要么是包含实际插入的数据的插槽(这可能与提供的数据不同,例如由于触发器操作),要么是NULL(如果没有实际插入行,通常也是由于触发器)。警察进来了狭槽可以重新用于此目的。

仅当插入声明有一个返回子句或包含一种观点带支票选项; 或者如果外国桌子上有赛后触发触发器需要所有列,但FDW可以根据触发器的内容选择优化返回部分或所有列返回条款或带支票选项限制。无论如何,必须返回一些槽来表示成功,否则查询报告的行数将是错误的。

如果死刑执行官指针设置为无效的,尝试插入外部表将失败,并显示错误消息。

请注意,在将路由元组插入外部表分区或执行抄袭在国外的桌子上,在这种情况下,它的调用方式与在国外的不同插入案例请参阅下面描述的回调函数,这些函数允许FDW支持该功能。

TupleTableSlot **
ExecForeignBatchInsert(EState *estate,
                       ResultRelInfo *rinfo,
                       TupleTableSlot **slots,
                       TupleTableSlot **planSlots,
                       int *numSlots);

在外部表中批量插入多个元组。这些参数对于死刑执行官除了插槽平面槽包含多个元组和*纽姆斯洛特指定这些数组中的元组数。

返回值是包含实际插入的数据的插槽数组(这可能与提供的数据不同,例如由于触发操作的结果)警察进来了插槽可以重新用于此目的。在中返回成功插入的元组数*纽姆斯洛特.

仅当插入声明包含一种观点带支票选项; 或者如果外国桌子上有赛后触发触发器需要所有列,但FDW可以根据触发器的内容选择优化返回部分或所有列带支票选项限制。

如果ExecForeignBatchInsertGetForeignModifyBatchSize指针设置为无效的,尝试插入到外部表将使用死刑执行官.如果插入返回条款

请注意,将路由元组插入外部表分区时,也会调用此函数。请参阅下面描述的回调函数,这些函数允许FDW支持该功能。

int
GetForeignModifyBatchSize(ResultRelInfo *rinfo);

报告单个数据集所包含的最大元组数ExecForeignBatchInsert调用可以处理指定的外部表。执行器最多将给定数量的元组传递给ExecForeignBatchInsert. 林福是吗结果林福描述目标外部表的结构。FDW将提供一个外部服务器和/或外部表选项,供用户设置该值或某些硬编码值。

如果ExecForeignBatchInsertGetForeignModifyBatchSize指针设置为无效的,尝试插入到外部表将使用死刑执行官.

TupleTableSlot *
ExecForeignUpdate(EState *estate,
                  ResultRelInfo *rinfo,
                  TupleTableSlot *slot,
                  TupleTableSlot *planSlot);

更新外部表中的一个元组。大片私有土地是查询的全局执行状态。林福是吗结果林福描述目标外部表的结构。狭槽包含元组的新数据;它将匹配外部表的行类型定义。平面槽包含由可修改计划节点的子计划。不像狭槽,此元组只包含查询更改的列的新值,因此不要依赖外部表的属性号进行索引平面槽而且平面槽通常包含额外的“垃圾”列。特别是AddForeignUpdateTargets将从此插槽中提供。

返回值要么是包含实际更新的行的插槽(这可能与提供的数据不同,例如由于触发器操作),要么是NULL(如果没有实际更新行,通常也是由于触发器)。警察进来了狭槽可以重新用于此目的。

仅当使现代化声明有一个返回子句或包含一种观点带支票选项; 或者如果外国桌子上有赛后触发触发器需要所有列,但FDW可以根据触发器的内容选择优化返回部分或所有列返回条款或带支票选项限制。无论如何,必须返回一些槽来表示成功,否则查询报告的行数将是错误的。

如果ExecForeignUpdate指针设置为无效的,尝试更新外部表将失败,并显示错误消息。

TupleTableSlot *
ExecForeignDelete(EState *estate,
                  ResultRelInfo *rinfo,
                  TupleTableSlot *slot,
                  TupleTableSlot *planSlot);

从外部表中删除一个元组。大片私有土地是查询的全局执行状态。林福是吗结果林福描述目标外部表的结构。狭槽不包含任何调用时有用的内容,但可用于保存返回的元组。平面槽包含由可修改计划节点的子计划;特别是,它将承载任何由AddForeignUpdateTargets。垃圾列必须用于标识要删除的元组。

返回值要么是包含已删除行的插槽,要么是NULL(如果未删除任何行)(通常是由于触发器)。警察进来了狭槽可以用来保存要返回的元组。

仅当删去查询有一个返回子句或foreign表具有赛后触发触发器需要所有列,但FDW可以根据触发器的内容选择优化返回部分或所有列返回条款无论如何,必须返回一些槽来表示成功,否则查询报告的行数将是错误的。

如果ExecForeignDelete指针设置为无效的,尝试从外部表中删除将失败,并显示错误消息。

void
EndForeignModify(EState *estate,
                 ResultRelInfo *rinfo);

结束表更新并释放资源。释放palloc的内存通常并不重要,但例如,应该清理打开的文件和与远程服务器的连接。

如果EndForeignModify指针设置为无效的,执行器关闭期间未采取任何措施。

插入到分区表中的元组插入抄袭路由到分区。如果FDW支持可路由的外部表分区,那么它还应该提供以下回调函数。这些函数在以下情况下也被调用:抄袭是在外国的桌子上执行的。

void
BeginForeignInsert(ModifyTableState *mtstate,
                   ResultRelInfo *rinfo);

开始对外部表执行插入操作。在这两种情况下,当第一个元组是为元组路由选择的分区,并且是在抄袭命令它应该在实际插入之前执行所需的任何初始化。随后死刑执行官ExecForeignBatchInsert将调用以将元组插入到外部表中。

mtstate是整个系统的状态可修改正在执行的计划节点;有关计划和执行状态的全局数据可通过此结构获得。林福是吗结果林福描述目标外部表的结构。(小标题)里夫达斯特领域结果林福可供FDW存储此操作所需的任何私有状态。)

当这被一个抄袭命令中与计划相关的全局数据mtstate未提供,并且平面槽参数死刑执行官随后为每个插入的元组调用无效的,外部表是为元组路由选择的分区还是命令中指定的目标。

如果Beginformeinsert指针设置为无效的,则不会对初始化执行任何操作。

请注意,如果FDW不支持可路由的外部表分区和/或执行抄袭在外国表上,此函数或ExecForeignInsert/ExecForeignBatchInsert后续调用必须根据需要抛出错误。

void
EndForeignInsert(EState *estate,
                 ResultRelInfo *rinfo);

结束插入操作并释放资源。释放palloc的内存通常并不重要,但例如,应该清理打开的文件和与远程服务器的连接。

如果EndForeignInsert指针设置为无效的,则不采取任何终止措施。

int
IsForeignRelUpdatable(Relation rel);

报告指定的外部表支持哪些更新操作。返回值应该是规则事件号的位掩码,使用CmdType列举;就是,(1<<CMD_UPDATE)=4对于使现代化, (1<<CMD_INSERT)=8对于插入(1<<CMD_DELETE)=16对于删去.

如果IsForeignRelable可更新吗指针设置为无效的,如果FDW提供,则假定外部表是可插入、可更新或可删除的死刑执行官, ExecForeignUpdateExecForeignDelete分别地只有当FDW支持一些可更新的表和一些不可更新的表时,才需要此函数。(即使如此,也允许在执行例程中抛出错误,而不是检入此函数。但是,此函数用于确定执行例程中显示的可更新性。)信息模式视图。)

通过实现一组替代接口,可以优化对外部表的某些插入、更新和删除。用于从远程服务器插入、更新和删除获取行,然后一次修改一行的普通接口。在某些情况下,这种逐行的方法是必要的,但可能效率低下。外部服务器是否可以在不实际检索行的情况下确定应该修改哪些行,以及是否没有影响操作的本地结构(行级本地触发器、存储的生成列或带支票选项父视图中的约束),然后可以进行安排,以便在远程服务器上执行整个操作。下面描述的接口使这成为可能。

bool
PlanDirectModify(PlannerInfo *root,
                 ModifyTable *plan,
                 Index resultRelation,
                 int subplan_index);

决定在远程服务器上执行直接修改是否安全。如果是,请返回符合事实的在执行了所需的计划行动之后。否则,请返回错误的.在查询计划期间调用此可选函数。如果这个功能成功,开始间接修改, 迭代直接修改EndDirectModify将在执行阶段调用。否则,将使用上述表更新功能执行表修改。参数与的相同PlanForeignModify.

要在远程服务器上执行直接修改,此函数必须使用外国扫描在远程服务器上执行直接修改的计划节点。这个操作结果相关田野外国扫描必须进行适当的设置。操作必须设置为CmdType与语句种类对应的枚举(即,CMD_更新对于更新, CMD_插入对于插入鸭子CMD_删除对于删除),以及结果相关参数必须复制到结果相关领域

看见第57.4节了解更多信息。

如果PlanDirectModify指针设置为无效的,则不会尝试在远程服务器上执行直接修改。

void
BeginDirectModify(ForeignScanState *node,
                  int eflags);

准备在远程服务器上执行直接修改。这在executor启动期间调用。它应该在直接修改之前执行所需的任何初始化(应该在第一次调用迭代直接修改).这个外国节点已创建,但其fdw_州字段仍然为空。有关要修改的表的信息可通过外国节点(尤其是从底层外国扫描“计划”节点,其中包含由PlanDirectModify). eflags包含描述此计划节点的执行器操作模式的标志位。

注意,当(仅适用于eflags和EXEC标志)如果是真的,此功能不应执行任何外部可见的操作;它应该只执行使节点状态对其有效所需的最低限度解释直接修改EndDirectModify.

如果开始间接修改指针设置为无效的,则不会尝试在远程服务器上执行直接修改。

TupleTableSlot *
IterateDirectModify(ForeignScanState *node);

插入, 使现代化删去查询没有返回子句,只需在远程服务器上直接修改后返回NULL。当查询包含子句时,获取一个结果,该结果包含查询所需的数据返回计算,将其返回到元组表槽(节点的ScanTupleSlot应用于此目的)。实际插入、更新或删除的数据必须存储在node->resultRelInfo->ri_projectReturning->pi_exprContext->ecxt_scantuple.如果没有更多行可用,则返回NULL。请注意,这是在短期内存上下文中调用的,在调用之间将重置该上下文。在内存中创建一个内存上下文开始间接修改如果您需要寿命更长的存储,或使用查询节点的大片私有土地.

返回的行必须与fdw_扫描列表如果提供了目标列表,则它们必须与正在更新的外部表的行类型匹配。如果选择优化返回计算时,应在这些列位置插入空值,否则将生成fdw_扫描列表省略这些列的列表。

无论查询是否包含该子句,查询报告的行数必须由FDW本身递增。当查询没有子句时,FDW还必须增加外国中的节点解释分析案例

如果迭代直接修改指针设置为无效的,则不会尝试在远程服务器上执行直接修改。

void
EndDirectModify(ForeignScanState *node);

在远程服务器上直接修改后进行清理。释放palloc的内存通常并不重要,但例如,应该清理打开的文件和与远程服务器的连接。

如果EndDirectModify指针设置为无效的,则不会尝试在远程服务器上执行直接修改。

# 57.2.5.用于截断

void
ExecForeignTruncate(List *rels,
                    DropBehavior behavior,
                    bool restart_seqs);

截断外部表。在以下情况下调用此函数:截断是在外国的桌子上执行的。雷尔斯这是一份关系要截断的外部表的数据结构。

行为要么放弃限制瀑布表明限制大量原始文件中要求提供选项截断指挥部。

如果重新启动符合事实的,原著截断司令部要求重新启动标识行为,否则继续身份要求采取行动。

请注意只有原始文件中指定的选项截断命令未传递给行政长官。此行为类似于的回调函数选择, 使现代化删去在外国的桌子上。

行政长官对于要截断其外部表的每个外部服务器调用一次。这意味着所有包含在雷尔斯必须属于同一台服务器。

如果行政长官指针设置为无效的,尝试截断外部表将失败,并显示错误消息。

# 57.2.6.用于行锁定的FDW例程

如果FDW希望支持晚行锁定(如中所述)第57.5节),它必须提供以下回调函数:

RowMarkType
GetForeignRowMarkType(RangeTblEntry *rte,
                      LockClauseStrength strength);

报告要用于外部表的行标记选项。rte是吗射程透镜表和力量描述了相关部门要求的锁紧强度更新/分享条款,如有。结果必须是行标记类型枚举类型。

在查询计划过程中,会为列表中出现的每个外部表调用此函数使现代化, 删去选择更新/共享查询,而不是使现代化删去.

如果GetForeignRowMarkType指针设置为无效的这个行标记副本选项始终被使用。(这意味着RefetchForeignRow将永远不会被调用,因此也不需要提供。)

看见第57.5节了解更多信息。

void
RefetchForeignRow(EState *estate,
                  ExecRowMark *erm,
                  Datum rowid,
                  TupleTableSlot *slot,
                  bool *updated);

如果需要,在锁定它之后,从外部表中重新获取一个元组插槽。大片私有土地是查询的全局执行状态。是吗ExecRowMark描述目标外部表和要获取的行锁类型(如果有)的结构。罗伊德标识要获取的元组。狭槽不包含任何调用时有用的内容,但可用于保存返回的元组。更新是一个输出参数。

这个函数应该将元组存储到提供的插槽中,或者在无法获得行锁时清除它。要获取的行锁类型由erm->markType,它是以前由返回的值GetForeignRowMarkType. (行标记参考意味着在不获取任何锁的情况下重新获取元组行标记副本永远不会被这种惯例所看到。)

此外*更新应该设置为符合事实的如果获取的是元组的更新版本,而不是之前获得的相同版本。(如果FDW对此不能确定,请始终返回。)符合事实的建议使用。)

请注意,默认情况下,未能获取行锁将导致引发错误;只有当跳转锁定选项由指定呃->等待政策.

这个罗伊德是吗ctid之前为要重新提取的行读取的值。虽然罗伊德值作为资料,目前只能是tid.选择函数API是希望将来可能允许行ID使用其他数据类型。

如果RefetchForeignRow指针设置为无效的,重新获取行的尝试将失败,并显示错误消息。

看见第57.5节了解更多信息。

bool
RecheckForeignScan(ForeignScanState *node,
                   TupleTableSlot *slot);

重新检查之前返回的元组是否仍与相关的扫描和连接限定符匹配,并可能提供元组的修改版本。对于不执行连接下推的外部数据包装器,将其设置为无效的而是设定重新检查质量恰如其分。然而,当按下外部联接时,即使所有需要的属性都存在,也不足以将与所有基表相关的检查重新应用于结果元组,因为未能匹配某些限定符可能会导致某些属性变为NULL,而不是不返回任何元组。外国扫描可以重新检查限定符,如果它们仍然满足,则返回true,否则返回false,但它也可以将替换元组存储到提供的插槽中。

为了实现连接下推,外部数据包装器通常会构造一个仅用于复查的替代本地连接计划;这将成为系统的外部子计划外国扫描.当需要重新检查时,可以执行此子计划,并将生成的元组存储在插槽中。这个计划不需要高效,因为没有一个基表会返回超过一行;例如,它可以将所有连接实现为嵌套循环。功能GetExistingLocalJoinPath可用于搜索现有路径以找到合适的本地连接路径,该路径可用作替代本地连接计划。GetExistingLocalJoinPath在指定联接关系的路径列表中搜索未经参数化的路径。(如果找不到这样的路径,则返回NULL,在这种情况下,外部数据包装器可以自行构建本地路径,也可以选择不为该连接创建访问路径。)

# 57.2.7.用于解释

void
ExplainForeignScan(ForeignScanState *node,
                   ExplainState *es);

打印其他解释外部表扫描的输出。此函数可以调用ExplainPropertyText以及相关函数,以将字段添加到解释输出国旗飘扬在天空中可用于确定要打印的内容以及外国可以检查节点以在中提供运行时统计信息解释分析案例

如果解释外国扫描指针设置为无效的,期间不会打印其他信息解释.

void
ExplainForeignModify(ModifyTableState *mtstate,
                     ResultRelInfo *rinfo,
                     List *fdw_private,
                     int subplan_index,
                     struct ExplainState *es);

打印其他解释外部表更新的输出。此函数可以调用ExplainPropertyText以及相关函数,以将字段添加到解释输出国旗飘扬在天空中可用于确定要打印的内容以及修改表状态可以检查节点以在中提供运行时统计信息解释分析案例前四个参数与for相同开始修改.

如果解释外国修改指针设置为无效的,期间不会打印其他信息解释.

void
ExplainDirectModify(ForeignScanState *node,
                    ExplainState *es);

打印其他解释在远程服务器上直接修改的输出。此函数可以调用ExplainPropertyText以及相关函数,以将字段添加到解释输出国旗飘扬在天空中可用于确定要打印的内容以及外国可以检查节点以在中提供运行时统计信息解释分析案例

如果解释直接修改指针设置为无效的,期间不会打印其他信息解释.

# 57.2.8.用于分析

bool
AnalyzeForeignTable(Relation relation,
                    AcquireSampleRowsFunc *func,
                    BlockNumber *totalpages);

在以下情况下调用此函数:分析是在外国的桌子上执行的。如果FDW可以收集此外部表的统计信息,它应该返回符合事实的,并提供指向函数的指针,该函数将从中的表中收集样本行*func,加上中表格的估计大小(以页数为单位)总页数*.否则,请返回错误的.

如果FDW不支持收集任何表的统计信息,则可分析的外国指针可以设置为无效的.

如果提供,样本采集功能必须具有签名

int
AcquireSampleRowsFunc(Relation relation,
                      int elevel,
                      HeapTuple *rows,
                      int targrows,
                      double *totalrows,
                      double *totaldeadrows);

随机抽取的样本多达*塔格罗斯应该从表中收集行,并将其存储到提供的调用者中大堆必须返回实际收集的行数。此外,将表中活行和死行总数的估计值存储到输出参数中全行完全死囚(设定)完全死囚*如果FDW没有任何死行概念,则设置为零。)

# 57.2.9.用于导入外部模式

List *
ImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid);

获取外部表创建命令的列表。执行时调用此函数导入外部模式,并传递该语句的解析树,以及要使用的外部服务器的OID。它应该返回一个C字符串列表,每个字符串必须包含创建外部表命令这些字符串将由核心服务器解析和执行。

ImportForeignSchemaStmt结构,远程模式要从中导入表的远程架构的名称。列表类型确定如何筛选表名:FDW_导入_模式_全部意味着应该导入远程架构中的所有表(在本例中)表1是空的),FDW_导入_模式_限制_至指仅包括表中列出的表格表1FDW_导入_模式_除外表示排除中列出的表格表1. 选项是用于导入过程的选项列表。选项的含义由FDW决定。例如,FDW可以使用一个选项来定义非空应该导入列的属性。这些选项不需要与FDW支持的数据库对象选项有任何关系。

FDW可能会忽略局部模式领域ImportForeignSchemaStmt,因为核心服务器将自动将该名称插入解析的创建外部表命令。

FDW不必关心如何实现列表类型表1,因为核心服务器将自动跳过根据这些选项排除的表的任何返回命令。然而,首先避免为排除的表创建命令通常是有用的。功能IsImportableForeignTable()可能有助于测试给定的外部表名是否会通过过滤器。

如果FDW不支持导入表定义,则ImportForeignSchema指针可以设置为无效的.

# 57.2.10.用于并行执行的FDW例程

A.外国扫描节点可以(可选)支持并行执行。相似的外国扫描将在多个进程中执行,并且必须在所有协作进程中准确返回每一行。为此,进程可以通过固定大小的动态共享内存块进行协调。这个共享内存不能保证在每个进程中映射到同一地址,因此它不能包含指针。以下函数都是可选的,但如果要支持并行执行,大多数函数都是必需的。

bool
IsForeignScanParallelSafe(PlannerInfo *root, RelOptInfo *rel,
                          RangeTblEntry *rte);

测试是否可以在并行工作进程内执行扫描。仅当计划员认为可能有并行计划时,才会调用此函数,如果在并行工作程序中运行扫描是安全的,则应返回true。如果远程数据源具有事务语义,则通常不会出现这种情况,除非工人与数据的连接可以以某种方式与领导者共享相同的事务上下文。

如果未定义此功能,则假定扫描必须在平行引线内进行。请注意,返回true并不意味着扫描本身可以并行完成,只意味着扫描可以在并行工作进程中执行。因此,即使不支持并行执行,也可以定义此方法。

Size
EstimateDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt);

估计并行操作所需的动态共享内存量。这可能高于实际使用量,但不得低于实际使用量。返回值以字节为单位。此功能为可选功能,不需要时可省略;但是如果省略了它,接下来的三个函数也必须省略,因为不会为FDW的使用分配共享内存。

void
InitializeDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt,
                         void *coordinate);

初始化并行操作所需的动态共享内存。坐标指向大小等于返回值的共享内存区域估计外汇扫描.此功能是可选的,如果不需要,可以省略。

void
ReInitializeDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt,
                           void *coordinate);

当外部扫描计划节点即将重新扫描时,重新初始化并行操作所需的动态共享内存。此功能是可选的,如果不需要,可以省略。建议的做法是,此功能仅重置共享状态,而重新扫描函数只重置本地状态。当前,此函数将在之前调用重新扫描,但最好不要依赖这种顺序。

void
InitializeWorkerForeignScan(ForeignScanState *node, shm_toc *toc,
                            void *coordinate);

根据领导者在任务期间设置的共享状态初始化并行工作程序的本地状态初始化SMForeignScan.此功能是可选的,如果不需要,可以省略。

void
ShutdownForeignScan(ForeignScanState *node);

当预期节点不会执行到完成时释放资源。并不是所有情况下都这样;有时EndForeignScan可以在没有先调用此函数的情况下调用。由于并行查询使用的DSM段在调用此回调后立即被销毁,因此希望在DSM段消失之前采取一些操作的外部数据包装器应该实现此方法。

# 57.2.11.用于异步执行的FDW例程

A.外国扫描节点可以(可选)支持异步执行,如中所述src/backend/executor/README。以下功能都是可选的,但如果要支持异步执行,则都是必需的。

bool
IsForeignPathAsyncCapable(ForeignPath *path);

测试一个给定的外国人path可以异步扫描底层外部关系。只有在给定路径是查询的直接子路径时,才会在查询规划结束时调用此函数附录路径当规划者认为异步执行可以提高性能时,如果给定的路径能够异步扫描外部关系,则应该返回true。

如果未定义此函数,则假定给定路径使用迭代扫描(这意味着永远不会调用下面描述的回调函数,因此也不需要提供它们。)

void
ForeignAsyncRequest(AsyncRequest *areq);

外国扫描节点。阿雷克是吗异步请求描述外国扫描节点和父节点追加从中请求元组的节点。此函数应将元组存储到areq->结果,并设置areq->请求完成符合事实的; 或者,如果它需要等待核心服务器外部的事件(如网络I/O),并且无法立即生成任何元组,请将标志设置为错误的,并设置areq->callback_挂起符合事实的对于外国扫描节点从下面描述的回调函数中获取回调。如果没有更多元组可用,请将插槽设置为NULL或空插槽,然后areq->请求完成符合事实的.建议使用执行异步请求完成ExecAsyncRequestPending阿雷克.

void
ForeignAsyncConfigureWait(AsyncRequest *areq);

配置文件描述符事件外国扫描节点希望等待。只有当外国扫描节点具有areq->callback_挂起标志集,并应将事件添加到作为事件集父母的追加阿雷克.有关详细信息,请参阅评论执行异步配置等待在里面src/backend/executor/execAsync。C了解更多信息。当文件描述符事件发生时,外宾将被调用。

void
ForeignAsyncNotify(AsyncRequest *areq);

处理已发生的相关事件,然后从外国扫描节点。此函数应在中设置输出参数阿雷克就像外国请求.

# 57.2.12.用于路径重新参数化的FDW例程

List *
ReparameterizeForeignPathByChild(PlannerInfo *root, List *fdw_private,
                                 RelOptInfo *child_rel);

转换由给定子关系的最顶层父级参数化的路径时,将调用此函数儿童关系由子关系参数化。该函数用于重新参数化任何路径或转换保存在给定路径中的任何表达式节点二等兵会员外国人.回调可能会使用按子对象重新参数化路径, 调整附件属性调整附件属性按要求。