From 89a368418c56125f79f46a81229e824d519f9718 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sat, 20 Nov 2010 15:07:16 -0500
Subject: [PATCH] Further cleanup of indxpath logic related to
 IndexOptInfo.opfamily array.

We no longer need the terminating zero entry in opfamily[], so get rid of
it.  Also replace assorted ad-hoc looping logic with simple for and foreach
constructs.  This code is now noticeably more readable than it was an hour
ago; credit to Robert for seeing that it could be simplified.
---
 src/backend/optimizer/path/indxpath.c | 53 ++++++++++++---------------
 src/backend/optimizer/util/plancat.c  | 10 ++---
 src/include/nodes/relation.h          |  3 --
 3 files changed, 28 insertions(+), 38 deletions(-)

diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index e14d0f5f02c..d8fc12068fb 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -1047,14 +1047,14 @@ group_clauses_by_indexkey(IndexOptInfo *index,
 {
 	List	   *clausegroup_list = NIL;
 	bool		found_outer_clause = false;
-	int			indexcol = 0;
+	int			indexcol;
 
 	*found_clause = false;		/* default result */
 
 	if (clauses == NIL && outer_clauses == NIL)
 		return NIL;				/* cannot succeed */
 
-	do
+	for (indexcol = 0; indexcol < index->ncolumns; indexcol++)
 	{
 		List	   *clausegroup = NIL;
 		ListCell   *l;
@@ -1102,10 +1102,7 @@ group_clauses_by_indexkey(IndexOptInfo *index,
 			return NIL;
 
 		clausegroup_list = lappend(clausegroup_list, clausegroup);
-
-		indexcol++;
-
-	} while (indexcol < index->ncolumns);
+	}
 
 	if (!*found_clause && !found_outer_clause)
 		return NIL;				/* no indexable clauses anywhere */
@@ -1163,8 +1160,8 @@ group_clauses_by_indexkey(IndexOptInfo *index,
  *
  * 'index' is the index of interest.
  * 'indexcol' is a column number of 'index' (counting from 0).
- * 'opfamily' is the corresponding operator family.
  * 'rinfo' is the clause to be tested (as a RestrictInfo node).
+ * 'outer_relids' lists rels whose Vars can be considered pseudoconstant.
  * 'saop_control' indicates whether ScalarArrayOpExpr clauses can be used.
  *
  * Returns true if the clause can be used with this index key.
@@ -1180,12 +1177,12 @@ match_clause_to_indexcol(IndexOptInfo *index,
 						 SaOpControl saop_control)
 {
 	Expr	   *clause = rinfo->clause;
+	Oid			opfamily = index->opfamily[indexcol];
 	Node	   *leftop,
 			   *rightop;
 	Relids		left_relids;
 	Relids		right_relids;
 	Oid			expr_op;
-	Oid			opfamily = index->opfamily[indexcol];
 	bool		plain_op;
 
 	/*
@@ -1571,9 +1568,9 @@ matches_any_index(RestrictInfo *rinfo, RelOptInfo *rel, Relids outer_relids)
 	foreach(l, rel->indexlist)
 	{
 		IndexOptInfo *index = (IndexOptInfo *) lfirst(l);
-		int			indexcol = 0;
+		int			indexcol;
 
-		do
+		for (indexcol = 0; indexcol < index->ncolumns; indexcol++)
 		{
 			if (match_clause_to_indexcol(index,
 										 indexcol,
@@ -1581,9 +1578,7 @@ matches_any_index(RestrictInfo *rinfo, RelOptInfo *rel, Relids outer_relids)
 										 outer_relids,
 										 SAOP_ALLOW))
 				return true;
-
-			indexcol++;
-		} while (indexcol < index->ncolumns);
+		}
 	}
 
 	return false;
@@ -1605,9 +1600,9 @@ eclass_matches_any_index(EquivalenceClass *ec, EquivalenceMember *em,
 	foreach(l, rel->indexlist)
 	{
 		IndexOptInfo *index = (IndexOptInfo *) lfirst(l);
-		int			indexcol = 0;
+		int			indexcol;
 
-		do
+		for (indexcol = 0; indexcol < index->ncolumns; indexcol++)
 		{
 			Oid			curFamily = index->opfamily[indexcol];
 
@@ -1625,9 +1620,7 @@ eclass_matches_any_index(EquivalenceClass *ec, EquivalenceMember *em,
 				 list_member_oid(ec->ec_opfamilies, curFamily)) &&
 				match_index_to_operand((Node *) em->em_expr, indexcol, index))
 				return true;
-
-			indexcol++;
-		} while (indexcol < index->ncolumns);
+		}
 	}
 
 	return false;
@@ -2360,21 +2353,25 @@ List *
 expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
 {
 	List	   *resultquals = NIL;
-	ListCell   *clausegroup_item;
-	int			indexcol = 0;
+	ListCell   *lc;
+	int			indexcol;
 
 	if (clausegroups == NIL)
 		return NIL;
 
-	clausegroup_item = list_head(clausegroups);
-	do
+	/* clausegroups must correspond to index columns */
+	Assert(list_length(clausegroups) <= index->ncolumns);
+
+	indexcol = 0;
+	foreach(lc, clausegroups)
 	{
+		List	   *clausegroup = (List *) lfirst(lc);
 		Oid			curFamily = index->opfamily[indexcol];
-		ListCell   *l;
+		ListCell   *lc2;
 
-		foreach(l, (List *) lfirst(clausegroup_item))
+		foreach(lc2, clausegroup)
 		{
-			RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
+			RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc2);
 			Expr	   *clause = rinfo->clause;
 
 			/* First check for boolean cases */
@@ -2426,12 +2423,8 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
 					 (int) nodeTag(clause));
 		}
 
-		clausegroup_item = lnext(clausegroup_item);
-
 		indexcol++;
-	} while (clausegroup_item != NULL && indexcol < index->ncolumns);
-
-	Assert(clausegroup_item == NULL);	/* else more groups than indexkeys */
+	}
 
 	return resultquals;
 }
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index aafaf843fcc..73132ddf5ca 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -192,13 +192,13 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 
 			/*
 			 * Allocate per-column info arrays.  To save a few palloc cycles
-			 * we allocate all the Oid-type arrays in one request.	Note that
-			 * the opfamily array needs an extra, terminating zero at the end.
-			 * We pre-zero the ordering info in case the index is unordered.
+			 * we allocate all the Oid-type arrays in one request.  We must
+			 * pre-zero the sortop and nulls_first arrays in case the index is
+			 * unordered.
 			 */
 			info->indexkeys = (int *) palloc(sizeof(int) * ncolumns);
-			info->opfamily = (Oid *) palloc0(sizeof(Oid) * (4 * ncolumns + 1));
-			info->opcintype = info->opfamily + (ncolumns + 1);
+			info->opfamily = (Oid *) palloc0(sizeof(Oid) * (4 * ncolumns));
+			info->opcintype = info->opfamily + ncolumns;
 			info->fwdsortop = info->opcintype + ncolumns;
 			info->revsortop = info->fwdsortop + ncolumns;
 			info->nulls_first = (bool *) palloc0(sizeof(bool) * ncolumns);
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index 81126a23665..677134dcec9 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -427,9 +427,6 @@ typedef struct RelOptInfo
  *
  *		opfamily[], indexkeys[], opcintype[], fwdsortop[], revsortop[],
  *		and nulls_first[] each have ncolumns entries.
- *		Note: for historical reasons, the opfamily array has an extra entry
- *		that is always zero.  Some code scans until it sees a zero entry,
- *		rather than looking at ncolumns.
  *
  *		Zeroes in the indexkeys[] array indicate index columns that are
  *		expressions; there is one element in indexprs for each such column.
-- 
GitLab