void parquet_getnext(ParquetScanDesc scan, ScanDirection direction, TupleTableSlot *slot) { AOTupleId aoTupleId; Assert(ScanDirectionIsForward(direction)); for(;;) { if(scan->bufferDone) { /* * Get the next row group. We call this function until we * successfully get a block to process, or finished reading * all the data (all 'segment' files) for this relation. */ while(!getNextRowGroup(scan)) { /* have we read all this relation's data. done! */ if(scan->pqs_done_all_splits) { ExecClearTuple(slot); return /*NULL*/; } } scan->bufferDone = false; } bool tupleExist = ParquetRowGroupReader_ScanNextTuple( scan->pqs_tupDesc, &scan->rowGroupReader, scan->hawqAttrToParquetColChunks, scan->proj, slot); if(tupleExist) { int segno = ((FileSplitNode *)list_nth(scan->splits, scan->pqs_splits_processed - 1))->segno; AOTupleIdInit_Init(&aoTupleId); AOTupleIdInit_segmentFileNum(&aoTupleId, segno); scan->cur_seg_row++; AOTupleIdInit_rowNum(&aoTupleId, scan->cur_seg_row); scan->cdb_fake_ctid = *((ItemPointer)&aoTupleId); slot_set_ctid(slot, &(scan->cdb_fake_ctid)); return; } /* no more items in the row group, get new buffer */ scan->bufferDone = true; } }
Oid parquet_insert_values(ParquetInsertDesc parquetInsertDesc, Datum *values, bool *nulls, AOTupleId *aoTupleId) { ParquetRowGroup rowgroup; MemoryContext oldMemoryContext; oldMemoryContext = MemoryContextSwitchTo(parquetInsertDesc->memoryContext); if (parquetInsertDesc->current_rowGroup == NULL) /* TODO maybe create in insert_init phase */ { parquetInsertDesc->current_rowGroup = addRowGroup(parquetInsertDesc->parquetMetadata, parquetInsertDesc->parquet_rel->rd_att, parquetInsertDesc->aoEntry, parquetInsertDesc->parquet_file); } rowgroup = parquetInsertDesc->current_rowGroup; if (rowgroup->rowGroupMetadata->totalByteSize >= rowgroup->catalog->blocksize) { flushRowGroup(rowgroup, parquetInsertDesc->parquetMetadata, parquetInsertDesc->mirroredOpen, parquetInsertDesc->footerProtocol, &parquetInsertDesc->fileLen, &parquetInsertDesc->fileLen_uncompressed); rowgroup = addRowGroup(parquetInsertDesc->parquetMetadata, parquetInsertDesc->parquet_rel->rd_att, parquetInsertDesc->aoEntry, parquetInsertDesc->parquet_file); parquetInsertDesc->current_rowGroup = rowgroup; } Assert(parquetInsertDesc->parquet_file == rowgroup->parquetFile); appendRowValue(rowgroup, parquetInsertDesc->parquetMetadata, values, nulls); parquetInsertDesc->insertCount++; parquetInsertDesc->rowCount++; /* Allocation is done. Go back to caller memory-context. */ MemoryContextSwitchTo(oldMemoryContext); AOTupleIdInit_Init(aoTupleId); AOTupleIdInit_segmentFileNum(aoTupleId, parquetInsertDesc->cur_segno); AOTupleIdInit_rowNum(aoTupleId, parquetInsertDesc->rowCount); return InvalidOid; }
static Datum gp_aovisimap_internal(PG_FUNCTION_ARGS, Oid aoRelOid) { Datum values[3]; bool nulls[3]; HeapTuple tuple; Datum result; typedef struct Context { Relation aorel; AppendOnlyVisimapScan visiMapScan; AOTupleId aoTupleId; } 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(3, false); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "tid", TIDOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 2, "segno", INT4OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 3, "row_num", INT8OID, -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->aorel = heap_open(aoRelOid, AccessShareLock); if (!(RelationIsAoRows(context->aorel) || RelationIsAoCols(context->aorel))) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("Function not supported on relation"))); } AppendOnlyVisimapScan_Init(&context->visiMapScan, context->aorel->rd_appendonly->visimaprelid, context->aorel->rd_appendonly->visimapidxid, AccessShareLock, SnapshotNow); AOTupleIdInit_Init(&context->aoTupleId); funcctx->user_fctx = (void *) context; MemoryContextSwitchTo(oldcontext); } funcctx = SRF_PERCALL_SETUP(); context = (Context *) funcctx->user_fctx; while (true) { if (!AppendOnlyVisimapScan_GetNextInvisible( &context->visiMapScan, &context->aoTupleId)) { break; } MemSet(values, 0, sizeof(values)); MemSet(nulls, false, sizeof(nulls)); values[0] = ItemPointerGetDatum((ItemPointer)&context->aoTupleId); values[1] = Int32GetDatum(AOTupleIdGet_segmentFileNum(&context->aoTupleId)); values[2] = Int64GetDatum(AOTupleIdGet_rowNum(&context->aoTupleId)); tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); SRF_RETURN_NEXT(funcctx, result); } AppendOnlyVisimapScan_Finish(&context->visiMapScan, AccessShareLock); heap_close(context->aorel, AccessShareLock); pfree(context); funcctx->user_fctx = NULL; SRF_RETURN_DONE(funcctx); }