LCOV - differential code coverage report
Current view: top level - src/backend/executor - execAmi.c (source / functions) Coverage Total Hit UBC CBC
Current: c38de3ae6098ccf1904109f2e550eb4777f66024 vs e352ac8c5c90ed6ce792f044c22145578542a330 Lines: 80.1 % 291 233 58 233
Current Date: 2026-11-05 14:14:01 +0100 Functions: 100.0 % 7 7 7
Baseline: lcov-20261105-baseline Branches: 71.1 % 152 108 44 108
Baseline Date: 2026-11-05 14:14:01 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(1,7] days: 100.0 % 2 2 2
(360..) days: 79.9 % 289 231 58 231
Function coverage date bins:
(360..) days: 100.0 % 7 7 7
Branch coverage date bins:
(1,7] days: 100.0 % 2 2 2
(360..) days: 70.7 % 150 106 44 106

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * execAmi.c
                                  4                 :                :  *    miscellaneous executor access method routines
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
                                  7                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :                :  *
                                  9                 :                :  *  src/backend/executor/execAmi.c
                                 10                 :                :  *
                                 11                 :                :  *-------------------------------------------------------------------------
                                 12                 :                :  */
                                 13                 :                : #include "postgres.h"
                                 14                 :                : 
                                 15                 :                : #include "access/amapi.h"
                                 16                 :                : #include "access/htup_details.h"
                                 17                 :                : #include "catalog/pg_class.h"
                                 18                 :                : #include "executor/executor.h"
                                 19                 :                : #include "executor/instrument.h"
                                 20                 :                : #include "executor/nodeAgg.h"
                                 21                 :                : #include "executor/nodeAppend.h"
                                 22                 :                : #include "executor/nodeBitmapAnd.h"
                                 23                 :                : #include "executor/nodeBitmapHeapscan.h"
                                 24                 :                : #include "executor/nodeBitmapIndexscan.h"
                                 25                 :                : #include "executor/nodeBitmapOr.h"
                                 26                 :                : #include "executor/nodeCtescan.h"
                                 27                 :                : #include "executor/nodeCustom.h"
                                 28                 :                : #include "executor/nodeForeignscan.h"
                                 29                 :                : #include "executor/nodeFunctionscan.h"
                                 30                 :                : #include "executor/nodeGather.h"
                                 31                 :                : #include "executor/nodeGatherMerge.h"
                                 32                 :                : #include "executor/nodeGroup.h"
                                 33                 :                : #include "executor/nodeHash.h"
                                 34                 :                : #include "executor/nodeHashjoin.h"
                                 35                 :                : #include "executor/nodeIncrementalSort.h"
                                 36                 :                : #include "executor/nodeIndexonlyscan.h"
                                 37                 :                : #include "executor/nodeIndexscan.h"
                                 38                 :                : #include "executor/nodeLimit.h"
                                 39                 :                : #include "executor/nodeLockRows.h"
                                 40                 :                : #include "executor/nodeMaterial.h"
                                 41                 :                : #include "executor/nodeMemoize.h"
                                 42                 :                : #include "executor/nodeMergeAppend.h"
                                 43                 :                : #include "executor/nodeMergejoin.h"
                                 44                 :                : #include "executor/nodeModifyTable.h"
                                 45                 :                : #include "executor/nodeNamedtuplestorescan.h"
                                 46                 :                : #include "executor/nodeNestloop.h"
                                 47                 :                : #include "executor/nodeProjectSet.h"
                                 48                 :                : #include "executor/nodeRecursiveunion.h"
                                 49                 :                : #include "executor/nodeResult.h"
                                 50                 :                : #include "executor/nodeSamplescan.h"
                                 51                 :                : #include "executor/nodeSeqscan.h"
                                 52                 :                : #include "executor/nodeSetOp.h"
                                 53                 :                : #include "executor/nodeSort.h"
                                 54                 :                : #include "executor/nodeSubplan.h"
                                 55                 :                : #include "executor/nodeSubqueryscan.h"
                                 56                 :                : #include "executor/nodeTableFuncscan.h"
                                 57                 :                : #include "executor/nodeTidrangescan.h"
                                 58                 :                : #include "executor/nodeTidscan.h"
                                 59                 :                : #include "executor/nodeUnique.h"
                                 60                 :                : #include "executor/nodeValuesscan.h"
                                 61                 :                : #include "executor/nodeWindowAgg.h"
                                 62                 :                : #include "executor/nodeWorktablescan.h"
                                 63                 :                : #include "nodes/extensible.h"
                                 64                 :                : #include "nodes/pathnodes.h"
                                 65                 :                : #include "utils/syscache.h"
                                 66                 :                : 
                                 67                 :                : static bool IndexSupportsBackwardScan(Oid indexid);
                                 68                 :                : 
                                 69                 :                : 
                                 70                 :                : /*
                                 71                 :                :  * ExecReScan
                                 72                 :                :  *      Reset a plan node so that its output can be re-scanned.
                                 73                 :                :  *
                                 74                 :                :  * Note that if the plan node has parameters that have changed value,
                                 75                 :                :  * the output might be different from last time.
                                 76                 :                :  */
                                 77                 :                : void
 5960 tgl@sss.pgh.pa.us          78                 :CBC     2576989 : ExecReScan(PlanState *node)
                                 79                 :                : {
                                 80                 :                :     /* If collecting timing stats, update them */
 9179                            81         [ +  + ]:        2576989 :     if (node->instrument)
                                 82                 :          28583 :         InstrEndLoop(node->instrument);
                                 83                 :                : 
                                 84                 :                :     /*
                                 85                 :                :      * If we have changed parameters, propagate that info.
                                 86                 :                :      *
                                 87                 :                :      * Note: ExecReScanSetParamPlan() can add bits to node->chgParam,
                                 88                 :                :      * corresponding to the output param(s) that the InitPlan will update.
                                 89                 :                :      * Since we make only one pass over the list, that means that an InitPlan
                                 90                 :                :      * can depend on the output param(s) of a sibling InitPlan only if that
                                 91                 :                :      * sibling appears earlier in the list.  This is workable for now given
                                 92                 :                :      * the limited ways in which one InitPlan could depend on another, but
                                 93                 :                :      * eventually we might need to work harder (or else make the planner
                                 94                 :                :      * enlarge the extParam/allParam sets to include the params of depended-on
                                 95                 :                :      * InitPlans).
                                 96                 :                :      */
 8670                            97         [ +  + ]:        2576989 :     if (node->chgParam != NULL)
                                 98                 :                :     {
                                 99                 :                :         ListCell   *l;
                                100                 :                : 
 8198 neilc@samurai.com         101   [ +  +  +  +  :        2331920 :         foreach(l, node->initPlan)
                                              +  + ]
                                102                 :                :         {
                                103                 :           1331 :             SubPlanState *sstate = (SubPlanState *) lfirst(l);
 8728 tgl@sss.pgh.pa.us         104                 :           1331 :             PlanState  *splan = sstate->planstate;
                                105                 :                : 
 8670                           106         [ +  + ]:           1331 :             if (splan->plan->extParam != NULL)    /* don't care about child
                                107                 :                :                                                  * local Params */
                                108                 :           1174 :                 UpdateChangedParamSet(splan, node->chgParam);
                                109         [ +  + ]:           1331 :             if (splan->chgParam != NULL)
 8728                           110                 :           1014 :                 ExecReScanSetParamPlan(sstate, node);
                                111                 :                :         }
 8198 neilc@samurai.com         112   [ +  +  +  +  :        2371598 :         foreach(l, node->subPlan)
                                              +  + ]
                                113                 :                :         {
                                114                 :          41009 :             SubPlanState *sstate = (SubPlanState *) lfirst(l);
 8728 tgl@sss.pgh.pa.us         115                 :          41009 :             PlanState  *splan = sstate->planstate;
                                116                 :                : 
 8670                           117         [ +  + ]:          41009 :             if (splan->plan->extParam != NULL)
                                118                 :            785 :                 UpdateChangedParamSet(splan, node->chgParam);
                                119                 :                : 
                                120                 :                :             /*
                                121                 :                :              * Mark the hash table stale.  This is tracked per SubPlanState,
                                122                 :                :              * since several of them can share one subplan PlanState.
                                123                 :                :              */
    3 rguo@postgresql.org       124         [ +  + ]:          41009 :             if (splan->chgParam != NULL)
                                125                 :            480 :                 sstate->hashtablestale = true;
                                126                 :                :         }
                                127                 :                :         /* Well. Now set chgParam for child trees. */
 1582 tgl@sss.pgh.pa.us         128         [ +  + ]:        2330589 :         if (outerPlanState(node) != NULL)
                                129                 :        1038062 :             UpdateChangedParamSet(outerPlanState(node), node->chgParam);
                                130         [ +  + ]:        2330589 :         if (innerPlanState(node) != NULL)
                                131                 :          52710 :             UpdateChangedParamSet(innerPlanState(node), node->chgParam);
                                132                 :                :     }
                                133                 :                : 
                                134                 :                :     /* Call expression callbacks */
 8358                           135         [ +  + ]:        2576989 :     if (node->ps_ExprContext)
                                136                 :        2395667 :         ReScanExprContext(node->ps_ExprContext);
                                137                 :                : 
                                138                 :                :     /* And do node-type-specific processing */
10651 bruce@momjian.us          139   [ +  +  -  +  :        2576989 :     switch (nodeTag(node))
                                     +  +  +  +  +  
                                     +  +  +  +  +  
                                     +  +  +  +  +  
                                     +  +  +  +  -  
                                     +  +  -  +  +  
                                     +  +  +  +  +  
                                     +  +  +  +  +  
                                        +  +  +  - ]
                                140                 :                :     {
 8736 tgl@sss.pgh.pa.us         141                 :         108566 :         case T_ResultState:
 5960                           142                 :         108566 :             ExecReScanResult((ResultState *) node);
10492 vadim4o@yahoo.com         143                 :         108566 :             break;
                                144                 :                : 
 3578 andres@anarazel.de        145                 :           9604 :         case T_ProjectSetState:
                                146                 :           9604 :             ExecReScanProjectSet((ProjectSetState *) node);
                                147                 :           9604 :             break;
                                148                 :                : 
 6235 tgl@sss.pgh.pa.us         149                 :UBC           0 :         case T_ModifyTableState:
 5960                           150                 :              0 :             ExecReScanModifyTable((ModifyTableState *) node);
 6235                           151                 :              0 :             break;
                                152                 :                : 
 8736 tgl@sss.pgh.pa.us         153                 :CBC       12481 :         case T_AppendState:
 5960                           154                 :          12481 :             ExecReScanAppend((AppendState *) node);
10492 vadim4o@yahoo.com         155                 :          12481 :             break;
                                156                 :                : 
 5866 tgl@sss.pgh.pa.us         157                 :             12 :         case T_MergeAppendState:
                                158                 :             12 :             ExecReScanMergeAppend((MergeAppendState *) node);
                                159                 :             12 :             break;
                                160                 :                : 
 6606                           161                 :              8 :         case T_RecursiveUnionState:
 5960                           162                 :              8 :             ExecReScanRecursiveUnion((RecursiveUnionState *) node);
 6606                           163                 :              8 :             break;
                                164                 :                : 
 7870                           165                 :             86 :         case T_BitmapAndState:
 5960                           166                 :             86 :             ExecReScanBitmapAnd((BitmapAndState *) node);
 7870                           167                 :             86 :             break;
                                168                 :                : 
                                169                 :              4 :         case T_BitmapOrState:
 5960                           170                 :              4 :             ExecReScanBitmapOr((BitmapOrState *) node);
 7870                           171                 :              4 :             break;
                                172                 :                : 
 8736                           173                 :         659803 :         case T_SeqScanState:
 5960                           174                 :         659803 :             ExecReScanSeqScan((SeqScanState *) node);
 9533                           175                 :         659803 :             break;
                                176                 :                : 
 4192 simon@2ndQuadrant.co      177                 :             65 :         case T_SampleScanState:
                                178                 :             65 :             ExecReScanSampleScan((SampleScanState *) node);
                                179                 :             65 :             break;
                                180                 :                : 
 4054 rhaas@postgresql.org      181                 :            212 :         case T_GatherState:
                                182                 :            212 :             ExecReScanGather((GatherState *) node);
                                183                 :            212 :             break;
                                184                 :                : 
 3369                           185                 :             32 :         case T_GatherMergeState:
                                186                 :             32 :             ExecReScanGatherMerge((GatherMergeState *) node);
                                187                 :             32 :             break;
                                188                 :                : 
 8736 tgl@sss.pgh.pa.us         189                 :         345268 :         case T_IndexScanState:
 5960                           190                 :         345268 :             ExecReScanIndexScan((IndexScanState *) node);
 9533                           191                 :         345268 :             break;
                                192                 :                : 
 5504                           193                 :         143109 :         case T_IndexOnlyScanState:
                                194                 :         143109 :             ExecReScanIndexOnlyScan((IndexOnlyScanState *) node);
                                195                 :         143109 :             break;
                                196                 :                : 
 7870                           197                 :           3130 :         case T_BitmapIndexScanState:
 5960                           198                 :           3130 :             ExecReScanBitmapIndexScan((BitmapIndexScanState *) node);
 7870                           199                 :           3130 :             break;
                                200                 :                : 
                                201                 :           2772 :         case T_BitmapHeapScanState:
 5960                           202                 :           2772 :             ExecReScanBitmapHeapScan((BitmapHeapScanState *) node);
 7870                           203                 :           2772 :             break;
                                204                 :                : 
 8736                           205                 :           7677 :         case T_TidScanState:
 5960                           206                 :           7677 :             ExecReScanTidScan((TidScanState *) node);
 8943                           207                 :           7677 :             break;
                                208                 :                : 
 2077 drowley@postgresql.o      209                 :             80 :         case T_TidRangeScanState:
                                210                 :             80 :             ExecReScanTidRangeScan((TidRangeScanState *) node);
                                211                 :             80 :             break;
                                212                 :                : 
 8736 tgl@sss.pgh.pa.us         213                 :            495 :         case T_SubqueryScanState:
 5960                           214                 :            495 :             ExecReScanSubqueryScan((SubqueryScanState *) node);
10492 vadim4o@yahoo.com         215                 :            495 :             break;
                                216                 :                : 
 8736 tgl@sss.pgh.pa.us         217                 :          73272 :         case T_FunctionScanState:
 5960                           218                 :          73272 :             ExecReScanFunctionScan((FunctionScanState *) node);
10492 vadim4o@yahoo.com         219                 :          73272 :             break;
                                220                 :                : 
 3529 alvherre@alvh.no-ip.      221                 :            344 :         case T_TableFuncScanState:
                                222                 :            344 :             ExecReScanTableFuncScan((TableFuncScanState *) node);
                                223                 :            344 :             break;
                                224                 :                : 
 7400 mail@joeconway.com        225                 :          40262 :         case T_ValuesScanState:
 5960 tgl@sss.pgh.pa.us         226                 :          40262 :             ExecReScanValuesScan((ValuesScanState *) node);
 7400 mail@joeconway.com        227                 :          40262 :             break;
                                228                 :                : 
 6606 tgl@sss.pgh.pa.us         229                 :           5020 :         case T_CteScanState:
 5960                           230                 :           5020 :             ExecReScanCteScan((CteScanState *) node);
 6606                           231                 :           5020 :             break;
                                232                 :                : 
 3506 kgrittn@postgresql.o      233                 :UBC           0 :         case T_NamedTuplestoreScanState:
                                234                 :              0 :             ExecReScanNamedTuplestoreScan((NamedTuplestoreScanState *) node);
                                235                 :              0 :             break;
                                236                 :                : 
 6606 tgl@sss.pgh.pa.us         237                 :CBC        4440 :         case T_WorkTableScanState:
 5960                           238                 :           4440 :             ExecReScanWorkTableScan((WorkTableScanState *) node);
 6606                           239                 :           4440 :             break;
                                240                 :                : 
 5737                           241                 :            448 :         case T_ForeignScanState:
                                242                 :            448 :             ExecReScanForeignScan((ForeignScanState *) node);
                                243                 :            448 :             break;
                                244                 :                : 
 4381 rhaas@postgresql.org      245                 :UBC           0 :         case T_CustomScanState:
                                246                 :              0 :             ExecReScanCustomScan((CustomScanState *) node);
                                247                 :              0 :             break;
                                248                 :                : 
 8736 tgl@sss.pgh.pa.us         249                 :CBC       48927 :         case T_NestLoopState:
 5960                           250                 :          48927 :             ExecReScanNestLoop((NestLoopState *) node);
10492 vadim4o@yahoo.com         251                 :          48927 :             break;
                                252                 :                : 
 8736 tgl@sss.pgh.pa.us         253                 :            596 :         case T_MergeJoinState:
 5960                           254                 :            596 :             ExecReScanMergeJoin((MergeJoinState *) node);
10492 vadim4o@yahoo.com         255                 :            596 :             break;
                                256                 :                : 
 8736 tgl@sss.pgh.pa.us         257                 :           3199 :         case T_HashJoinState:
 5960                           258                 :           3199 :             ExecReScanHashJoin((HashJoinState *) node);
10492 vadim4o@yahoo.com         259                 :           3199 :             break;
                                260                 :                : 
 8736 tgl@sss.pgh.pa.us         261                 :         137168 :         case T_MaterialState:
 5960                           262                 :         137168 :             ExecReScanMaterial((MaterialState *) node);
10339 bruce@momjian.us          263                 :         137168 :             break;
                                264                 :                : 
 1940 drowley@postgresql.o      265                 :         866681 :         case T_MemoizeState:
                                266                 :         866681 :             ExecReScanMemoize((MemoizeState *) node);
 2043                           267                 :         866681 :             break;
                                268                 :                : 
 8736 tgl@sss.pgh.pa.us         269                 :          28417 :         case T_SortState:
 5960                           270                 :          28417 :             ExecReScanSort((SortState *) node);
10492 vadim4o@yahoo.com         271                 :          28417 :             break;
                                272                 :                : 
 2404 tomas.vondra@postgre      273                 :              8 :         case T_IncrementalSortState:
                                274                 :              8 :             ExecReScanIncrementalSort((IncrementalSortState *) node);
                                275                 :              8 :             break;
                                276                 :                : 
 8736 tgl@sss.pgh.pa.us         277                 :             15 :         case T_GroupState:
 5960                           278                 :             15 :             ExecReScanGroup((GroupState *) node);
10482 vadim4o@yahoo.com         279                 :             15 :             break;
                                280                 :                : 
 8736 tgl@sss.pgh.pa.us         281                 :          31533 :         case T_AggState:
 5960                           282                 :          31533 :             ExecReScanAgg((AggState *) node);
 9527                           283                 :          31533 :             break;
                                284                 :                : 
 6521                           285                 :             52 :         case T_WindowAggState:
 5960                           286                 :             52 :             ExecReScanWindowAgg((WindowAggState *) node);
 6521                           287                 :             52 :             break;
                                288                 :                : 
 8736                           289                 :             24 :         case T_UniqueState:
 5960                           290                 :             24 :             ExecReScanUnique((UniqueState *) node);
 9506                           291                 :             24 :             break;
                                292                 :                : 
 8736                           293                 :           1706 :         case T_HashState:
 5960                           294                 :           1706 :             ExecReScanHash((HashState *) node);
10482 vadim4o@yahoo.com         295                 :           1706 :             break;
                                296                 :                : 
 8736 tgl@sss.pgh.pa.us         297                 :            800 :         case T_SetOpState:
 5960                           298                 :            800 :             ExecReScanSetOp((SetOpState *) node);
10478 vadim4o@yahoo.com         299                 :            800 :             break;
                                300                 :                : 
 6233 tgl@sss.pgh.pa.us         301                 :              8 :         case T_LockRowsState:
 5960                           302                 :              8 :             ExecReScanLockRows((LockRowsState *) node);
 6233                           303                 :              8 :             break;
                                304                 :                : 
 8736                           305                 :          40665 :         case T_LimitState:
 5960                           306                 :          40665 :             ExecReScanLimit((LimitState *) node);
10340 bruce@momjian.us          307                 :          40665 :             break;
                                308                 :                : 
10650 bruce@momjian.us          309                 :UBC           0 :         default:
 8508 tgl@sss.pgh.pa.us         310         [ #  # ]:              0 :             elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
                                311                 :                :             break;
                                312                 :                :     }
                                313                 :                : 
 8670 tgl@sss.pgh.pa.us         314         [ +  + ]:CBC     2576989 :     if (node->chgParam != NULL)
                                315                 :                :     {
                                316                 :        2330589 :         bms_free(node->chgParam);
                                317                 :        2330589 :         node->chgParam = NULL;
                                318                 :                :     }
11076 scrappy@hub.org           319                 :        2576989 : }
                                320                 :                : 
                                321                 :                : /*
                                322                 :                :  * ExecMarkPos
                                323                 :                :  *
                                324                 :                :  * Marks the current scan position.
                                325                 :                :  *
                                326                 :                :  * NOTE: mark/restore capability is currently needed only for plan nodes
                                327                 :                :  * that are the immediate inner child of a MergeJoin node.  Since MergeJoin
                                328                 :                :  * requires sorted input, there is never any need to support mark/restore in
                                329                 :                :  * node types that cannot produce sorted output.  There are some cases in
                                330                 :                :  * which a node can pass through sorted data from its child; if we don't
                                331                 :                :  * implement mark/restore for such a node type, the planner compensates by
                                332                 :                :  * inserting a Material node above that node.
                                333                 :                :  */
                                334                 :                : void
 8490 bruce@momjian.us          335                 :         451719 : ExecMarkPos(PlanState *node)
                                336                 :                : {
10651                           337   [ +  +  -  +  :         451719 :     switch (nodeTag(node))
                                           +  -  - ]
                                338                 :                :     {
 8736 tgl@sss.pgh.pa.us         339                 :           4384 :         case T_IndexScanState:
                                340                 :           4384 :             ExecIndexMarkPos((IndexScanState *) node);
10650 bruce@momjian.us          341                 :           4384 :             break;
                                342                 :                : 
 5504 tgl@sss.pgh.pa.us         343                 :          86019 :         case T_IndexOnlyScanState:
                                344                 :          86019 :             ExecIndexOnlyMarkPos((IndexOnlyScanState *) node);
                                345                 :          86019 :             break;
                                346                 :                : 
 4381 rhaas@postgresql.org      347                 :UBC           0 :         case T_CustomScanState:
                                348                 :              0 :             ExecCustomMarkPos((CustomScanState *) node);
                                349                 :              0 :             break;
                                350                 :                : 
 8736 tgl@sss.pgh.pa.us         351                 :CBC        4341 :         case T_MaterialState:
                                352                 :           4341 :             ExecMaterialMarkPos((MaterialState *) node);
 9636                           353                 :           4341 :             break;
                                354                 :                : 
 8736                           355                 :         356975 :         case T_SortState:
                                356                 :         356975 :             ExecSortMarkPos((SortState *) node);
10650 bruce@momjian.us          357                 :         356975 :             break;
                                358                 :                : 
 7203 tgl@sss.pgh.pa.us         359                 :UBC           0 :         case T_ResultState:
                                360                 :              0 :             ExecResultMarkPos((ResultState *) node);
                                361                 :              0 :             break;
                                362                 :                : 
10650 bruce@momjian.us          363                 :              0 :         default:
                                364                 :                :             /* don't make hard error unless caller asks to restore... */
 8508 tgl@sss.pgh.pa.us         365         [ #  # ]:              0 :             elog(DEBUG2, "unrecognized node type: %d", (int) nodeTag(node));
10650 bruce@momjian.us          366                 :              0 :             break;
                                367                 :                :     }
11076 scrappy@hub.org           368                 :CBC      451719 : }
                                369                 :                : 
                                370                 :                : /*
                                371                 :                :  * ExecRestrPos
                                372                 :                :  *
                                373                 :                :  * restores the scan position previously saved with ExecMarkPos()
                                374                 :                :  *
                                375                 :                :  * NOTE: the semantics of this are that the first ExecProcNode following
                                376                 :                :  * the restore operation will yield the same tuple as the first one following
                                377                 :                :  * the mark operation.  It is unspecified what happens to the plan node's
                                378                 :                :  * result TupleTableSlot.  (In most cases the result slot is unchanged by
                                379                 :                :  * a restore, but the node may choose to clear it or to load it with the
                                380                 :                :  * restored-to tuple.)  Hence the caller should discard any previously
                                381                 :                :  * returned TupleTableSlot after doing a restore.
                                382                 :                :  */
                                383                 :                : void
 8490 bruce@momjian.us          384                 :         116457 : ExecRestrPos(PlanState *node)
                                385                 :                : {
10651                           386   [ +  +  -  +  :         116457 :     switch (nodeTag(node))
                                           +  -  - ]
                                387                 :                :     {
 8736 tgl@sss.pgh.pa.us         388                 :          36018 :         case T_IndexScanState:
                                389                 :          36018 :             ExecIndexRestrPos((IndexScanState *) node);
 9599                           390                 :          36018 :             break;
                                391                 :                : 
 5504                           392                 :          16000 :         case T_IndexOnlyScanState:
                                393                 :          16000 :             ExecIndexOnlyRestrPos((IndexOnlyScanState *) node);
                                394                 :          16000 :             break;
                                395                 :                : 
 4381 rhaas@postgresql.org      396                 :UBC           0 :         case T_CustomScanState:
                                397                 :              0 :             ExecCustomRestrPos((CustomScanState *) node);
                                398                 :              0 :             break;
                                399                 :                : 
 8736 tgl@sss.pgh.pa.us         400                 :CBC       36132 :         case T_MaterialState:
                                401                 :          36132 :             ExecMaterialRestrPos((MaterialState *) node);
 9599                           402                 :          36132 :             break;
                                403                 :                : 
 8736                           404                 :          28307 :         case T_SortState:
                                405                 :          28307 :             ExecSortRestrPos((SortState *) node);
 9599                           406                 :          28307 :             break;
                                407                 :                : 
 7203 tgl@sss.pgh.pa.us         408                 :UBC           0 :         case T_ResultState:
                                409                 :              0 :             ExecResultRestrPos((ResultState *) node);
                                410                 :              0 :             break;
                                411                 :                : 
10650 bruce@momjian.us          412                 :              0 :         default:
 8508 tgl@sss.pgh.pa.us         413         [ #  # ]:              0 :             elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node));
                                414                 :                :             break;
                                415                 :                :     }
11076 scrappy@hub.org           416                 :CBC      116457 : }
                                417                 :                : 
                                418                 :                : /*
                                419                 :                :  * ExecSupportsMarkRestore - does a Path support mark/restore?
                                420                 :                :  *
                                421                 :                :  * This is used during planning and so must accept a Path, not a Plan.
                                422                 :                :  * We keep it here to be adjacent to the routines above, which also must
                                423                 :                :  * know which plan types support mark/restore.
                                424                 :                :  */
                                425                 :                : bool
 4381 rhaas@postgresql.org      426                 :           7019 : ExecSupportsMarkRestore(Path *pathnode)
                                427                 :                : {
                                428                 :                :     /*
                                429                 :                :      * For consistency with the routines above, we do not examine the nodeTag
                                430                 :                :      * but rather the pathtype, which is the Plan node type the Path would
                                431                 :                :      * produce.
                                432                 :                :      */
                                433   [ +  -  -  -  :           7019 :     switch (pathnode->pathtype)
                                           +  +  + ]
                                434                 :                :     {
 8741 tgl@sss.pgh.pa.us         435                 :           4714 :         case T_IndexScan:
                                436                 :                :         case T_IndexOnlyScan:
                                437                 :                : 
                                438                 :                :             /*
                                439                 :                :              * Not all index types support mark/restore.
                                440                 :                :              */
 2172 rhodiumtoad@postgres      441                 :           4714 :             return castNode(IndexPath, pathnode)->indexinfo->amcanmarkpos;
                                442                 :                : 
 8741 tgl@sss.pgh.pa.us         443                 :UBC           0 :         case T_Material:
                                444                 :                :         case T_Sort:
                                445                 :              0 :             return true;
                                446                 :                : 
 4368                           447                 :              0 :         case T_CustomScan:
 1948                           448         [ #  # ]:              0 :             if (castNode(CustomPath, pathnode)->flags & CUSTOMPATH_SUPPORT_MARK_RESTORE)
                                449                 :              0 :                 return true;
                                450                 :              0 :             return false;
                                451                 :                : 
 7203                           452                 :              0 :         case T_Result:
                                453                 :                : 
                                454                 :                :             /*
                                455                 :                :              * Result supports mark/restore iff it has a child plan that does.
                                456                 :                :              *
                                457                 :                :              * We have to be careful here because there is more than one Path
                                458                 :                :              * type that can produce a Result plan node.
                                459                 :                :              */
 3895                           460         [ #  # ]:              0 :             if (IsA(pathnode, ProjectionPath))
                                461                 :              0 :                 return ExecSupportsMarkRestore(((ProjectionPath *) pathnode)->subpath);
                                462         [ #  # ]:              0 :             else if (IsA(pathnode, MinMaxAggPath))
                                463                 :              0 :                 return false;   /* childless Result */
 2838                           464         [ #  # ]:              0 :             else if (IsA(pathnode, GroupResultPath))
                                465                 :              0 :                 return false;   /* childless Result */
                                466                 :                :             else
                                467                 :                :             {
                                468                 :                :                 /* Simple RTE_RESULT base relation */
                                469         [ #  # ]:              0 :                 Assert(IsA(pathnode, Path));
 3895                           470                 :              0 :                 return false;   /* childless Result */
                                471                 :                :             }
                                472                 :                : 
 2782 tgl@sss.pgh.pa.us         473                 :CBC         484 :         case T_Append:
                                474                 :                :             {
                                475                 :            484 :                 AppendPath *appendPath = castNode(AppendPath, pathnode);
                                476                 :                : 
                                477                 :                :                 /*
                                478                 :                :                  * If there's exactly one child, then there will be no Append
                                479                 :                :                  * in the final plan, so we can handle mark/restore if the
                                480                 :                :                  * child plan node can.
                                481                 :                :                  */
                                482         [ -  + ]:            484 :                 if (list_length(appendPath->subpaths) == 1)
 2782 tgl@sss.pgh.pa.us         483                 :UBC           0 :                     return ExecSupportsMarkRestore((Path *) linitial(appendPath->subpaths));
                                484                 :                :                 /* Otherwise, Append can't handle it */
 2782 tgl@sss.pgh.pa.us         485                 :CBC         484 :                 return false;
                                486                 :                :             }
                                487                 :                : 
                                488                 :             24 :         case T_MergeAppend:
                                489                 :                :             {
                                490                 :             24 :                 MergeAppendPath *mapath = castNode(MergeAppendPath, pathnode);
                                491                 :                : 
                                492                 :                :                 /*
                                493                 :                :                  * Like the Append case above, single-subpath MergeAppends
                                494                 :                :                  * won't be in the final plan, so just return the child's
                                495                 :                :                  * mark/restore ability.
                                496                 :                :                  */
                                497         [ -  + ]:             24 :                 if (list_length(mapath->subpaths) == 1)
 2782 tgl@sss.pgh.pa.us         498                 :UBC           0 :                     return ExecSupportsMarkRestore((Path *) linitial(mapath->subpaths));
                                499                 :                :                 /* Otherwise, MergeAppend can't handle it */
 2782 tgl@sss.pgh.pa.us         500                 :CBC          24 :                 return false;
                                501                 :                :             }
                                502                 :                : 
 8741                           503                 :           1797 :         default:
                                504                 :           1797 :             break;
                                505                 :                :     }
                                506                 :                : 
                                507                 :           1797 :     return false;
                                508                 :                : }
                                509                 :                : 
                                510                 :                : /*
                                511                 :                :  * ExecSupportsBackwardScan - does a plan type support backwards scanning?
                                512                 :                :  *
                                513                 :                :  * Ideally, all plan types would support backwards scan, but that seems
                                514                 :                :  * unlikely to happen soon.  In some cases, a plan node passes the backwards
                                515                 :                :  * scan down to its children, and so supports backwards scan only if its
                                516                 :                :  * children do.  Therefore, this routine must be passed a complete plan tree.
                                517                 :                :  */
                                518                 :                : bool
 8641                           519                 :           3079 : ExecSupportsBackwardScan(Plan *node)
                                520                 :                : {
                                521         [ -  + ]:           3079 :     if (node == NULL)
 8641 tgl@sss.pgh.pa.us         522                 :UBC           0 :         return false;
                                523                 :                : 
                                524                 :                :     /*
                                525                 :                :      * Parallel-aware nodes return a subset of the tuples in each worker, and
                                526                 :                :      * in general we can't expect to have enough bookkeeping state to know
                                527                 :                :      * which ones we returned in this worker as opposed to some other worker.
                                528                 :                :      */
 4012 rhaas@postgresql.org      529         [ -  + ]:CBC        3079 :     if (node->parallel_aware)
 4012 rhaas@postgresql.org      530                 :UBC           0 :         return false;
                                531                 :                : 
 8641 tgl@sss.pgh.pa.us         532   [ +  +  +  -  :CBC        3079 :     switch (nodeTag(node))
                                     +  +  -  -  +  
                                           +  +  + ]
                                533                 :                :     {
                                534                 :             49 :         case T_Result:
                                535         [ -  + ]:             49 :             if (outerPlan(node) != NULL)
 3577 andres@anarazel.de        536                 :UBC           0 :                 return ExecSupportsBackwardScan(outerPlan(node));
                                537                 :                :             else
 8641 tgl@sss.pgh.pa.us         538                 :CBC          49 :                 return false;
                                539                 :                : 
                                540                 :             32 :         case T_Append:
                                541                 :                :             {
                                542                 :                :                 ListCell   *l;
                                543                 :                : 
                                544                 :                :                 /* With async, tuples may be interleaved, so can't back up. */
 2045 efujita@postgresql.o      545         [ -  + ]:             32 :                 if (((Append *) node)->nasyncplans > 0)
 2045 efujita@postgresql.o      546                 :UBC           0 :                     return false;
                                547                 :                : 
 8494 bruce@momjian.us          548   [ +  -  +  +  :CBC         110 :                 foreach(l, ((Append *) node)->appendplans)
                                              +  + ]
                                549                 :                :                 {
                                550         [ +  + ]:             79 :                     if (!ExecSupportsBackwardScan((Plan *) lfirst(l)))
                                551                 :              1 :                         return false;
                                552                 :                :                 }
                                553                 :                :                 /* need not check tlist because Append doesn't evaluate it */
                                554                 :             31 :                 return true;
                                555                 :                :             }
                                556                 :                : 
 4121 tgl@sss.pgh.pa.us         557                 :              5 :         case T_SampleScan:
                                558                 :                :             /* Simplify life for tablesample methods by disallowing this */
                                559                 :              5 :             return false;
                                560                 :                : 
 4054 rhaas@postgresql.org      561                 :UBC           0 :         case T_Gather:
                                562                 :              0 :             return false;
                                563                 :                : 
 6593 tgl@sss.pgh.pa.us         564                 :CBC         242 :         case T_IndexScan:
 3577 andres@anarazel.de        565                 :            242 :             return IndexSupportsBackwardScan(((IndexScan *) node)->indexid);
                                566                 :                : 
 5504 tgl@sss.pgh.pa.us         567                 :             27 :         case T_IndexOnlyScan:
 3577 andres@anarazel.de        568                 :             27 :             return IndexSupportsBackwardScan(((IndexOnlyScan *) node)->indexid);
                                569                 :                : 
 8641 tgl@sss.pgh.pa.us         570                 :UBC           0 :         case T_SubqueryScan:
 3577 andres@anarazel.de        571                 :              0 :             return ExecSupportsBackwardScan(((SubqueryScan *) node)->subplan);
                                572                 :                : 
 4381 rhaas@postgresql.org      573                 :              0 :         case T_CustomScan:
 1948 tgl@sss.pgh.pa.us         574         [ #  # ]:              0 :             if (((CustomScan *) node)->flags & CUSTOMPATH_SUPPORT_BACKWARD_SCAN)
                                575                 :              0 :                 return true;
 4381 rhaas@postgresql.org      576                 :              0 :             return false;
                                577                 :                : 
 3577 andres@anarazel.de        578                 :CBC        2225 :         case T_SeqScan:
                                579                 :                :         case T_TidScan:
                                580                 :                :         case T_TidRangeScan:
                                581                 :                :         case T_FunctionScan:
                                582                 :                :         case T_ValuesScan:
                                583                 :                :         case T_CteScan:
                                584                 :                :         case T_Material:
                                585                 :                :         case T_Sort:
                                586                 :                :             /* these don't evaluate tlist */
 8641 tgl@sss.pgh.pa.us         587                 :           2225 :             return true;
                                588                 :                : 
 2404 tomas.vondra@postgre      589                 :              2 :         case T_IncrementalSort:
                                590                 :                : 
                                591                 :                :             /*
                                592                 :                :              * Unlike full sort, incremental sort keeps only a single group of
                                593                 :                :              * tuples in memory, so it can't scan backwards.
                                594                 :                :              */
                                595                 :              2 :             return false;
                                596                 :                : 
 6233 tgl@sss.pgh.pa.us         597                 :             83 :         case T_LockRows:
                                598                 :                :         case T_Limit:
 8641                           599                 :             83 :             return ExecSupportsBackwardScan(outerPlan(node));
                                600                 :                : 
                                601                 :            414 :         default:
                                602                 :            414 :             return false;
                                603                 :                :     }
                                604                 :                : }
                                605                 :                : 
                                606                 :                : /*
                                607                 :                :  * An IndexScan or IndexOnlyScan node supports backward scan only if the
                                608                 :                :  * index's AM does.
                                609                 :                :  */
                                610                 :                : static bool
 6593                           611                 :            269 : IndexSupportsBackwardScan(Oid indexid)
                                612                 :                : {
                                613                 :                :     bool        result;
                                614                 :                :     HeapTuple   ht_idxrel;
                                615                 :                :     Form_pg_class idxrelrec;
                                616                 :                :     const IndexAmRoutine *amroutine;
                                617                 :                : 
                                618                 :                :     /* Fetch the pg_class tuple of the index relation */
 6108 rhaas@postgresql.org      619                 :            269 :     ht_idxrel = SearchSysCache1(RELOID, ObjectIdGetDatum(indexid));
 6593 tgl@sss.pgh.pa.us         620         [ -  + ]:            269 :     if (!HeapTupleIsValid(ht_idxrel))
 6593 tgl@sss.pgh.pa.us         621         [ #  # ]:UBC           0 :         elog(ERROR, "cache lookup failed for relation %u", indexid);
 6593 tgl@sss.pgh.pa.us         622                 :CBC         269 :     idxrelrec = (Form_pg_class) GETSTRUCT(ht_idxrel);
                                623                 :                : 
                                624                 :                :     /* Fetch the index AM's API struct */
 3736                           625                 :            269 :     amroutine = GetIndexAmRoutineByAmId(idxrelrec->relam, false);
                                626                 :                : 
 3945                           627                 :            269 :     result = amroutine->amcanbackward;
                                628                 :                : 
 6593                           629                 :            269 :     ReleaseSysCache(ht_idxrel);
                                630                 :                : 
                                631                 :            269 :     return result;
                                632                 :                : }
                                633                 :                : 
                                634                 :                : /*
                                635                 :                :  * ExecMaterializesOutput - does a plan type materialize its output?
                                636                 :                :  *
                                637                 :                :  * Returns true if the plan node type is one that automatically materializes
                                638                 :                :  * its output (typically by keeping it in a tuplestore).  For such plans,
                                639                 :                :  * a rescan without any parameter change will have zero startup cost and
                                640                 :                :  * very low per-tuple cost.
                                641                 :                :  */
                                642                 :                : bool
 6263                           643                 :         527361 : ExecMaterializesOutput(NodeTag plantype)
                                644                 :                : {
                                645         [ +  + ]:         527361 :     switch (plantype)
                                646                 :                :     {
                                647                 :          16889 :         case T_Material:
                                648                 :                :         case T_FunctionScan:
                                649                 :                :         case T_TableFuncScan:
                                650                 :                :         case T_CteScan:
                                651                 :                :         case T_NamedTuplestoreScan:
                                652                 :                :         case T_WorkTableScan:
                                653                 :                :         case T_Sort:
                                654                 :          16889 :             return true;
                                655                 :                : 
                                656                 :         510472 :         default:
                                657                 :         510472 :             break;
                                658                 :                :     }
                                659                 :                : 
                                660                 :         510472 :     return false;
                                661                 :                : }
        

Generated by: LCOV version 2.0-1