Fix failure to copy IndexScan.indexorderbyops in copyfuncs.c.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 18 May 2015 01:22:12 +0000 (21:22 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 18 May 2015 01:22:12 +0000 (21:22 -0400)
This oversight results in a crash at executor startup if the plan has
been copied.  outfuncs.c was missed as well.

While we could probably have taught both those files to cope with the
originally chosen representation of an Oid array, it would have been
painful, not least because there'd be no easy way to verify the array
length.  An Oid List is far easier to work with.  And AFAICS, there is
no particular notational benefit to using an array rather than a list
in the existing parts of the patch either.  So just change it to a list.

Error in commit 35fcb1b3d038a501f3f4c87c05630095abaaadab, which is new,
so no need for back-patch.

src/backend/executor/nodeIndexscan.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/outfuncs.c
src/backend/optimizer/plan/createplan.c
src/include/nodes/plannodes.h

index 434a1d95f01c1d4c32dbb63765e85eeb1e1ba64f..60cb42b454016e57d33390899337ce8fe38db6cd 100644 (file)
@@ -793,7 +793,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
        IndexScanState *indexstate;
        Relation        currentRelation;
        bool            relistarget;
-       int                     i;
 
        /*
         * create state structure
@@ -917,35 +916,40 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
        if (indexstate->iss_NumOrderByKeys > 0)
        {
                int                     numOrderByKeys = indexstate->iss_NumOrderByKeys;
+               int                     i;
+               ListCell   *lc;
 
                /*
                 * Prepare sort support, and look up the distance type for each ORDER
                 * BY expression.
                 */
+               Assert(numOrderByKeys == list_length(node->indexorderbyops));
                indexstate->iss_SortSupport =
                        palloc0(numOrderByKeys * sizeof(SortSupportData));
                indexstate->iss_OrderByTypByVals =
                        palloc(numOrderByKeys * sizeof(bool));
                indexstate->iss_OrderByTypLens =
                        palloc(numOrderByKeys * sizeof(int16));
-               for (i = 0; i < indexstate->iss_NumOrderByKeys; i++)
+               i = 0;
+               foreach(lc, node->indexorderbyops)
                {
+                       Oid orderbyop = lfirst_oid(lc);
                        Oid                     orderbyType;
                        Oid                     opfamily;
                        int16           strategy;
 
-                       PrepareSortSupportFromOrderingOp(node->indexorderbyops[i],
+                       PrepareSortSupportFromOrderingOp(orderbyop,
                                                                                         &indexstate->iss_SortSupport[i]);
 
-                       if (!get_ordering_op_properties(node->indexorderbyops[i],
+                       if (!get_ordering_op_properties(orderbyop,
                                                                                 &opfamily, &orderbyType, &strategy))
-                       {
-                               elog(LOG, "operator %u is not a valid ordering operator",
-                                        node->indexorderbyops[i]);
-                       }
+                               elog(ERROR, "operator %u is not a valid ordering operator",
+                                        orderbyop);
+
                        get_typlenbyval(orderbyType,
                                                        &indexstate->iss_OrderByTypLens[i],
                                                        &indexstate->iss_OrderByTypByVals[i]);
+                       i++;
                }
 
                /* allocate arrays to hold the re-calculated distances */
index fa7d2865c1ec42438b74cfe4bf4125ffd224f441..d36be3c80685ab698be8ffe724eecd64611ee6af 100644 (file)
@@ -381,6 +381,7 @@ _copyIndexScan(const IndexScan *from)
        COPY_NODE_FIELD(indexqualorig);
        COPY_NODE_FIELD(indexorderby);
        COPY_NODE_FIELD(indexorderbyorig);
+       COPY_NODE_FIELD(indexorderbyops);
        COPY_SCALAR_FIELD(indexorderdir);
 
        return newnode;
index 66fee3ef61d228899766b23a2727d0781628a224..fdd6032b4cb227b39d6fbb04e170671352962d48 100644 (file)
@@ -457,6 +457,7 @@ _outIndexScan(StringInfo str, const IndexScan *node)
        WRITE_NODE_FIELD(indexqualorig);
        WRITE_NODE_FIELD(indexorderby);
        WRITE_NODE_FIELD(indexorderbyorig);
+       WRITE_NODE_FIELD(indexorderbyops);
        WRITE_ENUM_FIELD(indexorderdir, ScanDirection);
 }
 
index 6fde832227791f41dc4ec7035a5bd5d26be3057c..36015ea6c4b4dcf8163f615c86219e01236492a2 100644 (file)
@@ -106,7 +106,8 @@ static SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid);
 static SampleScan *make_samplescan(List *qptlist, List *qpqual, Index scanrelid);
 static IndexScan *make_indexscan(List *qptlist, List *qpqual, Index scanrelid,
                           Oid indexid, List *indexqual, List *indexqualorig,
-                          List *indexorderby, List *indexorderbyorig, Oid *indexorderbyops,
+                          List *indexorderby, List *indexorderbyorig,
+                          List *indexorderbyops,
                           ScanDirection indexscandir);
 static IndexOnlyScan *make_indexonlyscan(List *qptlist, List *qpqual,
                                   Index scanrelid, Oid indexid,
@@ -1211,7 +1212,7 @@ create_indexscan_plan(PlannerInfo *root,
        List       *stripped_indexquals;
        List       *fixed_indexquals;
        List       *fixed_indexorderbys;
-       Oid                *indexorderbyops = NULL;
+       List       *indexorderbyops = NIL;
        ListCell   *l;
 
        /* it should be a base rel... */
@@ -1329,37 +1330,31 @@ create_indexscan_plan(PlannerInfo *root,
         */
        if (best_path->path.pathkeys && indexorderbys)
        {
-               int                     numOrderBys = list_length(indexorderbys);
-               int                     i;
                ListCell   *pathkeyCell,
                                   *exprCell;
-               PathKey    *pathkey;
-               Expr       *expr;
-               EquivalenceMember *em;
-
-               indexorderbyops = (Oid *) palloc(numOrderBys * sizeof(Oid));
 
                /*
                 * PathKey contains pointer to the equivalence class, but that's not
                 * enough because we need the expression's datatype to look up the
-                * sort operator in the operator family.  We have to dig the
+                * sort operator in the operator family.  We have to dig out the
                 * equivalence member for the datatype.
                 */
-               i = 0;
-               forboth (pathkeyCell, best_path->path.pathkeys, exprCell, indexorderbys)
+               forboth(pathkeyCell, best_path->path.pathkeys, exprCell, indexorderbys)
                {
-                       pathkey = (PathKey *) lfirst(pathkeyCell);
-                       expr = (Expr *) lfirst(exprCell);
+                       PathKey    *pathkey = (PathKey *) lfirst(pathkeyCell);
+                       Expr       *expr = (Expr *) lfirst(exprCell);
+                       EquivalenceMember *em;
 
                        /* Find equivalence member for the order by expression */
                        em = find_ec_member_for_expr(pathkey->pk_eclass, expr, NULL);
 
                        /* Get sort operator from opfamily */
-                       indexorderbyops[i] = get_opfamily_member(pathkey->pk_opfamily,
-                                                                                                        em->em_datatype,
-                                                                                                        em->em_datatype,
-                                                                                                        pathkey->pk_strategy);
-                       i++;
+                       indexorderbyops =
+                               lappend_oid(indexorderbyops,
+                                                       get_opfamily_member(pathkey->pk_opfamily,
+                                                                                               em->em_datatype,
+                                                                                               em->em_datatype,
+                                                                                               pathkey->pk_strategy));
                }
        }
 
@@ -3457,7 +3452,7 @@ make_indexscan(List *qptlist,
                           List *indexqualorig,
                           List *indexorderby,
                           List *indexorderbyorig,
-                          Oid *indexorderbyops,
+                          List *indexorderbyops,
                           ScanDirection indexscandir)
 {
        IndexScan  *node = makeNode(IndexScan);
@@ -5008,6 +5003,8 @@ make_modifytable(PlannerInfo *root,
                node->onConflictSet = NIL;
                node->onConflictWhere = NULL;
                node->arbiterIndexes = NIL;
+               node->exclRelRTI = 0;
+               node->exclRelTlist = NIL;
        }
        else
        {
index 51906d68985193667567400aa7a308d6470cd3b7..b70231919febacfd0ceb9be939c07848c2c9c96d 100644 (file)
@@ -73,7 +73,6 @@ typedef struct PlannedStmt
        int                     nParamExec;             /* number of PARAM_EXEC Params used */
 
        bool            hasRowSecurity; /* row security applied? */
-
 } PlannedStmt;
 
 /* macro for fetching the Plan associated with a SubPlan node */
@@ -320,10 +319,10 @@ typedef Scan SampleScan;
  * indexorderbyorig is used at runtime to recheck the ordering, if the index
  * cannot calculate an accurate ordering.  It is also needed for EXPLAIN.
  *
- * indexorderbyops is an array of operators used to sort the ORDER BY
- * expressions, used together with indexorderbyorig to recheck ordering at run
- * time.  (Note these fields are used for amcanorderbyop cases, not amcanorder
- * cases.)
+ * indexorderbyops is a list of the OIDs of the operators used to sort the
+ * ORDER BY expressions.  This is used together with indexorderbyorig to
+ * recheck ordering at run time.  (Note that indexorderby, indexorderbyorig,
+ * and indexorderbyops are used for amcanorderbyop cases, not amcanorder.)
  *
  * indexorderdir specifies the scan ordering, for indexscans on amcanorder
  * indexes (for other indexes it should be "don't care").
@@ -337,7 +336,7 @@ typedef struct IndexScan
        List       *indexqualorig;      /* the same in original form */
        List       *indexorderby;       /* list of index ORDER BY exprs */
        List       *indexorderbyorig;           /* the same in original form */
-       Oid                *indexorderbyops;    /* operators to sort ORDER BY exprs */
+       List       *indexorderbyops;    /* OIDs of sort ops for ORDER BY exprs */
        ScanDirection indexorderdir;    /* forward or backward or don't care */
 } IndexScan;