选择 打开 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1
历史版本PostgreSQL 9.1 已于 2016 年 10 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本

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

FDW 处理器函数返回一个用 palloc 分配的 FdwRoutine 结构体,其中包含指向下列回调函数的指针:

FdwPlan *
PlanForeignScan (Oid foreigntableid,
                 PlannerInfo *root,
                 RelOptInfo *baserel);

规划一个外部表上的扫描。这在查询被规划时调用。foreigntableid 是外部表的 pg_class OID。root 是规划器关于该查询的全局信息,而 baserel 是规划器关于这个表的信息。该函数必须返回一个用 palloc 分配的结构体,其中包含代价估计以及以后执行外部扫描所需的任何 FDW 私有信息。(注意,私有信息必须以 copyObject 会复制的形式表示。)

rootbaserel 中的信息可用来减少必须从外部表取回的信息量(从而降低代价估计)。baserel->baserestrictinfo 尤其值得注意,它包含可用于过滤要取回的行的限制条件(WHERE 子句)。(并不要求 FDW 强制执行这些条件,因为完成的计划无论如何都会重新检查它们。)baserel->reltargetlist 可用来确定需要取回哪些列。

除了返回代价估计之外,该函数还应在考虑限制条件所做的过滤之后,把 baserel->rows 更新为扫描预期返回的行数。baserel->rows 的初始值只是一个常量默认估计,应当尽可能替换掉它。如果该函数能计算出平均结果行宽度的更好估计,也可以选择更新 baserel->width

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

为外部表扫描打印额外的 EXPLAIN 输出。如果不需要打印任何内容,直接返回即可。否则,它应调用 ExplainPropertyText 及相关函数向 EXPLAIN 输出中添加字段。es 中的标志字段可用来确定要打印什么,而在 EXPLAIN ANALYZE 的情形下,可以检查 ForeignScanState 节点的状态以提供运行时统计信息。

void
BeginForeignScan (ForeignScanState *node,
                  int eflags);

开始执行一次外部扫描。这在执行器启动期间被调用。它应执行扫描开始前所需的任何初始化,但不要开始执行实际的扫描(那应该在第一次调用 IterateForeignScan 时进行)。ForeignScanState 节点已经创建,但其 fdw_state 字段仍为 NULL。有关被扫描表的信息可以通过 ForeignScanState 节点访问(特别是通过底层的 ForeignScan 计划节点,它包含指向由 PlanForeignScan 返回的 FdwPlan 结构的指针)。

注意,当(eflags & EXEC_FLAG_EXPLAIN_ONLY)为真时,这个函数不应执行任何外部可见的动作;它只应做使节点状态对ExplainForeignScanEndForeignScan有效所需的最少工作。

TupleTableSlot *
IterateForeignScan (ForeignScanState *node);

从外部数据源取得一行,并放入元组表槽中返回(应使用节点的 ScanTupleSlot)。如果没有更多行,则返回 NULL。元组表槽机制允许返回物理元组或虚拟元组;从性能角度看,大多数情况下后者更合适。注意,此函数在短期内存上下文中调用,该上下文会在各次调用之间重置。如果需要更长久的存储,请在 BeginForeignScan 中创建内存上下文,或者使用 es_query_cxt,它属于节点的 EState

返回的行必须与被扫描外部表的列签名匹配。如果选择优化掉不需要取回的列,则应当在这些列的位置上填入空值。

注意,PostgreSQL 的执行器并不关心返回的行是否违反外部表列上定义的 NOT NULL 约束——但规划器关心这一点,如果一个声明为不包含 NULL 值的列中出现了 NULL 值,规划器可能会错误地优化查询。当用户已声明不应出现 NULL 值却遇到了 NULL 值时,引发一个错误可能是恰当的做法(正如在数据类型不匹配的情况下你需要做的那样)。

void
ReScanForeignScan (ForeignScanState *node);

从头重新扫描。注意,扫描所依赖的参数值可能已经改变,因此新扫描不一定返回完全相同的行。

void
EndForeignScan (ForeignScanState *node);

结束扫描并释放资源。通常无需专门释放 palloc 分配的内存,但应清理打开的文件、到远程服务器的连接等资源。

FdwRoutineFdwPlan 结构类型声明在 src/include/foreign/fdwapi.h 中,更多细节请参见该文件。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。