Skip to content

Using the REPL ​

The REPL is quarry's command line. Start it by giving quarry a target without --tui:

sh
quarry postgres://me@localhost/app

The prompt ​

The default prompt takes two lines and tells you where you are:

╭─ PostgreSQL me@localhost:5432 ▸ app  TX  RO  ✓ 12.0 ms
╰─❯
  • TX appears while a transaction is open, and the ❯ changes colour.
  • RO appears in read-only mode.
  • ✓ 12.0 ms (or ✗) shows how the last statement went and how long it took.

You can replace it with your own format; see Prompt, keys and completion.

Running statements ​

With multi-line mode on (the default), Enter runs the buffer only when the statement is complete. Otherwise it starts a new line:

  • A statement ends with ;.
  • End it with \G instead to show that one result vertically.
  • Special commands (\dt, use db, describe t, status) run straight away.
  • Alt+Enter runs whatever is in the buffer, complete or not.

Several statements in one buffer run in order and stop at the first error. Semicolons inside strings, comments, $$ blocks and BEGIN … END bodies of triggers and procedures don't end the statement, so MySQL procedures work without changing the delimiter. If you prefer, delimiter // changes it, and delimiter ; restores it.

F3 toggles multi-line mode. With it off, Enter always runs the buffer.

Completion ​

A menu of suggestions opens as you type. Take the highlighted one with Tab, move with ↑ / ↓. Enter never picks a suggestion; it always runs the line.

What you get depends on where the cursor is:

WhereSuggestions
Start of a statementStatement keywords and special commands
After FROM, JOIN, INTO, UPDATETables, views, CTE names and schemas
In SELECT, WHERE and other expressionsColumns of the tables in the statement, then aliases, functions and keywords
After alias., table. or schema.That table's columns, or that schema's objects
SELECT * then TabThe full column list
After JOINWhole join clauses built from foreign keys: orders o ON o.user_id = u.id
After :: or CAST(… ASData types
After \i, \o, tee, .read and similarFile paths

Matching is fuzzy: ui finds user_id (initials of each word), and so does uid (letters in order). Exact prefixes rank first.

Grey text after the cursor is a suggestion from your history. Press → to accept it.

If completion gets in your way, F2 turns off the context awareness (you get every keyword, table and column, matched against the word you're typing), and complete_while_typing = false in the config opens the menu only on Tab.

Results ​

Results stream from the server and print as a table:

╭─────────┬────────╮
│ status  │ orders │
├─────────┼────────┤
│ paid    │    667 │
├─────────┼────────┤
│ shipped │    667 │
╰─────────┴────────╯
2 rows · 0.57 ms
  • Rows are separated by a line in the boxed formats; row_lines = false in the config turns that off.
  • Wide results (wider than the terminal) switch to vertical layout automatically: one framed record per row. \x cycles between on, off and auto; \x off keeps the table and the pager scrolls it sideways.
  • Long values are cut at 500 characters (max_field_width) and end with ….
  • Big results: past 1000 rows (row_limit), quarry asks before fetching the rest. Say no and it shows the first 1000 and cancels the query at the server.
  • Output that doesn't fit the screen goes through a pager, less -SRXF by default. \nopager turns it off, and \pager cmd picks another.
  • Formats: \T lists them and \T markdown switches. See Output formats.
  • Timing is shown after each result. \timing toggles it.

Server notices and warnings print before the result. Errors show the SQLSTATE or error number, and a caret under the failing position when the server reports one:

✗ ERROR 42703  column "nmae" does not exist

Ctrl+C while a query runs cancels it at the server: a cancel request on PostgreSQL, KILL QUERY on MySQL, an interrupt on SQLite.

History ​

Every statement you run is saved to ~/.local/share/quarry/history.txt (10,000 entries by default).

  • Ctrl+R searches it.
  • ↑ and ↓ step through it.
  • \history 20 prints the last 20.

Lines containing password, identified by, secret or encrypted are never saved.

Everyday special commands ​

Special commands start with \ and run immediately. On SQLite the familiar dot commands work too (.tables, .schema, .mode). The ones you'll use most:

CommandDoes
\?List every command. \? export filters the list.
\dt, \dv, \di, \dfList tables, views, indexes, functions. Add a pattern: \dt user*
\d nameDescribe a table: columns, indexes, keys, triggers. \d+ adds sizes and comments.
\lList databases
\c db / use dbSwitch database
\x, \T fmtVertical output, output format
\eEdit the last query in $EDITOR
\formatPretty-print the last query
\explain queryShow the plan as a tree. \explain analyze query runs it.
\watch 5 queryRe-run a query every 5 seconds, until Ctrl+C
\sConnection and server status
\qQuit (Ctrl+D works too)

The full list, with every alias and option, is in Special commands.

Editing in your editor ​

\e opens the last query you ran in $VISUAL or $EDITOR (vi by default). When you save and quit, the text comes back to the prompt for you to run. Type query \e to open a query you've just written instead, and \e file.sql to edit a file.

Sending results somewhere else ​

CommandResult goes to
\o fileThe next result goes to file instead of the screen
| commandThe next result is piped to a shell command, e.g. | wc -l
tee fileEvery result also goes to file until notee (-o overwrites instead of appending)
\export csv file queryThe complete result of query, written to file in any format
query \clipThe query text is copied to the clipboard

Switching to the TUI ​

\tui opens the full-screen interface on the same connection. Quitting the TUI ends quarry.

Released under the MIT licence.