PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
nodeBitmapOr.c
Go to the documentation of this file.
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  * ExecInitBitmapOr
38  *
39  * Begin all of the subscans of the BitmapOr node.
40  * ----------------------------------------------------------------
41  */
43 ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
44 {
45  BitmapOrState *bitmaporstate = makeNode(BitmapOrState);
46  PlanState **bitmapplanstates;
47  int nplans;
48  int i;
49  ListCell *l;
50  Plan *initNode;
51 
52  /* check for unsupported flags */
53  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
54 
55  /*
56  * Set up empty vector of subplan states
57  */
58  nplans = list_length(node->bitmapplans);
59 
60  bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
61 
62  /*
63  * create new BitmapOrState for our BitmapOr node
64  */
65  bitmaporstate->ps.plan = (Plan *) node;
66  bitmaporstate->ps.state = estate;
67  bitmaporstate->bitmapplans = bitmapplanstates;
68  bitmaporstate->nplans = nplans;
69 
70  /*
71  * Miscellaneous initialization
72  *
73  * BitmapOr plans don't have expression contexts because they never call
74  * ExecQual or ExecProject. They don't need any tuple slots either.
75  */
76 
77  /*
78  * call ExecInitNode on each of the plans to be executed and save the
79  * results into the array "bitmapplanstates".
80  */
81  i = 0;
82  foreach(l, node->bitmapplans)
83  {
84  initNode = (Plan *) lfirst(l);
85  bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
86  i++;
87  }
88 
89  return bitmaporstate;
90 }
91 
92 /* ----------------------------------------------------------------
93  * MultiExecBitmapOr
94  * ----------------------------------------------------------------
95  */
96 Node *
98 {
99  PlanState **bitmapplans;
100  int nplans;
101  int i;
102  TIDBitmap *result = NULL;
103 
104  /* must provide our own instrumentation support */
105  if (node->ps.instrument)
107 
108  /*
109  * get information from the node
110  */
111  bitmapplans = node->bitmapplans;
112  nplans = node->nplans;
113 
114  /*
115  * Scan all the subplans and OR their result bitmaps
116  */
117  for (i = 0; i < nplans; i++)
118  {
119  PlanState *subnode = bitmapplans[i];
120  TIDBitmap *subresult;
121 
122  /*
123  * We can special-case BitmapIndexScan children to avoid an explicit
124  * tbm_union step for each child: just pass down the current result
125  * bitmap and let the child OR directly into it.
126  */
127  if (IsA(subnode, BitmapIndexScanState))
128  {
129  if (result == NULL) /* first subplan */
130  {
131  /* XXX should we use less than work_mem for this? */
132  result = tbm_create(work_mem * 1024L);
133  }
134 
135  ((BitmapIndexScanState *) subnode)->biss_result = result;
136 
137  subresult = (TIDBitmap *) MultiExecProcNode(subnode);
138 
139  if (subresult != result)
140  elog(ERROR, "unrecognized result from subplan");
141  }
142  else
143  {
144  /* standard implementation */
145  subresult = (TIDBitmap *) MultiExecProcNode(subnode);
146 
147  if (!subresult || !IsA(subresult, TIDBitmap))
148  elog(ERROR, "unrecognized result from subplan");
149 
150  if (result == NULL)
151  result = subresult; /* first subplan */
152  else
153  {
154  tbm_union(result, subresult);
155  tbm_free(subresult);
156  }
157  }
158  }
159 
160  /* We could return an empty result set here? */
161  if (result == NULL)
162  elog(ERROR, "BitmapOr doesn't support zero inputs");
163 
164  /* must provide our own instrumentation support */
165  if (node->ps.instrument)
166  InstrStopNode(node->ps.instrument, 0 /* XXX */ );
167 
168  return (Node *) result;
169 }
170 
171 /* ----------------------------------------------------------------
172  * ExecEndBitmapOr
173  *
174  * Shuts down the subscans of the BitmapOr node.
175  *
176  * Returns nothing of interest.
177  * ----------------------------------------------------------------
178  */
179 void
181 {
182  PlanState **bitmapplans;
183  int nplans;
184  int i;
185 
186  /*
187  * get information from the node
188  */
189  bitmapplans = node->bitmapplans;
190  nplans = node->nplans;
191 
192  /*
193  * shut down each of the subscans (that we've initialized)
194  */
195  for (i = 0; i < nplans; i++)
196  {
197  if (bitmapplans[i])
198  ExecEndNode(bitmapplans[i]);
199  }
200 }
201 
202 void
204 {
205  int i;
206 
207  for (i = 0; i < node->nplans; i++)
208  {
209  PlanState *subnode = node->bitmapplans[i];
210 
211  /*
212  * ExecReScan doesn't know about my subplans, so I have to do
213  * changed-parameter signaling myself.
214  */
215  if (node->ps.chgParam != NULL)
216  UpdateChangedParamSet(subnode, node->ps.chgParam);
217 
218  /*
219  * If chgParam of subnode is not null then plan will be re-scanned by
220  * first ExecProcNode.
221  */
222  if (subnode->chgParam == NULL)
223  ExecReScan(subnode);
224  }
225 }
void InstrStopNode(Instrumentation *instr, double nTuples)
Definition: instrument.c:80
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Instrumentation * instrument
Definition: execnodes.h:1053
PlanState ps
Definition: execnodes.h:1262
void tbm_union(TIDBitmap *a, const TIDBitmap *b)
Definition: tidbitmap.c:371
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:624
void ExecReScan(PlanState *node)
Definition: execAmi.c:73
Definition: nodes.h:508
EState * state
Definition: execnodes.h:1049
#define ERROR
Definition: elog.h:43
void InstrStartNode(Instrumentation *instr)
Definition: instrument.c:63
PlanState ** bitmapplans
Definition: execnodes.h:1263
#define EXEC_FLAG_BACKWARD
Definition: executor.h:60
void tbm_free(TIDBitmap *tbm)
Definition: tidbitmap.c:272
Bitmapset * chgParam
Definition: execnodes.h:1072
Node * MultiExecBitmapOr(BitmapOrState *node)
Definition: nodeBitmapOr.c:97
List * bitmapplans
Definition: plannodes.h:295
void * palloc0(Size size)
Definition: mcxt.c:920
int work_mem
Definition: globals.c:112
void ExecEndBitmapOr(BitmapOrState *node)
Definition: nodeBitmapOr.c:180
Plan * plan
Definition: execnodes.h:1047
void ExecReScanBitmapOr(BitmapOrState *node)
Definition: nodeBitmapOr.c:203
void UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
Definition: execUtils.c:840
#define makeNode(_type_)
Definition: nodes.h:556
BitmapOrState * ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
Definition: nodeBitmapOr.c:43
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
#define EXEC_FLAG_MARK
Definition: executor.h:61
static int list_length(const List *l)
Definition: pg_list.h:89
TIDBitmap * tbm_create(long maxbytes)
Definition: tidbitmap.c:210
Node * MultiExecProcNode(PlanState *node)
Definition: execProcnode.c:571
int i
#define elog
Definition: elog.h:219
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:137