diff --git a/apis/python/src/tiledbsoma/_dense_nd_array.py b/apis/python/src/tiledbsoma/_dense_nd_array.py index 35c1f4fa77..7a841386b0 100644 --- a/apis/python/src/tiledbsoma/_dense_nd_array.py +++ b/apis/python/src/tiledbsoma/_dense_nd_array.py @@ -258,7 +258,20 @@ def read( timestamp=handle.timestamp and (0, handle.timestamp), ) - # TODO: more on #2407, including the slotwise-none case + # Scenario to avoid: + # * Query dense array with coords not provided + # * When coords not provided, core uses the core domain + # For old shape: + # * Core current domain did not exist + # * Core max domain may be small; .shape returns this + # For new shape (core 2.27 and tiledbsoma 1.15): + # * Core current domain exists and will be small; .shape returns this + # * Core max domain will be huge + # In either case, applying these coords is the right thing to do + # + # TODO: more on #2407, including the case where the coords + # is not the empty tuple but has None or slice-of-None + # in one or more slots if coords == (): coords = tuple(slice(0, e - 1) for e in data_shape) diff --git a/apis/python/tests/test_dense_nd_array.py b/apis/python/tests/test_dense_nd_array.py index 87b7c29415..942dd6e24d 100644 --- a/apis/python/tests/test_dense_nd_array.py +++ b/apis/python/tests/test_dense_nd_array.py @@ -9,6 +9,7 @@ import pytest import tiledbsoma as soma +import tiledbsoma.pytiledbsoma as clib from tiledbsoma.options import SOMATileDBContext from . import NDARRAY_ARROW_TYPES_NOT_SUPPORTED, NDARRAY_ARROW_TYPES_SUPPORTED @@ -180,8 +181,13 @@ def test_dense_nd_array_requires_shape(tmp_path, shape_is_numeric): with soma.DenseNDArray.open(uri) as dnda: assert dnda.shape == (2, 3) else: - with pytest.raises(ValueError): - soma.DenseNDArray.create(uri, type=pa.float32(), shape=(None, None)).close() + soma.DenseNDArray.create(uri, type=pa.float32(), shape=(None, None)).close() + with soma.DenseNDArray.open(uri) as dnda: + if ( + soma._flags.NEW_SHAPE_FEATURE_FLAG_ENABLED + and clib.embedded_version_triple() >= (2, 27, 0) + ): + assert dnda.shape == (1, 1) def test_dense_nd_array_ned_write(tmp_path): diff --git a/apis/r/R/SOMADataFrame.R b/apis/r/R/SOMADataFrame.R index de778fc56f..04b9fa518b 100644 --- a/apis/r/R/SOMADataFrame.R +++ b/apis/r/R/SOMADataFrame.R @@ -148,6 +148,7 @@ SOMADataFrame <- R6::R6Class( uri = self$uri, naap = naap, nasp = nasp, + coords_list = list(), # only used for SOMADenseNDArray ctxxp = private$.soma_context, arraytype = "SOMADataFrame", config = NULL, diff --git a/apis/r/R/SOMADenseNDArray.R b/apis/r/R/SOMADenseNDArray.R index 6cd9c24e57..0299077e21 100644 --- a/apis/r/R/SOMADenseNDArray.R +++ b/apis/r/R/SOMADenseNDArray.R @@ -154,9 +154,9 @@ SOMADenseNDArray <- R6::R6Class( # arr[] <- values writeArrayFromArrow( uri = self$uri, - coords, naap = naap, nasp = nasp, + coords_list = coords, ctxxp = private$.soma_context, arraytype = "SOMADenseNDArray", config = NULL, diff --git a/apis/r/R/SOMASparseNDArray.R b/apis/r/R/SOMASparseNDArray.R index 024de6cca6..186549d3ec 100644 --- a/apis/r/R/SOMASparseNDArray.R +++ b/apis/r/R/SOMASparseNDArray.R @@ -277,6 +277,7 @@ SOMASparseNDArray <- R6::R6Class( uri = self$uri, naap = naap, nasp = nasp, + coords_list = list(), # only used for SOMADenseNDArray ctxxp = private$.soma_context, arraytype = "SOMASparseNDArray", config = NULL, diff --git a/apis/r/src/arrow.cpp b/apis/r/src/arrow.cpp index 565a406fde..1fb024ca11 100644 --- a/apis/r/src/arrow.cpp +++ b/apis/r/src/arrow.cpp @@ -273,7 +273,20 @@ void writeArrayFromArrow( int lo = *std::min_element(slot_values.begin(), slot_values.end()); int hi = *std::max_element(slot_values.begin(), slot_values.end()); spdl::debug( - "dense array write: dim {} set range lo {} hi {}", dim_name, lo, hi); + "dense array write: dim {} set 1-up range lo {} hi {}", + dim_name, + lo, + hi); + // These are 1-up indices from R. Convert to 0-up for C++. + if (lo < 1) { + Rcpp::stop(tfm::format( + "dense array write: expected lower bound %d >= 1 for dim " + "name %s", + lo, + dim_name)); + } + lo--; + hi--; std::pair lo_hi(int64_t{lo}, int64_t{hi}); std::vector> range({lo_hi}); arrup.get()->set_dim_ranges(dim_name, range);