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
2 changes: 1 addition & 1 deletion r/R/as-array.R
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ as_nanoarrow_array.list <- function(x, ..., schema = NULL) {

array <- nanoarrow_array_init(schema)

child <- unlist(x, recursive = FALSE, use.names = FALSE)
child <- do.call(c, x)
if (is.null(child)) {
child_array <- as_nanoarrow_array.vctrs_unspecified(logical(), schema = na_na())
} else {
Expand Down
2 changes: 1 addition & 1 deletion r/src/materialize_int64.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ static inline int nanoarrow_materialize_int64(struct ArrayViewSlice* src,
break;
case NANOARROW_TYPE_INT64:
memcpy(result + dst->offset,
src->array_view->buffer_views[1].data.as_int32 + raw_src_offset,
src->array_view->buffer_views[1].data.as_int64 + raw_src_offset,
dst->length * sizeof(int64_t));

// Set any nulls to NA_INTEGER64
Expand Down
23 changes: 23 additions & 0 deletions r/tests/testthat/test-as-array.R
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,29 @@ test_that("as_nanoarrow_array() works for list(integer()) -> na_list(na_int32())
expect_identical(array$children[[1]]$length, 10L)
})

test_that("as_nanoarrow_array() works for list(integer64()) -> na_list(na_int64())", {
# GH932: unlist() silently strips the integer64 class from list elements,
# reinterpreting the underlying int64 bit pattern as a double and corrupting
# values before the child array is even built.
skip_if_not_installed("bit64")

big <- bit64::as.integer64(c("9223372036854775295", "2"))
x <- list(big, bit64::as.integer64("3"))
array <- as_nanoarrow_array(x, schema = na_list(na_int64()))

expect_identical(infer_nanoarrow_schema(array)$format, "+l")
expect_identical(array$length, 2L)
expect_identical(array$null_count, 0L)
expect_identical(infer_nanoarrow_schema(array$children[[1]])$format, "l")
expect_identical(array$children[[1]]$length, 3L)

to <- vctrs::new_list_of(list(), ptype = bit64::integer64())
expect_identical(
convert_array(array, to),
vctrs::new_list_of(list(big, bit64::as.integer64("3")), ptype = bit64::integer64())
)
})

test_that("as_nanoarrow_array() works for unspecified() -> na_na()", {
skip_if_not_installed("vctrs")

Expand Down
18 changes: 18 additions & 0 deletions r/tests/testthat/test-convert-array.R
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,24 @@ test_that("convert to vector works for valid integer64()", {
)
})

test_that("convert to vector works for int64 with a nonzero offset", {
# GH932: the int64 materializer read from buffer_views[1].data.as_int32
# (i.e., with int32-sized pointer arithmetic) instead of as_int64, so any
# slice with a nonzero starting offset (e.g., a list child sliced per-row)
# read from the wrong memory location.
skip_if_not_installed("bit64")

vals <- bit64::as.integer64(c("9223372036854775295", "2", "3"))
array <- as_nanoarrow_array(vals, schema = na_int64())

sliced <- nanoarrow_array_modify(array, list(offset = 1L, length = 2L))

expect_identical(
convert_array(sliced, bit64::integer64()),
vals[2:3]
)
})

test_that("convert to vector works for null -> integer64()", {
skip_if_not_installed("bit64")

Expand Down
Loading