PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
nodeBitmapIndexscan.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * nodeBitmapIndexscan.c
4  * Routines to support bitmapped index scans of relations
5  *
6  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/executor/nodeBitmapIndexscan.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 /*
16  * INTERFACE ROUTINES
17  * MultiExecBitmapIndexScan scans a relation using index.
18  * ExecInitBitmapIndexScan creates and initializes state info.
19  * ExecReScanBitmapIndexScan prepares to rescan the plan.
20  * ExecEndBitmapIndexScan releases all storage.
21  */
22 #include "postgres.h"
23 
24 #include "executor/execdebug.h"
26 #include "executor/nodeIndexscan.h"
27 #include "miscadmin.h"
28 #include "utils/memutils.h"
29 
30 
31 /* ----------------------------------------------------------------
32  * MultiExecBitmapIndexScan(node)
33  * ----------------------------------------------------------------
34  */
35 Node *
37 {
38  TIDBitmap *tbm;
39  IndexScanDesc scandesc;
40  double nTuples = 0;
41  bool doscan;
42 
43  /* must provide our own instrumentation support */
44  if (node->ss.ps.instrument)
46 
47  /*
48  * extract necessary information from index scan node
49  */
50  scandesc = node->biss_ScanDesc;
51 
52  /*
53  * If we have runtime keys and they've not already been set up, do it now.
54  * Array keys are also treated as runtime keys; note that if ExecReScan
55  * returns with biss_RuntimeKeysReady still false, then there is an empty
56  * array key so we should do nothing.
57  */
58  if (!node->biss_RuntimeKeysReady &&
59  (node->biss_NumRuntimeKeys != 0 || node->biss_NumArrayKeys != 0))
60  {
61  ExecReScan((PlanState *) node);
62  doscan = node->biss_RuntimeKeysReady;
63  }
64  else
65  doscan = true;
66 
67  /*
68  * Prepare the result bitmap. Normally we just create a new one to pass
69  * back; however, our parent node is allowed to store a pre-made one into
70  * node->biss_result, in which case we just OR our tuple IDs into the
71  * existing bitmap. (This saves needing explicit UNION steps.)
72  */
73  if (node->biss_result)
74  {
75  tbm = node->biss_result;
76  node->biss_result = NULL; /* reset for next time */
77  }
78  else
79  {
80  /* XXX should we use less than work_mem for this? */
81  tbm = tbm_create(work_mem * 1024L,
82  ((BitmapIndexScan *) node->ss.ps.plan)->isshared ?
83  node->ss.ps.state->es_query_dsa : NULL);
84  }
85 
86  /*
87  * Get TIDs from index and insert into bitmap
88  */
89  while (doscan)
90  {
91  nTuples += (double) index_getbitmap(scandesc, tbm);
92 
94 
96  node->biss_NumArrayKeys);
97  if (doscan) /* reset index scan */
99  node->biss_ScanKeys, node->biss_NumScanKeys,
100  NULL, 0);
101  }
102 
103  /* must provide our own instrumentation support */
104  if (node->ss.ps.instrument)
105  InstrStopNode(node->ss.ps.instrument, nTuples);
106 
107  return (Node *) tbm;
108 }
109 
110 /* ----------------------------------------------------------------
111  * ExecReScanBitmapIndexScan(node)
112  *
113  * Recalculates the values of any scan keys whose value depends on
114  * information known at runtime, then rescans the indexed relation.
115  * ----------------------------------------------------------------
116  */
117 void
119 {
120  ExprContext *econtext = node->biss_RuntimeContext;
121 
122  /*
123  * Reset the runtime-key context so we don't leak memory as each outer
124  * tuple is scanned. Note this assumes that we will recalculate *all*
125  * runtime keys on each call.
126  */
127  if (econtext)
128  ResetExprContext(econtext);
129 
130  /*
131  * If we are doing runtime key calculations (ie, any of the index key
132  * values weren't simple Consts), compute the new key values.
133  *
134  * Array keys are also treated as runtime keys; note that if we return
135  * with biss_RuntimeKeysReady still false, then there is an empty array
136  * key so no index scan is needed.
137  */
138  if (node->biss_NumRuntimeKeys != 0)
139  ExecIndexEvalRuntimeKeys(econtext,
140  node->biss_RuntimeKeys,
141  node->biss_NumRuntimeKeys);
142  if (node->biss_NumArrayKeys != 0)
143  node->biss_RuntimeKeysReady =
144  ExecIndexEvalArrayKeys(econtext,
145  node->biss_ArrayKeys,
146  node->biss_NumArrayKeys);
147  else
148  node->biss_RuntimeKeysReady = true;
149 
150  /* reset index scan */
151  if (node->biss_RuntimeKeysReady)
153  node->biss_ScanKeys, node->biss_NumScanKeys,
154  NULL, 0);
155 }
156 
157 /* ----------------------------------------------------------------
158  * ExecEndBitmapIndexScan
159  * ----------------------------------------------------------------
160  */
161 void
163 {
164  Relation indexRelationDesc;
165  IndexScanDesc indexScanDesc;
166 
167  /*
168  * extract information from the node
169  */
170  indexRelationDesc = node->biss_RelationDesc;
171  indexScanDesc = node->biss_ScanDesc;
172 
173  /*
174  * Free the exprcontext ... now dead code, see ExecFreeExprContext
175  */
176 #ifdef NOT_USED
177  if (node->biss_RuntimeContext)
179 #endif
180 
181  /*
182  * close the index relation (no-op if we didn't open it)
183  */
184  if (indexScanDesc)
185  index_endscan(indexScanDesc);
186  if (indexRelationDesc)
187  index_close(indexRelationDesc, NoLock);
188 }
189 
190 /* ----------------------------------------------------------------
191  * ExecInitBitmapIndexScan
192  *
193  * Initializes the index scan's state information.
194  * ----------------------------------------------------------------
195  */
197 ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
198 {
199  BitmapIndexScanState *indexstate;
200  bool relistarget;
201 
202  /* check for unsupported flags */
203  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
204 
205  /*
206  * create state structure
207  */
208  indexstate = makeNode(BitmapIndexScanState);
209  indexstate->ss.ps.plan = (Plan *) node;
210  indexstate->ss.ps.state = estate;
211 
212  /* normally we don't make the result bitmap till runtime */
213  indexstate->biss_result = NULL;
214 
215  /*
216  * Miscellaneous initialization
217  *
218  * We do not need a standard exprcontext for this node, though we may
219  * decide below to create a runtime-key exprcontext
220  */
221 
222  /*
223  * initialize child expressions
224  *
225  * We don't need to initialize targetlist or qual since neither are used.
226  *
227  * Note: we don't initialize all of the indexqual expression, only the
228  * sub-parts corresponding to runtime keys (see below).
229  */
230 
231  /*
232  * We do not open or lock the base relation here. We assume that an
233  * ancestor BitmapHeapScan node is holding AccessShareLock (or better) on
234  * the heap relation throughout the execution of the plan tree.
235  */
236 
237  indexstate->ss.ss_currentRelation = NULL;
238  indexstate->ss.ss_currentScanDesc = NULL;
239 
240  /*
241  * If we are just doing EXPLAIN (ie, aren't going to run the plan), stop
242  * here. This allows an index-advisor plugin to EXPLAIN a plan containing
243  * references to nonexistent indexes.
244  */
245  if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
246  return indexstate;
247 
248  /*
249  * Open the index relation.
250  *
251  * If the parent table is one of the target relations of the query, then
252  * InitPlan already opened and write-locked the index, so we can avoid
253  * taking another lock here. Otherwise we need a normal reader's lock.
254  */
255  relistarget = ExecRelationIsTargetRelation(estate, node->scan.scanrelid);
256  indexstate->biss_RelationDesc = index_open(node->indexid,
257  relistarget ? NoLock : AccessShareLock);
258 
259  /*
260  * Initialize index-specific scan state
261  */
262  indexstate->biss_RuntimeKeysReady = false;
263  indexstate->biss_RuntimeKeys = NULL;
264  indexstate->biss_NumRuntimeKeys = 0;
265 
266  /*
267  * build the index scan keys from the index qualification
268  */
269  ExecIndexBuildScanKeys((PlanState *) indexstate,
270  indexstate->biss_RelationDesc,
271  node->indexqual,
272  false,
273  &indexstate->biss_ScanKeys,
274  &indexstate->biss_NumScanKeys,
275  &indexstate->biss_RuntimeKeys,
276  &indexstate->biss_NumRuntimeKeys,
277  &indexstate->biss_ArrayKeys,
278  &indexstate->biss_NumArrayKeys);
279 
280  /*
281  * If we have runtime keys or array keys, we need an ExprContext to
282  * evaluate them. We could just create a "standard" plan node exprcontext,
283  * but to keep the code looking similar to nodeIndexscan.c, it seems
284  * better to stick with the approach of using a separate ExprContext.
285  */
286  if (indexstate->biss_NumRuntimeKeys != 0 ||
287  indexstate->biss_NumArrayKeys != 0)
288  {
289  ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;
290 
291  ExecAssignExprContext(estate, &indexstate->ss.ps);
292  indexstate->biss_RuntimeContext = indexstate->ss.ps.ps_ExprContext;
293  indexstate->ss.ps.ps_ExprContext = stdecontext;
294  }
295  else
296  {
297  indexstate->biss_RuntimeContext = NULL;
298  }
299 
300  /*
301  * Initialize scan descriptor.
302  */
303  indexstate->biss_ScanDesc =
305  estate->es_snapshot,
306  indexstate->biss_NumScanKeys);
307 
308  /*
309  * If no run-time keys to calculate, go ahead and pass the scankeys to the
310  * index AM.
311  */
312  if (indexstate->biss_NumRuntimeKeys == 0 &&
313  indexstate->biss_NumArrayKeys == 0)
314  index_rescan(indexstate->biss_ScanDesc,
315  indexstate->biss_ScanKeys, indexstate->biss_NumScanKeys,
316  NULL, 0);
317 
318  /*
319  * all done.
320  */
321  return indexstate;
322 }
IndexScanDesc index_beginscan_bitmap(Relation indexRelation, Snapshot snapshot, int nkeys)
Definition: indexam.c:247
void InstrStopNode(Instrumentation *instr, double nTuples)
Definition: instrument.c:80
IndexRuntimeKeyInfo * biss_RuntimeKeys
Definition: execnodes.h:1213
struct dsa_area * es_query_dsa
Definition: execnodes.h:475
Index scanrelid
Definition: plannodes.h:316
Instrumentation * instrument
Definition: execnodes.h:806
TIDBitmap * tbm_create(long maxbytes, dsa_area *dsa)
Definition: tidbitmap.c:281
ExprContext * ps_ExprContext
Definition: execnodes.h:830
bool ExecIndexAdvanceArrayKeys(IndexArrayKeyInfo *arrayKeys, int numArrayKeys)
List * indexqual
Definition: plannodes.h:434
void ExecReScan(PlanState *node)
Definition: execAmi.c:74
Relation biss_RelationDesc
Definition: execnodes.h:1219
#define AccessShareLock
Definition: lockdefs.h:36
void index_rescan(IndexScanDesc scan, ScanKey keys, int nkeys, ScanKey orderbys, int norderbys)
Definition: indexam.c:310
Definition: nodes.h:504
Snapshot es_snapshot
Definition: execnodes.h:408
Relation ss_currentRelation
Definition: execnodes.h:1045
EState * state
Definition: execnodes.h:802
bool ExecIndexEvalArrayKeys(ExprContext *econtext, IndexArrayKeyInfo *arrayKeys, int numArrayKeys)
PlanState ps
Definition: execnodes.h:1044
void InstrStartNode(Instrumentation *instr)
Definition: instrument.c:63
BitmapIndexScanState * ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
#define EXEC_FLAG_BACKWARD
Definition: executor.h:60
#define NoLock
Definition: lockdefs.h:34
void ExecEndBitmapIndexScan(BitmapIndexScanState *node)
void ExecReScanBitmapIndexScan(BitmapIndexScanState *node)
Node * MultiExecBitmapIndexScan(BitmapIndexScanState *node)
void index_endscan(IndexScanDesc scan)
Definition: indexam.c:340
int64 index_getbitmap(IndexScanDesc scan, TIDBitmap *bitmap)
Definition: indexam.c:713
IndexScanDesc biss_ScanDesc
Definition: execnodes.h:1220
void FreeExprContext(ExprContext *econtext, bool isCommit)
Definition: execUtils.c:344
int work_mem
Definition: globals.c:112
TIDBitmap * biss_result
Definition: execnodes.h:1210
Plan * plan
Definition: execnodes.h:800
#define makeNode(_type_)
Definition: nodes.h:552
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define EXEC_FLAG_MARK
Definition: executor.h:61
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:413
void ExecIndexBuildScanKeys(PlanState *planstate, Relation index, List *quals, bool isorderby, ScanKey *scanKeys, int *numScanKeys, IndexRuntimeKeyInfo **runtimeKeys, int *numRuntimeKeys, IndexArrayKeyInfo **arrayKeys, int *numArrayKeys)
void ExecIndexEvalRuntimeKeys(ExprContext *econtext, IndexRuntimeKeyInfo *runtimeKeys, int numRuntimeKeys)
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:176
HeapScanDesc ss_currentScanDesc
Definition: execnodes.h:1046
IndexArrayKeyInfo * biss_ArrayKeys
Definition: execnodes.h:1215
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
ExprContext * biss_RuntimeContext
Definition: execnodes.h:1218
#define EXEC_FLAG_EXPLAIN_ONLY
Definition: executor.h:58
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:151
bool ExecRelationIsTargetRelation(EState *estate, Index scanrelid)
Definition: execUtils.c:572
#define ResetExprContext(econtext)
Definition: executor.h:450