/* * Reads a bitmap (with possibly many pages) from the underlying node. */ static void readBitmap(BitmapTableScanState *scanState) { if (scanState->tbm != NULL) { return; } Node *tbm = (Node *) MultiExecProcNode(outerPlanState(scanState)); if (tbm != NULL && (!(IsA(tbm, HashBitmap) || IsA(tbm, StreamBitmap)))) { elog(ERROR, "unrecognized result from subplan"); } /* * When a HashBitmap is returned, set the returning bitmaps * in the subplan to NULL, so that the subplan nodes do not * mistakenly try to release the space during the rescan. */ if (tbm != NULL && IsA(tbm, HashBitmap)) { tbm_reset_bitmaps(outerPlanState(scanState)); } scanState->tbm = tbm; scanState->needNewBitmapPage = true; }
/** * Init nodeDML, which initializes the insert TupleTableSlot. * */ DMLState* ExecInitDML(DML *node, EState *estate, int eflags) { /* check for unsupported flags */ Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK | EXEC_FLAG_REWIND))); DMLState *dmlstate = makeNode(DMLState); dmlstate->ps.plan = (Plan *)node; dmlstate->ps.state = estate; ExecInitResultTupleSlot(estate, &dmlstate->ps); dmlstate->ps.targetlist = (List *) ExecInitExpr((Expr *) node->plan.targetlist, (PlanState *) dmlstate); Plan *outerPlan = outerPlan(node); outerPlanState(dmlstate) = ExecInitNode(outerPlan, estate, eflags); ExecAssignResultTypeFromTL(&dmlstate->ps); /* Create expression evaluation context. This will be used for projections */ ExecAssignExprContext(estate, &dmlstate->ps); /* * Create projection info from the child tuple descriptor and our target list * Projection will be placed in the ResultSlot */ TupleTableSlot *childResultSlot = outerPlanState(dmlstate)->ps_ResultTupleSlot; ExecAssignProjectionInfo(&dmlstate->ps, childResultSlot->tts_tupleDescriptor); /* * Initialize slot to insert/delete using output relation descriptor. */ dmlstate->cleanedUpSlot = ExecInitExtraTupleSlot(estate); /* * Both input and output of the junk filter include dropped attributes, so * the junk filter doesn't need to do anything special there about them */ TupleDesc cleanTupType = CreateTupleDescCopy(dmlstate->ps.state->es_result_relation_info->ri_RelationDesc->rd_att); dmlstate->junkfilter = ExecInitJunkFilter(node->plan.targetlist, cleanTupType, dmlstate->cleanedUpSlot); if (estate->es_instrument) { dmlstate->ps.cdbexplainbuf = makeStringInfo(); /* Request a callback at end of query. */ dmlstate->ps.cdbexplainfun = ExecDMLExplainEnd; } initGpmonPktForDML((Plan *)node, &dmlstate->ps.gpmon_pkt, estate); return dmlstate; }
/* ---------------------------------------------------------------- * ExecInitUnique * * This initializes the unique node state structures and * the node's subplan. * ---------------------------------------------------------------- */ UniqueState * ExecInitUnique(Unique *node, EState *estate, int eflags) { UniqueState *uniquestate; /* check for unsupported flags */ Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); /* * create state structure */ uniquestate = makeNode(UniqueState); uniquestate->ps.plan = (Plan *) node; uniquestate->ps.state = estate; /* * Miscellaneous initialization * * Unique nodes have no ExprContext initialization because they never call * ExecQual or ExecProject. But they do need a per-tuple memory context * anyway for calling execTuplesMatch. */ uniquestate->tempContext = AllocSetContextCreate(CurrentMemoryContext, "Unique", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); #define UNIQUE_NSLOTS 1 /* * Tuple table initialization */ ExecInitResultTupleSlot(estate, &uniquestate->ps); /* * then initialize outer plan */ outerPlanState(uniquestate) = ExecInitNode(outerPlan(node), estate, eflags); /* * unique nodes do no projections, so initialize projection info for this * node appropriately */ ExecAssignResultTypeFromTL(&uniquestate->ps); uniquestate->ps.ps_ProjInfo = NULL; /* * Precompute fmgr lookup data for inner loop */ uniquestate->eqfunctions = execTuplesMatchPrepare(ExecGetResultType(&uniquestate->ps), node->numCols, node->uniqColIdx); initGpmonPktForUnique((Plan *)node, &uniquestate->ps.gpmon_pkt, estate); return uniquestate; }
/* ---------------------------------------------------------------- * ExecReScanBitmapHeapScan(node) * ---------------------------------------------------------------- */ void ExecReScanBitmapHeapScan(BitmapHeapScanState *node) { PlanState *outerPlan = outerPlanState(node); /* rescan to release any page pin */ heap_rescan(node->ss.ss_currentScanDesc, NULL); if (node->tbmiterator) tbm_end_iterate(node->tbmiterator); if (node->prefetch_iterator) tbm_end_iterate(node->prefetch_iterator); if (node->tbm) tbm_free(node->tbm); node->tbm = NULL; node->tbmiterator = NULL; node->tbmres = NULL; node->prefetch_iterator = NULL; ExecScanReScan(&node->ss); /* * if chgParam of subnode is not null then plan will be re-scanned by * first ExecProcNode. */ if (outerPlan->chgParam == NULL) ExecReScan(outerPlan); }
/* ---------------------------------------------------------------- * ExecEndMaterial * ---------------------------------------------------------------- */ void ExecEndMaterial(MaterialState *node) { ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot); ExecEagerFreeMaterial(node); /* * Release tuplestore resources for cases where EagerFree doesn't do it */ if (node->ts_state->matstore != NULL) { Material *ma = (Material *) node->ss.ps.plan; if (ma->share_type == SHARE_MATERIAL_XSLICE && node->share_lk_ctxt) { shareinput_writer_waitdone(node->share_lk_ctxt, ma->share_id, ma->nsharer_xslice); } Assert(node->ts_pos); DestroyTupleStore(node); } /* * shut down the subplan */ ExecEndNode(outerPlanState(node)); EndPlanStateGpmonPkt(&node->ss.ps); }
/* ---------------------------------------------------------------- * ExecReScanRecursiveUnion * * Rescans the relation. * ---------------------------------------------------------------- */ void ExecReScanRecursiveUnion(RecursiveUnionState *node) { PlanState *outerPlan = outerPlanState(node); PlanState *innerPlan = innerPlanState(node); RecursiveUnion *plan = (RecursiveUnion *) node->ps.plan; /* * Set recursive term's chgParam to tell it that we'll modify the working * table and therefore it has to rescan. */ innerPlan->chgParam = bms_add_member(innerPlan->chgParam, plan->wtParam); /* * if chgParam of subnode is not null then plan will be re-scanned by * first ExecProcNode. Because of above, we only have to do this to the * non-recursive term. */ if (outerPlan->chgParam == NULL) ExecReScan(outerPlan); /* Release any hashtable storage */ if (node->tableContext) MemoryContextResetAndDeleteChildren(node->tableContext); /* And rebuild empty hashtable if needed */ if (plan->numCols > 0) build_hash_table(node); /* reset processing state */ node->recursing = false; node->intermediate_empty = true; tuplestore_clear(node->working_table); tuplestore_clear(node->intermediate_table); }
/* * Prepares for scanning of a new partition/relation. */ void BitmapTableScanBeginPartition(ScanState *node, bool initExpressions) { Assert(node != NULL); BitmapTableScanState *scanState = (BitmapTableScanState *)node; Assert(SCAN_NEXT == scanState->ss.scan_state); initBitmapState(scanState); if (scanState->bitmapqualorig == NULL || initExpressions) { /* TODO rahmaf2 [JIRA: MPP-23293]: remap columns per-partition to handle dropped columns */ scanState->bitmapqualorig = (List *) ExecInitExpr((Expr *) ((BitmapTableScan*)(node->ps.plan))->bitmapqualorig, (PlanState *) scanState); } scanState->needNewBitmapPage = true; scanState->recheckTuples = true; getBitmapTableScanMethod(node->tableType)->beginScanMethod(node); /* * Prepare child node to produce new bitmaps for the new partition (and cleanup * any leftover state from old partition). */ ExecReScan(outerPlanState(node), NULL); }
/* * Prepares for a rescan. */ void BitmapTableScanReScan(BitmapTableScanState *node, ExprContext *exprCtxt) { ScanState *scanState = &node->ss; Assert(scanState->tableType >= 0 && scanState->tableType < TableTypeInvalid); /* * If we are being passed an outer tuple, link it into the "regular" * per-tuple econtext for possible qual eval. */ if (exprCtxt != NULL) { ExprContext *stdecontext = node->ss.ps.ps_ExprContext; stdecontext->ecxt_outertuple = exprCtxt->ecxt_outertuple; } EState *estate = node->ss.ps.state; Index scanrelid = ((Scan *)(scanState->ps.plan))->scanrelid; /* If this is re-scanning of PlanQual ... */ if (estate->es_evTuple != NULL && estate->es_evTuple[scanrelid - 1] != NULL) { estate->es_evTupleNull[scanrelid - 1] = false; } DynamicScan_ReScan((ScanState *)node, BitmapTableScanEndPartition, exprCtxt); ExecReScan(outerPlanState(node), exprCtxt); }
/* * Initializes the BitmapTableScanState, including creation of the * scan description and the bitmapqualorig. */ BitmapTableScanState * ExecInitBitmapTableScan(BitmapTableScan *node, EState *estate, int eflags) { /* check for unsupported flags */ Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); /* * Assert caller didn't ask for an unsafe snapshot --- see comments at * head of file. * * MPP-4703: the MVCC-snapshot restriction is required for correct results. * our test-mode may deliberately return incorrect results, but that's OK. */ Assert(IsMVCCSnapshot(estate->es_snapshot) || gp_select_invisible); BitmapTableScanState *state = makeNode(BitmapTableScanState); BitmapTableScanBegin(state, (Plan *) node, estate, eflags); /* * initialize child nodes * * We do this last because the child nodes will open indexscans on our * relation's indexes, and we want to be sure we have acquired a lock on * the relation first. */ outerPlanState(state) = ExecInitNode(outerPlan(node), estate, eflags); initGpmonPktForBitmapTableScan((Plan *)node, &state->ss.ps.gpmon_pkt, estate); return state; }
/* ---------------------------------------------------------------- * ExecEndNestLoop * * closes down scans and frees allocated storage * ---------------------------------------------------------------- */ void ExecEndNestLoop(NestLoopState *node) { NL1_printf("ExecEndNestLoop: %s\n", "ending node processing"); /* * Free the exprcontext */ ExecFreeExprContext(&node->js.ps); /* * clean out the tuple table */ ExecClearTuple(node->js.ps.ps_ResultTupleSlot); /* * close down subplans */ ExecEndNode(outerPlanState(node)); ExecEndNode(innerPlanState(node)); NL1_printf("ExecEndNestLoop: %s\n", "node processing ended"); }
/* * Frees the state relevant to bitmaps. */ static inline void freeBitmapState(BitmapTableScanState *scanstate) { if (scanstate->tbm != NULL) { if(IsA(scanstate->tbm, HashBitmap)) { tbm_free((HashBitmap *)scanstate->tbm); } else { tbm_bitmap_free(scanstate->tbm); } scanstate->tbm = NULL; } if (scanstate->tbmres != NULL) { pfree(scanstate->tbmres); scanstate->tbmres = NULL; } tbm_reset_bitmaps(outerPlanState(scanstate)); }
/* ---------------------------------------------------------------- * ExecEndSort(node) * ---------------------------------------------------------------- */ void ExecEndSort(SortState *node) { SO1_printf("ExecEndSort: %s\n", "shutting down sort node"); /* * clean out the tuple table */ ExecClearTuple(node->ss.ss_ScanTupleSlot); /* must drop pointer to sort result tuple */ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); /* * Release tuplesort resources */ if (node->tuplesortstate != NULL) tuplesort_end((Tuplesortstate *) node->tuplesortstate); node->tuplesortstate = NULL; /* * shut down the subplan */ ExecEndNode(outerPlanState(node)); SO1_printf("ExecEndSort: %s\n", "sort node shutdown"); }
/* ----------------- * ExecInitGroup * * Creates the run-time information for the group node produced by the * planner and initializes its outer subtree * ----------------- */ GroupState * ExecInitGroup(Group *node, EState *estate, int eflags) { GroupState *grpstate; /* check for unsupported flags */ Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); /* * create state structure */ grpstate = makeNode(GroupState); grpstate->ss.ps.plan = (Plan *) node; grpstate->ss.ps.state = estate; grpstate->ss.ps.ExecProcNode = ExecGroup; grpstate->grp_done = false; /* * create expression context */ ExecAssignExprContext(estate, &grpstate->ss.ps); /* * tuple table initialization */ ExecInitScanTupleSlot(estate, &grpstate->ss); ExecInitResultTupleSlot(estate, &grpstate->ss.ps); /* * initialize child expressions */ grpstate->ss.ps.qual = ExecInitQual(node->plan.qual, (PlanState *) grpstate); /* * initialize child nodes */ outerPlanState(grpstate) = ExecInitNode(outerPlan(node), estate, eflags); /* * initialize tuple type. */ ExecAssignScanTypeFromOuterPlan(&grpstate->ss); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&grpstate->ss.ps); ExecAssignProjectionInfo(&grpstate->ss.ps, NULL); /* * Precompute fmgr lookup data for inner loop */ grpstate->eqfunctions = execTuplesMatchPrepare(node->numCols, node->grpOperators); return grpstate; }
/* ---------------------------------------------------------------- * ExecInitResult * * Creates the run-time state information for the result node * produced by the planner and initailizes outer relations * (child nodes). * ---------------------------------------------------------------- */ ResultState * ExecInitResult(Result *node, EState *estate) { ResultState *resstate; /* * create state structure */ resstate = makeNode(ResultState); resstate->ps.plan = (Plan *) node; resstate->ps.state = estate; resstate->rs_done = false; resstate->rs_checkqual = (node->resconstantqual == NULL) ? false : true; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &resstate->ps); #define RESULT_NSLOTS 1 /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &resstate->ps); /* * initialize child expressions */ resstate->ps.targetlist = (List *) ExecInitExpr((Expr *) node->plan.targetlist, (PlanState *) resstate); resstate->ps.qual = (List *) ExecInitExpr((Expr *) node->plan.qual, (PlanState *) resstate); resstate->resconstantqual = ExecInitExpr((Expr *) node->resconstantqual, (PlanState *) resstate); /* * initialize child nodes */ outerPlanState(resstate) = ExecInitNode(outerPlan(node), estate); /* * we don't use inner plan */ Assert(innerPlan(node) == NULL); /* * initialize tuple type and projection info */ ExecAssignResultTypeFromTL(&resstate->ps); ExecAssignProjectionInfo(&resstate->ps); return resstate; }
/* ---------------------------------------------------------------- * ExecEndLimit * * This shuts down the subplan and frees resources allocated * to this node. * ---------------------------------------------------------------- */ void ExecEndLimit(LimitState *node) { ExecFreeExprContext(&node->ps); ExecEndNode(outerPlanState(node)); EndPlanStateGpmonPkt(&node->ps); }
/* ---------------------------------------------------------------- * ExecEndGatherMerge * * frees any storage allocated through C routines. * ---------------------------------------------------------------- */ void ExecEndGatherMerge(GatherMergeState *node) { ExecEndNode(outerPlanState(node)); /* let children clean up first */ ExecShutdownGatherMerge(node); ExecFreeExprContext(&node->ps); ExecClearTuple(node->ps.ps_ResultTupleSlot); }
/* ---------------------------------------------------------------- * ExecEndGather * * frees any storage allocated through C routines. * ---------------------------------------------------------------- */ void ExecEndGather(GatherState *node) { ExecShutdownGather(node); ExecFreeExprContext(&node->ps); ExecClearTuple(node->ps.ps_ResultTupleSlot); ExecEndNode(outerPlanState(node)); }
/* ---------------------------------------------------------------- * ExecInitHash * * Init routine for Hash node * ---------------------------------------------------------------- */ HashState * ExecInitHash(Hash *node, EState *estate, int eflags) { HashState *hashstate; /* check for unsupported flags */ Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); /* * create state structure */ hashstate = makeNode(HashState); hashstate->ps.plan = (Plan *) node; hashstate->ps.state = estate; hashstate->hashtable = NULL; hashstate->hashkeys = NIL; /* will be set by parent HashJoin */ /*CHANGED BY YASIN*/ if (eflags & EXEC_FLAG_INAROUND) hashstate->ps.ps_InAround = true; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &hashstate->ps); #define HASH_NSLOTS 1 /* * initialize our result slot */ ExecInitResultTupleSlot(estate, &hashstate->ps); /* * initialize child expressions */ hashstate->ps.targetlist = (List *) ExecInitExpr((Expr *) node->plan.targetlist, (PlanState *) hashstate); hashstate->ps.qual = (List *) ExecInitExpr((Expr *) node->plan.qual, (PlanState *) hashstate); /* * initialize child nodes */ outerPlanState(hashstate) = ExecInitNode(outerPlan(node), estate, eflags); /* * initialize tuple type. no need to initialize projection info because * this node doesn't do projections */ ExecAssignResultTypeFromTL(&hashstate->ps); hashstate->ps.ps_ProjInfo = NULL; return hashstate; }
/* ---------------------------------------------------------------- * ExecUnique * ---------------------------------------------------------------- */ TupleTableSlot * /* return: a tuple or NULL */ ExecUnique(UniqueState *node) { Unique *plannode = (Unique *) node->ps.plan; TupleTableSlot *resultTupleSlot; TupleTableSlot *slot; PlanState *outerPlan; /* * get information from the node */ outerPlan = outerPlanState(node); resultTupleSlot = node->ps.ps_ResultTupleSlot; /* * now loop, returning only non-duplicate tuples. We assume that the * tuples arrive in sorted order so we can detect duplicates easily. The * first tuple of each group is returned. */ for (;;) { /* * fetch a tuple from the outer subplan */ slot = ExecProcNode(outerPlan); if (TupIsNull(slot)) { /* end of subplan, so we're done */ ExecClearTuple(resultTupleSlot); return NULL; } /* * Always return the first tuple from the subplan. */ if (TupIsNull(resultTupleSlot)) break; /* * Else test if the new tuple and the previously returned tuple match. * If so then we loop back and fetch another new tuple from the * subplan. */ if (!execTuplesMatch(slot, resultTupleSlot, plannode->numCols, plannode->uniqColIdx, node->eqfunctions, node->tempContext)) break; } /* * We have a new tuple different from the previous saved tuple (if any). * Save it and return it. We must copy it because the source subplan * won't guarantee that this source tuple is still accessible after * fetching the next source tuple. */ return ExecCopySlot(resultTupleSlot, slot); }
/* ---------------------------------------------------------------- * ExecInitLimit * * This initializes the limit node state structures and * the node's subplan. * ---------------------------------------------------------------- */ LimitState * ExecInitLimit(Limit *node, EState *estate, int eflags) { LimitState *limitstate; Plan *outerPlan; /* check for unsupported flags */ Assert(!(eflags & EXEC_FLAG_MARK)); /* * create state structure */ limitstate = makeNode(LimitState); limitstate->ps.plan = (Plan *) node; limitstate->ps.state = estate; limitstate->lstate = LIMIT_INITIAL; /* * Miscellaneous initialization * * Limit nodes never call ExecQual or ExecProject, but they need an * exprcontext anyway to evaluate the limit/offset parameters in. */ ExecAssignExprContext(estate, &limitstate->ps); /* * initialize child expressions */ limitstate->limitOffset = ExecInitExpr((Expr *) node->limitOffset, (PlanState *) limitstate); limitstate->limitCount = ExecInitExpr((Expr *) node->limitCount, (PlanState *) limitstate); #define LIMIT_NSLOTS 1 /* * Tuple table initialization (XXX not actually used...) */ ExecInitResultTupleSlot(estate, &limitstate->ps); /* * then initialize outer plan */ outerPlan = outerPlan(node); outerPlanState(limitstate) = ExecInitNode(outerPlan, estate, eflags); /* * limit nodes do no projections, so initialize projection info for this * node appropriately */ ExecAssignResultTypeFromTL(&limitstate->ps); limitstate->ps.ps_ProjInfo = NULL; initGpmonPktForLimit((Plan *)node, &limitstate->ps.gpmon_pkt, estate); return limitstate; }
/* ---------------------------------------------------------------- * ExecHash * * build hash table for hashjoin, doing partitioning if more * than one batch is required. * ---------------------------------------------------------------- */ TupleTableSlot * ExecHash(HashState *node) { EState *estate; PlanState *outerNode; List *hashkeys; HashJoinTable hashtable; TupleTableSlot *slot; ExprContext *econtext; int nbatch; int i; /* * get state info from node */ estate = node->ps.state; outerNode = outerPlanState(node); hashtable = node->hashtable; nbatch = hashtable->nbatch; if (nbatch > 0) { /* * Open temp files for inner batches, if needed. Note that file * buffers are palloc'd in regular executor context. */ for (i = 0; i < nbatch; i++) hashtable->innerBatchFile[i] = BufFileCreateTemp(false); } /* * set expression context */ hashkeys = node->hashkeys; econtext = node->ps.ps_ExprContext; /* * get all inner tuples and insert into the hash table (or temp files) */ for (;;) { slot = ExecProcNode(outerNode); if (TupIsNull(slot)) break; hashtable->hashNonEmpty = true; econtext->ecxt_innertuple = slot; ExecHashTableInsert(hashtable, econtext, hashkeys); ExecClearTuple(slot); } /* * Return the slot so that we have the tuple descriptor when we need * to save/restore them. -Jeff 11 July 1991 */ return slot; }
void ExecEndTwice(TwiceState *node) { /* clean up tuple table */ ExecClearTuple(node->ps.ps_ResultTupleSlot); /* recursively clean up nodes in the plan rooted in this node */ ExecEndNode(outerPlanState(node)); }
/* ---------------------------------------------------------------- * ExecEndLimit * * This shuts down the subplan and frees resources allocated * to this node. * ---------------------------------------------------------------- */ void ExecEndLimit(LimitState *node) { ExecFreeExprContext(&node->ps); /* clean up tuple table */ ExecClearTuple(node->ps.ps_ResultTupleSlot); ExecEndNode(outerPlanState(node)); }
/* ---------------------------------------------------------------- * ExecEndUnique * * This shuts down the subplan and frees resources allocated * to this node. * ---------------------------------------------------------------- */ void ExecEndUnique(UniqueState *node) { /* clean up tuple table */ ExecClearTuple(node->ps.ps_ResultTupleSlot); MemoryContextDelete(node->tempContext); ExecEndNode(outerPlanState(node)); }
/* ---------------------------------------------------------------- * ExecResultRestrPos * ---------------------------------------------------------------- */ void ExecResultRestrPos(ResultState *node) { PlanState *outerPlan = outerPlanState(node); if (outerPlan != NULL) ExecRestrPos(outerPlan); else elog(ERROR, "Result nodes do not support mark/restore"); }
/* ---------------------------------------------------------------- * ExecResultMarkPos * ---------------------------------------------------------------- */ void ExecResultMarkPos(ResultState *node) { PlanState *outerPlan = outerPlanState(node); if (outerPlan != NULL) ExecMarkPos(outerPlan); else elog(DEBUG2, "Result nodes do not support mark/restore"); }
/* ---------------------------------------------------------------- * MultiExecHash * * build hash table for hashjoin, doing partitioning if more * than one batch is required. * ---------------------------------------------------------------- */ Node * MultiExecHash(HashState *node) { PlanState *outerNode; List *hashkeys; HashJoinTable hashtable; TupleTableSlot *slot; ExprContext *econtext; uint32 hashvalue; /* must provide our own instrumentation support */ if (node->ps.instrument) InstrStartNode(node->ps.instrument); /* * get state info from node */ outerNode = outerPlanState(node); hashtable = node->hashtable; /* * set expression context */ hashkeys = node->hashkeys; econtext = node->ps.ps_ExprContext; /* * get all inner tuples and insert into the hash table (or temp files) */ for (;;) { slot = ExecProcNode(outerNode); if (TupIsNull(slot)) break; hashtable->totalTuples += 1; /* We have to compute the hash value */ econtext->ecxt_innertuple = slot; hashvalue = ExecHashGetHashValue(hashtable, econtext, hashkeys); ExecHashTableInsert(hashtable, slot, hashvalue); } /* must provide our own instrumentation support */ if (node->ps.instrument) InstrStopNode(node->ps.instrument, hashtable->totalTuples); /* * We do not return the hash table directly because it's not a subtype of * Node, and so would violate the MultiExecProcNode API. Instead, our * parent Hashjoin node is expected to know how to fish it out of our node * state. Ugly but not really worth cleaning up, since Hashjoin knows * quite a bit more about Hash besides that. */ return NULL; }
/* ---------------------------------------------------------------- * ExecEndSetOp * * This shuts down the subplan and frees resources allocated * to this node. * ---------------------------------------------------------------- */ void ExecEndSetOp(SetOpState *node) { /* clean up tuple table */ ExecClearTuple(node->ps.ps_ResultTupleSlot); node->ps.ps_OuterTupleSlot = NULL; MemoryContextDelete(node->tempContext); ExecEndNode(outerPlanState(node)); }
/* * Prepares the BitmapTableScanState for a re-scan. */ void ExecBitmapTableReScan(BitmapTableScanState *node, ExprContext *exprCtxt) { BitmapTableScanReScan(node, exprCtxt); /* * Always rescan the input immediately, to ensure we can pass down any * outer tuple that might be used in index quals. */ CheckSendPlanStateGpmonPkt(&node->ss.ps); ExecReScan(outerPlanState(node), exprCtxt); }
/* ---------------------------------------------------------------- * ExecInitHash * * Init routine for Hash node * ---------------------------------------------------------------- */ HashState * ExecInitHash(Hash *node, EState *estate) { HashState *hashstate; SO_printf("ExecInitHash: initializing hash node\n"); /* * create state structure */ hashstate = makeNode(HashState); hashstate->ps.plan = (Plan *) node; hashstate->ps.state = estate; hashstate->hashtable = NULL; hashstate->hashkeys = NIL; /* will be set by parent HashJoin */ /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &hashstate->ps); #define HASH_NSLOTS 1 /* * initialize our result slot */ ExecInitResultTupleSlot(estate, &hashstate->ps); /* * initialize child expressions */ hashstate->ps.targetlist = (List *) ExecInitExpr((Expr *) node->plan.targetlist, (PlanState *) hashstate); hashstate->ps.qual = (List *) ExecInitExpr((Expr *) node->plan.qual, (PlanState *) hashstate); /* * initialize child nodes */ outerPlanState(hashstate) = ExecInitNode(outerPlan(node), estate); /* * initialize tuple type. no need to initialize projection info * because this node doesn't do projections */ ExecAssignResultTypeFromOuterPlan(&hashstate->ps); hashstate->ps.ps_ProjInfo = NULL; return hashstate; }