LCOV - code coverage report
Current view: top level - src/backend/executor - nodeBitmapAnd.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 48 54 88.9 %
Date: 2024-04-26 20:11:02 Functions: 4 5 80.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * nodeBitmapAnd.c
       4             :  *    routines to handle BitmapAnd 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/nodeBitmapAnd.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : /* INTERFACE ROUTINES
      16             :  *      ExecInitBitmapAnd   - initialize the BitmapAnd node
      17             :  *      MultiExecBitmapAnd  - retrieve the result bitmap from the node
      18             :  *      ExecEndBitmapAnd    - shut down the BitmapAnd node
      19             :  *      ExecReScanBitmapAnd - rescan the BitmapAnd node
      20             :  *
      21             :  *   NOTES
      22             :  *      BitmapAnd 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/nodeBitmapAnd.h"
      33             : 
      34             : 
      35             : /* ----------------------------------------------------------------
      36             :  *      ExecBitmapAnd
      37             :  *
      38             :  *      stub for pro forma compliance
      39             :  * ----------------------------------------------------------------
      40             :  */
      41             : static TupleTableSlot *
      42           0 : ExecBitmapAnd(PlanState *pstate)
      43             : {
      44           0 :     elog(ERROR, "BitmapAnd node does not support ExecProcNode call convention");
      45             :     return NULL;
      46             : }
      47             : 
      48             : /* ----------------------------------------------------------------
      49             :  *      ExecInitBitmapAnd
      50             :  *
      51             :  *      Begin all of the subscans of the BitmapAnd node.
      52             :  * ----------------------------------------------------------------
      53             :  */
      54             : BitmapAndState *
      55         104 : ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
      56             : {
      57         104 :     BitmapAndState *bitmapandstate = makeNode(BitmapAndState);
      58             :     PlanState **bitmapplanstates;
      59             :     int         nplans;
      60             :     int         i;
      61             :     ListCell   *l;
      62             :     Plan       *initNode;
      63             : 
      64             :     /* check for unsupported flags */
      65             :     Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
      66             : 
      67             :     /*
      68             :      * Set up empty vector of subplan states
      69             :      */
      70         104 :     nplans = list_length(node->bitmapplans);
      71             : 
      72         104 :     bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
      73             : 
      74             :     /*
      75             :      * create new BitmapAndState for our BitmapAnd node
      76             :      */
      77         104 :     bitmapandstate->ps.plan = (Plan *) node;
      78         104 :     bitmapandstate->ps.state = estate;
      79         104 :     bitmapandstate->ps.ExecProcNode = ExecBitmapAnd;
      80         104 :     bitmapandstate->bitmapplans = bitmapplanstates;
      81         104 :     bitmapandstate->nplans = nplans;
      82             : 
      83             :     /*
      84             :      * call ExecInitNode on each of the plans to be executed and save the
      85             :      * results into the array "bitmapplanstates".
      86             :      */
      87         104 :     i = 0;
      88         312 :     foreach(l, node->bitmapplans)
      89             :     {
      90         208 :         initNode = (Plan *) lfirst(l);
      91         208 :         bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
      92         208 :         i++;
      93             :     }
      94             : 
      95             :     /*
      96             :      * Miscellaneous initialization
      97             :      *
      98             :      * BitmapAnd plans don't have expression contexts because they never call
      99             :      * ExecQual or ExecProject.  They don't need any tuple slots either.
     100             :      */
     101             : 
     102         104 :     return bitmapandstate;
     103             : }
     104             : 
     105             : /* ----------------------------------------------------------------
     106             :  *     MultiExecBitmapAnd
     107             :  * ----------------------------------------------------------------
     108             :  */
     109             : Node *
     110          80 : MultiExecBitmapAnd(BitmapAndState *node)
     111             : {
     112             :     PlanState **bitmapplans;
     113             :     int         nplans;
     114             :     int         i;
     115          80 :     TIDBitmap  *result = NULL;
     116             : 
     117             :     /* must provide our own instrumentation support */
     118          80 :     if (node->ps.instrument)
     119           0 :         InstrStartNode(node->ps.instrument);
     120             : 
     121             :     /*
     122             :      * get information from the node
     123             :      */
     124          80 :     bitmapplans = node->bitmapplans;
     125          80 :     nplans = node->nplans;
     126             : 
     127             :     /*
     128             :      * Scan all the subplans and AND their result bitmaps
     129             :      */
     130         234 :     for (i = 0; i < nplans; i++)
     131             :     {
     132         160 :         PlanState  *subnode = bitmapplans[i];
     133             :         TIDBitmap  *subresult;
     134             : 
     135         160 :         subresult = (TIDBitmap *) MultiExecProcNode(subnode);
     136             : 
     137         160 :         if (!subresult || !IsA(subresult, TIDBitmap))
     138           0 :             elog(ERROR, "unrecognized result from subplan");
     139             : 
     140         160 :         if (result == NULL)
     141          80 :             result = subresult; /* first subplan */
     142             :         else
     143             :         {
     144          80 :             tbm_intersect(result, subresult);
     145          80 :             tbm_free(subresult);
     146             :         }
     147             : 
     148             :         /*
     149             :          * If at any stage we have a completely empty bitmap, we can fall out
     150             :          * without evaluating the remaining subplans, since ANDing them can no
     151             :          * longer change the result.  (Note: the fact that indxpath.c orders
     152             :          * the subplans by selectivity should make this case more likely to
     153             :          * occur.)
     154             :          */
     155         160 :         if (tbm_is_empty(result))
     156           6 :             break;
     157             :     }
     158             : 
     159          80 :     if (result == NULL)
     160           0 :         elog(ERROR, "BitmapAnd doesn't support zero inputs");
     161             : 
     162             :     /* must provide our own instrumentation support */
     163          80 :     if (node->ps.instrument)
     164           0 :         InstrStopNode(node->ps.instrument, 0 /* XXX */ );
     165             : 
     166          80 :     return (Node *) result;
     167             : }
     168             : 
     169             : /* ----------------------------------------------------------------
     170             :  *      ExecEndBitmapAnd
     171             :  *
     172             :  *      Shuts down the subscans of the BitmapAnd node.
     173             :  *
     174             :  *      Returns nothing of interest.
     175             :  * ----------------------------------------------------------------
     176             :  */
     177             : void
     178         104 : ExecEndBitmapAnd(BitmapAndState *node)
     179             : {
     180             :     PlanState **bitmapplans;
     181             :     int         nplans;
     182             :     int         i;
     183             : 
     184             :     /*
     185             :      * get information from the node
     186             :      */
     187         104 :     bitmapplans = node->bitmapplans;
     188         104 :     nplans = node->nplans;
     189             : 
     190             :     /*
     191             :      * shut down each of the subscans (that we've initialized)
     192             :      */
     193         312 :     for (i = 0; i < nplans; i++)
     194             :     {
     195         208 :         if (bitmapplans[i])
     196         208 :             ExecEndNode(bitmapplans[i]);
     197             :     }
     198         104 : }
     199             : 
     200             : void
     201          62 : ExecReScanBitmapAnd(BitmapAndState *node)
     202             : {
     203             :     int         i;
     204             : 
     205         186 :     for (i = 0; i < node->nplans; i++)
     206             :     {
     207         124 :         PlanState  *subnode = node->bitmapplans[i];
     208             : 
     209             :         /*
     210             :          * ExecReScan doesn't know about my subplans, so I have to do
     211             :          * changed-parameter signaling myself.
     212             :          */
     213         124 :         if (node->ps.chgParam != NULL)
     214          12 :             UpdateChangedParamSet(subnode, node->ps.chgParam);
     215             : 
     216             :         /*
     217             :          * If chgParam of subnode is not null then plan will be re-scanned by
     218             :          * first ExecProcNode.
     219             :          */
     220         124 :         if (subnode->chgParam == NULL)
     221         118 :             ExecReScan(subnode);
     222             :     }
     223          62 : }

Generated by: LCOV version 1.14