## ----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(), "time_travel_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) ## ----create-datalake---------------------------------------------------------- # Install the ducklake extension (required once per system) # The ducklake extension only needs installing once per machine: # install_ducklake() # Create or attach to a data lake attach_ducklake( ducklake_name = "time_travel_demo", lake_path = vignette_temp_dir ) # Create initial table with the mtcars dataset with_transaction( create_table(mtcars, "cars"), author = "Data Engineer", commit_message = "Initial load of mtcars dataset" ) # Verify the table was created get_ducklake_table("cars") |> select(mpg, cyl, hp, wt) |> head() ## ----version1----------------------------------------------------------------- get_ducklake_table("cars") |> summarise( n_cars = n(), avg_mpg = mean(mpg, na.rm = TRUE), avg_hp = mean(hp, na.rm = TRUE) ) ## ----version2----------------------------------------------------------------- # Update mpg for high-performance cars (5% reduction) with_transaction( get_ducklake_table("cars") |> mutate(mpg = if_else(hp > 200, mpg * 0.95, mpg)) |> replace_table("cars"), author = "Data Analyst", commit_message = "Adjust MPG for high-performance vehicles" ) # Check the updated averages get_ducklake_table("cars") |> summarise( n_cars = n(), avg_mpg = mean(mpg, na.rm = TRUE), avg_hp = mean(hp, na.rm = TRUE) ) ## ----version3----------------------------------------------------------------- with_transaction( get_ducklake_table("cars") |> mutate( efficiency_class = case_when( mpg >= 25 ~ "High", mpg >= 20 ~ "Medium", TRUE ~ "Low" ) ) |> replace_table("cars"), author = "Data Analyst", commit_message = "Add efficiency classification" ) # View the new classification get_ducklake_table("cars") |> count(efficiency_class) |> arrange(desc(n)) ## ----version4----------------------------------------------------------------- with_transaction( get_ducklake_table("cars") |> mutate( efficiency_class = case_when( mpg >= 30 ~ "High", mpg >= 20 ~ "Medium", TRUE ~ "Low" ) ) |> replace_table("cars"), author = "Senior Analyst", commit_message = "Correct efficiency classification thresholds" ) # View the corrected classification get_ducklake_table("cars") |> count(efficiency_class) |> arrange(desc(n)) ## ----list-snapshots----------------------------------------------------------- # View all available versions of the table snapshots <- list_table_snapshots("cars") snapshots ## ----query-version2----------------------------------------------------------- # Get version 2 (after MPG adjustment, before classification) get_ducklake_table_version("cars", version = 2) |> select(mpg, cyl, hp, wt) |> head() # Notice: no efficiency_class column yet ## ----query-version3----------------------------------------------------------- # Get version 3 (with initial classification) get_ducklake_table_version("cars", version = 3) |> select(mpg, efficiency_class) |> count(efficiency_class) ## ----timestamp-query---------------------------------------------------------- # Get the timestamp from version 2 version2_timestamp <- snapshots |> filter(schema_version == 2) |> pull(snapshot_time) # Query data as it existed at that time # Note: Add 1 second to ensure we query AFTER the snapshot was created get_ducklake_table_asof("cars", version2_timestamp + 1) |> summarise( avg_mpg = mean(mpg, na.rm = TRUE) ) ## ----compare-versions--------------------------------------------------------- # Get MPG values from version 1 (original) and version 2 (after adjustment) original <- get_ducklake_table_version("cars", version = 1) |> select(mpg) |> collect() |> mutate(version = "Original") adjusted <- get_ducklake_table_version("cars", version = 2) |> select(mpg) |> collect() |> mutate(version = "Adjusted") # Combine and compare bind_rows(original, adjusted) |> group_by(version) |> summarise( avg_mpg = mean(mpg, na.rm = TRUE), min_mpg = min(mpg), max_mpg = max(mpg) ) ## ----restore-demo------------------------------------------------------------- # Go back to version 2 (before adding classifications) restore_table_version("cars", version = 2, author = "Senior Analyst") # Verify the restoration - efficiency_class column should be gone get_ducklake_table("cars") |> colnames() ## ----after-restore------------------------------------------------------------ list_table_snapshots("cars") ## ----pinned-attach, eval=FALSE------------------------------------------------ # attach_ducklake( # "cars_milestone", # lake_path = "~/data/lake", # snapshot_version = 2 # ) ## ----metadata----------------------------------------------------------------- # Get detailed snapshot history with all metadata snapshot_history <- list_table_snapshots("cars") snapshot_history |> select(snapshot_id, snapshot_time, author, commit_message) ## ----all-metadata------------------------------------------------------------- # View metadata for all tables all_snapshots <- list_table_snapshots() all_snapshots |> select(snapshot_id, snapshot_time, changes) |> head(10) ## ----cleanup, include=FALSE--------------------------------------------------- detach_ducklake("time_travel_demo")