Skip to content

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

61.1.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必须初始化为任何其他路径,包括此路径提供的行计数估计、开始和总成本以及排序顺序。flags是一个位掩码,它指定扫描提供程序是否可以支持某些可选功能。如果自定义路径可以支持向后扫描,则flags应包含CUSTOMPATH_SUPPORT_BACKWARD_SCAN;如果它可以支持标记和还原,则应包含CUSTOMPATH_SUPPORT_MARK_RESTORE;如果它可以执行投影,则应包含CUSTOMPATH_SUPPORT_PROJECTION。(如果未设置CUSTOMPATH_SUPPORT_PROJECTION,则只会要求扫描节点生成扫描关系的 Vars;而如果设置了该标志,则扫描节点必须能够计算这些 Vars 上的标量表达式。)可选的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;

此挂钩将针对相同的联接关系重复调用,其中内部关系和外部关系的组合不同;挂钩负责最大程度地减少重复工作。

61.1.1. 自定义扫描路径回调#

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

将自定义路径转换为已完成的计划。返回值通常将是CustomScan对象,回调必须分配并初始化该对象。有关更多详细信息,请参阅第 61.2 节

List *(*ReparameterizeCustomPathByChild) (PlannerInfo *root,
                                          List *custom_private,
                                          RelOptInfo *child_rel);

在将由给定子关系child_rel的最顶层父级参数化的路径转换为由子关系参数化时调用此回调。此回调用于重新参数化任何路径或转换保存在CustomPath的给定custom_private成员中任何表达式节点。回调可能根据需要使用reparameterize_path_by_childadjust_appendrel_attrsadjust_appendrel_attrs_multilevel