bobstanton3k downloadsExecute SELECT, INSERT, UPDATE, and DELETE statements on notes, properties, tasks, tables, headings and links using SQL and SQLite.
Query and update notes using SQL. Display results as a table, chart, calendar, or using JavaScript.
Documentation site: https://vaultquery.stanton.dev/
Web sandbox: https://sandbox.obsidian.stanton.dev/
| Code Block | Description |
|---|---|
vaultquery |
Execute SQL queries, display results in SlickGrid or JavaScript rendering |
vaultquery-nl |
Turn a natural-language request into a query or visualization |
vaultquery-write |
Execute INSERT, UPDATE, DELETE with before/after preview |
vaultquery-chart |
Render query results as Chart.js visualizations |
vaultquery-chart-help |
Display chart output reference and examples |
vaultquery-calendar |
Render query results as a FullCalendar calendar |
vaultquery-markdown |
Render query results as a markdown table |
vaultquery-markdown-help |
Display markdown output reference and examples |
vaultquery-calendar-help |
Display calendar output reference and examples |
vaultquery-schema |
Display database schema documentation |
vaultquery-view |
Define reusable SQL views |
vaultquery-function |
Define custom SQL functions in JavaScript |
vaultquery-help |
Display built-in help documentation |
vaultquery-function-help |
Display function reference |
vaultquery-examples |
Display example collections |
vaultquery-api-help |
API guide for third-party plugin developers |
Add a vaultquery code block with a SQL query:
```vaultquery
SELECT title, path, modified FROM notes
WHERE content LIKE '%important%'
ORDER BY modified DESC
LIMIT 10
```
Results render in a sortable SlickGrid table.
Use vaultquery-help for in-app help and vaultquery-schema for available tables and columns.
See write limits and failure handling.
Use vaultquery-write to preview and apply changes:
```vaultquery-write
-- Add a new note
INSERT INTO notes (path, content)
VALUES ('Condo Notes.md', '# Shopping List for new Condo');
-- Add a new task
INSERT INTO tasks (path, task_text, status)
VALUES ('Condo Notes.md', 'Buy plasma TV', 'TODO');
-- Add a new tag
INSERT INTO tags (path, tag_name)
VALUES ('Condo Notes.md', 'party-pad');
-- Add a new link
INSERT INTO links (path, link_target)
VALUES ('Condo Notes.md', 'Office/Dinner Party Plan.md');
-- Add a heading at a specific line
INSERT INTO headings (path, level, heading_text, line_number)
VALUES ('Condo Notes.md', 2, 'Sliding glass door repair quotes:', 4);
-- Add a tag at the start of a line
INSERT INTO tags (path, tag_name, line_number, insert_position)
VALUES ('Condo Notes.md', 'fake-overtime-assignment', 3, 'line_end');
-- Create a new table at a specific line using table_rows view
INSERT INTO table_rows (path, table_index, row_json, table_line_number)
VALUES ('Condo Notes.md', 1, json('{"Vendor": "", "Price": ""}'), 5);
```
```vaultquery-write
WITH
-- Select all notes in the Projects folder
project_notes AS (
SELECT path, title FROM notes
WHERE path LIKE 'Projects/%'
ORDER BY title
),
-- Create a flattened list of links to those notes
flattenedLinks AS (
SELECT GROUP_CONCAT('- ' || link(path, title), '\n') as list
FROM project_notes
)
-- Create an index linking to each note in the Projects folder
INSERT INTO notes (path, content)
SELECT
'Projects/Index.md',
'# Project Index
' || COALESCE(list, '_No projects found_')
FROM flattenedLinks;
```
```vaultquery-write
UPDATE notes
SET content = content || '\n\nList condo on eBay at 80% of purchase price.'
WHERE path = 'Condo Notes.md'
```
```vaultquery-write
DELETE FROM notes
WHERE path = 'Condo Notes.md'
```
Use vaultquery-markdown to render query results as a Markdown table.
```vaultquery-markdown
SELECT title, path, modified FROM notes
WHERE content LIKE '%important%'
ORDER BY modified DESC
LIMIT 10
```
Configure the markdown output with a config: section:
```vaultquery-markdown
SELECT title, path, size
FROM notes
ORDER BY size DESC
LIMIT 10;
config:
alignment: left, left, right
```
Available config options:
alignment: Column alignments (left, center, right)```vaultquery
SELECT title, path, modified FROM notes
WHERE content LIKE '%important%'
ORDER BY modified DESC
LIMIT 10;
template:
return `
<div>
<h3>Important Notes (${count} results)</h3>
<ul>
${results.map(note => `
<li>
${h.link(note.path, note.title)} -
<em>${h.formatDate(note.modified)}</em>
</li>
`).join('')}
</ul>
</div>
`;
```
JavaScript rendering code receives these variables:
results - Array of query result rowsquery - The SQL query that was executedcount - Number of resultsh - Helper functions objectUse inline code in the form vq{SQL} to render the first column of the first row directly in surrounding text:
The hike was `vq{SELECT value FROM properties WHERE key = 'distance' AND path = '{this.path}' LIMIT 1}` miles.
Inline query values are read-only and only allow SELECT or WITH statements.
vaultquery:query runs SQL from the Obsidian CLI and waits for indexing to finish before executing:
obsidian vaultquery:query sql="SELECT title, path FROM notes LIMIT 5" format=json
Available formats are json, csv, tsv, md, and scalar. Use path to provide note context for {this.*} placeholders:
obsidian vaultquery:query path="Hikes/Trip.md" sql="SELECT value FROM properties WHERE path = '{this.path}' AND key = 'distance' LIMIT 1" format=scalar
See the helper reference.
| Table/View | INSERT | UPDATE | DELETE |
|---|---|---|---|
| notes | Creates files | Modifies files | Deletes files |
| notes_with_properties | Creates with frontmatter | Modifies all | Deletes files |
| tasks | Adds tasks | Modifies tasks | Removes tasks |
| headings | Adds headings | Modifies text | Removes headings |
| list_items | Adds items | Modifies items | Removes items |
| properties | Adds to YAML | Modifies YAML | Removes from YAML |
| table_cells | Adds cells(2) | Modifies cells | Removes cells |
| table_rows | Adds rows(2) | Modifies rows | Removes rows |
| tags | Frontmatter or inline(1) | Renames tags | Removes tags |
| links | Appends or at line(1) | Updates links | Removes links |
(1)With line_number and optional insert_position (new_line, line_start, line_end)
(2)With line_number (table_cells) or table_line_number (table_rows) to position new tables
Write behavior:
tasks, headings, list_items INSERT at specified line_number or end of file (line-based elements)tags INSERT adds to frontmatter when no line_number specified, or inserts inline with insert_positionlinks INSERT appends to end of file when no line_number specified, or inserts at position with insert_positiontable_cells and table_rows INSERT can use line_number/table_line_number to create tables at specific positionsnotes_with_properties creates files with frontmatter in one operationnote_properties is for properties-only queries; use notes_with_properties or properties to write frontmattertable_rows handles table row manipulation with JSONUse vaultquery-chart to render query results as a chart. Query must use label and value columns (or x/y for scatter). Add a series column for multiple datasets.
| Option | Description |
|---|---|
type |
Chart type: bar, line, pie, doughnut, or scatter (required) |
title |
Chart title displayed above the chart |
datasetLabel |
Legend label for the dataset |
xLabel |
X-axis label (bar, line, scatter only) |
yLabel |
Y-axis label (bar, line, scatter only) |
datasetBackgroundColor |
Fill color for bars/points |
datasetBorderColor |
Border color for bars/points |
| Column | Description |
|---|---|
backgroundColor |
Per-point fill color |
borderColor |
Per-point border color |
chartType |
Per-series chart type for mixed charts (bar, line) |
See chart examples for colors, multiple series, and mixed charts.
See the API guide for queries, writes, functions, and provider tables.
// Get the VaultQuery API
const vaultQuery = this.app.plugins.getPlugin('vaultquery');
if (vaultQuery?.api) {
// Wait for indexing to complete
await vaultQuery.api.waitForIndexing();
// Execute queries
const results = await vaultQuery.api.query('SELECT * FROM notes LIMIT 10');
// Register custom functions
vaultQuery.api.registerCustomFunction('myFunc', 'function(x) { return x * 2; }');
}
The vaultquery-api-help code block provides complete API documentation in any note.
The database is stored in Obsidian's Configuration Folder in /plugins/vaultquery/database.db when using disk storage.
If a grid disappears after scrolling, use its refresh button. Column widths reset when Obsidian restarts.
See external folders for supported platforms and file types.
Network requests depend on enabled features:
| Package | URL | Purpose |
|---|---|---|
| VaultQuery | https://cdn.jsdelivr.net/npm/sql.js@<version>/dist/sql-wasm.wasm |
Downloads the WASM for the sql.js version installed when this plugin was built. |
| VaultQuery | The provider URL configured in settings | Translates a natural language request into SQL and selects a VaultQuery output. Sends the database schema description, known property names, and the natural language request, plus failed SQL and error messages when a generated statement is retried. |
| VaultQuery | The HTTPS URL in a vaultquery-remote-csv or vaultquery-web-json block |
Downloads a read-only CSV or JSON snapshot during discovery or refresh. Requests contain the source URL and optional cache validators; vault contents are not uploaded. |
SQL.js loading modes:
| Mode | Behavior | Network activity |
|---|---|---|
Auto |
Loads the versioned cache or custom path, then downloads that build's sql.js WASM. | Only if the local file is missing. |
Local only |
Loads sql-wasm.wasm from the plugin folder or custom path. |
None. Initialization fails if the file is unavailable. |
CDN only |
Downloads that build's exact sql.js version from jsDelivr. | One request during database initialization. |