|
83 | 83 | return _store_for_node_attrs(attrs) |
84 | 84 | end |
85 | 85 |
|
| 86 | +function _subtree_has_node_id_conflict(node::Node, store::MTGAttributeStore) |
| 87 | + nid = node_id(node) |
| 88 | + if nid <= length(store.node_bucket) && store.node_bucket[nid] != 0 |
| 89 | + return true |
| 90 | + end |
| 91 | + for ch in children(node) |
| 92 | + _subtree_has_node_id_conflict(ch, store) && return true |
| 93 | + end |
| 94 | + return false |
| 95 | +end |
| 96 | + |
| 97 | +function _merge_columnar_subtree_into_store!(node::Node, target_store::MTGAttributeStore) |
| 98 | + attrs = node_attributes(node) |
| 99 | + attrs isa ColumnarAttrs || return false |
| 100 | + snapshot = Dict{Symbol,Any}(pairs(attrs)) |
| 101 | + _add_node_with_attrs!(target_store, node_id(node), symbol(node), snapshot) |
| 102 | + attrs.ref.store = target_store |
| 103 | + attrs.ref.node_id = node_id(node) |
| 104 | + empty!(attrs.staged) |
| 105 | + for ch in children(node) |
| 106 | + _merge_columnar_subtree_into_store!(ch, target_store) || return false |
| 107 | + end |
| 108 | + return true |
| 109 | +end |
| 110 | + |
| 111 | +function _try_merge_root_subtree_store!(child::Node, parent_store::MTGAttributeStore, child_store::MTGAttributeStore) |
| 112 | + parent_store === child_store && return true |
| 113 | + _subtree_has_node_id_conflict(child, parent_store) && return false |
| 114 | + return _merge_columnar_subtree_into_store!(child, parent_store) |
| 115 | +end |
| 116 | + |
86 | 117 | @inline function _maybe_recolumnarize_after_attach!(p::Node, child::Node, child_was_root::Bool) |
87 | 118 | child_was_root || return nothing |
88 | 119 | p_store = _columnar_store_or_nothing(p) |
89 | 120 | c_store = _columnar_store_or_nothing(child) |
90 | 121 | if p_store !== nothing && c_store !== nothing && p_store !== c_store |
91 | | - columnarize!(get_root(p)) |
| 122 | + # Fast path: re-bind only the attached subtree into the parent store. |
| 123 | + # Fallback to full re-columnarization when IDs collide. |
| 124 | + _try_merge_root_subtree_store!(child, p_store, c_store) || columnarize!(get_root(p)) |
92 | 125 | end |
93 | 126 | return nothing |
94 | 127 | end |
|
0 commit comments