1 /*-------------------------------------------------------------------------
2  *
3  * nodeBitmapOr.c
4  *	  routines to handle BitmapOr nodes.
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/nodeBitmapOr.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 /* INTERFACE ROUTINES
16  *		ExecInitBitmapOr	- initialize the BitmapOr node
17  *		MultiExecBitmapOr	- retrieve the result bitmap from the node
18  *		ExecEndBitmapOr		- shut down the BitmapOr node
19  *		ExecReScanBitmapOr	- rescan the BitmapOr node
20  *
21  *	 NOTES
22  *		BitmapOr nodes don't make use of their left and right
23  *		subtrees, rather they maintain a list of subplans,
24  *		much like Append nodes.  The logic is much simpler than
25  *		Append, however, since we needn't cope with forward/backward
26  *		execution.
27  */
28 
29 #include "postgres.h"
30 
31 #include "executor/execdebug.h"
32 #include "executor/nodeBitmapOr.h"
33 #include "miscadmin.h"
34 
35 
36 /* ----------------------------------------------------------------
37  *		ExecBitmapOr
38  *
39  *		stub for pro forma compliance
40  * ----------------------------------------------------------------
41  */
42 static TupleTableSlot *
ExecBitmapOr(PlanState * pstate)43 ExecBitmapOr(PlanState *pstate)
44 {
45 	elog(ERROR, "BitmapOr node does not support ExecProcNode call convention");
46 	return NULL;
47 }
48 
49 /* ----------------------------------------------------------------
50  *		ExecInitBitmapOr
51  *
52  *		Begin all of the subscans of the BitmapOr node.
53  * ----------------------------------------------------------------
54  */
55 BitmapOrState *
ExecInitBitmapOr(BitmapOr * node,EState * estate,int eflags)56 ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
57 {
58 	BitmapOrState *bitmaporstate = makeNode(BitmapOrState);
59 	PlanState **bitmapplanstates;
60 	int			nplans;
61 	int			i;
62 	ListCell   *l;
63 	Plan	   *initNode;
64 
65 	/* check for unsupported flags */
66 	Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
67 
68 	/*
69 	 * Set up empty vector of subplan states
70 	 */
71 	nplans = list_length(node->bitmapplans);
72 
73 	bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
74 
75 	/*
76 	 * create new BitmapOrState for our BitmapOr node
77 	 */
78 	bitmaporstate->ps.plan = (Plan *) node;
79 	bitmaporstate->ps.state = estate;
80 	bitmaporstate->ps.ExecProcNode = ExecBitmapOr;
81 	bitmaporstate->bitmapplans = bitmapplanstates;
82 	bitmaporstate->nplans = nplans;
83 
84 	/*
85 	 * Miscellaneous initialization
86 	 *
87 	 * BitmapOr plans don't have expression contexts because they never call
88 	 * ExecQual or ExecProject.  They don't need any tuple slots either.
89 	 */
90 
91 	/*
92 	 * call ExecInitNode on each of the plans to be executed and save the
93 	 * results into the array "bitmapplanstates".
94 	 */
95 	i = 0;
96 	foreach(l, node->bitmapplans)
97 	{
98 		initNode = (Plan *) lfirst(l);
99 		bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
100 		i++;
101 	}
102 
103 	return bitmaporstate;
104 }
105 
106 /* ----------------------------------------------------------------
107  *	   MultiExecBitmapOr
108  * ----------------------------------------------------------------
109  */
110 Node *
MultiExecBitmapOr(BitmapOrState * node)111 MultiExecBitmapOr(BitmapOrState *node)
112 {
113 	PlanState **bitmapplans;
114 	int			nplans;
115 	int			i;
116 	TIDBitmap  *result = NULL;
117 
118 	/* must provide our own instrumentation support */
119 	if (node->ps.instrument)
120 		InstrStartNode(node->ps.instrument);
121 
122 	/*
123 	 * get information from the node
124 	 */
125 	bitmapplans = node->bitmapplans;
126 	nplans = node->nplans;
127 
128 	/*
129 	 * Scan all the subplans and OR their result bitmaps
130 	 */
131 	for (i = 0; i < nplans; i++)
132 	{
133 		PlanState  *subnode = bitmapplans[i];
134 		TIDBitmap  *subresult;
135 
136 		/*
137 		 * We can special-case BitmapIndexScan children to avoid an explicit
138 		 * tbm_union step for each child: just pass down the current result
139 		 * bitmap and let the child OR directly into it.
140 		 */
141 		if (IsA(subnode, BitmapIndexScanState))
142 		{
143 			if (result == NULL) /* first subplan */
144 			{
145 				/* XXX should we use less than work_mem for this? */
146 				result = tbm_create(work_mem * 1024L,
147 									((BitmapOr *) node->ps.plan)->isshared ?
148 									node->ps.state->es_query_dsa : NULL);
149 			}
150 
151 			((BitmapIndexScanState *) subnode)->biss_result = result;
152 
153 			subresult = (TIDBitmap *) MultiExecProcNode(subnode);
154 
155 			if (subresult != result)
156 				elog(ERROR, "unrecognized result from subplan");
157 		}
158 		else
159 		{
160 			/* standard implementation */
161 			subresult = (TIDBitmap *) MultiExecProcNode(subnode);
162 
163 			if (!subresult || !IsA(subresult, TIDBitmap))
164 				elog(ERROR, "unrecognized result from subplan");
165 
166 			if (result == NULL)
167 				result = subresult; /* first subplan */
168 			else
169 			{
170 				tbm_union(result, subresult);
171 				tbm_free(subresult);
172 			}
173 		}
174 	}
175 
176 	/* We could return an empty result set here? */
177 	if (result == NULL)
178 		elog(ERROR, "BitmapOr doesn't support zero inputs");
179 
180 	/* must provide our own instrumentation support */
181 	if (node->ps.instrument)
182 		InstrStopNode(node->ps.instrument, 0 /* XXX */ );
183 
184 	return (Node *) result;
185 }
186 
187 /* ----------------------------------------------------------------
188  *		ExecEndBitmapOr
189  *
190  *		Shuts down the subscans of the BitmapOr node.
191  *
192  *		Returns nothing of interest.
193  * ----------------------------------------------------------------
194  */
195 void
ExecEndBitmapOr(BitmapOrState * node)196 ExecEndBitmapOr(BitmapOrState *node)
197 {
198 	PlanState **bitmapplans;
199 	int			nplans;
200 	int			i;
201 
202 	/*
203 	 * get information from the node
204 	 */
205 	bitmapplans = node->bitmapplans;
206 	nplans = node->nplans;
207 
208 	/*
209 	 * shut down each of the subscans (that we've initialized)
210 	 */
211 	for (i = 0; i < nplans; i++)
212 	{
213 		if (bitmapplans[i])
214 			ExecEndNode(bitmapplans[i]);
215 	}
216 }
217 
218 void
ExecReScanBitmapOr(BitmapOrState * node)219 ExecReScanBitmapOr(BitmapOrState *node)
220 {
221 	int			i;
222 
223 	for (i = 0; i < node->nplans; i++)
224 	{
225 		PlanState  *subnode = node->bitmapplans[i];
226 
227 		/*
228 		 * ExecReScan doesn't know about my subplans, so I have to do
229 		 * changed-parameter signaling myself.
230 		 */
231 		if (node->ps.chgParam != NULL)
232 			UpdateChangedParamSet(subnode, node->ps.chgParam);
233 
234 		/*
235 		 * If chgParam of subnode is not null then plan will be re-scanned by
236 		 * first ExecProcNode.
237 		 */
238 		if (subnode->chgParam == NULL)
239 			ExecReScan(subnode);
240 	}
241 }
242