aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/path
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/path')
-rw-r--r--src/backend/optimizer/path/allpaths.c4
-rw-r--r--src/backend/optimizer/path/costsize.c12
-rw-r--r--src/backend/optimizer/path/equivclass.c38
-rw-r--r--src/backend/optimizer/path/indxpath.c53
-rw-r--r--src/backend/optimizer/path/joinrels.c46
-rw-r--r--src/backend/optimizer/path/pathkeys.c6
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;
}