Postgresql 中文操作指南

61.2. Creating Custom Scan Plans #

定制扫描在完成的计划树中使用以下结构表示:

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 可用于存储子节点 Plancustom_exprs 应用于存储表达式树,这些表达式树需要由 setrefs.csubselect.c 修复,而 custom_private 应用于存储其他私有数据,这些数据仅由自定义扫描提供程序本身使用。扫描基本关系时,custom_scan_tlist 可以是 NIL,表示自定义扫描返回与基本关系行类型匹配的扫描元组。否则,它是一个描述实际扫描元组的目标列表。 custom_scan_tlist 必须用于联接,并且可以用于扫描,如果自定义扫描提供程序可以计算一些非 Var 表达式。 custom_relids 由核心代码设置为此扫描节点处理的关系集(范围表索引);除非此扫描替换联接,否则它只有一个成员。 methods 必须指向一个(通常是静态分配的)对象,该对象实现所需的自定义扫描方法,这些方法将在下面进一步详细介绍。

CustomScan 扫描单个关系时,scan.scanrelid 必须是要扫描的表的范围表索引。当它替换联接时,scan.scanrelid 应为零。

计划树必须能够使用 copyObject 复制,因此存储在“自定义”字段中的所有数据都必须由该函数可以处理的节点组成。此外,自定义扫描提供程序不能为结构本身替换一个包含 CustomScan 的更大的结构,而对于 CustomPathCustomScanState 来说是可能的。

61.2.1. Custom Scan Plan Callbacks #

Node *(*CreateCustomScanState) (CustomScan *cscan);

为此 CustomScan 分配一个 CustomScanState。实际分配通常会比普通 CustomScanState 所需的更大,因为许多提供程序希望将其嵌入到更大结构的第一个字段中。返回的值必须有适当设置的节点标记和 methods,但其他字段在此阶段应保留为零;在 ExecInitCustomScan 执行基本初始化之后,将调用 BeginCustomScan 回调以向自定义扫描提供程序提供一个机会,让它完成任何其他需要的事情。