@@ -254,8 +254,9 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
254254{
255255bool accept_new = true;/* unless we find a superior old path */
256256ListCell * insert_after = NULL ;/* where to insert new item */
257- ListCell * p1_prev = NULL ;
258257ListCell * p1 ;
258+ ListCell * p1_prev ;
259+ ListCell * p1_next ;
259260
260261/*
261262 * 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)
267268 * Loop to check proposed new path against old paths. Note it is possible
268269 * for more than one old path to be tossed out because new_path dominates
269270 * it.
271+ *
272+ * We can't use foreach here because the loop body may delete the current
273+ * list cell.
270274 */
271- p1 = list_head ( parent_rel -> pathlist ); /* cannot use foreach here */
272- while (p1 != NULL )
275+ p1_prev = NULL ;
276+ for (p1 = list_head ( parent_rel -> pathlist ); p1 != NULL ; p1 = p1_next )
273277{
274278Path * old_path = (Path * )lfirst (p1 );
275279bool remove_old = false;/* unless new proves superior */
276280int costcmp ;
277281
282+ p1_next = lnext (p1 );
283+
278284/*
279285 * As of Postgres 8.0, we use fuzzy cost comparison to avoid wasting
280286 * cycles keeping paths that are really not significantly different in
@@ -343,20 +349,15 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
343349 */
344350if (!IsA (old_path ,IndexPath ))
345351pfree (old_path );
346- /* Advance list pointer */
347- if (p1_prev )
348- p1 = lnext (p1_prev );
349- else
350- p1 = list_head (parent_rel -> pathlist );
352+ /* p1_prev does not advance */
351353}
352354else
353355{
354356/* new belongs after this old path if it has cost >= old's */
355357if (costcmp >=0 )
356358insert_after = p1 ;
357- /*Advance list pointers */
359+ /*p1_prev advances */
358360p1_prev = p1 ;
359- p1 = lnext (p1 );
360361}
361362
362363/*