## ----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")

