# 57.4.

国外数据包装查询规划FDW 回调函数GetForeignRelSize,GetForeignPaths,获取国外计划,计划外地修改,GetForeignJoinPaths,GetForeignUpperPaths, 和计划直接修改必须适合 PostgreSQL 规划器的工作。

这里有一些关于他们必须做什么的说明。中的信息基础可用于减少必须从外表获取的信息量(从而降低成本)。baserel->baserestrictinfo特别有趣,因为它包含限制条件 (在哪里子句)应该用于过滤要获取的行。(FDW 本身不需要强制执行这些 quals,因为 core executor 可以检查它们。)baserel->reltarget->exprs可用于确定需要获取哪些列;但请注意,它仅列出必须由外国扫描

计划节点,而不是在 qual 评估中使用但不是由查询输出的列。FDW 计划功能可以使用各种私有字段来保存信息。通常,您存储在 FDW 私有字段中的任何内容都应该是 palloc 的,以便在计划结束时将其回收。

baserel->fdw_private是一个空白可用于 FDW 计划功能的指针,用于存储与特定外部表相关的信息。核心规划器不会触及它,只是在RelOptInfo节点被创建。这对于从GetForeignRelSizeGetForeignPaths和/或GetForeignPaths获取国外计划,从而避免重新计算。

GetForeignPaths可以通过存储私有信息来识别不同访问路径的含义fdw_private现场外来路径节点。fdw_private被宣布为列表指针,但实际上可以包含任何内容,因为核心规划器没有触及它。但是,最佳实践是使用可通过以下方式转储的表示形式节点到字符串, 用于后端提供的调试支持。

获取国外计划可以检查fdw_private所选字段外来路径节点,并且可以生成fdw_exprsfdw_private列表被放置在外国扫描计划节点,它们将在执行时可用。这两个列表都必须以如下形式表示复制对象知道如何复制。这fdw_privatelist 没有其他限制,并且不会以任何方式被核心后端解释。这fdw_exprslist,如果不是 NIL,则应该包含打算在运行时执行的表达式树。这些树将由规划器进行后处理,以使其完全可执行。

获取国外计划,一般传入的目标列表可以原样复制到计划节点中。通过的扫描子句列表包含与baserel->baserestrictinfo,但可以重新排序以获得更好的执行效率。在简单的情况下,FDW 可以剥离限制信息从节点扫描子句列表(使用extract_actual_clauses) 并将所有子句放入计划节点的 qual 列表中,这意味着执行器在运行时将检查所有子句。更复杂的 FDW 可能能够在内部检查一些子句,在这种情况下,可以从计划节点的 qual 列表中删除这些子句,这样执行者就不会浪费时间重新检查它们。

例如,FDW 可能会确定一些限制条款的形式*外国变量* = 子表达式,它确定可以在远程服务器上执行给定的本地评估值*子表达式.这种条款的实际识别应该发生在GetForeignPaths,因为它会影响路径的成本估算。路径的fdw_private字段可能包含一个指向已识别子句的指针限制信息节点。然后获取国外计划将从中删除该条款扫描子句,但添加子表达式*到fdw_exprs以确保它被按摩成可执行的形式。它可能还会将控制信息放入计划节点的fdw_private字段告诉执行函数在运行时要做什么。传输到远程服务器的查询将涉及类似在哪里 *外国变量* = 1 美元,在运行时从评估中获得的参数值fdw_exprs表达树。

从计划节点的 qual 列表中删除的任何子句都必须添加到fdw_recheck_quals或重新检查重新检查ForeignScan为了确保正确的行为在阅读已提交隔离级别。当查询中涉及的某个其他表发生并发更新时,执行程序可能需要验证元组的所有原始 quals 是否仍然满足,可能针对一组不同的参数值。使用fdw_recheck_quals通常比在内部实施检查更容易重新检查ForeignScan,但是当外部连接被下推时,这种方法是不够的,因为在这种情况下,连接元组可能有一些字段变为 NULL 而不会完全拒绝元组。

其他外国扫描外籍女佣可以填写的字段是fdw_scan_tlist,它描述了 FDW 为这个计划节点返回的元组。对于简单的外部表扫描,这可以设置为,意味着返回的元组具有为外表声明的行类型。一个非值必须是一个目标列表(列表目标入口s) 包含表示返回列的变量和/或表达式。例如,这可能用于显示 FDW 省略了一些它注意到查询不需要的列。此外,如果 FDW 可以比本地计算更便宜地计算查询使用的表达式,它可以将这些表达式添加到fdw_scan_tlist.请注意,加入计划(从创建的路径创建GetForeignJoinPaths) 必须始终提供fdw_scan_tlist描述他们将返回的列集。

FDW 应该始终构造至少一个仅依赖于表的限制子句的路径。在连接查询中,它也可能选择构建依赖于连接子句的路径,例如*外国变量* = 本地变量.此类条款不会出现在baserel->baserestrictinfo但必须在关系的连接列表中查找。使用这种子句的路径称为“参数化路径”。它必须用适当的值来标识所选连接子句中使用的其他关系参数信息;采用get_baserel_parampathinfo计算该值。在获取国外计划, 这*本地变量*join 子句的一部分将被添加到fdw_exprs, 然后在运行时该案例的工作方式与普通限制条款相同。

如果 FDW 支持远程连接,GetForeignJoinPaths应该产生外来路径s 用于潜在的远程连接,其方式与GetForeignPaths适用于基表。有关预期加入的信息可以转发给获取国外计划以上述相同的方式。然而,基本限制信息与加入关系无关;相反,特定连接的相关连接子句被传递给GetForeignJoinPaths作为一个单独的参数(额外->限制清单)。

FDW 可能还支持直接执行某些高于扫描和连接级别的计划操作,例如分组或聚合。为了提供这样的选项,FDW 应该生成路径并将它们插入到适当的上层关系.例如,代表远程聚合的路径应该插入到UPPERREL_GROUP_AGG关系,使用添加路径.该路径将在成本基础上与通过读取外部关系的简单扫描路径执行的本地聚合进行比较(注意,还必须提供这样的路径,否则在计划时会出错)。如果远程聚合路径获胜(通常情况下),它将以通常的方式转换为计划,通过调用获取国外计划.生成此类路径的推荐位置是GetForeignUpperPaths回调函数,如果查询的所有基本关系都来自同一个 FDW,则为每个上层关系(即每个扫描后/连接处理步骤)调用该回调函数。

计划外地修改以及中描述的其他回调第 57.2.4 节是围绕这样的假设设计的,即外部关系将以通常的方式被扫描,然后单个行更新将由本地驱动修改表计划节点。对于更新需要读取本地表和外部表的一般情况,这种方法是必要的。但是,如果操作可以完全由外部服务器执行,FDW 可以生成一个表示该操作的路径并将其插入到UPPERREL_FINAL上层关系,它将与修改表方法。这种方法也可以用来实现远程选择更新,而不是使用中描述的行锁定回调第 57.2.6 节.请记住,插入的路径UPPERREL_FINAL负责实施全部查询的行为。

当计划一个更新或者删除,计划外地修改计划直接修改可以查RelOptInfo外部表的结构并利用baserel->fdw_private以前由扫描计划功能创建的数据。然而,在插入目标表没有被扫描所以没有RelOptInfo为了它。这列表由返回计划外地修改有同样的限制fdw_private一个列表外国扫描计划节点,即它必须只包含以下结构复制对象知道如何复制。

插入带着关于冲突子句不支持指定冲突目标,因为远程表上的唯一约束或排除约束在本地未知。这反过来意味着冲突时做更新不支持,因为规范在那里是强制性的。