Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * nodeBitmapAnd.c
4 : * routines to handle BitmapAnd nodes.
5 : *
6 : * Portions Copyright (c) 1996-2023, 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/execdebug.h"
32 : #include "executor/nodeBitmapAnd.h"
33 :
34 :
35 : /* ----------------------------------------------------------------
36 : * ExecBitmapAnd
37 : *
38 : * stub for pro forma compliance
39 : * ----------------------------------------------------------------
40 : */
41 : static TupleTableSlot *
2092 andres 42 UBC 0 : ExecBitmapAnd(PlanState *pstate)
43 : {
44 0 : elog(ERROR, "BitmapAnd node does not support ExecProcNode call convention");
45 : return NULL;
46 : }
47 :
48 : /* ----------------------------------------------------------------
49 : * ExecInitBitmapAnd
50 : *
51 : * Begin all of the subscans of the BitmapAnd node.
52 : * ----------------------------------------------------------------
53 : */
54 : BitmapAndState *
6249 tgl 55 CBC 38 : ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
56 : {
6564 57 38 : BitmapAndState *bitmapandstate = makeNode(BitmapAndState);
58 : PlanState **bitmapplanstates;
59 : int nplans;
60 : int i;
61 : ListCell *l;
62 : Plan *initNode;
63 :
64 : /* check for unsupported flags */
6249 65 38 : Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
66 :
67 : /*
68 : * Set up empty vector of subplan states
69 : */
6564 70 38 : nplans = list_length(node->bitmapplans);
71 :
72 38 : bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
73 :
74 : /*
75 : * create new BitmapAndState for our BitmapAnd node
76 : */
77 38 : bitmapandstate->ps.plan = (Plan *) node;
78 38 : bitmapandstate->ps.state = estate;
2092 andres 79 38 : bitmapandstate->ps.ExecProcNode = ExecBitmapAnd;
6564 tgl 80 38 : bitmapandstate->bitmapplans = bitmapplanstates;
81 38 : 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 : */
6563 87 38 : i = 0;
88 114 : foreach(l, node->bitmapplans)
89 : {
90 76 : initNode = (Plan *) lfirst(l);
6249 91 76 : bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
6563 92 76 : i++;
93 : }
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 :
6564 102 38 : return bitmapandstate;
103 : }
104 :
105 : /* ----------------------------------------------------------------
106 : * MultiExecBitmapAnd
107 : * ----------------------------------------------------------------
108 : */
109 : Node *
110 26 : MultiExecBitmapAnd(BitmapAndState *node)
111 : {
112 : PlanState **bitmapplans;
113 : int nplans;
114 : int i;
115 26 : TIDBitmap *result = NULL;
116 :
117 : /* must provide our own instrumentation support */
118 26 : if (node->ps.instrument)
6564 tgl 119 UBC 0 : InstrStartNode(node->ps.instrument);
120 :
121 : /*
122 : * get information from the node
123 : */
6564 tgl 124 CBC 26 : bitmapplans = node->bitmapplans;
125 26 : nplans = node->nplans;
126 :
127 : /*
128 : * Scan all the subplans and AND their result bitmaps
129 : */
130 75 : for (i = 0; i < nplans; i++)
131 : {
132 52 : PlanState *subnode = bitmapplans[i];
133 : TIDBitmap *subresult;
134 :
135 52 : subresult = (TIDBitmap *) MultiExecProcNode(subnode);
136 :
137 52 : if (!subresult || !IsA(subresult, TIDBitmap))
6564 tgl 138 UBC 0 : elog(ERROR, "unrecognized result from subplan");
139 :
6564 tgl 140 CBC 52 : if (result == NULL)
6385 bruce 141 26 : result = subresult; /* first subplan */
142 : else
143 : {
6564 tgl 144 26 : tbm_intersect(result, subresult);
145 26 : tbm_free(subresult);
146 : }
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 : */
6433 155 52 : if (tbm_is_empty(result))
156 3 : break;
157 : }
158 :
6564 159 26 : if (result == NULL)
6564 tgl 160 UBC 0 : elog(ERROR, "BitmapAnd doesn't support zero inputs");
161 :
162 : /* must provide our own instrumentation support */
6564 tgl 163 CBC 26 : if (node->ps.instrument)
6158 bruce 164 UBC 0 : InstrStopNode(node->ps.instrument, 0 /* XXX */ );
165 :
6564 tgl 166 CBC 26 : return (Node *) result;
167 : }
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 38 : ExecEndBitmapAnd(BitmapAndState *node)
179 : {
180 : PlanState **bitmapplans;
181 : int nplans;
182 : int i;
183 :
184 : /*
185 : * get information from the node
186 : */
187 38 : bitmapplans = node->bitmapplans;
188 38 : nplans = node->nplans;
189 :
190 : /*
191 : * shut down each of the subscans (that we've initialized)
192 : */
193 114 : for (i = 0; i < nplans; i++)
194 : {
195 76 : if (bitmapplans[i])
196 76 : ExecEndNode(bitmapplans[i]);
197 : }
198 38 : }
199 :
200 : void
4654 201 17 : ExecReScanBitmapAnd(BitmapAndState *node)
202 : {
203 : int i;
204 :
6564 205 51 : for (i = 0; i < node->nplans; i++)
206 : {
207 34 : 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 34 : if (node->ps.chgParam != NULL)
214 6 : 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 : */
4654 220 34 : if (subnode->chgParam == NULL)
221 31 : ExecReScan(subnode);
222 : }
6564 223 17 : }
|