On this page
59.2. 创建自定义扫描计划
使用以下结构在完成的计划树中表示自定义扫描:
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,表示自定义扫描返回与基本关系的行类型匹配的扫描 Tuples。否则,它是描述实际扫描 Tuples 的目标列表。必须为连接提供custom_scan_tlist
,如果自定义扫描提供程序可以计算某些非 Var 表达式,则可以为扫描提供custom_scan_tlist
。核心代码将custom_relids
设置为此扫描节点处理的一组关系(范围表索引);除非此扫描将替换联接,否则它将只有一个成员。 methods
必须指向实现所需的自定义扫描方法的(通常是静态分配的)对象,下面将对其进行详细说明。
CustomScan
扫描单个关系时,scan.scanrelid
必须是要扫描的表的范围表索引。当它替换联接时,scan.scanrelid
应该为零。
计划树必须能够使用copyObject
复制,因此存储在“ custom”字段中的所有数据必须由该功能可以处理的节点组成。此外,自定义扫描提供程序不能用嵌入CustomScan
的较大结构代替该结构本身,就像CustomPath
或CustomScanState
可能的那样。
59 .2.1. 自定义扫描计划回调
Node *(*CreateCustomScanState) (CustomScan *cscan);
为此CustomScan
分配一个CustomScanState
。实际分配通常会大于普通CustomScanState
所需的分配,因为许多提供程序都希望将其嵌入为较大结构的第一个字段。返回的值必须适当地设置了节点标记和methods
,但是在此阶段,其他字段应保留为零。 ExecInitCustomScan
执行基本初始化之后,将调用BeginCustomScan
回调,以使自定义扫描提供程序有机会执行所需的其他任何操作。