Nothing
# Multi-database transaction tests
# Tests db_transaction(), connection_begin(), connection_commit(), connection_rollback()
# Helper aliases for internal functions used in tests
connection_insert <- framework:::connection_insert
connection_find <- framework:::connection_find
connection_begin <- framework:::connection_begin
connection_commit <- framework:::connection_commit
connection_rollback <- framework:::connection_rollback
connection_with_transaction <- framework:::connection_with_transaction
test_that("db_transaction() commits on success", {
skip_if_no_driver("RSQLite", "SQLite")
db_path <- tempfile(fileext = ".db")
conn <- DBI::dbConnect(RSQLite::SQLite(), db_path)
on.exit({
DBI::dbDisconnect(conn)
unlink(db_path)
})
# Create table
create_test_table(conn, "users", with_soft_delete = FALSE)
# Execute transaction
result <- db_transaction(conn, {
id1 <- connection_insert(conn, "users", list(name = "Alice", email = "alice@example.com", age = 30))
id2 <- connection_insert(conn, "users", list(name = "Bob", email = "bob@example.com", age = 25))
c(id1, id2)
})
# Verify both records inserted
expect_length(result, 2)
users <- DBI::dbGetQuery(conn, "SELECT * FROM users ORDER BY id")
expect_equal(nrow(users), 2)
expect_equal(users$name, c("Alice", "Bob"))
})
test_that("db_transaction() rolls back on error", {
skip_if_no_driver("RSQLite", "SQLite")
db_path <- tempfile(fileext = ".db")
conn <- DBI::dbConnect(RSQLite::SQLite(), db_path)
on.exit({
DBI::dbDisconnect(conn)
unlink(db_path)
})
# Create table
create_test_table(conn, "users", with_soft_delete = FALSE)
# Transaction that fails
expect_error({
db_transaction(conn, {
connection_insert(conn, "users", list(name = "Alice", email = "alice@example.com", age = 30))
stop("Intentional error")
connection_insert(conn, "users", list(name = "Bob", email = "bob@example.com", age = 25))
})
}, "Transaction failed and was rolled back")
# Verify no records inserted (rollback worked)
users <- DBI::dbGetQuery(conn, "SELECT * FROM users")
expect_equal(nrow(users), 0)
})
test_that("db_transaction() preserves return value", {
skip_if_no_driver("RSQLite", "SQLite")
db_path <- tempfile(fileext = ".db")
conn <- DBI::dbConnect(RSQLite::SQLite(), db_path)
on.exit({
DBI::dbDisconnect(conn)
unlink(db_path)
})
# Create table
create_test_table(conn, "users", with_soft_delete = FALSE)
# Transaction with return value
user_data <- db_transaction(conn, {
id <- connection_insert(conn, "users", list(name = "Alice", email = "alice@example.com", age = 30))
connection_find(conn, "users", id)
})
expect_s3_class(user_data, "data.frame")
expect_equal(nrow(user_data), 1)
expect_equal(user_data$name, "Alice")
})
test_that("Manual transaction control works", {
skip_if_no_driver("RSQLite", "SQLite")
db_path <- tempfile(fileext = ".db")
conn <- DBI::dbConnect(RSQLite::SQLite(), db_path)
on.exit({
DBI::dbDisconnect(conn)
unlink(db_path)
})
# Create table
create_test_table(conn, "users", with_soft_delete = FALSE)
# Manual transaction - commit
connection_begin(conn)
id <- connection_insert(conn, "users", list(name = "Alice", email = "alice@example.com", age = 30))
connection_commit(conn)
# Verify committed
users <- DBI::dbGetQuery(conn, "SELECT * FROM users")
expect_equal(nrow(users), 1)
# Manual transaction - rollback
connection_begin(conn)
connection_insert(conn, "users", list(name = "Bob", email = "bob@example.com", age = 25))
connection_rollback(conn)
# Verify rolled back (still only 1 user)
users <- DBI::dbGetQuery(conn, "SELECT * FROM users")
expect_equal(nrow(users), 1)
expect_equal(users$name, "Alice")
})
test_that("connection_with_transaction() works", {
skip_if_no_driver("RSQLite", "SQLite")
db_path <- tempfile(fileext = ".db")
conn <- DBI::dbConnect(RSQLite::SQLite(), db_path)
on.exit({
DBI::dbDisconnect(conn)
unlink(db_path)
})
# Create table
create_test_table(conn, "users", with_soft_delete = FALSE)
# Standalone - should create transaction
connection_with_transaction(conn, {
connection_insert(conn, "users", list(name = "Alice", email = "alice@example.com", age = 30))
})
# Verify inserted
expect_equal(nrow(DBI::dbGetQuery(conn, "SELECT * FROM users")), 1)
# Nested - should use existing transaction
db_transaction(conn, {
connection_with_transaction(conn, {
connection_insert(conn, "users", list(name = "Bob", email = "bob@example.com", age = 25))
})
connection_with_transaction(conn, {
connection_insert(conn, "users", list(name = "Charlie", email = "charlie@example.com", age = 35))
})
})
# Verify both inserted in same transaction
expect_equal(nrow(DBI::dbGetQuery(conn, "SELECT * FROM users")), 3)
})
test_that("Transactions work on PostgreSQL if available", {
skip_if_no_driver("RPostgres", "PostgreSQL")
config <- list(
driver = "postgres",
host = Sys.getenv("TEST_POSTGRES_HOST", "localhost"),
port = 5432,
database = "framework_test",
user = "framework",
password = "framework_test_pass"
)
conn <- tryCatch(.connect_postgres(config), error = function(e) NULL)
if (is.null(conn)) skip("PostgreSQL not available")
on.exit(DBI::dbDisconnect(conn))
# Create temp table
drop_test_table(conn, "test_transaction_users")
create_test_table(conn, "test_transaction_users", with_soft_delete = FALSE)
on.exit(drop_test_table(conn, "test_transaction_users"), add = TRUE)
# Test transaction
db_transaction(conn, {
connection_insert(conn, "test_transaction_users", list(name = "Alice", email = "alice@example.com", age = 30))
connection_insert(conn, "test_transaction_users", list(name = "Bob", email = "bob@example.com", age = 25))
})
# Verify both inserted
users <- DBI::dbGetQuery(conn, "SELECT * FROM test_transaction_users ORDER BY name")
expect_equal(nrow(users), 2)
expect_equal(users$name, c("Alice", "Bob"))
})
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.