# 59.1.创建自定义扫描路径

59.1.1. 自定义扫描路径回调

自定义扫描提供程序通常会通过设置以下钩子为基本关系添加路径,该钩子在核心代码生成了它可以为该关系创建的所有访问路径后调用(收集路径除外,收集路径在此调用后创建,以便它们可以使用钩子添加的部分路径):

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;

尽管此钩子函数可用于检查、修改或删除核心系统生成的路径,但自定义扫描提供程序通常仅限于生成自定义路径对象并将其添加到雷尔使用添加路径。自定义扫描提供程序负责初始化自定义路径对象,声明如下:

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

路径必须与任何其他路径一样初始化,包括该路径提供的行计数估计、开始和总成本以及排序顺序。旗帜是一个小面具,应该包括自定义路径支持向后扫描如果自定义路径可以支持向后扫描和自定义路径\u支持\u标记\u恢复如果它能支持标记和恢复。这两种功能都是可选的。可选的自定义路径这是一份路径此自定义路径节点使用的节点;这些将被转化为计划节点由规划器管理。私人定制可用于存储自定义路径的专用数据。私有数据应以可由用户处理的形式存储节点字符串,以便尝试打印自定义路径的调试例程将按设计工作。方法必须指向(通常是静态分配的)实现所需自定义路径方法的对象,当前只有一个。

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

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);

将自定义路径转换为完工平面。返回值通常为a客户扫描对象,回调必须对其进行分配和初始化。看见第59.2节更多细节。