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