diff --git a/R/Driver.R b/R/Driver.R index de6125bc6..b2eed12d1 100644 --- a/R/Driver.R +++ b/R/Driver.R @@ -29,18 +29,7 @@ driver_registry <- new.env(parent = emptyenv()) #' @export duckdb <- function(dbdir = DBDIR_MEMORY, read_only = FALSE, bigint = "numeric", config = list()) { check_flag(read_only) - - switch(bigint, - numeric = { - # fine - }, - integer64 = { - if (!is_installed("bit64")) { - stop("bit64 package is required for integer64 support") - } - }, - stop(paste("Unsupported bigint configuration", bigint)) - ) + check_bigint(bigint) # R packages are not allowed to write extensions into home directory, so use R_user_dir instead if (!("extension_directory" %in% names(config))) { @@ -165,7 +154,6 @@ check_tz <- function(timezone) { timezone } - path_normalize <- function(path) { if (path == "" || path == DBDIR_MEMORY) { return(DBDIR_MEMORY) @@ -181,3 +169,17 @@ path_normalize <- function(path) { } out } + +check_bigint <- function(bigint_type) { + switch(bigint_type, + numeric = { + # fine + }, + integer64 = { + if (!is_installed("bit64")) { + stop("bit64 package is required for integer64 support") + } + }, + stop(paste("Unsupported bigint configuration", bigint_type)) + ) +} diff --git a/R/dbConnect__duckdb_driver.R b/R/dbConnect__duckdb_driver.R index 581859c53..10c412986 100644 --- a/R/dbConnect__duckdb_driver.R +++ b/R/dbConnect__duckdb_driver.R @@ -19,7 +19,9 @@ #' If `"force"` is chosen, the timestamp will have the same clock #' time as the timestamp in the database, but with the new time zone. #' @param config Named list with DuckDB configuration flags -#' @param bigint How 64-bit integers should be returned, default is double/numeric. Set to integer64 for bit64 encoding. +#' @param bigint How 64-bit integers should be returned. There are two options: `"numeric`" and `"integer64`". +#' If `"numeric`" is selected, bigint integers will be treated as double/numeric. +#' If `"integer64`" is selected, bigint integers will be set to bit64 encoding. #' #' @return `dbConnect()` returns an object of class #' \linkS4class{duckdb_connection}. @@ -65,6 +67,8 @@ dbConnect__duckdb_driver <- function( if (missing(bigint)) { bigint <- drv@bigint + } else { + check_bigint(bigint) } config <- utils::modifyList(drv@config, config) @@ -79,7 +83,6 @@ dbConnect__duckdb_driver <- function( conn@timezone_out <- timezone_out conn@tz_out_convert <- tz_out_convert - on.exit(NULL) rs_on_connection_opened(conn) diff --git a/man/duckdb.Rd b/man/duckdb.Rd index ef358114c..10d3cb133 100644 --- a/man/duckdb.Rd +++ b/man/duckdb.Rd @@ -43,7 +43,9 @@ data is kept in RAM.} \item{read_only}{Set to \code{TRUE} for read-only operation} -\item{bigint}{How 64-bit integers should be returned, default is double/numeric. Set to integer64 for bit64 encoding.} +\item{bigint}{How 64-bit integers should be returned. There are two options: \verb{"numeric}" and \verb{"integer64}". +If \verb{"numeric}" is selected, bigint integers will be treated as double/numeric. +If \verb{"integer64}" is selected, bigint integers will be set to bit64 encoding.} \item{config}{Named list with DuckDB configuration flags} diff --git a/tests/testthat/test-integer64.R b/tests/testthat/test-integer64.R index 44733f932..fc868533d 100644 --- a/tests/testthat/test-integer64.R +++ b/tests/testthat/test-integer64.R @@ -1,7 +1,6 @@ # this tests both retrieval and scans -test_that("we can roundtrip an integer64", { +test_that("we can roundtrip an integer64 via driver", { skip_if_not_installed("bit64") - con <- dbConnect(duckdb(bigint = "integer64")) on.exit(dbDisconnect(con, shutdown = TRUE)) df <- data.frame(a = bit64::as.integer64(42), b = bit64::as.integer64(-42), c = bit64::as.integer64(NA)) @@ -11,3 +10,15 @@ test_that("we can roundtrip an integer64", { res <- dbReadTable(con, "df") expect_identical(df, res) }) + +test_that("we can roundtrip an integer64 via dbConnect", { + skip_if_not_installed("bit64") + con <- dbConnect(duckdb(), bigint = "integer64") + on.exit(dbDisconnect(con, shutdown = TRUE)) + df <- data.frame(a = bit64::as.integer64(42), b = bit64::as.integer64(-42), c = bit64::as.integer64(NA)) + + duckdb_register(con, "df", df) + + res <- dbReadTable(con, "df") + expect_identical(df, res) +})