Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions src/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,27 @@ function read(driver::ArchGDALDriver, fn::AbstractString; layer = nothing, kwarg
end

function read(::ArchGDALDriver, ds, layer)
df, gnames, sr = AG.getlayer(ds, layer) do table
df, gnames, sr, metadata = AG.getlayer(ds, layer) do table
if table.ptr == C_NULL
throw(
ArgumentError(
"Given layer id/name doesn't exist. For reference this is the dataset:\n$ds",
),
)
end
domains = AG.GDAL.gdalgetmetadatadomainlist(table.ptr)
metadata = Dict{String, Any}()
for domain in domains
if domain == ""
merge!(metadata, dictstring(AG.GDAL.gdalgetmetadata(table.ptr, domain)))
else
metadata[domain] = dictstring(AG.GDAL.gdalgetmetadata(table.ptr, domain))
end
end
names, x = AG.schema_names(AG.layerdefn(table))
sr = AG.getspatialref(table)
return DataFrame(table), names, sr
df = DataFrame(table)
return df, names, sr, metadata
end
if "" in names(df)
rename!(df, Symbol("") => :geometry)
Expand All @@ -115,6 +125,10 @@ function read(::ArchGDALDriver, ds, layer)
end
crs = sr.ptr == C_NULL ? nothing : GFT.WellKnownText(GFT.CRS(), AG.toWKT(sr))
geometrycolumns = Tuple(gnames)

for (k, v) in pairs(metadata)
DataAPI.metadata!(df, k, v, style = :note)
end
metadata!(df, "crs", crs; style = :note)
metadata!(df, "geometrycolumns", geometrycolumns; style = :note)

Expand Down Expand Up @@ -270,6 +284,10 @@ function write(
push!(fieldindices, AG.findfieldindex(layer, name, false))
end

if DataAPI.metadatasupport(typeof(table)).read
setmetadatalayer!(layer, table)
end

for chunk in Iterators.partition(rows, chunksize)
can_use_transaction &&
AG.GDAL.gdaldatasetstarttransaction(ds.ptr, false)
Expand Down Expand Up @@ -308,12 +326,15 @@ function write(
end
if !can_create_layer
@warn "Can't create layers in this format, copying from memory instead."
AG.copy(
nlayer = AG.copy(
layer;
dataset = ds,
name = layer_name,
options = stringlist(options),
)
if DataAPI.metadatasupport(typeof(table)).read
setmetadatalayer!(nlayer, table)
end
end
end
end
Expand Down
32 changes: 32 additions & 0 deletions src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,38 @@ function stringlist(dict::Dict{String, String})
return sv
end

function dictstring(sv::Vector{String})
dict = Dict{String, String}()
for s in sv
kv = split(s, '=', limit=2)
if length(kv) == 2
dict[kv[1]] = kv[2]
else
@warn "Ignoring key-value metadata string: $s"
end
end
return dict
end

function setmetadatalayer!(layer, table)
for (k, v) in DataAPI.metadata(table)
if v isa Dict
for (dk, dv) in pairs(v)
@debug "Writing metadata item $dk = $dv for domain $k"
AG.GDAL.gdalsetmetadataitem(
layer.ptr,
string(dk),
string(dv),
string(k),
)
end
else
@debug "Writing metadata item $k = $v for domain ''"
AG.GDAL.gdalsetmetadataitem(layer.ptr, string(k), string(v), "")
end
end
end

function getgeometrycolumns(table)
if GI.isfeaturecollection(table)
return GI.geometrycolumns(table)
Expand Down
16 changes: 16 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ end
t = GDF.read(fn)
@test nrow(t) == 42
@test "ID" in names(t)

@test DataAPI.metadata(t)["DBF_DATE_LAST_UPDATE"] == "2007-08-16"
@test DataAPI.metadata(t)["SHAPEFILE"] isa Dict
end

@testitem "Read non-existent shapefile" setup = [Setup] begin
Expand Down Expand Up @@ -466,6 +469,19 @@ end
@test length(df2.geometry) == 5
end

@testitem "Metadata" setup = [Setup] begin
df = DataFrame(a=1, geometry=[(1.,2.)])
DataAPI.metadata!(df, "author", "test")
DataAPI.colmetadata!(df, :a, "description", "A normal column")
DataAPI.colmetadata!(df, :geometry, "description", "A point geometry")
GeoDataFrames.write("metadata.gpkg", df)
dfn = GeoDataFrames.read("metadata.gpkg")
@test DataAPI.metadata(dfn)["author"] == "test"
# Column metadata is not supported by GDAL
@test isnothing(get(DataAPI.colmetadata(dfn), :a, nothing))
@test isnothing(get(DataAPI.colmetadata(dfn), :geometry, nothing))
end

filter(ti) = !(:nowindows in ti.tags && Sys.iswindows())

@run_package_tests filter = filter
Loading