LCOV - code coverage report
Current view: top level - src/backend/executor - nodeBitmapOr.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 86.9 % 61 53
Test Date: 2026-07-03 19:57:34 Functions: 80.0 % 5 4
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 63.0 % 46 29

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

Generated by: LCOV version 2.0-1