Commit a2eb9e0c authored by Tom Lane's avatar Tom Lane

Simplify list traversal logic in add_path().

Its mechanism for recovering after deleting the current list cell was
a bit klugy.  Borrow the technique used in other places.
parent 696d1f7f
...@@ -254,8 +254,9 @@ add_path(RelOptInfo *parent_rel, Path *new_path) ...@@ -254,8 +254,9 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
{ {
bool accept_new = true; /* unless we find a superior old path */ bool accept_new = true; /* unless we find a superior old path */
ListCell *insert_after = NULL; /* where to insert new item */ ListCell *insert_after = NULL; /* where to insert new item */
ListCell *p1_prev = NULL;
ListCell *p1; ListCell *p1;
ListCell *p1_prev;
ListCell *p1_next;
/* /*
* This is a convenient place to check for query cancel --- no part of the * This is a convenient place to check for query cancel --- no part of the
...@@ -267,14 +268,19 @@ add_path(RelOptInfo *parent_rel, Path *new_path) ...@@ -267,14 +268,19 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
* Loop to check proposed new path against old paths. Note it is possible * Loop to check proposed new path against old paths. Note it is possible
* for more than one old path to be tossed out because new_path dominates * for more than one old path to be tossed out because new_path dominates
* it. * it.
*
* We can't use foreach here because the loop body may delete the current
* list cell.
*/ */
p1 = list_head(parent_rel->pathlist); /* cannot use foreach here */ p1_prev = NULL;
while (p1 != NULL) for (p1 = list_head(parent_rel->pathlist); p1 != NULL; p1 = p1_next)
{ {
Path *old_path = (Path *) lfirst(p1); Path *old_path = (Path *) lfirst(p1);
bool remove_old = false; /* unless new proves superior */ bool remove_old = false; /* unless new proves superior */
int costcmp; int costcmp;
p1_next = lnext(p1);
/* /*
* As of Postgres 8.0, we use fuzzy cost comparison to avoid wasting * As of Postgres 8.0, we use fuzzy cost comparison to avoid wasting
* cycles keeping paths that are really not significantly different in * cycles keeping paths that are really not significantly different in
...@@ -343,20 +349,15 @@ add_path(RelOptInfo *parent_rel, Path *new_path) ...@@ -343,20 +349,15 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
*/ */
if (!IsA(old_path, IndexPath)) if (!IsA(old_path, IndexPath))
pfree(old_path); pfree(old_path);
/* Advance list pointer */ /* p1_prev does not advance */
if (p1_prev)
p1 = lnext(p1_prev);
else
p1 = list_head(parent_rel->pathlist);
} }
else else
{ {
/* new belongs after this old path if it has cost >= old's */ /* new belongs after this old path if it has cost >= old's */
if (costcmp >= 0) if (costcmp >= 0)
insert_after = p1; insert_after = p1;
/* Advance list pointers */ /* p1_prev advances */
p1_prev = p1; p1_prev = p1;
p1 = lnext(p1);
} }
/* /*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment