LCOV - code coverage report
Current view: top level - src/backend/executor - nodeBitmapOr.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 89.3 % 84 75
Test Date: 2026-01-26 10:56:24 Functions: 80.0 % 5 4
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 53.7 % 54 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                 :             : /* 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                 :           0 :         return NULL;
      47                 :             : }
      48                 :             : 
      49                 :             : /* ----------------------------------------------------------------
      50                 :             :  *              ExecInitBitmapOr
      51                 :             :  *
      52                 :             :  *              Begin all of the subscans of the BitmapOr node.
      53                 :             :  * ----------------------------------------------------------------
      54                 :             :  */
      55                 :             : BitmapOrState *
      56                 :          33 : ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
      57                 :             : {
      58                 :          33 :         BitmapOrState *bitmaporstate = makeNode(BitmapOrState);
      59                 :          33 :         PlanState **bitmapplanstates;
      60                 :          33 :         int                     nplans;
      61                 :          33 :         int                     i;
      62                 :          33 :         ListCell   *l;
      63                 :          33 :         Plan       *initNode;
      64                 :             : 
      65                 :             :         /* check for unsupported flags */
      66         [ +  - ]:          33 :         Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
      67                 :             : 
      68                 :             :         /*
      69                 :             :          * Set up empty vector of subplan states
      70                 :             :          */
      71                 :          33 :         nplans = list_length(node->bitmapplans);
      72                 :             : 
      73                 :          33 :         bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
      74                 :             : 
      75                 :             :         /*
      76                 :             :          * create new BitmapOrState for our BitmapOr node
      77                 :             :          */
      78                 :          33 :         bitmaporstate->ps.plan = (Plan *) node;
      79                 :          33 :         bitmaporstate->ps.state = estate;
      80                 :          33 :         bitmaporstate->ps.ExecProcNode = ExecBitmapOr;
      81                 :          33 :         bitmaporstate->bitmapplans = bitmapplanstates;
      82                 :          33 :         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                 :          33 :         i = 0;
      89   [ +  -  +  +  :         100 :         foreach(l, node->bitmapplans)
                   +  + ]
      90                 :             :         {
      91                 :          67 :                 initNode = (Plan *) lfirst(l);
      92                 :          67 :                 bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
      93                 :          67 :                 i++;
      94                 :          67 :         }
      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                 :          66 :         return bitmaporstate;
     104                 :          33 : }
     105                 :             : 
     106                 :             : /* ----------------------------------------------------------------
     107                 :             :  *         MultiExecBitmapOr
     108                 :             :  * ----------------------------------------------------------------
     109                 :             :  */
     110                 :             : Node *
     111                 :           9 : MultiExecBitmapOr(BitmapOrState *node)
     112                 :             : {
     113                 :           9 :         PlanState **bitmapplans;
     114                 :           9 :         int                     nplans;
     115                 :           9 :         int                     i;
     116                 :           9 :         TIDBitmap  *result = NULL;
     117                 :             : 
     118                 :             :         /* must provide our own instrumentation support */
     119         [ +  + ]:           9 :         if (node->ps.instrument)
     120                 :           1 :                 InstrStartNode(node->ps.instrument);
     121                 :             : 
     122                 :             :         /*
     123                 :             :          * get information from the node
     124                 :             :          */
     125                 :           9 :         bitmapplans = node->bitmapplans;
     126                 :           9 :         nplans = node->nplans;
     127                 :             : 
     128                 :             :         /*
     129                 :             :          * Scan all the subplans and OR their result bitmaps
     130                 :             :          */
     131         [ +  + ]:          27 :         for (i = 0; i < nplans; i++)
     132                 :             :         {
     133                 :          18 :                 PlanState  *subnode = bitmapplans[i];
     134                 :          18 :                 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         [ +  + ]:          18 :                 if (IsA(subnode, BitmapIndexScanState))
     142                 :             :                 {
     143         [ +  + ]:          17 :                         if (result == NULL) /* first subplan */
     144                 :             :                         {
     145                 :             :                                 /* XXX should we use less than work_mem for this? */
     146                 :          16 :                                 result = tbm_create(work_mem * (Size) 1024,
     147         [ -  + ]:           8 :                                                                         ((BitmapOr *) node->ps.plan)->isshared ?
     148                 :           0 :                                                                         node->ps.state->es_query_dsa : NULL);
     149                 :           8 :                         }
     150                 :             : 
     151                 :          17 :                         ((BitmapIndexScanState *) subnode)->biss_result = result;
     152                 :             : 
     153                 :          17 :                         subresult = (TIDBitmap *) MultiExecProcNode(subnode);
     154                 :             : 
     155         [ +  - ]:          17 :                         if (subresult != result)
     156   [ #  #  #  # ]:           0 :                                 elog(ERROR, "unrecognized result from subplan");
     157                 :          17 :                 }
     158                 :             :                 else
     159                 :             :                 {
     160                 :             :                         /* standard implementation */
     161                 :           1 :                         subresult = (TIDBitmap *) MultiExecProcNode(subnode);
     162                 :             : 
     163         [ +  - ]:           1 :                         if (!subresult || !IsA(subresult, TIDBitmap))
     164   [ #  #  #  # ]:           0 :                                 elog(ERROR, "unrecognized result from subplan");
     165                 :             : 
     166         [ -  + ]:           1 :                         if (result == NULL)
     167                 :           1 :                                 result = subresult; /* first subplan */
     168                 :             :                         else
     169                 :             :                         {
     170                 :           0 :                                 tbm_union(result, subresult);
     171                 :           0 :                                 tbm_free(subresult);
     172                 :             :                         }
     173                 :             :                 }
     174                 :          18 :         }
     175                 :             : 
     176                 :             :         /* We could return an empty result set here? */
     177         [ +  - ]:           9 :         if (result == NULL)
     178   [ #  #  #  # ]:           0 :                 elog(ERROR, "BitmapOr doesn't support zero inputs");
     179                 :             : 
     180                 :             :         /* must provide our own instrumentation support */
     181         [ +  + ]:           9 :         if (node->ps.instrument)
     182                 :           1 :                 InstrStopNode(node->ps.instrument, 0 /* XXX */ );
     183                 :             : 
     184                 :          18 :         return (Node *) result;
     185                 :           9 : }
     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                 :          33 : ExecEndBitmapOr(BitmapOrState *node)
     197                 :             : {
     198                 :          33 :         PlanState **bitmapplans;
     199                 :          33 :         int                     nplans;
     200                 :          33 :         int                     i;
     201                 :             : 
     202                 :             :         /*
     203                 :             :          * get information from the node
     204                 :             :          */
     205                 :          33 :         bitmapplans = node->bitmapplans;
     206                 :          33 :         nplans = node->nplans;
     207                 :             : 
     208                 :             :         /*
     209                 :             :          * shut down each of the subscans (that we've initialized)
     210                 :             :          */
     211         [ +  + ]:         100 :         for (i = 0; i < nplans; i++)
     212                 :             :         {
     213         [ -  + ]:          67 :                 if (bitmapplans[i])
     214                 :          67 :                         ExecEndNode(bitmapplans[i]);
     215                 :          67 :         }
     216                 :          33 : }
     217                 :             : 
     218                 :             : void
     219                 :           1 : ExecReScanBitmapOr(BitmapOrState *node)
     220                 :             : {
     221                 :           1 :         int                     i;
     222                 :             : 
     223         [ +  + ]:           3 :         for (i = 0; i < node->nplans; i++)
     224                 :             :         {
     225                 :           2 :                 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         [ -  + ]:           2 :                 if (node->ps.chgParam != NULL)
     232                 :           2 :                         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         [ +  + ]:           2 :                 if (subnode->chgParam == NULL)
     239                 :           1 :                         ExecReScan(subnode);
     240                 :           2 :         }
     241                 :           1 : }
        

Generated by: LCOV version 2.3.2-1