PostgreSQL Source Code git master
execAmi.c File Reference
#include "postgres.h"
#include "access/amapi.h"
#include "access/htup_details.h"
#include "catalog/pg_class.h"
#include "executor/nodeAgg.h"
#include "executor/nodeAppend.h"
#include "executor/nodeBitmapAnd.h"
#include "executor/nodeBitmapHeapscan.h"
#include "executor/nodeBitmapIndexscan.h"
#include "executor/nodeBitmapOr.h"
#include "executor/nodeCtescan.h"
#include "executor/nodeCustom.h"
#include "executor/nodeForeignscan.h"
#include "executor/nodeFunctionscan.h"
#include "executor/nodeGather.h"
#include "executor/nodeGatherMerge.h"
#include "executor/nodeGroup.h"
#include "executor/nodeHash.h"
#include "executor/nodeHashjoin.h"
#include "executor/nodeIncrementalSort.h"
#include "executor/nodeIndexonlyscan.h"
#include "executor/nodeIndexscan.h"
#include "executor/nodeLimit.h"
#include "executor/nodeLockRows.h"
#include "executor/nodeMaterial.h"
#include "executor/nodeMemoize.h"
#include "executor/nodeMergeAppend.h"
#include "executor/nodeMergejoin.h"
#include "executor/nodeModifyTable.h"
#include "executor/nodeNamedtuplestorescan.h"
#include "executor/nodeNestloop.h"
#include "executor/nodeProjectSet.h"
#include "executor/nodeRecursiveunion.h"
#include "executor/nodeResult.h"
#include "executor/nodeSamplescan.h"
#include "executor/nodeSeqscan.h"
#include "executor/nodeSetOp.h"
#include "executor/nodeSort.h"
#include "executor/nodeSubplan.h"
#include "executor/nodeSubqueryscan.h"
#include "executor/nodeTableFuncscan.h"
#include "executor/nodeTidrangescan.h"
#include "executor/nodeTidscan.h"
#include "executor/nodeUnique.h"
#include "executor/nodeValuesscan.h"
#include "executor/nodeWindowAgg.h"
#include "executor/nodeWorktablescan.h"
#include "nodes/extensible.h"
#include "nodes/pathnodes.h"
#include "utils/syscache.h"
Include dependency graph for execAmi.c:

Go to the source code of this file.

Functions

static bool IndexSupportsBackwardScan (Oid indexid)
 
void ExecReScan (PlanState *node)
 
void ExecMarkPos (PlanState *node)
 
void ExecRestrPos (PlanState *node)
 
bool ExecSupportsMarkRestore (Path *pathnode)
 
bool ExecSupportsBackwardScan (Plan *node)
 
bool ExecMaterializesOutput (NodeTag plantype)
 

Function Documentation

◆ ExecMarkPos()

void ExecMarkPos ( PlanState node)

Definition at line 326 of file execAmi.c.

327{
328 switch (nodeTag(node))
329 {
330 case T_IndexScanState:
332 break;
333
334 case T_IndexOnlyScanState:
336 break;
337
338 case T_CustomScanState:
340 break;
341
342 case T_MaterialState:
344 break;
345
346 case T_SortState:
347 ExecSortMarkPos((SortState *) node);
348 break;
349
350 case T_ResultState:
352 break;
353
354 default:
355 /* don't make hard error unless caller asks to restore... */
356 elog(DEBUG2, "unrecognized node type: %d", (int) nodeTag(node));
357 break;
358 }
359}
#define DEBUG2
Definition: elog.h:29
#define elog(elevel,...)
Definition: elog.h:225
void ExecCustomMarkPos(CustomScanState *node)
Definition: nodeCustom.c:139
void ExecIndexOnlyMarkPos(IndexOnlyScanState *node)
void ExecIndexMarkPos(IndexScanState *node)
void ExecMaterialMarkPos(MaterialState *node)
Definition: nodeMaterial.c:262
void ExecResultMarkPos(ResultState *node)
Definition: nodeResult.c:146
void ExecSortMarkPos(SortState *node)
Definition: nodeSort.c:329
#define nodeTag(nodeptr)
Definition: nodes.h:133

References DEBUG2, elog, ExecCustomMarkPos(), ExecIndexMarkPos(), ExecIndexOnlyMarkPos(), ExecMaterialMarkPos(), ExecResultMarkPos(), ExecSortMarkPos(), and nodeTag.

Referenced by ExecMergeJoin(), and ExecResultMarkPos().

◆ ExecMaterializesOutput()

bool ExecMaterializesOutput ( NodeTag  plantype)

Definition at line 635 of file execAmi.c.

636{
637 switch (plantype)
638 {
639 case T_Material:
640 case T_FunctionScan:
641 case T_TableFuncScan:
642 case T_CteScan:
643 case T_NamedTuplestoreScan:
644 case T_WorkTableScan:
645 case T_Sort:
646 return true;
647
648 default:
649 break;
650 }
651
652 return false;
653}

Referenced by build_subplan(), consider_parallel_nestloop(), cost_subplan(), and match_unsorted_outer().

◆ ExecReScan()

void ExecReScan ( PlanState node)

Definition at line 76 of file execAmi.c.

77{
78 /* If collecting timing stats, update them */
79 if (node->instrument)
81
82 /*
83 * If we have changed parameters, propagate that info.
84 *
85 * Note: ExecReScanSetParamPlan() can add bits to node->chgParam,
86 * corresponding to the output param(s) that the InitPlan will update.
87 * Since we make only one pass over the list, that means that an InitPlan
88 * can depend on the output param(s) of a sibling InitPlan only if that
89 * sibling appears earlier in the list. This is workable for now given
90 * the limited ways in which one InitPlan could depend on another, but
91 * eventually we might need to work harder (or else make the planner
92 * enlarge the extParam/allParam sets to include the params of depended-on
93 * InitPlans).
94 */
95 if (node->chgParam != NULL)
96 {
97 ListCell *l;
98
99 foreach(l, node->initPlan)
100 {
101 SubPlanState *sstate = (SubPlanState *) lfirst(l);
102 PlanState *splan = sstate->planstate;
103
104 if (splan->plan->extParam != NULL) /* don't care about child
105 * local Params */
107 if (splan->chgParam != NULL)
108 ExecReScanSetParamPlan(sstate, node);
109 }
110 foreach(l, node->subPlan)
111 {
112 SubPlanState *sstate = (SubPlanState *) lfirst(l);
113 PlanState *splan = sstate->planstate;
114
115 if (splan->plan->extParam != NULL)
117 }
118 /* Well. Now set chgParam for child trees. */
119 if (outerPlanState(node) != NULL)
121 if (innerPlanState(node) != NULL)
123 }
124
125 /* Call expression callbacks */
126 if (node->ps_ExprContext)
128
129 /* And do node-type-specific processing */
130 switch (nodeTag(node))
131 {
132 case T_ResultState:
134 break;
135
136 case T_ProjectSetState:
138 break;
139
140 case T_ModifyTableState:
142 break;
143
144 case T_AppendState:
146 break;
147
148 case T_MergeAppendState:
150 break;
151
152 case T_RecursiveUnionState:
154 break;
155
156 case T_BitmapAndState:
158 break;
159
160 case T_BitmapOrState:
162 break;
163
164 case T_SeqScanState:
166 break;
167
168 case T_SampleScanState:
170 break;
171
172 case T_GatherState:
174 break;
175
176 case T_GatherMergeState:
178 break;
179
180 case T_IndexScanState:
182 break;
183
184 case T_IndexOnlyScanState:
186 break;
187
188 case T_BitmapIndexScanState:
190 break;
191
192 case T_BitmapHeapScanState:
194 break;
195
196 case T_TidScanState:
198 break;
199
200 case T_TidRangeScanState:
202 break;
203
204 case T_SubqueryScanState:
206 break;
207
208 case T_FunctionScanState:
210 break;
211
212 case T_TableFuncScanState:
214 break;
215
216 case T_ValuesScanState:
218 break;
219
220 case T_CteScanState:
222 break;
223
224 case T_NamedTuplestoreScanState:
226 break;
227
228 case T_WorkTableScanState:
230 break;
231
232 case T_ForeignScanState:
234 break;
235
236 case T_CustomScanState:
238 break;
239
240 case T_NestLoopState:
242 break;
243
244 case T_MergeJoinState:
246 break;
247
248 case T_HashJoinState:
250 break;
251
252 case T_MaterialState:
254 break;
255
256 case T_MemoizeState:
258 break;
259
260 case T_SortState:
261 ExecReScanSort((SortState *) node);
262 break;
263
264 case T_IncrementalSortState:
266 break;
267
268 case T_GroupState:
269 ExecReScanGroup((GroupState *) node);
270 break;
271
272 case T_AggState:
273 ExecReScanAgg((AggState *) node);
274 break;
275
276 case T_WindowAggState:
278 break;
279
280 case T_UniqueState:
282 break;
283
284 case T_HashState:
285 ExecReScanHash((HashState *) node);
286 break;
287
288 case T_SetOpState:
289 ExecReScanSetOp((SetOpState *) node);
290 break;
291
292 case T_LockRowsState:
294 break;
295
296 case T_LimitState:
297 ExecReScanLimit((LimitState *) node);
298 break;
299
300 default:
301 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
302 break;
303 }
304
305 if (node->chgParam != NULL)
306 {
307 bms_free(node->chgParam);
308 node->chgParam = NULL;
309 }
310}
void bms_free(Bitmapset *a)
Definition: bitmapset.c:239
#define ERROR
Definition: elog.h:39
void ReScanExprContext(ExprContext *econtext)
Definition: execUtils.c:443
void UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
Definition: execUtils.c:889
#define outerPlanState(node)
Definition: execnodes.h:1237
#define innerPlanState(node)
Definition: execnodes.h:1236
void InstrEndLoop(Instrumentation *instr)
Definition: instrument.c:140
void ExecReScanAgg(AggState *node)
Definition: nodeAgg.c:4357
void ExecReScanAppend(AppendState *node)
Definition: nodeAppend.c:420
void ExecReScanBitmapAnd(BitmapAndState *node)
void ExecReScanBitmapHeapScan(BitmapHeapScanState *node)
void ExecReScanBitmapIndexScan(BitmapIndexScanState *node)
void ExecReScanBitmapOr(BitmapOrState *node)
Definition: nodeBitmapOr.c:219
void ExecReScanCteScan(CteScanState *node)
Definition: nodeCtescan.c:307
void ExecReScanCustomScan(CustomScanState *node)
Definition: nodeCustom.c:132
void ExecReScanForeignScan(ForeignScanState *node)
void ExecReScanFunctionScan(FunctionScanState *node)
void ExecReScanGatherMerge(GatherMergeState *node)
void ExecReScanGather(GatherState *node)
Definition: nodeGather.c:442
void ExecReScanGroup(GroupState *node)
Definition: nodeGroup.c:235
void ExecReScanHash(HashState *node)
Definition: nodeHash.c:2246
void ExecReScanHashJoin(HashJoinState *node)
void ExecReScanIncrementalSort(IncrementalSortState *node)
void ExecReScanIndexOnlyScan(IndexOnlyScanState *node)
void ExecReScanIndexScan(IndexScanState *node)
void ExecReScanLimit(LimitState *node)
Definition: nodeLimit.c:541
void ExecReScanLockRows(LockRowsState *node)
Definition: nodeLockRows.c:394
void ExecReScanMaterial(MaterialState *node)
Definition: nodeMaterial.c:313
void ExecReScanMemoize(MemoizeState *node)
Definition: nodeMemoize.c:1139
void ExecReScanMergeAppend(MergeAppendState *node)
void ExecReScanMergeJoin(MergeJoinState *node)
void ExecReScanModifyTable(ModifyTableState *node)
void ExecReScanNamedTuplestoreScan(NamedTuplestoreScanState *node)
void ExecReScanNestLoop(NestLoopState *node)
Definition: nodeNestloop.c:381
void ExecReScanProjectSet(ProjectSetState *node)
void ExecReScanRecursiveUnion(RecursiveUnionState *node)
void ExecReScanResult(ResultState *node)
Definition: nodeResult.c:249
void ExecReScanSampleScan(SampleScanState *node)
void ExecReScanSeqScan(SeqScanState *node)
Definition: nodeSeqscan.c:212
void ExecReScanSetOp(SetOpState *node)
Definition: nodeSetOp.c:682
void ExecReScanSort(SortState *node)
Definition: nodeSort.c:362
void ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
Definition: nodeSubplan.c:1299
void ExecReScanSubqueryScan(SubqueryScanState *node)
void ExecReScanTableFuncScan(TableFuncScanState *node)
void ExecReScanTidRangeScan(TidRangeScanState *node)
void ExecReScanTidScan(TidScanState *node)
Definition: nodeTidscan.c:447
void ExecReScanUnique(UniqueState *node)
Definition: nodeUnique.c:175
void ExecReScanValuesScan(ValuesScanState *node)
void ExecReScanWindowAgg(WindowAggState *node)
void ExecReScanWorkTableScan(WorkTableScanState *node)
#define lfirst(lc)
Definition: pg_list.h:172
static SPIPlanPtr splan
Definition: regress.c:267
Instrumentation * instrument
Definition: execnodes.h:1151
List * subPlan
Definition: execnodes.h:1168
List * initPlan
Definition: execnodes.h:1166
Bitmapset * chgParam
Definition: execnodes.h:1173
ExprContext * ps_ExprContext
Definition: execnodes.h:1180
struct PlanState * planstate
Definition: execnodes.h:988

References bms_free(), PlanState::chgParam, elog, ERROR, ExecReScanAgg(), ExecReScanAppend(), ExecReScanBitmapAnd(), ExecReScanBitmapHeapScan(), ExecReScanBitmapIndexScan(), ExecReScanBitmapOr(), ExecReScanCteScan(), ExecReScanCustomScan(), ExecReScanForeignScan(), ExecReScanFunctionScan(), ExecReScanGather(), ExecReScanGatherMerge(), ExecReScanGroup(), ExecReScanHash(), ExecReScanHashJoin(), ExecReScanIncrementalSort(), ExecReScanIndexOnlyScan(), ExecReScanIndexScan(), ExecReScanLimit(), ExecReScanLockRows(), ExecReScanMaterial(), ExecReScanMemoize(), ExecReScanMergeAppend(), ExecReScanMergeJoin(), ExecReScanModifyTable(), ExecReScanNamedTuplestoreScan(), ExecReScanNestLoop(), ExecReScanProjectSet(), ExecReScanRecursiveUnion(), ExecReScanResult(), ExecReScanSampleScan(), ExecReScanSeqScan(), ExecReScanSetOp(), ExecReScanSetParamPlan(), ExecReScanSort(), ExecReScanSubqueryScan(), ExecReScanTableFuncScan(), ExecReScanTidRangeScan(), ExecReScanTidScan(), ExecReScanUnique(), ExecReScanValuesScan(), ExecReScanWindowAgg(), ExecReScanWorkTableScan(), PlanState::initPlan, innerPlanState, InstrEndLoop(), PlanState::instrument, lfirst, nodeTag, outerPlanState, SubPlanState::planstate, PlanState::ps_ExprContext, ReScanExprContext(), splan, PlanState::subPlan, and UpdateChangedParamSet().

Referenced by buildSubPlanHash(), ExecAsyncRequest(), ExecIndexOnlyScan(), ExecIndexScan(), ExecNestLoop(), ExecProcNode(), ExecReScanAgg(), ExecReScanAppend(), ExecReScanBitmapAnd(), ExecReScanBitmapHeapScan(), ExecReScanBitmapOr(), ExecReScanForeignScan(), ExecReScanGather(), ExecReScanGatherMerge(), ExecReScanGroup(), ExecReScanHash(), ExecReScanHashJoin(), ExecReScanIncrementalSort(), ExecReScanLimit(), ExecReScanLockRows(), ExecReScanMaterial(), ExecReScanMemoize(), ExecReScanMergeAppend(), ExecReScanMergeJoin(), ExecReScanNestLoop(), ExecReScanProjectSet(), ExecReScanRecursiveUnion(), ExecReScanResult(), ExecReScanSetOp(), ExecReScanSort(), ExecReScanSubqueryScan(), ExecReScanUnique(), ExecReScanWindowAgg(), ExecScanSubPlan(), ExecutorRewind(), MultiExecBitmapIndexScan(), and MultiExecProcNode().

◆ ExecRestrPos()

void ExecRestrPos ( PlanState node)

Definition at line 375 of file execAmi.c.

376{
377 switch (nodeTag(node))
378 {
379 case T_IndexScanState:
381 break;
382
383 case T_IndexOnlyScanState:
385 break;
386
387 case T_CustomScanState:
389 break;
390
391 case T_MaterialState:
393 break;
394
395 case T_SortState:
396 ExecSortRestrPos((SortState *) node);
397 break;
398
399 case T_ResultState:
401 break;
402
403 default:
404 elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
405 break;
406 }
407}
void ExecCustomRestrPos(CustomScanState *node)
Definition: nodeCustom.c:150
void ExecIndexOnlyRestrPos(IndexOnlyScanState *node)
void ExecIndexRestrPos(IndexScanState *node)
void ExecMaterialRestrPos(MaterialState *node)
Definition: nodeMaterial.c:290
void ExecResultRestrPos(ResultState *node)
Definition: nodeResult.c:161
void ExecSortRestrPos(SortState *node)
Definition: nodeSort.c:347

References elog, ERROR, ExecCustomRestrPos(), ExecIndexOnlyRestrPos(), ExecIndexRestrPos(), ExecMaterialRestrPos(), ExecResultRestrPos(), ExecSortRestrPos(), and nodeTag.

Referenced by ExecMergeJoin(), and ExecResultRestrPos().

◆ ExecSupportsBackwardScan()

bool ExecSupportsBackwardScan ( Plan node)

Definition at line 510 of file execAmi.c.

511{
512 if (node == NULL)
513 return false;
514
515 /*
516 * Parallel-aware nodes return a subset of the tuples in each worker, and
517 * in general we can't expect to have enough bookkeeping state to know
518 * which ones we returned in this worker as opposed to some other worker.
519 */
520 if (node->parallel_aware)
521 return false;
522
523 switch (nodeTag(node))
524 {
525 case T_Result:
526 if (outerPlan(node) != NULL)
528 else
529 return false;
530
531 case T_Append:
532 {
533 ListCell *l;
534
535 /* With async, tuples may be interleaved, so can't back up. */
536 if (((Append *) node)->nasyncplans > 0)
537 return false;
538
539 foreach(l, ((Append *) node)->appendplans)
540 {
542 return false;
543 }
544 /* need not check tlist because Append doesn't evaluate it */
545 return true;
546 }
547
548 case T_SampleScan:
549 /* Simplify life for tablesample methods by disallowing this */
550 return false;
551
552 case T_Gather:
553 return false;
554
555 case T_IndexScan:
556 return IndexSupportsBackwardScan(((IndexScan *) node)->indexid);
557
558 case T_IndexOnlyScan:
559 return IndexSupportsBackwardScan(((IndexOnlyScan *) node)->indexid);
560
561 case T_SubqueryScan:
562 return ExecSupportsBackwardScan(((SubqueryScan *) node)->subplan);
563
564 case T_CustomScan:
565 if (((CustomScan *) node)->flags & CUSTOMPATH_SUPPORT_BACKWARD_SCAN)
566 return true;
567 return false;
568
569 case T_SeqScan:
570 case T_TidScan:
571 case T_TidRangeScan:
572 case T_FunctionScan:
573 case T_ValuesScan:
574 case T_CteScan:
575 case T_Material:
576 case T_Sort:
577 /* these don't evaluate tlist */
578 return true;
579
580 case T_IncrementalSort:
581
582 /*
583 * Unlike full sort, incremental sort keeps only a single group of
584 * tuples in memory, so it can't scan backwards.
585 */
586 return false;
587
588 case T_LockRows:
589 case T_Limit:
591
592 default:
593 return false;
594 }
595}
static bool IndexSupportsBackwardScan(Oid indexid)
Definition: execAmi.c:602
bool ExecSupportsBackwardScan(Plan *node)
Definition: execAmi.c:510
#define CUSTOMPATH_SUPPORT_BACKWARD_SCAN
Definition: extensible.h:84
#define outerPlan(node)
Definition: plannodes.h:183
bool parallel_aware
Definition: plannodes.h:141

References CUSTOMPATH_SUPPORT_BACKWARD_SCAN, ExecSupportsBackwardScan(), IndexSupportsBackwardScan(), lfirst, nodeTag, outerPlan, and Plan::parallel_aware.

Referenced by ExecSupportsBackwardScan(), PerformCursorOpen(), SPI_cursor_open_internal(), and standard_planner().

◆ ExecSupportsMarkRestore()

bool ExecSupportsMarkRestore ( Path pathnode)

Definition at line 417 of file execAmi.c.

418{
419 /*
420 * For consistency with the routines above, we do not examine the nodeTag
421 * but rather the pathtype, which is the Plan node type the Path would
422 * produce.
423 */
424 switch (pathnode->pathtype)
425 {
426 case T_IndexScan:
427 case T_IndexOnlyScan:
428
429 /*
430 * Not all index types support mark/restore.
431 */
432 return castNode(IndexPath, pathnode)->indexinfo->amcanmarkpos;
433
434 case T_Material:
435 case T_Sort:
436 return true;
437
438 case T_CustomScan:
440 return true;
441 return false;
442
443 case T_Result:
444
445 /*
446 * Result supports mark/restore iff it has a child plan that does.
447 *
448 * We have to be careful here because there is more than one Path
449 * type that can produce a Result plan node.
450 */
451 if (IsA(pathnode, ProjectionPath))
452 return ExecSupportsMarkRestore(((ProjectionPath *) pathnode)->subpath);
453 else if (IsA(pathnode, MinMaxAggPath))
454 return false; /* childless Result */
455 else if (IsA(pathnode, GroupResultPath))
456 return false; /* childless Result */
457 else
458 {
459 /* Simple RTE_RESULT base relation */
460 Assert(IsA(pathnode, Path));
461 return false; /* childless Result */
462 }
463
464 case T_Append:
465 {
466 AppendPath *appendPath = castNode(AppendPath, pathnode);
467
468 /*
469 * If there's exactly one child, then there will be no Append
470 * in the final plan, so we can handle mark/restore if the
471 * child plan node can.
472 */
473 if (list_length(appendPath->subpaths) == 1)
474 return ExecSupportsMarkRestore((Path *) linitial(appendPath->subpaths));
475 /* Otherwise, Append can't handle it */
476 return false;
477 }
478
479 case T_MergeAppend:
480 {
481 MergeAppendPath *mapath = castNode(MergeAppendPath, pathnode);
482
483 /*
484 * Like the Append case above, single-subpath MergeAppends
485 * won't be in the final plan, so just return the child's
486 * mark/restore ability.
487 */
488 if (list_length(mapath->subpaths) == 1)
489 return ExecSupportsMarkRestore((Path *) linitial(mapath->subpaths));
490 /* Otherwise, MergeAppend can't handle it */
491 return false;
492 }
493
494 default:
495 break;
496 }
497
498 return false;
499}
#define Assert(condition)
Definition: c.h:815
bool ExecSupportsMarkRestore(Path *pathnode)
Definition: execAmi.c:417
#define CUSTOMPATH_SUPPORT_MARK_RESTORE
Definition: extensible.h:85
Datum subpath(PG_FUNCTION_ARGS)
Definition: ltree_op.c:308
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial(l)
Definition: pg_list.h:178
List * subpaths
Definition: pathnodes.h:1944
NodeTag pathtype
Definition: pathnodes.h:1637

References Assert, castNode, CUSTOMPATH_SUPPORT_MARK_RESTORE, ExecSupportsMarkRestore(), IsA, linitial, list_length(), Path::pathtype, subpath(), AppendPath::subpaths, and MergeAppendPath::subpaths.

Referenced by ExecSupportsMarkRestore(), and final_cost_mergejoin().

◆ IndexSupportsBackwardScan()

static bool IndexSupportsBackwardScan ( Oid  indexid)
static

Definition at line 602 of file execAmi.c.

603{
604 bool result;
605 HeapTuple ht_idxrel;
606 Form_pg_class idxrelrec;
607 IndexAmRoutine *amroutine;
608
609 /* Fetch the pg_class tuple of the index relation */
610 ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(indexid));
611 if (!HeapTupleIsValid(ht_idxrel))
612 elog(ERROR, "cache lookup failed for relation %u", indexid);
613 idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
614
615 /* Fetch the index AM's API struct */
616 amroutine = GetIndexAmRoutineByAmId(idxrelrec->relam, false);
617
618 result = amroutine->amcanbackward;
619
620 pfree(amroutine);
621 ReleaseSysCache(ht_idxrel);
622
623 return result;
624}
IndexAmRoutine * GetIndexAmRoutineByAmId(Oid amoid, bool noerror)
Definition: amapi.c:56
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
void pfree(void *pointer)
Definition: mcxt.c:1521
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
bool amcanbackward
Definition: amapi.h:239
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221

References IndexAmRoutine::amcanbackward, elog, ERROR, GetIndexAmRoutineByAmId(), GETSTRUCT, HeapTupleIsValid, ObjectIdGetDatum(), pfree(), ReleaseSysCache(), and SearchSysCache1().

Referenced by ExecSupportsBackwardScan().