blob: 94ef8f4979978cf33168f38a245495160898cf09 [file] [log] [blame]
/*
* execBitmapAOScan.c
* Support routines for scanning AO and AOCO tables using bitmaps.
*
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*/
#include "postgres.h"
#include "access/heapam.h"
#include "executor/execdebug.h"
#include "executor/nodeBitmapAppendOnlyscan.h"
#include "cdb/cdbappendonlyam.h"
#include "pgstat.h"
#include "utils/memutils.h"
#include "miscadmin.h"
#include "parser/parsetree.h"
#include "cdb/cdbvars.h" /* gp_select_invisible */
#include "nodes/tidbitmap.h"
typedef struct
{
int tupleIndex;
int nTuples;
} AOIteratorState;
/*
* Prepares for a new AO scan.
*/
void
BitmapAOScanBegin(ScanState *scanState)
{
BitmapTableScanState *node = (BitmapTableScanState *)(scanState);
Relation currentRelation = node->ss.ss_currentRelation;
EState *estate = node->ss.ps.state;
if (scanState->tableType == TableTypeAppendOnly)
{
node->scanDesc =
appendonly_fetch_init(currentRelation,
estate->es_snapshot);
}
else if (scanState->tableType == TableTypeParquet)
{
Assert(!"BitmapScan for Parquet is not supported yet");
/*
* Obtain the projection.
*/
Assert(currentRelation->rd_att != NULL);
bool *proj = (bool *)palloc0(sizeof(bool) * currentRelation->rd_att->natts);
GetNeededColumnsForScan((Node *) node->ss.ps.plan->targetlist, proj, currentRelation->rd_att->natts);
GetNeededColumnsForScan((Node *) node->ss.ps.plan->qual, proj, currentRelation->rd_att->natts);
int colno = 0;
/* Check if any column is projected */
for(colno = 0; colno < currentRelation->rd_att->natts; colno++)
{
if(proj[colno])
{
break;
}
}
/*
* At least project one column. Since the tids stored in the index may not have
* a corresponding tuple any more (because of previous crashes, for example), we
* need to read the tuple to make sure.
*/
if(colno == currentRelation->rd_att->natts)
{
proj[0] = true;
}
/*
node->scanDesc =
parquet_fetch_init(currentRelation, estate->es_snapshot, proj);
*/
}
else
{
Assert(!"Invalid table type");
}
/*
* AO doesn't need rechecking every tuple once it resolves
* from the bitmap page, except when it deals with lossy
* bitmap, which is handled via scanState->isLossyBitmapPage.
*/
node->recheckTuples = false;
}
/*
* Cleans up after the scanning is done.
*/
void
BitmapAOScanEnd(ScanState *scanState)
{
BitmapTableScanState *node = (BitmapTableScanState *)scanState;
Assert(node->ss.scan_state == SCAN_SCAN);
if (scanState->tableType == TableTypeAppendOnly)
{
appendonly_fetch_finish((AppendOnlyFetchDesc)node->scanDesc);
}
else if (scanState->tableType == TableTypeParquet)
{
Assert(!"BitmapScan for Parquet is not supported yet");
/*
pfree(((AOCSFetchDesc)node->scanDesc)->proj);
aocs_fetch_finish(node->scanDesc);
*/
}
else
{
Assert(!"Invalid table type");
}
pfree(node->scanDesc);
node->scanDesc = NULL;
if (node->iterator)
{
pfree(node->iterator);
node->iterator = NULL;
}
}
/*
* Returns the next matching tuple.
*/
TupleTableSlot *
BitmapAOScanNext(ScanState *scanState)
{
BitmapTableScanState *node = (BitmapTableScanState *)scanState;
TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
TBMIterateResult *tbmres = (TBMIterateResult *)node->tbmres;
/* Make sure we never cross 15-bit offset number [MPP-24326] */
Assert(tbmres->ntuples <= INT16_MAX + 1);
OffsetNumber psuedoHeapOffset;
ItemPointerData psudeoHeapTid;
AOTupleId aoTid;
Assert(tbmres != NULL && tbmres->ntuples != 0);
Assert(node->needNewBitmapPage == false);
AOIteratorState *iterator = (AOIteratorState *)node->iterator;
for (;;)
{
CHECK_FOR_INTERRUPTS();
if (iterator == NULL)
{
iterator = palloc0(sizeof(AOIteratorState));
if (node->isLossyBitmapPage)
{
/* Iterate over the first 2^15 tuples [MPP-24326] */
iterator->nTuples = INT16_MAX + 1;
}
else
{
iterator->nTuples = tbmres->ntuples;
}
/* Start from the beginning of the page */
iterator->tupleIndex = 0;
node->iterator = iterator;
}
else
{
/*
* Continuing in previously obtained page; advance tupleIndex
*/
iterator->tupleIndex++;
}
/*
* Out of range? If so, nothing more to look at on this page
*/
if (iterator->tupleIndex < 0 || iterator->tupleIndex >= iterator->nTuples)
{
pfree(iterator);
node->iterator = NULL;
node->needNewBitmapPage = true;
return ExecClearTuple(slot);
}
/*
* Must account for lossy page info...
*/
if (node->isLossyBitmapPage)
{
/* We are iterating through all items. */
psuedoHeapOffset = iterator->tupleIndex;
}
else
{
Assert(iterator->tupleIndex <= tbmres->ntuples);
psuedoHeapOffset = tbmres->offsets[iterator->tupleIndex];
/*
* Ensure that the reserved 16-th bit is always ON for offsets from
* lossless bitmap pages [MPP-24326].
*/
Assert(((uint16)(psuedoHeapOffset & 0x8000)) > 0);
}
/*
* Okay to fetch the tuple
*/
ItemPointerSet(
&psudeoHeapTid,
tbmres->blockno,
psuedoHeapOffset);
tbm_convert_appendonly_tid_out(&psudeoHeapTid, &aoTid);
if (scanState->tableType == TableTypeAppendOnly)
{
appendonly_fetch((AppendOnlyFetchDesc)node->scanDesc, &aoTid, slot);
}
else if (scanState->tableType == TableTypeParquet)
{
Assert(!"BitmapScan for Parquet is not supported yet");
/*
Assert(scanState->tableType == TableTypeAOCS);
aocs_fetch((AOCSFetchDesc)node->scanDesc, &aoTid, slot);
*/
}
if (TupIsNull(slot))
{
continue;
}
Assert(ItemPointerIsValid(slot_get_ctid(slot)));
pgstat_count_heap_fetch(node->ss.ss_currentRelation);
if (!BitmapTableScanRecheckTuple(node, slot))
{
ExecClearTuple(slot);
continue;
}
return slot;
}
/*
* We should never reach here as the termination is handled
* from nodeBitmapTableScan.
*/
Assert(false);
return NULL;
}
/*
* Prepares for a re-scan.
*/
void
BitmapAOScanReScan(ScanState *scanState)
{
/*
* As per the existing implementation from nodeBitmapAppendOnlyScan.c
* for rescanning of AO, we don't have anything specific
* to do here (the refactored BitmapTableScan takes care of everything).
*/
}