---
title: "Data Sources"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{Data Sources}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
eval = FALSE
)
```
`querychat` supports several different data sources, including:
1. Data frames
2. DBI database connections (e.g., SQLite, PostgreSQL, MySQL, DuckDB)
3. [Pins](https://pins.rstudio.com/) boards
4. Custom `DataSource` interfaces
The sections below describe how to use each type of data source with `querychat`.
## Data frames
You can use any data frame as a data source in `querychat`. Simply pass it to `querychat()`:
```{r}
library(querychat)
library(palmerpenguins)
qc <- querychat(mtcars)
qc$app() # Launch the app
```
Behind the scenes, `querychat` creates an in-memory DuckDB database and registers your data frame as a table for SQL query execution.
## Database connections
You can also connect `querychat` directly to a table in any database supported by [DBI](https://dbi.r-dbi.org/). This includes popular databases like SQLite, DuckDB, PostgreSQL, MySQL, and many more.
Assuming you have a database set up and accessible, you can create a DBI connection and pass it to `querychat()`. Below are some examples for common databases.
### DuckDB
```{r}
library(DBI)
library(duckdb)
library(querychat)
# Connect to a DuckDB database file
con <- dbConnect(duckdb::duckdb(), dbdir = "my_database.duckdb")
qc <- querychat(con, "my_table")
qc$app() # Launch the app
# Don't forget to disconnect when done
# dbDisconnect(con)
```
### SQLite
```{r}
library(DBI)
library(RSQLite)
library(querychat)
# Connect to a SQLite database file
con <- dbConnect(RSQLite::SQLite(), "my_database.db")
qc <- querychat(con, "my_table")
qc$app() # Launch the app
# Don't forget to disconnect when done
# dbDisconnect(con)
```
### PostgreSQL
```{r}
library(DBI)
library(RPostgres)
library(querychat)
# Connect to PostgreSQL
con <- dbConnect(
RPostgres::Postgres(),
host = "localhost",
port = 5432,
dbname = "mydatabase",
user = "myuser",
password = "mypassword"
)
qc <- querychat(con, "my_table")
qc$app() # Launch the app
# Don't forget to disconnect when done
# dbDisconnect(con)
```
### MySQL
```{r}
library(DBI)
library(RMariaDB)
library(querychat)
# Connect to MySQL
con <- dbConnect(
RMariaDB::MariaDB(),
host = "localhost",
port = 3306,
dbname = "mydatabase",
user = "myuser",
password = "mypassword"
)
qc <- querychat(con, "my_table")
qc$app() # Launch the app
# Don't forget to disconnect when done
# dbDisconnect(con)
```
## Creating a database from a data frame
If you don't have a database set up, you can easily create a local DuckDB database from a data frame:
```{r}
library(DBI)
library(duckdb)
con <- dbConnect(duckdb::duckdb(), dbdir = "my_database.duckdb")
# Write a data frame to the database
dbWriteTable(con, "penguins", penguins)
# Or from CSV
duckdb::duckdb_read_csv(con, "my_table", "path/to/your/file.csv")
```
Then you can connect to this database using the DuckDB example above.
## Pins
You can pass a [pins](https://pins.rstudio.com/) board directly to `querychat()` with the pin name as `table_name`:
```{r}
library(pins)
library(querychat)
board <- board_connect()
qc <- querychat(board, "my_pin")
qc$app()
```
The pin is read and loaded into an in-memory DuckDB database, the same as data frames. For parquet, CSV, and JSON pins, the cached files go straight into DuckDB without R deserialization. Other pin types (e.g. RDS) go through `pin_read()` first.
If the pin has a title, description, or tags, querychat uses them as the default `data_description`, which you can override.
Pin names with special characters (like `"user.name/my_pin"`) are sanitized into valid SQL table names. To control the table name yourself, use `PinSource`:
```{r}
ps <- PinSource$new(board, "user.name/my_pin", table_name = "my_data")
qc <- querychat(ps)
```
### Lazy queries with pins
By default, the full dataset is materialized into DuckDB. For large parquet pins, you can skip that step by reading the pin files yourself and passing a `tbl_sql`:
```{r}
library(pins)
library(dplyr)
library(duckdb)
library(querychat)
board <- board_connect()
paths <- pin_download(board, "my_pin")
con <- dbConnect(duckdb::duckdb())
DBI::dbExecute(
con,
sprintf("CREATE VIEW my_pin AS SELECT * FROM read_parquet('%s')", paths[1])
)
qc <- querychat(tbl(con, "my_pin"))
qc$app()
```
The pin files are still downloaded to a local cache --- `pin_download()` always fetches them. But rather than loading everything into memory, DuckDB reads the parquet file lazily through dbplyr. This is not the same as a database-backed source, where data never leaves the server.
This approach skips the security lockdown that `PinSource` applies, so LLM-generated SQL can access files on the local system.
## Custom sources
If you have a custom data source that doesn't fit into the above categories, you can implement the `DataSource` interface.
See the [DataSource reference](../reference/DataSource.html) for more details on implementing this interface.