Skip to content

Commit eeabf84

Browse files
committed
feat: add error handling for non-compliant GeoArrow structs in ddbs_open_dataset
1 parent 72d5dfe commit eeabf84

2 files changed

Lines changed: 36 additions & 4 deletions

File tree

R/io_open_dataset.R

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,11 @@ ddbs_open_dataset <- function(path,
195195
scan_query <- glue::glue("read_parquet('{path}'{p_args_str})")
196196

197197
# Resolve geometry column
198+
try_cols <- tryCatch({
199+
DBI::dbGetQuery(conn, glue::glue("DESCRIBE SELECT * FROM {scan_query}"))
200+
}, error = function(e) NULL)
201+
198202
if (is.null(geom_col)) {
199-
try_cols <- tryCatch({
200-
DBI::dbGetQuery(conn, glue::glue("DESCRIBE SELECT * FROM {scan_query}"))
201-
}, error = function(e) NULL)
202-
203203
if (!is.null(try_cols)) {
204204
possibles <- c("geometry", "geom", "wkb_geometry")
205205
found <- try_cols$column_name[try_cols$column_name %in% possibles]
@@ -208,6 +208,22 @@ ddbs_open_dataset <- function(path,
208208
geom_col <- NULL
209209
}
210210
}
211+
212+
# Intercept GeoArrow structs (native Arrow encoding) which DuckDB cannot parse
213+
if (!is.null(geom_col) && !is.null(try_cols)) {
214+
col_type <- try_cols$column_type[try_cols$column_name == geom_col]
215+
if (length(col_type) > 0 && grepl("STRUCT", toupper(col_type[1]))) {
216+
cli::cli_abort(c(
217+
"The geometry column {.val {geom_col}} is encoded as a native Arrow Struct, which is not supported by DuckDB's spatial extension.",
218+
"x" = "DuckDB requires standard GeoParquet 1.1 with WKB (Well-Known Binary) encoding.",
219+
"i" = "To fix this, please resave the file using:",
220+
" " = " {.code duckspatial::ddbs_write_dataset(data, path)}",
221+
" " = " # OR if using geoarrow:",
222+
" " = " {.code data${geom_col} <- geoarrow::as_geoarrow_vctr(data${geom_col}, schema = geoarrow::geoarrow_wkb())}",
223+
" " = " {.code arrow::write_parquet(data, path)}"
224+
))
225+
}
226+
}
211227

212228
view_query <- create_temp_table(
213229
name = view_name,

tests/testthat/test-ddbs_open_dataset.R

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,3 +265,19 @@ test_that("ddbs_open_dataset handles missing file gracefully", {
265265
ignore.case = TRUE
266266
)
267267
})
268+
269+
test_that("ddbs_open_dataset fails gracefully on non-compliant GeoArrow structs", {
270+
skip_if_not_installed("arrow")
271+
skip_if_not_installed("geoarrow")
272+
273+
# Create a file with Arrow native encoding (NOT WKB) using direct write_parquet
274+
# This triggers the GeoArrow native struct encoding
275+
tmp_bad <- tempfile(fileext = ".parquet")
276+
on.exit(unlink(tmp_bad))
277+
arrow::write_parquet(countries_sf, tmp_bad)
278+
279+
expect_error(
280+
ddbs_open_dataset(tmp_bad),
281+
"encoded as a native Arrow Struct"
282+
)
283+
})

0 commit comments

Comments
 (0)