blob: 3e4edfae6e82587024175656ccb47d6a237fafd8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*-------------------------------------------------------------------------
*
* nodeBitmapIndexscan.c
* Routines to support bitmapped index scans of relations
*
* Portions Copyright (c) 2007-2008, Greenplum inc
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapIndexscan.c,v 1.21 2006/10/04 00:29:52 momjian Exp $
*
*-------------------------------------------------------------------------
*/
/*
* INTERFACE ROUTINES
* MultiExecBitmapIndexScan scans a relation using index.
* ExecInitBitmapIndexScan creates and initializes state info.
* ExecBitmapIndexReScan prepares to rescan the plan.
* ExecEndBitmapIndexScan releases all storage.
*/
#include "postgres.h"
#include "access/genam.h"
#include "cdb/cdbvars.h"
#include "cdb/cdbpartition.h"
#include "executor/execdebug.h"
#include "executor/execDynamicScan.h"
#include "executor/instrument.h"
#include "executor/nodeBitmapIndexscan.h"
#include "executor/nodeIndexscan.h"
#include "miscadmin.h"
#include "utils/memutils.h"
#include "utils/lsyscache.h"
#include "nodes/tidbitmap.h"
#define BITMAPINDEXSCAN_NSLOTS 0
/* ----------------------------------------------------------------
* MultiExecBitmapIndexScan(node)
* ----------------------------------------------------------------
*/
Node *
MultiExecBitmapIndexScan(BitmapIndexScanState *node)
{
IndexScanState *scanState = (IndexScanState*)node;
Node *bitmap = NULL;
/* must provide our own instrumentation support */
if (scanState->ss.ps.instrument)
{
InstrStartNode(scanState->ss.ps.instrument);
}
bool partitionIsReady = DynamicScan_BeginIndexPartition(scanState, false /* initQual */,
false /* initTargetList */, true /* supportsArrayKeys */,
true /* isMultiScan */);
Assert(partitionIsReady);
if (!partitionIsReady)
{
DynamicScan_EndIndexPartition(scanState);
return NULL;
}
bool doscan = node->indexScanState.iss_RuntimeKeysReady;
IndexScanDesc scandesc = scanState->iss_ScanDesc;
/* Get bitmap from index */
while (doscan)
{
bitmap = index_getmulti(scandesc, node->bitmap);
if ((NULL != bitmap) &&
!(IsA(bitmap, HashBitmap) || IsA(bitmap, StreamBitmap)))
{
elog(ERROR, "unrecognized result from bitmap index scan");
}
CHECK_FOR_INTERRUPTS();
/* CDB: If EXPLAIN ANALYZE, let bitmap share our Instrumentation. */
if (scanState->ss.ps.instrument)
{
tbm_bitmap_set_instrument(bitmap, scanState->ss.ps.instrument);
}
if(node->bitmap == NULL)
{
node->bitmap = (Node *)bitmap;
}
doscan = ExecIndexAdvanceArrayKeys(scanState->iss_ArrayKeys,
scanState->iss_NumArrayKeys);
if (doscan)
{
/* reset index scan */
index_rescan(scanState->iss_ScanDesc, scanState->iss_ScanKeys);
}
}
DynamicScan_EndIndexPartition(scanState);
/* must provide our own instrumentation support */
if (scanState->ss.ps.instrument)
{
InstrStopNode(scanState->ss.ps.instrument, 1 /* nTuples */);
}
return (Node *) bitmap;
}
/* ----------------------------------------------------------------
* ExecBitmapIndexReScan(node)
*
* Recalculates the value of the scan keys whose value depends on
* information known at runtime and rescans the indexed relation.
* ----------------------------------------------------------------
*/
void
ExecBitmapIndexReScan(BitmapIndexScanState *node, ExprContext *exprCtxt)
{
IndexScanState *scanState = (IndexScanState*)node;
DynamicScan_RescanIndex(scanState, exprCtxt, false, false, true);
/* Sanity check */
if ((node->bitmap) && (!IsA(node->bitmap, HashBitmap) && !IsA(node->bitmap, StreamBitmap)))
{
ereport(ERROR,
(errcode(ERRCODE_GP_INTERNAL_ERROR),
errmsg("the returning bitmap in nodeBitmapIndexScan is invalid.")));
}
/* reset hashBitmap */
if(node->bitmap && IsA(node->bitmap, HashBitmap))
{
tbm_free((HashBitmap *)node->bitmap);
node->bitmap = NULL;
}
else
{
/* XXX: we leak here */
/* XXX: put in own memory context? */
node->bitmap = NULL;
}
Gpmon_M_Incr(GpmonPktFromBitmapIndexScanState(node), GPMON_BITMAPINDEXSCAN_RESCAN);
CheckSendPlanStateGpmonPkt(&scanState->ss.ps);
}
/* ----------------------------------------------------------------
* ExecEndBitmapIndexScan
* ----------------------------------------------------------------
*/
void
ExecEndBitmapIndexScan(BitmapIndexScanState *node)
{
IndexScanState *scanState = (IndexScanState*)node;
DynamicScan_EndIndexScan(scanState);
Assert(SCAN_END == scanState->ss.scan_state);
EndPlanStateGpmonPkt(&scanState->ss.ps);
}
/* ----------------------------------------------------------------
* ExecInitBitmapIndexScan
*
* Initializes the index scan's state information.
* ----------------------------------------------------------------
*/
BitmapIndexScanState *
ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
{
BitmapIndexScanState *indexstate;
/* check for unsupported flags */
Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
/*
* create state structure
*/
indexstate = makeNode(BitmapIndexScanState);
IndexScanState *scanState = (IndexScanState*)indexstate;
scanState->ss.ps.plan = (Plan *) node;
scanState->ss.ps.state = estate;
DynamicScan_BeginIndexScan(scanState, false, false, true);
/*
* 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.
*/
Assert(NULL == scanState->ss.ss_currentRelation);
initGpmonPktForBitmapIndexScan((Plan *)node, &scanState->ss.ps.gpmon_pkt, estate);
return indexstate;
}
int
ExecCountSlotsBitmapIndexScan(BitmapIndexScan *node)
{
return ExecCountSlotsNode(outerPlan((Plan *) node)) +
ExecCountSlotsNode(innerPlan((Plan *) node)) + BITMAPINDEXSCAN_NSLOTS;
}
void
initGpmonPktForBitmapIndexScan(Plan *planNode, gpmon_packet_t *gpmon_pkt, EState *estate)
{
Assert(NULL != planNode && NULL != gpmon_pkt && IsA(planNode, BitmapIndexScan));
{
char *relname = get_rel_name(((BitmapIndexScan *)planNode)->indexid);
Assert(GPMON_BITMAPINDEXSCAN_TOTAL <= (int)GPMON_QEXEC_M_COUNT);
InitPlanNodeGpmonPkt(planNode, gpmon_pkt, estate, PMNT_BitmapIndexScan,
(int64)planNode->plan_rows,
relname);
if (NULL != relname)
{
pfree(relname);
}
}
}