LCOV - code coverage report
Current view: top level - src/backend/executor - nodeBitmapOr.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 49 61 80.3 %
Date: 2024-04-27 00:11:45 Functions: 4 5 80.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * nodeBitmapOr.c
       4             :  *    routines to handle BitmapOr nodes.
       5             :  *
       6             :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/executor/nodeBitmapOr.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : /* INTERFACE ROUTINES
      16             :  *      ExecInitBitmapOr    - initialize the BitmapOr node
      17             :  *      MultiExecBitmapOr   - retrieve the result bitmap from the node
      18             :  *      ExecEndBitmapOr     - shut down the BitmapOr node
      19             :  *      ExecReScanBitmapOr  - rescan the BitmapOr node
      20             :  *
      21             :  *   NOTES
      22             :  *      BitmapOr nodes don't make use of their left and right
      23             :  *      subtrees, rather they maintain a list of subplans,
      24             :  *      much like Append nodes.  The logic is much simpler than
      25             :  *      Append, however, since we needn't cope with forward/backward
      26             :  *      execution.
      27             :  */
      28             : 
      29             : #include "postgres.h"
      30             : 
      31             : #include "executor/executor.h"
      32             : #include "executor/nodeBitmapOr.h"
      33             : #include "miscadmin.h"
      34             : 
      35             : 
      36             : /* ----------------------------------------------------------------
      37             :  *      ExecBitmapOr
      38             :  *
      39             :  *      stub for pro forma compliance
      40             :  * ----------------------------------------------------------------
      41             :  */
      42             : static TupleTableSlot *
      43           0 : ExecBitmapOr(PlanState *pstate)
      44             : {
      45           0 :     elog(ERROR, "BitmapOr node does not support ExecProcNode call convention");
      46             :     return NULL;
      47             : }
      48             : 
      49             : /* ----------------------------------------------------------------
      50             :  *      ExecInitBitmapOr
      51             :  *
      52             :  *      Begin all of the subscans of the BitmapOr node.
      53             :  * ----------------------------------------------------------------
      54             :  */
      55             : BitmapOrState *
      56         288 : ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
      57             : {
      58         288 :     BitmapOrState *bitmaporstate = makeNode(BitmapOrState);
      59             :     PlanState **bitmapplanstates;
      60             :     int         nplans;
      61             :     int         i;
      62             :     ListCell   *l;
      63             :     Plan       *initNode;
      64             : 
      65             :     /* check for unsupported flags */
      66             :     Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
      67             : 
      68             :     /*
      69             :      * Set up empty vector of subplan states
      70             :      */
      71         288 :     nplans = list_length(node->bitmapplans);
      72             : 
      73         288 :     bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
      74             : 
      75             :     /*
      76             :      * create new BitmapOrState for our BitmapOr node
      77             :      */
      78         288 :     bitmaporstate->ps.plan = (Plan *) node;
      79         288 :     bitmaporstate->ps.state = estate;
      80         288 :     bitmaporstate->ps.ExecProcNode = ExecBitmapOr;
      81         288 :     bitmaporstate->bitmapplans = bitmapplanstates;
      82         288 :     bitmaporstate->nplans = nplans;
      83             : 
      84             :     /*
      85             :      * call ExecInitNode on each of the plans to be executed and save the
      86             :      * results into the array "bitmapplanstates".
      87             :      */
      88         288 :     i = 0;
      89         918 :     foreach(l, node->bitmapplans)
      90             :     {
      91         630 :         initNode = (Plan *) lfirst(l);
      92         630 :         bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
      93         630 :         i++;
      94             :     }
      95             : 
      96             :     /*
      97             :      * Miscellaneous initialization
      98             :      *
      99             :      * BitmapOr plans don't have expression contexts because they never call
     100             :      * ExecQual or ExecProject.  They don't need any tuple slots either.
     101             :      */
     102             : 
     103         288 :     return bitmaporstate;
     104             : }
     105             : 
     106             : /* ----------------------------------------------------------------
     107             :  *     MultiExecBitmapOr
     108             :  * ----------------------------------------------------------------
     109             :  */
     110             : Node *
     111         230 : MultiExecBitmapOr(BitmapOrState *node)
     112             : {
     113             :     PlanState **bitmapplans;
     114             :     int         nplans;
     115             :     int         i;
     116         230 :     TIDBitmap  *result = NULL;
     117             : 
     118             :     /* must provide our own instrumentation support */
     119         230 :     if (node->ps.instrument)
     120          42 :         InstrStartNode(node->ps.instrument);
     121             : 
     122             :     /*
     123             :      * get information from the node
     124             :      */
     125         230 :     bitmapplans = node->bitmapplans;
     126         230 :     nplans = node->nplans;
     127             : 
     128             :     /*
     129             :      * Scan all the subplans and OR their result bitmaps
     130             :      */
     131         732 :     for (i = 0; i < nplans; i++)
     132             :     {
     133         502 :         PlanState  *subnode = bitmapplans[i];
     134             :         TIDBitmap  *subresult;
     135             : 
     136             :         /*
     137             :          * We can special-case BitmapIndexScan children to avoid an explicit
     138             :          * tbm_union step for each child: just pass down the current result
     139             :          * bitmap and let the child OR directly into it.
     140             :          */
     141         502 :         if (IsA(subnode, BitmapIndexScanState))
     142             :         {
     143         502 :             if (result == NULL) /* first subplan */
     144             :             {
     145             :                 /* XXX should we use less than work_mem for this? */
     146         230 :                 result = tbm_create(work_mem * 1024L,
     147         230 :                                     ((BitmapOr *) node->ps.plan)->isshared ?
     148           0 :                                     node->ps.state->es_query_dsa : NULL);
     149             :             }
     150             : 
     151         502 :             ((BitmapIndexScanState *) subnode)->biss_result = result;
     152             : 
     153         502 :             subresult = (TIDBitmap *) MultiExecProcNode(subnode);
     154             : 
     155         502 :             if (subresult != result)
     156           0 :                 elog(ERROR, "unrecognized result from subplan");
     157             :         }
     158             :         else
     159             :         {
     160             :             /* standard implementation */
     161           0 :             subresult = (TIDBitmap *) MultiExecProcNode(subnode);
     162             : 
     163           0 :             if (!subresult || !IsA(subresult, TIDBitmap))
     164           0 :                 elog(ERROR, "unrecognized result from subplan");
     165             : 
     166           0 :             if (result == NULL)
     167           0 :                 result = subresult; /* first subplan */
     168             :             else
     169             :             {
     170           0 :                 tbm_union(result, subresult);
     171           0 :                 tbm_free(subresult);
     172             :             }
     173             :         }
     174             :     }
     175             : 
     176             :     /* We could return an empty result set here? */
     177         230 :     if (result == NULL)
     178           0 :         elog(ERROR, "BitmapOr doesn't support zero inputs");
     179             : 
     180             :     /* must provide our own instrumentation support */
     181         230 :     if (node->ps.instrument)
     182          42 :         InstrStopNode(node->ps.instrument, 0 /* XXX */ );
     183             : 
     184         230 :     return (Node *) result;
     185             : }
     186             : 
     187             : /* ----------------------------------------------------------------
     188             :  *      ExecEndBitmapOr
     189             :  *
     190             :  *      Shuts down the subscans of the BitmapOr node.
     191             :  *
     192             :  *      Returns nothing of interest.
     193             :  * ----------------------------------------------------------------
     194             :  */
     195             : void
     196         288 : ExecEndBitmapOr(BitmapOrState *node)
     197             : {
     198             :     PlanState **bitmapplans;
     199             :     int         nplans;
     200             :     int         i;
     201             : 
     202             :     /*
     203             :      * get information from the node
     204             :      */
     205         288 :     bitmapplans = node->bitmapplans;
     206         288 :     nplans = node->nplans;
     207             : 
     208             :     /*
     209             :      * shut down each of the subscans (that we've initialized)
     210             :      */
     211         918 :     for (i = 0; i < nplans; i++)
     212             :     {
     213         630 :         if (bitmapplans[i])
     214         630 :             ExecEndNode(bitmapplans[i]);
     215             :     }
     216         288 : }
     217             : 
     218             : void
     219          28 : ExecReScanBitmapOr(BitmapOrState *node)
     220             : {
     221             :     int         i;
     222             : 
     223          84 :     for (i = 0; i < node->nplans; i++)
     224             :     {
     225          56 :         PlanState  *subnode = node->bitmapplans[i];
     226             : 
     227             :         /*
     228             :          * ExecReScan doesn't know about my subplans, so I have to do
     229             :          * changed-parameter signaling myself.
     230             :          */
     231          56 :         if (node->ps.chgParam != NULL)
     232          12 :             UpdateChangedParamSet(subnode, node->ps.chgParam);
     233             : 
     234             :         /*
     235             :          * If chgParam of subnode is not null then plan will be re-scanned by
     236             :          * first ExecProcNode.
     237             :          */
     238          56 :         if (subnode->chgParam == NULL)
     239          50 :             ExecReScan(subnode);
     240             :     }
     241          28 : }

Generated by: LCOV version 1.14