forked from JuliaArrays/StructArrays.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathStructArraysTablesExt.jl
47 lines (39 loc) · 1.64 KB
/
StructArraysTablesExt.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
module StructArraysTablesExt
using StructArrays
using StructArrays: components, hasfields, foreachfield, staticschema
import Tables
Tables.isrowtable(::Type{<:StructArray}) = true
Tables.columnaccess(::Type{<:StructArray}) = true
Tables.columns(s::StructArray) = components(s)
Tables.schema(s::StructArray) = _schema(staticschema(eltype(s)))
_schema(::Type{NT}) where {NT<:NamedTuple} = Tables.Schema(NT)
# make schema for unnamed case
function _schema(::Type{T}) where {T<:NTuple{N, Any}} where N
return Tables.Schema{ntuple(identity, N), T}
end
function try_compatible_columns(rows::R, s::StructArray) where {R}
Tables.isrowtable(rows) && Tables.columnaccess(rows) || return nothing
T = eltype(rows)
hasfields(T) || return nothing
NT = staticschema(T)
_schema(NT) == Tables.schema(rows) || return nothing
return Tables.columntable(rows)
end
try_compatible_columns(rows::StructArray{T}, s::StructArray{T}) where {T} = Tables.columntable(rows)
try_compatible_columns(rows::StructArray{R}, s::StructArray{S}) where {R,S} = nothing
for (f, g) in zip((:append!, :prepend!), (:push!, :pushfirst!))
@eval function Base.$f(s::StructVector, rows)
table = try_compatible_columns(rows, s)
if table !== nothing
# Input `rows` is a container of rows _and_ satisfies column
# table interface. Thus, we can add the input column-by-column.
foreachfield($f, s, table)
return s
else
# Otherwise, fallback to a generic implementation expecting
# that `rows` is an iterator:
return foldl($g, rows; init = s)
end
end
end
end # module