## ----include = FALSE---------------------------------------------------------- # Evaluate chunks only where the ducklake DuckDB extension is already # installed. The probe never downloads anything, so building this vignette # needs no network access. ducklake_available <- ducklake::ducklake_extension_available() knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = ducklake_available ) # Use a unique temp directory for this vignette to avoid conflicts during R CMD check vignette_temp_dir <- file.path(tempdir(), "transactions_vignette") dir.create(vignette_temp_dir, showWarnings = FALSE, recursive = TRUE) knitr::opts_knit$set(root.dir = vignette_temp_dir) ## ----setup, message=FALSE----------------------------------------------------- library(ducklake) library(dplyr) # Setup for examples # The ducklake extension only needs installing once per machine: # install_ducklake() attach_ducklake("transactions_lake", lake_path = vignette_temp_dir) ## ----load-data---------------------------------------------------------------- # Load initial data with_transaction( create_table(mtcars, "cars"), author = "Tutorial", commit_message = "Initial load of mtcars dataset" ) # View the data get_ducklake_table("cars") |> select(mpg, cyl, hp, wt) |> head() ## ----with-transaction-single-------------------------------------------------- # Add a new column with automatic metadata tracking with_transaction( get_ducklake_table("cars") |> mutate(kpl = mpg * 0.425144) |> replace_table("cars"), author = "Data Team", commit_message = "Add kilometers per liter column" ) # Verify the change get_ducklake_table("cars") |> select(mpg, kpl) |> head() ## ----with-transaction-multiple------------------------------------------------ # Multiple related changes in one atomic transaction with_transaction({ # Add efficiency rating get_ducklake_table("cars") |> mutate( efficiency = case_when( mpg >= 25 ~ "high", mpg >= 20 ~ "medium", TRUE ~ "low" ) ) |> replace_table("cars") # Create a summary table get_ducklake_table("cars") |> group_by(cyl) |> summarize( avg_mpg = mean(mpg, na.rm = TRUE), avg_hp = mean(hp, na.rm = TRUE), count = n() ) |> create_table("cars_summary") }, author = "Data Team", commit_message = "Add efficiency ratings and summary table") # View results get_ducklake_table("cars") |> select(mpg, cyl, efficiency) |> head() get_ducklake_table("cars_summary") |> collect() ## ----with-transaction-error--------------------------------------------------- # This transaction will fail and automatically rollback tryCatch( with_transaction({ # This will succeed get_ducklake_table("cars") |> mutate(test_column = "temporary") |> replace_table("cars") # This will fail stop("Simulated error - something went wrong!") }, author = "Data Team", commit_message = "This will be rolled back"), error = function(e) { message("Transaction automatically rolled back: ", e$message) } ) # Verify that test_column was NOT added (transaction was rolled back) get_ducklake_table("cars") |> colnames() # View all versioned changes list_table_snapshots("cars") ## ----manual-basic------------------------------------------------------------- # Start a transaction begin_transaction() # Make changes get_ducklake_table("cars") |> mutate(weight_kg = wt * 453.592) |> replace_table("cars") # Commit the changes with metadata commit_transaction( author = "Data Team", commit_message = "Add weight in kg" ) # Verify changes get_ducklake_table("cars") |> filter(cyl == 4) |> select(wt, weight_kg) |> head() ## ----manual-rollback---------------------------------------------------------- # Start a transaction begin_transaction() # Make a test change get_ducklake_table("cars") |> mutate(test_flag = TRUE) |> replace_table("cars") # Check the result test_result <- get_ducklake_table("cars") |> select(mpg, test_flag) |> head() |> collect() print(test_result) # Decide to rollback rollback_transaction() # Verify the change was NOT applied "test_flag" %in% colnames(get_ducklake_table("cars")) # View all versioned changes list_table_snapshots("cars") ## ----metadata-at-commit------------------------------------------------------- # Metadata set at commit time (preferred approach) begin_transaction() get_ducklake_table("cars") |> mutate(hp_per_liter = hp / (cyl * 0.5)) |> replace_table("cars") commit_transaction( author = "Performance Team", commit_message = "Add horsepower per liter metric", commit_extra_info = '{"ticket": "DATA-123"}' ) get_ducklake_table("cars") |> select(hp, cyl, hp_per_liter) |> head() ## ----metadata-after-fact------------------------------------------------------ # Retrospectively update metadata on the last snapshot set_snapshot_metadata( ducklake_name = "transactions_lake", author = "Performance Team (reviewed)", commit_message = "Add horsepower per liter metric (approved)" ) ## ----view-history------------------------------------------------------------- # View recent transaction history list_table_snapshots("cars") |> select(snapshot_id, snapshot_time, author, commit_message) |> tail(5) ## ----cleanup, include=FALSE--------------------------------------------------- detach_ducklake("transactions_lake")