Skip to content

SQL and DuckDB

SQL cells run through DuckDB inside the notebook runtime. Register vault files from JavaScript/TypeScript cells, then query them from SQL cells with {{parameter}} placeholders.

These read-only tables expose vault metadata to SQL:

TableContents
lapis.notesNote paths, names, extensions
lapis.linksResolved internal links
lapis.search_documentsSearch-indexed document text

Example:

:::cell{#recent-notes lang="sql"}
```sql
SELECT path, name
FROM lapis.notes
ORDER BY name
LIMIT 10
```
:::

Register CSV, Parquet, or JSON files from a TypeScript cell:

:::cell{#register lang="ts"}
```ts
await lapis.duckdb.registerVaultFile("sales_csv", "./assets/sales.csv");
lapis.markdown("Registered `./assets/sales.csv` for SQL queries.");
```
:::
:::cell{#query lang="sql"}
```sql
SELECT month, amount
FROM read_csv_auto('sales_csv')
WHERE region = {{selectedRegion}}
ORDER BY month
```
:::

Paths are vault-relative. On desktop, native DuckDB can register files from the filesystem vault without copying large buffers through the renderer.

SQL cells can reference JavaScript variables with {{name}} syntax. Upstream cells must define those variables before the SQL cell runs.

Notebooks that use DuckDB run on the in-process runtime in the browser. Simple notebooks without DuckDB or live DOM can use the lighter worker runtime. The status bar tells you which path is active.