Coverage Report

Created: 2025-07-03 06:49

/src/postgres/src/backend/executor/nodeBitmapAnd.c
Line
Count
Source (jump to first uncovered line)
1
/*-------------------------------------------------------------------------
2
 *
3
 * nodeBitmapAnd.c
4
 *    routines to handle BitmapAnd 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/nodeBitmapAnd.c
12
 *
13
 *-------------------------------------------------------------------------
14
 */
15
/* INTERFACE ROUTINES
16
 *    ExecInitBitmapAnd - initialize the BitmapAnd node
17
 *    MultiExecBitmapAnd  - retrieve the result bitmap from the node
18
 *    ExecEndBitmapAnd  - shut down the BitmapAnd node
19
 *    ExecReScanBitmapAnd - rescan the BitmapAnd node
20
 *
21
 *   NOTES
22
 *    BitmapAnd 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/nodeBitmapAnd.h"
33
34
35
/* ----------------------------------------------------------------
36
 *    ExecBitmapAnd
37
 *
38
 *    stub for pro forma compliance
39
 * ----------------------------------------------------------------
40
 */
41
static TupleTableSlot *
42
ExecBitmapAnd(PlanState *pstate)
43
0
{
44
0
  elog(ERROR, "BitmapAnd node does not support ExecProcNode call convention");
45
0
  return NULL;
46
0
}
47
48
/* ----------------------------------------------------------------
49
 *    ExecInitBitmapAnd
50
 *
51
 *    Begin all of the subscans of the BitmapAnd node.
52
 * ----------------------------------------------------------------
53
 */
54
BitmapAndState *
55
ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
56
0
{
57
0
  BitmapAndState *bitmapandstate = makeNode(BitmapAndState);
58
0
  PlanState **bitmapplanstates;
59
0
  int     nplans;
60
0
  int     i;
61
0
  ListCell   *l;
62
0
  Plan     *initNode;
63
64
  /* check for unsupported flags */
65
0
  Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
66
67
  /*
68
   * Set up empty vector of subplan states
69
   */
70
0
  nplans = list_length(node->bitmapplans);
71
72
0
  bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
73
74
  /*
75
   * create new BitmapAndState for our BitmapAnd node
76
   */
77
0
  bitmapandstate->ps.plan = (Plan *) node;
78
0
  bitmapandstate->ps.state = estate;
79
0
  bitmapandstate->ps.ExecProcNode = ExecBitmapAnd;
80
0
  bitmapandstate->bitmapplans = bitmapplanstates;
81
0
  bitmapandstate->nplans = nplans;
82
83
  /*
84
   * call ExecInitNode on each of the plans to be executed and save the
85
   * results into the array "bitmapplanstates".
86
   */
87
0
  i = 0;
88
0
  foreach(l, node->bitmapplans)
89
0
  {
90
0
    initNode = (Plan *) lfirst(l);
91
0
    bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
92
0
    i++;
93
0
  }
94
95
  /*
96
   * Miscellaneous initialization
97
   *
98
   * BitmapAnd plans don't have expression contexts because they never call
99
   * ExecQual or ExecProject.  They don't need any tuple slots either.
100
   */
101
102
0
  return bitmapandstate;
103
0
}
104
105
/* ----------------------------------------------------------------
106
 *     MultiExecBitmapAnd
107
 * ----------------------------------------------------------------
108
 */
109
Node *
110
MultiExecBitmapAnd(BitmapAndState *node)
111
0
{
112
0
  PlanState **bitmapplans;
113
0
  int     nplans;
114
0
  int     i;
115
0
  TIDBitmap  *result = NULL;
116
117
  /* must provide our own instrumentation support */
118
0
  if (node->ps.instrument)
119
0
    InstrStartNode(node->ps.instrument);
120
121
  /*
122
   * get information from the node
123
   */
124
0
  bitmapplans = node->bitmapplans;
125
0
  nplans = node->nplans;
126
127
  /*
128
   * Scan all the subplans and AND their result bitmaps
129
   */
130
0
  for (i = 0; i < nplans; i++)
131
0
  {
132
0
    PlanState  *subnode = bitmapplans[i];
133
0
    TIDBitmap  *subresult;
134
135
0
    subresult = (TIDBitmap *) MultiExecProcNode(subnode);
136
137
0
    if (!subresult || !IsA(subresult, TIDBitmap))
138
0
      elog(ERROR, "unrecognized result from subplan");
139
140
0
    if (result == NULL)
141
0
      result = subresult; /* first subplan */
142
0
    else
143
0
    {
144
0
      tbm_intersect(result, subresult);
145
0
      tbm_free(subresult);
146
0
    }
147
148
    /*
149
     * If at any stage we have a completely empty bitmap, we can fall out
150
     * without evaluating the remaining subplans, since ANDing them can no
151
     * longer change the result.  (Note: the fact that indxpath.c orders
152
     * the subplans by selectivity should make this case more likely to
153
     * occur.)
154
     */
155
0
    if (tbm_is_empty(result))
156
0
      break;
157
0
  }
158
159
0
  if (result == NULL)
160
0
    elog(ERROR, "BitmapAnd doesn't support zero inputs");
161
162
  /* must provide our own instrumentation support */
163
0
  if (node->ps.instrument)
164
0
    InstrStopNode(node->ps.instrument, 0 /* XXX */ );
165
166
0
  return (Node *) result;
167
0
}
168
169
/* ----------------------------------------------------------------
170
 *    ExecEndBitmapAnd
171
 *
172
 *    Shuts down the subscans of the BitmapAnd node.
173
 *
174
 *    Returns nothing of interest.
175
 * ----------------------------------------------------------------
176
 */
177
void
178
ExecEndBitmapAnd(BitmapAndState *node)
179
0
{
180
0
  PlanState **bitmapplans;
181
0
  int     nplans;
182
0
  int     i;
183
184
  /*
185
   * get information from the node
186
   */
187
0
  bitmapplans = node->bitmapplans;
188
0
  nplans = node->nplans;
189
190
  /*
191
   * shut down each of the subscans (that we've initialized)
192
   */
193
0
  for (i = 0; i < nplans; i++)
194
0
  {
195
0
    if (bitmapplans[i])
196
0
      ExecEndNode(bitmapplans[i]);
197
0
  }
198
0
}
199
200
void
201
ExecReScanBitmapAnd(BitmapAndState *node)
202
0
{
203
0
  int     i;
204
205
0
  for (i = 0; i < node->nplans; i++)
206
0
  {
207
0
    PlanState  *subnode = node->bitmapplans[i];
208
209
    /*
210
     * ExecReScan doesn't know about my subplans, so I have to do
211
     * changed-parameter signaling myself.
212
     */
213
0
    if (node->ps.chgParam != NULL)
214
0
      UpdateChangedParamSet(subnode, node->ps.chgParam);
215
216
    /*
217
     * If chgParam of subnode is not null then plan will be re-scanned by
218
     * first ExecProcNode.
219
     */
220
0
    if (subnode->chgParam == NULL)
221
0
      ExecReScan(subnode);
222
0
  }
223
0
}