Header And Logo

PostgreSQL
| The world's most advanced open source database.

nodeBitmapAnd.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * nodeBitmapAnd.c
00004  *    routines to handle BitmapAnd nodes.
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/executor/nodeBitmapAnd.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 /* INTERFACE ROUTINES
00016  *      ExecInitBitmapAnd   - initialize the BitmapAnd node
00017  *      MultiExecBitmapAnd  - retrieve the result bitmap from the node
00018  *      ExecEndBitmapAnd    - shut down the BitmapAnd node
00019  *      ExecReScanBitmapAnd - rescan the BitmapAnd node
00020  *
00021  *   NOTES
00022  *      BitmapAnd nodes don't make use of their left and right
00023  *      subtrees, rather they maintain a list of subplans,
00024  *      much like Append nodes.  The logic is much simpler than
00025  *      Append, however, since we needn't cope with forward/backward
00026  *      execution.
00027  */
00028 
00029 #include "postgres.h"
00030 
00031 #include "executor/execdebug.h"
00032 #include "executor/nodeBitmapAnd.h"
00033 
00034 
00035 /* ----------------------------------------------------------------
00036  *      ExecInitBitmapAnd
00037  *
00038  *      Begin all of the subscans of the BitmapAnd node.
00039  * ----------------------------------------------------------------
00040  */
00041 BitmapAndState *
00042 ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
00043 {
00044     BitmapAndState *bitmapandstate = makeNode(BitmapAndState);
00045     PlanState **bitmapplanstates;
00046     int         nplans;
00047     int         i;
00048     ListCell   *l;
00049     Plan       *initNode;
00050 
00051     /* check for unsupported flags */
00052     Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
00053 
00054     /*
00055      * Set up empty vector of subplan states
00056      */
00057     nplans = list_length(node->bitmapplans);
00058 
00059     bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
00060 
00061     /*
00062      * create new BitmapAndState for our BitmapAnd node
00063      */
00064     bitmapandstate->ps.plan = (Plan *) node;
00065     bitmapandstate->ps.state = estate;
00066     bitmapandstate->bitmapplans = bitmapplanstates;
00067     bitmapandstate->nplans = nplans;
00068 
00069     /*
00070      * Miscellaneous initialization
00071      *
00072      * BitmapAnd plans don't have expression contexts because they never call
00073      * ExecQual or ExecProject.  They don't need any tuple slots either.
00074      */
00075 
00076     /*
00077      * call ExecInitNode on each of the plans to be executed and save the
00078      * results into the array "bitmapplanstates".
00079      */
00080     i = 0;
00081     foreach(l, node->bitmapplans)
00082     {
00083         initNode = (Plan *) lfirst(l);
00084         bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
00085         i++;
00086     }
00087 
00088     return bitmapandstate;
00089 }
00090 
00091 /* ----------------------------------------------------------------
00092  *     MultiExecBitmapAnd
00093  * ----------------------------------------------------------------
00094  */
00095 Node *
00096 MultiExecBitmapAnd(BitmapAndState *node)
00097 {
00098     PlanState **bitmapplans;
00099     int         nplans;
00100     int         i;
00101     TIDBitmap  *result = NULL;
00102 
00103     /* must provide our own instrumentation support */
00104     if (node->ps.instrument)
00105         InstrStartNode(node->ps.instrument);
00106 
00107     /*
00108      * get information from the node
00109      */
00110     bitmapplans = node->bitmapplans;
00111     nplans = node->nplans;
00112 
00113     /*
00114      * Scan all the subplans and AND their result bitmaps
00115      */
00116     for (i = 0; i < nplans; i++)
00117     {
00118         PlanState  *subnode = bitmapplans[i];
00119         TIDBitmap  *subresult;
00120 
00121         subresult = (TIDBitmap *) MultiExecProcNode(subnode);
00122 
00123         if (!subresult || !IsA(subresult, TIDBitmap))
00124             elog(ERROR, "unrecognized result from subplan");
00125 
00126         if (result == NULL)
00127             result = subresult; /* first subplan */
00128         else
00129         {
00130             tbm_intersect(result, subresult);
00131             tbm_free(subresult);
00132         }
00133 
00134         /*
00135          * If at any stage we have a completely empty bitmap, we can fall out
00136          * without evaluating the remaining subplans, since ANDing them can no
00137          * longer change the result.  (Note: the fact that indxpath.c orders
00138          * the subplans by selectivity should make this case more likely to
00139          * occur.)
00140          */
00141         if (tbm_is_empty(result))
00142             break;
00143     }
00144 
00145     if (result == NULL)
00146         elog(ERROR, "BitmapAnd doesn't support zero inputs");
00147 
00148     /* must provide our own instrumentation support */
00149     if (node->ps.instrument)
00150         InstrStopNode(node->ps.instrument, 0 /* XXX */ );
00151 
00152     return (Node *) result;
00153 }
00154 
00155 /* ----------------------------------------------------------------
00156  *      ExecEndBitmapAnd
00157  *
00158  *      Shuts down the subscans of the BitmapAnd node.
00159  *
00160  *      Returns nothing of interest.
00161  * ----------------------------------------------------------------
00162  */
00163 void
00164 ExecEndBitmapAnd(BitmapAndState *node)
00165 {
00166     PlanState **bitmapplans;
00167     int         nplans;
00168     int         i;
00169 
00170     /*
00171      * get information from the node
00172      */
00173     bitmapplans = node->bitmapplans;
00174     nplans = node->nplans;
00175 
00176     /*
00177      * shut down each of the subscans (that we've initialized)
00178      */
00179     for (i = 0; i < nplans; i++)
00180     {
00181         if (bitmapplans[i])
00182             ExecEndNode(bitmapplans[i]);
00183     }
00184 }
00185 
00186 void
00187 ExecReScanBitmapAnd(BitmapAndState *node)
00188 {
00189     int         i;
00190 
00191     for (i = 0; i < node->nplans; i++)
00192     {
00193         PlanState  *subnode = node->bitmapplans[i];
00194 
00195         /*
00196          * ExecReScan doesn't know about my subplans, so I have to do
00197          * changed-parameter signaling myself.
00198          */
00199         if (node->ps.chgParam != NULL)
00200             UpdateChangedParamSet(subnode, node->ps.chgParam);
00201 
00202         /*
00203          * If chgParam of subnode is not null then plan will be re-scanned by
00204          * first ExecProcNode.
00205          */
00206         if (subnode->chgParam == NULL)
00207             ExecReScan(subnode);
00208     }
00209 }