tests/testthat/test-duckdb.R

test_that("case-insensitive duplicates", {
  out <- duckdb_tibble(a = 1:2) %>%
    mutate(A = a + 1L, b = A - 1L)

  expect_identical(out$a, out$b)
})

test_that("rel_translate() records window function usage in has_window attribute", {
  df <- data.frame(a = 1:3, b = c(1, 1, 2))

  # A plain expression: no window
  expr_plain <- rel_translate(quote(a + 1L), df)
  expect_false(isTRUE(attr(expr_plain, "has_window")))

  # A window expression (via need_window = TRUE and .by context)
  expr_win <- rel_translate(quote(n()), df, partition = "b", need_window = TRUE)
  expect_true(isTRUE(attr(expr_win, "has_window")))

  # A non-window aggregate (need_window = FALSE)
  expr_agg <- rel_translate(quote(n()), df, need_window = FALSE)
  expect_false(isTRUE(attr(expr_agg, "has_window")))
})

test_that("mutate() uses oo_prep only when window functions are present", {
  withr::local_envvar(DUCKPLYR_OUTPUT_ORDER = "TRUE")

  df <- duckdb_tibble(a = 1:3, b = c(1, 1, 2))

  # Non-window expression: ___row_number should not appear
  rel_simple <- duckplyr:::duckdb_rel_from_df(df)
  rel_simple <- duckplyr:::oo_prep(rel_simple, force = FALSE)
  expect_false("___row_number" %in% duckplyr:::rel_names(rel_simple))

  # Window expression path goes through oo_prep: ___row_number appears
  rel_prepped <- duckplyr:::duckdb_rel_from_df(df)
  rel_prepped <- duckplyr:::oo_prep(rel_prepped, force = TRUE)
  expect_true("___row_number" %in% duckplyr:::rel_names(rel_prepped))

  # Full mutate with window function: result should be intact
  out <- df |> mutate(n = n(), .by = b)
  r <- collect(out)
  # group b==1 has 2 rows, group b==2 has 1 row
  expect_identical(r$n[r$b == 1], c(2L, 2L))
  expect_identical(r$n[r$b == 2], c(1L))
})

Try the duckplyr package in your browser

Any scripts or data that you put into this service are public.

duckplyr documentation built on March 10, 2026, 9:06 a.m.