## ----include = FALSE----------------------------------------------------------
# The raw-SQL examples need Python sqlglot, so only evaluate chunks when
# the full stack is available. has_sqlglot() initializes Python, which lets
# reticulate provision an environment over the network, so it must not be
# called during a CRAN check; there the chunks render as unevaluated code.
can_eval <- identical(Sys.getenv("NOT_CRAN"), "true") &&
  requireNamespace("dplyr", quietly = TRUE) &&
  requireNamespace("dbplyr", quietly = TRUE) &&
  requireNamespace("duckdb", quietly = TRUE) &&
  tryCatch(dplyneage::has_sqlglot(), error = function(e) FALSE)

knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  eval = can_eval
)

## ----eval = FALSE-------------------------------------------------------------
# pak::pak("tgerke/dplyneage")

## ----message=FALSE------------------------------------------------------------
library(dplyneage)
library(dplyr)
library(duckdb)

con <- dbConnect(duckdb(), ":memory:")

customers <- tibble(
  id = 1:5,
  name = c("Alice", "Bob", "Charlie", "Diana", "Eve"),
  email = paste0(tolower(name), "@example.com")
)

orders <- tibble(
  order_id = 1:10,
  customer_id = rep(1:5, each = 2),
  amount = c(100, 150, 200, 75, 300, 125, 180, 90, 250, 160)
)

copy_to(con, customers, "customers", overwrite = TRUE)
copy_to(con, orders, "orders", overwrite = TRUE)

## -----------------------------------------------------------------------------
tbl(con, "customers") |>
  select(id, name) |>
  extract_lineage() |>
  lineage_flow(height = "300px")

## -----------------------------------------------------------------------------
tbl(con, "customers") |>
  left_join(tbl(con, "orders"), by = c("id" = "customer_id")) |>
  group_by(id, name) |>
  summarise(total_spent = sum(amount, na.rm = TRUE), .groups = "drop") |>
  extract_lineage() |>
  lineage_flow(height = "400px")

## -----------------------------------------------------------------------------
extract_lineage("
  WITH recent AS (
    SELECT customer_id, amount FROM orders WHERE order_date > '2024-01-01'
  )
  SELECT customer_id, SUM(amount) AS total FROM recent GROUP BY customer_id
") |>
  lineage_flow(height = "300px")

## -----------------------------------------------------------------------------
extract_lineage("
  SELECT COALESCE(u.email, a.email) AS email
  FROM users u FULL JOIN archive a ON u.id = a.id
") |>
  lineage_flow(height = "300px")

## -----------------------------------------------------------------------------
extract_lineage(
  "SELECT * FROM customers",
  schema = list(customers = c("id", "name", "email"))
) |>
  lineage_flow(height = "300px")

## -----------------------------------------------------------------------------
extract_lineage(
  "SELECT c.name, order_date
   FROM customers c JOIN orders o ON c.id = o.customer_id",
  schema = list(
    customers = c("id", "name", "email"),
    orders = c("order_id", "customer_id", "order_date", "amount")
  )
) |>
  lineage_flow(height = "300px")

## ----eval = FALSE-------------------------------------------------------------
# extract_lineage(query, dialect = "postgres")
# extract_lineage(query, dialect = "snowflake")

## ----eval = can_eval && requireNamespace("RSQLite", quietly = TRUE)-----------
sales <- dbplyr::memdb_frame(
  customer_id = c(1, 1, 2),
  amount = c(100, 250, 40),
  .name = "sales"
)

sales |>
  group_by(customer_id) |>
  summarise(total = sum(amount, na.rm = TRUE)) |>
  extract_lineage() |>
  lineage_flow(height = "300px")

## -----------------------------------------------------------------------------
nodes <- list(
  create_table_node(
    table_name = "customers",
    columns = c("id", "name", "email"),
    x = 0, y = 100,
    table_type = "source"
  ),
  create_table_node(
    table_name = "customer_summary",
    columns = c("customer_id", "full_name", "contact"),
    x = 500, y = 100,
    table_type = "target"
  )
)

edges <- list(
  create_column_edge("customers", "id", "customer_summary", "customer_id"),
  create_column_edge("customers", "name", "customer_summary", "full_name"),
  create_column_edge("customers", "email", "customer_summary", "contact")
)

lineage_flow(nodes, edges, height = "300px")

## -----------------------------------------------------------------------------
lineage <- tbl(con, "customers") |>
  left_join(tbl(con, "orders"), by = c("id" = "customer_id")) |>
  group_by(id, name) |>
  summarise(total_spent = sum(amount, na.rm = TRUE), .groups = "drop") |>
  extract_lineage()

lineage_json(lineage)

## ----eval = can_eval && requireNamespace("igraph", quietly = TRUE)------------
path <- tempfile(fileext = ".graphml")
lineage_graphml(lineage, path)

g <- igraph::read_graph(path, format = "graphml")

# Everything upstream of total_spent
igraph::subcomponent(g, "output.total_spent", mode = "in")

# Everything downstream of orders.amount
igraph::subcomponent(g, "orders.amount", mode = "out")

## ----include = FALSE----------------------------------------------------------
dbDisconnect(con)

