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 */