/* * ExecAssignScanProjectionInfoWithVarno * As above, but caller can specify varno expected in Vars in the tlist. */ void ExecAssignScanProjectionInfoWithVarno(ScanState *node, Index varno) { TupleDesc tupdesc = node->ss_ScanTupleSlot->tts_tupleDescriptor; ExecConditionalAssignProjectionInfo(&node->ps, tupdesc, varno); }
/* * ExecAssignScanProjectionInfo * Set up projection info for a scan node, if necessary. * * We can avoid a projection step if the requested tlist exactly matches * the underlying tuple type. If so, we just set ps_ProjInfo to NULL. * Note that this case occurs not only for simple "SELECT * FROM ...", but * also in most cases where there are joins or other processing nodes above * the scan node, because the planner will preferentially generate a matching * tlist. * * ExecAssignScanType must have been called already. */ void ExecAssignScanProjectionInfo(ScanState *node) { Scan *scan = (Scan *) node->ps.plan; TupleDesc tupdesc = node->ss_ScanTupleSlot->tts_tupleDescriptor; ExecConditionalAssignProjectionInfo(&node->ps, tupdesc, scan->scanrelid); }
/* ---------------------------------------------------------------- * ExecInitGather * ---------------------------------------------------------------- */ GatherMergeState * ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags) { GatherMergeState *gm_state; Plan *outerNode; 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; gm_state->initialized = false; gm_state->gm_initialized = false; gm_state->tuples_needed = -1; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &gm_state->ps); /* * GatherMerge doesn't support checking a qual (it's always more efficient * to do it in the child node). */ Assert(!node->plan.qual); /* * now initialize outer plan */ outerNode = outerPlan(node); outerPlanState(gm_state) = ExecInitNode(outerNode, estate, eflags); /* * Leader may access ExecProcNode result directly (if * need_to_scan_locally), or from workers via tuple queue. So we can't * trivially rely on the slot type being fixed for expressions evaluated * within this node. */ gm_state->ps.outeropsset = true; gm_state->ps.outeropsfixed = false; /* * Store the tuple descriptor into gather merge state, so we can use it * while initializing the gather merge slots. */ tupDesc = ExecGetResultType(outerPlanState(gm_state)); gm_state->tupDesc = tupDesc; /* * Initialize result type and projection. */ ExecInitResultTypeTL(&gm_state->ps); ExecConditionalAssignProjectionInfo(&gm_state->ps, tupDesc, OUTER_VAR); /* * Without projections result slot type is not trivially known, see * comment above. */ if (gm_state->ps.ps_ProjInfo == NULL) { gm_state->ps.resultopsset = true; gm_state->ps.resultopsfixed = 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); } } /* Now allocate the workspace for gather merge */ gather_merge_setup(gm_state); return gm_state; }
/* ---------------------------------------------------------------- * 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; }