/* * BeginStreamScan */ void BeginStreamScan(ForeignScanState *node, int eflags) { ForeignScan *plan = (ForeignScan *) node->ss.ps.plan; StreamScanState *state; ListCell *lc; List *colnames = (List *) linitial(plan->fdw_private); List *physical_tlist = (List *) lsecond(plan->fdw_private); Value *sample_cutoff = (Value *) lthird(plan->fdw_private); int i = 0; state = palloc0(sizeof(StreamScanState)); state->pi = palloc(sizeof(StreamProjectionInfo)); state->pi->mcxt = AllocSetContextCreate(CurrentMemoryContext, "ExecProjectContext", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); state->pi->ecxt = CreateStandaloneExprContext(); state->pi->outdesc = ExecTypeFromTL(physical_tlist, false); state->pi->indesc = NULL; state->sample_cutoff = sample_cutoff ? intVal(sample_cutoff) : -1; Assert(state->pi->outdesc->natts == list_length(colnames)); foreach(lc, colnames) { Value *v = (Value *) lfirst(lc); namestrcpy(&(state->pi->outdesc->attrs[i++]->attname), strVal(v)); }
/* ---------------------------------------------------------------- * ExecInitPartitionSelector * * Create the run-time state information for PartitionSelector node * produced by Orca and initializes outer child if exists. * * ---------------------------------------------------------------- */ PartitionSelectorState * ExecInitPartitionSelector(PartitionSelector *node, EState *estate, int eflags) { /* check for unsupported flags */ Assert (!(eflags & (EXEC_FLAG_MARK | EXEC_FLAG_BACKWARD))); PartitionSelectorState *psstate = initPartitionSelection(node, estate); /* tuple table initialization */ ExecInitResultTupleSlot(estate, &psstate->ps); ExecAssignResultTypeFromTL(&psstate->ps); ExecAssignProjectionInfo(&psstate->ps, NULL); /* initialize child nodes */ /* No inner plan for PartitionSelector */ Assert(NULL == innerPlan(node)); if (NULL != outerPlan(node)) { outerPlanState(psstate) = ExecInitNode(outerPlan(node), estate, eflags); } /* * Initialize projection, to produce a tuple that has the partitioning key * columns at the same positions as in the partitioned table. */ if (node->partTabTargetlist) { List *exprStates; exprStates = (List *) ExecInitExpr((Expr *) node->partTabTargetlist, (PlanState *) psstate); psstate->partTabDesc = ExecTypeFromTL(node->partTabTargetlist, false); psstate->partTabSlot = MakeSingleTupleTableSlot(psstate->partTabDesc); psstate->partTabProj = ExecBuildProjectionInfo(exprStates, psstate->ps.ps_ExprContext, psstate->partTabSlot, ExecGetResultType(&psstate->ps)); } initGpmonPktForPartitionSelector((Plan *)node, &psstate->ps.gpmon_pkt, estate); return psstate; }
/* ---------------- * ExecAssignResultTypeFromTL * ---------------- */ void ExecAssignResultTypeFromTL(PlanState *planstate) { bool hasoid; TupleDesc tupDesc; if (ExecContextForcesOids(planstate, &hasoid)) { /* context forces OID choice; hasoid is now set correctly */ } else { /* given free choice, don't leave space for OIDs in result tuples */ hasoid = false; } /* * ExecTypeFromTL needs the parse-time representation of the tlist, not a * list of ExprStates. This is good because some plan nodes don't bother * to set up planstate->targetlist ... */ tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid); ExecAssignResultType(planstate, tupDesc); }
/* ---------------------------------------------------------------- * 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; }
/* ---------------------------------------------------------------- * ExecInitGather * ---------------------------------------------------------------- */ GatherState * ExecInitGather(Gather *node, EState *estate, int eflags) { GatherState *gatherstate; Plan *outerNode; bool hasoid; TupleDesc tupDesc; /* Gather node doesn't have innerPlan node. */ Assert(innerPlan(node) == NULL); /* * create state structure */ gatherstate = makeNode(GatherState); gatherstate->ps.plan = (Plan *) node; gatherstate->ps.state = estate; gatherstate->need_to_scan_locally = !node->single_copy; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &gatherstate->ps); /* * initialize child expressions */ gatherstate->ps.targetlist = (List *) ExecInitExpr((Expr *) node->plan.targetlist, (PlanState *) gatherstate); gatherstate->ps.qual = (List *) ExecInitExpr((Expr *) node->plan.qual, (PlanState *) gatherstate); /* * tuple table initialization */ gatherstate->funnel_slot = ExecInitExtraTupleSlot(estate); ExecInitResultTupleSlot(estate, &gatherstate->ps); /* * now initialize outer plan */ outerNode = outerPlan(node); outerPlanState(gatherstate) = ExecInitNode(outerNode, estate, eflags); gatherstate->ps.ps_TupFromTlist = false; /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&gatherstate->ps); ExecAssignProjectionInfo(&gatherstate->ps, NULL); /* * Initialize funnel slot to same tuple descriptor as outer plan. */ if (!ExecContextForcesOids(&gatherstate->ps, &hasoid)) hasoid = false; tupDesc = ExecTypeFromTL(outerNode->targetlist, hasoid); ExecSetSlotDescriptor(gatherstate->funnel_slot, tupDesc); return gatherstate; }
/* ------------------------------------------------------------------ * 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; }
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; }
/* ---------------------------------------------------------------- * 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; }
/* ---------------------------------------------------------------- * ExecInitGather * ---------------------------------------------------------------- */ GatherState * ExecInitGather(Gather *node, EState *estate, int eflags) { GatherState *gatherstate; Plan *outerNode; bool hasoid; TupleDesc tupDesc; /* Gather node doesn't have innerPlan node. */ Assert(innerPlan(node) == NULL); /* * create state structure */ gatherstate = makeNode(GatherState); gatherstate->ps.plan = (Plan *) node; gatherstate->ps.state = estate; gatherstate->ps.ExecProcNode = ExecGather; gatherstate->initialized = false; gatherstate->need_to_scan_locally = !node->single_copy && parallel_leader_participation; gatherstate->tuples_needed = -1; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &gatherstate->ps); /* * Gather doesn't support checking a qual (it's always more efficient to * do it in the child node). */ Assert(!node->plan.qual); /* * tuple table initialization */ gatherstate->funnel_slot = ExecInitExtraTupleSlot(estate); ExecInitResultTupleSlot(estate, &gatherstate->ps); /* * now initialize outer plan */ outerNode = outerPlan(node); outerPlanState(gatherstate) = ExecInitNode(outerNode, estate, eflags); /* * Initialize funnel slot to same tuple descriptor as outer plan. */ if (!ExecContextForcesOids(outerPlanState(gatherstate), &hasoid)) hasoid = false; tupDesc = ExecTypeFromTL(outerNode->targetlist, hasoid); ExecSetSlotDescriptor(gatherstate->funnel_slot, tupDesc); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&gatherstate->ps); ExecConditionalAssignProjectionInfo(&gatherstate->ps, tupDesc, OUTER_VAR); return gatherstate; }
/* ---------------------------------------------------------------- * ExecInitGather * ---------------------------------------------------------------- */ GatherMergeState * ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags) { GatherMergeState *gm_state; Plan *outerNode; bool hasoid; TupleDesc tupDesc; /* Gather merge node doesn't have innerPlan node. */ Assert(innerPlan(node) == NULL); /* * create state structure */ gm_state = makeNode(GatherMergeState); gm_state->ps.plan = (Plan *) node; gm_state->ps.state = estate; gm_state->ps.ExecProcNode = ExecGatherMerge; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &gm_state->ps); /* * initialize child expressions */ gm_state->ps.qual = ExecInitQual(node->plan.qual, &gm_state->ps); /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &gm_state->ps); /* * now initialize outer plan */ outerNode = outerPlan(node); outerPlanState(gm_state) = ExecInitNode(outerNode, estate, eflags); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&gm_state->ps); ExecAssignProjectionInfo(&gm_state->ps, NULL); gm_state->gm_initialized = false; /* * initialize sort-key information */ if (node->numCols) { int i; gm_state->gm_nkeys = node->numCols; gm_state->gm_sortkeys = palloc0(sizeof(SortSupportData) * node->numCols); for (i = 0; i < node->numCols; i++) { SortSupport sortKey = gm_state->gm_sortkeys + i; sortKey->ssup_cxt = CurrentMemoryContext; sortKey->ssup_collation = node->collations[i]; sortKey->ssup_nulls_first = node->nullsFirst[i]; sortKey->ssup_attno = node->sortColIdx[i]; /* * We don't perform abbreviated key conversion here, for the same * reasons that it isn't used in MergeAppend */ sortKey->abbreviate = false; PrepareSortSupportFromOrderingOp(node->sortOperators[i], sortKey); } } /* * store the tuple descriptor into gather merge state, so we can use it * later while initializing the gather merge slots. */ if (!ExecContextForcesOids(&gm_state->ps, &hasoid)) hasoid = false; tupDesc = ExecTypeFromTL(outerNode->targetlist, hasoid); gm_state->tupDesc = tupDesc; return gm_state; }