| 1100 | } |
| 1101 | |
| 1102 | void QueryPlan::cloneInplace(Node * node_to_replace, Node * subplan_root) |
| 1103 | { |
| 1104 | if (!subplan_root) |
| 1105 | throw Exception(ErrorCodes::LOGICAL_ERROR, "Cannot clone subplan in place because subplan root is null"); |
| 1106 | |
| 1107 | struct Frame |
| 1108 | { |
| 1109 | Node * node; |
| 1110 | Node * clone; |
| 1111 | std::vector<Node *> children = {}; |
| 1112 | }; |
| 1113 | |
| 1114 | std::vector<Frame> nodes_to_process{ Frame{ .node = subplan_root, .clone = node_to_replace } }; |
| 1115 | |
| 1116 | while (!nodes_to_process.empty()) |
| 1117 | { |
| 1118 | auto & frame = nodes_to_process.back(); |
| 1119 | if (frame.children.size() == frame.node->children.size()) |
| 1120 | { |
| 1121 | frame.clone->step = frame.node->step->clone(); |
| 1122 | frame.clone->children = std::move(frame.children); |
| 1123 | nodes_to_process.pop_back(); |
| 1124 | } |
| 1125 | else |
| 1126 | { |
| 1127 | size_t next_child = frame.children.size(); |
| 1128 | auto * child = frame.node->children[next_child]; |
| 1129 | |
| 1130 | nodes.emplace_back(Node{ .step = {} }); |
| 1131 | nodes.back().children.reserve(child->children.size()); |
| 1132 | auto * child_clone = &nodes.back(); |
| 1133 | |
| 1134 | frame.children.push_back(child_clone); |
| 1135 | |
| 1136 | nodes_to_process.push_back(Frame{ .node = child, .clone = child_clone }); |
| 1137 | } |
| 1138 | } |
| 1139 | } |
| 1140 | |
| 1141 | QueryPlan QueryPlan::clone() const |
| 1142 | { |