PostgreSQL Source Code  git master
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-2024, 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/executor.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 *
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  */
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  * call ExecInitNode on each of the plans to be executed and save the
86  * results into the array "bitmapplanstates".
87  */
88  i = 0;
89  foreach(l, node->bitmapplans)
90  {
91  initNode = (Plan *) lfirst(l);
92  bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
93  i++;
94  }
95 
96  /*
97  * Miscellaneous initialization
98  *
99  * BitmapOr plans don't have expression contexts because they never call
100  * ExecQual or ExecProject. They don't need any tuple slots either.
101  */
102 
103  return bitmaporstate;
104 }
105 
106 /* ----------------------------------------------------------------
107  * MultiExecBitmapOr
108  * ----------------------------------------------------------------
109  */
110 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)
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
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
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 }
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:557
Node * MultiExecProcNode(PlanState *node)
Definition: execProcnode.c:502
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:142
void UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
Definition: execUtils.c:844
#define EXEC_FLAG_BACKWARD
Definition: executor.h:68
#define EXEC_FLAG_MARK
Definition: executor.h:69
int work_mem
Definition: globals.c:128
void InstrStartNode(Instrumentation *instr)
Definition: instrument.c:68
void InstrStopNode(Instrumentation *instr, double nTuples)
Definition: instrument.c:84
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')
void * palloc0(Size size)
Definition: mcxt.c:1334
void ExecEndBitmapOr(BitmapOrState *node)
Definition: nodeBitmapOr.c:196
BitmapOrState * ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
Definition: nodeBitmapOr.c:56
Node * MultiExecBitmapOr(BitmapOrState *node)
Definition: nodeBitmapOr.c:111
void ExecReScanBitmapOr(BitmapOrState *node)
Definition: nodeBitmapOr.c:219
static TupleTableSlot * ExecBitmapOr(PlanState *pstate)
Definition: nodeBitmapOr.c:43
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define makeNode(_type_)
Definition: nodes.h:155
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
PlanState ps
Definition: execnodes.h:1530
PlanState ** bitmapplans
Definition: execnodes.h:1531
List * bitmapplans
Definition: plannodes.h:372
struct dsa_area * es_query_dsa
Definition: execnodes.h:702
Definition: nodes.h:129
Instrumentation * instrument
Definition: execnodes.h:1126
Plan * plan
Definition: execnodes.h:1116
EState * state
Definition: execnodes.h:1118
Bitmapset * chgParam
Definition: execnodes.h:1148
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:1122
void tbm_free(TIDBitmap *tbm)
Definition: tidbitmap.c:322
TIDBitmap * tbm_create(long maxbytes, dsa_area *dsa)
Definition: tidbitmap.c:266
void tbm_union(TIDBitmap *a, const TIDBitmap *b)
Definition: tidbitmap.c:458