Commit 42466191 authored by Tom Lane's avatar Tom Lane

Fix failure to copy IndexScan.indexorderbyops in copyfuncs.c.

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