Skip to content

DB block

The DB block is a fenced markdown code block whose language is db-<connection-name>, where <connection-name> is a key from connections.toml. Each connection auto-registers its own block type.

```db-local
SELECT id, name FROM users LIMIT 10
```

The fence language is db-local because there’s a [connections.local] entry in connections.toml.

TypeConnection stringNotes
sqlitepath = "./file.sqlite"Auto-creates the file on first use
postgreshost, port, database, user, password, ssl_modesqlx postgres driver
mysqlhost, port, database, user, passwordsqlx mysql driver

See config-files for the full connections.toml schema.

TokenDefaultNotes
alias=<name>noneRequired for capture/chain ({{users.row[0].id}}).
timeout=<ms>60000Query timeout in milliseconds.
display=<mode>splitPanel layout (same as HTTP).

The fence language is the connection — there’s no separate connection= token.

{{...}} references in SQL body are always converted to bind parameters. They are never string-interpolated.

```db-local
SELECT * FROM orders
WHERE customer_id = {{user.body.id}}
AND status = {{filter.body.status}}
```

What the driver sees:

SELECT * FROM orders
WHERE customer_id = $1
AND status = $2

Bind values: [user.body.id, filter.body.status].

Zero SQL injection surface. Even with user-controlled values flowing in from HTTP responses, the driver’s prepared-statement binding handles type coercion and escaping.

When a block contains DELETE, UPDATE, INSERT, TRUNCATE, DROP, or ALTER, httui shows a confirmation banner before running:

⚠ This block contains UPDATE. Run anyway?

The guard is structural — httui parses the SQL with a scanner, not a regex on the first word. So:

  • UPDATE inside a -- comment is not flagged.
  • A DELETE buried after a SELECT in a multi-statement block is flagged.

Disable per-block via the toolbar gear → Skip mutation prompt (persisted per-block in the info-string). Best for runbooks you trust and run often.

You can put multiple SQL statements in one block, separated by semicolons:

```db-local
CREATE TEMP TABLE staging AS SELECT * FROM users WHERE active = false;
DELETE FROM staging WHERE created_at < unixepoch() - 30 * 86400;
SELECT count(*) FROM staging;
```

The mutation guard flags if any statement is destructive. Results come from the last statement only — the result grid shows the final SELECT’s rows.

The response panel has a virtualised grid for SELECT results:

  • Sortable column headers (click)
  • Type badge per column (int, text, jsonb, etc)
  • Copy-as-CSV button
  • Windowed rendering — 100k+ rows stay scrollable

For mutation blocks (INSERT/UPDATE/DELETE), the panel shows “N rows affected” + the elapsed time.

The first row of every result is the implicit “response” — chain into it from later blocks:

```db-local alias=users_list
SELECT id, email FROM users ORDER BY id LIMIT 1
```
```http
GET {{BASE_URL}}/users/{{users_list.row[0].id}}
```

Available fields on a DB block response:

FieldMeaning
row[N].<col>nth row’s column value
rowsfull result array (rare to chain on)
rows.lengthnumber of rows
affectedrows affected by mutation

Run any EXPLAIN ANALYZE (Postgres / MySQL) or EXPLAIN QUERY PLAN (SQLite) and the panel renders the plan as a tree view:

  • Sequential scans with high cost are highlighted red
  • Nested-loop joins with bad cardinality estimates are flagged
  • Right-click any node → Copy as TEXT for sharing

For connections where you need to SSH-tunnel locally but the shared connections.toml points at the production hostname, use the toolbar ⚙ Session override dialog:

host: 127.0.0.1
port: 15432

Override is session-only — not persisted to disk, applied per DB run. Base connection pool is untouched; httui creates an override-keyed pool for the override session. Useful for one-off tunnel work without editing .local.toml.

Same SHA-256 hash as HTTP blocks:

SQL text (after bind substitution) + bind values
+ env snapshot (only referenced vars)

Mutation statements (INSERT/UPDATE/DELETE/TRUNCATE/DROP/ALTER) are never cached — they always re-execute. SELECT results cache; clear via toolbar gear → Clear cache.

Click the Schema tab in the sidebar to browse the active connection’s schema — tables, columns with types, foreign keys, indexes, row count estimates.

Schemas are introspected on connection open + cached in notes.db. Click the refresh icon to re-introspect (useful after a migration).

Schema-aware autocomplete fires inside DB blocks: type a table name, get column suggestions; type a column name, get type info.

ShortcutAction
Cmd+EnterRun block
Cmd+.Cancel running query
Cmd+Shift+ERun as EXPLAIN (wraps the query)
MessageCauseFix
connection refusedDB not reachableCheck host/port, tunnel, firewall
relation "X" does not existWrong schema / search_pathUse fully-qualified name public.X
password authentication failedWrong credsUpdate via Environment manager (see secrets)
pool exhaustedToo many concurrent queries against same connReduce parallelism in Run-all