一个自定义扫描提供程序通常是通过设置以下钩子来为一个基础关系添加路径的,该钩子在核心代码已经生成了关系的所有访问路径(聚合和聚合合并路径除外,它们是在该调用之后进行的,以便它们可以使用钩子添加的部分路径)
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
,或者如果它们是部分路径,则使用 add_partial_path
。自定义扫描提供程序负责初始化 CustomPath
对象,该对象的声明如下
typedef struct CustomPath { Path path; uint32 flags; List *custom_paths; List *custom_restrictinfo; List *custom_private; const CustomPathMethods *methods; } CustomPath;
路径
必须初始化为任何其他路径,包括行数估值、起始和总成本,以及此路径提供的排序顺序。 标志
是一个位掩码,它指定扫描提供程序是否可以支持某些可选功能。 flags
应包括以下内容:如果自定义路径可以支持反向扫描,则为CUSTOMPATH_SUPPORT_BACKWARD_SCAN
; 如果它可以支持标记和还原,则为CUSTOMPATH_SUPPORT_MARK_RESTORE
;如果它可以执行投影,则为CUSTOMPATH_SUPPORT_PROJECTION
。(如果未设置CUSTOMPATH_SUPPORT_PROJECTION
,则仅会要求扫描节点生成被扫描关系的变量;而如果设置了该标志,扫描节点必须能够针对这些变量求值标量表达式。)可选的custom_paths
是此自定义路径节点使用的路径
节点的列表; 规划器会将它们转换为计划
节点。如下所述,也可以为连接关系创建自定义路径。 在这种情况下,应使用custom_restrictinfo
来存储一组连接子句,以应用于自定义路径替换的连接。 否则,它应该是 NIL。 custom_private
可用于存储自定义路径的私有数据。 私有数据应存储为nodeToString
可以处理的形式,这样试图打印自定义路径的调试例程才能按设计工作。 方法
必须指向实现所需自定义路径方法的(通常是静态分配的)对象,下面会详细介绍这些方法。
自定义扫描提供程序还可以提供连接路径。 正如基本关系一样,此类路径必须生成与它替换的连接通常会生成相同的输出。 为此,连接提供程序应设置以下钩子,然后在钩子函数中,为连接关系创建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;
此钩子将针对相同的连接关系重复调用,同时会采用内部和外部关系的不同组合; 钩子有责任最大程度减少重复工作。
另请注意,应用于连接的一组连接子句(作为extra->restrictlist
传递)会根据内部和外部关系的组合而有所不同。 为joinrel
生成的CustomPath
路径必须包含其使用的连接子句,规划器将用此子句将CustomPath
路径转换为计划(如果规划器将其选为joinrel
的最佳路径)。
Plan *(*PlanCustomPath) (PlannerInfo *root, RelOptInfo *rel, CustomPath *best_path, List *tlist, List *clauses, List *custom_plans);
将自定义路径转换为最终的计划。 返回值通常是CustomScan
对象,回调必须分配并初始化该对象。 有关更多详细信息,请参阅第 59.2 节。
List *(*ReparameterizeCustomPathByChild) (PlannerInfo *root, List *custom_private, RelOptInfo *child_rel);
此回调在将由给定子关系的顶级父级参数化的路径 child_rel
转换为由子关系参数化时调用。该回调用于对任何路径重新参数化或转换存储在给定的 CustomPath
的 custom_private
成员中的任何表达式节点。回调可以根据需要使用 reparameterize_path_by_child
、adjust_appendrel_attrs
或 adjust_appendrel_attrs_multilevel
。