1+ import Tables
2+
13Tables. isrowtable (:: Type{<:StructArray} ) = true
24
35Tables. columnaccess (:: Type{<:StructArray} ) = true
46Tables. columns (s:: StructArray ) = fieldarrays (s)
5- Tables. schema (s:: StructArray ) = Tables. Schema (staticschema (eltype (s)))
7+ Tables. schema (s:: StructArray ) = _schema (staticschema (eltype (s)))
8+
9+ _schema (:: Type{NT} ) where {NT<: NamedTuple } = Tables. Schema (NT)
10+ # make schema for unnamed case
11+ function _schema (:: Type{T} ) where {T<: NTuple{N, Any} } where N
12+ return Tables. Schema{ntuple (identity, N), T}
13+ end
14+
15+ function try_compatible_columns (rows:: R , s:: StructArray ) where {R}
16+ Tables. isrowtable (rows) && Tables. columnaccess (rows) || return nothing
17+ T = eltype (rows)
18+ hasfields (T) || return nothing
19+ NT = staticschema (T)
20+ _schema (NT) == Tables. schema (rows) || return nothing
21+ table = Tables. columns (rows)
22+ fieldnames (NT) == propertynames (table) ? table : nothing
23+ end
624
725function Base. append! (s:: StructVector , rows)
8- if Tables. isrowtable (rows) && Tables. columnaccess (rows)
26+ table = try_compatible_columns (rows, s)
27+ if table != = nothing
928 # Input `rows` is a container of rows _and_ satisfies column
1029 # table interface. Thus, we can add the input column-by-column.
11- table = Tables. columns (rows)
12- isempty (_setdiff (propertynames (s), Tables. columnnames (rows))) ||
13- _invalid_columns_error (s, rows)
1430 foreachfield (append!, s, table)
1531 return s
1632 else
@@ -19,12 +35,3 @@ function Base.append!(s::StructVector, rows)
1935 return foldl (push!, rows; init = s)
2036 end
2137end
22-
23- @noinline function _invalid_columns_error (s, rows)
24- missingnames = setdiff! (collect (Tables. columnnames (rows)), propertynames (s))
25- throw (ArgumentError (string (
26- " Cannot append rows from `$(typeof (rows)) ` to `$(typeof (s)) ` due to " ,
27- " missing column(s):\n " ,
28- join (missingnames, " , " ),
29- )))
30- end
0 commit comments