* ExecShutdownNode * * Give execution nodes a chance to stop asynchronous resource consumption * and release any resources still held. */
| 1347 | * and release any resources still held. |
| 1348 | */ |
| 1349 | bool |
| 1350 | ExecShutdownNode(PlanState *node) |
| 1351 | { |
| 1352 | if (node == NULL) |
| 1353 | return false; |
| 1354 | |
| 1355 | check_stack_depth(); |
| 1356 | |
| 1357 | /* |
| 1358 | * Treat the node as running while we shut it down, but only if it's run |
| 1359 | * at least once already. We don't expect much CPU consumption during |
| 1360 | * node shutdown, but in the case of Gather or Gather Merge, we may shut |
| 1361 | * down workers at this stage. If so, their buffer usage will get |
| 1362 | * propagated into pgBufferUsage at this point, and we want to make sure |
| 1363 | * that it gets associated with the Gather node. We skip this if the node |
| 1364 | * has never been executed, so as to avoid incorrectly making it appear |
| 1365 | * that it has. |
| 1366 | */ |
| 1367 | if (node->instrument && node->instrument->running) |
| 1368 | InstrStartNode(node->instrument); |
| 1369 | |
| 1370 | planstate_tree_walker(node, ExecShutdownNode, NULL); |
| 1371 | |
| 1372 | switch (nodeTag(node)) |
| 1373 | { |
| 1374 | case T_GatherState: |
| 1375 | ExecShutdownGather((GatherState *) node); |
| 1376 | break; |
| 1377 | case T_ForeignScanState: |
| 1378 | ExecShutdownForeignScan((ForeignScanState *) node); |
| 1379 | break; |
| 1380 | case T_CustomScanState: |
| 1381 | ExecShutdownCustomScan((CustomScanState *) node); |
| 1382 | break; |
| 1383 | case T_GatherMergeState: |
| 1384 | ExecShutdownGatherMerge((GatherMergeState *) node); |
| 1385 | break; |
| 1386 | case T_HashState: |
| 1387 | ExecShutdownHash((HashState *) node); |
| 1388 | break; |
| 1389 | case T_HashJoinState: |
| 1390 | ExecShutdownHashJoin((HashJoinState *) node); |
| 1391 | break; |
| 1392 | default: |
| 1393 | break; |
| 1394 | } |
| 1395 | |
| 1396 | /* Stop the node if we started it above, reporting 0 tuples. */ |
| 1397 | if (node->instrument && node->instrument->running) |
| 1398 | InstrStopNode(node->instrument, 0); |
| 1399 | |
| 1400 | return false; |
| 1401 | } |
| 1402 | |
| 1403 | /* |
| 1404 | * ExecSetTupleBound |
no test coverage detected