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