| 401 | } |
| 402 | |
| 403 | JSONBuilder::ItemPtr QueryPlan::explainPlan(const ExplainPlanOptions & options) |
| 404 | { |
| 405 | checkInitialized(); |
| 406 | |
| 407 | struct Frame |
| 408 | { |
| 409 | Node * node = {}; |
| 410 | size_t next_child = 0; |
| 411 | std::unique_ptr<JSONBuilder::JSONMap> node_map = {}; |
| 412 | std::unique_ptr<JSONBuilder::JSONArray> children_array = {}; |
| 413 | }; |
| 414 | |
| 415 | std::stack<Frame> stack; |
| 416 | stack.push(Frame{.node = root}); |
| 417 | |
| 418 | std::unique_ptr<JSONBuilder::JSONMap> tree; |
| 419 | |
| 420 | while (!stack.empty()) |
| 421 | { |
| 422 | auto & frame = stack.top(); |
| 423 | |
| 424 | if (frame.next_child == 0) |
| 425 | { |
| 426 | if (!frame.node->children.empty()) |
| 427 | frame.children_array = std::make_unique<JSONBuilder::JSONArray>(); |
| 428 | |
| 429 | frame.node_map = std::make_unique<JSONBuilder::JSONMap>(); |
| 430 | explainStep(*frame.node->step, *frame.node_map, options); |
| 431 | } |
| 432 | |
| 433 | if (frame.next_child < frame.node->children.size()) |
| 434 | { |
| 435 | stack.push(Frame{frame.node->children[frame.next_child]}); |
| 436 | ++frame.next_child; |
| 437 | } |
| 438 | else |
| 439 | { |
| 440 | if (frame.children_array) |
| 441 | frame.node_map->add("Plans", std::move(frame.children_array)); |
| 442 | |
| 443 | tree.swap(frame.node_map); |
| 444 | stack.pop(); |
| 445 | |
| 446 | if (!stack.empty()) |
| 447 | stack.top().children_array->add(std::move(tree)); |
| 448 | } |
| 449 | } |
| 450 | |
| 451 | return tree; |
| 452 | } |
| 453 | |
| 454 | static void |
| 455 | explainStep(const IQueryPlanStep & step, IQueryPlanStep::FormatSettings & settings, const QueryPlan::ExplainPlanOptions & options) |
no test coverage detected