Nothing
os <- function() {
ostype <- .Platform[["OS.type"]]
if (ostype == "windows") {
return("windows")
}
if (grepl("darwin", R.Version()$os)) {
return("osx")
}
ostype
}
# Specific to RSQLite
test_that("can connect to memory database (#140)", {
expect_true(
dbDisconnect(dbConnect(SQLite(), ":memory:"))
)
})
# Specific to RSQLite
test_that("invalid dbnames throw errors", {
expect_error(dbConnect(SQLite(), dbname = 1:3))
expect_error(dbConnect(SQLite(), dbname = c("a", "b")))
expect_error(dbConnect(SQLite(), dbname = NA))
expect_error(dbConnect(SQLite(), dbname = as.character(NA)))
})
# Specific to RSQLite
test_that("can get and set vfs values", {
allowed <- switch(os(),
osx = c("unix-posix", "unix-afp", "unix-flock", "unix-dotfile", "unix-none"),
unix = c("unix-dotfile", "unix-none"),
windows = character(0),
character(0)
)
checkVfs <- function(v) {
force(v)
db <- dbConnect(SQLite(), vfs = v)
on.exit(dbDisconnect(db))
expect_equal(v, db@vfs)
}
for (v in allowed) checkVfs(v)
})
# Specific to RSQLite
test_that("forbidden operations throw errors", {
tmpFile <- tempfile()
on.exit(unlink(tmpFile))
## error if file does not exist
expect_error(dbConnect(SQLite(), tmpFile, flags = SQLITE_RO), "unable to open")
expect_error(dbConnect(SQLite(), tmpFile, flags = SQLITE_RW), "unable to open")
dbrw <- dbConnect(SQLite(), tmpFile, flags = SQLITE_RWC)
df <- data.frame(a = letters, b = runif(26L), stringsAsFactors = FALSE)
expect_true(dbWriteTable(dbrw, "t1", df))
dbDisconnect(dbrw)
dbro <- dbConnect(SQLite(), dbname = tmpFile, flags = SQLITE_RO)
expect_error(dbWriteTable(dbro, "t2", df), "readonly database")
dbDisconnect(dbro)
dbrw2 <- dbConnect(SQLite(), dbname = tmpFile, flags = SQLITE_RW)
expect_true(dbWriteTable(dbrw2, "t2", df))
dbDisconnect(dbrw2)
})
test_that("querying closed connection throws error", {
db <- dbConnect(SQLite(), dbname = ":memory:")
dbDisconnect(db)
expect_error(
dbGetQuery(db, "select * from foo"),
"Invalid or closed connection",
fixed = TRUE
)
})
test_that("can connect to same db from multiple connections", {
dbfile <- tempfile()
con1 <- dbConnect(SQLite(), dbfile)
con2 <- dbConnect(SQLite(), dbfile)
on.exit(dbDisconnect(con2), add = TRUE)
on.exit(dbDisconnect(con1), add = TRUE)
dbWriteTable(con1, "airquality", airquality)
expect_equal(dbReadTable(con2, "airquality"), airquality)
})
test_that("temporary tables are connection local", {
dbfile <- tempfile()
con1 <- dbConnect(SQLite(), dbfile)
con2 <- dbConnect(SQLite(), dbfile)
on.exit(dbDisconnect(con2), add = TRUE)
on.exit(dbDisconnect(con1), add = TRUE)
dbExecute(con1, "CREATE TEMPORARY TABLE temp (a TEXT)")
expect_true(dbExistsTable(con1, "temp"))
expect_false(dbExistsTable(con2, "temp"))
})
test_that("busy_handler", {
dbfile <- tempfile()
con1 <- dbConnect(SQLite(), dbfile)
con2 <- dbConnect(SQLite(), dbfile)
on.exit(dbDisconnect(con2), add = TRUE)
on.exit(dbDisconnect(con1), add = TRUE)
num <- NULL
cb <- function(n) {
num <<- n
if (n >= 5) 0L else 1L
}
sqliteSetBusyHandler(con2, cb)
dbExecute(con1, "BEGIN IMMEDIATE")
expect_error(dbExecute(con2, "BEGIN IMMEDIATE"), "database is locked")
expect_equal(num, 5L)
})
test_that("error in busy handler", {
dbfile <- tempfile()
con1 <- dbConnect(SQLite(), dbfile)
con2 <- dbConnect(SQLite(), dbfile)
on.exit(dbDisconnect(con2), add = TRUE)
on.exit(dbDisconnect(con1), add = TRUE)
cb <- function(n) stop("oops")
sqliteSetBusyHandler(con2, cb)
dbExecute(con1, "BEGIN IMMEDIATE")
expect_error(
expect_message(
dbExecute(con2, "BEGIN IMMEDIATE"),
"Busy callback failed, aborting.*oops"
),
"database is locked"
)
# con1 is still fine of course
dbWriteTable(con1, "mtcars", mtcars)
dbExecute(con1, "COMMIT")
# but con2 is fine as well
dbExecute(con2, "BEGIN IMMEDIATE")
expect_silent(dbGetQuery(con2, "SELECT * FROM mtcars"))
dbExecute(con2, "COMMIT")
})
test_that("interrupt in busy handler", {
skip_on_cran()
skip_if(getRversion() < "4.0")
dbfile <- tempfile()
con1 <- dbConnect(SQLite(), dbfile)
on.exit(dbDisconnect(con1), add = TRUE)
# This test makes use of the installed package!
session <- callr::r_session$new()
session$run(args = list(dbfile = dbfile), function(dbfile) {
.GlobalEnv$con2 <- DBI::dbConnect(RSQLite::SQLite(), dbfile)
cb <- function(n) {
message(n)
Sys.sleep(10)
1L
}
RSQLite::sqliteSetBusyHandler(.GlobalEnv$con2, cb)
})
dbExecute(con1, "BEGIN IMMEDIATE")
expect_equal(session$get_state(), "idle")
session$call(function() {
tryCatch(
DBI::dbExecute(.GlobalEnv$con2, "BEGIN IMMEDIATE"),
error = function(e) {
writeLines("caught error")
}
)
writeLines("done")
})
expect_equal(session$poll_process(200), "timeout")
expect_equal(session$get_state(), "busy")
expect_true(session$interrupt())
expect_equal(session$poll_process(2000), "ready")
out <- session$read()
expect_equal(out$code, 200)
expect_equal(gsub("\r", "", out$stdout), "caught error\ndone\n")
expect_equal(session$get_state(), "idle")
# con1 is still fine of course
dbWriteTable(con1, "trees", trees)
dbExecute(con1, "COMMIT")
# but con2 is fine as well
trees_out <- expect_silent(session$run(function() {
DBI::dbExecute(.GlobalEnv$con2, "BEGIN IMMEDIATE")
out <- DBI::dbGetQuery(.GlobalEnv$con2, "SELECT * FROM trees")
DBI::dbExecute(.GlobalEnv$con2, "COMMIT")
out
}))
expect_equal(trees, trees_out)
})
test_that("busy_handler timeout", {
skip_on_cran()
dbfile <- tempfile()
con1 <- dbConnect(SQLite(), dbfile)
con2 <- dbConnect(RSQLite::SQLite(), dbfile)
on.exit(dbDisconnect(con1), add = TRUE)
on.exit(dbDisconnect(con2), add = TRUE)
sqliteSetBusyHandler(con2, 200L)
dbExecute(con1, "BEGIN IMMEDIATE")
{
# {} is to not mess up the timing when copy-pasting this interactively
tic <- Sys.time()
err <- tryCatch(dbExecute(con2, "BEGIN IMMEDIATE"), error = identity)
time <- Sys.time() - tic
}
expect_match(conditionMessage(err), "database is locked")
expect_true(time >= as.difftime(0.2, units = "secs"))
expect_true(time < as.difftime(1.0, units = "secs"))
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.