fix_add_path.patch
application/octet-stream
Filename: fix_add_path.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/optimizer/plan/planner.c | 3 | 3 |
| src/backend/optimizer/util/pathnode.c | 14 | 3 |
| src/include/optimizer/pathnode.h | 2 | 0 |
commit f9c753286554cc2fb6e96dcfe6641247216d7107
Author: Jeevan Chalke <jeevan.chalke@enterprisedb.com>
Date: Tue Jul 11 14:39:58 2023 +0530
Conditionally free the path in add_path()
The passed-in path or already added path in the rel is freed if we
reject it or are not needed anymore. However, that path may have some
references elsewhere, and thus it is not safe to always free. We have
that case when add_path() is called to add an ordered path that is
already sorted but got rejected. To avoid this, add the free_path
argument to add_path() which is used for conditionally freeing the
path.
To avoid API breakage, add a wrapper instead, named add_path_extended.
Reported by me, fix suggested by Alvaro Herrera.
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 0e12fde..d0d7c3e 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -5162,7 +5162,7 @@ create_ordered_paths(PlannerInfo *root,
sorted_path = apply_projection_to_path(root, ordered_rel,
sorted_path, target);
- add_path(ordered_rel, sorted_path);
+ add_path_extended(ordered_rel, sorted_path, false);
}
/*
@@ -5212,7 +5212,7 @@ create_ordered_paths(PlannerInfo *root,
path = apply_projection_to_path(root, ordered_rel,
path, target);
- add_path(ordered_rel, path);
+ add_path_extended(ordered_rel, path, false);
}
/*
@@ -5271,7 +5271,7 @@ create_ordered_paths(PlannerInfo *root,
sorted_path = apply_projection_to_path(root, ordered_rel,
sorted_path, target);
- add_path(ordered_rel, sorted_path);
+ add_path_extended(ordered_rel, sorted_path, false);
}
}
}
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 5f55968..262084a 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -362,6 +362,16 @@ set_cheapest(RelOptInfo *parent_rel)
/*
* add_path
+ * See add_path_extended()
+ */
+void
+add_path(RelOptInfo *parent_rel, Path *new_path)
+{
+ add_path_extended(parent_rel, new_path, true);
+}
+
+/*
+ * add_path_extended
* Consider a potential implementation path for the specified parent rel,
* and add it to the rel's pathlist if it is worthy of consideration.
* A path is worthy if it has a better sort order (better pathkeys) or
@@ -415,11 +425,12 @@ set_cheapest(RelOptInfo *parent_rel)
*
* 'parent_rel' is the relation entry to which the path corresponds.
* 'new_path' is a potential path for parent_rel.
+ * 'free_path' if true, pfree() the path if rejected or not needed.
*
* Returns nothing, but modifies parent_rel->pathlist.
*/
void
-add_path(RelOptInfo *parent_rel, Path *new_path)
+add_path_extended(RelOptInfo *parent_rel, Path *new_path, bool free_path)
{
bool accept_new = true; /* unless we find a superior old path */
int insert_at = 0; /* where to insert new item */
@@ -590,7 +601,7 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
/*
* Delete the data pointed-to by the deleted cell, if possible
*/
- if (!IsA(old_path, IndexPath))
+ if (free_path && !IsA(old_path, IndexPath))
pfree(old_path);
}
else
@@ -618,7 +629,7 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
else
{
/* Reject and recycle the new path */
- if (!IsA(new_path, IndexPath))
+ if (free_path && !IsA(new_path, IndexPath))
pfree(new_path);
}
}
diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h
index 001e75b..567e70e 100644
--- a/src/include/optimizer/pathnode.h
+++ b/src/include/optimizer/pathnode.h
@@ -27,6 +27,8 @@ extern int compare_fractional_path_costs(Path *path1, Path *path2,
double fraction);
extern void set_cheapest(RelOptInfo *parent_rel);
extern void add_path(RelOptInfo *parent_rel, Path *new_path);
+extern void add_path_extended(RelOptInfo *parent_rel, Path *new_path,
+ bool free_path);
extern bool add_path_precheck(RelOptInfo *parent_rel,
Cost startup_cost, Cost total_cost,
List *pathkeys, Relids required_outer);