diff options
Diffstat (limited to 'src/backend/optimizer')
20 files changed, 145 insertions, 205 deletions
diff --git a/src/backend/optimizer/geqo/geqo_eval.c b/src/backend/optimizer/geqo/geqo_eval.c index 6c69c1c1478..8a44ac8530d 100644 --- a/src/backend/optimizer/geqo/geqo_eval.c +++ b/src/backend/optimizer/geqo/geqo_eval.c @@ -238,11 +238,9 @@ static List * merge_clump(PlannerInfo *root, List *clumps, Clump *new_clump, int num_gene, bool force) { - ListCell *prev; ListCell *lc; /* Look for a clump that new_clump can join to */ - prev = NULL; foreach(lc, clumps) { Clump *old_clump = (Clump *) lfirst(lc); @@ -286,7 +284,7 @@ merge_clump(PlannerInfo *root, List *clumps, Clump *new_clump, int num_gene, pfree(new_clump); /* Remove old_clump from list */ - clumps = list_delete_cell(clumps, lc, prev); + clumps = foreach_delete_current(clumps, lc); /* * Recursively try to merge the enlarged old_clump with @@ -296,7 +294,6 @@ merge_clump(PlannerInfo *root, List *clumps, Clump *new_clump, int num_gene, return merge_clump(root, clumps, old_clump, num_gene, force); } } - prev = lc; } /* @@ -315,7 +312,7 @@ merge_clump(PlannerInfo *root, List *clumps, Clump *new_clump, int num_gene, /* Else search for the place to insert it */ for (;;) { - ListCell *nxt = lnext(lc); + ListCell *nxt = lnext(clumps, lc); if (nxt == NULL || new_clump->size > ((Clump *) lfirst(nxt))->size) break; /* it belongs after 'lc', before 'nxt' */ diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index b7723481b0e..e9ee32b7f43 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -3204,7 +3204,7 @@ compare_tlist_datatypes(List *tlist, List *colTypes, elog(ERROR, "wrong number of tlist entries"); if (exprType((Node *) tle->expr) != lfirst_oid(colType)) safetyInfo->unsafeColumns[tle->resno] = true; - colType = lnext(colType); + colType = lnext(colTypes, colType); } if (colType != NULL) elog(ERROR, "wrong number of tlist entries"); @@ -3761,7 +3761,7 @@ print_restrictclauses(PlannerInfo *root, List *clauses) RestrictInfo *c = lfirst(l); print_expr((Node *) c->clause, root->parse->rtable); - if (lnext(l)) + if (lnext(clauses, l)) printf(", "); } } diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index a2a9b1f7be6..3a9a994733b 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -1838,7 +1838,7 @@ append_nonpartial_cost(List *subpaths, int numpaths, int parallel_workers) * For each of the remaining subpaths, add its cost to the array element * with minimum cost. */ - for_each_cell(l, cell) + for_each_cell(l, subpaths, cell) { Path *subpath = (Path *) lfirst(l); int i; @@ -4724,8 +4724,6 @@ get_foreign_key_join_selectivity(PlannerInfo *root, bool ref_is_outer; List *removedlist; ListCell *cell; - ListCell *prev; - ListCell *next; /* * This FK is not relevant unless it connects a baserel on one side of @@ -4766,14 +4764,12 @@ get_foreign_key_join_selectivity(PlannerInfo *root, worklist = list_copy(worklist); removedlist = NIL; - prev = NULL; - for (cell = list_head(worklist); cell; cell = next) + foreach(cell, worklist) { RestrictInfo *rinfo = (RestrictInfo *) lfirst(cell); bool remove_it = false; int i; - next = lnext(cell); /* Drop this clause if it matches any column of the FK */ for (i = 0; i < fkinfo->nkeys; i++) { @@ -4813,11 +4809,9 @@ get_foreign_key_join_selectivity(PlannerInfo *root, } if (remove_it) { - worklist = list_delete_cell(worklist, cell, prev); + worklist = foreach_delete_current(worklist, cell); removedlist = lappend(removedlist, rinfo); } - else - prev = cell; } /* diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c index 688d9b07075..78d076b13cd 100644 --- a/src/backend/optimizer/path/equivclass.c +++ b/src/backend/optimizer/path/equivclass.c @@ -1573,8 +1573,6 @@ reconsider_outer_join_clauses(PlannerInfo *root) { bool found; ListCell *cell; - ListCell *prev; - ListCell *next; /* Outer loop repeats until we find no more deductions */ do @@ -1582,72 +1580,60 @@ reconsider_outer_join_clauses(PlannerInfo *root) found = false; /* Process the LEFT JOIN clauses */ - prev = NULL; - for (cell = list_head(root->left_join_clauses); cell; cell = next) + foreach(cell, root->left_join_clauses) { RestrictInfo *rinfo = (RestrictInfo *) lfirst(cell); - next = lnext(cell); if (reconsider_outer_join_clause(root, rinfo, true)) { found = true; /* remove it from the list */ root->left_join_clauses = - list_delete_cell(root->left_join_clauses, cell, prev); + foreach_delete_current(root->left_join_clauses, cell); /* we throw it back anyway (see notes above) */ /* but the thrown-back clause has no extra selectivity */ rinfo->norm_selec = 2.0; rinfo->outer_selec = 1.0; distribute_restrictinfo_to_rels(root, rinfo); } - else - prev = cell; } /* Process the RIGHT JOIN clauses */ - prev = NULL; - for (cell = list_head(root->right_join_clauses); cell; cell = next) + foreach(cell, root->right_join_clauses) { RestrictInfo *rinfo = (RestrictInfo *) lfirst(cell); - next = lnext(cell); if (reconsider_outer_join_clause(root, rinfo, false)) { found = true; /* remove it from the list */ root->right_join_clauses = - list_delete_cell(root->right_join_clauses, cell, prev); + foreach_delete_current(root->right_join_clauses, cell); /* we throw it back anyway (see notes above) */ /* but the thrown-back clause has no extra selectivity */ rinfo->norm_selec = 2.0; rinfo->outer_selec = 1.0; distribute_restrictinfo_to_rels(root, rinfo); } - else - prev = cell; } /* Process the FULL JOIN clauses */ - prev = NULL; - for (cell = list_head(root->full_join_clauses); cell; cell = next) + foreach(cell, root->full_join_clauses) { RestrictInfo *rinfo = (RestrictInfo *) lfirst(cell); - next = lnext(cell); if (reconsider_full_join_clause(root, rinfo)) { found = true; /* remove it from the list */ root->full_join_clauses = - list_delete_cell(root->full_join_clauses, cell, prev); + foreach_delete_current(root->full_join_clauses, cell); /* we throw it back anyway (see notes above) */ /* but the thrown-back clause has no extra selectivity */ rinfo->norm_selec = 2.0; rinfo->outer_selec = 1.0; distribute_restrictinfo_to_rels(root, rinfo); } - else - prev = cell; } } while (found); @@ -2123,7 +2109,7 @@ add_child_rel_equivalences(PlannerInfo *root, foreach(lc1, root->eq_classes) { EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1); - ListCell *lc2; + int num_members; /* * If this EC contains a volatile expression, then generating child @@ -2140,9 +2126,15 @@ add_child_rel_equivalences(PlannerInfo *root, if (!bms_is_subset(child_rel->top_parent_relids, cur_ec->ec_relids)) continue; - foreach(lc2, cur_ec->ec_members) + /* + * We don't use foreach() here because there's no point in scanning + * newly-added child members, so we can stop after the last + * pre-existing EC member. + */ + num_members = list_length(cur_ec->ec_members); + for (int pos = 0; pos < num_members; pos++) { - EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2); + EquivalenceMember *cur_em = (EquivalenceMember *) list_nth(cur_ec->ec_members, pos); if (cur_em->em_is_const) continue; /* ignore consts here */ diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index c208e9bfb0b..5f339fdfde7 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -520,7 +520,7 @@ consider_index_join_outer_rels(PlannerInfo *root, RelOptInfo *rel, IndexClause *iclause = (IndexClause *) lfirst(lc); Relids clause_relids = iclause->rinfo->clause_relids; EquivalenceClass *parent_ec = iclause->rinfo->parent_ec; - ListCell *lc2; + int num_considered_relids; /* If we already tried its relids set, no need to do so again */ if (bms_equal_any(clause_relids, *considered_relids)) @@ -533,15 +533,16 @@ consider_index_join_outer_rels(PlannerInfo *root, RelOptInfo *rel, * exponential growth of planning time when there are many clauses, * limit the number of relid sets accepted to 10 * considered_clauses. * - * Note: get_join_index_paths adds entries to *considered_relids, but - * it prepends them to the list, so that we won't visit new entries - * during the inner foreach loop. No real harm would be done if we - * did, since the subset check would reject them; but it would waste - * some cycles. + * Note: get_join_index_paths appends entries to *considered_relids, + * but we do not need to visit such newly-added entries within this + * loop, so we don't use foreach() here. No real harm would be done + * if we did visit them, since the subset check would reject them; but + * it would waste some cycles. */ - foreach(lc2, *considered_relids) + num_considered_relids = list_length(*considered_relids); + for (int pos = 0; pos < num_considered_relids; pos++) { - Relids oldrelids = (Relids) lfirst(lc2); + Relids oldrelids = (Relids) list_nth(*considered_relids, pos); /* * If either is a subset of the other, no new set is possible. @@ -671,10 +672,9 @@ get_join_index_paths(PlannerInfo *root, RelOptInfo *rel, get_index_paths(root, rel, index, &clauseset, bitindexpaths); /* - * Remember we considered paths for this set of relids. We use lcons not - * lappend to avoid confusing the loop in consider_index_join_outer_rels. + * Remember we considered paths for this set of relids. */ - *considered_relids = lcons(relids, *considered_relids); + *considered_relids = lappend(*considered_relids, relids); } /* @@ -1502,7 +1502,6 @@ choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths) Cost costsofar; List *qualsofar; Bitmapset *clauseidsofar; - ListCell *lastcell; pathinfo = pathinfoarray[i]; paths = list_make1(pathinfo->path); @@ -1510,7 +1509,6 @@ choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths) qualsofar = list_concat(list_copy(pathinfo->quals), list_copy(pathinfo->preds)); clauseidsofar = bms_copy(pathinfo->clauseids); - lastcell = list_head(paths); /* for quick deletions */ for (j = i + 1; j < npaths; j++) { @@ -1551,14 +1549,12 @@ choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths) list_copy(pathinfo->preds)); clauseidsofar = bms_add_members(clauseidsofar, pathinfo->clauseids); - lastcell = lnext(lastcell); } else { /* reject new path, remove it from paths list */ - paths = list_delete_cell(paths, lnext(lastcell), lastcell); + paths = list_truncate(paths, list_length(paths) - 1); } - Assert(lnext(lastcell) == NULL); } /* Keep the cheapest AND-group (or singleton) */ @@ -2970,10 +2966,6 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo, List *new_ops; List *var_args; List *non_var_args; - ListCell *vargs_cell; - ListCell *nargs_cell; - ListCell *opnos_cell; - ListCell *collids_cell; iclause->rinfo = rinfo; iclause->indexcol = indexcol; @@ -3010,18 +3002,14 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo, * indexed relation. */ matching_cols = 1; - vargs_cell = lnext(list_head(var_args)); - nargs_cell = lnext(list_head(non_var_args)); - opnos_cell = lnext(list_head(clause->opnos)); - collids_cell = lnext(list_head(clause->inputcollids)); - while (vargs_cell != NULL) + while (matching_cols < list_length(var_args)) { - Node *varop = (Node *) lfirst(vargs_cell); - Node *constop = (Node *) lfirst(nargs_cell); + Node *varop = (Node *) list_nth(var_args, matching_cols); + Node *constop = (Node *) list_nth(non_var_args, matching_cols); int i; - expr_op = lfirst_oid(opnos_cell); + expr_op = list_nth_oid(clause->opnos, matching_cols); if (!var_on_left) { /* indexkey is on right, so commute the operator */ @@ -3043,7 +3031,8 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo, get_op_opfamily_strategy(expr_op, index->opfamily[i]) == op_strategy && IndexCollMatchesExprColl(index->indexcollations[i], - lfirst_oid(collids_cell))) + list_nth_oid(clause->inputcollids, + matching_cols))) break; } if (i >= index->nkeycolumns) @@ -3064,10 +3053,6 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo, /* This column matches, keep scanning */ matching_cols++; - vargs_cell = lnext(vargs_cell); - nargs_cell = lnext(nargs_cell); - opnos_cell = lnext(opnos_cell); - collids_cell = lnext(collids_cell); } /* Result is non-lossy if all columns are usable as index quals */ @@ -3866,7 +3851,7 @@ match_index_to_operand(Node *operand, { if (indexpr_item == NULL) elog(ERROR, "wrong number of index expressions"); - indexpr_item = lnext(indexpr_item); + indexpr_item = lnext(index->indexprs, indexpr_item); } } if (indexpr_item == NULL) diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index 43c3b7ea489..6a480ab7644 100644 --- a/src/backend/optimizer/path/joinrels.c +++ b/src/backend/optimizer/path/joinrels.c @@ -26,10 +26,11 @@ static void make_rels_by_clause_joins(PlannerInfo *root, RelOptInfo *old_rel, + List *other_rels_list, ListCell *other_rels); static void make_rels_by_clauseless_joins(PlannerInfo *root, RelOptInfo *old_rel, - ListCell *other_rels); + List *other_rels); static bool has_join_restriction(PlannerInfo *root, RelOptInfo *rel); static bool has_legal_joinclause(PlannerInfo *root, RelOptInfo *rel); static bool restriction_is_constant_false(List *restrictlist, @@ -101,15 +102,23 @@ join_search_one_level(PlannerInfo *root, int level) * to each initial rel they don't already include but have a join * clause or restriction with. */ + List *other_rels_list; ListCell *other_rels; if (level == 2) /* consider remaining initial rels */ - other_rels = lnext(r); + { + other_rels_list = joinrels[level - 1]; + other_rels = lnext(other_rels_list, r); + } else /* consider all initial rels */ - other_rels = list_head(joinrels[1]); + { + other_rels_list = joinrels[1]; + other_rels = list_head(other_rels_list); + } make_rels_by_clause_joins(root, old_rel, + other_rels_list, other_rels); } else @@ -128,7 +137,7 @@ join_search_one_level(PlannerInfo *root, int level) */ make_rels_by_clauseless_joins(root, old_rel, - list_head(joinrels[1])); + joinrels[1]); } } @@ -154,6 +163,7 @@ join_search_one_level(PlannerInfo *root, int level) foreach(r, joinrels[k]) { RelOptInfo *old_rel = (RelOptInfo *) lfirst(r); + List *other_rels_list; ListCell *other_rels; ListCell *r2; @@ -167,11 +177,18 @@ join_search_one_level(PlannerInfo *root, int level) continue; if (k == other_level) - other_rels = lnext(r); /* only consider remaining rels */ + { + /* only consider remaining rels */ + other_rels_list = joinrels[k]; + other_rels = lnext(other_rels_list, r); + } else - other_rels = list_head(joinrels[other_level]); + { + other_rels_list = joinrels[other_level]; + other_rels = list_head(other_rels_list); + } - for_each_cell(r2, other_rels) + for_each_cell(r2, other_rels_list, other_rels) { RelOptInfo *new_rel = (RelOptInfo *) lfirst(r2); @@ -223,7 +240,7 @@ join_search_one_level(PlannerInfo *root, int level) make_rels_by_clauseless_joins(root, old_rel, - list_head(joinrels[1])); + joinrels[1]); } /*---------- @@ -265,8 +282,9 @@ join_search_one_level(PlannerInfo *root, int level) * automatically ensures that each new joinrel is only added to the list once. * * 'old_rel' is the relation entry for the relation to be joined - * 'other_rels': the first cell in a linked list containing the other + * 'other_rels_list': a list containing the other * rels to be considered for joining + * 'other_rels': the first cell to be considered * * Currently, this is only used with initial rels in other_rels, but it * will work for joining to joinrels too. @@ -274,11 +292,12 @@ join_search_one_level(PlannerInfo *root, int level) static void make_rels_by_clause_joins(PlannerInfo *root, RelOptInfo *old_rel, + List *other_rels_list, ListCell *other_rels) { ListCell *l; - for_each_cell(l, other_rels) + for_each_cell(l, other_rels_list, other_rels) { RelOptInfo *other_rel = (RelOptInfo *) lfirst(l); @@ -299,8 +318,7 @@ make_rels_by_clause_joins(PlannerInfo *root, * The join rels are returned in root->join_rel_level[join_cur_level]. * * 'old_rel' is the relation entry for the relation to be joined - * 'other_rels': the first cell of a linked list containing the - * other rels to be considered for joining + * 'other_rels': a list containing the other rels to be considered for joining * * Currently, this is only used with initial rels in other_rels, but it would * work for joining to joinrels too. @@ -308,11 +326,11 @@ make_rels_by_clause_joins(PlannerInfo *root, static void make_rels_by_clauseless_joins(PlannerInfo *root, RelOptInfo *old_rel, - ListCell *other_rels) + List *other_rels) { ListCell *l; - for_each_cell(l, other_rels) + foreach(l, other_rels) { RelOptInfo *other_rel = (RelOptInfo *) lfirst(l); diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c index 08b50616128..202a4b9db82 100644 --- a/src/backend/optimizer/path/pathkeys.c +++ b/src/backend/optimizer/path/pathkeys.c @@ -1529,7 +1529,7 @@ make_inner_pathkeys_for_merge(PlannerInfo *root, if (!lop) elog(ERROR, "too few pathkeys for mergeclauses"); opathkey = (PathKey *) lfirst(lop); - lop = lnext(lop); + lop = lnext(outer_pathkeys, lop); lastoeclass = opathkey->pk_eclass; if (oeclass != lastoeclass) elog(ERROR, "outer pathkeys do not match mergeclause"); @@ -1609,7 +1609,7 @@ trim_mergeclauses_for_inner_pathkeys(PlannerInfo *root, lip = list_head(pathkeys); pathkey = (PathKey *) lfirst(lip); pathkey_ec = pathkey->pk_eclass; - lip = lnext(lip); + lip = lnext(pathkeys, lip); matched_pathkey = false; /* Scan mergeclauses to see how many we can use */ @@ -1636,7 +1636,7 @@ trim_mergeclauses_for_inner_pathkeys(PlannerInfo *root, break; pathkey = (PathKey *) lfirst(lip); pathkey_ec = pathkey->pk_eclass; - lip = lnext(lip); + lip = lnext(pathkeys, lip); matched_pathkey = false; } diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c index 32695db367b..d19ff4138e5 100644 --- a/src/backend/optimizer/plan/analyzejoins.c +++ b/src/backend/optimizer/plan/analyzejoins.c @@ -96,17 +96,16 @@ restart: /* * We can delete this SpecialJoinInfo from the list too, since it's no - * longer of interest. + * longer of interest. (Since we'll restart the foreach loop + * immediately, we don't bother with foreach_delete_current.) */ - root->join_info_list = list_delete_ptr(root->join_info_list, sjinfo); + root->join_info_list = list_delete_cell(root->join_info_list, lc); /* * Restart the scan. This is necessary to ensure we find all * removable joins independently of ordering of the join_info_list * (note that removal of attr_needed bits may make a join appear - * removable that did not before). Also, since we just deleted the - * current list cell, we'd have to have some kluge to continue the - * list scan anyway. + * removable that did not before). */ goto restart; } @@ -316,7 +315,6 @@ remove_rel_from_query(PlannerInfo *root, int relid, Relids joinrelids) List *joininfos; Index rti; ListCell *l; - ListCell *nextl; /* * Mark the rel as "dead" to show it is no longer part of the join tree. @@ -383,16 +381,15 @@ remove_rel_from_query(PlannerInfo *root, int relid, Relids joinrelids) * remove or just update the PHV. There is no corresponding test in * join_is_removable because it doesn't need to distinguish those cases. */ - for (l = list_head(root->placeholder_list); l != NULL; l = nextl) + foreach(l, root->placeholder_list) { PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(l); - nextl = lnext(l); Assert(!bms_is_member(relid, phinfo->ph_lateral)); if (bms_is_subset(phinfo->ph_needed, joinrelids) && bms_is_member(relid, phinfo->ph_eval_at)) - root->placeholder_list = list_delete_ptr(root->placeholder_list, - phinfo); + root->placeholder_list = foreach_delete_current(root->placeholder_list, + l); else { phinfo->ph_eval_at = bms_del_member(phinfo->ph_eval_at, relid); @@ -511,13 +508,11 @@ void reduce_unique_semijoins(PlannerInfo *root) { ListCell *lc; - ListCell *next; /* - * Scan the join_info_list to find semijoins. We can't use foreach - * because we may delete the current cell. + * Scan the join_info_list to find semijoins. */ - for (lc = list_head(root->join_info_list); lc != NULL; lc = next) + foreach(lc, root->join_info_list) { SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc); int innerrelid; @@ -525,8 +520,6 @@ reduce_unique_semijoins(PlannerInfo *root) Relids joinrelids; List *restrictlist; - next = lnext(lc); - /* * Must be a non-delaying semijoin to a single baserel, else we aren't * going to be able to do anything with it. (It's probably not @@ -572,7 +565,7 @@ reduce_unique_semijoins(PlannerInfo *root) continue; /* OK, remove the SpecialJoinInfo from the list. */ - root->join_info_list = list_delete_ptr(root->join_info_list, sjinfo); + root->join_info_list = foreach_delete_current(root->join_info_list, lc); } } @@ -897,7 +890,7 @@ query_is_distinct_for(Query *query, List *colnos, List *opids) /* non-resjunk columns should have grouping clauses */ Assert(lg != NULL); sgc = (SortGroupClause *) lfirst(lg); - lg = lnext(lg); + lg = lnext(topop->groupClauses, lg); opid = distinct_col_search(tle->resno, colnos, opids); if (!OidIsValid(opid) || diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 12fba56285d..c6b8553a083 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -2211,10 +2211,9 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path) chain = NIL; if (list_length(rollups) > 1) { - ListCell *lc2 = lnext(list_head(rollups)); bool is_first_sort = ((RollupData *) linitial(rollups))->is_hashed; - for_each_cell(lc, lc2) + for_each_cell(lc, rollups, list_second_cell(rollups)) { RollupData *rollup = lfirst(lc); AttrNumber *new_grpColIdx; @@ -4261,7 +4260,7 @@ create_mergejoin_plan(PlannerInfo *root, elog(ERROR, "outer pathkeys do not match mergeclauses"); opathkey = (PathKey *) lfirst(lop); opeclass = opathkey->pk_eclass; - lop = lnext(lop); + lop = lnext(outerpathkeys, lop); if (oeclass != opeclass) elog(ERROR, "outer pathkeys do not match mergeclauses"); } @@ -4288,7 +4287,7 @@ create_mergejoin_plan(PlannerInfo *root, if (ieclass == ipeclass) { /* successful first match to this inner pathkey */ - lip = lnext(lip); + lip = lnext(innerpathkeys, lip); first_inner_match = true; } } @@ -4820,7 +4819,7 @@ fix_indexqual_operand(Node *node, IndexOptInfo *index, int indexcol) else elog(ERROR, "index key does not match expected index column"); } - indexpr_item = lnext(indexpr_item); + indexpr_item = lnext(index->indexprs, indexpr_item); } } diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 401299e5420..ca3b7f29e18 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -3351,7 +3351,7 @@ extract_rollup_sets(List *groupingSets) while (lc1 && lfirst(lc1) == NIL) { ++num_empty; - lc1 = lnext(lc1); + lc1 = lnext(groupingSets, lc1); } /* bail out now if it turns out that all we had were empty sets. */ @@ -3385,7 +3385,7 @@ extract_rollup_sets(List *groupingSets) j = 0; i = 1; - for_each_cell(lc, lc1) + for_each_cell(lc, groupingSets, lc1) { List *candidate = (List *) lfirst(lc); Bitmapset *candidate_set = NULL; @@ -4243,7 +4243,7 @@ consider_groupingsets_paths(PlannerInfo *root, { unhashed_rollup = lfirst_node(RollupData, l_start); exclude_groups = unhashed_rollup->numGroups; - l_start = lnext(l_start); + l_start = lnext(gd->rollups, l_start); } hashsize = estimate_hashagg_tablesize(path, @@ -4264,7 +4264,7 @@ consider_groupingsets_paths(PlannerInfo *root, */ sets_data = list_copy(gd->unsortable_sets); - for_each_cell(lc, l_start) + for_each_cell(lc, gd->rollups, l_start) { RollupData *rollup = lfirst_node(RollupData, lc); @@ -4425,7 +4425,7 @@ consider_groupingsets_paths(PlannerInfo *root, * below, must use the same condition. */ i = 0; - for_each_cell(lc, lnext(list_head(gd->rollups))) + for_each_cell(lc, gd->rollups, list_second_cell(gd->rollups)) { RollupData *rollup = lfirst_node(RollupData, lc); @@ -4459,7 +4459,7 @@ consider_groupingsets_paths(PlannerInfo *root, rollups = list_make1(linitial(gd->rollups)); i = 0; - for_each_cell(lc, lnext(list_head(gd->rollups))) + for_each_cell(lc, gd->rollups, list_second_cell(gd->rollups)) { RollupData *rollup = lfirst_node(RollupData, lc); @@ -4672,7 +4672,7 @@ create_one_window_path(PlannerInfo *root, -1.0); } - if (lnext(l)) + if (lnext(activeWindows, l)) { /* * Add the current WindowFuncs to the output target for this @@ -5333,7 +5333,7 @@ postprocess_setop_tlist(List *new_tlist, List *orig_tlist) Assert(orig_tlist_item != NULL); orig_tle = lfirst_node(TargetEntry, orig_tlist_item); - orig_tlist_item = lnext(orig_tlist_item); + orig_tlist_item = lnext(orig_tlist, orig_tlist_item); if (orig_tle->resjunk) /* should not happen */ elog(ERROR, "resjunk output columns are not implemented"); Assert(new_tle->resno == orig_tle->resno); diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index efd0fbc21c5..48b62a55de8 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -567,7 +567,7 @@ build_subplan(PlannerInfo *root, Plan *plan, PlannerInfo *subroot, { ptr += sprintf(ptr, "$%d%s", lfirst_int(lc), - lnext(lc) ? "," : ")"); + lnext(splan->setParam, lc) ? "," : ")"); } } diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c index 67eeba938db..e20bee0b330 100644 --- a/src/backend/optimizer/prep/prepjointree.c +++ b/src/backend/optimizer/prep/prepjointree.c @@ -2791,8 +2791,6 @@ void remove_useless_result_rtes(PlannerInfo *root) { ListCell *cell; - ListCell *prev; - ListCell *next; /* Top level of jointree must always be a FromExpr */ Assert(IsA(root->parse->jointree, FromExpr)); @@ -2813,16 +2811,12 @@ remove_useless_result_rtes(PlannerInfo *root) * RTE_RESULT RTE; otherwise we'll generate a whole-row Var for the * RTE_RESULT, which the executor has no support for. */ - prev = NULL; - for (cell = list_head(root->rowMarks); cell; cell = next) + foreach(cell, root->rowMarks) { PlanRowMark *rc = (PlanRowMark *) lfirst(cell); - next = lnext(cell); if (rt_fetch(rc->rti, root->parse->rtable)->rtekind == RTE_RESULT) - root->rowMarks = list_delete_cell(root->rowMarks, cell, prev); - else - prev = cell; + root->rowMarks = foreach_delete_current(root->rowMarks, cell); } } @@ -2845,17 +2839,14 @@ remove_useless_results_recurse(PlannerInfo *root, Node *jtnode) FromExpr *f = (FromExpr *) jtnode; Relids result_relids = NULL; ListCell *cell; - ListCell *prev; - ListCell *next; /* * We can drop RTE_RESULT rels from the fromlist so long as at least * one child remains, since joining to a one-row table changes * nothing. The easiest way to mechanize this rule is to modify the - * list in-place, using list_delete_cell. + * list in-place. */ - prev = NULL; - for (cell = list_head(f->fromlist); cell; cell = next) + foreach(cell, f->fromlist) { Node *child = (Node *) lfirst(cell); int varno; @@ -2864,7 +2855,6 @@ remove_useless_results_recurse(PlannerInfo *root, Node *jtnode) child = remove_useless_results_recurse(root, child); /* ... and stick it back into the tree */ lfirst(cell) = child; - next = lnext(cell); /* * If it's an RTE_RESULT with at least one sibling, we can drop @@ -2874,11 +2864,9 @@ remove_useless_results_recurse(PlannerInfo *root, Node *jtnode) if (list_length(f->fromlist) > 1 && (varno = get_result_relid(root, child)) != 0) { - f->fromlist = list_delete_cell(f->fromlist, cell, prev); + f->fromlist = foreach_delete_current(f->fromlist, cell); result_relids = bms_add_member(result_relids, varno); } - else - prev = cell; } /* diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c index 05172ff0234..792ae393d97 100644 --- a/src/backend/optimizer/prep/preptlist.c +++ b/src/backend/optimizer/prep/preptlist.c @@ -285,7 +285,7 @@ expand_targetlist(List *tlist, int command_type, if (!old_tle->resjunk && old_tle->resno == attrno) { new_tle = old_tle; - tlist_item = lnext(tlist_item); + tlist_item = lnext(tlist, tlist_item); } } @@ -410,7 +410,7 @@ expand_targetlist(List *tlist, int command_type, } new_tlist = lappend(new_tlist, old_tle); attrno++; - tlist_item = lnext(tlist_item); + tlist_item = lnext(tlist, tlist_item); } return new_tlist; diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index cd9d49c1f79..61120778516 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -1310,7 +1310,7 @@ generate_append_tlist(List *colTypes, List *colCollations, /* types disagree, so force typmod to -1 */ colTypmods[colindex] = -1; } - curColType = lnext(curColType); + curColType = lnext(colTypes, curColType); colindex++; } Assert(curColType == NULL); @@ -1410,7 +1410,7 @@ generate_setop_grouplist(SetOperationStmt *op, List *targetlist) /* non-resjunk columns should have grouping clauses */ Assert(lg != NULL); sgc = (SortGroupClause *) lfirst(lg); - lg = lnext(lg); + lg = lnext(grouplist, lg); Assert(sgc->tleSortGroupRef == 0); sgc->tleSortGroupRef = tle->ressortgroupref; diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index d78f4e64c1b..f0e789f37e6 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -5255,7 +5255,7 @@ tlist_matches_coltypelist(List *tlist, List *coltypelist) return false; /* too many tlist items */ coltype = lfirst_oid(clistitem); - clistitem = lnext(clistitem); + clistitem = lnext(coltypelist, clistitem); if (exprType((Node *) tle->expr) != coltype) return false; /* column type mismatch */ diff --git a/src/backend/optimizer/util/paramassign.c b/src/backend/optimizer/util/paramassign.c index 838587c2b8d..536d80a2756 100644 --- a/src/backend/optimizer/util/paramassign.c +++ b/src/backend/optimizer/util/paramassign.c @@ -510,17 +510,12 @@ identify_current_nestloop_params(PlannerInfo *root, Relids leftrelids) { List *result; ListCell *cell; - ListCell *prev; - ListCell *next; result = NIL; - prev = NULL; - for (cell = list_head(root->curOuterParams); cell; cell = next) + foreach(cell, root->curOuterParams) { NestLoopParam *nlp = (NestLoopParam *) lfirst(cell); - next = lnext(cell); - /* * We are looking for Vars and PHVs that can be supplied by the * lefthand rels. The "bms_overlap" test is just an optimization to @@ -529,8 +524,8 @@ identify_current_nestloop_params(PlannerInfo *root, Relids leftrelids) if (IsA(nlp->paramval, Var) && bms_is_member(nlp->paramval->varno, leftrelids)) { - root->curOuterParams = list_delete_cell(root->curOuterParams, - cell, prev); + root->curOuterParams = foreach_delete_current(root->curOuterParams, + cell); result = lappend(result, nlp); } else if (IsA(nlp->paramval, PlaceHolderVar) && @@ -541,12 +536,10 @@ identify_current_nestloop_params(PlannerInfo *root, Relids leftrelids) false)->ph_eval_at, leftrelids)) { - root->curOuterParams = list_delete_cell(root->curOuterParams, - cell, prev); + root->curOuterParams = foreach_delete_current(root->curOuterParams, + cell); result = lappend(result, nlp); } - else - prev = cell; } return result; } diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index d884d2bb000..67254c2fd91 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -423,11 +423,9 @@ void add_path(RelOptInfo *parent_rel, Path *new_path) { bool accept_new = true; /* unless we find a superior old path */ - ListCell *insert_after = NULL; /* where to insert new item */ + int insert_at = 0; /* where to insert new item */ List *new_path_pathkeys; ListCell *p1; - ListCell *p1_prev; - ListCell *p1_next; /* * This is a convenient place to check for query cancel --- no part of the @@ -442,12 +440,8 @@ add_path(RelOptInfo *parent_rel, Path *new_path) * 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 * it. - * - * We can't use foreach here because the loop body may delete the current - * list cell. */ - p1_prev = NULL; - for (p1 = list_head(parent_rel->pathlist); p1 != NULL; p1 = p1_next) + foreach(p1, parent_rel->pathlist) { Path *old_path = (Path *) lfirst(p1); bool remove_old = false; /* unless new proves superior */ @@ -455,8 +449,6 @@ add_path(RelOptInfo *parent_rel, Path *new_path) PathKeysComparison keyscmp; BMS_Comparison outercmp; - p1_next = lnext(p1); - /* * Do a fuzzy cost comparison with standard fuzziness limit. */ @@ -593,23 +585,20 @@ add_path(RelOptInfo *parent_rel, Path *new_path) */ if (remove_old) { - parent_rel->pathlist = list_delete_cell(parent_rel->pathlist, - p1, p1_prev); + 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); - /* p1_prev does not advance */ } else { /* new belongs after this old path if it has cost >= old's */ if (new_path->total_cost >= old_path->total_cost) - insert_after = p1; - /* p1_prev advances */ - p1_prev = p1; + insert_at = foreach_current_index(p1) + 1; } /* @@ -624,10 +613,8 @@ add_path(RelOptInfo *parent_rel, Path *new_path) if (accept_new) { /* Accept the new path: insert it at proper place in pathlist */ - if (insert_after) - lappend_cell(parent_rel->pathlist, insert_after, new_path); - else - parent_rel->pathlist = lcons(new_path, parent_rel->pathlist); + parent_rel->pathlist = + list_insert_nth(parent_rel->pathlist, insert_at, new_path); } else { @@ -763,10 +750,8 @@ void add_partial_path(RelOptInfo *parent_rel, Path *new_path) { bool accept_new = true; /* unless we find a superior old path */ - ListCell *insert_after = NULL; /* where to insert new item */ + int insert_at = 0; /* where to insert new item */ ListCell *p1; - ListCell *p1_prev; - ListCell *p1_next; /* Check for query cancel. */ CHECK_FOR_INTERRUPTS(); @@ -781,16 +766,12 @@ add_partial_path(RelOptInfo *parent_rel, Path *new_path) * As in add_path, throw out any paths which are dominated by the new * path, but throw out the new path if some existing path dominates it. */ - p1_prev = NULL; - for (p1 = list_head(parent_rel->partial_pathlist); p1 != NULL; - p1 = p1_next) + foreach(p1, parent_rel->partial_pathlist) { Path *old_path = (Path *) lfirst(p1); bool remove_old = false; /* unless new proves superior */ PathKeysComparison keyscmp; - p1_next = lnext(p1); - /* Compare pathkeys. */ keyscmp = compare_pathkeys(new_path->pathkeys, old_path->pathkeys); @@ -841,17 +822,14 @@ add_partial_path(RelOptInfo *parent_rel, Path *new_path) if (remove_old) { parent_rel->partial_pathlist = - list_delete_cell(parent_rel->partial_pathlist, p1, p1_prev); + foreach_delete_current(parent_rel->partial_pathlist, p1); pfree(old_path); - /* p1_prev does not advance */ } else { /* new belongs after this old path if it has cost >= old's */ if (new_path->total_cost >= old_path->total_cost) - insert_after = p1; - /* p1_prev advances */ - p1_prev = p1; + insert_at = foreach_current_index(p1) + 1; } /* @@ -866,11 +844,8 @@ add_partial_path(RelOptInfo *parent_rel, Path *new_path) if (accept_new) { /* Accept the new path: insert it at proper place */ - if (insert_after) - lappend_cell(parent_rel->partial_pathlist, insert_after, new_path); - else - parent_rel->partial_pathlist = - lcons(new_path, parent_rel->partial_pathlist); + parent_rel->partial_pathlist = + list_insert_nth(parent_rel->partial_pathlist, insert_at, new_path); } else { diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 40f497660d1..6ea625a148c 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -1742,7 +1742,7 @@ build_index_tlist(PlannerInfo *root, IndexOptInfo *index, if (indexpr_item == NULL) elog(ERROR, "wrong number of index expressions"); indexvar = (Expr *) lfirst(indexpr_item); - indexpr_item = lnext(indexpr_item); + indexpr_item = lnext(index->indexprs, indexpr_item); } tlist = lappend(tlist, @@ -2301,7 +2301,7 @@ set_baserel_partition_key_exprs(Relation relation, /* Re-stamp the expression with given varno. */ partexpr = (Expr *) copyObject(lfirst(lc)); ChangeVarNodes((Node *) partexpr, 1, varno, 0); - lc = lnext(lc); + lc = lnext(partkey->partexprs, lc); } partexprs[cnt] = list_make1(partexpr); diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c index b81eba72191..08a160fff60 100644 --- a/src/backend/optimizer/util/predtest.c +++ b/src/backend/optimizer/util/predtest.c @@ -59,6 +59,7 @@ typedef struct PredIterInfoData { /* node-type-specific iteration state */ void *state; + List *state_list; /* initialize to do the iteration */ void (*startup_fn) (Node *clause, PredIterInfo info); /* next-component iteration function */ @@ -905,7 +906,8 @@ predicate_classify(Node *clause, PredIterInfo info) static void list_startup_fn(Node *clause, PredIterInfo info) { - info->state = (void *) list_head((List *) clause); + info->state_list = (List *) clause; + info->state = (void *) list_head(info->state_list); } static Node * @@ -917,7 +919,7 @@ list_next_fn(PredIterInfo info) if (l == NULL) return NULL; n = lfirst(l); - info->state = (void *) lnext(l); + info->state = (void *) lnext(info->state_list, l); return n; } @@ -934,7 +936,8 @@ list_cleanup_fn(PredIterInfo info) static void boolexpr_startup_fn(Node *clause, PredIterInfo info) { - info->state = (void *) list_head(((BoolExpr *) clause)->args); + info->state_list = ((BoolExpr *) clause)->args; + info->state = (void *) list_head(info->state_list); } /* @@ -1057,6 +1060,7 @@ arrayexpr_startup_fn(Node *clause, PredIterInfo info) /* Initialize iteration variable to first member of ArrayExpr */ arrayexpr = (ArrayExpr *) lsecond(saop->args); + info->state_list = arrayexpr->elements; state->next = list_head(arrayexpr->elements); } @@ -1068,7 +1072,7 @@ arrayexpr_next_fn(PredIterInfo info) if (state->next == NULL) return NULL; lsecond(state->opexpr.args) = lfirst(state->next); - state->next = lnext(state->next); + state->next = lnext(info->state_list, state->next); return (Node *) &(state->opexpr); } diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c index 41402821a15..7ccb10e4e1b 100644 --- a/src/backend/optimizer/util/tlist.c +++ b/src/backend/optimizer/util/tlist.c @@ -287,7 +287,7 @@ tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK) return false; /* tlist longer than colTypes */ if (exprType((Node *) tle->expr) != lfirst_oid(curColType)) return false; - curColType = lnext(curColType); + curColType = lnext(colTypes, curColType); } } if (curColType != NULL) @@ -321,7 +321,7 @@ tlist_same_collations(List *tlist, List *colCollations, bool junkOK) return false; /* tlist longer than colCollations */ if (exprCollation((Node *) tle->expr) != lfirst_oid(curColColl)) return false; - curColColl = lnext(curColColl); + curColColl = lnext(colCollations, curColColl); } } if (curColColl != NULL) @@ -1022,7 +1022,7 @@ split_pathtarget_at_srfs(PlannerInfo *root, List *level_srfs = (List *) lfirst(lc1); PathTarget *ntarget; - if (lnext(lc1) == NULL) + if (lnext(context.level_srfs, lc1) == NULL) { ntarget = target; } @@ -1037,13 +1037,15 @@ split_pathtarget_at_srfs(PlannerInfo *root, * later levels. */ add_sp_items_to_pathtarget(ntarget, level_srfs); - for_each_cell(lc, lnext(lc2)) + for_each_cell(lc, context.level_input_vars, + lnext(context.level_input_vars, lc2)) { List *input_vars = (List *) lfirst(lc); add_sp_items_to_pathtarget(ntarget, input_vars); } - for_each_cell(lc, lnext(lc3)) + for_each_cell(lc, context.level_input_srfs, + lnext(context.level_input_srfs, lc3)) { List *input_srfs = (List *) lfirst(lc); ListCell *lcx; |
