nocfbot-0068-Use-foreach_node-and-friends-in-row-pattern-recog.txt

text/plain

Filename: nocfbot-0068-Use-foreach_node-and-friends-in-row-pattern-recog.txt
Type: text/plain
Part: 67
Message: Re: Row pattern recognition
From b010580c9b62244ba323520bb7202aa348c18195 Mon Sep 17 00:00:00 2001
From: Henson Choi <assam258@gmail.com>
Date: Mon, 8 Jun 2026 21:27:44 +0900
Subject: [PATCH 68/68] Use foreach_node and friends in row pattern recognition
 code

Replace the hand-written foreach()/lfirst() loops in the row pattern
recognition code with foreach_node(), foreach_ptr(), foreach_current_index()
and forboth(), dropping the now-unneeded ListCell declarations, casts and
manual index counters.  No behavior change.
---
 src/backend/executor/execRPR.c            | 10 +--
 src/backend/executor/nodeWindowAgg.c      | 12 +--
 src/backend/optimizer/path/allpaths.c     |  9 +--
 src/backend/optimizer/path/costsize.c     |  5 +-
 src/backend/optimizer/plan/createplan.c   |  5 +-
 src/backend/optimizer/plan/rpr.c          | 90 +++++++----------------
 src/backend/optimizer/prep/prepjointree.c |  4 +-
 src/backend/parser/parse_cte.c            |  3 +-
 src/backend/parser/parse_expr.c           |  5 +-
 src/backend/parser/parse_rpr.c            | 38 +++-------
 src/backend/utils/adt/ruleutils.c         | 18 ++---
 11 files changed, 62 insertions(+), 137 deletions(-)

diff --git a/src/backend/executor/execRPR.c b/src/backend/executor/execRPR.c
index 1c89875a306..5ae54495968 100644
--- a/src/backend/executor/execRPR.c
+++ b/src/backend/executor/execRPR.c
@@ -1595,8 +1595,6 @@ nfa_reevaluate_dependent_vars(WindowAggState *winstate, RPRNFAContext *ctx,
 	ExprContext *econtext = winstate->ss.ps.ps_ExprContext;
 	int64		saved_match_start = winstate->nav_match_start;
 	int64		saved_pos = winstate->currentpos;
-	int			varIdx = 0;
-	ListCell   *lc;
 
 	/* Temporarily set nav_match_start and currentpos for FIRST/LAST */
 	winstate->nav_match_start = ctx->matchStartRow;
@@ -1605,11 +1603,12 @@ nfa_reevaluate_dependent_vars(WindowAggState *winstate, RPRNFAContext *ctx,
 	/* Invalidate nav_slot cache since match_start changed */
 	winstate->nav_slot_pos = -1;
 
-	foreach(lc, winstate->defineClauseList)
+	foreach_ptr(ExprState, exprState, winstate->defineClauseList)
 	{
+		int			varIdx = foreach_current_index(exprState);
+
 		if (bms_is_member(varIdx, winstate->defineMatchStartDependent))
 		{
-			ExprState  *exprState = (ExprState *) lfirst(lc);
 			Datum		result;
 			bool		isnull;
 
@@ -1618,8 +1617,7 @@ nfa_reevaluate_dependent_vars(WindowAggState *winstate, RPRNFAContext *ctx,
 			winstate->nfaVarMatched[varIdx] = (!isnull && DatumGetBool(result));
 		}
 
-		varIdx++;
-		if (varIdx >= list_length(winstate->defineVariableList))
+		if (varIdx + 1 >= list_length(winstate->defineVariableList))
 			break;
 	}
 
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index 13661181986..15579ae5ea4 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -3084,9 +3084,8 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
 		 * by EEOP_RPR_NAV_SET/RESTORE opcodes emitted during ExecInitExpr, so
 		 * no varno rewriting is needed here.
 		 */
-		foreach(l, node->defineClause)
+		foreach_node(TargetEntry, te, node->defineClause)
 		{
-			TargetEntry *te = lfirst(l);
 			char	   *name = te->resname;
 			Expr	   *expr = te->expr;
 			ExprState  *exps;
@@ -4173,7 +4172,6 @@ eval_define_offsets(WindowAggState *winstate, List *defineClause)
 {
 	EvalDefineOffsetsContext ctx;
 	NavTraversal trav;
-	ListCell   *lc;
 	bool		needsMax = (winstate->navMaxOffsetKind == RPR_NAV_OFFSET_NEEDS_EVAL);
 	bool		needsFirst = (winstate->hasFirstNav &&
 							  winstate->navFirstOffsetKind == RPR_NAV_OFFSET_NEEDS_EVAL);
@@ -4189,10 +4187,8 @@ eval_define_offsets(WindowAggState *winstate, List *defineClause)
 	trav.visit = visit_nav_exec;
 	trav.data = &ctx;
 
-	foreach(lc, defineClause)
+	foreach_node(TargetEntry, te, defineClause)
 	{
-		TargetEntry *te = (TargetEntry *) lfirst(lc);
-
 		nav_traversal_walker((Node *) te->expr, &trav);
 	}
 
@@ -4586,7 +4582,6 @@ nfa_evaluate_row(WindowObject winobj, int64 pos, bool *varMatched)
 	WindowAggState *winstate = winobj->winstate;
 	ExprContext *econtext = winstate->ss.ps.ps_ExprContext;
 	int			numDefineVars = list_length(winstate->defineVariableList);
-	ListCell   *lc;
 	int			varIdx = 0;
 	TupleTableSlot *slot;
 	int64		saved_pos;
@@ -4609,9 +4604,8 @@ nfa_evaluate_row(WindowObject winobj, int64 pos, bool *varMatched)
 	/* Invalidate nav_slot cache so PREV/NEXT re-fetch for new row */
 	winstate->nav_slot_pos = -1;
 
-	foreach(lc, winstate->defineClauseList)
+	foreach_ptr(ExprState, exprState, winstate->defineClauseList)
 	{
-		ExprState  *exprState = (ExprState *) lfirst(lc);
 		Datum		result;
 		bool		isnull;
 
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 22339f7491f..f3c9f3c0bd6 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -4760,21 +4760,16 @@ remove_unused_subquery_outputs(Query *subquery, RelOptInfo *rel,
 		if (IsA(texpr, Var))
 		{
 			Var		   *var = (Var *) texpr;
-			ListCell   *wlc;
 			bool		needed_by_define = false;
 
-			foreach(wlc, subquery->windowClause)
+			foreach_node(WindowClause, wc, subquery->windowClause)
 			{
-				WindowClause *wc = lfirst_node(WindowClause, wlc);
-
 				if (wc->defineClause != NIL)
 				{
 					List	   *vars = pull_var_clause((Node *) wc->defineClause, 0);
-					ListCell   *vlc;
 
-					foreach(vlc, vars)
+					foreach_node(Var, dvar, vars)
 					{
-						Var		   *dvar = (Var *) lfirst(vlc);
 
 						/*
 						 * Match varno as well as varattno: a Var pulled from
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index b38cad9f121..82472c3fe96 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -3236,14 +3236,13 @@ cost_windowagg(Path *path, PlannerInfo *root,
 	if (winclause->rpPattern)
 	{
 		List	   *pattern_vars;
-		ListCell   *lc2;
 		QualCost	defcosts;
 
 		pattern_vars = collectPatternVariables(winclause->rpPattern);
 
-		foreach(lc2, pattern_vars)
+		foreach_node(String, pv, pattern_vars)
 		{
-			char	   *ptname = strVal(lfirst(lc2));
+			char	   *ptname = strVal(pv);
 
 			foreach_node(TargetEntry, def, winclause->defineClause)
 			{
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index d2e19d61d58..cca4126e511 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -2736,7 +2736,6 @@ compute_define_metadata(List *defineClause,
 {
 	DefineMetadataContext ctx;
 	NavTraversal trav;
-	ListCell   *lc;
 
 	ctx.maxOffset = 0;
 	ctx.maxNeedsEval = false;
@@ -2750,10 +2749,8 @@ compute_define_metadata(List *defineClause,
 	trav.visit = visit_nav_plan;
 	trav.data = &ctx;
 
-	foreach(lc, defineClause)
+	foreach_node(TargetEntry, te, defineClause)
 	{
-		TargetEntry *te = (TargetEntry *) lfirst(lc);
-
 		nav_traversal_walker((Node *) te->expr, &trav);
 		ctx.curVarIdx++;
 	}
diff --git a/src/backend/optimizer/plan/rpr.c b/src/backend/optimizer/plan/rpr.c
index d768422deeb..664c942e575 100644
--- a/src/backend/optimizer/plan/rpr.c
+++ b/src/backend/optimizer/plan/rpr.c
@@ -191,12 +191,10 @@ tryUnwrapSingleChild(RPRPatternNode *pattern)
 static List *
 flattenSeqChildren(List *children)
 {
-	ListCell   *lc;
 	List	   *newChildren = NIL;
 
-	foreach(lc, children)
+	foreach_node(RPRPatternNode, child, children)
 	{
-		RPRPatternNode *child = (RPRPatternNode *) lfirst(lc);
 		RPRPatternNode *opt = optimizeRPRPattern(child);
 
 		/* GROUP{1,1} should have been unwrapped by optimizeGroupPattern */
@@ -229,14 +227,11 @@ flattenSeqChildren(List *children)
 static List *
 mergeConsecutiveVars(List *children)
 {
-	ListCell   *lc;
 	List	   *mergedChildren = NIL;
 	RPRPatternNode *prev = NULL;
 
-	foreach(lc, children)
+	foreach_node(RPRPatternNode, child, children)
 	{
-		RPRPatternNode *child = (RPRPatternNode *) lfirst(lc);
-
 		if (child->nodeType == RPR_PATTERN_VAR && child->reluctant == false)
 		{
 			/* ----------------------
@@ -306,14 +301,11 @@ mergeConsecutiveVars(List *children)
 static List *
 mergeConsecutiveGroups(List *children)
 {
-	ListCell   *lc;
 	List	   *mergedChildren = NIL;
 	RPRPatternNode *prev = NULL;
 
-	foreach(lc, children)
+	foreach_node(RPRPatternNode, child, children)
 	{
-		RPRPatternNode *child = (RPRPatternNode *) lfirst(lc);
-
 		if (child->nodeType == RPR_PATTERN_GROUP && child->reluctant == false)
 		{
 			/* ----------------------
@@ -385,15 +377,12 @@ mergeConsecutiveGroups(List *children)
 static List *
 mergeConsecutiveAlts(List *children)
 {
-	ListCell   *lc;
 	List	   *mergedChildren = NIL;
 	RPRPatternNode *prev = NULL;
 	int			count = 0;
 
-	foreach(lc, children)
+	foreach_node(RPRPatternNode, child, children)
 	{
-		RPRPatternNode *child = (RPRPatternNode *) lfirst(lc);
-
 		if (child->nodeType == RPR_PATTERN_ALT && child->reluctant == false)
 		{
 			if (prev != NULL &&
@@ -702,12 +691,10 @@ optimizeSeqPattern(RPRPatternNode *pattern)
 static List *
 flattenAltChildren(List *children)
 {
-	ListCell   *lc;
 	List	   *newChildren = NIL;
 
-	foreach(lc, children)
+	foreach_node(RPRPatternNode, child, children)
 	{
-		RPRPatternNode *child = (RPRPatternNode *) lfirst(lc);
 		RPRPatternNode *opt = optimizeRPRPattern(child);
 
 		if (opt->nodeType == RPR_PATTERN_ALT)
@@ -732,18 +719,15 @@ flattenAltChildren(List *children)
 static List *
 removeDuplicateAlternatives(List *children)
 {
-	ListCell   *lc;
-	ListCell   *lc2;
 	List	   *uniqueChildren = NIL;
 
-	foreach(lc, children)
+	foreach_node(RPRPatternNode, child, children)
 	{
-		RPRPatternNode *child = (RPRPatternNode *) lfirst(lc);
 		bool		isDuplicate = false;
 
-		foreach(lc2, uniqueChildren)
+		foreach_node(RPRPatternNode, uchild, uniqueChildren)
 		{
-			if (rprPatternEqual((RPRPatternNode *) lfirst(lc2), child))
+			if (rprPatternEqual(uchild, child))
 			{
 				isDuplicate = true;
 				break;
@@ -940,16 +924,13 @@ tryUnwrapGroup(RPRPatternNode *pattern)
 static RPRPatternNode *
 optimizeGroupPattern(RPRPatternNode *pattern)
 {
-	ListCell   *lc;
 	List	   *newChildren;
 	RPRPatternNode *result;
 
 	/* Recursively optimize children */
 	newChildren = NIL;
-	foreach(lc, pattern->children)
+	foreach_node(RPRPatternNode, child, pattern->children)
 	{
-		RPRPatternNode *child = (RPRPatternNode *) lfirst(lc);
-
 		newChildren = lappend(newChildren, optimizeRPRPattern(child));
 	}
 	pattern->children = newChildren;
@@ -1005,15 +986,14 @@ optimizeRPRPattern(RPRPatternNode *pattern)
 static int
 collectDefineVariables(List *defineVariableList, char **varNames)
 {
-	ListCell   *lc;
 	int			numVars = 0;
 
-	foreach(lc, defineVariableList)
+	foreach_node(String, varname, defineVariableList)
 	{
 		/* Parser already checked this limit in transformDefineClause */
 		Assert(numVars <= RPR_VARID_MAX);
 
-		varNames[numVars++] = strVal(lfirst(lc));
+		varNames[numVars++] = strVal(varname);
 	}
 
 	return numVars;
@@ -1031,7 +1011,6 @@ static void
 scanRPRPatternRecursive(RPRPatternNode *node, char **varNames, int *numVars,
 						int *numElements, RPRDepth depth, RPRDepth *maxDepth)
 {
-	ListCell   *lc;
 	int			i;
 
 	/* Pattern nodes from parser are never NULL */
@@ -1075,9 +1054,9 @@ scanRPRPatternRecursive(RPRPatternNode *node, char **varNames, int *numVars,
 
 		case RPR_PATTERN_SEQ:
 			/* Sequence: just recurse into children */
-			foreach(lc, node->children)
+			foreach_node(RPRPatternNode, child, node->children)
 			{
-				scanRPRPatternRecursive((RPRPatternNode *) lfirst(lc), varNames,
+				scanRPRPatternRecursive(child, varNames,
 										numVars, numElements, depth, maxDepth);
 			}
 			break;
@@ -1088,9 +1067,9 @@ scanRPRPatternRecursive(RPRPatternNode *node, char **varNames, int *numVars,
 				(*numElements)++;
 
 			/* Recurse into children at increased depth */
-			foreach(lc, node->children)
+			foreach_node(RPRPatternNode, child, node->children)
 			{
-				scanRPRPatternRecursive((RPRPatternNode *) lfirst(lc), varNames,
+				scanRPRPatternRecursive(child, varNames,
 										numVars, numElements, depth + 1, maxDepth);
 			}
 
@@ -1104,9 +1083,9 @@ scanRPRPatternRecursive(RPRPatternNode *node, char **varNames, int *numVars,
 			(*numElements)++;
 
 			/* Recurse into children at increased depth */
-			foreach(lc, node->children)
+			foreach_node(RPRPatternNode, child, node->children)
 			{
-				scanRPRPatternRecursive((RPRPatternNode *) lfirst(lc), varNames,
+				scanRPRPatternRecursive(child, varNames,
 										numVars, numElements, depth + 1, maxDepth);
 			}
 			break;
@@ -1248,7 +1227,6 @@ fillRPRPatternVar(RPRPatternNode *node, RPRPattern *pat, int *idx, RPRDepth dept
 static bool
 fillRPRPatternGroup(RPRPatternNode *node, RPRPattern *pat, int *idx, RPRDepth depth)
 {
-	ListCell   *lc;
 	int			groupStartIdx = *idx;
 	int			beginIdx = -1;
 	bool		bodyNullable = true;
@@ -1275,9 +1253,9 @@ fillRPRPatternGroup(RPRPatternNode *node, RPRPattern *pat, int *idx, RPRDepth de
 		groupStartIdx = *idx;	/* children start after BEGIN */
 	}
 
-	foreach(lc, node->children)
+	foreach_node(RPRPatternNode, child, node->children)
 	{
-		if (!fillRPRPattern((RPRPatternNode *) lfirst(lc), pat, idx, depth + 1))
+		if (!fillRPRPattern(child, pat, idx, depth + 1))
 			bodyNullable = false;
 	}
 
@@ -1350,9 +1328,8 @@ fillRPRPatternAlt(RPRPatternNode *node, RPRPattern *pat, int *idx, RPRDepth dept
 	(*idx)++;
 
 	/* Fill each alternative */
-	foreach(lc, node->children)
+	foreach_node(RPRPatternNode, alt, node->children)
 	{
-		RPRPatternNode *alt = (RPRPatternNode *) lfirst(lc);
 		int			branchStart = *idx;
 
 		altBranchStarts = lappend_int(altBranchStarts, branchStart);
@@ -1372,9 +1349,8 @@ fillRPRPatternAlt(RPRPatternNode *node, RPRPattern *pat, int *idx, RPRDepth dept
 
 	/* Set next on last element of each alternative to after the alternation */
 	afterAltIdx = *idx;
-	lc2 = list_head(altBranchStarts);
 
-	foreach(lc, altEndPositions)
+	forboth(lc, altEndPositions, lc2, altBranchStarts)
 	{
 		int			endPos = lfirst_int(lc);
 		int			branchStart = lfirst_int(lc2);
@@ -1399,8 +1375,6 @@ fillRPRPatternAlt(RPRPatternNode *node, RPRPattern *pat, int *idx, RPRDepth dept
 		{
 			pat->elements[endPos].next = afterAltIdx;
 		}
-
-		lc2 = lnext(altBranchStarts, lc2);
 	}
 
 	list_free(altBranchStarts);
@@ -1422,7 +1396,6 @@ fillRPRPatternAlt(RPRPatternNode *node, RPRPattern *pat, int *idx, RPRDepth dept
 static bool
 fillRPRPattern(RPRPatternNode *node, RPRPattern *pat, int *idx, RPRDepth depth)
 {
-	ListCell   *lc;
 	bool		allNullable = true;
 
 	/* Pattern nodes from parser are never NULL */
@@ -1433,9 +1406,9 @@ fillRPRPattern(RPRPatternNode *node, RPRPattern *pat, int *idx, RPRDepth depth)
 	switch (node->nodeType)
 	{
 		case RPR_PATTERN_SEQ:
-			foreach(lc, node->children)
+			foreach_node(RPRPatternNode, child, node->children)
 			{
-				if (!fillRPRPattern((RPRPatternNode *) lfirst(lc), pat, idx, depth))
+				if (!fillRPRPattern(child, pat, idx, depth))
 					allNullable = false;
 			}
 			return allNullable;
@@ -1856,8 +1829,6 @@ computeAbsorbability(RPRPattern *pattern)
 static void
 collectPatternVariablesRecursive(RPRPatternNode *node, List **varNames)
 {
-	ListCell   *lc;
-
 	Assert(node != NULL);
 
 	check_stack_depth();
@@ -1866,9 +1837,9 @@ collectPatternVariablesRecursive(RPRPatternNode *node, List **varNames)
 	{
 		case RPR_PATTERN_VAR:
 			/* Add variable if not already in list */
-			foreach(lc, *varNames)
+			foreach_node(String, varname, *varNames)
 			{
-				if (strcmp(strVal(lfirst(lc)), node->varName) == 0)
+				if (strcmp(strVal(varname), node->varName) == 0)
 					return;		/* Already collected */
 			}
 			*varNames = lappend(*varNames, makeString(pstrdup(node->varName)));
@@ -1877,10 +1848,9 @@ collectPatternVariablesRecursive(RPRPatternNode *node, List **varNames)
 		case RPR_PATTERN_SEQ:
 		case RPR_PATTERN_ALT:
 		case RPR_PATTERN_GROUP:
-			foreach(lc, node->children)
+			foreach_node(RPRPatternNode, child, node->children)
 			{
-				collectPatternVariablesRecursive((RPRPatternNode *) lfirst(lc),
-												 varNames);
+				collectPatternVariablesRecursive(child, varNames);
 			}
 			break;
 	}
@@ -1917,14 +1887,10 @@ collectPatternVariables(RPRPatternNode *pattern)
 void
 buildDefineVariableList(List *defineClause, List **defineVariableList)
 {
-	ListCell   *lc;
-
 	*defineVariableList = NIL;
 
-	foreach(lc, defineClause)
+	foreach_node(TargetEntry, te, defineClause)
 	{
-		TargetEntry *te = (TargetEntry *) lfirst(lc);
-
 		*defineVariableList = lappend(*defineVariableList,
 									  makeString(pstrdup(te->resname)));
 	}
diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c
index 02898a9106b..74dc486b1f5 100644
--- a/src/backend/optimizer/prep/prepjointree.c
+++ b/src/backend/optimizer/prep/prepjointree.c
@@ -2593,10 +2593,8 @@ perform_pullup_replace_vars(PlannerInfo *root,
 	parse->returningList = (List *)
 		pullup_replace_vars((Node *) parse->returningList, rvcontext);
 
-	foreach(lc, parse->windowClause)
+	foreach_node(WindowClause, wc, parse->windowClause)
 	{
-		WindowClause *wc = lfirst_node(WindowClause, lc);
-
 		if (wc->defineClause != NIL)
 			wc->defineClause = (List *)
 				pullup_replace_vars((Node *) wc->defineClause, rvcontext);
diff --git a/src/backend/parser/parse_cte.c b/src/backend/parser/parse_cte.c
index 0974b43d028..3e493beba0b 100644
--- a/src/backend/parser/parse_cte.c
+++ b/src/backend/parser/parse_cte.c
@@ -182,9 +182,8 @@ transformWithClause(ParseState *pstate, WithClause *withClause)
 		 * rewritten to WITH RECURSIVE by makeRecursiveViewSelect() and so
 		 * flows through here as well.
 		 */
-		foreach(lc, withClause->ctes)
+		foreach_node(CommonTableExpr, cte, withClause->ctes)
 		{
-			CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
 			ContainRPRContext ctx;
 
 			ctx.location = -1;
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index f65a270d20e..0f7207577b3 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -652,12 +652,11 @@ transformColumnRef(ParseState *pstate, ColumnRef *cref)
 		list_length(cref->fields) != 1)
 	{
 		char	   *qualifier = strVal(linitial(cref->fields));
-		ListCell   *lc;
 		bool		is_pattern_var = false;
 
-		foreach(lc, pstate->p_rpr_pattern_vars)
+		foreach_node(String, pv, pstate->p_rpr_pattern_vars)
 		{
-			if (strcmp(strVal(lfirst(lc)), qualifier) == 0)
+			if (strcmp(strVal(pv), qualifier) == 0)
 			{
 				is_pattern_var = true;
 				break;
diff --git a/src/backend/parser/parse_rpr.c b/src/backend/parser/parse_rpr.c
index 4e1d2650cf6..d12a0d45c94 100644
--- a/src/backend/parser/parse_rpr.c
+++ b/src/backend/parser/parse_rpr.c
@@ -208,8 +208,6 @@ static void
 validateRPRPatternVarCount(ParseState *pstate, RPRPatternNode *node,
 						   List *rpDefs, List **varNames)
 {
-	ListCell   *lc;
-
 	/* Pattern node must exist - parser always provides non-NULL root */
 	Assert(node != NULL);
 
@@ -228,9 +226,9 @@ validateRPRPatternVarCount(ParseState *pstate, RPRPatternNode *node,
 			{
 				bool		found = false;
 
-				foreach(lc, *varNames)
+				foreach_node(String, varname, *varNames)
 				{
-					if (strcmp(strVal(lfirst(lc)), node->varName) == 0)
+					if (strcmp(strVal(varname), node->varName) == 0)
 					{
 						found = true;
 						break;
@@ -261,10 +259,9 @@ validateRPRPatternVarCount(ParseState *pstate, RPRPatternNode *node,
 		case RPR_PATTERN_ALT:
 		case RPR_PATTERN_GROUP:
 			/* Recurse into children */
-			foreach(lc, node->children)
+			foreach_node(RPRPatternNode, child, node->children)
 			{
-				validateRPRPatternVarCount(pstate, (RPRPatternNode *) lfirst(lc),
-										   NULL, varNames);
+				validateRPRPatternVarCount(pstate, child, NULL, varNames);
 			}
 			break;
 	}
@@ -277,15 +274,13 @@ validateRPRPatternVarCount(ParseState *pstate, RPRPatternNode *node,
 	 */
 	if (rpDefs)
 	{
-		foreach(lc, rpDefs)
+		foreach_node(ResTarget, rt, rpDefs)
 		{
-			ResTarget  *rt = (ResTarget *) lfirst(lc);
-			ListCell   *lc2;
 			bool		found = false;
 
-			foreach(lc2, *varNames)
+			foreach_node(String, varname, *varNames)
 			{
-				if (strcmp(strVal(lfirst(lc2)), rt->name) == 0)
+				if (strcmp(strVal(varname), rt->name) == 0)
 				{
 					found = true;
 					break;
@@ -327,10 +322,6 @@ static List *
 transformDefineClause(ParseState *pstate, WindowClause *wc, WindowDef *windef,
 					  List **targetlist)
 {
-	ListCell   *lc,
-			   *l;
-	ResTarget  *restarget,
-			   *r;
 	List	   *restargets;
 	List	   *defineClause = NIL;
 	char	   *name;
@@ -357,18 +348,16 @@ transformDefineClause(ParseState *pstate, WindowClause *wc, WindowDef *windef,
 	 * equivalent.
 	 */
 	restargets = NIL;
-	foreach(lc, windef->rpCommonSyntax->rpDefs)
+	foreach_node(ResTarget, restarget, windef->rpCommonSyntax->rpDefs)
 	{
 		TargetEntry *teDefine;
 
-		restarget = (ResTarget *) lfirst(lc);
 		name = restarget->name;
 
-		foreach(l, restargets)
+		foreach_node(ResTarget, r, restargets)
 		{
 			char	   *n;
 
-			r = (ResTarget *) lfirst(l);
 			n = r->name;
 
 			if (!strcmp(n, name))
@@ -394,7 +383,6 @@ transformDefineClause(ParseState *pstate, WindowClause *wc, WindowDef *windef,
 		{
 			Node	   *expr;
 			List	   *vars;
-			ListCell   *lc2;
 
 			expr = transformExpr(pstate, restarget->val,
 								 EXPR_KIND_RPR_DEFINE);
@@ -407,16 +395,12 @@ transformDefineClause(ParseState *pstate, WindowClause *wc, WindowDef *windef,
 			 * evaluation.
 			 */
 			vars = pull_var_clause(expr, 0);
-			foreach(lc2, vars)
+			foreach_node(Var, var, vars)
 			{
-				Var		   *var = (Var *) lfirst(lc2);
 				bool		found = false;
-				ListCell   *tl;
 
-				foreach(tl, *targetlist)
+				foreach_node(TargetEntry, tle, *targetlist)
 				{
-					TargetEntry *tle = (TargetEntry *) lfirst(tl);
-
 					if (IsA(tle->expr, Var) &&
 						((Var *) tle->expr)->varno == var->varno &&
 						((Var *) tle->expr)->varattno == var->varattno)
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index d588cd8263d..415da6417d4 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -7153,7 +7153,6 @@ static void
 get_rule_pattern_node(RPRPatternNode *node, deparse_context *context)
 {
 	StringInfo	buf = context->buf;
-	ListCell   *lc;
 	const char *sep;
 
 	Assert(node != NULL);
@@ -7167,20 +7166,20 @@ get_rule_pattern_node(RPRPatternNode *node, deparse_context *context)
 
 		case RPR_PATTERN_SEQ:
 			sep = "";
-			foreach(lc, node->children)
+			foreach_node(RPRPatternNode, child, node->children)
 			{
 				appendStringInfoString(buf, sep);
-				get_rule_pattern_node((RPRPatternNode *) lfirst(lc), context);
+				get_rule_pattern_node(child, context);
 				sep = " ";
 			}
 			break;
 
 		case RPR_PATTERN_ALT:
 			sep = "";
-			foreach(lc, node->children)
+			foreach_node(RPRPatternNode, child, node->children)
 			{
 				appendStringInfoString(buf, sep);
-				get_rule_pattern_node((RPRPatternNode *) lfirst(lc), context);
+				get_rule_pattern_node(child, context);
 				sep = " | ";
 			}
 			break;
@@ -7188,10 +7187,10 @@ get_rule_pattern_node(RPRPatternNode *node, deparse_context *context)
 		case RPR_PATTERN_GROUP:
 			appendStringInfoChar(buf, '(');
 			sep = "";
-			foreach(lc, node->children)
+			foreach_node(RPRPatternNode, child, node->children)
 			{
 				appendStringInfoString(buf, sep);
-				get_rule_pattern_node((RPRPatternNode *) lfirst(lc), context);
+				get_rule_pattern_node(child, context);
 				sep = " ";
 			}
 			appendStringInfoChar(buf, ')');
@@ -7221,14 +7220,11 @@ get_rule_define(List *defineClause, deparse_context *context)
 {
 	StringInfo	buf = context->buf;
 	const char *sep;
-	ListCell   *lc_def;
 
 	sep = "  ";
 
-	foreach(lc_def, defineClause)
+	foreach_node(TargetEntry, te, defineClause)
 	{
-		TargetEntry *te = (TargetEntry *) lfirst(lc_def);
-
 		appendStringInfo(buf, "%s%s AS ", sep, quote_identifier(te->resname));
 		get_rule_expr((Node *) te->expr, context, false);
 		sep = ",\n  ";
-- 
2.50.1 (Apple Git-155)