From 0c7c4c4634c40150f180ba2b8cddc70a507f0442 Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat Date: Mon, 17 Jul 2023 10:57:30 +0530 Subject: [PATCH 3/4] Actual code to use pathnode referencing infrastructure The commit uses the infrastructure built by the previous commit to references, unreference and free paths. The code is not completely mature. There are TODOs. --- src/backend/optimizer/util/pathnode.c | 126 +++++++++++++++----------- 1 file changed, 71 insertions(+), 55 deletions(-) diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index e00eb0e19b..0d5ab390c4 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -586,12 +586,8 @@ add_path(RelOptInfo *parent_rel, Path *new_path) { parent_rel->pathlist = foreach_delete_current(parent_rel->pathlist, p1); - - /* - * Delete the data pointed-to by the deleted cell, if possible - */ - if (!IsA(old_path, IndexPath)) - pfree(old_path); + /* TODO: write a routine to unlink a path from the list node and delete the list node */ + unlink_path(&old_path); } else { @@ -614,12 +610,12 @@ add_path(RelOptInfo *parent_rel, Path *new_path) /* Accept the new path: insert it at proper place in pathlist */ parent_rel->pathlist = list_insert_nth(parent_rel->pathlist, insert_at, new_path); + new_path->ref_count++; + /* TODO: write a function to link_path in a List */ } else { - /* Reject and recycle the new path */ - if (!IsA(new_path, IndexPath)) - pfree(new_path); + free_path(new_path); } } @@ -822,7 +818,8 @@ add_partial_path(RelOptInfo *parent_rel, Path *new_path) { parent_rel->partial_pathlist = foreach_delete_current(parent_rel->partial_pathlist, p1); - pfree(old_path); + /* TODO use routine to unlink a path from the linked list */ + unlink_path(&old_path); } else { @@ -845,11 +842,13 @@ add_partial_path(RelOptInfo *parent_rel, Path *new_path) /* Accept the new path: insert it at proper place */ parent_rel->partial_pathlist = list_insert_nth(parent_rel->partial_pathlist, insert_at, new_path); + new_path->ref_count++; + /* TODO create a routine to link path in a list at a given place */ } else { /* Reject and recycle the new path */ - pfree(new_path); + free_path(new_path); } } @@ -1196,7 +1195,7 @@ create_bitmap_heap_path(PlannerInfo *root, pathnode->path.parallel_workers = parallel_degree; pathnode->path.pathkeys = NIL; /* always unordered */ - pathnode->bitmapqual = bitmapqual; + link_path(&(pathnode->bitmapqual), bitmapqual); cost_bitmap_heap_scan(&pathnode->path, root, rel, pathnode->path.param_info, @@ -1231,6 +1230,8 @@ create_bitmap_and_path(PlannerInfo *root, { Path *bitmapqual = (Path *) lfirst(lc); + /* TODO: find a better way to link a path in a linked list */ + bitmapqual->ref_count++; required_outer = bms_add_members(required_outer, PATH_REQ_OUTER(bitmapqual)); } @@ -1283,6 +1284,8 @@ create_bitmap_or_path(PlannerInfo *root, { Path *bitmapqual = (Path *) lfirst(lc); + /* TODO: find a better way to link a path in a linked list */ + bitmapqual->ref_count++; required_outer = bms_add_members(required_outer, PATH_REQ_OUTER(bitmapqual)); } @@ -1452,6 +1455,8 @@ create_append_path(PlannerInfo *root, { Path *subpath = (Path *) lfirst(l); + /* TODO: we should use the routine to link path to list */ + subpath->ref_count++; pathnode->path.parallel_safe = pathnode->path.parallel_safe && subpath->parallel_safe; @@ -1587,6 +1592,9 @@ create_merge_append_path(PlannerInfo *root, { Path *subpath = (Path *) lfirst(l); + /* TODO: use routine which links a path into a list */ + subpath->ref_count++; + pathnode->path.rows += subpath->rows; pathnode->path.parallel_safe = pathnode->path.parallel_safe && subpath->parallel_safe; @@ -1713,7 +1721,7 @@ create_material_path(RelOptInfo *rel, Path *subpath) pathnode->path.parallel_workers = subpath->parallel_workers; pathnode->path.pathkeys = subpath->pathkeys; - pathnode->subpath = subpath; + link_path(&pathnode->subpath, subpath); cost_material(&pathnode->path, subpath->startup_cost, @@ -1747,7 +1755,7 @@ create_memoize_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, pathnode->path.parallel_workers = subpath->parallel_workers; pathnode->path.pathkeys = subpath->pathkeys; - pathnode->subpath = subpath; + link_path(&pathnode->subpath, subpath); pathnode->hash_operators = hash_operators; pathnode->param_exprs = param_exprs; pathnode->singlerow = singlerow; @@ -1838,7 +1846,7 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, */ pathnode->path.pathkeys = NIL; - pathnode->subpath = subpath; + link_path(&(pathnode->subpath), subpath); pathnode->in_operators = sjinfo->semi_operators; pathnode->uniq_exprs = sjinfo->semi_rhs_exprs; @@ -1859,7 +1867,8 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, pathnode->path.total_cost = subpath->total_cost; pathnode->path.pathkeys = subpath->pathkeys; - rel->cheapest_unique_path = (Path *) pathnode; + /* TODO: Do we need to make sure that cheapest_unique_path is NULL. */ + link_path(&(rel->cheapest_unique_path), (Path *) pathnode); MemoryContextSwitchTo(oldcontext); @@ -1897,7 +1906,7 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, pathnode->path.total_cost = subpath->total_cost; pathnode->path.pathkeys = subpath->pathkeys; - rel->cheapest_unique_path = (Path *) pathnode; + link_path(&(rel->cheapest_unique_path), (Path *) pathnode); MemoryContextSwitchTo(oldcontext); @@ -1992,7 +2001,7 @@ create_unique_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, pathnode->path.total_cost = sort_path.total_cost; } - rel->cheapest_unique_path = (Path *) pathnode; + link_path(&(rel->cheapest_unique_path), (Path *) pathnode); MemoryContextSwitchTo(oldcontext); @@ -2023,7 +2032,7 @@ create_gather_merge_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, required_outer); pathnode->path.parallel_aware = false; - pathnode->subpath = subpath; + link_path(&pathnode->subpath, subpath); pathnode->num_workers = subpath->parallel_workers; pathnode->path.pathkeys = pathkeys; pathnode->path.pathtarget = target ? target : rel->reltarget; @@ -2114,7 +2123,7 @@ create_gather_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, pathnode->path.parallel_workers = 0; pathnode->path.pathkeys = NIL; /* Gather has unordered result */ - pathnode->subpath = subpath; + link_path(&(pathnode->subpath), subpath); pathnode->num_workers = subpath->parallel_workers; pathnode->single_copy = false; @@ -2157,7 +2166,7 @@ create_subqueryscan_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath, subpath->parallel_safe; pathnode->path.parallel_workers = subpath->parallel_workers; pathnode->path.pathkeys = pathkeys; - pathnode->subpath = subpath; + link_path(&pathnode->subpath, subpath); cost_subqueryscan(pathnode, root, rel, pathnode->path.param_info, trivial_pathtarget); @@ -2386,7 +2395,7 @@ create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel, pathnode->path.total_cost = total_cost; pathnode->path.pathkeys = pathkeys; - pathnode->fdw_outerpath = fdw_outerpath; + link_path(&pathnode->fdw_outerpath, fdw_outerpath); pathnode->fdw_restrictinfo = fdw_restrictinfo; pathnode->fdw_private = fdw_private; @@ -2438,7 +2447,7 @@ create_foreign_join_path(PlannerInfo *root, RelOptInfo *rel, pathnode->path.total_cost = total_cost; pathnode->path.pathkeys = pathkeys; - pathnode->fdw_outerpath = fdw_outerpath; + link_path(&pathnode->fdw_outerpath, fdw_outerpath); pathnode->fdw_restrictinfo = fdw_restrictinfo; pathnode->fdw_private = fdw_private; @@ -2485,7 +2494,7 @@ create_foreign_upper_path(PlannerInfo *root, RelOptInfo *rel, pathnode->path.total_cost = total_cost; pathnode->path.pathkeys = pathkeys; - pathnode->fdw_outerpath = fdw_outerpath; + link_path(&pathnode->fdw_outerpath, fdw_outerpath); pathnode->fdw_restrictinfo = fdw_restrictinfo; pathnode->fdw_private = fdw_private; @@ -2616,8 +2625,8 @@ create_nestloop_path(PlannerInfo *root, pathnode->jpath.path.pathkeys = pathkeys; pathnode->jpath.jointype = jointype; pathnode->jpath.inner_unique = extra->inner_unique; - pathnode->jpath.outerjoinpath = outer_path; - pathnode->jpath.innerjoinpath = inner_path; + link_path(&(pathnode->jpath.outerjoinpath), outer_path); + link_path(&(pathnode->jpath.innerjoinpath), inner_path); pathnode->jpath.joinrestrictinfo = restrict_clauses; final_cost_nestloop(root, pathnode, workspace, extra); @@ -2680,8 +2689,8 @@ create_mergejoin_path(PlannerInfo *root, pathnode->jpath.path.pathkeys = pathkeys; pathnode->jpath.jointype = jointype; pathnode->jpath.inner_unique = extra->inner_unique; - pathnode->jpath.outerjoinpath = outer_path; - pathnode->jpath.innerjoinpath = inner_path; + link_path(&(pathnode->jpath.outerjoinpath), outer_path); + link_path(&(pathnode->jpath.innerjoinpath), inner_path); pathnode->jpath.joinrestrictinfo = restrict_clauses; pathnode->path_mergeclauses = mergeclauses; pathnode->outersortkeys = outersortkeys; @@ -2757,8 +2766,8 @@ create_hashjoin_path(PlannerInfo *root, pathnode->jpath.path.pathkeys = NIL; pathnode->jpath.jointype = jointype; pathnode->jpath.inner_unique = extra->inner_unique; - pathnode->jpath.outerjoinpath = outer_path; - pathnode->jpath.innerjoinpath = inner_path; + link_path(&(pathnode->jpath.outerjoinpath), outer_path); + link_path(&(pathnode->jpath.innerjoinpath), inner_path); pathnode->jpath.joinrestrictinfo = restrict_clauses; pathnode->path_hashclauses = hashclauses; /* final_cost_hashjoin will fill in pathnode->num_batches */ @@ -2799,6 +2808,9 @@ create_projection_path(PlannerInfo *root, Assert(subpp->path.parent == rel); subpath = subpp->subpath; Assert(!IsA(subpath, ProjectionPath)); + + /* Free it if not used anywhere else. */ + unlink_path((Path **) &subpp); } pathnode->path.pathtype = T_Result; @@ -2814,7 +2826,7 @@ create_projection_path(PlannerInfo *root, /* Projection does not change the sort order */ pathnode->path.pathkeys = subpath->pathkeys; - pathnode->subpath = subpath; + link_path(&pathnode->subpath, subpath); /* * We might not need a separate Result node. If the input plan node type @@ -2933,21 +2945,21 @@ apply_projection_to_path(PlannerInfo *root, { GatherPath *gpath = (GatherPath *) path; - gpath->subpath = (Path *) - create_projection_path(root, - gpath->subpath->parent, - gpath->subpath, - target); + link_path(&gpath->subpath, + (Path *) create_projection_path(root, + gpath->subpath->parent, + gpath->subpath, + target)); } else { GatherMergePath *gmpath = (GatherMergePath *) path; - gmpath->subpath = (Path *) - create_projection_path(root, - gmpath->subpath->parent, - gmpath->subpath, - target); + link_path(&gmpath->subpath, + (Path *) create_projection_path(root, + gmpath->subpath->parent, + gmpath->subpath, + target)); } } else if (path->parallel_safe && @@ -2996,7 +3008,7 @@ create_set_projection_path(PlannerInfo *root, /* Projection does not change the sort order XXX? */ pathnode->path.pathkeys = subpath->pathkeys; - pathnode->subpath = subpath; + link_path(&pathnode->subpath, subpath); /* * Estimate number of rows produced by SRFs for each row of input; if @@ -3065,7 +3077,7 @@ create_incremental_sort_path(PlannerInfo *root, pathnode->path.parallel_workers = subpath->parallel_workers; pathnode->path.pathkeys = pathkeys; - pathnode->subpath = subpath; + link_path(&pathnode->subpath, subpath); cost_incremental_sort(&pathnode->path, root, pathkeys, presorted_keys, @@ -3112,7 +3124,7 @@ create_sort_path(PlannerInfo *root, pathnode->path.parallel_workers = subpath->parallel_workers; pathnode->path.pathkeys = pathkeys; - pathnode->subpath = subpath; + link_path(&pathnode->subpath, subpath); cost_sort(&pathnode->path, root, pathkeys, subpath->total_cost, @@ -3158,7 +3170,7 @@ create_group_path(PlannerInfo *root, /* Group doesn't change sort ordering */ pathnode->path.pathkeys = subpath->pathkeys; - pathnode->subpath = subpath; + link_path(&pathnode->subpath, subpath); pathnode->groupClause = groupClause; pathnode->qual = qual; @@ -3216,7 +3228,7 @@ create_upper_unique_path(PlannerInfo *root, /* Unique doesn't change the input ordering */ pathnode->path.pathkeys = subpath->pathkeys; - pathnode->subpath = subpath; + link_path(&pathnode->subpath, subpath); pathnode->numkeys = numCols; /* @@ -3289,7 +3301,7 @@ create_agg_path(PlannerInfo *root, else pathnode->path.pathkeys = NIL; /* output is unordered */ - pathnode->subpath = subpath; + link_path(&pathnode->subpath, subpath); pathnode->aggstrategy = aggstrategy; pathnode->aggsplit = aggsplit; @@ -3352,7 +3364,7 @@ create_groupingsets_path(PlannerInfo *root, pathnode->path.parallel_safe = rel->consider_parallel && subpath->parallel_safe; pathnode->path.parallel_workers = subpath->parallel_workers; - pathnode->subpath = subpath; + link_path(&pathnode->subpath, subpath); /* * Simplify callers by downgrading AGG_SORTED to AGG_PLAIN, and AGG_MIXED @@ -3602,7 +3614,7 @@ create_windowagg_path(PlannerInfo *root, /* WindowAgg preserves the input sort order */ pathnode->path.pathkeys = subpath->pathkeys; - pathnode->subpath = subpath; + link_path(&pathnode->subpath, subpath); pathnode->winclause = winclause; pathnode->qual = qual; pathnode->topwindow = topwindow; @@ -3671,7 +3683,7 @@ create_setop_path(PlannerInfo *root, pathnode->path.pathkeys = (strategy == SETOP_SORTED) ? subpath->pathkeys : NIL; - pathnode->subpath = subpath; + link_path(&pathnode->subpath, subpath); pathnode->cmd = cmd; pathnode->strategy = strategy; pathnode->distinctList = distinctList; @@ -3730,8 +3742,8 @@ create_recursiveunion_path(PlannerInfo *root, /* RecursiveUnion result is always unsorted */ pathnode->path.pathkeys = NIL; - pathnode->leftpath = leftpath; - pathnode->rightpath = rightpath; + link_path(&pathnode->leftpath, leftpath); + link_path(&pathnode->rightpath, rightpath); pathnode->distinctList = distinctList; pathnode->wtParam = wtParam; pathnode->numGroups = numGroups; @@ -3773,7 +3785,7 @@ create_lockrows_path(PlannerInfo *root, RelOptInfo *rel, */ pathnode->path.pathkeys = NIL; - pathnode->subpath = subpath; + link_path(&pathnode->subpath, subpath); pathnode->rowMarks = rowMarks; pathnode->epqParam = epqParam; @@ -3876,7 +3888,7 @@ create_modifytable_path(PlannerInfo *root, RelOptInfo *rel, pathnode->path.pathtarget->width = 0; } - pathnode->subpath = subpath; + link_path(&pathnode->subpath, subpath); pathnode->operation = operation; pathnode->canSetTag = canSetTag; pathnode->nominalRelation = nominalRelation; @@ -3934,7 +3946,7 @@ create_limit_path(PlannerInfo *root, RelOptInfo *rel, pathnode->path.startup_cost = subpath->startup_cost; pathnode->path.total_cost = subpath->total_cost; pathnode->path.pathkeys = subpath->pathkeys; - pathnode->subpath = subpath; + link_path(&pathnode->subpath, subpath); pathnode->limitOffset = limitOffset; pathnode->limitCount = limitCount; pathnode->limitOption = limitOption; @@ -4215,6 +4227,7 @@ do { \ (path) = reparameterize_path_by_child(root, (path), child_rel); \ if ((path) == NULL) \ return NULL; \ + link_path(&(path), (path)); \ } while(0) #define REPARAMETERIZE_CHILD_PATH_LIST(pathlist) \ @@ -4506,11 +4519,14 @@ reparameterize_pathlist_by_child(PlannerInfo *root, if (path == NULL) { + /* TODO: unlink paths in the list */ list_free(result); return NIL; } + /* TODO: need a routine to link a path into a linked list */ result = lappend(result, path); + path->ref_count++; } return result; -- 2.25.1