Skip to content

fix: return native GeoArrow layouts - #150

Open
e-kotov wants to merge 4 commits into
Cidree:devfrom
e-kotov:fix/native-geoarrow-stream
Open

e-kotov wants to merge 4 commits into
Cidree:devfrom
e-kotov:fix/native-geoarrow-stream

Conversation

@e-kotov

@e-kotov e-kotov commented Sep 12, 2026

Copy link
Copy Markdown
Collaborator

Related to #121.

Summary

  • Fix nanoarrow::as_nanoarrow_array_stream(..., native = TRUE) so WKB geometry is converted to native GeoArrow layouts instead of remaining geoarrow.wkb.
  • Infer compatible point, line, or polygon geometry families and promote mixed single/multi inputs to the corresponding multi layout.
  • Replace the permissive metadata test with exact assertions for geoarrow.point, geoarrow.linestring, and geoarrow.multipolygon.
  • Document the previous behavior and its origin in futureproofing for arrow/geoarrow support #121.

Verification

  • Rscript -e 'devtools::test(filter = "^nanoarrow_methods$")': 17 passed.\n- Rscript -e 'devtools::test()': 3,033 passed, 0 failed, 3 skipped.

@e-kotov
e-kotov marked this pull request as ready for review September 12, 2026 13:30
@e-kotov
e-kotov requested a review from Cidree September 12, 2026 13:31
@e-kotov

e-kotov commented Sep 12, 2026

Copy link
Copy Markdown
Collaborator Author

Hi @Cidree ! This is a quick fix to further improve compatibility with https://github.com/r-spatial/geoarrowDeckglLayers and https://github.com/r-spatial/geoarrowWidget

cc @tim-salabim, PR to geoarrowDeckglLayers soon too

@tim-salabim

Copy link
Copy Markdown

r-spatial/deckglgeoarrow#19 merged.

`as_nanoarrow_array_stream(native = TRUE)` rebuilt the result with
`as.list(tab)` and `arrow::record_batch()`. `as.list()` on an Arrow table
converts every column to an R vector, and rebuilding from those re-infers
the types, so a DuckDB BIGINT came back as int32 whenever its values
happened to fit in 32 bits:

  largest id value   source    emitted
  1,000              BIGINT    int32
  2,000,001,000      BIGINT    int32
  3,000,001,000      BIGINT    int64

The emitted schema therefore depended on the data rather than the table:
the same query over different rows could produce a different column type.
Consumers that key on the schema (browser code, caches, tests) could see
a column change type for no visible reason.

Replace only the geometry column and keep every other column as an Arrow
array, which also removes an unnecessary Arrow -> R -> Arrow round trip
for all non-geometry columns.

Verified unchanged for inputs without int64 columns: the nc fixture emits
an identical schema, the same geoarrow.multipolygon extension and the same
1924-character CRS metadata before and after.

Adds a regression test that fails before this change and passes after.
Full suite: exit 0, no failures, no new warnings.
`native = TRUE` combined the WKB column into a single Arrow array with
`as_arrow_array()` while every other column kept the chunk layout Arrow
produced when fetching (1e6 rows per chunk). Each record batch after the
first therefore held a geometry child that was a slice with a nonzero
offset, and the Arrow IPC writer rejects those:

  ArrowIpcWriterWriteArrayStream() failed: Cannot encode arrays with
  nonzero offset

So any result over one chunk could not be serialised to Arrow IPC at all:

  rows        before      after
  10,000      ok          ok
  500,000     ok          ok
  2,000,000   IPC error   ok
  5,000,000   IPC error   ok (120,626,848 bytes)

Convert the WKB column one chunk at a time and rebuild it as a
ChunkedArray, so its chunk boundaries match the other columns and every
batch starts at offset 0.

Adds a regression test (skipped on CRAN, 2e6 rows) that fails before this
change with the error above and passes after. Full suite: exit 0, no
failures, no new warnings.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants