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"
25 #include "executor/nodeBitmapIndexscan.h"
26 #include "executor/nodeIndexscan.h"
27 #include "miscadmin.h"
28 #include "utils/memutils.h"
29 
30 
31 /* ----------------------------------------------------------------
32  *		ExecBitmapIndexScan
33  *
34  *		stub for pro forma compliance
35  * ----------------------------------------------------------------
36  */
37 static TupleTableSlot *
ExecBitmapIndexScan(PlanState * pstate)38 ExecBitmapIndexScan(PlanState *pstate)
39 {
40 	elog(ERROR, "BitmapIndexScan node does not support ExecProcNode call convention");
41 	return NULL;
42 }
43 
44 /* ----------------------------------------------------------------
45  *		MultiExecBitmapIndexScan(node)
46  * ----------------------------------------------------------------
47  */
48 Node *
MultiExecBitmapIndexScan(BitmapIndexScanState * node)49 MultiExecBitmapIndexScan(BitmapIndexScanState *node)
50 {
51 	TIDBitmap  *tbm;
52 	IndexScanDesc scandesc;
53 	double		nTuples = 0;
54 	bool		doscan;
55 
56 	/* must provide our own instrumentation support */
57 	if (node->ss.ps.instrument)
58 		InstrStartNode(node->ss.ps.instrument);
59 
60 	/*
61 	 * extract necessary information from index scan node
62 	 */
63 	scandesc = node->biss_ScanDesc;
64 
65 	/*
66 	 * If we have runtime keys and they've not already been set up, do it now.
67 	 * Array keys are also treated as runtime keys; note that if ExecReScan
68 	 * returns with biss_RuntimeKeysReady still false, then there is an empty
69 	 * array key so we should do nothing.
70 	 */
71 	if (!node->biss_RuntimeKeysReady &&
72 		(node->biss_NumRuntimeKeys != 0 || node->biss_NumArrayKeys != 0))
73 	{
74 		ExecReScan((PlanState *) node);
75 		doscan = node->biss_RuntimeKeysReady;
76 	}
77 	else
78 		doscan = true;
79 
80 	/*
81 	 * Prepare the result bitmap.  Normally we just create a new one to pass
82 	 * back; however, our parent node is allowed to store a pre-made one into
83 	 * node->biss_result, in which case we just OR our tuple IDs into the
84 	 * existing bitmap.  (This saves needing explicit UNION steps.)
85 	 */
86 	if (node->biss_result)
87 	{
88 		tbm = node->biss_result;
89 		node->biss_result = NULL;	/* reset for next time */
90 	}
91 	else
92 	{
93 		/* XXX should we use less than work_mem for this? */
94 		tbm = tbm_create(work_mem * 1024L,
95 						 ((BitmapIndexScan *) node->ss.ps.plan)->isshared ?
96 						 node->ss.ps.state->es_query_dsa : NULL);
97 	}
98 
99 	/*
100 	 * Get TIDs from index and insert into bitmap
101 	 */
102 	while (doscan)
103 	{
104 		nTuples += (double) index_getbitmap(scandesc, tbm);
105 
106 		CHECK_FOR_INTERRUPTS();
107 
108 		doscan = ExecIndexAdvanceArrayKeys(node->biss_ArrayKeys,
109 										   node->biss_NumArrayKeys);
110 		if (doscan)				/* reset index scan */
111 			index_rescan(node->biss_ScanDesc,
112 						 node->biss_ScanKeys, node->biss_NumScanKeys,
113 						 NULL, 0);
114 	}
115 
116 	/* must provide our own instrumentation support */
117 	if (node->ss.ps.instrument)
118 		InstrStopNode(node->ss.ps.instrument, nTuples);
119 
120 	return (Node *) tbm;
121 }
122 
123 /* ----------------------------------------------------------------
124  *		ExecReScanBitmapIndexScan(node)
125  *
126  *		Recalculates the values of any scan keys whose value depends on
127  *		information known at runtime, then rescans the indexed relation.
128  * ----------------------------------------------------------------
129  */
130 void
ExecReScanBitmapIndexScan(BitmapIndexScanState * node)131 ExecReScanBitmapIndexScan(BitmapIndexScanState *node)
132 {
133 	ExprContext *econtext = node->biss_RuntimeContext;
134 
135 	/*
136 	 * Reset the runtime-key context so we don't leak memory as each outer
137 	 * tuple is scanned.  Note this assumes that we will recalculate *all*
138 	 * runtime keys on each call.
139 	 */
140 	if (econtext)
141 		ResetExprContext(econtext);
142 
143 	/*
144 	 * If we are doing runtime key calculations (ie, any of the index key
145 	 * values weren't simple Consts), compute the new key values.
146 	 *
147 	 * Array keys are also treated as runtime keys; note that if we return
148 	 * with biss_RuntimeKeysReady still false, then there is an empty array
149 	 * key so no index scan is needed.
150 	 */
151 	if (node->biss_NumRuntimeKeys != 0)
152 		ExecIndexEvalRuntimeKeys(econtext,
153 								 node->biss_RuntimeKeys,
154 								 node->biss_NumRuntimeKeys);
155 	if (node->biss_NumArrayKeys != 0)
156 		node->biss_RuntimeKeysReady =
157 			ExecIndexEvalArrayKeys(econtext,
158 								   node->biss_ArrayKeys,
159 								   node->biss_NumArrayKeys);
160 	else
161 		node->biss_RuntimeKeysReady = true;
162 
163 	/* reset index scan */
164 	if (node->biss_RuntimeKeysReady)
165 		index_rescan(node->biss_ScanDesc,
166 					 node->biss_ScanKeys, node->biss_NumScanKeys,
167 					 NULL, 0);
168 }
169 
170 /* ----------------------------------------------------------------
171  *		ExecEndBitmapIndexScan
172  * ----------------------------------------------------------------
173  */
174 void
ExecEndBitmapIndexScan(BitmapIndexScanState * node)175 ExecEndBitmapIndexScan(BitmapIndexScanState *node)
176 {
177 	Relation	indexRelationDesc;
178 	IndexScanDesc indexScanDesc;
179 
180 	/*
181 	 * extract information from the node
182 	 */
183 	indexRelationDesc = node->biss_RelationDesc;
184 	indexScanDesc = node->biss_ScanDesc;
185 
186 	/*
187 	 * Free the exprcontext ... now dead code, see ExecFreeExprContext
188 	 */
189 #ifdef NOT_USED
190 	if (node->biss_RuntimeContext)
191 		FreeExprContext(node->biss_RuntimeContext, true);
192 #endif
193 
194 	/*
195 	 * close the index relation (no-op if we didn't open it)
196 	 */
197 	if (indexScanDesc)
198 		index_endscan(indexScanDesc);
199 	if (indexRelationDesc)
200 		index_close(indexRelationDesc, NoLock);
201 }
202 
203 /* ----------------------------------------------------------------
204  *		ExecInitBitmapIndexScan
205  *
206  *		Initializes the index scan's state information.
207  * ----------------------------------------------------------------
208  */
209 BitmapIndexScanState *
ExecInitBitmapIndexScan(BitmapIndexScan * node,EState * estate,int eflags)210 ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags)
211 {
212 	BitmapIndexScanState *indexstate;
213 	bool		relistarget;
214 
215 	/* check for unsupported flags */
216 	Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
217 
218 	/*
219 	 * create state structure
220 	 */
221 	indexstate = makeNode(BitmapIndexScanState);
222 	indexstate->ss.ps.plan = (Plan *) node;
223 	indexstate->ss.ps.state = estate;
224 	indexstate->ss.ps.ExecProcNode = ExecBitmapIndexScan;
225 
226 	/* normally we don't make the result bitmap till runtime */
227 	indexstate->biss_result = NULL;
228 
229 	/*
230 	 * Miscellaneous initialization
231 	 *
232 	 * We do not need a standard exprcontext for this node, though we may
233 	 * decide below to create a runtime-key exprcontext
234 	 */
235 
236 	/*
237 	 * initialize child expressions
238 	 *
239 	 * We don't need to initialize targetlist or qual since neither are used.
240 	 *
241 	 * Note: we don't initialize all of the indexqual expression, only the
242 	 * sub-parts corresponding to runtime keys (see below).
243 	 */
244 
245 	/*
246 	 * We do not open or lock the base relation here.  We assume that an
247 	 * ancestor BitmapHeapScan node is holding AccessShareLock (or better) on
248 	 * the heap relation throughout the execution of the plan tree.
249 	 */
250 
251 	indexstate->ss.ss_currentRelation = NULL;
252 	indexstate->ss.ss_currentScanDesc = NULL;
253 
254 	/*
255 	 * If we are just doing EXPLAIN (ie, aren't going to run the plan), stop
256 	 * here.  This allows an index-advisor plugin to EXPLAIN a plan containing
257 	 * references to nonexistent indexes.
258 	 */
259 	if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
260 		return indexstate;
261 
262 	/*
263 	 * Open the index relation.
264 	 *
265 	 * If the parent table is one of the target relations of the query, then
266 	 * InitPlan already opened and write-locked the index, so we can avoid
267 	 * taking another lock here.  Otherwise we need a normal reader's lock.
268 	 */
269 	relistarget = ExecRelationIsTargetRelation(estate, node->scan.scanrelid);
270 	indexstate->biss_RelationDesc = index_open(node->indexid,
271 											   relistarget ? NoLock : AccessShareLock);
272 
273 	/*
274 	 * Initialize index-specific scan state
275 	 */
276 	indexstate->biss_RuntimeKeysReady = false;
277 	indexstate->biss_RuntimeKeys = NULL;
278 	indexstate->biss_NumRuntimeKeys = 0;
279 
280 	/*
281 	 * build the index scan keys from the index qualification
282 	 */
283 	ExecIndexBuildScanKeys((PlanState *) indexstate,
284 						   indexstate->biss_RelationDesc,
285 						   node->indexqual,
286 						   false,
287 						   &indexstate->biss_ScanKeys,
288 						   &indexstate->biss_NumScanKeys,
289 						   &indexstate->biss_RuntimeKeys,
290 						   &indexstate->biss_NumRuntimeKeys,
291 						   &indexstate->biss_ArrayKeys,
292 						   &indexstate->biss_NumArrayKeys);
293 
294 	/*
295 	 * If we have runtime keys or array keys, we need an ExprContext to
296 	 * evaluate them. We could just create a "standard" plan node exprcontext,
297 	 * but to keep the code looking similar to nodeIndexscan.c, it seems
298 	 * better to stick with the approach of using a separate ExprContext.
299 	 */
300 	if (indexstate->biss_NumRuntimeKeys != 0 ||
301 		indexstate->biss_NumArrayKeys != 0)
302 	{
303 		ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;
304 
305 		ExecAssignExprContext(estate, &indexstate->ss.ps);
306 		indexstate->biss_RuntimeContext = indexstate->ss.ps.ps_ExprContext;
307 		indexstate->ss.ps.ps_ExprContext = stdecontext;
308 	}
309 	else
310 	{
311 		indexstate->biss_RuntimeContext = NULL;
312 	}
313 
314 	/*
315 	 * Initialize scan descriptor.
316 	 */
317 	indexstate->biss_ScanDesc =
318 		index_beginscan_bitmap(indexstate->biss_RelationDesc,
319 							   estate->es_snapshot,
320 							   indexstate->biss_NumScanKeys);
321 
322 	/*
323 	 * If no run-time keys to calculate, go ahead and pass the scankeys to the
324 	 * index AM.
325 	 */
326 	if (indexstate->biss_NumRuntimeKeys == 0 &&
327 		indexstate->biss_NumArrayKeys == 0)
328 		index_rescan(indexstate->biss_ScanDesc,
329 					 indexstate->biss_ScanKeys, indexstate->biss_NumScanKeys,
330 					 NULL, 0);
331 
332 	/*
333 	 * all done.
334 	 */
335 	return indexstate;
336 }
337