Coverage Report

Created: 2025-06-13 06:06

/src/postgres/src/backend/executor/nodeBitmapOr.c
Line
Count
Source (jump to first uncovered line)
1
/*-------------------------------------------------------------------------
2
 *
3
 * nodeBitmapOr.c
4
 *    routines to handle BitmapOr nodes.
5
 *
6
 * Portions Copyright (c) 1996-2025, 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 *
43
ExecBitmapOr(PlanState *pstate)
44
0
{
45
0
  elog(ERROR, "BitmapOr node does not support ExecProcNode call convention");
46
0
  return NULL;
47
0
}
48
49
/* ----------------------------------------------------------------
50
 *    ExecInitBitmapOr
51
 *
52
 *    Begin all of the subscans of the BitmapOr node.
53
 * ----------------------------------------------------------------
54
 */
55
BitmapOrState *
56
ExecInitBitmapOr(BitmapOr *node, EState *estate, int eflags)
57
0
{
58
0
  BitmapOrState *bitmaporstate = makeNode(BitmapOrState);
59
0
  PlanState **bitmapplanstates;
60
0
  int     nplans;
61
0
  int     i;
62
0
  ListCell   *l;
63
0
  Plan     *initNode;
64
65
  /* check for unsupported flags */
66
0
  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
67
68
  /*
69
   * Set up empty vector of subplan states
70
   */
71
0
  nplans = list_length(node->bitmapplans);
72
73
0
  bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
74
75
  /*
76
   * create new BitmapOrState for our BitmapOr node
77
   */
78
0
  bitmaporstate->ps.plan = (Plan *) node;
79
0
  bitmaporstate->ps.state = estate;
80
0
  bitmaporstate->ps.ExecProcNode = ExecBitmapOr;
81
0
  bitmaporstate->bitmapplans = bitmapplanstates;
82
0
  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
0
  i = 0;
89
0
  foreach(l, node->bitmapplans)
90
0
  {
91
0
    initNode = (Plan *) lfirst(l);
92
0
    bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
93
0
    i++;
94
0
  }
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
0
  return bitmaporstate;
104
0
}
105
106
/* ----------------------------------------------------------------
107
 *     MultiExecBitmapOr
108
 * ----------------------------------------------------------------
109
 */
110
Node *
111
MultiExecBitmapOr(BitmapOrState *node)
112
0
{
113
0
  PlanState **bitmapplans;
114
0
  int     nplans;
115
0
  int     i;
116
0
  TIDBitmap  *result = NULL;
117
118
  /* must provide our own instrumentation support */
119
0
  if (node->ps.instrument)
120
0
    InstrStartNode(node->ps.instrument);
121
122
  /*
123
   * get information from the node
124
   */
125
0
  bitmapplans = node->bitmapplans;
126
0
  nplans = node->nplans;
127
128
  /*
129
   * Scan all the subplans and OR their result bitmaps
130
   */
131
0
  for (i = 0; i < nplans; i++)
132
0
  {
133
0
    PlanState  *subnode = bitmapplans[i];
134
0
    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
0
    if (IsA(subnode, BitmapIndexScanState))
142
0
    {
143
0
      if (result == NULL) /* first subplan */
144
0
      {
145
        /* XXX should we use less than work_mem for this? */
146
0
        result = tbm_create(work_mem * (Size) 1024,
147
0
                  ((BitmapOr *) node->ps.plan)->isshared ?
148
0
                  node->ps.state->es_query_dsa : NULL);
149
0
      }
150
151
0
      ((BitmapIndexScanState *) subnode)->biss_result = result;
152
153
0
      subresult = (TIDBitmap *) MultiExecProcNode(subnode);
154
155
0
      if (subresult != result)
156
0
        elog(ERROR, "unrecognized result from subplan");
157
0
    }
158
0
    else
159
0
    {
160
      /* standard implementation */
161
0
      subresult = (TIDBitmap *) MultiExecProcNode(subnode);
162
163
0
      if (!subresult || !IsA(subresult, TIDBitmap))
164
0
        elog(ERROR, "unrecognized result from subplan");
165
166
0
      if (result == NULL)
167
0
        result = subresult; /* first subplan */
168
0
      else
169
0
      {
170
0
        tbm_union(result, subresult);
171
0
        tbm_free(subresult);
172
0
      }
173
0
    }
174
0
  }
175
176
  /* We could return an empty result set here? */
177
0
  if (result == NULL)
178
0
    elog(ERROR, "BitmapOr doesn't support zero inputs");
179
180
  /* must provide our own instrumentation support */
181
0
  if (node->ps.instrument)
182
0
    InstrStopNode(node->ps.instrument, 0 /* XXX */ );
183
184
0
  return (Node *) result;
185
0
}
186
187
/* ----------------------------------------------------------------
188
 *    ExecEndBitmapOr
189
 *
190
 *    Shuts down the subscans of the BitmapOr node.
191
 *
192
 *    Returns nothing of interest.
193
 * ----------------------------------------------------------------
194
 */
195
void
196
ExecEndBitmapOr(BitmapOrState *node)
197
0
{
198
0
  PlanState **bitmapplans;
199
0
  int     nplans;
200
0
  int     i;
201
202
  /*
203
   * get information from the node
204
   */
205
0
  bitmapplans = node->bitmapplans;
206
0
  nplans = node->nplans;
207
208
  /*
209
   * shut down each of the subscans (that we've initialized)
210
   */
211
0
  for (i = 0; i < nplans; i++)
212
0
  {
213
0
    if (bitmapplans[i])
214
0
      ExecEndNode(bitmapplans[i]);
215
0
  }
216
0
}
217
218
void
219
ExecReScanBitmapOr(BitmapOrState *node)
220
0
{
221
0
  int     i;
222
223
0
  for (i = 0; i < node->nplans; i++)
224
0
  {
225
0
    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
0
    if (node->ps.chgParam != NULL)
232
0
      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
0
    if (subnode->chgParam == NULL)
239
0
      ExecReScan(subnode);
240
0
  }
241
0
}