void
_planner_init(void)
{
prev_planner_hook = planner_hook;
planner_hook = timescaledb_planner;
prev_set_rel_pathlist_hook = set_rel_pathlist_hook;
set_rel_pathlist_hook = timescaledb_set_rel_pathlist;
prev_get_relation_info_hook = get_relation_info_hook;
get_relation_info_hook = timescaledb_get_relation_info_hook;
prev_create_upper_paths_hook = create_upper_paths_hook;
create_upper_paths_hook = timescale_create_upper_paths_hook;
}
_PG_init ---> _planner_init
_planner_init里设置了4个hook函数,取代posgresql原有的部分逻辑
这些hook都是postresql里的全局变量(函数指针),如果被赋值,则使用该hook指向的函数。
1. planner_hook: 生成计划数时hit
timescaledb_planner取代standard_planner
PlannedStmt *
planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
{
PlannedStmt *result;
if (planner_hook)
result = (*planner_hook) (parse, cursorOptions, boundParams);
else
result = standard_planner(parse, cursorOptions, boundParams);
return result;
}
实际上,ttimescaledb_planner内部实现也是先执行 standard_planner, 得到plan, 再按照自己逻辑对plan做处理的。
2. set_rel_pathlist_hook: 构造访问路径时hit
timescaledb_set_rel_pathlist 在原来构造路径的基础上做一次编辑修改
/*
* Allow a plugin to editorialize on the set of Paths for this base
* relation. It could add new paths (such as CustomPaths) by calling
* add_path(), or delete or modify paths added by the core code.
*/
if (set_rel_pathlist_hook)
(*set_rel_pathlist_hook) (root, rel, rti, rte);
3. get_relation_info_hook: 获取表对象信息时hit
timescaledb_get_relation_info_hook 编辑修改获取的表对象信息(大小,索引等)
/*
* Allow a plugin to editorialize on the info we obtained from the
* catalogs. Actions might include altering the assumed relation size,
* removing an index, or adding a hypothetical index to the indexlist.
*/
if (get_relation_info_hook)
(*get_relation_info_hook) (root, relationObjectId, inhparent, rel);
4. create_upper_paths_hook: 创建一些路径(分组聚合,窗口,排序等)时hit
timescale_create_upper_paths_hook 编辑修改这些路径
In grouping_planner function
/* Let extensions possibly add some more paths */
if (create_upper_paths_hook)
(*create_upper_paths_hook) (root, UPPERREL_FINAL,
current_rel, final_rel);
In create_grouping_paths function
/* Let extensions possibly add some more paths */
if (create_upper_paths_hook)
(*create_upper_paths_hook) (root, UPPERREL_GROUP_AGG,
input_rel, grouped_rel);
In create_window_paths function
/* Let extensions possibly add some more paths */
if (create_upper_paths_hook)
(*create_upper_paths_hook) (root, UPPERREL_WINDOW,
input_rel, window_rel);
In create_distinct_paths function
/* Let extensions possibly add some more paths */
if (create_upper_paths_hook)
(*create_upper_paths_hook) (root, UPPERREL_DISTINCT,
input_rel, distinct_rel);
In create_ordered_paths function
/* Let extensions possibly add some more paths */
if (create_upper_paths_hook)
(*create_upper_paths_hook) (root, UPPERREL_ORDERED,
input_rel, ordered_rel);