Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * nodeBitmapAnd.c
4 : : * routines to handle BitmapAnd 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/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 *
2463 andres@anarazel.de 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 *
6620 tgl@sss.pgh.pa.us 55 :CBC 50 : ExecInitBitmapAnd(BitmapAnd *node, EState *estate, int eflags)
56 : : {
6935 57 : 50 : 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 */
6620 65 [ - + ]: 50 : Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
66 : :
67 : : /*
68 : : * Set up empty vector of subplan states
69 : : */
6935 70 : 50 : nplans = list_length(node->bitmapplans);
71 : :
72 : 50 : bitmapplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
73 : :
74 : : /*
75 : : * create new BitmapAndState for our BitmapAnd node
76 : : */
77 : 50 : bitmapandstate->ps.plan = (Plan *) node;
78 : 50 : bitmapandstate->ps.state = estate;
2463 andres@anarazel.de 79 : 50 : bitmapandstate->ps.ExecProcNode = ExecBitmapAnd;
6935 tgl@sss.pgh.pa.us 80 : 50 : bitmapandstate->bitmapplans = bitmapplanstates;
81 : 50 : 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 : : */
6934 87 : 50 : i = 0;
88 [ + - + + : 150 : foreach(l, node->bitmapplans)
+ + ]
89 : : {
90 : 100 : initNode = (Plan *) lfirst(l);
6620 91 : 100 : bitmapplanstates[i] = ExecInitNode(initNode, estate, eflags);
6934 92 : 100 : 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 : :
6935 102 : 50 : return bitmapandstate;
103 : : }
104 : :
105 : : /* ----------------------------------------------------------------
106 : : * MultiExecBitmapAnd
107 : : * ----------------------------------------------------------------
108 : : */
109 : : Node *
110 : 38 : MultiExecBitmapAnd(BitmapAndState *node)
111 : : {
112 : : PlanState **bitmapplans;
113 : : int nplans;
114 : : int i;
115 : 38 : TIDBitmap *result = NULL;
116 : :
117 : : /* must provide our own instrumentation support */
118 [ - + ]: 38 : if (node->ps.instrument)
6935 tgl@sss.pgh.pa.us 119 :UBC 0 : InstrStartNode(node->ps.instrument);
120 : :
121 : : /*
122 : : * get information from the node
123 : : */
6935 tgl@sss.pgh.pa.us 124 :CBC 38 : bitmapplans = node->bitmapplans;
125 : 38 : nplans = node->nplans;
126 : :
127 : : /*
128 : : * Scan all the subplans and AND their result bitmaps
129 : : */
130 [ + + ]: 111 : for (i = 0; i < nplans; i++)
131 : : {
132 : 76 : PlanState *subnode = bitmapplans[i];
133 : : TIDBitmap *subresult;
134 : :
135 : 76 : subresult = (TIDBitmap *) MultiExecProcNode(subnode);
136 : :
137 [ + - - + ]: 76 : if (!subresult || !IsA(subresult, TIDBitmap))
6935 tgl@sss.pgh.pa.us 138 [ # # ]:UBC 0 : elog(ERROR, "unrecognized result from subplan");
139 : :
6935 tgl@sss.pgh.pa.us 140 [ + + ]:CBC 76 : if (result == NULL)
6756 bruce@momjian.us 141 : 38 : result = subresult; /* first subplan */
142 : : else
143 : : {
6935 tgl@sss.pgh.pa.us 144 : 38 : tbm_intersect(result, subresult);
145 : 38 : 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 : : */
6804 155 [ + + ]: 76 : if (tbm_is_empty(result))
156 : 3 : break;
157 : : }
158 : :
6935 159 [ - + ]: 38 : if (result == NULL)
6935 tgl@sss.pgh.pa.us 160 [ # # ]:UBC 0 : elog(ERROR, "BitmapAnd doesn't support zero inputs");
161 : :
162 : : /* must provide our own instrumentation support */
6935 tgl@sss.pgh.pa.us 163 [ - + ]:CBC 38 : if (node->ps.instrument)
6529 bruce@momjian.us 164 :UBC 0 : InstrStopNode(node->ps.instrument, 0 /* XXX */ );
165 : :
6935 tgl@sss.pgh.pa.us 166 :CBC 38 : 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 : 50 : ExecEndBitmapAnd(BitmapAndState *node)
179 : : {
180 : : PlanState **bitmapplans;
181 : : int nplans;
182 : : int i;
183 : :
184 : : /*
185 : : * get information from the node
186 : : */
187 : 50 : bitmapplans = node->bitmapplans;
188 : 50 : nplans = node->nplans;
189 : :
190 : : /*
191 : : * shut down each of the subscans (that we've initialized)
192 : : */
193 [ + + ]: 150 : for (i = 0; i < nplans; i++)
194 : : {
195 [ + - ]: 100 : if (bitmapplans[i])
196 : 100 : ExecEndNode(bitmapplans[i]);
197 : : }
198 : 50 : }
199 : :
200 : : void
5025 201 : 29 : ExecReScanBitmapAnd(BitmapAndState *node)
202 : : {
203 : : int i;
204 : :
6935 205 [ + + ]: 87 : for (i = 0; i < node->nplans; i++)
206 : : {
207 : 58 : 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 [ + + ]: 58 : 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 : : */
5025 220 [ + + ]: 58 : if (subnode->chgParam == NULL)
221 : 55 : ExecReScan(subnode);
222 : : }
6935 223 : 29 : }
|