tests/testthat/test-tmp_conn.R

testthat::skip_on_cran()

test_that("ddbs_temp_conn: default in-memory connection", {
  conn <- ddbs_temp_conn()
  expect_true(DBI::dbIsValid(conn))
  # dbdir is NULL for in-memory connections in this environment
  expect_true(is.null(DBI::dbGetInfo(conn)$dbdir) || DBI::dbGetInfo(conn)$dbdir == ":memory:")
  
  # Auto-close check
  get_conn <- function() {
    c <- ddbs_temp_conn()
    c
  }
  ret_conn <- get_conn()
  expect_false(DBI::dbIsValid(ret_conn))
})

test_that("ddbs_temp_conn: file-based temporary connection", {
  conn <- ddbs_temp_conn(file = TRUE)
  expect_true(DBI::dbIsValid(conn))
  
  db_file <- attr(conn, "db_file")
  expect_true(is.character(db_file))
  expect_true(file.exists(db_file))
  
  # Cleanup check
  get_file_status <- function() {
    c <- ddbs_temp_conn(file = TRUE)
    f <- attr(c, "db_file")
    list(conn = c, file = f)
  }
  status <- get_file_status()
  expect_false(DBI::dbIsValid(status$conn))
  expect_false(file.exists(status$file))
})

test_that("ddbs_temp_conn: custom file path", {
  custom_path <- tempfile(fileext = ".myduck")
  conn <- ddbs_temp_conn(file = custom_path)
  expect_true(DBI::dbIsValid(conn))
  expect_equal(attr(conn, "db_file"), custom_path)
  expect_true(file.exists(custom_path))
  
  # Manual cleanup trigger (by exiting scope)
  # Use a separate path to avoid locking issues on Windows with the still-open 'conn'
  custom_path_cleanup <- tempfile(fileext = ".myduck_cleanup")
  test_custom_cleanup <- function(path) {
    c <- ddbs_temp_conn(file = path)
  }
  test_custom_cleanup(custom_path_cleanup)
  expect_false(file.exists(custom_path_cleanup))
  
  # Ensure we close the original connection too, safely
  if (DBI::dbIsValid(conn)) DBI::dbDisconnect(conn, shutdown = TRUE)
})

test_that("ddbs_temp_conn: custom path with cleanup = FALSE", {
  custom_path <- tempfile(fileext = ".duckdb")
  
  test_no_cleanup <- function(path) {
    c <- ddbs_temp_conn(file = path, cleanup = FALSE)
    DBI::dbExecute(c, "CREATE TABLE t(id INT)")
  }
  
  test_no_cleanup(custom_path)
  
  # File should STILL exist
  expect_true(file.exists(custom_path))
  expect_false(file.exists(paste0(custom_path, ".wal")))
  
  # Verify we can connect to it
  c2 <- ddbs_create_conn(custom_path)
  expect_true("t" %in% DBI::dbListTables(c2))
  ddbs_stop_conn(c2)
  
  # Clean up manually
  unlink(custom_path)
})

test_that("ddbs_temp_conn: read_only file connection", {
  # Create a file first
  base_path <- tempfile(fileext = ".base")
  c1 <- DBI::dbConnect(duckdb::duckdb(), dbdir = base_path)
  DBI::dbExecute(c1, "CREATE TABLE t(id INT)")
  DBI::dbDisconnect(c1, shutdown = TRUE)
  
  # Use ddbs_temp_conn as read-only
  test_ro <- function(path) {
    c <- ddbs_temp_conn(file = path, read_only = TRUE, cleanup = FALSE)
    expect_error(DBI::dbExecute(c, "INSERT INTO t VALUES (1)"), "read-only")
  }
  test_ro(base_path)
  
  unlink(base_path)
})

test_that("ddbs_temp_conn: read_only with file=TRUE creates file first (regression)", {
  # Regression test: Previously failed because DuckDB can't open non-existent
  # files in read-only mode. The fix creates the file first, then opens as read-only.
  test_tempfile_readonly <- function() {
    conn <- ddbs_temp_conn(file = TRUE, read_only = TRUE, cleanup = FALSE)
    
    # Verify connection is valid
    expect_true(DBI::dbIsValid(conn))
    
    # Verify it's actually read-only by attempting a write operation
    expect_error(
      DBI::dbExecute(conn, "CREATE TABLE should_fail (id INT)"),
      "read-only"
    )
    
    # Verify spatial extension is loaded and works
    # result <- DBI::dbGetQuery(conn, "SELECT ST_Point(0, 0) as geom;")
    result <- DBI::dbGetQuery(conn, "SELECT ST_AsWKB(ST_Point(0, 0)) as geom;")
    expect_equal(nrow(result), 1)
    
    # Cleanup
    db_file <- attr(conn, "db_file")
    DBI::dbDisconnect(conn, shutdown = TRUE)
    unlink(db_file)
  }
  
  test_tempfile_readonly()
})

Try the duckspatial package in your browser

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

duckspatial documentation built on June 22, 2026, 9:08 a.m.