在完成的计划树中,自定义扫描使用下述结构表示:
typedef struct CustomScan
{
Scan scan;
uint32 flags;
List *custom_plans;
List *custom_exprs;
List *custom_private;
List *custom_scan_tlist;
Bitmapset *custom_relids;
const CustomScanMethods *methods;
} CustomScan;
scan 必须像其他任何扫描一样完成初始化,包括估计代价、目标列表、限定条件等。flags 是一个位掩码,其含义与 CustomPath 中相同。custom_plans 可用于存储子 Plan 节点。custom_exprs 应当用于存储那些需要由 setrefs.c 和 subselect.c 修正的表达式树,而 custom_private 则应用于存放仅供自定义扫描提供者自身使用的其他私有数据。扫描基本关系时,custom_scan_tlist 可以为 NIL,表示该自定义扫描返回的扫描元组与该基本关系的行类型一致。否则,它就是描述实际扫描元组的目标列表。对于连接,必须提供 custom_scan_tlist;如果自定义扫描提供者能够计算某些非 Var 表达式,则在扫描场景下也可以提供该字段。custom_relids 由核心代码设置为该扫描节点所处理关系(范围表索引)的集合;除非该扫描是在替代一个连接,否则它将只有一个成员。methods 必须指向一个实现了所需自定义扫描方法的对象(通常是静态分配的),下文会进一步说明。
当 CustomScan 扫描单个关系时,scan.scanrelid 必须是待扫描表的范围表索引。当它替代的是一个连接时,scan.scanrelid 应为零。
计划树必须能够通过 copyObject 复制,因此存放在 “custom” 字段中的所有数据都必须由该函数能够处理的节点组成。此外,自定义扫描提供者不能像对 CustomPath 或 CustomScanState 那样,用一个包含 CustomScan 的更大结构替代该结构本身。
Node *(*CreateCustomScanState) (CustomScan *cscan);
为该 CustomScan 分配一个 CustomScanState。实际分配的空间往往会比普通 CustomScanState 所需的更大,因为很多提供者都希望把它作为第一个字段嵌入到一个更大的结构中。返回的值必须适当地设置节点标签和 methods,但在这个阶段,其他字段应当保留为零;待 ExecInitCustomScan 完成基本初始化之后,将调用 BeginCustomScan 回调,让自定义扫描提供者有机会执行其他所需操作。
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。