diff options
Diffstat (limited to 'src/backend/optimizer/path')
-rw-r--r-- | src/backend/optimizer/path/allpaths.c | 4 | ||||
-rw-r--r-- | src/backend/optimizer/path/costsize.c | 12 | ||||
-rw-r--r-- | src/backend/optimizer/path/equivclass.c | 38 | ||||
-rw-r--r-- | src/backend/optimizer/path/indxpath.c | 53 | ||||
-rw-r--r-- | src/backend/optimizer/path/joinrels.c | 46 | ||||
-rw-r--r-- | src/backend/optimizer/path/pathkeys.c | 6 |
6 files changed, 74 insertions, 85 deletions
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; } |