1515@inline _to_table_key (key:: Symbol ) = key
1616@inline _to_table_key (key) = Symbol (key)
1717
18+ @inline _to_table_vars (vars:: Nothing ) = nothing
19+ @inline _to_table_vars (var:: Symbol ) = Symbol[var]
20+ @inline _to_table_vars (var:: AbstractString ) = Symbol[Symbol (var)]
21+ @inline function _to_table_vars (vars:: Union{Tuple,AbstractVector} )
22+ out = Vector {Symbol} (undef, length (vars))
23+ @inbounds for i in eachindex (vars)
24+ out[i] = _to_table_key (vars[i])
25+ end
26+ out
27+ end
28+
1829@inline function _table_attr_type_from_store (store:: MTGAttributeStore , key:: Symbol )
1930 has_any = false
2031 has_missing = false
@@ -109,33 +120,56 @@ end
109120end
110121
111122"""
112- symbol_table(mtg::Node, symbol)
123+ symbol_table(mtg::Node, symbol, vars=nothing )
113124
114125Return a per-symbol column table view (Tables.jl-compatible).
126+ If `vars` is provided (`Symbol`/`String`/vector/tuple), only these attributes are included.
115127"""
116- function symbol_table (mtg:: Node , symbol)
128+ function symbol_table (mtg:: Node , symbol, vars = nothing )
117129 symbol_ = _to_table_key (symbol)
130+ vars_ = _to_table_vars (vars)
118131 attrs = node_attributes (get_root (mtg))
119132 if attrs isa ColumnarAttrs
120133 store = _store_for_node_attrs (attrs)
121134 if store != = nothing
122135 bid = get (store. symbol_to_bucket, symbol_, 0 )
123136 if bid == 0
124- return ColumnTable (Symbol[:node_id ], AbstractVector[Int[]])
137+ names_ = Symbol[:node_id ]
138+ cols_ = AbstractVector[Int[]]
139+ if vars_ != = nothing
140+ for key in vars_
141+ push! (names_, key)
142+ push! (cols_, Missing[])
143+ end
144+ end
145+ return ColumnTable (names_, cols_)
125146 end
126147 bucket = store. buckets[bid]
127148 names_ = Symbol[:node_id ]
128149 cols_ = AbstractVector[bucket. row_to_node]
129- for col in bucket. columns
130- push! (names_, col. name)
131- push! (cols_, col. data)
150+ if vars_ === nothing
151+ for col in bucket. columns
152+ push! (names_, col. name)
153+ push! (cols_, col. data)
154+ end
155+ else
156+ for key in vars_
157+ col_idx = get (bucket. col_index, key, 0 )
158+ push! (names_, key)
159+ if col_idx == 0
160+ push! (cols_, fill (missing , length (bucket. row_to_node)))
161+ else
162+ push! (cols_, bucket. columns[col_idx]. data)
163+ end
164+ end
132165 end
133166 return ColumnTable (names_, cols_)
134167 end
135168 end
136169
137170 nodes = traverse (mtg, node -> node, symbol= symbol_, type= typeof (mtg))
138171 attr_names = _collect_attr_names_from_nodes (nodes)
172+ attr_names = vars_ === nothing ? attr_names : vars_
139173 attr_cols = _build_attr_columns (nodes, attr_names)
140174
141175 names_ = Symbol[:node_id ]
@@ -148,13 +182,15 @@ function symbol_table(mtg::Node, symbol)
148182end
149183
150184"""
151- mtg_table(mtg::Node)
185+ mtg_table(mtg::Node, vars=nothing )
152186
153187Return a unified traversal-ordered table view of an MTG (Tables.jl-compatible).
154188Absent attributes are represented as `missing`.
189+ If `vars` is provided (`Symbol`/`String`/vector/tuple), only these attributes are included.
155190"""
156- function mtg_table (mtg:: Node )
191+ function mtg_table (mtg:: Node , vars = nothing )
157192 nodes = traverse (mtg, node -> node, type= typeof (mtg))
193+ vars_ = _to_table_vars (vars)
158194
159195 names_ = Symbol[:node_id , :symbol , :scale , :index , :link , :parent_id ]
160196 cols_ = AbstractVector[
@@ -170,7 +206,7 @@ function mtg_table(mtg::Node)
170206 if attrs isa ColumnarAttrs
171207 store = _store_for_node_attrs (attrs)
172208 if store != = nothing
173- attr_names = _collect_attr_names_from_store (store)
209+ attr_names = vars_ === nothing ? _collect_attr_names_from_store (store) : vars_
174210 for key in attr_names
175211 push! (names_, key)
176212 T = _table_attr_type_from_store (store, key)
@@ -181,6 +217,7 @@ function mtg_table(mtg::Node)
181217 end
182218
183219 attr_names = _collect_attr_names_from_nodes (nodes)
220+ attr_names = vars_ === nothing ? attr_names : vars_
184221 attr_cols = _build_attr_columns (nodes, attr_names)
185222 @inbounds for i in eachindex (attr_names)
186223 push! (names_, attr_names[i])
@@ -191,14 +228,15 @@ function mtg_table(mtg::Node)
191228end
192229
193230"""
194- to_table(mtg::Node; symbol=nothing)
231+ to_table(mtg::Node; symbol=nothing, vars=nothing )
195232
196233Convenience helper to get a Tables.jl-compatible view from an MTG.
197234- `symbol=nothing`: unified traversal-ordered table (`mtg_table`)
198235- `symbol=<symbol>`: per-symbol table (`symbol_table`)
236+ - `vars`: optional attribute selection (`Symbol`/`String`/vector/tuple)
199237"""
200- function to_table (mtg:: Node ; symbol= nothing )
201- symbol === nothing ? mtg_table (mtg) : symbol_table (mtg, symbol)
238+ function to_table (mtg:: Node ; symbol= nothing , vars = nothing )
239+ symbol === nothing ? mtg_table (mtg, vars ) : symbol_table (mtg, symbol, vars )
202240end
203241
204242Tables. istable (:: Type{<:Node} ) = true
0 commit comments