diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index 434a1d95f01c1d4c32dbb63765e85eeb1e1ba64f..60cb42b454016e57d33390899337ce8fe38db6cd 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -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 */ diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index fa7d2865c1ec42438b74cfe4bf4125ffd224f441..d36be3c80685ab698be8ffe724eecd64611ee6af 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -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; diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 66fee3ef61d228899766b23a2727d0781628a224..fdd6032b4cb227b39d6fbb04e170671352962d48 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -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); } diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 6fde832227791f41dc4ec7035a5bd5d26be3057c..36015ea6c4b4dcf8163f615c86219e01236492a2 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -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 { diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 51906d68985193667567400aa7a308d6470cd3b7..b70231919febacfd0ceb9be939c07848c2c9c96d 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -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;