]> granicus.if.org Git - postgresql/commitdiff
Standardize some more loops that chase down parallel lists.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 28 Feb 2019 19:25:01 +0000 (14:25 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 28 Feb 2019 19:25:01 +0000 (14:25 -0500)
We have forboth() and forthree() macros that simplify iterating
through several parallel lists, but not everyplace that could
reasonably use those was doing so.  Also invent forfour() and
forfive() macros to do the same for four or five parallel lists,
and use those where applicable.

The immediate motivation for doing this is to reduce the number
of ad-hoc lnext() calls, to reduce the footprint of a WIP patch.
However, it seems like good cleanup and error-proofing anyway;
the places that were combining forthree() with a manually iterated
loop seem particularly illegible and bug-prone.

There was some speculation about restructuring related parsetree
representations to reduce the need for parallel list chasing of
this sort.  Perhaps that's a win, or perhaps not, but in any case
it would be considerably more invasive than this patch; and it's
not particularly related to my immediate goal of improving the
List infrastructure.  So I'll leave that question for another day.

Patch by me; thanks to David Rowley for review.

Discussion: https://postgr.es/m/11587.1550975080@sss.pgh.pa.us

src/backend/access/common/tupdesc.c
src/backend/executor/execExpr.c
src/backend/executor/nodeIndexscan.c
src/backend/optimizer/plan/subselect.c
src/backend/optimizer/prep/prepunion.c
src/backend/parser/analyze.c
src/backend/parser/parse_func.c
src/backend/utils/adt/ruleutils.c
src/include/nodes/pg_list.h

index 47e80ae1860dee2a6bf55d6f8f9511140d71d003..832c3e9af6c8f322a00cd53d740aafa076fafed0 100644 (file)
@@ -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++;
 
index db3777d15ef4b7b098a87d3889dff677d2e21403..7cbf9d3bc1c786d0ce10fc5e7c9f4486107ac5dc 100644 (file)
@@ -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);
index 324356ec7579cdbf13b66f7610d0141e52617a40..8b294378936ecea15084dfa1bb5a1e04437270ad 100644 (file)
@@ -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;
 
index c721054787286d675104d93bc73c8a7220758954..555c91f61e39882b5335a1f00929e612f6fcf3ab 100644 (file)
@@ -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),
index 55eeb5127cbbce2d334b74971eb2302c2894d045..eb815c2f126d88c09c7935ec3ee7e106dfa9d018 100644 (file)
@@ -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);
index e3544efb6fe574747ad76d55fe68518eaeb8ef29..d6cdd1660739181e9e1bd50646f622105cea5792 100644 (file)
@@ -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 +847,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 +943,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 +981,6 @@ transformInsertRow(ParseState *pstate, List *exprlist,
                }
 
                result = lappend(result, expr);
-
-               icols = lnext(icols);
-               attnos = lnext(attnos);
        }
 
        return result;
@@ -1699,11 +1686,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 +1716,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 +2187,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 +2203,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 */
index 5222231b511821976b4b500e9ee81afc92211973..654ee80b279a5c73532cdc9e43de8baf1beacca7 100644 (file)
@@ -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);
        }
 
        /*
index 1258092dc8c615016621b586b916c77615e63755..85055bbb95a41c94093a9b60b8006dd195b1f48f 100644 (file)
@@ -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++;
        }
 
index 4624604783a6e23dd9cee68e8122deab3eaaa3bf..8dd22e795ef0feed40620a61214c53b2ef2654e2 100644 (file)
@@ -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);