PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
execScan.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * execScan.c
4  * This code provides support for generalized relation scans. ExecScan
5  * is passed a node and a pointer to a function to "do the right thing"
6  * and return a tuple from the relation. ExecScan then does the tedious
7  * stuff - checking the qualification and projecting the tuple
8  * appropriately.
9  *
10  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
11  * Portions Copyright (c) 1994, Regents of the University of California
12  *
13  *
14  * IDENTIFICATION
15  * src/backend/executor/execScan.c
16  *
17  *-------------------------------------------------------------------------
18  */
19 #include "postgres.h"
20 
21 #include "executor/executor.h"
22 #include "miscadmin.h"
23 #include "utils/memutils.h"
24 
25 
26 static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc);
27 
28 
29 /*
30  * ExecScanFetch -- check interrupts & fetch next potential tuple
31  *
32  * This routine is concerned with substituting a test tuple if we are
33  * inside an EvalPlanQual recheck. If we aren't, just execute
34  * the access method's next-tuple routine.
35  */
36 static inline TupleTableSlot *
38  ExecScanAccessMtd accessMtd,
39  ExecScanRecheckMtd recheckMtd)
40 {
41  EState *estate = node->ps.state;
42 
44 
45  if (estate->es_epqTuple != NULL)
46  {
47  /*
48  * We are inside an EvalPlanQual recheck. Return the test tuple if
49  * one is available, after rechecking any access-method-specific
50  * conditions.
51  */
52  Index scanrelid = ((Scan *) node->ps.plan)->scanrelid;
53 
54  if (scanrelid == 0)
55  {
56  TupleTableSlot *slot = node->ss_ScanTupleSlot;
57 
58  /*
59  * This is a ForeignScan or CustomScan which has pushed down a
60  * join to the remote side. The recheck method is responsible not
61  * only for rechecking the scan/join quals but also for storing
62  * the correct tuple in the slot.
63  */
64  if (!(*recheckMtd) (node, slot))
65  ExecClearTuple(slot); /* would not be returned by scan */
66  return slot;
67  }
68  else if (estate->es_epqTupleSet[scanrelid - 1])
69  {
70  TupleTableSlot *slot = node->ss_ScanTupleSlot;
71 
72  /* Return empty slot if we already returned a tuple */
73  if (estate->es_epqScanDone[scanrelid - 1])
74  return ExecClearTuple(slot);
75  /* Else mark to remember that we shouldn't return more */
76  estate->es_epqScanDone[scanrelid - 1] = true;
77 
78  /* Return empty slot if we haven't got a test tuple */
79  if (estate->es_epqTuple[scanrelid - 1] == NULL)
80  return ExecClearTuple(slot);
81 
82  /* Store test tuple in the plan node's scan slot */
83  ExecStoreTuple(estate->es_epqTuple[scanrelid - 1],
84  slot, InvalidBuffer, false);
85 
86  /* Check if it meets the access-method conditions */
87  if (!(*recheckMtd) (node, slot))
88  ExecClearTuple(slot); /* would not be returned by scan */
89 
90  return slot;
91  }
92  }
93 
94  /*
95  * Run the node-type-specific access method function to get the next tuple
96  */
97  return (*accessMtd) (node);
98 }
99 
100 /* ----------------------------------------------------------------
101  * ExecScan
102  *
103  * Scans the relation using the 'access method' indicated and
104  * returns the next qualifying tuple in the direction specified
105  * in the global variable ExecDirection.
106  * The access method returns the next tuple and ExecScan() is
107  * responsible for checking the tuple returned against the qual-clause.
108  *
109  * A 'recheck method' must also be provided that can check an
110  * arbitrary tuple of the relation against any qual conditions
111  * that are implemented internal to the access method.
112  *
113  * Conditions:
114  * -- the "cursor" maintained by the AMI is positioned at the tuple
115  * returned previously.
116  *
117  * Initial States:
118  * -- the relation indicated is opened for scanning so that the
119  * "cursor" is positioned before the first qualifying tuple.
120  * ----------------------------------------------------------------
121  */
124  ExecScanAccessMtd accessMtd, /* function returning a tuple */
125  ExecScanRecheckMtd recheckMtd)
126 {
127  ExprContext *econtext;
128  ExprState *qual;
129  ProjectionInfo *projInfo;
130 
131  /*
132  * Fetch data from node
133  */
134  qual = node->ps.qual;
135  projInfo = node->ps.ps_ProjInfo;
136  econtext = node->ps.ps_ExprContext;
137 
138  /* interrupt checks are in ExecScanFetch */
139 
140  /*
141  * If we have neither a qual to check nor a projection to do, just skip
142  * all the overhead and return the raw scan tuple.
143  */
144  if (!qual && !projInfo)
145  {
146  ResetExprContext(econtext);
147  return ExecScanFetch(node, accessMtd, recheckMtd);
148  }
149 
150  /*
151  * Reset per-tuple memory context to free any expression evaluation
152  * storage allocated in the previous tuple cycle.
153  */
154  ResetExprContext(econtext);
155 
156  /*
157  * get a tuple from the access method. Loop until we obtain a tuple that
158  * passes the qualification.
159  */
160  for (;;)
161  {
162  TupleTableSlot *slot;
163 
164  slot = ExecScanFetch(node, accessMtd, recheckMtd);
165 
166  /*
167  * if the slot returned by the accessMtd contains NULL, then it means
168  * there is nothing more to scan so we just return an empty slot,
169  * being careful to use the projection result slot so it has correct
170  * tupleDesc.
171  */
172  if (TupIsNull(slot))
173  {
174  if (projInfo)
175  return ExecClearTuple(projInfo->pi_state.resultslot);
176  else
177  return slot;
178  }
179 
180  /*
181  * place the current tuple into the expr context
182  */
183  econtext->ecxt_scantuple = slot;
184 
185  /*
186  * check that the current tuple satisfies the qual-clause
187  *
188  * check for non-null qual here to avoid a function call to ExecQual()
189  * when the qual is null ... saves only a few cycles, but they add up
190  * ...
191  */
192  if (qual == NULL || ExecQual(qual, econtext))
193  {
194  /*
195  * Found a satisfactory scan tuple.
196  */
197  if (projInfo)
198  {
199  /*
200  * Form a projection tuple, store it in the result tuple slot
201  * and return it.
202  */
203  return ExecProject(projInfo);
204  }
205  else
206  {
207  /*
208  * Here, we aren't projecting, so just return scan tuple.
209  */
210  return slot;
211  }
212  }
213  else
214  InstrCountFiltered1(node, 1);
215 
216  /*
217  * Tuple fails qual, so free per-tuple memory and try again.
218  */
219  ResetExprContext(econtext);
220  }
221 }
222 
223 /*
224  * ExecAssignScanProjectionInfo
225  * Set up projection info for a scan node, if necessary.
226  *
227  * We can avoid a projection step if the requested tlist exactly matches
228  * the underlying tuple type. If so, we just set ps_ProjInfo to NULL.
229  * Note that this case occurs not only for simple "SELECT * FROM ...", but
230  * also in most cases where there are joins or other processing nodes above
231  * the scan node, because the planner will preferentially generate a matching
232  * tlist.
233  *
234  * ExecAssignScanType must have been called already.
235  */
236 void
238 {
239  Scan *scan = (Scan *) node->ps.plan;
240 
242 }
243 
244 /*
245  * ExecAssignScanProjectionInfoWithVarno
246  * As above, but caller can specify varno expected in Vars in the tlist.
247  */
248 void
250 {
251  Scan *scan = (Scan *) node->ps.plan;
252 
253  if (tlist_matches_tupdesc(&node->ps,
254  scan->plan.targetlist,
255  varno,
257  node->ps.ps_ProjInfo = NULL;
258  else
261 }
262 
263 static bool
264 tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc)
265 {
266  int numattrs = tupdesc->natts;
267  int attrno;
268  bool hasoid;
269  ListCell *tlist_item = list_head(tlist);
270 
271  /* Check the tlist attributes */
272  for (attrno = 1; attrno <= numattrs; attrno++)
273  {
274  Form_pg_attribute att_tup = TupleDescAttr(tupdesc, attrno - 1);
275  Var *var;
276 
277  if (tlist_item == NULL)
278  return false; /* tlist too short */
279  var = (Var *) ((TargetEntry *) lfirst(tlist_item))->expr;
280  if (!var || !IsA(var, Var))
281  return false; /* tlist item not a Var */
282  /* if these Asserts fail, planner messed up */
283  Assert(var->varno == varno);
284  Assert(var->varlevelsup == 0);
285  if (var->varattno != attrno)
286  return false; /* out of order */
287  if (att_tup->attisdropped)
288  return false; /* table contains dropped columns */
289 
290  /*
291  * Note: usually the Var's type should match the tupdesc exactly, but
292  * in situations involving unions of columns that have different
293  * typmods, the Var may have come from above the union and hence have
294  * typmod -1. This is a legitimate situation since the Var still
295  * describes the column, just not as exactly as the tupdesc does. We
296  * could change the planner to prevent it, but it'd then insert
297  * projection steps just to convert from specific typmod to typmod -1,
298  * which is pretty silly.
299  */
300  if (var->vartype != att_tup->atttypid ||
301  (var->vartypmod != att_tup->atttypmod &&
302  var->vartypmod != -1))
303  return false; /* type mismatch */
304 
305  tlist_item = lnext(tlist_item);
306  }
307 
308  if (tlist_item)
309  return false; /* tlist too long */
310 
311  /*
312  * If the plan context requires a particular hasoid setting, then that has
313  * to match, too.
314  */
315  if (ExecContextForcesOids(ps, &hasoid) &&
316  hasoid != tupdesc->tdhasoid)
317  return false;
318 
319  return true;
320 }
321 
322 /*
323  * ExecScanReScan
324  *
325  * This must be called within the ReScan function of any plan node type
326  * that uses ExecScan().
327  */
328 void
330 {
331  EState *estate = node->ps.state;
332 
333  /* Rescan EvalPlanQual tuple if we're inside an EvalPlanQual recheck */
334  if (estate->es_epqScanDone != NULL)
335  {
336  Index scanrelid = ((Scan *) node->ps.plan)->scanrelid;
337 
338  if (scanrelid > 0)
339  estate->es_epqScanDone[scanrelid - 1] = false;
340  else
341  {
342  Bitmapset *relids;
343  int rtindex = -1;
344 
345  /*
346  * If an FDW or custom scan provider has replaced the join with a
347  * scan, there are multiple RTIs; reset the epqScanDone flag for
348  * all of them.
349  */
350  if (IsA(node->ps.plan, ForeignScan))
351  relids = ((ForeignScan *) node->ps.plan)->fs_relids;
352  else if (IsA(node->ps.plan, CustomScan))
353  relids = ((CustomScan *) node->ps.plan)->custom_relids;
354  else
355  elog(ERROR, "unexpected scan node: %d",
356  (int) nodeTag(node->ps.plan));
357 
358  while ((rtindex = bms_next_member(relids, rtindex)) >= 0)
359  {
360  Assert(rtindex > 0);
361  estate->es_epqScanDone[rtindex - 1] = false;
362  }
363  }
364  }
365 }
TupleTableSlot * ExecStoreTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer, bool shouldFree)
Definition: execTuples.c:320
HeapTuple * es_epqTuple
Definition: execnodes.h:506
Plan plan
Definition: plannodes.h:328
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
Index varlevelsup
Definition: primnodes.h:173
bool tdhasoid
Definition: tupdesc.h:76
Index scanrelid
Definition: plannodes.h:329
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:882
static TupleTableSlot * ExecScanFetch(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:37
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:84
TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd, ExecScanRecheckMtd recheckMtd)
Definition: execScan.c:123
ExprContext * ps_ExprContext
Definition: execnodes.h:881
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:937
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
#define InvalidBuffer
Definition: buf.h:25
AttrNumber varattno
Definition: primnodes.h:168
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1103
EState * state
Definition: execnodes.h:849
TupleTableSlot * resultslot
Definition: execnodes.h:69
static bool ExecQual(ExprState *state, ExprContext *econtext)
Definition: executor.h:366
Definition: primnodes.h:163
int natts
Definition: tupdesc.h:73
TupleTableSlot *(* ExecScanAccessMtd)(ScanState *node)
Definition: executor.h:409
void ExecAssignScanProjectionInfoWithVarno(ScanState *node, Index varno)
Definition: execScan.c:249
PlanState ps
Definition: execnodes.h:1100
bool(* ExecScanRecheckMtd)(ScanState *node, TupleTableSlot *slot)
Definition: executor.h:410
#define ERROR
Definition: elog.h:43
void ExecAssignScanProjectionInfo(ScanState *node)
Definition: execScan.c:237
Oid vartype
Definition: primnodes.h:170
void ExecAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc)
Definition: execUtils.c:492
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define TupIsNull(slot)
Definition: tuptable.h:138
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
#define InstrCountFiltered1(node, delta)
Definition: execnodes.h:896
#define lnext(lc)
Definition: pg_list.h:105
Index varno
Definition: primnodes.h:166
TupleDesc tts_tupleDescriptor
Definition: tuptable.h:121
static bool tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc)
Definition: execScan.c:264
unsigned int Index
Definition: c.h:359
Plan * plan
Definition: execnodes.h:847
#define Assert(condition)
Definition: c.h:664
#define lfirst(lc)
Definition: pg_list.h:106
TupleTableSlot * ecxt_scantuple
Definition: execnodes.h:197
bool * es_epqTupleSet
Definition: execnodes.h:507
#define nodeTag(nodeptr)
Definition: nodes.h:514
List * targetlist
Definition: plannodes.h:144
ExprState * qual
Definition: execnodes.h:865
bool * es_epqScanDone
Definition: execnodes.h:508
void ExecScanReScan(ScanState *node)
Definition: execScan.c:329
ExprState pi_state
Definition: execnodes.h:296
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
bool ExecContextForcesOids(PlanState *planstate, bool *hasoids)
Definition: execMain.c:1515
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
static TupleTableSlot * ExecProject(ProjectionInfo *projInfo)
Definition: executor.h:329
#define ResetExprContext(econtext)
Definition: executor.h:470
int32 vartypmod
Definition: primnodes.h:171