LCOV - differential code coverage report
Current view: top level - src/backend/executor - execAmi.c (source / functions) Coverage Total Hit UBC GBC CBC
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 79.0 % 290 229 61 3 226
Current Date: 2025-09-06 07:49:51 +0900 Functions: 100.0 % 7 7 7
Baseline: lcov-20250906-005545-baseline Branches: 70.0 % 150 105 45 1 104
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(360..) days: 79.0 % 290 229 61 3 226
Function coverage date bins:
(360..) days: 100.0 % 7 7 7
Branch coverage date bins:
(360..) days: 70.0 % 150 105 45 1 104

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

Generated by: LCOV version 2.4-beta