59.1. 创建自定义扫描路径

自定义扫描提供程序通常会通过设置以下钩子来为基本关系添加路径,该钩子在核心代码生成其可以为该关系提供的所有访问路径后调用(Gather 路径除外,该路径在此调用之后进行,他们可以使用由钩子添加的部分路径):

typedef void (*set_rel_pathlist_hook_type) (PlannerInfo *root,
                                            RelOptInfo *rel,
                                            Index rti,
                                            RangeTblEntry *rte);
extern PGDLLIMPORT set_rel_pathlist_hook_type set_rel_pathlist_hook;

尽管此钩子函数可用于检查,修改或删除核心系统生成的路径,但是自定义扫描提供程序通常会将自身限制为生成CustomPath对象,并使用add_path将它们添加到rel。定制扫描提供程序负责初始化CustomPath对象,该对象声明如下:

typedef struct CustomPath
{
    Path      path;
    uint32    flags;
    List     *custom_paths;
    List     *custom_private;
    const CustomPathMethods *methods;
} CustomPath;

path必须像其他任何路径一样进行初始化,包括该行提供的行数估计,开始和总成本以及排序 Sequences。 flags是位掩码,如果自定义路径可以支持向后扫描,则应包含CUSTOMPATH_SUPPORT_BACKWARD_SCAN,如果它可以支持标记和还原,则应包含CUSTOMPATH_SUPPORT_MARK_RESTORE。两种功能都是可选的。可选的custom_paths是此自定义路径节点使用的Path节点的列表;这些将由计划者转换为Plan个节点。 custom_private可用于存储自定义路径的私有数据。私有数据应以nodeToString可以处理的形式存储,以便尝试打印自定义路径的调试例程将按设计工作。 methods必须指向实现所需的自定义路径方法的(通常是静态分配的)对象,目前只有一种。

定制扫描提供程序还可以提供连接路径。就像基本关系一样,这种路径必须产生与其替换的连接通常产生的输出相同的输出。为此,联接提供程序应设置以下钩子,然后在钩子函数中为联接关系创建CustomPath路径。

typedef void (*set_join_pathlist_hook_type) (PlannerInfo *root,
                                             RelOptInfo *joinrel,
                                             RelOptInfo *outerrel,
                                             RelOptInfo *innerrel,
                                             JoinType jointype,
                                             JoinPathExtraData *extra);
extern PGDLLIMPORT set_join_pathlist_hook_type set_join_pathlist_hook;

对于相同的联接关系,使用内部和外部关系的不同组合,将重复调用此钩子。钩子的责任是最大程度地减少重复工作。

59 .1.1. 自定义扫描路径回调

Plan *(*PlanCustomPath) (PlannerInfo *root,
                         RelOptInfo *rel,
                         CustomPath *best_path,
                         List *tlist,
                         List *clauses,
                         List *custom_plans);

将自定义路径转换为完成的计划。返回值通常是CustomScan对象,回调必须对其进行分配和初始化。有关更多详细信息,请参见Section 59.2