#include "postgres.h"
#include "executor/execdebug.h"
#include "executor/nodeAppend.h"
Go to the source code of this file.
Functions | |
static bool | exec_append_initialize_next (AppendState *appendstate) |
AppendState * | ExecInitAppend (Append *node, EState *estate, int eflags) |
TupleTableSlot * | ExecAppend (AppendState *node) |
void | ExecEndAppend (AppendState *node) |
void | ExecReScanAppend (AppendState *node) |
static bool exec_append_initialize_next | ( | AppendState * | appendstate | ) | [static] |
Definition at line 75 of file nodeAppend.c.
References AppendState::as_nplans, and AppendState::as_whichplan.
Referenced by ExecAppend(), ExecInitAppend(), and ExecReScanAppend().
{ int whichplan; /* * get information from the append node */ whichplan = appendstate->as_whichplan; if (whichplan < 0) { /* * if scanning in reverse, we start at the last scan in the list and * then proceed back to the first.. in any case we inform ExecAppend * that we are at the end of the line by returning FALSE */ appendstate->as_whichplan = 0; return FALSE; } else if (whichplan >= appendstate->as_nplans) { /* * as above, end the scan if we go beyond the last scan in our list.. */ appendstate->as_whichplan = appendstate->as_nplans - 1; return FALSE; } else { return TRUE; } }
TupleTableSlot* ExecAppend | ( | AppendState * | node | ) |
Definition at line 194 of file nodeAppend.c.
References AppendState::appendplans, AppendState::as_whichplan, EState::es_direction, exec_append_initialize_next(), ExecClearTuple(), ExecProcNode(), AppendState::ps, PlanState::ps_ResultTupleSlot, ScanDirectionIsForward, PlanState::state, and TupIsNull.
Referenced by ExecProcNode().
{ for (;;) { PlanState *subnode; TupleTableSlot *result; /* * figure out which subplan we are currently processing */ subnode = node->appendplans[node->as_whichplan]; /* * get a tuple from the subplan */ result = ExecProcNode(subnode); if (!TupIsNull(result)) { /* * If the subplan gave us something then return it as-is. We do * NOT make use of the result slot that was set up in * ExecInitAppend; there's no need for it. */ return result; } /* * Go on to the "next" subplan in the appropriate direction. If no * more subplans, return the empty slot set up for us by * ExecInitAppend. */ if (ScanDirectionIsForward(node->ps.state->es_direction)) node->as_whichplan++; else node->as_whichplan--; if (!exec_append_initialize_next(node)) return ExecClearTuple(node->ps.ps_ResultTupleSlot); /* Else loop back and try to get a tuple from the new subplan */ } }
void ExecEndAppend | ( | AppendState * | node | ) |
Definition at line 246 of file nodeAppend.c.
References AppendState::appendplans, AppendState::as_nplans, ExecEndNode(), and i.
Referenced by ExecEndNode().
{ PlanState **appendplans; int nplans; int i; /* * get information from the node */ appendplans = node->appendplans; nplans = node->as_nplans; /* * shut down each of the subscans */ for (i = 0; i < nplans; i++) ExecEndNode(appendplans[i]); }
AppendState* ExecInitAppend | ( | Append * | node, | |
EState * | estate, | |||
int | eflags | |||
) |
Definition at line 120 of file nodeAppend.c.
References AppendState::appendplans, Append::appendplans, AppendState::as_nplans, AppendState::as_whichplan, Assert, exec_append_initialize_next(), EXEC_FLAG_MARK, ExecAssignResultTypeFromTL(), ExecInitNode(), ExecInitResultTupleSlot(), i, lfirst, list_length(), makeNode, palloc0(), PlanState::plan, AppendState::ps, PlanState::ps_ProjInfo, and PlanState::state.
Referenced by ExecInitNode().
{ AppendState *appendstate = makeNode(AppendState); PlanState **appendplanstates; int nplans; int i; ListCell *lc; /* check for unsupported flags */ Assert(!(eflags & EXEC_FLAG_MARK)); /* * Set up empty vector of subplan states */ nplans = list_length(node->appendplans); appendplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *)); /* * create new AppendState for our append node */ appendstate->ps.plan = (Plan *) node; appendstate->ps.state = estate; appendstate->appendplans = appendplanstates; appendstate->as_nplans = nplans; /* * Miscellaneous initialization * * Append plans don't have expression contexts because they never call * ExecQual or ExecProject. */ /* * append nodes still have Result slots, which hold pointers to tuples, so * we have to initialize them. */ ExecInitResultTupleSlot(estate, &appendstate->ps); /* * call ExecInitNode on each of the plans to be executed and save the * results into the array "appendplans". */ i = 0; foreach(lc, node->appendplans) { Plan *initNode = (Plan *) lfirst(lc); appendplanstates[i] = ExecInitNode(initNode, estate, eflags); i++; } /* * initialize output tuple type */ ExecAssignResultTypeFromTL(&appendstate->ps); appendstate->ps.ps_ProjInfo = NULL; /* * initialize to scan first subplan */ appendstate->as_whichplan = 0; exec_append_initialize_next(appendstate); return appendstate; }
void ExecReScanAppend | ( | AppendState * | node | ) |
Definition at line 266 of file nodeAppend.c.
References AppendState::appendplans, AppendState::as_nplans, AppendState::as_whichplan, PlanState::chgParam, exec_append_initialize_next(), ExecReScan(), i, NULL, AppendState::ps, and UpdateChangedParamSet().
Referenced by ExecReScan().
{ int i; for (i = 0; i < node->as_nplans; i++) { PlanState *subnode = node->appendplans[i]; /* * ExecReScan doesn't know about my subplans, so I have to do * changed-parameter signaling myself. */ if (node->ps.chgParam != NULL) UpdateChangedParamSet(subnode, node->ps.chgParam); /* * If chgParam of subnode is not null then plan will be re-scanned by * first ExecProcNode. */ if (subnode->chgParam == NULL) ExecReScan(subnode); } node->as_whichplan = 0; exec_append_initialize_next(node); }