LCOV - differential code coverage report
Current view: top level - src/backend/executor - nodeBitmapIndexscan.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 97.6 % 83 81 2 81
Current Date: 2023-04-08 15:15:32 Functions: 80.0 % 5 4 1 4
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * nodeBitmapIndexscan.c
       4                 :  *    Routines to support bitmapped index scans of relations
       5                 :  *
       6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
       7                 :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :  *
       9                 :  *
      10                 :  * IDENTIFICATION
      11                 :  *    src/backend/executor/nodeBitmapIndexscan.c
      12                 :  *
      13                 :  *-------------------------------------------------------------------------
      14                 :  */
      15                 : /*
      16                 :  * INTERFACE ROUTINES
      17                 :  *      MultiExecBitmapIndexScan    scans a relation using index.
      18                 :  *      ExecInitBitmapIndexScan     creates and initializes state info.
      19                 :  *      ExecReScanBitmapIndexScan   prepares to rescan the plan.
      20                 :  *      ExecEndBitmapIndexScan      releases all storage.
      21                 :  */
      22                 : #include "postgres.h"
      23                 : 
      24                 : #include "access/genam.h"
      25                 : #include "executor/execdebug.h"
      26                 : #include "executor/nodeBitmapIndexscan.h"
      27                 : #include "executor/nodeIndexscan.h"
      28                 : #include "miscadmin.h"
      29                 : #include "utils/memutils.h"
      30                 : 
      31                 : 
      32                 : /* ----------------------------------------------------------------
      33                 :  *      ExecBitmapIndexScan
      34                 :  *
      35                 :  *      stub for pro forma compliance
      36                 :  * ----------------------------------------------------------------
      37                 :  */
      38                 : static TupleTableSlot *
      39 UBC           0 : ExecBitmapIndexScan(PlanState *pstate)
      40                 : {
      41               0 :     elog(ERROR, "BitmapIndexScan node does not support ExecProcNode call convention");
      42                 :     return NULL;
      43                 : }
      44                 : 
      45                 : /* ----------------------------------------------------------------
      46                 :  *      MultiExecBitmapIndexScan(node)
      47                 :  * ----------------------------------------------------------------
      48                 :  */
      49                 : Node *
      50 CBC        8691 : MultiExecBitmapIndexScan(BitmapIndexScanState *node)
      51                 : {
      52                 :     TIDBitmap  *tbm;
      53                 :     IndexScanDesc scandesc;
      54            8691 :     double      nTuples = 0;
      55                 :     bool        doscan;
      56                 : 
      57                 :     /* must provide our own instrumentation support */
      58            8691 :     if (node->ss.ps.instrument)
      59             219 :         InstrStartNode(node->ss.ps.instrument);
      60                 : 
      61                 :     /*
      62                 :      * extract necessary information from index scan node
      63                 :      */
      64            8691 :     scandesc = node->biss_ScanDesc;
      65                 : 
      66                 :     /*
      67                 :      * If we have runtime keys and they've not already been set up, do it now.
      68                 :      * Array keys are also treated as runtime keys; note that if ExecReScan
      69                 :      * returns with biss_RuntimeKeysReady still false, then there is an empty
      70                 :      * array key so we should do nothing.
      71                 :      */
      72            8691 :     if (!node->biss_RuntimeKeysReady &&
      73            6940 :         (node->biss_NumRuntimeKeys != 0 || node->biss_NumArrayKeys != 0))
      74                 :     {
      75             263 :         ExecReScan((PlanState *) node);
      76             263 :         doscan = node->biss_RuntimeKeysReady;
      77                 :     }
      78                 :     else
      79            8428 :         doscan = true;
      80                 : 
      81                 :     /*
      82                 :      * Prepare the result bitmap.  Normally we just create a new one to pass
      83                 :      * back; however, our parent node is allowed to store a pre-made one into
      84                 :      * node->biss_result, in which case we just OR our tuple IDs into the
      85                 :      * existing bitmap.  (This saves needing explicit UNION steps.)
      86                 :      */
      87            8691 :     if (node->biss_result)
      88                 :     {
      89             185 :         tbm = node->biss_result;
      90             185 :         node->biss_result = NULL;    /* reset for next time */
      91                 :     }
      92                 :     else
      93                 :     {
      94                 :         /* XXX should we use less than work_mem for this? */
      95            8506 :         tbm = tbm_create(work_mem * 1024L,
      96            8506 :                          ((BitmapIndexScan *) node->ss.ps.plan)->isshared ?
      97              36 :                          node->ss.ps.state->es_query_dsa : NULL);
      98                 :     }
      99                 : 
     100                 :     /*
     101                 :      * Get TIDs from index and insert into bitmap
     102                 :      */
     103           17394 :     while (doscan)
     104                 :     {
     105            8703 :         nTuples += (double) index_getbitmap(scandesc, tbm);
     106                 : 
     107            8703 :         CHECK_FOR_INTERRUPTS();
     108                 : 
     109            8703 :         doscan = ExecIndexAdvanceArrayKeys(node->biss_ArrayKeys,
     110                 :                                            node->biss_NumArrayKeys);
     111            8703 :         if (doscan)             /* reset index scan */
     112              12 :             index_rescan(node->biss_ScanDesc,
     113              12 :                          node->biss_ScanKeys, node->biss_NumScanKeys,
     114                 :                          NULL, 0);
     115                 :     }
     116                 : 
     117                 :     /* must provide our own instrumentation support */
     118            8691 :     if (node->ss.ps.instrument)
     119             219 :         InstrStopNode(node->ss.ps.instrument, nTuples);
     120                 : 
     121            8691 :     return (Node *) tbm;
     122                 : }
     123                 : 
     124                 : /* ----------------------------------------------------------------
     125                 :  *      ExecReScanBitmapIndexScan(node)
     126                 :  *
     127                 :  *      Recalculates the values of any scan keys whose value depends on
     128                 :  *      information known at runtime, then rescans the indexed relation.
     129                 :  * ----------------------------------------------------------------
     130                 :  */
     131                 : void
     132            2014 : ExecReScanBitmapIndexScan(BitmapIndexScanState *node)
     133                 : {
     134            2014 :     ExprContext *econtext = node->biss_RuntimeContext;
     135                 : 
     136                 :     /*
     137                 :      * Reset the runtime-key context so we don't leak memory as each outer
     138                 :      * tuple is scanned.  Note this assumes that we will recalculate *all*
     139                 :      * runtime keys on each call.
     140                 :      */
     141            2014 :     if (econtext)
     142            1906 :         ResetExprContext(econtext);
     143                 : 
     144                 :     /*
     145                 :      * If we are doing runtime key calculations (ie, any of the index key
     146                 :      * values weren't simple Consts), compute the new key values.
     147                 :      *
     148                 :      * Array keys are also treated as runtime keys; note that if we return
     149                 :      * with biss_RuntimeKeysReady still false, then there is an empty array
     150                 :      * key so no index scan is needed.
     151                 :      */
     152            2014 :     if (node->biss_NumRuntimeKeys != 0)
     153            1894 :         ExecIndexEvalRuntimeKeys(econtext,
     154                 :                                  node->biss_RuntimeKeys,
     155                 :                                  node->biss_NumRuntimeKeys);
     156            2014 :     if (node->biss_NumArrayKeys != 0)
     157              12 :         node->biss_RuntimeKeysReady =
     158              12 :             ExecIndexEvalArrayKeys(econtext,
     159                 :                                    node->biss_ArrayKeys,
     160                 :                                    node->biss_NumArrayKeys);
     161                 :     else
     162            2002 :         node->biss_RuntimeKeysReady = true;
     163                 : 
     164                 :     /* reset index scan */
     165            2014 :     if (node->biss_RuntimeKeysReady)
     166            2014 :         index_rescan(node->biss_ScanDesc,
     167            2014 :                      node->biss_ScanKeys, node->biss_NumScanKeys,
     168                 :                      NULL, 0);
     169            2014 : }
     170                 : 
     171                 : /* ----------------------------------------------------------------
     172                 :  *      ExecEndBitmapIndexScan
     173                 :  * ----------------------------------------------------------------
     174                 :  */
     175                 : void
     176           10743 : ExecEndBitmapIndexScan(BitmapIndexScanState *node)
     177                 : {
     178                 :     Relation    indexRelationDesc;
     179                 :     IndexScanDesc indexScanDesc;
     180                 : 
     181                 :     /*
     182                 :      * extract information from the node
     183                 :      */
     184           10743 :     indexRelationDesc = node->biss_RelationDesc;
     185           10743 :     indexScanDesc = node->biss_ScanDesc;
     186                 : 
     187                 :     /*
     188                 :      * Free the exprcontext ... now dead code, see ExecFreeExprContext
     189                 :      */
     190                 : #ifdef NOT_USED
     191                 :     if (node->biss_RuntimeContext)
     192                 :         FreeExprContext(node->biss_RuntimeContext, true);
     193                 : #endif
     194                 : 
     195                 :     /*
     196                 :      * close the index relation (no-op if we didn't open it)
     197                 :      */
     198           10743 :     if (indexScanDesc)
     199            9039 :         index_endscan(indexScanDesc);
     200           10743 :     if (indexRelationDesc)
     201            9039 :         index_close(indexRelationDesc, NoLock);
     202           10743 : }
     203                 : 
     204                 : /* ----------------------------------------------------------------
     205                 :  *      ExecInitBitmapIndexScan
     206                 :  *
     207                 :  *      Initializes the index scan's state information.
     208                 :  * ----------------------------------------------------------------
     209                 :  */
     210                 : BitmapIndexScanState *
     211           10774 : ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
     212                 : {
     213                 :     BitmapIndexScanState *indexstate;
     214                 :     LOCKMODE    lockmode;
     215                 : 
     216                 :     /* check for unsupported flags */
     217           10774 :     Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
     218                 : 
     219                 :     /*
     220                 :      * create state structure
     221                 :      */
     222           10774 :     indexstate = makeNode(BitmapIndexScanState);
     223           10774 :     indexstate->ss.ps.plan = (Plan *) node;
     224           10774 :     indexstate->ss.ps.state = estate;
     225           10774 :     indexstate->ss.ps.ExecProcNode = ExecBitmapIndexScan;
     226                 : 
     227                 :     /* normally we don't make the result bitmap till runtime */
     228           10774 :     indexstate->biss_result = NULL;
     229                 : 
     230                 :     /*
     231                 :      * We do not open or lock the base relation here.  We assume that an
     232                 :      * ancestor BitmapHeapScan node is holding AccessShareLock (or better) on
     233                 :      * the heap relation throughout the execution of the plan tree.
     234                 :      */
     235                 : 
     236           10774 :     indexstate->ss.ss_currentRelation = NULL;
     237           10774 :     indexstate->ss.ss_currentScanDesc = NULL;
     238                 : 
     239                 :     /*
     240                 :      * Miscellaneous initialization
     241                 :      *
     242                 :      * We do not need a standard exprcontext for this node, though we may
     243                 :      * decide below to create a runtime-key exprcontext
     244                 :      */
     245                 : 
     246                 :     /*
     247                 :      * initialize child expressions
     248                 :      *
     249                 :      * We don't need to initialize targetlist or qual since neither are used.
     250                 :      *
     251                 :      * Note: we don't initialize all of the indexqual expression, only the
     252                 :      * sub-parts corresponding to runtime keys (see below).
     253                 :      */
     254                 : 
     255                 :     /*
     256                 :      * If we are just doing EXPLAIN (ie, aren't going to run the plan), stop
     257                 :      * here.  This allows an index-advisor plugin to EXPLAIN a plan containing
     258                 :      * references to nonexistent indexes.
     259                 :      */
     260           10774 :     if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
     261            1704 :         return indexstate;
     262                 : 
     263                 :     /* Open the index relation. */
     264            9070 :     lockmode = exec_rt_fetch(node->scan.scanrelid, estate)->rellockmode;
     265            9070 :     indexstate->biss_RelationDesc = index_open(node->indexid, lockmode);
     266                 : 
     267                 :     /*
     268                 :      * Initialize index-specific scan state
     269                 :      */
     270            9070 :     indexstate->biss_RuntimeKeysReady = false;
     271            9070 :     indexstate->biss_RuntimeKeys = NULL;
     272            9070 :     indexstate->biss_NumRuntimeKeys = 0;
     273                 : 
     274                 :     /*
     275                 :      * build the index scan keys from the index qualification
     276                 :      */
     277            9070 :     ExecIndexBuildScanKeys((PlanState *) indexstate,
     278                 :                            indexstate->biss_RelationDesc,
     279                 :                            node->indexqual,
     280                 :                            false,
     281            9070 :                            &indexstate->biss_ScanKeys,
     282                 :                            &indexstate->biss_NumScanKeys,
     283                 :                            &indexstate->biss_RuntimeKeys,
     284                 :                            &indexstate->biss_NumRuntimeKeys,
     285                 :                            &indexstate->biss_ArrayKeys,
     286                 :                            &indexstate->biss_NumArrayKeys);
     287                 : 
     288                 :     /*
     289                 :      * If we have runtime keys or array keys, we need an ExprContext to
     290                 :      * evaluate them. We could just create a "standard" plan node exprcontext,
     291                 :      * but to keep the code looking similar to nodeIndexscan.c, it seems
     292                 :      * better to stick with the approach of using a separate ExprContext.
     293                 :      */
     294            9070 :     if (indexstate->biss_NumRuntimeKeys != 0 ||
     295            8428 :         indexstate->biss_NumArrayKeys != 0)
     296             654 :     {
     297             654 :         ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;
     298                 : 
     299             654 :         ExecAssignExprContext(estate, &indexstate->ss.ps);
     300             654 :         indexstate->biss_RuntimeContext = indexstate->ss.ps.ps_ExprContext;
     301             654 :         indexstate->ss.ps.ps_ExprContext = stdecontext;
     302                 :     }
     303                 :     else
     304                 :     {
     305            8416 :         indexstate->biss_RuntimeContext = NULL;
     306                 :     }
     307                 : 
     308                 :     /*
     309                 :      * Initialize scan descriptor.
     310                 :      */
     311            9070 :     indexstate->biss_ScanDesc =
     312            9070 :         index_beginscan_bitmap(indexstate->biss_RelationDesc,
     313                 :                                estate->es_snapshot,
     314                 :                                indexstate->biss_NumScanKeys);
     315                 : 
     316                 :     /*
     317                 :      * If no run-time keys to calculate, go ahead and pass the scankeys to the
     318                 :      * index AM.
     319                 :      */
     320            9070 :     if (indexstate->biss_NumRuntimeKeys == 0 &&
     321            8428 :         indexstate->biss_NumArrayKeys == 0)
     322            8416 :         index_rescan(indexstate->biss_ScanDesc,
     323            8416 :                      indexstate->biss_ScanKeys, indexstate->biss_NumScanKeys,
     324                 :                      NULL, 0);
     325                 : 
     326                 :     /*
     327                 :      * all done.
     328                 :      */
     329            9070 :     return indexstate;
     330                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a