Header And Logo

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

Functions

nodeBitmapIndexscan.c File Reference

#include "postgres.h"
#include "executor/execdebug.h"
#include "executor/nodeBitmapIndexscan.h"
#include "executor/nodeIndexscan.h"
#include "miscadmin.h"
#include "utils/memutils.h"
Include dependency graph for nodeBitmapIndexscan.c:

Go to the source code of this file.

Functions

NodeMultiExecBitmapIndexScan (BitmapIndexScanState *node)
void ExecReScanBitmapIndexScan (BitmapIndexScanState *node)
void ExecEndBitmapIndexScan (BitmapIndexScanState *node)
BitmapIndexScanStateExecInitBitmapIndexScan (BitmapIndexScan *node, EState *estate, int eflags)

Function Documentation

void ExecEndBitmapIndexScan ( BitmapIndexScanState node  ) 

Definition at line 160 of file nodeBitmapIndexscan.c.

References BitmapIndexScanState::biss_RelationDesc, BitmapIndexScanState::biss_RuntimeContext, BitmapIndexScanState::biss_ScanDesc, FreeExprContext(), index_close(), index_endscan(), and NoLock.

Referenced by ExecEndNode().

{
    Relation    indexRelationDesc;
    IndexScanDesc indexScanDesc;

    /*
     * extract information from the node
     */
    indexRelationDesc = node->biss_RelationDesc;
    indexScanDesc = node->biss_ScanDesc;

    /*
     * Free the exprcontext ... now dead code, see ExecFreeExprContext
     */
#ifdef NOT_USED
    if (node->biss_RuntimeContext)
        FreeExprContext(node->biss_RuntimeContext, true);
#endif

    /*
     * close the index relation (no-op if we didn't open it)
     */
    if (indexScanDesc)
        index_endscan(indexScanDesc);
    if (indexRelationDesc)
        index_close(indexRelationDesc, NoLock);
}

BitmapIndexScanState* ExecInitBitmapIndexScan ( BitmapIndexScan node,
EState estate,
int  eflags 
)

Definition at line 195 of file nodeBitmapIndexscan.c.

References AccessShareLock, Assert, BitmapIndexScanState::biss_NumRuntimeKeys, BitmapIndexScanState::biss_RelationDesc, BitmapIndexScanState::biss_result, BitmapIndexScanState::biss_RuntimeKeys, BitmapIndexScanState::biss_RuntimeKeysReady, EState::es_snapshot, EXEC_FLAG_BACKWARD, EXEC_FLAG_EXPLAIN_ONLY, EXEC_FLAG_MARK, ExecAssignExprContext(), ExecIndexBuildScanKeys(), ExecRelationIsTargetRelation(), index_beginscan_bitmap(), index_open(), index_rescan(), BitmapIndexScan::indexid, BitmapIndexScan::indexqual, makeNode, NoLock, NULL, PlanState::plan, ScanState::ps, PlanState::ps_ExprContext, BitmapIndexScan::scan, Scan::scanrelid, BitmapIndexScanState::ss, ScanState::ss_currentRelation, ScanState::ss_currentScanDesc, and PlanState::state.

Referenced by ExecInitNode().

{
    BitmapIndexScanState *indexstate;
    bool        relistarget;

    /* check for unsupported flags */
    Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));

    /*
     * create state structure
     */
    indexstate = makeNode(BitmapIndexScanState);
    indexstate->ss.ps.plan = (Plan *) node;
    indexstate->ss.ps.state = estate;

    /* normally we don't make the result bitmap till runtime */
    indexstate->biss_result = NULL;

    /*
     * Miscellaneous initialization
     *
     * We do not need a standard exprcontext for this node, though we may
     * decide below to create a runtime-key exprcontext
     */

    /*
     * initialize child expressions
     *
     * We don't need to initialize targetlist or qual since neither are used.
     *
     * Note: we don't initialize all of the indexqual expression, only the
     * sub-parts corresponding to runtime keys (see below).
     */

    /*
     * We do not open or lock the base relation here.  We assume that an
     * ancestor BitmapHeapScan node is holding AccessShareLock (or better) on
     * the heap relation throughout the execution of the plan tree.
     */

    indexstate->ss.ss_currentRelation = NULL;
    indexstate->ss.ss_currentScanDesc = NULL;

    /*
     * If we are just doing EXPLAIN (ie, aren't going to run the plan), stop
     * here.  This allows an index-advisor plugin to EXPLAIN a plan containing
     * references to nonexistent indexes.
     */
    if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
        return indexstate;

    /*
     * Open the index relation.
     *
     * If the parent table is one of the target relations of the query, then
     * InitPlan already opened and write-locked the index, so we can avoid
     * taking another lock here.  Otherwise we need a normal reader's lock.
     */
    relistarget = ExecRelationIsTargetRelation(estate, node->scan.scanrelid);
    indexstate->biss_RelationDesc = index_open(node->indexid,
                                     relistarget ? NoLock : AccessShareLock);

    /*
     * Initialize index-specific scan state
     */
    indexstate->biss_RuntimeKeysReady = false;
    indexstate->biss_RuntimeKeys = NULL;
    indexstate->biss_NumRuntimeKeys = 0;

    /*
     * build the index scan keys from the index qualification
     */
    ExecIndexBuildScanKeys((PlanState *) indexstate,
                           indexstate->biss_RelationDesc,
                           node->indexqual,
                           false,
                           &indexstate->biss_ScanKeys,
                           &indexstate->biss_NumScanKeys,
                           &indexstate->biss_RuntimeKeys,
                           &indexstate->biss_NumRuntimeKeys,
                           &indexstate->biss_ArrayKeys,
                           &indexstate->biss_NumArrayKeys);

    /*
     * If we have runtime keys or array keys, we need an ExprContext to
     * evaluate them. We could just create a "standard" plan node exprcontext,
     * but to keep the code looking similar to nodeIndexscan.c, it seems
     * better to stick with the approach of using a separate ExprContext.
     */
    if (indexstate->biss_NumRuntimeKeys != 0 ||
        indexstate->biss_NumArrayKeys != 0)
    {
        ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;

        ExecAssignExprContext(estate, &indexstate->ss.ps);
        indexstate->biss_RuntimeContext = indexstate->ss.ps.ps_ExprContext;
        indexstate->ss.ps.ps_ExprContext = stdecontext;
    }
    else
    {
        indexstate->biss_RuntimeContext = NULL;
    }

    /*
     * Initialize scan descriptor.
     */
    indexstate->biss_ScanDesc =
        index_beginscan_bitmap(indexstate->biss_RelationDesc,
                               estate->es_snapshot,
                               indexstate->biss_NumScanKeys);

    /*
     * If no run-time keys to calculate, go ahead and pass the scankeys to the
     * index AM.
     */
    if (indexstate->biss_NumRuntimeKeys == 0 &&
        indexstate->biss_NumArrayKeys == 0)
        index_rescan(indexstate->biss_ScanDesc,
                     indexstate->biss_ScanKeys, indexstate->biss_NumScanKeys,
                     NULL, 0);

    /*
     * all done.
     */
    return indexstate;
}

void ExecReScanBitmapIndexScan ( BitmapIndexScanState node  ) 

Definition at line 116 of file nodeBitmapIndexscan.c.

References BitmapIndexScanState::biss_ArrayKeys, BitmapIndexScanState::biss_NumArrayKeys, BitmapIndexScanState::biss_NumRuntimeKeys, BitmapIndexScanState::biss_NumScanKeys, BitmapIndexScanState::biss_RuntimeContext, BitmapIndexScanState::biss_RuntimeKeys, BitmapIndexScanState::biss_RuntimeKeysReady, BitmapIndexScanState::biss_ScanDesc, BitmapIndexScanState::biss_ScanKeys, ExecIndexEvalArrayKeys(), ExecIndexEvalRuntimeKeys(), index_rescan(), NULL, and ResetExprContext.

Referenced by ExecReScan().

{
    ExprContext *econtext = node->biss_RuntimeContext;

    /*
     * Reset the runtime-key context so we don't leak memory as each outer
     * tuple is scanned.  Note this assumes that we will recalculate *all*
     * runtime keys on each call.
     */
    if (econtext)
        ResetExprContext(econtext);

    /*
     * If we are doing runtime key calculations (ie, any of the index key
     * values weren't simple Consts), compute the new key values.
     *
     * Array keys are also treated as runtime keys; note that if we return
     * with biss_RuntimeKeysReady still false, then there is an empty array
     * key so no index scan is needed.
     */
    if (node->biss_NumRuntimeKeys != 0)
        ExecIndexEvalRuntimeKeys(econtext,
                                 node->biss_RuntimeKeys,
                                 node->biss_NumRuntimeKeys);
    if (node->biss_NumArrayKeys != 0)
        node->biss_RuntimeKeysReady =
            ExecIndexEvalArrayKeys(econtext,
                                   node->biss_ArrayKeys,
                                   node->biss_NumArrayKeys);
    else
        node->biss_RuntimeKeysReady = true;

    /* reset index scan */
    if (node->biss_RuntimeKeysReady)
        index_rescan(node->biss_ScanDesc,
                     node->biss_ScanKeys, node->biss_NumScanKeys,
                     NULL, 0);
}

Node* MultiExecBitmapIndexScan ( BitmapIndexScanState node  ) 

Definition at line 36 of file nodeBitmapIndexscan.c.

References BitmapIndexScanState::biss_ArrayKeys, BitmapIndexScanState::biss_NumArrayKeys, BitmapIndexScanState::biss_NumRuntimeKeys, BitmapIndexScanState::biss_NumScanKeys, BitmapIndexScanState::biss_result, BitmapIndexScanState::biss_RuntimeKeysReady, BitmapIndexScanState::biss_ScanDesc, BitmapIndexScanState::biss_ScanKeys, CHECK_FOR_INTERRUPTS, ExecIndexAdvanceArrayKeys(), ExecReScan(), index_getbitmap(), index_rescan(), InstrStartNode(), InstrStopNode(), PlanState::instrument, NULL, ScanState::ps, BitmapIndexScanState::ss, tbm_create(), and work_mem.

Referenced by MultiExecProcNode().

{
    TIDBitmap  *tbm;
    IndexScanDesc scandesc;
    double      nTuples = 0;
    bool        doscan;

    /* must provide our own instrumentation support */
    if (node->ss.ps.instrument)
        InstrStartNode(node->ss.ps.instrument);

    /*
     * extract necessary information from index scan node
     */
    scandesc = node->biss_ScanDesc;

    /*
     * If we have runtime keys and they've not already been set up, do it now.
     * Array keys are also treated as runtime keys; note that if ExecReScan
     * returns with biss_RuntimeKeysReady still false, then there is an empty
     * array key so we should do nothing.
     */
    if (!node->biss_RuntimeKeysReady &&
        (node->biss_NumRuntimeKeys != 0 || node->biss_NumArrayKeys != 0))
    {
        ExecReScan((PlanState *) node);
        doscan = node->biss_RuntimeKeysReady;
    }
    else
        doscan = true;

    /*
     * Prepare the result bitmap.  Normally we just create a new one to pass
     * back; however, our parent node is allowed to store a pre-made one into
     * node->biss_result, in which case we just OR our tuple IDs into the
     * existing bitmap.  (This saves needing explicit UNION steps.)
     */
    if (node->biss_result)
    {
        tbm = node->biss_result;
        node->biss_result = NULL;       /* reset for next time */
    }
    else
    {
        /* XXX should we use less than work_mem for this? */
        tbm = tbm_create(work_mem * 1024L);
    }

    /*
     * Get TIDs from index and insert into bitmap
     */
    while (doscan)
    {
        nTuples += (double) index_getbitmap(scandesc, tbm);

        CHECK_FOR_INTERRUPTS();

        doscan = ExecIndexAdvanceArrayKeys(node->biss_ArrayKeys,
                                           node->biss_NumArrayKeys);
        if (doscan)             /* reset index scan */
            index_rescan(node->biss_ScanDesc,
                         node->biss_ScanKeys, node->biss_NumScanKeys,
                         NULL, 0);
    }

    /* must provide our own instrumentation support */
    if (node->ss.ps.instrument)
        InstrStopNode(node->ss.ps.instrument, nTuples);

    return (Node *) tbm;
}