Skip to content

Commit

Permalink
Merge pull request #157 from duckdblabs/f-na-expr
Browse files Browse the repository at this point in the history
  • Loading branch information
krlmlr committed May 7, 2024
2 parents d0985cf + 583dda6 commit bd739e6
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 3 deletions.
6 changes: 3 additions & 3 deletions R/relational.R
Expand Up @@ -110,7 +110,7 @@ rel_translate <- function(

used <- character()

do_translate <- function(expr, in_window = FALSE) {
do_translate <- function(expr, in_window = FALSE, top_level = FALSE) {
if (is_quosure(expr)) {
# FIXME: What to do with the environment here?
expr <- quo_get_expr(expr)
Expand All @@ -121,7 +121,7 @@ rel_translate <- function(
integer = ,
double = relexpr_constant(expr),
# https://github.com/duckdb/duckdb-r/pull/156
logical = if (is.na(expr)) relexpr_function("___null", list()) else relexpr_constant(expr),
logical = if (top_level && length(expr) == 1 && is.na(expr)) relexpr_function("___null", list()) else relexpr_constant(expr),
#
symbol = {
if (as.character(expr) %in% names_forbidden) {
Expand Down Expand Up @@ -335,7 +335,7 @@ rel_translate <- function(
)
}

out <- do_translate(expr)
out <- do_translate(expr, top_level = TRUE)

if (!is.null(alias) && !identical(alias, "")) {
out <- relexpr_set_alias(out, alias)
Expand Down
13 changes: 13 additions & 0 deletions tests/testthat/test-as_duckplyr_df.R
Expand Up @@ -1690,6 +1690,19 @@ test_that("as_duckplyr_df() and mutate(d = NA_character_)", {
expect_identical(pre, post)
})


test_that("as_duckplyr_df() and mutate(d = if_else(a > 1, \"ok\", NA))", {
# Data
test_df <- data.frame(a = 1:6 + 0, b = 2, g = rep(1:3, 1:3))

# Run
pre <- test_df %>% as_duckplyr_df() %>% mutate(d = if_else(a > 1, "ok", NA))
post <- test_df %>% mutate(d = if_else(a > 1, "ok", NA)) %>% as_duckplyr_df()

# Compare
expect_identical(pre, post)
})

test_that("as_duckplyr_df() and n_groups()", {
withr::local_envvar(DUCKPLYR_FORCE = "FALSE")

Expand Down
166 changes: 166 additions & 0 deletions tests/testthat/test-rel_api.R
Expand Up @@ -9277,6 +9277,87 @@ test_that("relational mutate(d = NA_character_) order-preserving", {
DBI::dbDisconnect(con, shutdown = TRUE)
})

test_that("relational mutate(d = if_else(a > 1, \"ok\", NA)) order-preserving", {
# Autogenerated
duckdb <- asNamespace("duckdb")
drv <- duckdb::duckdb()
con <- DBI::dbConnect(drv)
experimental <- FALSE
invisible(
DBI::dbExecute(
con,
'CREATE MACRO "if_else"(test, yes, no) AS (CASE WHEN test THEN yes ELSE no END)'
)
)
invisible(duckdb$rapi_load_rfuns(drv@database_ref))
invisible(DBI::dbExecute(con, 'CREATE MACRO ">"(x, y) AS "r_base::>"(x, y)'))
df1 <- data.frame(a = seq(1, 6, by = 1), b = rep(2, 6L), g = c(1L, 2L, 2L, 3L, 3L, 3L))

rel1 <- duckdb$rel_from_df(con, df1, experimental = experimental)
rel2 <- duckdb$rel_project(
rel1,
list(
{
tmp_expr <- duckdb$expr_reference("a")
duckdb$expr_set_alias(tmp_expr, "a")
tmp_expr
},
{
tmp_expr <- duckdb$expr_reference("b")
duckdb$expr_set_alias(tmp_expr, "b")
tmp_expr
},
{
tmp_expr <- duckdb$expr_reference("g")
duckdb$expr_set_alias(tmp_expr, "g")
tmp_expr
},
{
tmp_expr <- duckdb$expr_function(
"if_else",
list(
duckdb$expr_function(
">",
list(
duckdb$expr_reference("a"),
if ("experimental" %in% names(formals(duckdb$expr_constant))) {
duckdb$expr_constant(1, experimental = experimental)
} else {
duckdb$expr_constant(1)
}
)
),
if ("experimental" %in% names(formals(duckdb$expr_constant))) {
duckdb$expr_constant("ok", experimental = experimental)
} else {
duckdb$expr_constant("ok")
},
if ("experimental" %in% names(formals(duckdb$expr_constant))) {
duckdb$expr_constant(NA, experimental = experimental)
} else {
duckdb$expr_constant(NA)
}
)
)
duckdb$expr_set_alias(tmp_expr, "d")
tmp_expr
}
)
)
rel2
out <- duckdb$rel_to_altrep(rel2)
expect_identical(
out,
data.frame(
a = seq(1, 6, by = 1),
b = rep(2, 6L),
g = c(1L, 2L, 2L, 3L, 3L, 3L),
d = rep(c(NA, "ok"), c(1L, 5L))
)
)
DBI::dbDisconnect(con, shutdown = TRUE)
})

# mutate order-enforcing ---------------------------------------------------------------

test_that("relational mutate() order-enforcing", {
Expand Down Expand Up @@ -13089,6 +13170,91 @@ test_that("relational mutate(d = NA_character_) order-enforcing", {
DBI::dbDisconnect(con, shutdown = TRUE)
})

test_that("relational mutate(d = if_else(a > 1, \"ok\", NA)) order-enforcing", {
# Autogenerated
duckdb <- asNamespace("duckdb")
drv <- duckdb::duckdb()
con <- DBI::dbConnect(drv)
experimental <- FALSE
invisible(
DBI::dbExecute(
con,
'CREATE MACRO "if_else"(test, yes, no) AS (CASE WHEN test THEN yes ELSE no END)'
)
)
invisible(duckdb$rapi_load_rfuns(drv@database_ref))
invisible(DBI::dbExecute(con, 'CREATE MACRO ">"(x, y) AS "r_base::>"(x, y)'))
df1 <- data.frame(a = seq(1, 6, by = 1), b = rep(2, 6L), g = c(1L, 2L, 2L, 3L, 3L, 3L))

rel1 <- duckdb$rel_from_df(con, df1, experimental = experimental)
rel2 <- duckdb$rel_project(
rel1,
list(
{
tmp_expr <- duckdb$expr_reference("a")
duckdb$expr_set_alias(tmp_expr, "a")
tmp_expr
},
{
tmp_expr <- duckdb$expr_reference("b")
duckdb$expr_set_alias(tmp_expr, "b")
tmp_expr
},
{
tmp_expr <- duckdb$expr_reference("g")
duckdb$expr_set_alias(tmp_expr, "g")
tmp_expr
},
{
tmp_expr <- duckdb$expr_function(
"if_else",
list(
duckdb$expr_function(
">",
list(
duckdb$expr_reference("a"),
if ("experimental" %in% names(formals(duckdb$expr_constant))) {
duckdb$expr_constant(1, experimental = experimental)
} else {
duckdb$expr_constant(1)
}
)
),
if ("experimental" %in% names(formals(duckdb$expr_constant))) {
duckdb$expr_constant("ok", experimental = experimental)
} else {
duckdb$expr_constant("ok")
},
if ("experimental" %in% names(formals(duckdb$expr_constant))) {
duckdb$expr_constant(NA, experimental = experimental)
} else {
duckdb$expr_constant(NA)
}
)
)
duckdb$expr_set_alias(tmp_expr, "d")
tmp_expr
}
)
)
rel3 <- duckdb$rel_order(
rel2,
list(duckdb$expr_reference("a"), duckdb$expr_reference("b"), duckdb$expr_reference("g"), duckdb$expr_reference("d"))
)
rel3
out <- duckdb$rel_to_altrep(rel3)
expect_identical(
out,
data.frame(
a = seq(1, 6, by = 1),
b = rep(2, 6L),
g = c(1L, 2L, 2L, 3L, 3L, 3L),
d = rep(c(NA, "ok"), c(1L, 5L))
)
)
DBI::dbDisconnect(con, shutdown = TRUE)
})

# relocate order-preserving ------------------------------------------------------------

test_that("relational relocate(g) order-preserving", {
Expand Down
3 changes: 3 additions & 0 deletions tools/00-funs.R
Expand Up @@ -668,6 +668,9 @@ test_extra_arg_map <- list(
"d = NA_real_",
"d = NA_character_",

# NA in use
'd = if_else(a > 1, "ok", NA)',

NULL
),
nest_join = "join_by(a)",
Expand Down

0 comments on commit bd739e6

Please sign in to comment.