---
title: "Connection Management"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Connection Management}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
```

## The Problem

Database connections in R are stateful and can be easy to lose track of:

```r
con <- DBI::dbConnect(duckdb::duckdb(), dbdir = "data.duckdb")
tbl1 <- dplyr::tbl(con, "table1")
# ... 50 lines later: Is the connection still valid? Who closed it?
```

## dbProject's Solution

An R6 class that centralizes your connection and pinned tables:
```{r project-demo}
library(dbProject)

project_path <- tempfile("dbproject-")
proj <- dbProject$new(path = project_path)
expression_data <- data.frame(gene = c("A", "B"), count = c(10, 20))
proj$pin_write(expression_data, "expression_data")

# Later (even after R restart):
proj$reconnect()
my_tbl <- proj$pin_read("expression_data")
my_tbl
```

## DBI Compatibility

dbProject works alongside DBI, not instead of it:

| Approach | When to Use |
|----------|-------------|
| DBI directly | Quick scripts, one-off analysis |
| dbProject | Multi-session work, centralized management |

Both approaches get automatic reconnection via the `dbData` base class.

## Convenience Features

dbProject includes small convenience functions to help manage and organize
database connections in R.

`DBI::dbListTables()` is useful when you just need the table names in a
connection:

```{r dbi-list-tables}
con <- proj$get_conn()
DBI::dbWriteTable(
  con,
  "sample_metadata",
  data.frame(sample = c("sample1", "sample2"), n = c(100, 120)),
  overwrite = TRUE
)
DBI::dbExecute(
  con,
  "CREATE OR REPLACE TEMPORARY TABLE current_batch AS
   SELECT * FROM sample_metadata"
)
DBI::dbExecute(
  con,
  "CREATE OR REPLACE VIEW sample_summary AS
   SELECT sample, n FROM sample_metadata"
)

DBI::dbListTables(con)
```

`dbList()` keeps the same DBI connection but groups the results by table type,
which makes it easier to distinguish persistent tables from temporary tables and
views:

```{r dbproject-list-tables}
dbList(con)
```

## Core Concepts

### Mutable State (R6)

```r
proj <- dbProject$new(path = "my_analysis/")

# These modify the same object - no reassignment needed
proj$disconnect()
proj$reconnect()
proj$pin_write(my_tbl, "results")
```

### Centralized Management

```r
proj
#> ── dbProject ──────────────────────────────────────────
#> ✓ Connected
#> ── Board Content ──────────────────────────────────────
#>   name              type
#>   expression_data   tbl
#> ── Database Content ───────────────────────────────────
#> ℹ Tables: expression_raw, cell_types
```

### Automatic Reconnection

The empty extract `[]` method on all dbverse objects auto-reconnects if the connection is stale:

```r
mat[]  # Can be either a DBI connection or a dbProject connection
```

## Working with Pins

```r
proj$pin_write(my_tbl, "results")   # Save lazy table
my_tbl <- proj$pin_read("results") # Restore reference
proj$pin_delete("old_results")     # Clean up
```

```{r cleanup, include=FALSE}
proj$disconnect()
unlink(project_path, recursive = TRUE)
```
