diff --git a/r/NAMESPACE b/r/NAMESPACE index df4f36408e3..c8aae1b9346 100644 --- a/r/NAMESPACE +++ b/r/NAMESPACE @@ -215,6 +215,7 @@ export(date32) export(date64) export(decimal) export(decimal128) +export(decimal256) export(default_memory_pool) export(dictionary) export(ends_with) diff --git a/r/NEWS.md b/r/NEWS.md index 8576d38edfc..90a9bba79d0 100644 --- a/r/NEWS.md +++ b/r/NEWS.md @@ -19,11 +19,12 @@ # arrow 6.0.1.9000 +* Added `decimal256()`. Updated `decimal()`, which now calls `decimal256()` or `decimal128()` based on the value of the `precision` argument. * updated `write_csv_arrow()` to follow the signature of `readr::write_csv()`. The following arguments are supported: * `file` identical to `sink` * `col_names` identical to `include_header` * other arguments are currently unsupported, but the function errors with a meaningful message. -* Added `decimal128()` (identical to `decimal()`) as the name is more explicit and updated docs to encourage its use. +* Added `decimal128()` (~~identical to `decimal()`~~) as the name is more explicit and updated docs to encourage its use. * Source builds now by default use `pkg-config` to search for system dependencies (such as `libz`) and link to them if present. To retain the previous behaviour of downloading and building all dependencies, set `ARROW_DEPENDENCY_SOURCE=BUNDLED`. diff --git a/r/R/array.R b/r/R/array.R index 65fb450f8de..0e472207f54 100644 --- a/r/R/array.R +++ b/r/R/array.R @@ -187,8 +187,30 @@ Array$create <- function(x, type = NULL) { } return(out) } - vec_to_Array(x, type) + + if (is.null(type)) { + return(vec_to_Array(x, type)) + } + + # when a type is given, try to create a vector of the desired type. If that + # fails, attempt to cast and if casting is successful, suggest to the user + # to try casting manually. If the casting fails, return the original error + # message. + tryCatch( + vec_to_Array(x, type), + error = function(cnd) { + attempt <- try(vec_to_Array(x, NULL)$cast(type), silent = TRUE) + abort( + c(conditionMessage(cnd), + i = if (!inherits(attempt, "try-error")) { + "You might want to try casting manually with `Array$create(...)$cast(...)`." + } + ) + ) + } + ) } + #' @include arrowExports.R Array$import_from_c <- ImportArray diff --git a/r/R/arrowExports.R b/r/R/arrowExports.R index c1e0fca788d..5eaf1b91c5b 100644 --- a/r/R/arrowExports.R +++ b/r/R/arrowExports.R @@ -696,6 +696,10 @@ Decimal128Type__initialize <- function(precision, scale) { .Call(`_arrow_Decimal128Type__initialize`, precision, scale) } +Decimal256Type__initialize <- function(precision, scale) { + .Call(`_arrow_Decimal256Type__initialize`, precision, scale) +} + FixedSizeBinary__initialize <- function(byte_width) { .Call(`_arrow_FixedSizeBinary__initialize`, byte_width) } diff --git a/r/R/type.R b/r/R/type.R index 60f0045e514..eb71cd7432e 100644 --- a/r/R/type.R +++ b/r/R/type.R @@ -150,8 +150,11 @@ DecimalType <- R6Class("DecimalType", scale = function() DecimalType__scale(self) ) ) + Decimal128Type <- R6Class("Decimal128Type", inherit = DecimalType) +Decimal256Type <- R6Class("Decimal256Type", inherit = DecimalType) + NestedType <- R6Class("NestedType", inherit = DataType) #' Apache Arrow data types @@ -181,7 +184,7 @@ NestedType <- R6Class("NestedType", inherit = DataType) #' `bit64::integer64` object) by setting `options(arrow.int64_downcast = #' FALSE)`. #' -#' `decimal128()` creates a `decimal128` type. Arrow decimals are fixed-point +#' `decimal128()` creates a `Decimal128Type`. Arrow decimals are fixed-point #' decimal numbers encoded as a scalar integer. The `precision` is the number of #' significant digits that the decimal type can represent; the `scale` is the #' number of digits after the decimal point. For example, the number 1234.567 @@ -197,9 +200,16 @@ NestedType <- R6Class("NestedType", inherit = DataType) #' negative, `scale` causes the number to be expressed using scientific notation #' and power of 10. #' -#' `decimal()` is identical to `decimal128()`, defined for backward compatibility. -#' Use `decimal128()` as the name is more informative and `decimal()` might be -#' deprecated in the future. +#' `decimal256()` creates a `Decimal256Type`, which allows for higher maximum +#' precision. For most use cases, the maximum precision offered by `Decimal128Type` +#' is sufficient, and it will result in a more compact and more efficient encoding. +#' +#' #' `decimal()` creates either a `Decimal128Type` or a `Decimal256Type` +#' depending on the value for `precision`. If `precision` is greater than 38 a +#' `Decimal256Type` is returned, otherwise a `Decimal128Type`. +#' +#' Use `decimal128()` or `decimal256()` as the names are more informative than +#' `decimal()`. #' #' @param unit For time/timestamp types, the time unit. `time32()` can take #' either "s" or "ms", while `time64()` can be "us" or "ns". `timestamp()` can @@ -207,11 +217,13 @@ NestedType <- R6Class("NestedType", inherit = DataType) #' @param timezone For `timestamp()`, an optional time zone string. #' @param byte_width byte width for `FixedSizeBinary` type. #' @param list_size list size for `FixedSizeList` type. -#' @param precision For `decimal()`, `decimal128()` the number of significant -#' digits the arrow `decimal` type can represent. The maximum precision for -#' `decimal()` and `decimal128()` is 38 significant digits. -#' @param scale For `decimal()` and `decimal128()`, the number of digits after -#' the decimal point. It can be negative. +#' @param precision For `decimal()`, `decimal128()`, and `decimal256()` the +#' number of significant digits the arrow `decimal` type can represent. The +#' maximum precision for `decimal128()` is 38 significant digits, while for +#' `decimal256()` it is 76 digits. `decimal()` will use it to choose which +#' type of decimal to return. +#' @param scale For `decimal()`, `decimal128()`, and `decimal256()` the number +#' of digits after the decimal point. It can be negative. #' @param type For `list_of()`, a data type to make a list-of-type #' @param ... For `struct()`, a named list of types to define the struct columns #' @@ -375,25 +387,49 @@ timestamp <- function(unit = c("s", "ms", "us", "ns"), timezone = "") { Timestamp__initialize(unit, timezone) } +#' @rdname data-type +#' @export +decimal <- function(precision, scale) { + args <- check_decimal_args(precision, scale) + + if (args$precision > 38) { + decimal256(args$precision, args$scale) + } else { + decimal128(args$precision, args$scale) + } +} + #' @rdname data-type #' @export decimal128 <- function(precision, scale) { + args <- check_decimal_args(precision, scale) + Decimal128Type__initialize(args$precision, args$scale) +} + +#' @rdname data-type +#' @export +decimal256 <- function(precision, scale) { + args <- check_decimal_args(precision, scale) + Decimal256Type__initialize(args$precision, args$scale) +} + +check_decimal_args <- function(precision, scale) { if (is.numeric(precision)) { - precision <- as.integer(precision) + precision <- vec_cast(precision, to = integer()) + vctrs::vec_assert(precision, size = 1L) } else { - stop('"precision" must be an integer', call. = FALSE) + stop("`precision` must be an integer", call. = FALSE) } + if (is.numeric(scale)) { - scale <- as.integer(scale) + scale <- vec_cast(scale, to = integer()) + vctrs::vec_assert(scale, size = 1L) } else { - stop('"scale" must be an integer', call. = FALSE) + stop("`scale` must be an integer", call. = FALSE) } - Decimal128Type__initialize(precision, scale) -} -#' @rdname data-type -#' @export -decimal <- decimal128 + list(precision = precision, scale = scale) +} StructType <- R6Class("StructType", inherit = NestedType, @@ -496,6 +532,7 @@ canonical_type_str <- function(type_str) { null = "null", timestamp = "timestamp", decimal128 = "decimal128", + decimal256 = "decimal256", struct = "struct", list_of = "list", list = "list", diff --git a/r/man/data-type.Rd b/r/man/data-type.Rd index 2b1c4bbff25..a8e653ae819 100644 --- a/r/man/data-type.Rd +++ b/r/man/data-type.Rd @@ -29,8 +29,9 @@ \alias{time64} \alias{null} \alias{timestamp} -\alias{decimal128} \alias{decimal} +\alias{decimal128} +\alias{decimal256} \alias{struct} \alias{list_of} \alias{large_list_of} @@ -92,9 +93,11 @@ null() timestamp(unit = c("s", "ms", "us", "ns"), timezone = "") +decimal(precision, scale) + decimal128(precision, scale) -decimal(precision, scale) +decimal256(precision, scale) struct(...) @@ -113,12 +116,14 @@ take any of those four values.} \item{timezone}{For \code{timestamp()}, an optional time zone string.} -\item{precision}{For \code{decimal()}, \code{decimal128()} the number of significant -digits the arrow \code{decimal} type can represent. The maximum precision for -\code{decimal()} and \code{decimal128()} is 38 significant digits.} +\item{precision}{For \code{decimal()}, \code{decimal128()}, and \code{decimal256()} the +number of significant digits the arrow \code{decimal} type can represent. The +maximum precision for \code{decimal128()} is 38 significant digits, while for +\code{decimal256()} it is 76 digits. \code{decimal()} will use it to choose which +type of decimal to return.} -\item{scale}{For \code{decimal()} and \code{decimal128()}, the number of digits after -the decimal point. It can be negative.} +\item{scale}{For \code{decimal()}, \code{decimal128()}, and \code{decimal256()} the number +of digits after the decimal point. It can be negative.} \item{...}{For \code{struct()}, a named list of types to define the struct columns} @@ -156,7 +161,7 @@ are translated to R objects, \code{uint32} and \code{uint64} are converted to \c types, this conversion can be disabled (so that \code{int64} always yields a \code{bit64::integer64} object) by setting \code{options(arrow.int64_downcast = FALSE)}. -\code{decimal128()} creates a \code{decimal128} type. Arrow decimals are fixed-point +\code{decimal128()} creates a \code{Decimal128Type}. Arrow decimals are fixed-point decimal numbers encoded as a scalar integer. The \code{precision} is the number of significant digits that the decimal type can represent; the \code{scale} is the number of digits after the decimal point. For example, the number 1234.567 @@ -172,9 +177,16 @@ The \code{scale} can be thought of as an argument that controls rounding. When negative, \code{scale} causes the number to be expressed using scientific notation and power of 10. -\code{decimal()} is identical to \code{decimal128()}, defined for backward compatibility. -Use \code{decimal128()} as the name is more informative and \code{decimal()} might be -deprecated in the future. +\code{decimal256()} creates a \code{Decimal256Type}, which allows for higher maximum +precision. For most use cases, the maximum precision offered by \code{Decimal128Type} +is sufficient, and it will result in a more compact and more efficient encoding. + +#' \code{decimal()} creates either a \code{Decimal128Type} or a \code{Decimal256Type} +depending on the value for \code{precision}. If \code{precision} is greater than 38 a +\code{Decimal256Type} is returned, otherwise a \code{Decimal128Type}. + +Use \code{decimal128()} or \code{decimal256()} as the names are more informative than +\code{decimal()}. } \examples{ \dontshow{if (arrow_available()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} diff --git a/r/src/array_to_vector.cpp b/r/src/array_to_vector.cpp index 3ac32d7c395..f381bf086d8 100644 --- a/r/src/array_to_vector.cpp +++ b/r/src/array_to_vector.cpp @@ -905,6 +905,7 @@ class Converter_Timestamp : public Converter_Time { } }; +template class Converter_Decimal : public Converter { public: explicit Converter_Decimal(const std::shared_ptr& chunked_array) @@ -919,8 +920,9 @@ class Converter_Decimal : public Converter { Status Ingest_some_nulls(SEXP data, const std::shared_ptr& array, R_xlen_t start, R_xlen_t n, size_t chunk_index) const { + using DecimalArray = typename TypeTraits::ArrayType; auto p_data = REAL(data) + start; - const auto& decimals_arr = checked_cast(*array); + const auto& decimals_arr = checked_cast(*array); auto ingest_one = [&](R_xlen_t i) { p_data[i] = std::stod(decimals_arr.FormatValue(i).c_str()); @@ -1217,7 +1219,10 @@ std::shared_ptr Converter::Make( } case Type::DECIMAL128: - return std::make_shared(chunked_array); + return std::make_shared>(chunked_array); + + case Type::DECIMAL256: + return std::make_shared>(chunked_array); // nested case Type::STRUCT: @@ -1245,7 +1250,7 @@ std::shared_ptr Converter::Make( break; } - cpp11::stop("cannot handle Array of type ", type->name().c_str()); + cpp11::stop("cannot handle Array of type <%s>", type->name().c_str()); } std::shared_ptr to_chunks(const std::shared_ptr& array) { diff --git a/r/src/arrowExports.cpp b/r/src/arrowExports.cpp index ef388b09208..95e7d458929 100644 --- a/r/src/arrowExports.cpp +++ b/r/src/arrowExports.cpp @@ -2730,6 +2730,22 @@ extern "C" SEXP _arrow_Decimal128Type__initialize(SEXP precision_sexp, SEXP scal } #endif +// datatype.cpp +#if defined(ARROW_R_WITH_ARROW) +std::shared_ptr Decimal256Type__initialize(int32_t precision, int32_t scale); +extern "C" SEXP _arrow_Decimal256Type__initialize(SEXP precision_sexp, SEXP scale_sexp){ +BEGIN_CPP11 + arrow::r::Input::type precision(precision_sexp); + arrow::r::Input::type scale(scale_sexp); + return cpp11::as_sexp(Decimal256Type__initialize(precision, scale)); +END_CPP11 +} +#else +extern "C" SEXP _arrow_Decimal256Type__initialize(SEXP precision_sexp, SEXP scale_sexp){ + Rf_error("Cannot call Decimal256Type__initialize(). See https://arrow.apache.org/docs/r/articles/install.html for help installing Arrow C++ libraries. "); +} +#endif + // datatype.cpp #if defined(ARROW_R_WITH_ARROW) std::shared_ptr FixedSizeBinary__initialize(R_xlen_t byte_width); @@ -7345,6 +7361,7 @@ static const R_CallMethodDef CallEntries[] = { { "_arrow_Date64__initialize", (DL_FUNC) &_arrow_Date64__initialize, 0}, { "_arrow_Null__initialize", (DL_FUNC) &_arrow_Null__initialize, 0}, { "_arrow_Decimal128Type__initialize", (DL_FUNC) &_arrow_Decimal128Type__initialize, 2}, + { "_arrow_Decimal256Type__initialize", (DL_FUNC) &_arrow_Decimal256Type__initialize, 2}, { "_arrow_FixedSizeBinary__initialize", (DL_FUNC) &_arrow_FixedSizeBinary__initialize, 1}, { "_arrow_Timestamp__initialize", (DL_FUNC) &_arrow_Timestamp__initialize, 2}, { "_arrow_Time32__initialize", (DL_FUNC) &_arrow_Time32__initialize, 1}, diff --git a/r/src/datatype.cpp b/r/src/datatype.cpp index bfc6687ed5b..942b6f0133d 100644 --- a/r/src/datatype.cpp +++ b/r/src/datatype.cpp @@ -82,6 +82,8 @@ const char* r6_class_name::get( case Type::DECIMAL128: return "Decimal128Type"; + case Type::DECIMAL256: + return "Decimal256Type"; case Type::LIST: return "ListType"; @@ -180,6 +182,13 @@ std::shared_ptr Decimal128Type__initialize(int32_t precision, return ValueOrStop(arrow::Decimal128Type::Make(precision, scale)); } +// [[arrow::export]] +std::shared_ptr Decimal256Type__initialize(int32_t precision, + int32_t scale) { + // Use the builder that validates inputs + return ValueOrStop(arrow::Decimal256Type::Make(precision, scale)); +} + // [[arrow::export]] std::shared_ptr FixedSizeBinary__initialize(R_xlen_t byte_width) { if (byte_width == NA_INTEGER) { diff --git a/r/tests/testthat/test-Array.R b/r/tests/testthat/test-Array.R index ce23c260908..c4e3174b149 100644 --- a/r/tests/testthat/test-Array.R +++ b/r/tests/testthat/test-Array.R @@ -795,6 +795,24 @@ test_that("Array$create() should have helpful error", { expect_error(Array$create(list()), "Requires at least one element to infer") expect_error(Array$create(list(lgl, lgl, int)), "Expecting a logical vector") expect_error(Array$create(list(char, num, char)), "Expecting a character vector") + + # hint at casting if direct fails and casting looks like it might work + expect_error( + Array$create(as.double(1:10), type = decimal(4, 2)), + "You might want to try casting manually" + ) + + expect_error( + Array$create(1:10, type = decimal(12, 2)), + "You might want to try casting manually" + ) + + a <- expect_error(Array$create("one", int32())) + b <- expect_error(vec_to_Array("one", int32())) + # the captured conditions (errors) are not identical, but their messages should be + expect_s3_class(a, "rlang_error") + expect_s3_class(b, "simpleError") + expect_equal(a$message, b$message) }) test_that("Array$View() (ARROW-6542)", { diff --git a/r/tests/testthat/test-chunked-array.R b/r/tests/testthat/test-chunked-array.R index 73e536514a2..4cd8b5387be 100644 --- a/r/tests/testthat/test-chunked-array.R +++ b/r/tests/testthat/test-chunked-array.R @@ -206,7 +206,8 @@ test_that("ChunkedArray supports empty arrays (ARROW-13761)", { int8(), int16(), int32(), int64(), uint8(), uint16(), uint32(), uint64(), float32(), float64(), timestamp("ns"), binary(), large_binary(), fixed_size_binary(32), date32(), date64(), - decimal128(4, 2), dictionary(), struct(x = int32()) + decimal128(4, 2), #decimal256(4, 2), # un-comment once ARROW-15166 is solved + dictionary(), struct(x = int32()) ) empty_filter <- ChunkedArray$create(type = bool()) @@ -228,6 +229,29 @@ test_that("ChunkedArray supports empty arrays (ARROW-13761)", { expect_identical(length(as.vector(zero_empty_chunks)), 1L) } } + + skip("array_filter has no kernel matching input types `(array[decimal256(4, 2)], array[bool])`") + # TODO once ARROW-15166 is addressed decimal256() can be moved together with + # the other types (separated to be able to skip). this whole chunk can be + # deleted + type <- decimal256(4, 2) + empty_filter <- ChunkedArray$create(type = bool()) + one_empty_chunk <- ChunkedArray$create(type = type) + expect_type_equal(one_empty_chunk$type, type) + if (type != struct(x = int32())) { + expect_identical(length(one_empty_chunk), length(as.vector(one_empty_chunk))) + } else { + # struct -> tbl and length(tbl) is num_columns instead of num_rows + expect_identical(length(as.vector(one_empty_chunk)), 1L) + } + zero_empty_chunks <- one_empty_chunk$Filter(empty_filter) + expect_equal(zero_empty_chunks$num_chunks, 0) + expect_type_equal(zero_empty_chunks$type, type) + if (type != struct(x = int32())) { + expect_identical(length(zero_empty_chunks), length(as.vector(zero_empty_chunks))) + } else { + expect_identical(length(as.vector(zero_empty_chunks)), 1L) + } }) test_that("integer types casts for ChunkedArray (ARROW-3741)", { diff --git a/r/tests/testthat/test-data-type.R b/r/tests/testthat/test-data-type.R index d2795722928..30a54796d98 100644 --- a/r/tests/testthat/test-data-type.R +++ b/r/tests/testthat/test-data-type.R @@ -386,20 +386,44 @@ test_that("DictionaryType validation", { test_that("decimal type and validation", { expect_r6_class(decimal(4, 2), "Decimal128Type") + expect_r6_class(decimal(39, 2), "Decimal256Type") - expect_error(decimal("four"), '"precision" must be an integer') - expect_error(decimal(4, "two"), '"scale" must be an integer') - expect_error(decimal(NA, 2), '"precision" must be an integer') - expect_error(decimal(4, NA), '"scale" must be an integer') + expect_error(decimal("four"), "`precision` must be an integer") + expect_error(decimal(4, "two"), "`scale` must be an integer") + expect_error(decimal(NA, 2), "`precision` must be an integer") + expect_error(decimal(4, NA), "`scale` must be an integer") + # TODO remove precision range tests below once functionality is tested in C++ (ARROW-15162) + expect_error(decimal(0, 2), "Invalid: Decimal precision out of range [1, 38]: 0", fixed = TRUE) + expect_error(decimal(100, 2), "Invalid: Decimal precision out of range [1, 76]: 100", fixed = TRUE) + + # decimal() creates either decimal128 or decimal256 based on precision + expect_identical(class(decimal(38, 2)), class(decimal128(38, 2))) + expect_identical(class(decimal(39, 2)), class(decimal256(38, 2))) - # decimal() is just an alias for decimal128() for backwards compatibility expect_r6_class(decimal128(4, 2), "Decimal128Type") - expect_identical(class(decimal(2, 4)), class(decimal128(2, 4))) - expect_error(decimal128("four"), '"precision" must be an integer') - expect_error(decimal128(4, "two"), '"scale" must be an integer') - expect_error(decimal128(NA, 2), '"precision" must be an integer') - expect_error(decimal128(4, NA), '"scale" must be an integer') + expect_error(decimal128("four"), "`precision` must be an integer") + expect_error(decimal128(4, "two"), "`scale` must be an integer") + expect_error(decimal128(NA, 2), "`precision` must be an integer") + expect_error(decimal128(4, NA), "`scale` must be an integer") + expect_error(decimal128(3:4, NA), "`precision` must have size 1. not size 2") + expect_error(decimal128(4, 2:3), "`scale` must have size 1. not size 2") + # TODO remove precision range tests below once functionality is tested in C++ (ARROW-15162) + expect_error(decimal128(0, 2), "Invalid: Decimal precision out of range [1, 38]: 0", fixed = TRUE) + expect_error(decimal128(100, 2), "Invalid: Decimal precision out of range [1, 38]: 100", fixed = TRUE) + + + expect_r6_class(decimal256(4, 2), "Decimal256Type") + + expect_error(decimal256("four"), "`precision` must be an integer") + expect_error(decimal256(4, "two"), "`scale` must be an integer") + expect_error(decimal256(NA, 2), "`precision` must be an integer") + expect_error(decimal256(4, NA), "`scale` must be an integer") + expect_error(decimal256(3:4, NA), "`precision` must have size 1. not size 2") + expect_error(decimal256(4, 2:3), "`scale` must have size 1. not size 2") + # TODO remove precision range tests below once functionality is tested in C++ (ARROW-15162) + expect_error(decimal256(0, 2), "Invalid: Decimal precision out of range [1, 76]: 0", fixed = TRUE) + expect_error(decimal256(100, 2), "Invalid: Decimal precision out of range [1, 76]: 100", fixed = TRUE) }) test_that("Binary", { diff --git a/r/tests/testthat/test-dplyr-funcs-type.R b/r/tests/testthat/test-dplyr-funcs-type.R index 22696eb2ae6..c5fd83cb0f4 100644 --- a/r/tests/testthat/test-dplyr-funcs-type.R +++ b/r/tests/testthat/test-dplyr-funcs-type.R @@ -209,39 +209,50 @@ test_that("type checks with is() giving Arrow types", { i32 = Array$create(1, int32()), dec = Array$create(pi)$cast(decimal(3, 2)), dec128 = Array$create(pi)$cast(decimal128(3, 2)), + dec256 = Array$create(pi)$cast(decimal256(3, 2)), f64 = Array$create(1.1, float64()), str = Array$create("a", arrow::string()) ) %>% transmute( i32_is_i32 = is(i32, int32()), i32_is_dec = is(i32, decimal(3, 2)), i32_is_dec128 = is(i32, decimal128(3, 2)), + i32_is_dec256 = is(i32, decimal256(3, 2)), i32_is_i64 = is(i32, float64()), i32_is_str = is(i32, arrow::string()), dec_is_i32 = is(dec, int32()), dec_is_dec = is(dec, decimal(3, 2)), dec_is_dec128 = is(dec, decimal128(3, 2)), + dec_is_dec256 = is(dec, decimal256(3, 2)), dec_is_i64 = is(dec, float64()), dec_is_str = is(dec, arrow::string()), dec128_is_i32 = is(dec128, int32()), dec128_is_dec128 = is(dec128, decimal128(3, 2)), + dec128_is_dec256 = is(dec128, decimal256(3, 2)), dec128_is_i64 = is(dec128, float64()), dec128_is_str = is(dec128, arrow::string()), + dec256_is_i32 = is(dec128, int32()), + dec256_is_dec128 = is(dec128, decimal128(3, 2)), + dec256_is_dec256 = is(dec128, decimal256(3, 2)), + dec256_is_i64 = is(dec128, float64()), + dec256_is_str = is(dec128, arrow::string()), f64_is_i32 = is(f64, int32()), f64_is_dec = is(f64, decimal(3, 2)), f64_is_dec128 = is(f64, decimal128(3, 2)), + f64_is_dec256 = is(f64, decimal256(3, 2)), f64_is_i64 = is(f64, float64()), f64_is_str = is(f64, arrow::string()), str_is_i32 = is(str, int32()), str_is_dec128 = is(str, decimal128(3, 2)), + str_is_dec256 = is(str, decimal256(3, 2)), str_is_i64 = is(str, float64()), str_is_str = is(str, arrow::string()) ) %>% collect() %>% t() %>% as.vector(), - c(TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, - TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, - TRUE) + c(TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, + FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, + FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE) ) # with class2=string expect_equal( diff --git a/r/tests/testthat/test-type.R b/r/tests/testthat/test-type.R index 8046ebbaa57..64a305f8eb8 100644 --- a/r/tests/testthat/test-type.R +++ b/r/tests/testthat/test-type.R @@ -164,6 +164,10 @@ test_that("Type strings are correctly canonicalized", { canonical_type_str("decimal128"), sub("^([^([<]+).*$", "\\1", decimal128(3, 2)$ToString()) ) + expect_equal( + canonical_type_str("decimal256"), + sub("^([^([<]+).*$", "\\1", decimal256(3, 2)$ToString()) + ) expect_equal( canonical_type_str("struct"), sub("^([^([<]+).*$", "\\1", struct(foo = int32())$ToString())