LCOV - differential code coverage report
Current view: top level - src/backend/executor - nodeTidscan.c (source / functions) Coverage Total Hit UBC CBC
Current: a2387c32f2f8a1643c7d71b951587e6bcb2d4744 vs 371a302eecdc82274b0ae2967d18fd726a0aa6a1 Lines: 93.8 % 177 166 11 166
Current Date: 2025-10-26 12:31:50 -0700 Functions: 100.0 % 9 9 9
Baseline: lcov-20251027-010456-baseline Branches: 73.8 % 122 90 32 90
Baseline Date: 2025-10-26 11:01:32 +1300 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 85.7 % 7 6 1 6
(360..) days: 94.1 % 170 160 10 160
Function coverage date bins:
(360..) days: 100.0 % 9 9 9
Branch coverage date bins:
(30,360] days: 50.0 % 4 2 2 2
(360..) days: 74.6 % 118 88 30 88

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * nodeTidscan.c
                                  4                 :                :  *    Routines to support direct tid scans of relations
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
                                  7                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :                :  *
                                  9                 :                :  *
                                 10                 :                :  * IDENTIFICATION
                                 11                 :                :  *    src/backend/executor/nodeTidscan.c
                                 12                 :                :  *
                                 13                 :                :  *-------------------------------------------------------------------------
                                 14                 :                :  */
                                 15                 :                : /*
                                 16                 :                :  * INTERFACE ROUTINES
                                 17                 :                :  *
                                 18                 :                :  *      ExecTidScan         scans a relation using tids
                                 19                 :                :  *      ExecInitTidScan     creates and initializes state info.
                                 20                 :                :  *      ExecReScanTidScan   rescans the tid relation.
                                 21                 :                :  *      ExecEndTidScan      releases all storage.
                                 22                 :                :  */
                                 23                 :                : #include "postgres.h"
                                 24                 :                : 
                                 25                 :                : #include "access/sysattr.h"
                                 26                 :                : #include "access/tableam.h"
                                 27                 :                : #include "catalog/pg_type.h"
                                 28                 :                : #include "executor/executor.h"
                                 29                 :                : #include "executor/nodeTidscan.h"
                                 30                 :                : #include "lib/qunique.h"
                                 31                 :                : #include "miscadmin.h"
                                 32                 :                : #include "nodes/nodeFuncs.h"
                                 33                 :                : #include "utils/array.h"
                                 34                 :                : #include "utils/rel.h"
                                 35                 :                : 
                                 36                 :                : 
                                 37                 :                : /*
                                 38                 :                :  * It's sufficient to check varattno to identify the CTID variable, as any
                                 39                 :                :  * Var in the relation scan qual must be for our table.  (Even if it's a
                                 40                 :                :  * parameterized scan referencing some other table's CTID, the other table's
                                 41                 :                :  * Var would have become a Param by the time it gets here.)
                                 42                 :                :  */
                                 43                 :                : #define IsCTIDVar(node)  \
                                 44                 :                :     ((node) != NULL && \
                                 45                 :                :      IsA((node), Var) && \
                                 46                 :                :      ((Var *) (node))->varattno == SelfItemPointerAttributeNumber)
                                 47                 :                : 
                                 48                 :                : /* one element in tss_tidexprs */
                                 49                 :                : typedef struct TidExpr
                                 50                 :                : {
                                 51                 :                :     ExprState  *exprstate;      /* ExprState for a TID-yielding subexpr */
                                 52                 :                :     bool        isarray;        /* if true, it yields tid[] not just tid */
                                 53                 :                :     CurrentOfExpr *cexpr;       /* alternatively, we can have CURRENT OF */
                                 54                 :                : } TidExpr;
                                 55                 :                : 
                                 56                 :                : static void TidExprListCreate(TidScanState *tidstate);
                                 57                 :                : static void TidListEval(TidScanState *tidstate);
                                 58                 :                : static int  itemptr_comparator(const void *a, const void *b);
                                 59                 :                : static TupleTableSlot *TidNext(TidScanState *node);
                                 60                 :                : 
                                 61                 :                : 
                                 62                 :                : /*
                                 63                 :                :  * Extract the qual subexpressions that yield TIDs to search for,
                                 64                 :                :  * and compile them into ExprStates if they're ordinary expressions.
                                 65                 :                :  *
                                 66                 :                :  * CURRENT OF is a special case that we can't compile usefully;
                                 67                 :                :  * just drop it into the TidExpr list as-is.
                                 68                 :                :  */
                                 69                 :                : static void
 3149 andres@anarazel.de         70                 :CBC         431 : TidExprListCreate(TidScanState *tidstate)
                                 71                 :                : {
                                 72                 :            431 :     TidScan    *node = (TidScan *) tidstate->ss.ps.plan;
                                 73                 :                :     ListCell   *l;
                                 74                 :                : 
                                 75                 :            431 :     tidstate->tss_tidexprs = NIL;
                                 76                 :            431 :     tidstate->tss_isCurrentOf = false;
                                 77                 :                : 
                                 78   [ +  -  +  +  :            876 :     foreach(l, node->tidquals)
                                              +  + ]
                                 79                 :                :     {
                                 80                 :            445 :         Expr       *expr = (Expr *) lfirst(l);
                                 81                 :            445 :         TidExpr    *tidexpr = (TidExpr *) palloc0(sizeof(TidExpr));
                                 82                 :                : 
                                 83         [ +  + ]:            445 :         if (is_opclause(expr))
                                 84                 :                :         {
                                 85                 :                :             Node       *arg1;
                                 86                 :                :             Node       *arg2;
                                 87                 :                : 
                                 88                 :            194 :             arg1 = get_leftop(expr);
                                 89                 :            194 :             arg2 = get_rightop(expr);
                                 90   [ +  -  +  +  :            194 :             if (IsCTIDVar(arg1))
                                              +  - ]
                                 91                 :            170 :                 tidexpr->exprstate = ExecInitExpr((Expr *) arg2,
                                 92                 :                :                                                   &tidstate->ss.ps);
                                 93   [ +  -  +  -  :             24 :             else if (IsCTIDVar(arg2))
                                              +  - ]
                                 94                 :             24 :                 tidexpr->exprstate = ExecInitExpr((Expr *) arg1,
                                 95                 :                :                                                   &tidstate->ss.ps);
                                 96                 :                :             else
 3149 andres@anarazel.de         97         [ #  # ]:UBC           0 :                 elog(ERROR, "could not identify CTID variable");
 3149 andres@anarazel.de         98                 :CBC         194 :             tidexpr->isarray = false;
                                 99                 :                :         }
                                100   [ +  -  +  + ]:            251 :         else if (expr && IsA(expr, ScalarArrayOpExpr))
                                101                 :             25 :         {
                                102                 :             25 :             ScalarArrayOpExpr *saex = (ScalarArrayOpExpr *) expr;
                                103                 :                : 
                                104   [ +  -  +  -  :             25 :             Assert(IsCTIDVar(linitial(saex->args)));
                                              -  + ]
                                105                 :             25 :             tidexpr->exprstate = ExecInitExpr(lsecond(saex->args),
                                106                 :                :                                               &tidstate->ss.ps);
                                107                 :             25 :             tidexpr->isarray = true;
                                108                 :                :         }
                                109   [ +  -  +  - ]:            226 :         else if (expr && IsA(expr, CurrentOfExpr))
                                110                 :            226 :         {
                                111                 :            226 :             CurrentOfExpr *cexpr = (CurrentOfExpr *) expr;
                                112                 :                : 
                                113                 :            226 :             tidexpr->cexpr = cexpr;
                                114                 :            226 :             tidstate->tss_isCurrentOf = true;
                                115                 :                :         }
                                116                 :                :         else
 3149 andres@anarazel.de        117         [ #  # ]:UBC           0 :             elog(ERROR, "could not identify CTID expression");
                                118                 :                : 
 3149 andres@anarazel.de        119                 :CBC         445 :         tidstate->tss_tidexprs = lappend(tidstate->tss_tidexprs, tidexpr);
                                120                 :                :     }
                                121                 :                : 
                                122                 :                :     /* CurrentOfExpr could never appear OR'd with something else */
                                123   [ +  +  -  + ]:            431 :     Assert(list_length(tidstate->tss_tidexprs) == 1 ||
                                124                 :                :            !tidstate->tss_isCurrentOf);
                                125                 :            431 : }
                                126                 :                : 
                                127                 :                : /*
                                128                 :                :  * Compute the list of TIDs to be visited, by evaluating the expressions
                                129                 :                :  * for them.
                                130                 :                :  *
                                131                 :                :  * (The result is actually an array, not a list.)
                                132                 :                :  */
                                133                 :                : static void
                                134                 :            383 : TidListEval(TidScanState *tidstate)
                                135                 :                : {
 8067 tgl@sss.pgh.pa.us         136                 :            383 :     ExprContext *econtext = tidstate->ss.ps.ps_ExprContext;
                                137                 :                :     TableScanDesc scan;
                                138                 :                :     ItemPointerData *tidList;
                                139                 :                :     int         numAllocTids;
                                140                 :                :     int         numTids;
                                141                 :                :     ListCell   *l;
                                142                 :                : 
                                143                 :                :     /*
                                144                 :                :      * Start scan on-demand - initializing a scan isn't free (e.g. heap stats
                                145                 :                :      * the size of the table), so it makes sense to delay that until needed -
                                146                 :                :      * the node might never get executed.
                                147                 :                :      */
 2355 andres@anarazel.de        148         [ +  + ]:            383 :     if (tidstate->ss.ss_currentScanDesc == NULL)
                                149                 :            380 :         tidstate->ss.ss_currentScanDesc =
 2089 fujii@postgresql.org      150                 :            380 :             table_beginscan_tid(tidstate->ss.ss_currentRelation,
 1992 tgl@sss.pgh.pa.us         151                 :            380 :                                 tidstate->ss.ps.state->es_snapshot);
 2355 andres@anarazel.de        152                 :            383 :     scan = tidstate->ss.ss_currentScanDesc;
                                153                 :                : 
                                154                 :                :     /*
                                155                 :                :      * We initialize the array with enough slots for the case that all quals
                                156                 :                :      * are simple OpExprs or CurrentOfExprs.  If there are any
                                157                 :                :      * ScalarArrayOpExprs, we may have to enlarge the array.
                                158                 :                :      */
 3149                           159                 :            383 :     numAllocTids = list_length(tidstate->tss_tidexprs);
                                160                 :                :     tidList = (ItemPointerData *)
 7275 tgl@sss.pgh.pa.us         161                 :            383 :         palloc(numAllocTids * sizeof(ItemPointerData));
                                162                 :            383 :     numTids = 0;
                                163                 :                : 
 3149 andres@anarazel.de        164   [ +  -  +  +  :            744 :     foreach(l, tidstate->tss_tidexprs)
                                              +  + ]
                                165                 :                :     {
                                166                 :            391 :         TidExpr    *tidexpr = (TidExpr *) lfirst(l);
                                167                 :                :         ItemPointer itemptr;
                                168                 :                :         bool        isNull;
                                169                 :                : 
                                170   [ +  +  +  + ]:            391 :         if (tidexpr->exprstate && !tidexpr->isarray)
                                171                 :                :         {
                                172                 :                :             itemptr = (ItemPointer)
                                173                 :            173 :                 DatumGetPointer(ExecEvalExprSwitchContext(tidexpr->exprstate,
                                174                 :                :                                                           econtext,
                                175                 :                :                                                           &isNull));
 2355                           176         [ -  + ]:            173 :             if (isNull)
 2355 andres@anarazel.de        177                 :UBC           0 :                 continue;
                                178                 :                : 
                                179                 :                :             /*
                                180                 :                :              * We silently discard any TIDs that the AM considers invalid
                                181                 :                :              * (E.g. for heap, they could be out of range at the time of scan
                                182                 :                :              * start.  Since we hold at least AccessShareLock on the table, it
                                183                 :                :              * won't be possible for someone to truncate away the blocks we
                                184                 :                :              * intend to visit.).
                                185                 :                :              */
 2355 andres@anarazel.de        186         [ -  + ]:CBC         173 :             if (!table_tuple_tid_valid(scan, itemptr))
 2355 andres@anarazel.de        187                 :UBC           0 :                 continue;
                                188                 :                : 
 2355 andres@anarazel.de        189         [ +  + ]:CBC         173 :             if (numTids >= numAllocTids)
                                190                 :                :             {
                                191                 :              3 :                 numAllocTids *= 2;
                                192                 :                :                 tidList = (ItemPointerData *)
                                193                 :              3 :                     repalloc(tidList,
                                194                 :                :                              numAllocTids * sizeof(ItemPointerData));
                                195                 :                :             }
                                196                 :            173 :             tidList[numTids++] = *itemptr;
                                197                 :                :         }
 3149                           198   [ +  +  +  - ]:            218 :         else if (tidexpr->exprstate && tidexpr->isarray)
 7275 tgl@sss.pgh.pa.us         199                 :             22 :         {
                                200                 :                :             Datum       arraydatum;
                                201                 :                :             ArrayType  *itemarray;
                                202                 :                :             Datum      *ipdatums;
                                203                 :                :             bool       *ipnulls;
                                204                 :                :             int         ndatums;
                                205                 :                :             int         i;
                                206                 :                : 
 3149 andres@anarazel.de        207                 :             22 :             arraydatum = ExecEvalExprSwitchContext(tidexpr->exprstate,
                                208                 :                :                                                    econtext,
                                209                 :                :                                                    &isNull);
 7275 tgl@sss.pgh.pa.us         210         [ -  + ]:             22 :             if (isNull)
 7275 tgl@sss.pgh.pa.us         211                 :UBC           0 :                 continue;
 7275 tgl@sss.pgh.pa.us         212                 :CBC          22 :             itemarray = DatumGetArrayTypeP(arraydatum);
 1214 peter@eisentraut.org      213                 :             22 :             deconstruct_array_builtin(itemarray, TIDOID, &ipdatums, &ipnulls, &ndatums);
 7275 tgl@sss.pgh.pa.us         214         [ +  + ]:             22 :             if (numTids + ndatums > numAllocTids)
                                215                 :                :             {
                                216                 :             19 :                 numAllocTids = numTids + ndatums;
                                217                 :                :                 tidList = (ItemPointerData *)
                                218                 :             19 :                     repalloc(tidList,
                                219                 :                :                              numAllocTids * sizeof(ItemPointerData));
                                220                 :                :             }
                                221         [ +  + ]:             78 :             for (i = 0; i < ndatums; i++)
                                222                 :                :             {
 2355 andres@anarazel.de        223         [ -  + ]:             56 :                 if (ipnulls[i])
 2355 andres@anarazel.de        224                 :UBC           0 :                     continue;
                                225                 :                : 
 2355 andres@anarazel.de        226                 :CBC          56 :                 itemptr = (ItemPointer) DatumGetPointer(ipdatums[i]);
                                227                 :                : 
                                228         [ +  + ]:             56 :                 if (!table_tuple_tid_valid(scan, itemptr))
                                229                 :              9 :                     continue;
                                230                 :                : 
                                231                 :             47 :                 tidList[numTids++] = *itemptr;
                                232                 :                :             }
 7275 tgl@sss.pgh.pa.us         233                 :             22 :             pfree(ipdatums);
                                234                 :             22 :             pfree(ipnulls);
                                235                 :                :         }
                                236                 :                :         else
                                237                 :                :         {
                                238                 :                :             ItemPointerData cursor_tid;
                                239                 :                : 
 3149 andres@anarazel.de        240         [ -  + ]:            196 :             Assert(tidexpr->cexpr);
                                241         [ +  + ]:            166 :             if (execCurrentOf(tidexpr->cexpr, econtext,
 3050 tgl@sss.pgh.pa.us         242                 :            196 :                               RelationGetRelid(tidstate->ss.ss_currentRelation),
                                243                 :                :                               &cursor_tid))
                                244                 :                :             {
 6713                           245         [ -  + ]:            141 :                 if (numTids >= numAllocTids)
                                246                 :                :                 {
 6713 tgl@sss.pgh.pa.us         247                 :UBC           0 :                     numAllocTids *= 2;
                                248                 :                :                     tidList = (ItemPointerData *)
                                249                 :              0 :                         repalloc(tidList,
                                250                 :                :                                  numAllocTids * sizeof(ItemPointerData));
                                251                 :                :                 }
 6713 tgl@sss.pgh.pa.us         252                 :CBC         141 :                 tidList[numTids++] = cursor_tid;
                                253                 :                :             }
                                254                 :                :         }
                                255                 :                :     }
                                256                 :                : 
                                257                 :                :     /*
                                258                 :                :      * Sort the array of TIDs into order, and eliminate duplicates.
                                259                 :                :      * Eliminating duplicates is necessary since we want OR semantics across
                                260                 :                :      * the list.  Sorting makes it easier to detect duplicates, and as a bonus
                                261                 :                :      * ensures that we will visit the heap in the most efficient way.
                                262                 :                :      */
 7275                           263         [ +  + ]:            353 :     if (numTids > 1)
                                264                 :                :     {
                                265                 :                :         /* CurrentOfExpr could never appear OR'd with something else */
 6578                           266         [ -  + ]:             27 :         Assert(!tidstate->tss_isCurrentOf);
                                267                 :                : 
  993 peter@eisentraut.org      268                 :             27 :         qsort(tidList, numTids, sizeof(ItemPointerData),
                                269                 :                :               itemptr_comparator);
 2181 tmunro@postgresql.or      270                 :             27 :         numTids = qunique(tidList, numTids, sizeof(ItemPointerData),
                                271                 :                :                           itemptr_comparator);
                                272                 :                :     }
                                273                 :                : 
 8067 tgl@sss.pgh.pa.us         274                 :            353 :     tidstate->tss_TidList = tidList;
                                275                 :            353 :     tidstate->tss_NumTids = numTids;
                                276                 :            353 :     tidstate->tss_TidPtr = -1;
 9470 bruce@momjian.us          277                 :            353 : }
                                278                 :                : 
                                279                 :                : /*
                                280                 :                :  * qsort comparator for ItemPointerData items
                                281                 :                :  */
                                282                 :                : static int
 7275 tgl@sss.pgh.pa.us         283                 :             71 : itemptr_comparator(const void *a, const void *b)
                                284                 :                : {
                                285                 :             71 :     const ItemPointerData *ipa = (const ItemPointerData *) a;
                                286                 :             71 :     const ItemPointerData *ipb = (const ItemPointerData *) b;
 6963 bruce@momjian.us          287                 :             71 :     BlockNumber ba = ItemPointerGetBlockNumber(ipa);
                                288                 :             71 :     BlockNumber bb = ItemPointerGetBlockNumber(ipb);
 7275 tgl@sss.pgh.pa.us         289                 :             71 :     OffsetNumber oa = ItemPointerGetOffsetNumber(ipa);
                                290                 :             71 :     OffsetNumber ob = ItemPointerGetOffsetNumber(ipb);
                                291                 :                : 
                                292         [ +  + ]:             71 :     if (ba < bb)
                                293                 :              4 :         return -1;
                                294         [ +  + ]:             67 :     if (ba > bb)
                                295                 :              4 :         return 1;
                                296         [ +  + ]:             63 :     if (oa < ob)
                                297                 :             23 :         return -1;
                                298         [ +  + ]:             40 :     if (oa > ob)
                                299                 :             39 :         return 1;
                                300                 :              1 :     return 0;
                                301                 :                : }
                                302                 :                : 
                                303                 :                : /* ----------------------------------------------------------------
                                304                 :                :  *      TidNext
                                305                 :                :  *
                                306                 :                :  *      Retrieve a tuple from the TidScan node's currentRelation
                                307                 :                :  *      using the tids in the TidScanState information.
                                308                 :                :  *
                                309                 :                :  * ----------------------------------------------------------------
                                310                 :                :  */
                                311                 :                : static TupleTableSlot *
 8362                           312                 :            699 : TidNext(TidScanState *node)
                                313                 :                : {
                                314                 :                :     EState     *estate;
                                315                 :                :     ScanDirection direction;
                                316                 :                :     Snapshot    snapshot;
                                317                 :                :     TableScanDesc scan;
                                318                 :                :     Relation    heapRelation;
                                319                 :                :     TupleTableSlot *slot;
                                320                 :                :     ItemPointerData *tidList;
                                321                 :                :     int         numTids;
                                322                 :                :     bool        bBackward;
                                323                 :                : 
                                324                 :                :     /*
                                325                 :                :      * extract necessary information from tid scan node
                                326                 :                :      */
                                327                 :            699 :     estate = node->ss.ps.state;
 9470 bruce@momjian.us          328                 :            699 :     direction = estate->es_direction;
                                329                 :            699 :     snapshot = estate->es_snapshot;
 8362 tgl@sss.pgh.pa.us         330                 :            699 :     heapRelation = node->ss.ss_currentRelation;
                                331                 :            699 :     slot = node->ss.ss_ScanTupleSlot;
                                332                 :                : 
                                333                 :                :     /*
                                334                 :                :      * First time through, compute the list of TIDs to be visited
                                335                 :                :      */
 8067                           336         [ +  + ]:            699 :     if (node->tss_TidList == NULL)
 3149 andres@anarazel.de        337                 :            381 :         TidListEval(node);
                                338                 :                : 
 2355                           339                 :            669 :     scan = node->ss.ss_currentScanDesc;
 8067 tgl@sss.pgh.pa.us         340                 :            669 :     tidList = node->tss_TidList;
                                341                 :            669 :     numTids = node->tss_NumTids;
                                342                 :                : 
                                343                 :                :     /*
                                344                 :                :      * Initialize or advance scan position, depending on direction.
                                345                 :                :      */
 9470 bruce@momjian.us          346                 :            669 :     bBackward = ScanDirectionIsBackward(direction);
                                347         [ +  + ]:            669 :     if (bBackward)
                                348                 :                :     {
 7275 tgl@sss.pgh.pa.us         349         [ -  + ]:              3 :         if (node->tss_TidPtr < 0)
                                350                 :                :         {
                                351                 :                :             /* initialize for backward scan */
 8362 tgl@sss.pgh.pa.us         352                 :UBC           0 :             node->tss_TidPtr = numTids - 1;
                                353                 :                :         }
                                354                 :                :         else
 7275 tgl@sss.pgh.pa.us         355                 :CBC           3 :             node->tss_TidPtr--;
                                356                 :                :     }
                                357                 :                :     else
                                358                 :                :     {
                                359         [ +  + ]:            666 :         if (node->tss_TidPtr < 0)
                                360                 :                :         {
                                361                 :                :             /* initialize for forward scan */
 8362                           362                 :            351 :             node->tss_TidPtr = 0;
                                363                 :                :         }
                                364                 :                :         else
 7275                           365                 :            315 :             node->tss_TidPtr++;
                                366                 :                :     }
                                367                 :                : 
                                368   [ +  -  +  + ]:            691 :     while (node->tss_TidPtr >= 0 && node->tss_TidPtr < numTids)
                                369                 :                :     {
 2408 andres@anarazel.de        370                 :            355 :         ItemPointerData tid = tidList[node->tss_TidPtr];
                                371                 :                : 
                                372                 :                :         /*
                                373                 :                :          * For WHERE CURRENT OF, the tuple retrieved from the cursor might
                                374                 :                :          * since have been updated; if so, we should fetch the version that is
                                375                 :                :          * current according to our snapshot.
                                376                 :                :          */
 6578 tgl@sss.pgh.pa.us         377         [ +  + ]:            355 :         if (node->tss_isCurrentOf)
 2349 andres@anarazel.de        378                 :            141 :             table_tuple_get_latest_tid(scan, &tid);
                                379                 :                : 
                                380         [ +  + ]:            355 :         if (table_tuple_fetch_row_version(heapRelation, &tid, snapshot, slot))
 7275 tgl@sss.pgh.pa.us         381                 :            324 :             return slot;
                                382                 :                : 
                                383                 :                :         /* Bad TID or failed snapshot qual; try next */
 9470 bruce@momjian.us          384         [ -  + ]:             22 :         if (bBackward)
 8362 tgl@sss.pgh.pa.us         385                 :UBC           0 :             node->tss_TidPtr--;
                                386                 :                :         else
 8362 tgl@sss.pgh.pa.us         387                 :CBC          22 :             node->tss_TidPtr++;
                                388                 :                : 
 3016 andres@anarazel.de        389         [ -  + ]:             22 :         CHECK_FOR_INTERRUPTS();
                                390                 :                :     }
                                391                 :                : 
                                392                 :                :     /*
                                393                 :                :      * if we get here it means the tid scan failed so we are at the end of the
                                394                 :                :      * scan..
                                395                 :                :      */
 9470 bruce@momjian.us          396                 :            336 :     return ExecClearTuple(slot);
                                397                 :                : }
                                398                 :                : 
                                399                 :                : /*
                                400                 :                :  * TidRecheck -- access method routine to recheck a tuple in EvalPlanQual
                                401                 :                :  */
                                402                 :                : static bool
 5845 tgl@sss.pgh.pa.us         403                 :              2 : TidRecheck(TidScanState *node, TupleTableSlot *slot)
                                404                 :                : {
                                405                 :                :     ItemPointer match;
                                406                 :                : 
                                407                 :                :     /* WHERE CURRENT OF always intends to resolve to the latest tuple */
   40 drowley@postgresql.o      408         [ -  + ]:              2 :     if (node->tss_isCurrentOf)
   40 drowley@postgresql.o      409                 :UBC           0 :         return true;
                                410                 :                : 
   40 drowley@postgresql.o      411         [ +  - ]:CBC           2 :     if (node->tss_TidList == NULL)
                                412                 :              2 :         TidListEval(node);
                                413                 :                : 
                                414                 :                :     /*
                                415                 :                :      * Binary search the TidList to see if this ctid is mentioned and return
                                416                 :                :      * true if it is.
                                417                 :                :      */
                                418                 :              2 :     match = (ItemPointer) bsearch(&slot->tts_tid, node->tss_TidList,
                                419                 :              2 :                                   node->tss_NumTids, sizeof(ItemPointerData),
                                420                 :                :                                   itemptr_comparator);
                                421                 :              2 :     return match != NULL;
                                422                 :                : }
                                423                 :                : 
                                424                 :                : 
                                425                 :                : /* ----------------------------------------------------------------
                                426                 :                :  *      ExecTidScan(node)
                                427                 :                :  *
                                428                 :                :  *      Scans the relation using tids and returns
                                429                 :                :  *         the next qualifying tuple in the direction specified.
                                430                 :                :  *      We call the ExecScan() routine and pass it the appropriate
                                431                 :                :  *      access method functions.
                                432                 :                :  *
                                433                 :                :  *      Conditions:
                                434                 :                :  *        -- the "cursor" maintained by the AMI is positioned at the tuple
                                435                 :                :  *           returned previously.
                                436                 :                :  *
                                437                 :                :  *      Initial States:
                                438                 :                :  *        -- the relation indicated is opened for scanning so that the
                                439                 :                :  *           "cursor" is positioned before the first qualifying tuple.
                                440                 :                :  *        -- tss_TidPtr is -1.
                                441                 :                :  * ----------------------------------------------------------------
                                442                 :                :  */
                                443                 :                : static TupleTableSlot *
 3024 andres@anarazel.de        444                 :            692 : ExecTidScan(PlanState *pstate)
                                445                 :                : {
                                446                 :            692 :     TidScanState *node = castNode(TidScanState, pstate);
                                447                 :                : 
 5845 tgl@sss.pgh.pa.us         448                 :            692 :     return ExecScan(&node->ss,
                                449                 :                :                     (ExecScanAccessMtd) TidNext,
                                450                 :                :                     (ExecScanRecheckMtd) TidRecheck);
                                451                 :                : }
                                452                 :                : 
                                453                 :                : /* ----------------------------------------------------------------
                                454                 :                :  *      ExecReScanTidScan(node)
                                455                 :                :  * ----------------------------------------------------------------
                                456                 :                :  */
                                457                 :                : void
 5586                           458                 :              9 : ExecReScanTidScan(TidScanState *node)
                                459                 :                : {
 8067                           460         [ +  + ]:              9 :     if (node->tss_TidList)
                                461                 :              3 :         pfree(node->tss_TidList);
                                462                 :              9 :     node->tss_TidList = NULL;
                                463                 :              9 :     node->tss_NumTids = 0;
 8362                           464                 :              9 :     node->tss_TidPtr = -1;
                                465                 :                : 
                                466                 :                :     /* not really necessary, but seems good form */
 2355 andres@anarazel.de        467         [ +  + ]:              9 :     if (node->ss.ss_currentScanDesc)
                                468                 :              3 :         table_rescan(node->ss.ss_currentScanDesc, NULL);
                                469                 :                : 
 5845 tgl@sss.pgh.pa.us         470                 :              9 :     ExecScanReScan(&node->ss);
 9470 bruce@momjian.us          471                 :              9 : }
                                472                 :                : 
                                473                 :                : /* ----------------------------------------------------------------
                                474                 :                :  *      ExecEndTidScan
                                475                 :                :  *
                                476                 :                :  *      Releases any storage allocated through C routines.
                                477                 :                :  *      Returns nothing.
                                478                 :                :  * ----------------------------------------------------------------
                                479                 :                :  */
                                480                 :                : void
 8362 tgl@sss.pgh.pa.us         481                 :            359 : ExecEndTidScan(TidScanState *node)
                                482                 :                : {
 2355 andres@anarazel.de        483         [ +  + ]:            359 :     if (node->ss.ss_currentScanDesc)
                                484                 :            332 :         table_endscan(node->ss.ss_currentScanDesc);
 9470 bruce@momjian.us          485                 :            359 : }
                                486                 :                : 
                                487                 :                : /* ----------------------------------------------------------------
                                488                 :                :  *      ExecInitTidScan
                                489                 :                :  *
                                490                 :                :  *      Initializes the tid scan's state information, creates
                                491                 :                :  *      scan keys, and opens the base and tid relations.
                                492                 :                :  *
                                493                 :                :  *      Parameters:
                                494                 :                :  *        node: TidScan node produced by the planner.
                                495                 :                :  *        estate: the execution state initialized in InitPlan.
                                496                 :                :  * ----------------------------------------------------------------
                                497                 :                :  */
                                498                 :                : TidScanState *
 7181 tgl@sss.pgh.pa.us         499                 :            431 : ExecInitTidScan(TidScan *node, EState *estate, int eflags)
                                500                 :                : {
                                501                 :                :     TidScanState *tidstate;
                                502                 :                :     Relation    currentRelation;
                                503                 :                : 
                                504                 :                :     /*
                                505                 :                :      * create state structure
                                506                 :                :      */
 8362                           507                 :            431 :     tidstate = makeNode(TidScanState);
                                508                 :            431 :     tidstate->ss.ps.plan = (Plan *) node;
                                509                 :            431 :     tidstate->ss.ps.state = estate;
 3024 andres@anarazel.de        510                 :            431 :     tidstate->ss.ps.ExecProcNode = ExecTidScan;
                                511                 :                : 
                                512                 :                :     /*
                                513                 :                :      * Miscellaneous initialization
                                514                 :                :      *
                                515                 :                :      * create expression context for node
                                516                 :                :      */
 8362 tgl@sss.pgh.pa.us         517                 :            431 :     ExecAssignExprContext(estate, &tidstate->ss.ps);
                                518                 :                : 
                                519                 :                :     /*
                                520                 :                :      * mark tid list as not computed yet
                                521                 :                :      */
 8067                           522                 :            431 :     tidstate->tss_TidList = NULL;
                                523                 :            431 :     tidstate->tss_NumTids = 0;
                                524                 :            431 :     tidstate->tss_TidPtr = -1;
                                525                 :                : 
                                526                 :                :     /*
                                527                 :                :      * open the scan relation
                                528                 :                :      */
 4566                           529                 :            431 :     currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags);
                                530                 :                : 
 8362                           531                 :            431 :     tidstate->ss.ss_currentRelation = currentRelation;
 3050                           532                 :            431 :     tidstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
                                533                 :                : 
                                534                 :                :     /*
                                535                 :                :      * get the scan type from the relation descriptor.
                                536                 :                :      */
 2810 andres@anarazel.de        537                 :            431 :     ExecInitScanTupleSlot(estate, &tidstate->ss,
                                538                 :                :                           RelationGetDescr(currentRelation),
                                539                 :                :                           table_slot_callbacks(currentRelation));
                                540                 :                : 
                                541                 :                :     /*
                                542                 :                :      * Initialize result type and projection.
                                543                 :                :      */
 2544                           544                 :            431 :     ExecInitResultTypeTL(&tidstate->ss.ps);
 8302 tgl@sss.pgh.pa.us         545                 :            431 :     ExecAssignScanProjectionInfo(&tidstate->ss);
                                546                 :                : 
                                547                 :                :     /*
                                548                 :                :      * initialize child expressions
                                549                 :                :      */
 2810 andres@anarazel.de        550                 :            431 :     tidstate->ss.ps.qual =
                                551                 :            431 :         ExecInitQual(node->scan.plan.qual, (PlanState *) tidstate);
                                552                 :                : 
                                553                 :            431 :     TidExprListCreate(tidstate);
                                554                 :                : 
                                555                 :                :     /*
                                556                 :                :      * all done.
                                557                 :                :      */
 8362 tgl@sss.pgh.pa.us         558                 :            431 :     return tidstate;
                                559                 :                : }
        

Generated by: LCOV version 2.4-beta