---------------------------------------------------------------- * ExecMergeAppend * * Handles iteration over multiple subplans. * ---------------------------------------------------------------- */
| 212 | * ---------------------------------------------------------------- |
| 213 | */ |
| 214 | static TupleTableSlot * |
| 215 | ExecMergeAppend(PlanState *pstate) |
| 216 | { |
| 217 | MergeAppendState *node = castNode(MergeAppendState, pstate); |
| 218 | TupleTableSlot *result; |
| 219 | SlotNumber i; |
| 220 | |
| 221 | CHECK_FOR_INTERRUPTS(); |
| 222 | |
| 223 | if (!node->ms_initialized) |
| 224 | { |
| 225 | /* Nothing to do if all subplans were pruned */ |
| 226 | if (node->ms_nplans == 0) |
| 227 | return ExecClearTuple(node->ps.ps_ResultTupleSlot); |
| 228 | |
| 229 | /* |
| 230 | * If we've yet to determine the valid subplans then do so now. If |
| 231 | * run-time pruning is disabled then the valid subplans will always be |
| 232 | * set to all subplans. |
| 233 | */ |
| 234 | if (node->ms_valid_subplans == NULL) |
| 235 | { |
| 236 | MergeAppend *plan = (MergeAppend *) node->ps.plan; |
| 237 | |
| 238 | node->ms_valid_subplans = |
| 239 | ExecFindMatchingSubPlans(node->ms_prune_state, |
| 240 | node->ps.state, |
| 241 | list_length(plan->mergeplans), |
| 242 | plan->join_prune_paramids); |
| 243 | } |
| 244 | |
| 245 | /* |
| 246 | * First time through: pull the first tuple from each valid subplan, |
| 247 | * and set up the heap. |
| 248 | */ |
| 249 | i = -1; |
| 250 | while ((i = bms_next_member(node->ms_valid_subplans, i)) >= 0) |
| 251 | { |
| 252 | node->ms_slots[i] = ExecProcNode(node->mergeplans[i]); |
| 253 | if (!TupIsNull(node->ms_slots[i])) |
| 254 | binaryheap_add_unordered(node->ms_heap, Int32GetDatum(i)); |
| 255 | } |
| 256 | binaryheap_build(node->ms_heap); |
| 257 | node->ms_initialized = true; |
| 258 | } |
| 259 | else |
| 260 | { |
| 261 | /* |
| 262 | * Otherwise, pull the next tuple from whichever subplan we returned |
| 263 | * from last time, and reinsert the subplan index into the heap, |
| 264 | * because it might now compare differently against the existing |
| 265 | * elements of the heap. (We could perhaps simplify the logic a bit |
| 266 | * by doing this before returning from the prior call, but it's better |
| 267 | * to not pull tuples until necessary.) |
| 268 | */ |
| 269 | i = DatumGetInt32(binaryheap_first(node->ms_heap)); |
| 270 | node->ms_slots[i] = ExecProcNode(node->mergeplans[i]); |
| 271 | if (!TupIsNull(node->ms_slots[i])) |
nothing calls this directly
no test coverage detected