/* * Returns true iff there are entries stored for the * given segment file num. */ bool AppendOnlyVisimapStore_IsSegmentFileFullyVisible( AppendOnlyVisimapStore *visiMapStore, int segmentFileNum) { ScanKeyData scanKey; IndexScanDesc indexScan; bool found_visimap_entry; Assert(visiMapStore); Assert(RelationIsValid(visiMapStore->visimapRelation)); Assert(RelationIsValid(visiMapStore->visimapIndex)); ScanKeyInit(&scanKey, Anum_pg_aovisimap_segno, /* segno */ BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(segmentFileNum)); indexScan = AppendOnlyVisimapStore_BeginScan( visiMapStore, 1, &scanKey); found_visimap_entry = AppendOnlyVisimapStore_GetNext( visiMapStore, indexScan, ForwardScanDirection, NULL, NULL); AppendOnlyVisimapStore_EndScan(visiMapStore, indexScan); return !found_visimap_entry; }
/* * Returns the number of hidden tuples in a given releation */ int64 AppendOnlyVisimapStore_GetRelationHiddenTupleCount( AppendOnlyVisimapStore *visiMapStore, AppendOnlyVisimapEntry *visiMapEntry) { IndexScanDesc indexScan; int64 hiddenTupcount = 0; Assert(visiMapStore); Assert(visiMapEntry); Assert(RelationIsValid(visiMapStore->visimapRelation)); Assert(RelationIsValid(visiMapStore->visimapIndex)); indexScan = AppendOnlyVisimapStore_BeginScan( visiMapStore, 0, NULL); while (AppendOnlyVisimapStore_GetNext(visiMapStore, indexScan, ForwardScanDirection, visiMapEntry, NULL)) { hiddenTupcount += AppendOnlyVisimapEntry_GetHiddenTupleCount(visiMapEntry); } AppendOnlyVisimapStore_EndScan(visiMapStore, indexScan); return hiddenTupcount; }
/* * Returns the number of hidden tuples in a given segment file */ int64 AppendOnlyVisimapStore_GetSegmentFileHiddenTupleCount( AppendOnlyVisimapStore *visiMapStore, AppendOnlyVisimapEntry *visiMapEntry, int segmentFileNum) { ScanKeyData scanKey; IndexScanDesc indexScan; int64 hiddenTupcount = 0; Assert(visiMapStore); Assert(visiMapEntry); Assert(RelationIsValid(visiMapStore->visimapRelation)); Assert(RelationIsValid(visiMapStore->visimapIndex)); ScanKeyInit(&scanKey, Anum_pg_aovisimap_segno, /* segno */ BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(segmentFileNum)); indexScan = AppendOnlyVisimapStore_BeginScan( visiMapStore, 1, &scanKey); while (AppendOnlyVisimapStore_GetNext(visiMapStore, indexScan, ForwardScanDirection, visiMapEntry, NULL)) { hiddenTupcount += AppendOnlyVisimapEntry_GetHiddenTupleCount(visiMapEntry); } AppendOnlyVisimapStore_EndScan(visiMapStore, indexScan); return hiddenTupcount; }
/** * Finds the visibility map entry tuple for a given * segmentFileNum and firstRowNum. * * Note: The firstRowNum needs to be a valid firstRowNum. It is * especially not the tuple id of the append-only tuple checked, updated, * or deleted. * * Returns true if there is such a tuple and * the tuple is used as current tuple. * Otherwise false is returned. * * Assumes that the store data structure has been initialized, but not finished. */ bool AppendOnlyVisimapStore_Find( AppendOnlyVisimapStore* visiMapStore, int32 segmentFileNum, int64 firstRowNum, AppendOnlyVisimapEntry* visiMapEntry) { ScanKey scanKeys; IndexScanDesc indexScan; Assert(visiMapStore); Assert(visiMapEntry); Assert(RelationIsValid(visiMapStore->visimapRelation)); Assert(RelationIsValid(visiMapStore->visimapIndex)); elogif (Debug_appendonly_print_visimap, LOG, "Append-only visi map store: Load entry: " "(segFileNum, firstRowNum) = (%u, " INT64_FORMAT ")", segmentFileNum, firstRowNum); scanKeys = visiMapStore->scanKeys; scanKeys[0].sk_argument = Int32GetDatum(segmentFileNum); scanKeys[1].sk_argument = Int64GetDatum(firstRowNum); indexScan = AppendOnlyVisimapStore_BeginScan( visiMapStore, APPENDONLY_VISIMAP_INDEX_SCAN_KEY_NUM, scanKeys); if (!AppendOnlyVisimapStore_GetNext( visiMapStore, indexScan, BackwardScanDirection, visiMapEntry, &visiMapEntry->tupleTid)) { elogif(Debug_appendonly_print_visimap, LOG, "Append-only visi map store: Visimap entry does not exist: " "(segFileNum, firstRowNum) = (%u, " INT64_FORMAT ")", segmentFileNum, firstRowNum); // failed to lookup row AppendOnlyVisimapStore_EndScan(visiMapStore, indexScan); return false; } AppendOnlyVisimapStore_EndScan(visiMapStore, indexScan); return true; }
/* * Deletes all visibility map information from a given * segment file. */ void AppendOnlyVisimapStore_DeleteSegmentFile( AppendOnlyVisimapStore *visiMapStore, int segmentFileNum) { ScanKeyData scanKey; IndexScanDesc indexScan; ItemPointerData tid; Assert(visiMapStore); Assert(RelationIsValid(visiMapStore->visimapRelation)); Assert(RelationIsValid(visiMapStore->visimapIndex)); elogif(Debug_appendonly_print_visimap, LOG, "Append-only visi map store: Delete segment file: " "(segFileNum) = (%u)", segmentFileNum); ScanKeyInit(&scanKey, Anum_pg_aovisimap_segno, /* segno */ BTEqualStrategyNumber, F_INT4EQ, Int32GetDatum(segmentFileNum)); indexScan = AppendOnlyVisimapStore_BeginScan( visiMapStore, 1, &scanKey); while (AppendOnlyVisimapStore_GetNext(visiMapStore, indexScan, ForwardScanDirection, NULL, &tid)) { simple_heap_delete(visiMapStore->visimapRelation, &tid); } AppendOnlyVisimapStore_EndScan(visiMapStore, indexScan); }
/* * Returns true iff there are entries of the relation are visible */ bool AppendOnlyVisimapStore_IsRelationFullyVisible( AppendOnlyVisimapStore *visiMapStore) { IndexScanDesc indexScan; bool found_visimap_entry; Assert(visiMapStore); Assert(RelationIsValid(visiMapStore->visimapRelation)); Assert(RelationIsValid(visiMapStore->visimapIndex)); indexScan = AppendOnlyVisimapStore_BeginScan( visiMapStore, 0, NULL); found_visimap_entry = AppendOnlyVisimapStore_GetNext( visiMapStore, indexScan, ForwardScanDirection, NULL, NULL); AppendOnlyVisimapStore_EndScan(visiMapStore, indexScan); return !found_visimap_entry; }
static Datum gp_aovisimap_entry_internal(PG_FUNCTION_ARGS, Oid aoRelOid) { Datum values[4]; bool nulls[4]; HeapTuple tuple; Datum result; typedef struct Context { AppendOnlyVisimap visiMap; Relation parentRelation; IndexScanDesc indexScan; text *bitmapBuffer; } Context; FuncCallContext *funcctx; Context *context; if (SRF_IS_FIRSTCALL()) { TupleDesc tupdesc; MemoryContext oldcontext; /* create a function context for cross-call persistence */ funcctx = SRF_FIRSTCALL_INIT(); /* * switch to memory context appropriate for multiple function * calls */ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); /* build tupdesc for result tuples */ tupdesc = CreateTemplateTupleDesc(4, false); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "segno", INT4OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 2, "first_row_num", INT8OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 3, "hidden_tupcount", INT4OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 4, "bitmap", TEXTOID, -1, 0); funcctx->tuple_desc = BlessTupleDesc(tupdesc); /* * Collect all the locking information that we will format and send * out as a result set. */ context = (Context *) palloc0(sizeof(Context)); context->parentRelation = heap_open(aoRelOid, AccessShareLock); if (!(RelationIsAoRows(context->parentRelation) || RelationIsAoCols(context->parentRelation))) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Function not supported on relation"))); } AppendOnlyVisimap_Init(&context->visiMap, context->parentRelation->rd_appendonly->visimaprelid, context->parentRelation->rd_appendonly->visimapidxid, AccessShareLock, SnapshotNow); context->indexScan = AppendOnlyVisimapStore_BeginScan(& context->visiMap.visimapStore, 0, NULL); context->bitmapBuffer = palloc0(VARHDRSZ + APPENDONLY_VISIMAP_MAX_RANGE + 1); funcctx->user_fctx = (void *) context; MemoryContextSwitchTo(oldcontext); } funcctx = SRF_PERCALL_SETUP(); context = (Context *) funcctx->user_fctx; if (AppendOnlyVisimapStore_GetNext(&context->visiMap.visimapStore, context->indexScan, ForwardScanDirection, &context->visiMap.visimapEntry, NULL)) { AppendOnlyVisimapEntry *visimapEntry = &context->visiMap.visimapEntry; MemSet(values, 0, sizeof(values)); MemSet(nulls, false, sizeof(nulls)); values[0] = Int32GetDatum(visimapEntry->segmentFileNum); values[1] = Int64GetDatum(visimapEntry->firstRowNum); values[2] = Int32GetDatum( (int32)AppendOnlyVisimapEntry_GetHiddenTupleCount(visimapEntry)); gp_aovisimap_encode_bitmap(VARDATA(context->bitmapBuffer), visimapEntry->bitmap); SET_VARSIZE(context->bitmapBuffer, APPENDONLY_VISIMAP_MAX_RANGE); values[3] = PointerGetDatum(context->bitmapBuffer); tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); SRF_RETURN_NEXT(funcctx, result); } AppendOnlyVisimapStore_EndScan(&context->visiMap.visimapStore, context->indexScan); AppendOnlyVisimap_Finish(&context->visiMap, AccessShareLock); heap_close(context->parentRelation, AccessShareLock); pfree(context->bitmapBuffer); pfree(context); funcctx->user_fctx = NULL; SRF_RETURN_DONE(funcctx); }