@@ -254,8 +254,9 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
254
254
{
255
255
bool accept_new = true; /* unless we find a superior old path */
256
256
ListCell * insert_after = NULL ; /* where to insert new item */
257
- ListCell * p1_prev = NULL ;
258
257
ListCell * p1 ;
258
+ ListCell * p1_prev ;
259
+ ListCell * p1_next ;
259
260
260
261
/*
261
262
* 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
268
* Loop to check proposed new path against old paths. Note it is possible
268
269
* for more than one old path to be tossed out because new_path dominates
269
270
* it.
271
+ *
272
+ * We can't use foreach here because the loop body may delete the current
273
+ * list cell.
270
274
*/
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 )
273
277
{
274
278
Path * old_path = (Path * ) lfirst (p1 );
275
279
bool remove_old = false; /* unless new proves superior */
276
280
int costcmp ;
277
281
282
+ p1_next = lnext (p1 );
283
+
278
284
/*
279
285
* As of Postgres 8.0, we use fuzzy cost comparison to avoid wasting
280
286
* cycles keeping paths that are really not significantly different in
@@ -343,20 +349,15 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
343
349
*/
344
350
if (!IsA (old_path , IndexPath ))
345
351
pfree (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 */
351
353
}
352
354
else
353
355
{
354
356
/* new belongs after this old path if it has cost >= old's */
355
357
if (costcmp >= 0 )
356
358
insert_after = p1 ;
357
- /* Advance list pointers */
359
+ /* p1_prev advances */
358
360
p1_prev = p1 ;
359
- p1 = lnext (p1 );
360
361
}
361
362
362
363
/*
0 commit comments