/* ---------------------------------------------------------------- * InitScanRelation * * This does the initialization for scan relations and * subplans of scans. * ---------------------------------------------------------------- */ static void InitScanRelation(SeqScanState *node, EState *estate) { Relation currentRelation; HeapScanDesc currentScanDesc; //elog(WARNING, "InitScanRelation"); /* * get the relation object id from the relid'th entry in the range table, * open that relation and acquire appropriate lock on it. */ currentRelation = ExecOpenScanRelation(estate, ((SeqScan *) node->ps.plan)->scanrelid); //elog(WARNING, "Rel kind %c",currentRelation->rd_rel->relkind); if(currentRelation->rd_rel->relkind== RELKIND_ARRAY) currentScanDesc = heap_beginscan_ar(currentRelation, estate->es_snapshot, 0, NULL); else currentScanDesc = heap_beginscan(currentRelation, estate->es_snapshot, 0, NULL); node->ss_currentRelation = currentRelation; node->ss_currentScanDesc = currentScanDesc; ExecAssignScanType(node, RelationGetDescr(currentRelation)); }
/* ---------------------------------------------------------------- * InitScanRelation * * Set up to access the scan relation. * ---------------------------------------------------------------- */ static void InitScanRelation(SeqScanState *node, EState *estate, int eflags) { Relation currentRelation; HeapScanDesc currentScanDesc; /* * get the relation object id from the relid'th entry in the range table, * open that relation and acquire appropriate lock on it. */ currentRelation = ExecOpenScanRelation(estate, ((SeqScan *) node->ps.plan)->scanrelid, eflags); /* initialize a heapscan */ currentScanDesc = heap_beginscan(currentRelation, estate->es_snapshot, 0, NULL); node->ss_currentRelation = currentRelation; node->ss_currentScanDesc = currentScanDesc; /* and report the scan tuple slot's rowtype */ ExecAssignScanType(node, RelationGetDescr(currentRelation)); }
/* ---------------------------------------------------------------- * InitScanRelation * * This does the initialization for scan relations and * subplans of scans. * ---------------------------------------------------------------- */ static void InitScanRelation(SeqScanState *node, EState *estate) { Relation currentRelation; HeapScanDesc currentScanDesc; /* * get the relation object id from the relid'th entry in the range table, * open that relation and acquire appropriate lock on it. */ /*CHANGED BY YASIN*/ if (node->ps.ps_InAround) /*If this is in the around branch*/ /*currentRelation = ExecOpenScanRelationAround(estate,((SeqScan *) node->ps.plan)->scanrelid);*/ currentRelation = ExecOpenScanRelation(estate,((SeqScan *) node->ps.plan)->scanrelid); else /*Original code*/ currentRelation = ExecOpenScanRelation(estate,((SeqScan *) node->ps.plan)->scanrelid); currentScanDesc = heap_beginscan(currentRelation, estate->es_snapshot, 0, NULL); node->ss_currentRelation = currentRelation; node->ss_currentScanDesc = currentScanDesc; ExecAssignScanType(node, RelationGetDescr(currentRelation)); }
/* ---------------------------------------------------------------- * ExecInitAppendOnlyScan * ---------------------------------------------------------------- */ AppendOnlyScanState * ExecInitAppendOnlyScan(AppendOnlyScan *node, EState *estate, int eflags) { AppendOnlyScanState *appendonlystate; Relation currentRelation; Assert(outerPlan(node) == NULL); Assert(innerPlan(node) == NULL); /* * create state structure */ appendonlystate = makeNode(AppendOnlyScanState); appendonlystate->ss.ps.plan = (Plan *) node; appendonlystate->ss.ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &appendonlystate->ss.ps); /* * initialize child expressions */ appendonlystate->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) appendonlystate); appendonlystate->ss.ps.qual = (List *) ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) appendonlystate); #define AOSCAN_NSLOTS 2 /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &appendonlystate->ss.ps); ExecInitScanTupleSlot(estate, &appendonlystate->ss); /* * get the relation object id from the relid'th entry in the range table * and open that relation. */ currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid); appendonlystate->ss.ss_currentRelation = currentRelation; ExecAssignScanType(&appendonlystate->ss, RelationGetDescr(currentRelation)); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&appendonlystate->ss.ps); ExecAssignScanProjectionInfo(&appendonlystate->ss); initGpmonPktForAppendOnlyScan((Plan *)node, &appendonlystate->ss.ps.gpmon_pkt, estate); return appendonlystate; }
/* ---------------------------------------------------------------- * InitScanRelation * * This does the initialization for scan relations and * subplans of scans. * ---------------------------------------------------------------- */ static void InitScanRelation(SeqScanState *node, EState *estate) { Relation currentRelation; /* * get the relation object id from the relid'th entry in the range table, * open that relation and acquire appropriate lock on it. */ currentRelation = ExecOpenScanRelation(estate, ((SeqScan *) node->ps.plan)->scanrelid); node->ss_currentRelation = currentRelation; ExecAssignScanType(node, RelationGetDescr(currentRelation)); }
/* ---------------------------------------------------------------- * InitScanRelation * * Set up to access the scan relation. * ---------------------------------------------------------------- */ static void InitScanRelation(SeqScanState *node, EState *estate, int eflags) { Relation currentRelation; /* * get the relation object id from the relid'th entry in the range table, * open that relation and acquire appropriate lock on it. */ currentRelation = ExecOpenScanRelation(estate, ((SeqScan *) node->ss.ps.plan)->scanrelid, eflags); node->ss.ss_currentRelation = currentRelation; /* and report the scan tuple slot's rowtype */ ExecAssignScanType(&node->ss, RelationGetDescr(currentRelation)); }
/* ---------------------------------------------------------------- * ExecWorkTableScan(node) * * Scans the worktable sequentially and returns the next qualifying tuple. * We call the ExecScan() routine and pass it the appropriate * access method functions. * ---------------------------------------------------------------- */ static TupleTableSlot * ExecWorkTableScan(PlanState *pstate) { WorkTableScanState *node = castNode(WorkTableScanState, pstate); /* * On the first call, find the ancestor RecursiveUnion's state via the * Param slot reserved for it. (We can't do this during node init because * there are corner cases where we'll get the init call before the * RecursiveUnion does.) */ if (node->rustate == NULL) { WorkTableScan *plan = (WorkTableScan *) node->ss.ps.plan; EState *estate = node->ss.ps.state; ParamExecData *param; param = &(estate->es_param_exec_vals[plan->wtParam]); Assert(param->execPlan == NULL); Assert(!param->isnull); node->rustate = castNode(RecursiveUnionState, DatumGetPointer(param->value)); Assert(node->rustate); /* * The scan tuple type (ie, the rowtype we expect to find in the work * table) is the same as the result rowtype of the ancestor * RecursiveUnion node. Note this depends on the assumption that * RecursiveUnion doesn't allow projection. */ ExecAssignScanType(&node->ss, ExecGetResultType(&node->rustate->ps)); /* * Now we can initialize the projection info. This must be completed * before we can call ExecScan(). */ ExecAssignScanProjectionInfo(&node->ss); } return ExecScan(&node->ss, (ExecScanAccessMtd) WorkTableScanNext, (ExecScanRecheckMtd) WorkTableScanRecheck); }
/* * DynamicScan_UpdateScanStateForNewPart * Updates ScanState properties for a new part */ static void DynamicScan_UpdateScanStateForNewPart(ScanState *scanState, Relation newRelation) { scanState->ss_currentRelation = newRelation; ExecAssignScanType(scanState, RelationGetDescr(newRelation)); Oid newOid = RelationGetRelid(newRelation); /* * Inside ExecInitScanTupleSlot() we set the tuple table slot's oid * to range table entry's relid, which for partitioned table always set * to parent table's oid. In queries where we need to read table oids * (MPP-20736) we use the tuple table slot's saved oid (refer to slot_getsysattr()). * This wrongly returns parent oid, instead of partition oid. Therefore, * to return correct partition oid, we need to update * our tuple table slot's oid to reflect the partition oid. */ scanState->ss_ScanTupleSlot->tts_tableOid = newOid; scanState->tableType = getTableType(scanState->ss_currentRelation); }
/* * InitScanStateRelationDetails * Opens a relation and sets various relation specific ScanState fields. */ void InitScanStateRelationDetails(ScanState *scanState, Plan *plan, EState *estate) { Assert(NULL != scanState); PlanState *planState = &scanState->ps; /* Initialize child expressions */ planState->targetlist = (List *)ExecInitExpr((Expr *)plan->targetlist, planState); planState->qual = (List *)ExecInitExpr((Expr *)plan->qual, planState); Relation currentRelation = ExecOpenScanRelation(estate, ((Scan *)plan)->scanrelid); scanState->ss_currentRelation = currentRelation; if (RelationIsAoRows(currentRelation) || RelationIsParquet(currentRelation)) { scanState->splits = GetFileSplitsOfSegment(estate->es_plannedstmt->scantable_splits, currentRelation->rd_id, GetQEIndex()); } ExecAssignScanType(scanState, RelationGetDescr(currentRelation)); ExecAssignScanProjectionInfo(scanState); scanState->tableType = getTableType(scanState->ss_currentRelation); }
/* ---------------------------------------------------------------- * ExecInitIndexScan * * Initializes the index scan's state information, creates * scan keys, and opens the base and index relations. * * Note: index scans have 2 sets of state information because * we have to keep track of the base relation and the * index relation. * ---------------------------------------------------------------- */ IndexScanState * ExecInitIndexScan(IndexScan *node, EState *estate, int eflags) { IndexScanState *indexstate; Relation currentRelation; bool relistarget; /* * create state structure */ indexstate = makeNode(IndexScanState); indexstate->ss.ps.plan = (Plan *) node; indexstate->ss.ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &indexstate->ss.ps); /*indexstate->ss.ps.ps_TupFromTlist = false;*/ /* * initialize child expressions * * Note: we don't initialize all of the indexqual expression, only the * sub-parts corresponding to runtime keys (see below). The indexqualorig * expression is always initialized even though it will only be used in * some uncommon cases --- would be nice to improve that. (Problem is * that any SubPlans present in the expression must be found now...) */ indexstate->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) indexstate); indexstate->ss.ps.qual = (List *) ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) indexstate); indexstate->indexqualorig = (List *) ExecInitExpr((Expr *) node->indexqualorig, (PlanState *) indexstate); #define INDEXSCAN_NSLOTS 2 /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &indexstate->ss.ps); ExecInitScanTupleSlot(estate, &indexstate->ss); /* * open the base relation and acquire appropriate lock on it. */ currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid); indexstate->ss.ss_currentRelation = currentRelation; /* * get the scan type from the relation descriptor. */ ExecAssignScanType(&indexstate->ss, RelationGetDescr(currentRelation)); /* * Open the index relation. * * If the parent table is one of the target relations of the query, then * InitPlan already opened and write-locked the index, so we can avoid * taking another lock here. Otherwise we need a normal reader's lock. */ relistarget = ExecRelationIsTargetRelation(estate, node->scan.scanrelid); indexstate->iss_RelationDesc = index_open(node->indexid, relistarget ? NoLock : AccessShareLock); /* * build the index scan keys from the index qualification */ ExecIndexBuildScanKeys((PlanState *) indexstate, indexstate->iss_RelationDesc, node->indexqual, node->indexstrategy, node->indexsubtype, &indexstate->iss_ScanKeys, &indexstate->iss_NumScanKeys, &indexstate->iss_RuntimeKeys, &indexstate->iss_NumRuntimeKeys, NULL, /* no ArrayKeys */ NULL); /* * If we have runtime keys, we need an ExprContext to evaluate them. The * node's standard context won't do because we want to reset that context * for every tuple. So, build another context just like the other one... * -tgl 7/11/00 */ if (indexstate->iss_NumRuntimeKeys != 0) { ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext; ExecAssignExprContext(estate, &indexstate->ss.ps); indexstate->iss_RuntimeContext = indexstate->ss.ps.ps_ExprContext; indexstate->ss.ps.ps_ExprContext = stdecontext; } else { indexstate->iss_RuntimeContext = NULL; } /* * Initialize index-specific scan state */ indexstate->iss_RuntimeKeysReady = false; /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&indexstate->ss.ps); ExecAssignScanProjectionInfo(&indexstate->ss); initGpmonPktForIndexScan((Plan *)node, &indexstate->ss.ps.gpmon_pkt, estate); /* * If eflag contains EXEC_FLAG_REWIND or EXEC_FLAG_BACKWARD or EXEC_FLAG_MARK, * then this node is not eager free safe. */ indexstate->ss.ps.delayEagerFree = ((eflags & (EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)) != 0); /* * all done. */ return indexstate; }
/* ---------------------------------------------------------------- * ExecInitSubqueryScan * ---------------------------------------------------------------- */ SubqueryScanState * ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags) { SubqueryScanState *subquerystate; /* check for unsupported flags */ Assert(!(eflags & EXEC_FLAG_MARK)); /* * SubqueryScan should not have any "normal" children. Also, if planner * left anything in subrtable, it's fishy. */ Assert(outerPlan(node) == NULL); Assert(innerPlan(node) == NULL); Assert(node->subrtable == NIL); /* * Since subquery nodes create its own executor state, * and pass it down to its child nodes, we always * initialize the subquery node. However, some * fields are not initialized if not necessary, see * below. */ /* * create state structure */ subquerystate = makeNode(SubqueryScanState); subquerystate->ss.ps.plan = (Plan *) node; subquerystate->ss.ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &subquerystate->ss.ps); /* * initialize child expressions */ subquerystate->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) subquerystate); subquerystate->ss.ps.qual = (List *) ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) subquerystate); /* Check if targetlist or qual contains a var node referencing the ctid column */ subquerystate->cdb_want_ctid = contain_ctid_var_reference(&node->scan); ItemPointerSetInvalid(&subquerystate->cdb_fake_ctid); #define SUBQUERYSCAN_NSLOTS 2 /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &subquerystate->ss.ps); ExecInitScanTupleSlot(estate, &subquerystate->ss); /* * initialize subquery */ subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags); /* return borrowed share node list */ estate->es_sharenode = estate->es_sharenode; /*subquerystate->ss.ps.ps_TupFromTlist = false;*/ /* * Initialize scan tuple type (needed by ExecAssignScanProjectionInfo) */ ExecAssignScanType(&subquerystate->ss, ExecGetResultType(subquerystate->subplan)); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&subquerystate->ss.ps); ExecAssignScanProjectionInfo(&subquerystate->ss); initGpmonPktForSubqueryScan((Plan *)node, &subquerystate->ss.ps.gpmon_pkt, estate); return subquerystate; }
/* * This function initializes a part and returns true if a new index has been prepared for scanning. */ static bool initNextIndexToScan(DynamicIndexScanState *node) { IndexScanState *indexState = &(node->indexScanState); DynamicIndexScan *dynamicIndexScan = (DynamicIndexScan *)node->indexScanState.ss.ps.plan; /* Load new index when the scanning of the previous index is done. */ if (indexState->ss.scan_state == SCAN_INIT || indexState->ss.scan_state == SCAN_DONE) { /* This is the oid of a partition of the table (*not* index) */ Oid *pid = hash_seq_search(&node->pidxStatus); if (pid == NULL) { /* Return if all parts have been scanned. */ node->shouldCallHashSeqTerm = false; return false; } /* Collect number of partitions scanned in EXPLAIN ANALYZE */ if(NULL != indexState->ss.ps.instrument) { Instrumentation *instr = indexState->ss.ps.instrument; instr->numPartScanned ++; } DynamicIndexScan_ReMapColumns(node, *pid); /* * The is the oid of the partition of an *index*. Note: a partitioned table * has a root and a set of partitions (may be multi-level). An index * on a partitioned table also has a root and a set of index partitions. * We started at table level, and now we are fetching the oid of an index * partition. */ Oid pindex = getPhysicalIndexRelid(dynamicIndexScan->logicalIndexInfo, *pid); Assert(OidIsValid(pindex)); Relation currentRelation = OpenScanRelationByOid(*pid); indexState->ss.ss_currentRelation = currentRelation; for (int i=0; i < DYNAMICINDEXSCAN_NSLOTS; i++) { indexState->ss.ss_ScanTupleSlot[i].tts_tableOid = *pid; } ExecAssignScanType(&indexState->ss, RelationGetDescr(currentRelation)); ScanState *scanState = (ScanState *)node; MemoryContextReset(node->partitionMemoryContext); MemoryContext oldCxt = MemoryContextSwitchTo(node->partitionMemoryContext); /* Initialize child expressions */ scanState->ps.qual = (List *)ExecInitExpr((Expr *)scanState->ps.plan->qual, (PlanState*)scanState); scanState->ps.targetlist = (List *)ExecInitExpr((Expr *)scanState->ps.plan->targetlist, (PlanState*)scanState); ExecAssignScanProjectionInfo(scanState); EState *estate = indexState->ss.ps.state; indexState->iss_RelationDesc = OpenIndexRelation(estate, pindex, *pid); /* * build the index scan keys from the index qualification */ ExecIndexBuildScanKeys((PlanState *) indexState, indexState->iss_RelationDesc, dynamicIndexScan->indexqual, dynamicIndexScan->indexstrategy, dynamicIndexScan->indexsubtype, &indexState->iss_ScanKeys, &indexState->iss_NumScanKeys, &indexState->iss_RuntimeKeys, &indexState->iss_NumRuntimeKeys, NULL, NULL); MemoryContextSwitchTo(oldCxt); ExprContext *econtext = indexState->iss_RuntimeContext; /* context for runtime keys */ if (indexState->iss_NumRuntimeKeys != 0) { ExecIndexEvalRuntimeKeys(econtext, indexState->iss_RuntimeKeys, indexState->iss_NumRuntimeKeys); } indexState->iss_RuntimeKeysReady = true; /* * Initialize result tuple type and projection info. */ TupleDesc td = indexState->ss.ps.ps_ResultTupleSlot->tts_tupleDescriptor; if (td) { pfree(td); td = NULL; } ExecAssignResultTypeFromTL(&indexState->ss.ps); ExecAssignScanProjectionInfo(&indexState->ss); indexState->iss_ScanDesc = index_beginscan(currentRelation, indexState->iss_RelationDesc, estate->es_snapshot, indexState->iss_NumScanKeys, indexState->iss_ScanKeys); indexState->ss.scan_state = SCAN_SCAN; } return true; }
/* ---------------------------------------------------------------- * ExecInitForeignScan * ---------------------------------------------------------------- */ foreign_ss * ExecInitForeignScan(foreign_scan_sc *node, exec_state_n *estate, int eflags) { foreign_ss* scanstate; struct relation* currentRelation; FdwRoutine *fdwroutine; /* check for unsupported flags */ ASSERT(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); /* * create state structure */ scanstate = MK_N(ForeignScanState,foreign_ss); scanstate->ss.ps.plan = (plan_n *) node; scanstate->ss.ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &scanstate->ss.ps); scanstate->ss.ps.ps_TupFromTlist = false; /* * initialize child expressions */ scanstate->ss.ps.targetlist = (struct list *) exec_init_expr( (expr_n *) node->scan.plan.targetlist, (plan_state_n *) scanstate); scanstate->ss.ps.qual = (struct list *) exec_init_expr( (expr_n *) node->scan.plan.qual, (plan_state_n *) scanstate); /* * tuple table initialization */ exec_init_result_tupslot(estate, &scanstate->ss.ps); exec_init_scan_tupslot(estate, &scanstate->ss); /* * open the base relation and acquire appropriate lock on it. */ currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid); scanstate->ss.ss_currentRelation = currentRelation; /* * get the scan type from the relation descriptor. */ ExecAssignScanType(&scanstate->ss, REL_DESC(currentRelation)); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&scanstate->ss.ps); ExecAssignScanProjectionInfo(&scanstate->ss); /* * Acquire function pointers from the FDW's handler, and init fdw_state. */ fdwroutine = GetFdwRoutineByRelId(REL_ID(currentRelation)); scanstate->fdwroutine = fdwroutine; scanstate->fdw_state = NULL; /* * Tell the FDW to initiate the scan. */ fdwroutine->BeginForeignScan(scanstate, eflags); return scanstate; }
/* ---------------------------------------------------------------- * ExecInitFunctionScan * ---------------------------------------------------------------- */ FunctionScanState * ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags) { FunctionScanState *scanstate; RangeTblEntry *rte; Oid funcrettype; TypeFuncClass functypclass; TupleDesc tupdesc = NULL; /* * FunctionScan should not have any children. */ Assert(outerPlan(node) == NULL); Assert(innerPlan(node) == NULL); /* * create new ScanState for node */ scanstate = makeNode(FunctionScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &scanstate->ss.ps); #define FUNCTIONSCAN_NSLOTS 2 /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &scanstate->ss.ps); ExecInitScanTupleSlot(estate, &scanstate->ss); /* * initialize child expressions */ scanstate->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) scanstate); scanstate->ss.ps.qual = (List *) ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) scanstate); /* Check if targetlist or qual contains a var node referencing the ctid column */ scanstate->cdb_want_ctid = contain_ctid_var_reference(&node->scan); ItemPointerSet(&scanstate->cdb_fake_ctid, 0, 0); ItemPointerSet(&scanstate->cdb_mark_ctid, 0, 0); /* * get info about function */ rte = rt_fetch(node->scan.scanrelid, estate->es_range_table); Assert(rte->rtekind == RTE_FUNCTION); /* * Now determine if the function returns a simple or composite type, and * build an appropriate tupdesc. */ functypclass = get_expr_result_type(rte->funcexpr, &funcrettype, &tupdesc); if (functypclass == TYPEFUNC_COMPOSITE) { /* Composite data type, e.g. a table's row type */ Assert(tupdesc); /* Must copy it out of typcache for safety */ tupdesc = CreateTupleDescCopy(tupdesc); } else if (functypclass == TYPEFUNC_SCALAR) { /* Base data type, i.e. scalar */ char *attname = strVal(linitial(rte->eref->colnames)); tupdesc = CreateTemplateTupleDesc(1, false); TupleDescInitEntry(tupdesc, (AttrNumber) 1, attname, funcrettype, -1, 0); } else if (functypclass == TYPEFUNC_RECORD) { tupdesc = BuildDescFromLists(rte->eref->colnames, rte->funccoltypes, rte->funccoltypmods); } else { /* crummy error message, but parser should have caught this */ elog(ERROR, "function in FROM has unsupported return type"); } /* * For RECORD results, make sure a typmod has been assigned. (The * function should do this for itself, but let's cover things in case it * doesn't.) */ BlessTupleDesc(tupdesc); scanstate->tupdesc = tupdesc; ExecAssignScanType(&scanstate->ss, tupdesc); /* * Other node-specific setup */ scanstate->tuplestorestate = NULL; scanstate->funcexpr = ExecInitExpr((Expr *) rte->funcexpr, (PlanState *) scanstate); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&scanstate->ss.ps); ExecAssignScanProjectionInfo(&scanstate->ss); initGpmonPktForFunctionScan((Plan *)node, &scanstate->ss.ps.gpmon_pkt, estate); if (gp_resqueue_memory_policy != RESQUEUE_MEMORY_POLICY_NONE) { SPI_ReserveMemory(((Plan *)node)->operatorMemKB * 1024L); } return scanstate; }
/* ---------------------------------------------------------------- * ExecInitBitmapHeapScan * * Initializes the scan's state information. * ---------------------------------------------------------------- */ BitmapHeapScanState * ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags) { BitmapHeapScanState *scanstate; Relation currentRelation; /* 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. */ Assert(IsMVCCSnapshot(estate->es_snapshot)); /* * create state structure */ scanstate = makeNode(BitmapHeapScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; scanstate->tbm = NULL; scanstate->tbmiterator = NULL; scanstate->tbmres = NULL; scanstate->prefetch_iterator = NULL; scanstate->prefetch_pages = 0; scanstate->prefetch_target = 0; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &scanstate->ss.ps); scanstate->ss.ps.ps_TupFromTlist = false; /* * initialize child expressions */ scanstate->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) scanstate); scanstate->ss.ps.qual = (List *) ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) scanstate); scanstate->bitmapqualorig = (List *) ExecInitExpr((Expr *) node->bitmapqualorig, (PlanState *) scanstate); /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &scanstate->ss.ps); ExecInitScanTupleSlot(estate, &scanstate->ss); /* * open the base relation and acquire appropriate lock on it. */ currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid); scanstate->ss.ss_currentRelation = currentRelation; /* * Even though we aren't going to do a conventional seqscan, it is useful * to create a HeapScanDesc --- most of the fields in it are usable. */ scanstate->ss.ss_currentScanDesc = heap_beginscan_bm(currentRelation, estate->es_snapshot, 0, NULL); /* * get the scan type from the relation descriptor. */ ExecAssignScanType(&scanstate->ss, RelationGetDescr(currentRelation)); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&scanstate->ss.ps); ExecAssignScanProjectionInfo(&scanstate->ss); /* * 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(scanstate) = ExecInitNode(outerPlan(node), estate, eflags); /* * all done. */ return scanstate; }
/* ---------------------------------------------------------------- * ExecInitExternalScan * ---------------------------------------------------------------- */ ExternalScanState * ExecInitExternalScan(ExternalScan *node, EState *estate, int eflags) { ResultRelSegFileInfo *segfileinfo = NULL; ExternalScanState *externalstate; Relation currentRelation; FileScanDesc currentScanDesc; Assert(outerPlan(node) == NULL); Assert(innerPlan(node) == NULL); /* * create state structure */ externalstate = makeNode(ExternalScanState); externalstate->ss.ps.plan = (Plan *) node; externalstate->ss.ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &externalstate->ss.ps); /* * initialize child expressions */ externalstate->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) externalstate); externalstate->ss.ps.qual = (List *) ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) externalstate); /* Check if targetlist or qual contains a var node referencing the ctid column */ externalstate->cdb_want_ctid = contain_ctid_var_reference(&node->scan); ItemPointerSetInvalid(&externalstate->cdb_fake_ctid); #define EXTSCAN_NSLOTS 2 /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &externalstate->ss.ps); ExecInitScanTupleSlot(estate, &externalstate->ss); /* * get the relation object id from the relid'th entry in the range table * and open that relation. */ currentRelation = ExecOpenScanExternalRelation(estate, node->scan.scanrelid); if (Gp_role == GP_ROLE_EXECUTE && node->err_aosegfileinfos) { segfileinfo = (ResultRelSegFileInfo *)list_nth(node->err_aosegfileinfos, GetQEIndex()); } else { segfileinfo = NULL; } currentScanDesc = external_beginscan(currentRelation, node->scan.scanrelid, node->scancounter, node->uriList, node->fmtOpts, node->fmtType, node->isMasterOnly, node->rejLimit, node->rejLimitInRows, node->fmterrtbl, segfileinfo, node->encoding, node->scan.plan.qual); externalstate->ss.ss_currentRelation = currentRelation; externalstate->ess_ScanDesc = currentScanDesc; ExecAssignScanType(&externalstate->ss, RelationGetDescr(currentRelation)); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&externalstate->ss.ps); ExecAssignScanProjectionInfo(&externalstate->ss); /* * If eflag contains EXEC_FLAG_REWIND or EXEC_FLAG_BACKWARD or EXEC_FLAG_MARK, * then this node is not eager free safe. */ externalstate->ss.ps.delayEagerFree = ((eflags & (EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)) != 0); initGpmonPktForExternalScan((Plan *)node, &externalstate->ss.ps.gpmon_pkt, estate); return externalstate; }
/* ---------------------------------------------------------------- * ExecInitFunctionScan * ---------------------------------------------------------------- */ FunctionScanState * ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags) { FunctionScanState *scanstate; Oid funcrettype; TypeFuncClass functypclass; TupleDesc tupdesc = NULL; /* check for unsupported flags */ Assert(!(eflags & EXEC_FLAG_MARK)); /* * FunctionScan should not have any children. */ Assert(outerPlan(node) == NULL); Assert(innerPlan(node) == NULL); /* * create new ScanState for node */ scanstate = makeNode(FunctionScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; scanstate->eflags = eflags; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &scanstate->ss.ps); /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &scanstate->ss.ps); ExecInitScanTupleSlot(estate, &scanstate->ss); /* * initialize child expressions */ scanstate->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) scanstate); scanstate->ss.ps.qual = (List *) ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) scanstate); /* * Now determine if the function returns a simple or composite type, and * build an appropriate tupdesc. */ functypclass = get_expr_result_type(node->funcexpr, &funcrettype, &tupdesc); if (functypclass == TYPEFUNC_COMPOSITE) { /* Composite data type, e.g. a table's row type */ Assert(tupdesc); /* Must copy it out of typcache for safety */ tupdesc = CreateTupleDescCopy(tupdesc); } else if (functypclass == TYPEFUNC_SCALAR) { /* Base data type, i.e. scalar */ char *attname = strVal(linitial(node->funccolnames)); tupdesc = CreateTemplateTupleDesc(1, false); TupleDescInitEntry(tupdesc, (AttrNumber) 1, attname, funcrettype, -1, 0); } else if (functypclass == TYPEFUNC_RECORD) { tupdesc = BuildDescFromLists(node->funccolnames, node->funccoltypes, node->funccoltypmods); } else { /* crummy error message, but parser should have caught this */ elog(ERROR, "function in FROM has unsupported return type"); } /* * For RECORD results, make sure a typmod has been assigned. (The * function should do this for itself, but let's cover things in case it * doesn't.) */ BlessTupleDesc(tupdesc); scanstate->tupdesc = tupdesc; ExecAssignScanType(&scanstate->ss, tupdesc); /* * Other node-specific setup */ scanstate->tuplestorestate = NULL; scanstate->funcexpr = ExecInitExpr((Expr *) node->funcexpr, (PlanState *) scanstate); scanstate->ss.ps.ps_TupFromTlist = false; /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&scanstate->ss.ps); ExecAssignScanProjectionInfo(&scanstate->ss); return scanstate; }
/* ---------------------------------------------------------------- * ExecInitSubqueryScan * ---------------------------------------------------------------- */ SubqueryScanState * ExecInitSubqueryScan(SubqueryScan *node, EState *estate) { SubqueryScanState *subquerystate; RangeTblEntry *rte; EState *sp_estate; MemoryContext oldcontext; /* * SubqueryScan should not have any "normal" children. */ Assert(outerPlan(node) == NULL); Assert(innerPlan(node) == NULL); /* * create state structure */ subquerystate = makeNode(SubqueryScanState); subquerystate->ss.ps.plan = (Plan *) node; subquerystate->ss.ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &subquerystate->ss.ps); /* * initialize child expressions */ subquerystate->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) subquerystate); subquerystate->ss.ps.qual = (List *) ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) subquerystate); #define SUBQUERYSCAN_NSLOTS 2 /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &subquerystate->ss.ps); ExecInitScanTupleSlot(estate, &subquerystate->ss); /* * initialize subquery * * This should agree with ExecInitSubPlan */ rte = rt_fetch(node->scan.scanrelid, estate->es_range_table); Assert(rte->rtekind == RTE_SUBQUERY); /* * Do access checking on the rangetable entries in the subquery. */ ExecCheckRTPerms(rte->subquery->rtable); /* * The subquery needs its own EState because it has its own rangetable. It * shares our Param ID space, however. XXX if rangetable access were done * differently, the subquery could share our EState, which would eliminate * some thrashing about in this module... */ sp_estate = CreateExecutorState(); subquerystate->sss_SubEState = sp_estate; oldcontext = MemoryContextSwitchTo(sp_estate->es_query_cxt); sp_estate->es_range_table = rte->subquery->rtable; sp_estate->es_param_list_info = estate->es_param_list_info; sp_estate->es_param_exec_vals = estate->es_param_exec_vals; sp_estate->es_tupleTable = ExecCreateTupleTable(ExecCountSlotsNode(node->subplan) + 10); sp_estate->es_snapshot = estate->es_snapshot; sp_estate->es_crosscheck_snapshot = estate->es_crosscheck_snapshot; sp_estate->es_instrument = estate->es_instrument; /* * Start up the subplan (this is a very cut-down form of InitPlan()) */ subquerystate->subplan = ExecInitNode(node->subplan, sp_estate); MemoryContextSwitchTo(oldcontext); subquerystate->ss.ps.ps_TupFromTlist = false; /* * Initialize scan tuple type (needed by ExecAssignScanProjectionInfo) */ ExecAssignScanType(&subquerystate->ss, ExecGetResultType(subquerystate->subplan), false); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&subquerystate->ss.ps); ExecAssignScanProjectionInfo(&subquerystate->ss); return subquerystate; }
/* ---------------------------------------------------------------- * ExecInitIndexOnlyScan * * Initializes the index scan's state information, creates * scan keys, and opens the base and index relations. * * Note: index scans have 2 sets of state information because * we have to keep track of the base relation and the * index relation. * ---------------------------------------------------------------- */ IndexOnlyScanState * ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags) { IndexOnlyScanState *indexstate; Relation currentRelation; bool relistarget; TupleDesc tupDesc; /* * create state structure */ indexstate = makeNode(IndexOnlyScanState); indexstate->ss.ps.plan = (Plan *) node; indexstate->ss.ps.state = estate; indexstate->ioss_HeapFetches = 0; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &indexstate->ss.ps); indexstate->ss.ps.ps_TupFromTlist = false; /* * initialize child expressions * * Note: we don't initialize all of the indexorderby expression, only the * sub-parts corresponding to runtime keys (see below). */ indexstate->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) indexstate); indexstate->ss.ps.qual = (List *) ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) indexstate); indexstate->indexqual = (List *) ExecInitExpr((Expr *) node->indexqual, (PlanState *) indexstate); /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &indexstate->ss.ps); ExecInitScanTupleSlot(estate, &indexstate->ss); /* * open the base relation and acquire appropriate lock on it. */ currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags); indexstate->ss.ss_currentRelation = currentRelation; indexstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */ /* * Build the scan tuple type using the indextlist generated by the * planner. We use this, rather than the index's physical tuple * descriptor, because the latter contains storage column types not the * types of the original datums. (It's the AM's responsibility to return * suitable data anyway.) */ tupDesc = ExecTypeFromTL(node->indextlist, false); ExecAssignScanType(&indexstate->ss, tupDesc); /* * Initialize result tuple type and projection info. The node's * targetlist will contain Vars with varno = INDEX_VAR, referencing the * scan tuple. */ ExecAssignResultTypeFromTL(&indexstate->ss.ps); ExecAssignScanProjectionInfoWithVarno(&indexstate->ss, INDEX_VAR); /* * If we are just doing EXPLAIN (ie, aren't going to run the plan), stop * here. This allows an index-advisor plugin to EXPLAIN a plan containing * references to nonexistent indexes. */ if (eflags & EXEC_FLAG_EXPLAIN_ONLY) return indexstate; /* * Open the index relation. * * If the parent table is one of the target relations of the query, then * InitPlan already opened and write-locked the index, so we can avoid * taking another lock here. Otherwise we need a normal reader's lock. */ relistarget = ExecRelationIsTargetRelation(estate, node->scan.scanrelid); indexstate->ioss_RelationDesc = index_open(node->indexid, relistarget ? NoLock : AccessShareLock); /* * Initialize index-specific scan state */ indexstate->ioss_RuntimeKeysReady = false; indexstate->ioss_RuntimeKeys = NULL; indexstate->ioss_NumRuntimeKeys = 0; /* * build the index scan keys from the index qualification */ ExecIndexBuildScanKeys((PlanState *) indexstate, indexstate->ioss_RelationDesc, node->indexqual, false, &indexstate->ioss_ScanKeys, &indexstate->ioss_NumScanKeys, &indexstate->ioss_RuntimeKeys, &indexstate->ioss_NumRuntimeKeys, NULL, /* no ArrayKeys */ NULL); /* * any ORDER BY exprs have to be turned into scankeys in the same way */ ExecIndexBuildScanKeys((PlanState *) indexstate, indexstate->ioss_RelationDesc, node->indexorderby, true, &indexstate->ioss_OrderByKeys, &indexstate->ioss_NumOrderByKeys, &indexstate->ioss_RuntimeKeys, &indexstate->ioss_NumRuntimeKeys, NULL, /* no ArrayKeys */ NULL); /* * If we have runtime keys, we need an ExprContext to evaluate them. The * node's standard context won't do because we want to reset that context * for every tuple. So, build another context just like the other one... * -tgl 7/11/00 */ if (indexstate->ioss_NumRuntimeKeys != 0) { ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext; ExecAssignExprContext(estate, &indexstate->ss.ps); indexstate->ioss_RuntimeContext = indexstate->ss.ps.ps_ExprContext; indexstate->ss.ps.ps_ExprContext = stdecontext; } else { indexstate->ioss_RuntimeContext = NULL; } /* * Initialize scan descriptor. */ indexstate->ioss_ScanDesc = index_beginscan(currentRelation, indexstate->ioss_RelationDesc, estate->es_snapshot, indexstate->ioss_NumScanKeys, indexstate->ioss_NumOrderByKeys); /* Set it up for index-only scan */ indexstate->ioss_ScanDesc->xs_want_itup = true; indexstate->ioss_VMBuffer = InvalidBuffer; /* * If no run-time keys to calculate, go ahead and pass the scankeys to the * index AM. */ if (indexstate->ioss_NumRuntimeKeys == 0) index_rescan(indexstate->ioss_ScanDesc, indexstate->ioss_ScanKeys, indexstate->ioss_NumScanKeys, indexstate->ioss_OrderByKeys, indexstate->ioss_NumOrderByKeys); /* * all done. */ return indexstate; }
/* ---------------------------------------------------------------- * ExecInitForeignScan * ---------------------------------------------------------------- */ ForeignScanState * ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags) { ForeignScanState *scanstate; Relation currentRelation = NULL; Index scanrelid = node->scan.scanrelid; Index tlistvarno; FdwRoutine *fdwroutine; /* check for unsupported flags */ Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); /* * create state structure */ scanstate = makeNode(ForeignScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &scanstate->ss.ps); scanstate->ss.ps.ps_TupFromTlist = false; /* * initialize child expressions */ scanstate->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) scanstate); scanstate->ss.ps.qual = (List *) ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) scanstate); scanstate->fdw_recheck_quals = (List *) ExecInitExpr((Expr *) node->fdw_recheck_quals, (PlanState *) scanstate); /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &scanstate->ss.ps); ExecInitScanTupleSlot(estate, &scanstate->ss); /* * open the base relation, if any, and acquire an appropriate lock on it; * also acquire function pointers from the FDW's handler */ if (scanrelid > 0) { currentRelation = ExecOpenScanRelation(estate, scanrelid, eflags); scanstate->ss.ss_currentRelation = currentRelation; fdwroutine = GetFdwRoutineForRelation(currentRelation, true); } else { /* We can't use the relcache, so get fdwroutine the hard way */ fdwroutine = GetFdwRoutineByServerId(node->fs_server); } /* * Determine the scan tuple type. If the FDW provided a targetlist * describing the scan tuples, use that; else use base relation's rowtype. */ if (node->fdw_scan_tlist != NIL || currentRelation == NULL) { TupleDesc scan_tupdesc; scan_tupdesc = ExecTypeFromTL(node->fdw_scan_tlist, false); ExecAssignScanType(&scanstate->ss, scan_tupdesc); /* Node's targetlist will contain Vars with varno = INDEX_VAR */ tlistvarno = INDEX_VAR; } else { ExecAssignScanType(&scanstate->ss, RelationGetDescr(currentRelation)); /* Node's targetlist will contain Vars with varno = scanrelid */ tlistvarno = scanrelid; } /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&scanstate->ss.ps); ExecAssignScanProjectionInfoWithVarno(&scanstate->ss, tlistvarno); /* * Initialize FDW-related state. */ scanstate->fdwroutine = fdwroutine; scanstate->fdw_state = NULL; /* Initialize any outer plan. */ if (outerPlan(node)) outerPlanState(scanstate) = ExecInitNode(outerPlan(node), estate, eflags); /* * Tell the FDW to initialize the scan. */ fdwroutine->BeginForeignScan(scanstate, eflags); return scanstate; }
/* * initNextTableToScan * Find the next table to scan and initiate the scan if the previous table * is finished. * * If scanning on the current table is not finished, or a new table is found, * this function returns true. * If no more table is found, this function returns false. */ static bool initNextTableToScan(DynamicTableScanState *node) { ScanState *scanState = (ScanState *)node; if (scanState->scan_state == SCAN_INIT || scanState->scan_state == SCAN_DONE) { Oid *pid = hash_seq_search(&node->pidStatus); if (pid == NULL) { node->shouldCallHashSeqTerm = false; return false; } /* Collect number of partitions scanned in EXPLAIN ANALYZE */ if (NULL != scanState->ps.instrument) { Instrumentation *instr = scanState->ps.instrument; instr->numPartScanned ++; } /* * Inside ExecInitScanTupleSlot() we set the tuple table slot's oid * to range table entry's relid, which for partitioned table always set * to parent table's oid. In queries where we need to read table oids * (MPP-20736) we use the tuple table slot's saved oid (refer to slot_getsysattr()). * This wrongly returns parent oid, instead of partition oid. Therefore, * to return correct partition oid, we need to update * our tuple table slot's oid to reflect the partition oid. */ scanState->ss_ScanTupleSlot->tts_tableOid = *pid; scanState->ss_currentRelation = OpenScanRelationByOid(*pid); Relation lastScannedRel = OpenScanRelationByOid(node->lastRelOid); TupleDesc lastTupDesc = RelationGetDescr(lastScannedRel); CloseScanRelation(lastScannedRel); TupleDesc partTupDesc = RelationGetDescr(scanState->ss_currentRelation); ExecAssignScanType(scanState, partTupDesc); AttrNumber *attMap = NULL; attMap = varattnos_map(lastTupDesc, partTupDesc); /* If attribute remapping is not necessary, then do not change the varattno */ if (attMap) { change_varattnos_of_a_varno((Node*)scanState->ps.plan->qual, attMap, node->scanrelid); change_varattnos_of_a_varno((Node*)scanState->ps.plan->targetlist, attMap, node->scanrelid); /* * Now that the varattno mapping has been changed, change the relation that * the new varnos correspond to */ node->lastRelOid = *pid; } /* * For the very first partition, the targetlist of planstate is set to null. So, we must * initialize quals and targetlist, regardless of remapping requirements. For later * partitions, we only initialize quals and targetlist if a column re-mapping is necessary. */ if (attMap || node->firstPartition) { node->firstPartition = false; MemoryContextReset(node->partitionMemoryContext); MemoryContext oldCxt = MemoryContextSwitchTo(node->partitionMemoryContext); /* Initialize child expressions */ scanState->ps.qual = (List *)ExecInitExpr((Expr *)scanState->ps.plan->qual, (PlanState*)scanState); scanState->ps.targetlist = (List *)ExecInitExpr((Expr *)scanState->ps.plan->targetlist, (PlanState*)scanState); MemoryContextSwitchTo(oldCxt); } if (attMap) { pfree(attMap); } ExecAssignScanProjectionInfo(scanState); scanState->tableType = getTableType(scanState->ss_currentRelation); BeginTableScanRelation(scanState); } return true; }
/* ---------------------------------------------------------------- * ExecInitSubqueryScan * ---------------------------------------------------------------- */ SubqueryScanState * ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags) { SubqueryScanState *subquerystate; /* check for unsupported flags */ Assert(!(eflags & EXEC_FLAG_MARK)); /* SubqueryScan should not have any "normal" children */ Assert(outerPlan(node) == NULL); Assert(innerPlan(node) == NULL); /* * create state structure */ subquerystate = makeNode(SubqueryScanState); subquerystate->ss.ps.plan = (Plan *) node; subquerystate->ss.ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &subquerystate->ss.ps); /* * initialize child expressions */ subquerystate->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) subquerystate); subquerystate->ss.ps.qual = (List *) ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) subquerystate); /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &subquerystate->ss.ps); ExecInitScanTupleSlot(estate, &subquerystate->ss); /* * initialize subquery */ subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags); subquerystate->ss.ps.ps_TupFromTlist = false; /* * Initialize scan tuple type (needed by ExecAssignScanProjectionInfo) */ ExecAssignScanType(&subquerystate->ss, ExecGetResultType(subquerystate->subplan)); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&subquerystate->ss.ps); ExecAssignScanProjectionInfo(&subquerystate->ss); return subquerystate; }
/* ---------------------------------------------------------------- * ExecInitBitmapHeapScan * * Initializes the scan's state information. * ---------------------------------------------------------------- */ BitmapHeapScanState * ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags) { BitmapHeapScanState *scanstate; Relation currentRelation; /* 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. */ Assert(IsMVCCSnapshot(estate->es_snapshot)); /* * create state structure */ scanstate = makeNode(BitmapHeapScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; scanstate->tbm = NULL; scanstate->tbmres = NULL; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &scanstate->ss.ps); scanstate->ss.ps.ps_TupFromTlist = false; /* * initialize child expressions */ scanstate->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) scanstate); scanstate->ss.ps.qual = (List *) ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) scanstate); scanstate->bitmapqualorig = (List *) ExecInitExpr((Expr *) node->bitmapqualorig, (PlanState *) scanstate); #define BITMAPHEAPSCAN_NSLOTS 2 /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &scanstate->ss.ps); ExecInitScanTupleSlot(estate, &scanstate->ss); /* * open the base relation and acquire appropriate lock on it. */ currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid); scanstate->ss.ss_currentRelation = currentRelation; /* * Even though we aren't going to do a conventional seqscan, it is useful * to create a HeapScanDesc --- this checks the relation size and sets up * statistical infrastructure for us. */ scanstate->ss.ss_currentScanDesc = heap_beginscan(currentRelation, estate->es_snapshot, 0, NULL); /* * One problem is that heap_beginscan counts a "sequential scan" start, * when we actually aren't doing any such thing. Reverse out the added * scan count. (Eventually we may want to count bitmap scans separately.) */ pgstat_discount_heap_scan(&scanstate->ss.ss_currentScanDesc->rs_pgstat_info); /* * get the scan type from the relation descriptor. */ ExecAssignScanType(&scanstate->ss, RelationGetDescr(currentRelation)); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&scanstate->ss.ps); ExecAssignScanProjectionInfo(&scanstate->ss); /* * 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(scanstate) = ExecInitNode(outerPlan(node), estate, eflags); /* * all done. */ return scanstate; }
/* ------------------------------------------------------------------ * ExecInitShareInputScan * ------------------------------------------------------------------ */ ShareInputScanState * ExecInitShareInputScan(ShareInputScan *node, EState *estate, int eflags) { ShareInputScanState *sisstate; Plan *outerPlan; TupleDesc tupDesc; Assert(innerPlan(node) == NULL); /* create state data structure */ sisstate = makeNode(ShareInputScanState); sisstate->ss.ps.plan = (Plan *) node; sisstate->ss.ps.state = estate; sisstate->ts_state = NULL; sisstate->ts_pos = NULL; sisstate->ts_markpos = NULL; sisstate->share_lk_ctxt = NULL; sisstate->freed = false; /* * init child node. * if outerPlan is NULL, this is no-op (so that the ShareInput node will be * only init-ed once). */ outerPlan = outerPlan(node); outerPlanState(sisstate) = ExecInitNode(outerPlan, estate, eflags); sisstate->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) node->plan.targetlist, (PlanState *) sisstate); Assert(node->plan.qual == NULL); sisstate->ss.ps.qual = NULL; /* Misc initialization * * Create expression context */ ExecAssignExprContext(estate, &sisstate->ss.ps); /* tuple table init */ ExecInitResultTupleSlot(estate, &sisstate->ss.ps); sisstate->ss.ss_ScanTupleSlot = ExecInitExtraTupleSlot(estate); /* * init tuple type. */ ExecAssignResultTypeFromTL(&sisstate->ss.ps); { bool hasoid; if (!ExecContextForcesOids(&sisstate->ss.ps, &hasoid)) hasoid = false; tupDesc = ExecTypeFromTL(node->plan.targetlist, hasoid); } ExecAssignScanType(&sisstate->ss, tupDesc); sisstate->ss.ps.ps_ProjInfo = NULL; /* * If this is an intra-slice share node, increment reference count to * tell the underlying node not to be freed before this node is ready to * be freed. fCreate flag to ExecGetShareNodeEntry is true because * at this point we don't have the entry which will be initialized in * the underlying node initialization later. */ if (node->share_type == SHARE_MATERIAL || node->share_type == SHARE_SORT) { ShareNodeEntry *snEntry = ExecGetShareNodeEntry(estate, node->share_id, true); snEntry->refcount++; } initGpmonPktForShareInputScan((Plan *)node, &sisstate->ss.ps.gpmon_pkt, estate); return sisstate; }
/* ---------------------------------------------------------------- * ExecInitForeignScan * ---------------------------------------------------------------- */ ForeignScanState * ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags) { ForeignScanState *scanstate; Relation currentRelation; FdwRoutine *fdwroutine; /* check for unsupported flags */ Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); /* * create state structure */ scanstate = makeNode(ForeignScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &scanstate->ss.ps); scanstate->ss.ps.ps_TupFromTlist = false; /* * initialize child expressions */ scanstate->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) scanstate); scanstate->ss.ps.qual = (List *) ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) scanstate); /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &scanstate->ss.ps); ExecInitScanTupleSlot(estate, &scanstate->ss); /* * open the base relation and acquire appropriate lock on it. */ currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid); scanstate->ss.ss_currentRelation = currentRelation; /* * get the scan type from the relation descriptor. */ ExecAssignScanType(&scanstate->ss, RelationGetDescr(currentRelation)); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&scanstate->ss.ps); ExecAssignScanProjectionInfo(&scanstate->ss); /* * Acquire function pointers from the FDW's handler, and init fdw_state. */ fdwroutine = GetFdwRoutineByRelId(RelationGetRelid(currentRelation)); scanstate->fdwroutine = fdwroutine; scanstate->fdw_state = NULL; /* * Tell the FDW to initiate the scan. */ fdwroutine->BeginForeignScan(scanstate, eflags); return scanstate; }
CustomScanState * ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags) { CustomScanState *css; Relation scan_rel = NULL; Index scanrelid = cscan->scan.scanrelid; Index tlistvarno; /* * Allocate the CustomScanState object. We let the custom scan provider * do the palloc, in case it wants to make a larger object that embeds * CustomScanState as the first field. It must set the node tag and the * methods field correctly at this time. Other standard fields should be * set to zero. */ css = (CustomScanState *) cscan->methods->CreateCustomScanState(cscan); Assert(IsA(css, CustomScanState)); /* ensure flags is filled correctly */ css->flags = cscan->flags; /* fill up fields of ScanState */ css->ss.ps.plan = &cscan->scan.plan; css->ss.ps.state = estate; /* create expression context for node */ ExecAssignExprContext(estate, &css->ss.ps); #ifdef PG95 css->ss.ps.ps_TupFromTlist = false; #endif /* initialize child expressions */ css->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) cscan->scan.plan.targetlist, (PlanState *) css); css->ss.ps.qual = (List *) ExecInitExpr((Expr *) cscan->scan.plan.qual, (PlanState *) css); /* tuple table initialization */ #ifndef PG95 if (((Scan*)css->ss.ps.plan)->scanrelid) { // For table scans ExecInitScanTupleSlot(estate, &css->ss); } else { // For tuple-table-slot scans (typically over Motion nodes) css->ss.ss_ScanTupleSlot = ExecAllocTableSlot(&estate->es_tupleTable); } #else ExecInitScanTupleSlot(estate, &css->ss); #endif ExecInitResultTupleSlot(estate, &css->ss.ps); /* * open the base relation, if any, and acquire an appropriate lock on it */ if (scanrelid > 0) { scan_rel = ExecOpenScanRelation(estate , scanrelid #ifdef PG95 , eflags #endif ); css->ss.ss_currentRelation = scan_rel; } /* * Determine the scan tuple type. If the custom scan provider provided a * targetlist describing the scan tuples, use that; else use base * relation's rowtype. */ if (cscan->custom_scan_tlist != NIL || scan_rel == NULL) { // index-only scan? GP doesn't define INDEX_VAR TupleDesc scan_tupdesc; scan_tupdesc = ExecTypeFromTL(cscan->custom_scan_tlist, false); ExecAssignScanType(&css->ss, scan_tupdesc); #ifdef PG95 /* Node's targetlist will contain Vars with varno = INDEX_VAR */ tlistvarno = INDEX_VAR; #endif } else { ExecAssignScanType(&css->ss, RelationGetDescr(scan_rel)); /* Node's targetlist will contain Vars with varno = scanrelid */ tlistvarno = scanrelid; } /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&css->ss.ps); #ifdef PG95 ExecAssignScanProjectionInfoWithVarno(&css->ss, tlistvarno); #else ExecAssignScanProjectionInfo(&css->ss); #endif /* * The callback of custom-scan provider applies the final initialization * of the custom-scan-state node according to its logic. */ css->methods->BeginCustomScan(css, estate, eflags); return css; }
/* ---------------------------------------------------------------- * ExecInitCteScan * ---------------------------------------------------------------- */ CteScanState * ExecInitCteScan(CteScan *node, EState *estate, int eflags) { CteScanState *scanstate; ParamExecData *prmdata; /* check for unsupported flags */ Assert(!(eflags & EXEC_FLAG_MARK)); /* * For the moment we have to force the tuplestore to allow REWIND, because * we might be asked to rescan the CTE even though upper levels didn't * tell us to be prepared to do it efficiently. Annoying, since this * prevents truncation of the tuplestore. XXX FIXME * * Note: if we are in an EPQ recheck plan tree, it's likely that no access * to the tuplestore is needed at all, making this even more annoying. * It's not worth improving that as long as all the read pointers would * have REWIND anyway, but if we ever improve this logic then that aspect * should be considered too. */ eflags |= EXEC_FLAG_REWIND; /* * CteScan should not have any children. */ Assert(outerPlan(node) == NULL); Assert(innerPlan(node) == NULL); /* * create new CteScanState for node */ scanstate = makeNode(CteScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; scanstate->eflags = eflags; scanstate->cte_table = NULL; scanstate->eof_cte = false; /* * Find the already-initialized plan for the CTE query. */ scanstate->cteplanstate = (PlanState *) list_nth(estate->es_subplanstates, node->ctePlanId - 1); /* * The Param slot associated with the CTE query is used to hold a pointer * to the CteState of the first CteScan node that initializes for this * CTE. This node will be the one that holds the shared state for all the * CTEs, particularly the shared tuplestore. */ prmdata = &(estate->es_param_exec_vals[node->cteParam]); Assert(prmdata->execPlan == NULL); Assert(!prmdata->isnull); scanstate->leader = (CteScanState *) DatumGetPointer(prmdata->value); if (scanstate->leader == NULL) { /* I am the leader */ prmdata->value = PointerGetDatum(scanstate); scanstate->leader = scanstate; scanstate->cte_table = tuplestore_begin_heap(true, false, work_mem); tuplestore_set_eflags(scanstate->cte_table, scanstate->eflags); scanstate->readptr = 0; } else { /* Not the leader */ Assert(IsA(scanstate->leader, CteScanState)); /* Create my own read pointer, and ensure it is at start */ scanstate->readptr = tuplestore_alloc_read_pointer(scanstate->leader->cte_table, scanstate->eflags); tuplestore_select_read_pointer(scanstate->leader->cte_table, scanstate->readptr); tuplestore_rescan(scanstate->leader->cte_table); } /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &scanstate->ss.ps); /* * initialize child expressions */ scanstate->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) scanstate); scanstate->ss.ps.qual = (List *) ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) scanstate); /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &scanstate->ss.ps); ExecInitScanTupleSlot(estate, &scanstate->ss); /* * The scan tuple type (ie, the rowtype we expect to find in the work * table) is the same as the result rowtype of the CTE query. */ ExecAssignScanType(&scanstate->ss, ExecGetResultType(scanstate->cteplanstate)); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&scanstate->ss.ps); ExecAssignScanProjectionInfo(&scanstate->ss); return scanstate; }
/* ---------------------------------------------------------------- * ExecInitBitmapHeapScan * * Initializes the scan's state information. * ---------------------------------------------------------------- */ BitmapHeapScanState * ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags) { BitmapHeapScanState *scanstate; Relation currentRelation; int io_concurrency; /* 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. */ Assert(IsMVCCSnapshot(estate->es_snapshot)); /* * create state structure */ scanstate = makeNode(BitmapHeapScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; scanstate->tbm = NULL; scanstate->tbmiterator = NULL; scanstate->tbmres = NULL; scanstate->exact_pages = 0; scanstate->lossy_pages = 0; scanstate->prefetch_iterator = NULL; scanstate->prefetch_pages = 0; scanstate->prefetch_target = 0; /* may be updated below */ scanstate->prefetch_maximum = target_prefetch_pages; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &scanstate->ss.ps); scanstate->ss.ps.ps_TupFromTlist = false; /* * initialize child expressions */ scanstate->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) scanstate); scanstate->ss.ps.qual = (List *) ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) scanstate); scanstate->bitmapqualorig = (List *) ExecInitExpr((Expr *) node->bitmapqualorig, (PlanState *) scanstate); /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &scanstate->ss.ps); ExecInitScanTupleSlot(estate, &scanstate->ss); /* * open the base relation and acquire appropriate lock on it. */ currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid, eflags); /* * Determine the maximum for prefetch_target. If the tablespace has a * specific IO concurrency set, use that to compute the corresponding * maximum value; otherwise, we already initialized to the value computed * by the GUC machinery. */ io_concurrency = get_tablespace_io_concurrency(currentRelation->rd_rel->reltablespace); if (io_concurrency != effective_io_concurrency) { double maximum; if (ComputeIoConcurrency(io_concurrency, &maximum)) scanstate->prefetch_maximum = rint(maximum); } scanstate->ss.ss_currentRelation = currentRelation; /* * Even though we aren't going to do a conventional seqscan, it is useful * to create a HeapScanDesc --- most of the fields in it are usable. */ scanstate->ss.ss_currentScanDesc = heap_beginscan_bm(currentRelation, estate->es_snapshot, 0, NULL); /* * get the scan type from the relation descriptor. */ ExecAssignScanType(&scanstate->ss, RelationGetDescr(currentRelation)); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&scanstate->ss.ps); ExecAssignScanProjectionInfo(&scanstate->ss); /* * 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(scanstate) = ExecInitNode(outerPlan(node), estate, eflags); /* * all done. */ return scanstate; }
/* ---------------------------------------------------------------- * ExecInitIndexScan * * Initializes the index scan's state information, creates * scan keys, and opens the base and index relations. * * Note: index scans have 2 sets of state information because * we have to keep track of the base relation and the * index relation. * ---------------------------------------------------------------- */ IndexScanState * ExecInitIndexScan(IndexScan *node, EState *estate, int eflags) { IndexScanState *indexstate; Relation currentRelation; bool relistarget; /* * create state structure */ indexstate = makeNode(IndexScanState); indexstate->ss.ps.plan = (Plan *) node; indexstate->ss.ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &indexstate->ss.ps); indexstate->ss.ps.ps_TupFromTlist = false; /* * initialize child expressions * * Note: we don't initialize all of the indexqual expression, only the * sub-parts corresponding to runtime keys (see below). Likewise for * indexorderby, if any. But the indexqualorig expression is always * initialized even though it will only be used in some uncommon cases --- * would be nice to improve that. (Problem is that any SubPlans present * in the expression must be found now...) */ indexstate->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) indexstate); indexstate->ss.ps.qual = (List *) ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) indexstate); indexstate->indexqualorig = (List *) ExecInitExpr((Expr *) node->indexqualorig, (PlanState *) indexstate); /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &indexstate->ss.ps); ExecInitScanTupleSlot(estate, &indexstate->ss); /* * open the base relation and acquire appropriate lock on it. */ currentRelation = ExecOpenScanRelation(estate, node->scan.scanrelid); indexstate->ss.ss_currentRelation = currentRelation; indexstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */ /* * get the scan type from the relation descriptor. */ ExecAssignScanType(&indexstate->ss, RelationGetDescr(currentRelation)); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&indexstate->ss.ps); ExecAssignScanProjectionInfo(&indexstate->ss); /* * If we are just doing EXPLAIN (ie, aren't going to run the plan), stop * here. This allows an index-advisor plugin to EXPLAIN a plan containing * references to nonexistent indexes. */ if (eflags & EXEC_FLAG_EXPLAIN_ONLY) return indexstate; /* * Open the index relation. * * If the parent table is one of the target relations of the query, then * InitPlan already opened and write-locked the index, so we can avoid * taking another lock here. Otherwise we need a normal reader's lock. */ relistarget = ExecRelationIsTargetRelation(estate, node->scan.scanrelid); indexstate->iss_RelationDesc = index_open(node->indexid, relistarget ? NoLock : AccessShareLock); /* * Initialize index-specific scan state */ indexstate->iss_RuntimeKeysReady = false; indexstate->iss_RuntimeKeys = NULL; indexstate->iss_NumRuntimeKeys = 0; /* * build the index scan keys from the index qualification */ ExecIndexBuildScanKeys((PlanState *) indexstate, indexstate->iss_RelationDesc, node->scan.scanrelid, node->indexqual, false, &indexstate->iss_ScanKeys, &indexstate->iss_NumScanKeys, &indexstate->iss_RuntimeKeys, &indexstate->iss_NumRuntimeKeys, NULL, /* no ArrayKeys */ NULL); /* * any ORDER BY exprs have to be turned into scankeys in the same way */ ExecIndexBuildScanKeys((PlanState *) indexstate, indexstate->iss_RelationDesc, node->scan.scanrelid, node->indexorderby, true, &indexstate->iss_OrderByKeys, &indexstate->iss_NumOrderByKeys, &indexstate->iss_RuntimeKeys, &indexstate->iss_NumRuntimeKeys, NULL, /* no ArrayKeys */ NULL); /* * If we have runtime keys, we need an ExprContext to evaluate them. The * node's standard context won't do because we want to reset that context * for every tuple. So, build another context just like the other one... * -tgl 7/11/00 */ if (indexstate->iss_NumRuntimeKeys != 0) { ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext; ExecAssignExprContext(estate, &indexstate->ss.ps); indexstate->iss_RuntimeContext = indexstate->ss.ps.ps_ExprContext; indexstate->ss.ps.ps_ExprContext = stdecontext; } else { indexstate->iss_RuntimeContext = NULL; } /* * Initialize scan descriptor. */ indexstate->iss_ScanDesc = index_beginscan(currentRelation, indexstate->iss_RelationDesc, estate->es_snapshot, indexstate->iss_NumScanKeys, indexstate->iss_NumOrderByKeys); /* * If no run-time keys to calculate, go ahead and pass the scankeys to the * index AM. */ if (indexstate->iss_NumRuntimeKeys == 0) index_rescan(indexstate->iss_ScanDesc, indexstate->iss_ScanKeys, indexstate->iss_NumScanKeys, indexstate->iss_OrderByKeys, indexstate->iss_NumOrderByKeys); /* * all done. */ return indexstate; }
/* ---------------------------------------------------------------- * ExecInitSubqueryScan * ---------------------------------------------------------------- */ subquery_ss* ExecInitSubqueryScan(subquery_scan_sc *node, exec_state_n *estate, int eflags) { subquery_ss *subquerystate; /* check for unsupported flags */ ASSERT(!(eflags & EXEC_FLAG_MARK)); /* * subquery_scan_sc should not have any "normal" children. Also, if planner * left anything in subrtable/subrowmark, it's fishy. */ ASSERT(OUTER_PLAN(node) == NULL); ASSERT(INNER_PLAN(node) == NULL); ASSERT(node->subrtable == NIL); ASSERT(node->subrowmark == NIL); /* * create state structure */ subquerystate = MK_N(SubqueryScanState,subquery_ss); subquerystate->ss.ps.plan = (plan_n *) node; subquerystate->ss.ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &subquerystate->ss.ps); /* * initialize child expressions */ subquerystate->ss.ps.targetlist = (struct list*) exec_init_expr( (expr_n*) node->scan.plan.targetlist, (plan_state_n*) subquerystate); subquerystate->ss.ps.qual = (struct list*) exec_init_expr( (expr_n*) node->scan.plan.qual, (plan_state_n*) subquerystate); /* * tuple table initialization */ exec_init_result_tupslot(estate, &subquerystate->ss.ps); exec_init_scan_tupslot(estate, &subquerystate->ss); /* * initialize subquery */ subquerystate->subplan = exec_init_node(node->subplan, estate, eflags); subquerystate->ss.ps.ps_TupFromTlist = false; /* * Initialize scan tuple type (needed by ExecAssignScanProjectionInfo) */ ExecAssignScanType(&subquerystate->ss, exec_get_result_type(subquerystate->subplan)); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&subquerystate->ss.ps); ExecAssignScanProjectionInfo(&subquerystate->ss); return subquerystate; }