I wrote:
> I did find a number of places where getting rid of explicit lnext()
> calls led to just plain cleaner code. Most of these were places that
> could be using forboth() or forthree() and just weren't. There's
> also several places that are crying out for a forfour() macro, so
> I'm not sure why we've stubbornly refused to provide it. I'm a bit
> inclined to just fix those things in the name of code readability,
> independent of this patch.
0001 below does this. I found a couple of places that could use
forfive(), as well. I think this is a clear legibility and
error-proofing win, and we should just push it.
> I also noticed that there's quite a lot of places that are testing
> lnext(cell) for being NULL or not. What that really means is whether
> this cell is last in the list or not, so maybe readability would be
> improved by defining a macro along the lines of list_cell_is_last().
> Any thoughts about that?
0002 below does this. I'm having a hard time deciding whether this
part is a good idea or just code churn. It might be more readable
(especially to newbies) but I can't evaluate that very objectively.
I'm particularly unsure about whether we need two macros; though the
way I initially tried it with just list_cell_is_last() seemed kind of
double-negatively confusing in the places where the test needs to be
not-last. Also, are these macro names too long, and if so what would
be better?
Also: if we accept either or both of these, should we back-patch the
macro additions, so that these new macros will be available for use
in back-patched code? I'm not sure that forfour/forfive have enough
use-cases to worry about that; but the is-last macros would have a
better case for that, I think.
regards, tom lane
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index 47e80ae..832c3e9 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -902,23 +902,12 @@ BuildDescFromLists(List *names, List *types, List *typmods, List *collations)
desc = CreateTemplateTupleDesc(natts);
attnum = 0;
-
- l2 = list_head(types);
- l3 = list_head(typmods);
- l4 = list_head(collations);
- foreach(l1, names)
+ forfour(l1, names, l2, types, l3, typmods, l4, collations)
{
char *attname = strVal(lfirst(l1));
- Oid atttypid;
- int32 atttypmod;
- Oid attcollation;
-
- atttypid = lfirst_oid(l2);
- l2 = lnext(l2);
- atttypmod = lfirst_int(l3);
- l3 = lnext(l3);
- attcollation = lfirst_oid(l4);
- l4 = lnext(l4);
+ Oid atttypid = lfirst_oid(l2);
+ int32 atttypmod = lfirst_int(l3);
+ Oid attcollation = lfirst_oid(l4);
attnum++;
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index db3777d..7cbf9d3 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -1683,7 +1683,6 @@ ExecInitExprRec(Expr *node, ExprState *state,
*l_opfamily,
*l_inputcollid;
ListCell *lc;
- int off;
/*
* Iterate over each field, prepare comparisons. To handle
@@ -1695,20 +1694,11 @@ ExecInitExprRec(Expr *node, ExprState *state,
Assert(list_length(rcexpr->opfamilies) == nopers);
Assert(list_length(rcexpr->inputcollids) == nopers);
- off = 0;
- for (off = 0,
- l_left_expr = list_head(rcexpr->largs),
- l_right_expr = list_head(rcexpr->rargs),
- l_opno = list_head(rcexpr->opnos),
- l_opfamily = list_head(rcexpr->opfamilies),
- l_inputcollid = list_head(rcexpr->inputcollids);
- off < nopers;
- off++,
- l_left_expr = lnext(l_left_expr),
- l_right_expr = lnext(l_right_expr),
- l_opno = lnext(l_opno),
- l_opfamily = lnext(l_opfamily),
- l_inputcollid = lnext(l_inputcollid))
+ forfive(l_left_expr, rcexpr->largs,
+ l_right_expr, rcexpr->rargs,
+ l_opno, rcexpr->opnos,
+ l_opfamily, rcexpr->opfamilies,
+ l_inputcollid, rcexpr->inputcollids)
{
Expr *left_expr = (Expr *) lfirst(l_left_expr);
Expr *right_expr = (Expr *) lfirst(l_right_expr);
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 324356e..8b29437 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -1332,12 +1332,12 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
{
/* (indexkey, indexkey, ...) op (expression, expression, ...) */
RowCompareExpr *rc = (RowCompareExpr *) clause;
- ListCell *largs_cell = list_head(rc->largs);
- ListCell *rargs_cell = list_head(rc->rargs);
- ListCell *opnos_cell = list_head(rc->opnos);
- ListCell *collids_cell = list_head(rc->inputcollids);
ScanKey first_sub_key;
int n_sub_key;
+ ListCell *largs_cell;
+ ListCell *rargs_cell;
+ ListCell *opnos_cell;
+ ListCell *collids_cell;
Assert(!isorderby);
@@ -1346,19 +1346,22 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
n_sub_key = 0;
/* Scan RowCompare columns and generate subsidiary ScanKey items */
- while (opnos_cell != NULL)
+ forfour(largs_cell, rc->largs, rargs_cell, rc->rargs,
+ opnos_cell, rc->opnos, collids_cell, rc->inputcollids)
{
ScanKey this_sub_key = &first_sub_key[n_sub_key];
int flags = SK_ROW_MEMBER;
Datum scanvalue;
Oid inputcollation;
+ leftop = (Expr *) lfirst(largs_cell);
+ rightop = (Expr *) lfirst(rargs_cell);
+ opno = lfirst_oid(opnos_cell);
+ inputcollation = lfirst_oid(collids_cell);
+
/*
* leftop should be the index key Var, possibly relabeled
*/
- leftop = (Expr *) lfirst(largs_cell);
- largs_cell = lnext(largs_cell);
-
if (leftop && IsA(leftop, RelabelType))
leftop = ((RelabelType *) leftop)->arg;
@@ -1374,9 +1377,6 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
* We have to look up the operator's associated btree support
* function
*/
- opno = lfirst_oid(opnos_cell);
- opnos_cell = lnext(opnos_cell);
-
if (index->rd_rel->relam != BTREE_AM_OID ||
varattno < 1 || varattno > indnkeyatts)
elog(ERROR, "bogus RowCompare index qualification");
@@ -1398,15 +1398,9 @@ ExecIndexBuildScanKeys(PlanState *planstate, Relation index,
elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
BTORDER_PROC, op_lefttype, op_righttype, opfamily);
- inputcollation = lfirst_oid(collids_cell);
- collids_cell = lnext(collids_cell);
-
/*
* rightop is the constant or variable comparison value
*/
- rightop = (Expr *) lfirst(rargs_cell);
- rargs_cell = lnext(rargs_cell);
-
if (rightop && IsA(rightop, RelabelType))
rightop = ((RelabelType *) rightop)->arg;
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index c721054..555c91f 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -1680,9 +1680,7 @@ convert_EXISTS_to_ANY(PlannerInfo *root, Query *subselect,
*/
tlist = testlist = paramids = NIL;
resno = 1;
- /* there's no "forfour" so we have to chase one of the lists manually */
- cc = list_head(opcollations);
- forthree(lc, leftargs, rc, rightargs, oc, opids)
+ forfour(lc, leftargs, rc, rightargs, oc, opids, cc, opcollations)
{
Node *leftarg = (Node *) lfirst(lc);
Node *rightarg = (Node *) lfirst(rc);
@@ -1690,7 +1688,6 @@ convert_EXISTS_to_ANY(PlannerInfo *root, Query *subselect,
Oid opcollation = lfirst_oid(cc);
Param *param;
- cc = lnext(cc);
param = generate_new_exec_param(root,
exprType(rightarg),
exprTypmod(rightarg),
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 55eeb51..eb815c2 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -1130,17 +1130,14 @@ generate_setop_tlist(List *colTypes, List *colCollations,
TargetEntry *tle;
Node *expr;
- /* there's no forfour() so we must chase one list manually */
- rtlc = list_head(refnames_tlist);
- forthree(ctlc, colTypes, cclc, colCollations, itlc, input_tlist)
+ forfour(ctlc, colTypes, cclc, colCollations,
+ itlc, input_tlist, rtlc, refnames_tlist)
{
Oid colType = lfirst_oid(ctlc);
Oid colColl = lfirst_oid(cclc);
TargetEntry *inputtle = (TargetEntry *) lfirst(itlc);
TargetEntry *reftle = (TargetEntry *) lfirst(rtlc);
- rtlc = lnext(rtlc);
-
Assert(inputtle->resno == resno);
Assert(reftle->resno == resno);
Assert(!inputtle->resjunk);
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index e3544ef..5efd86e 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -831,18 +831,14 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
*/
rte = pstate->p_target_rangetblentry;
qry->targetList = NIL;
- icols = list_head(icolumns);
- attnos = list_head(attrnos);
- foreach(lc, exprList)
+ Assert(list_length(exprList) <= list_length(icolumns));
+ forthree(lc, exprList, icols, icolumns, attnos, attrnos)
{
Expr *expr = (Expr *) lfirst(lc);
- ResTarget *col;
- AttrNumber attr_num;
+ ResTarget *col = lfirst_node(ResTarget, icols);
+ AttrNumber attr_num = (AttrNumber) lfirst_int(attnos);
TargetEntry *tle;
- col = lfirst_node(ResTarget, icols);
- attr_num = (AttrNumber) lfirst_int(attnos);
-
tle = makeTargetEntry(expr,
attr_num,
col->name,
@@ -851,9 +848,6 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
rte->insertedCols = bms_add_member(rte->insertedCols,
attr_num - FirstLowInvalidHeapAttributeNumber);
-
- icols = lnext(icols);
- attnos = lnext(attnos);
}
/* Process ON CONFLICT, if any. */
@@ -950,19 +944,16 @@ transformInsertRow(ParseState *pstate, List *exprlist,
* Prepare columns for assignment to target table.
*/
result = NIL;
- icols = list_head(icolumns);
- attnos = list_head(attrnos);
- foreach(lc, exprlist)
+ forthree(lc, exprlist, icols, icolumns, attnos, attrnos)
{
Expr *expr = (Expr *) lfirst(lc);
- ResTarget *col;
-
- col = lfirst_node(ResTarget, icols);
+ ResTarget *col = lfirst_node(ResTarget, icols);
+ int attno = lfirst_int(attnos);
expr = transformAssignedExpr(pstate, expr,
EXPR_KIND_INSERT_TARGET,
col->name,
- lfirst_int(attnos),
+ attno,
col->indirection,
col->location);
@@ -991,9 +982,6 @@ transformInsertRow(ParseState *pstate, List *exprlist,
}
result = lappend(result, expr);
-
- icols = lnext(icols);
- attnos = lnext(attnos);
}
return result;
@@ -1699,11 +1687,11 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
qry->targetList = NIL;
targetvars = NIL;
targetnames = NIL;
- left_tlist = list_head(leftmostQuery->targetList);
- forthree(lct, sostmt->colTypes,
- lcm, sostmt->colTypmods,
- lcc, sostmt->colCollations)
+ forfour(lct, sostmt->colTypes,
+ lcm, sostmt->colTypmods,
+ lcc, sostmt->colCollations,
+ left_tlist, leftmostQuery->targetList)
{
Oid colType = lfirst_oid(lct);
int32 colTypmod = lfirst_int(lcm);
@@ -1729,7 +1717,6 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
qry->targetList = lappend(qry->targetList, tle);
targetvars = lappend(targetvars, var);
targetnames = lappend(targetnames, makeString(colName));
- left_tlist = lnext(left_tlist);
}
/*
@@ -2201,10 +2188,9 @@ determineRecursiveColTypes(ParseState *pstate, Node *larg, List *nrtargetlist)
* dummy result expressions of the non-recursive term.
*/
targetList = NIL;
- left_tlist = list_head(leftmostQuery->targetList);
next_resno = 1;
- foreach(nrtl, nrtargetlist)
+ forboth(nrtl, nrtargetlist, left_tlist, leftmostQuery->targetList)
{
TargetEntry *nrtle = (TargetEntry *) lfirst(nrtl);
TargetEntry *lefttle = (TargetEntry *) lfirst(left_tlist);
@@ -2218,7 +2204,6 @@ determineRecursiveColTypes(ParseState *pstate, Node *larg, List *nrtargetlist)
colName,
false);
targetList = lappend(targetList, tle);
- left_tlist = lnext(left_tlist);
}
/* Now build CTE's output column info using dummy targetlist */
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 5222231..654ee80 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -2124,13 +2124,12 @@ LookupFuncWithArgs(ObjectType objtype, ObjectWithArgs *func, bool noError)
FUNC_MAX_ARGS,
FUNC_MAX_ARGS)));
- args_item = list_head(func->objargs);
- for (i = 0; i < argcount; i++)
+ i = 0;
+ foreach(args_item, func->objargs)
{
TypeName *t = (TypeName *) lfirst(args_item);
- argoids[i] = LookupTypeNameOid(NULL, t, noError);
- args_item = lnext(args_item);
+ argoids[i++] = LookupTypeNameOid(NULL, t, noError);
}
/*
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 1258092..85055bb 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -9811,31 +9811,18 @@ get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
ListCell *l5;
int colnum = 0;
- l2 = list_head(tf->coltypes);
- l3 = list_head(tf->coltypmods);
- l4 = list_head(tf->colexprs);
- l5 = list_head(tf->coldefexprs);
-
appendStringInfoString(buf, " COLUMNS ");
- foreach(l1, tf->colnames)
+ forfive(l1, tf->colnames, l2, tf->coltypes, l3, tf->coltypmods,
+ l4, tf->colexprs, l5, tf->coldefexprs)
{
char *colname = strVal(lfirst(l1));
- Oid typid;
- int32 typmod;
- Node *colexpr;
- Node *coldefexpr;
- bool ordinality = tf->ordinalitycol == colnum;
+ Oid typid = lfirst_oid(l2);
+ int32 typmod = lfirst_int(l3);
+ Node *colexpr = (Node *) lfirst(l4);
+ Node *coldefexpr = (Node *) lfirst(l5);
+ bool ordinality = (tf->ordinalitycol == colnum);
bool notnull = bms_is_member(colnum, tf->notnulls);
- typid = lfirst_oid(l2);
- l2 = lnext(l2);
- typmod = lfirst_int(l3);
- l3 = lnext(l3);
- colexpr = (Node *) lfirst(l4);
- l4 = lnext(l4);
- coldefexpr = (Node *) lfirst(l5);
- l5 = lnext(l5);
-
if (colnum > 0)
appendStringInfoString(buf, ", ");
colnum++;
@@ -10349,12 +10336,11 @@ get_from_clause_coldeflist(RangeTblFunction *rtfunc,
appendStringInfoChar(buf, '(');
- /* there's no forfour(), so must chase one list the hard way */
i = 0;
- l4 = list_head(rtfunc->funccolnames);
- forthree(l1, rtfunc->funccoltypes,
- l2, rtfunc->funccoltypmods,
- l3, rtfunc->funccolcollations)
+ forfour(l1, rtfunc->funccoltypes,
+ l2, rtfunc->funccoltypmods,
+ l3, rtfunc->funccolcollations,
+ l4, rtfunc->funccolnames)
{
Oid atttypid = lfirst_oid(l1);
int32 atttypmod = lfirst_int(l2);
@@ -10378,7 +10364,6 @@ get_from_clause_coldeflist(RangeTblFunction *rtfunc,
appendStringInfo(buf, " COLLATE %s",
generate_collation_name(attcollation));
- l4 = lnext(l4);
i++;
}
diff --git a/src/include/nodes/pg_list.h b/src/include/nodes/pg_list.h
index 4624604..8dd22e7 100644
--- a/src/include/nodes/pg_list.h
+++ b/src/include/nodes/pg_list.h
@@ -205,6 +205,32 @@ list_length(const List *l)
(cell1) != NULL && (cell2) != NULL && (cell3) != NULL; \
(cell1) = lnext(cell1), (cell2) = lnext(cell2), (cell3) = lnext(cell3))
+/*
+ * forfour -
+ * the same for four lists
+ */
+#define forfour(cell1, list1, cell2, list2, cell3, list3, cell4, list4) \
+ for ((cell1) = list_head(list1), (cell2) = list_head(list2), \
+ (cell3) = list_head(list3), (cell4) = list_head(list4); \
+ (cell1) != NULL && (cell2) != NULL && \
+ (cell3) != NULL && (cell4) != NULL; \
+ (cell1) = lnext(cell1), (cell2) = lnext(cell2), \
+ (cell3) = lnext(cell3), (cell4) = lnext(cell4))
+
+/*
+ * forfive -
+ * the same for five lists
+ */
+#define forfive(cell1, list1, cell2, list2, cell3, list3, cell4, list4, cell5, list5) \
+ for ((cell1) = list_head(list1), (cell2) = list_head(list2), \
+ (cell3) = list_head(list3), (cell4) = list_head(list4), \
+ (cell5) = list_head(list5); \
+ (cell1) != NULL && (cell2) != NULL && (cell3) != NULL && \
+ (cell4) != NULL && (cell5) != NULL; \
+ (cell1) = lnext(cell1), (cell2) = lnext(cell2), \
+ (cell3) = lnext(cell3), (cell4) = lnext(cell4), \
+ (cell5) = lnext(cell5))
+
extern List *lappend(List *list, void *datum);
extern List *lappend_int(List *list, int datum);
extern List *lappend_oid(List *list, Oid datum);
diff --git a/contrib/postgres_fdw/deparse.c b/contrib/postgres_fdw/deparse.c
index 92a0ab6..e8de6ac 100644
--- a/contrib/postgres_fdw/deparse.c
+++ b/contrib/postgres_fdw/deparse.c
@@ -2617,7 +2617,7 @@ deparseFuncExpr(FuncExpr *node, deparse_expr_cxt *context)
{
if (!first)
appendStringInfoString(buf, ", ");
- if (use_variadic && lnext(arg) == NULL)
+ if (use_variadic && list_cell_is_last(arg))
appendStringInfoString(buf, "VARIADIC ");
deparseExpr((Expr *) lfirst(arg), context);
first = false;
@@ -2945,7 +2945,7 @@ deparseAggref(Aggref *node, deparse_expr_cxt *context)
first = false;
/* Add VARIADIC */
- if (use_variadic && lnext(arg) == NULL)
+ if (use_variadic && list_cell_is_last(arg))
appendStringInfoString(buf, "VARIADIC ");
deparseExpr((Expr *) n, context);
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 1831ea8..c3d898e 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -254,7 +254,7 @@ ExplainQuery(ParseState *pstate, ExplainStmt *stmt, const char *queryString,
queryString, params, queryEnv);
/* Separate plans with an appropriate separator */
- if (lnext(l) != NULL)
+ if (list_cell_is_not_last(l))
ExplainSeparatePlans(es);
}
}
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index a98c836..f7a1333 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -692,7 +692,7 @@ ExplainExecuteQuery(ExecuteStmt *execstmt, IntoClause *into, ExplainState *es,
/* No need for CommandCounterIncrement, as ExplainOnePlan did it */
/* Separate plans with an appropriate separator */
- if (lnext(p) != NULL)
+ if (list_cell_is_not_last(p))
ExplainSeparatePlans(es);
}
diff --git a/src/backend/commands/seclabel.c b/src/backend/commands/seclabel.c
index 9db8228..e0cc3e9 100644
--- a/src/backend/commands/seclabel.c
+++ b/src/backend/commands/seclabel.c
@@ -58,7 +58,7 @@ ExecSecLabelStmt(SecLabelStmt *stmt)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("no security label providers have been loaded")));
- if (lnext(list_head(label_provider_list)) != NULL)
+ if (list_length(label_provider_list) > 1)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("must specify provider when multiple security label providers have been loaded")));
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index 8e5eec2..7c8990a 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -1558,7 +1558,7 @@ serialize_deflist(List *deflist)
appendStringInfoChar(&buf, ch);
}
appendStringInfoChar(&buf, '\'');
- if (lnext(l) != NULL)
+ if (list_cell_is_not_last(l))
appendStringInfoString(&buf, ", ");
}
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 65302fe..7232552 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -218,7 +218,7 @@ _outList(StringInfo str, const List *node)
if (IsA(node, List))
{
outNode(str, lfirst(lc));
- if (lnext(lc))
+ if (list_cell_is_not_last(lc))
appendStringInfoChar(str, ' ');
}
else if (IsA(node, IntList))
diff --git a/src/backend/nodes/print.c b/src/backend/nodes/print.c
index 4b9e141..8fb8634 100644
--- a/src/backend/nodes/print.c
+++ b/src/backend/nodes/print.c
@@ -410,7 +410,7 @@ print_expr(const Node *expr, const List *rtable)
foreach(l, e->args)
{
print_expr(lfirst(l), rtable);
- if (lnext(l))
+ if (list_cell_is_not_last(l))
printf(",");
}
printf(")");
@@ -453,7 +453,7 @@ print_pathkeys(const List *pathkeys, const List *rtable)
print_expr((Node *) mem->em_expr, rtable);
}
printf(")");
- if (lnext(i))
+ if (list_cell_is_not_last(i))
printf(", ");
}
printf(")\n");
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 0debac7..0c14af2 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -3721,7 +3721,7 @@ print_restrictclauses(PlannerInfo *root, List *clauses)
RestrictInfo *c = lfirst(l);
print_expr((Node *) c->clause, root->parse->rtable);
- if (lnext(l))
+ if (list_cell_is_not_last(l))
printf(", ");
}
}
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 3434219..bd94800 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -1558,7 +1558,7 @@ choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths)
/* reject new path, remove it from paths list */
paths = list_delete_cell(paths, lnext(lastcell), lastcell);
}
- Assert(lnext(lastcell) == NULL);
+ Assert(list_cell_is_last(lastcell));
}
/* Keep the cheapest AND-group (or singleton) */
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index bc81535..e6a7d00 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -4581,7 +4581,7 @@ create_one_window_path(PlannerInfo *root,
-1.0);
}
- if (lnext(l))
+ if (list_cell_is_not_last(l))
{
/*
* Add the current WindowFuncs to the output target for this
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index 555c91f..0f8663f 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -565,7 +565,7 @@ build_subplan(PlannerInfo *root, Plan *plan, PlannerInfo *subroot,
{
ptr += sprintf(ptr, "$%d%s",
lfirst_int(lc),
- lnext(lc) ? "," : ")");
+ list_cell_is_not_last(lc) ? "," : ")");
}
}
diff --git a/src/backend/optimizer/util/tlist.c b/src/backend/optimizer/util/tlist.c
index 14d1c67..a5e7207 100644
--- a/src/backend/optimizer/util/tlist.c
+++ b/src/backend/optimizer/util/tlist.c
@@ -997,7 +997,7 @@ split_pathtarget_at_srfs(PlannerInfo *root,
List *level_srfs = (List *) lfirst(lc1);
PathTarget *ntarget;
- if (lnext(lc1) == NULL)
+ if (list_cell_is_last(lc1))
{
ntarget = target;
}
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 0279013..96077ec 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -15509,7 +15509,7 @@ makeColumnRef(char *colname, List *indirection,
else if (IsA(lfirst(l), A_Star))
{
/* We only allow '*' at the end of a ColumnRef */
- if (lnext(l) != NULL)
+ if (list_cell_is_not_last(l))
parser_yyerror("improper use of \"*\"");
}
nfields++;
@@ -15698,7 +15698,7 @@ check_indirection(List *indirection, core_yyscan_t yyscanner)
{
if (IsA(lfirst(l), A_Star))
{
- if (lnext(l) != NULL)
+ if (list_cell_is_not_last(l))
parser_yyerror("improper use of \"*\"");
}
}
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c
index def6c03..ab32e59 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -355,7 +355,7 @@ perform_base_backup(basebackup_options *opt)
*/
if (opt->includewal && ti->path == NULL)
{
- Assert(lnext(lc) == NULL);
+ Assert(list_cell_is_last(lc));
}
else
pq_putemptymessage('c'); /* CopyDone */
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 8b4d94c..82f275e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -1224,7 +1224,7 @@ exec_simple_query(const char *query_string)
PortalDrop(portal, false);
- if (lnext(parsetree_item) == NULL)
+ if (list_cell_is_last(parsetree_item))
{
/*
* If this is the last parsetree of the query string, close down
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index 7f15933..9a31ff1 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -1334,7 +1334,7 @@ PortalRunMulti(Portal portal,
* Increment command counter between queries, but not after the last
* one.
*/
- if (lnext(stmtlist_item) != NULL)
+ if (list_cell_is_not_last(stmtlist_item))
CommandCounterIncrement();
/*
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 6ec795f..3a67d4d 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -1070,7 +1070,7 @@ ProcessUtilitySlow(ParseState *pstate,
}
/* Need CCI between commands */
- if (lnext(l) != NULL)
+ if (list_cell_is_not_last(l))
CommandCounterIncrement();
}
@@ -1151,7 +1151,7 @@ ProcessUtilitySlow(ParseState *pstate,
}
/* Need CCI between commands */
- if (lnext(l) != NULL)
+ if (list_cell_is_not_last(l))
CommandCounterIncrement();
}
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 85055bb..564bd49 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -2722,7 +2722,7 @@ pg_get_functiondef(PG_FUNCTION_ARGS)
char *curname = (char *) lfirst(lc);
simple_quote_literal(&buf, curname);
- if (lnext(lc))
+ if (list_cell_is_not_last(lc))
appendStringInfoString(&buf, ", ");
}
}
@@ -8081,7 +8081,7 @@ get_rule_expr(Node *node, deparse_context *context,
appendStringInfo(buf, "hashed %s", splan->plan_name);
else
appendStringInfoString(buf, splan->plan_name);
- if (lnext(lc))
+ if (list_cell_is_not_last(lc))
appendStringInfoString(buf, " or ");
}
appendStringInfoChar(buf, ')');
@@ -9189,7 +9189,7 @@ get_func_expr(FuncExpr *expr, deparse_context *context,
{
if (nargs++ > 0)
appendStringInfoString(buf, ", ");
- if (use_variadic && lnext(l) == NULL)
+ if (use_variadic && list_cell_is_last(l))
appendStringInfoString(buf, "VARIADIC ");
get_rule_expr((Node *) lfirst(l), context, true);
}
diff --git a/src/include/nodes/pg_list.h b/src/include/nodes/pg_list.h
index 8dd22e7..a35772d 100644
--- a/src/include/nodes/pg_list.h
+++ b/src/include/nodes/pg_list.h
@@ -133,6 +133,9 @@ list_length(const List *l)
#define llast_oid(l) lfirst_oid(list_tail(l))
#define llast_node(type,l) castNode(type, llast(l))
+#define list_cell_is_last(l) (lnext(l) == NULL)
+#define list_cell_is_not_last(l) (lnext(l) != NULL)
+
/*
* Convenience macros for building fixed-length lists
*/