From c043baa69d202263750bd19a14eb04f6e735c5b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kirill=20M=C3=BCller?= Date: Sun, 8 Dec 2024 10:11:32 +0100 Subject: [PATCH] Compatibility with R >= 4.5.0 --- src/register.cpp | 10 +++++----- tests/testthat/test-scan.R | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/register.cpp b/src/register.cpp index 221002d88..9abbfc461 100644 --- a/src/register.cpp +++ b/src/register.cpp @@ -55,6 +55,9 @@ unique_ptr duckdb::EnvironmentScanReplacement(ClientContext &context, auto table_name_symbol = cpp11::safe[Rf_install](input.table_name.c_str()); SEXP df; SEXP rho = db_wrapper->env; +#if defined(R_VERSION) && R_VERSION >= R_Version(4, 5, 0) + df = cpp11::safe[R_getVarEx](table_name_symbol, rho, Rboolean::TRUE, R_NilValue); +#else while(rho != R_EmptyEnv) { df = cpp11::safe[Rf_findVarInFrame3](rho, table_name_symbol, TRUE); if (df != R_UnboundValue) { @@ -62,12 +65,10 @@ unique_ptr duckdb::EnvironmentScanReplacement(ClientContext &context, } rho = ENCLOS(rho); } - if (!df) { - return nullptr; - } if (TYPEOF(df) == PROMSXP) { df = cpp11::safe[Rf_eval](df, rho); } +#endif if (!Rf_inherits(df, "data.frame")) { return nullptr; } @@ -79,8 +80,7 @@ unique_ptr duckdb::EnvironmentScanReplacement(ClientContext &context, // TODO: do utf conversion auto table_function = make_uniq(); vector> children; - children.push_back( - make_uniq(Value::POINTER((uintptr_t)df))); + children.push_back(make_uniq(Value::POINTER((uintptr_t)df))); table_function->function = make_uniq("r_dataframe_scan", std::move(children)); return std::move(table_function); } diff --git a/tests/testthat/test-scan.R b/tests/testthat/test-scan.R index e31806c00..605be8e1f 100644 --- a/tests/testthat/test-scan.R +++ b/tests/testthat/test-scan.R @@ -40,6 +40,21 @@ test_that("Data frame scan fetches from the correct environment", { expect_equal(dbGetQuery(con, "FROM x"), x) }) +test_that("Function hides data frame", { + con <- dbConnect(duckdb(environment_scan = TRUE)) + on.exit(dbDisconnect(con)) + + x <- data.frame(a = 1) + + fun <- function() { + x <- function() {} + dbGetQuery(con, "FROM x") + } + + expect_error(fun()) + expect_equal(dbGetQuery(con, "FROM x"), x) +}) + test_that("Database tables take precedence", { con <- dbConnect(duckdb(environment_scan = TRUE)) on.exit(dbDisconnect(con))