PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
nodeWorktablescan.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * nodeWorktablescan.c
4  * routines to handle WorkTableScan nodes.
5  *
6  * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/executor/nodeWorktablescan.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 
16 #include "postgres.h"
17 
18 #include "executor/execdebug.h"
20 
22 
23 /* ----------------------------------------------------------------
24  * WorkTableScanNext
25  *
26  * This is a workhorse for ExecWorkTableScan
27  * ----------------------------------------------------------------
28  */
29 static TupleTableSlot *
31 {
32  TupleTableSlot *slot;
33  Tuplestorestate *tuplestorestate;
34 
35  /*
36  * get information from the estate and scan state
37  *
38  * Note: we intentionally do not support backward scan. Although it would
39  * take only a couple more lines here, it would force nodeRecursiveunion.c
40  * to create the tuplestore with backward scan enabled, which has a
41  * performance cost. In practice backward scan is never useful for a
42  * worktable plan node, since it cannot appear high enough in the plan
43  * tree of a scrollable cursor to be exposed to a backward-scan
44  * requirement. So it's not worth expending effort to support it.
45  *
46  * Note: we are also assuming that this node is the only reader of the
47  * worktable. Therefore, we don't need a private read pointer for the
48  * tuplestore, nor do we need to tell tuplestore_gettupleslot to copy.
49  */
51 
52  tuplestorestate = node->rustate->working_table;
53 
54  /*
55  * Get the next tuple from tuplestore. Return NULL if no more tuples.
56  */
57  slot = node->ss.ss_ScanTupleSlot;
58  (void) tuplestore_gettupleslot(tuplestorestate, true, false, slot);
59  return slot;
60 }
61 
62 /*
63  * WorkTableScanRecheck -- access method routine to recheck a tuple in EvalPlanQual
64  */
65 static bool
67 {
68  /* nothing to check */
69  return true;
70 }
71 
72 /* ----------------------------------------------------------------
73  * ExecWorkTableScan(node)
74  *
75  * Scans the worktable sequentially and returns the next qualifying tuple.
76  * We call the ExecScan() routine and pass it the appropriate
77  * access method functions.
78  * ----------------------------------------------------------------
79  */
82 {
83  /*
84  * On the first call, find the ancestor RecursiveUnion's state via the
85  * Param slot reserved for it. (We can't do this during node init because
86  * there are corner cases where we'll get the init call before the
87  * RecursiveUnion does.)
88  */
89  if (node->rustate == NULL)
90  {
91  WorkTableScan *plan = (WorkTableScan *) node->ss.ps.plan;
92  EState *estate = node->ss.ps.state;
93  ParamExecData *param;
94 
95  param = &(estate->es_param_exec_vals[plan->wtParam]);
96  Assert(param->execPlan == NULL);
97  Assert(!param->isnull);
98  node->rustate = (RecursiveUnionState *) DatumGetPointer(param->value);
99  Assert(node->rustate && IsA(node->rustate, RecursiveUnionState));
100 
101  /*
102  * The scan tuple type (ie, the rowtype we expect to find in the work
103  * table) is the same as the result rowtype of the ancestor
104  * RecursiveUnion node. Note this depends on the assumption that
105  * RecursiveUnion doesn't allow projection.
106  */
107  ExecAssignScanType(&node->ss,
108  ExecGetResultType(&node->rustate->ps));
109 
110  /*
111  * Now we can initialize the projection info. This must be completed
112  * before we can call ExecScan().
113  */
115  }
116 
117  return ExecScan(&node->ss,
120 }
121 
122 
123 /* ----------------------------------------------------------------
124  * ExecInitWorkTableScan
125  * ----------------------------------------------------------------
126  */
128 ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags)
129 {
130  WorkTableScanState *scanstate;
131 
132  /* check for unsupported flags */
133  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
134 
135  /*
136  * WorkTableScan should not have any children.
137  */
138  Assert(outerPlan(node) == NULL);
139  Assert(innerPlan(node) == NULL);
140 
141  /*
142  * create new WorkTableScanState for node
143  */
144  scanstate = makeNode(WorkTableScanState);
145  scanstate->ss.ps.plan = (Plan *) node;
146  scanstate->ss.ps.state = estate;
147  scanstate->rustate = NULL; /* we'll set this later */
148 
149  /*
150  * Miscellaneous initialization
151  *
152  * create expression context for node
153  */
154  ExecAssignExprContext(estate, &scanstate->ss.ps);
155 
156  /*
157  * initialize child expressions
158  */
159  scanstate->ss.ps.targetlist = (List *)
161  (PlanState *) scanstate);
162  scanstate->ss.ps.qual = (List *)
163  ExecInitExpr((Expr *) node->scan.plan.qual,
164  (PlanState *) scanstate);
165 
166  /*
167  * tuple table initialization
168  */
169  ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
170  ExecInitScanTupleSlot(estate, &scanstate->ss);
171 
172  /*
173  * Initialize result tuple type, but not yet projection info.
174  */
175  ExecAssignResultTypeFromTL(&scanstate->ss.ps);
176 
177  scanstate->ss.ps.ps_TupFromTlist = false;
178 
179  return scanstate;
180 }
181 
182 /* ----------------------------------------------------------------
183  * ExecEndWorkTableScan
184  *
185  * frees any storage allocated through C routines.
186  * ----------------------------------------------------------------
187  */
188 void
190 {
191  /*
192  * Free exprcontext
193  */
194  ExecFreeExprContext(&node->ss.ps);
195 
196  /*
197  * clean out the tuple table
198  */
201 }
202 
203 /* ----------------------------------------------------------------
204  * ExecReScanWorkTableScan
205  *
206  * Rescans the relation.
207  * ----------------------------------------------------------------
208  */
209 void
211 {
213 
214  ExecScanReScan(&node->ss);
215 
216  /* No need (or way) to rescan if ExecWorkTableScan not called yet */
217  if (node->rustate)
219 }
void tuplestore_rescan(Tuplestorestate *state)
Definition: tuplestore.c:1216
List * qual
Definition: plannodes.h:122
Plan plan
Definition: plannodes.h:286
#define IsA(nodeptr, _type_)
Definition: nodes.h:542
void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate)
Definition: execTuples.c:845
#define ScanDirectionIsForward(direction)
Definition: sdir.h:55
static TupleTableSlot * WorkTableScanNext(WorkTableScanState *node)
Definition: plannodes.h:96
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:121
void ExecEndWorkTableScan(WorkTableScanState *node)
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:442
List * qual
Definition: execnodes.h:1042
List * targetlist
Definition: execnodes.h:1041
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1251
void ExecReScanWorkTableScan(WorkTableScanState *node)
EState * state
Definition: execnodes.h:1029
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:696
ScanDirection es_direction
Definition: execnodes.h:359
void ExecAssignResultTypeFromTL(PlanState *planstate)
Definition: execUtils.c:435
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:255
PlanState ps
Definition: execnodes.h:1248
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:256
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1057
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execQual.c:4452
void ExecAssignScanProjectionInfo(ScanState *node)
Definition: execScan.c:259
void ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
Definition: execTuples.c:835
#define EXEC_FLAG_BACKWARD
Definition: executor.h:59
#define innerPlan(node)
Definition: plannodes.h:150
Tuplestorestate * working_table
Definition: execnodes.h:1195
#define outerPlan(node)
Definition: plannodes.h:151
RecursiveUnionState * rustate
Definition: execnodes.h:1577
TupleTableSlot * ExecWorkTableScan(WorkTableScanState *node)
Plan * plan
Definition: execnodes.h:1027
#define makeNode(_type_)
Definition: nodes.h:539
bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)
Definition: tuplestore.c:1061
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:667
#define EXEC_FLAG_MARK
Definition: executor.h:60
static bool WorkTableScanRecheck(WorkTableScanState *node, TupleTableSlot *slot)
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:413
TupleDesc ExecGetResultType(PlanState *planstate)
Definition: execUtils.c:464
List * targetlist
Definition: plannodes.h:121
#define DatumGetPointer(X)
Definition: postgres.h:557
void ExecScanReScan(ScanState *node)
Definition: execScan.c:351
void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
Definition: execUtils.c:720
WorkTableScanState * ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags)
bool ps_TupFromTlist
Definition: execnodes.h:1060
Definition: pg_list.h:45