Skip to content

SQL editor ​

中文

Each query tab holds its own editor buffer. The editor highlights real SQL via tree-sitter, indents with 2 spaces, and shows line numbers.

Tabs ​

ControlWhat it does
+ or ⌘TAppends a new query tab and focuses it
Click a tabSwitches to it
Ctrl+Tab / Ctrl+Shift+TabThe next / previous tab
⌘1 … ⌘8, ⌘9The first to eighth tab; ⌘9 is the last tab
Drag a tabMoves it along the strip
×, ⌘W or a middle clickCloses a tab. The last tab cannot be closed: its × is hidden and ⌘W does nothing. A dashboard with unsaved edits asks first
Right-click a tabClose tab, Close other tabs, Close tabs to the right. Dashboards with unsaved edits stay open, and a notice says how many
Double-click a tabEdits its title in place. Enter or clicking away keeps the new title, Escape keeps the old one; an empty title falls back to Query N

Open tabs come back on the next launch, in their order: query tabs with their titles and the SQL in their editors, whether or not it ran, and dashboard tabs. Results do not — rerun the query. A query tab you open fresh starts with SELECT 'Hello, DuckLocal' AS greeting;.

The toolbar ​

Above the editor, from the left:

ButtonWhat it does
RunRuns the editor's SQL — see Running SQL
StopShown only while a query or a profile is running; interrupts it
FormatReformats the SQL — see Format
ExplainShows the plan DuckDB would use, without running the statement
ProfileRuns the query and shows what each operator cost

Explain and Profile are described in Explain and Profile.

Running SQL ​

Press ⌘↵ (Cmd+Enter) with the editor focused, or use the Run button.

While a query is running, pressing run again does nothing (nor do Explain and Profile), and a Stop button appears beside Run. Stop, or ⌘., interrupts the query; it ends with DuckDB's Interrupted error, recorded in history like any failure. There is no timeout: without Stop, a query runs as long as DuckDB needs, and other database work queues behind it.

Results stream from DuckDB, so a scan stops once the grid's row limit is reached instead of reading the rest of the file. A query that has to see every row before its first — ORDER BY, GROUP BY, an aggregate, a window function — still computes in full.

Each tab has its own results. A result that arrives after you switched tabs lands in the tab that ran it.

How a statement is treated depends on its leading keyword. SELECT, WITH, SHOW, DESCRIBE, EXPLAIN, PRAGMA, SUMMARIZE, VALUES, FROM, TABLE, PIVOT, and CALL produce a result set. Anything else — DDL (data definition) and DML (data modification) statements — reports Done: N rows affected, took … instead of a grid. Leading -- comments are skipped when deciding; block comments are not.

Scripts ​

The editor can hold several statements. Run executes all of them, in order, the way the DuckDB shell reads a file, and stops at the first failure — running a SELECT after a failed ATTACH would only add a second, misleading error. A strip above the results lists the statements, each marked with its row count, done, failed or not run; click one to see its result. An error underlines the statement that failed, not the whole script.

A few of the shell's dot commands work too, each on a line of its own:

CommandShows
.tables ?PATTERN?Tables and views, optionally filtered by an ILIKE pattern such as stat%
.schema ?PATTERN?The CREATE statements of tables and views, optionally filtered
.databasesThe attached databases
.helpThis list

Any other dot command (.mode, .read, …) is an error naming the ones that work.

Errors ​

A failed statement shows an alert titled Query failed with DuckDB's message verbatim. The message comes from the engine and is always in English, whatever the interface language is. Nothing is written to the grid, and the attempt is still recorded in history with a failure marker.

When the message points at a position — parser and binder errors do, with a LINE n: line and a caret — the editor underlines that spot with a red wavy line: the token the caret marks, or the span a run of carets covers. The mark follows your edits and clears on the next run. Runtime errors carry no position and get no mark.

Format ​

Format runs the buffer through sqlformat with a 2-space indent and uppercased keywords, then replaces the entire buffer. It does nothing on an empty buffer.

Explain and Profile ​

Both buttons work on the editor's whole text, and both take exactly one statement. With two or more — or with a dot command — they refuse with Explain and Profile take one statement: put the one to look at in a tab of its own. A trailing ; and trailing comments are fine.

While one of Run, Explain or Profile is busy, the other two do nothing. Neither Explain nor Profile is recorded in history. Their output replaces the grid on the Results tab, switching to it if another tab was open; a failure shows the Query failed alert, as a failed run does.

Explain ​

Explain runs EXPLAIN <your statement> and shows DuckDB's plan as plain monospace text, with the time it took. It only plans: the statement is not executed, so explaining an INSERT, UPDATE or DELETE is safe.

Profile ​

Profile runs the statement under EXPLAIN (ANALYZE, FORMAT JSON) and shows the plan that ran as a tree: each operator's own time and share of the total, the rows it produced against the optimizer's estimate (flagged when off by more than 10×), and what it filtered, joined on or projected. The operator that cost the most is named at the top and drawn in red. How to read it: Explain and Profile output.

Profiling really runs the statement — that is how its operators get timed. So it accepts only a single read-only query:

  • Accepted: SELECT, WITH … SELECT, FROM …, VALUES, TABLE, SHOW, DESCRIBE, SUMMARIZE.
  • Refused: anything that writes (INSERT, UPDATE, DELETE, CREATE, …), CALL, PRAGMA, COPY, EXPLAIN itself, a write hidden behind a WITH (WITH s AS (…) INSERT …), and a PIVOT without an explicit IN (…) list.

A refused statement gets Only statements that read can be profiled (SELECT, WITH, FROM…): profiling runs the statement. DuckDB's own parser decides this before anything runs, not the first keyword.

A profile takes as long as the query, plus the cost of measuring it. Stop (or ⌘.) interrupts it like a run.

Autocompletion ​

The completion menu is catalog-aware. Candidates are ranked:

  1. Tables and columns from the schema (up to 35 entries)
  2. DuckDB function names
  3. SQL keywords

At most 50 items are offered. Matching is a case-insensitive prefix match on the identifier immediately to the left of the cursor, so sel completes to SELECT but elect completes to nothing. A function inserts its name and an opening parenthesis; identifiers that contain spaces or special characters are inserted double-quoted.

The keyword and function lists are a curated subset — not every DuckDB function will appear.

Keyboard shortcuts ​

On Windows and Linux, read Ctrl for ⌘ throughout.

DuckLocal's own shortcuts, all listed in the menu bar:

ShortcutAction
⌘↵Run the query
⌘.Stop the running query
⌘TNew query tab
⌘WClose the tab
Ctrl+Tab / Ctrl+Shift+TabNext / previous tab (Ctrl on a Mac too)
⌘1 … ⌘9Go to the tab in that place; ⌘9 is the last
⌘OOpen data
⌘SSave a dashboard's source, in its source view
⌘BHide or show the sidebar
⌘+ / ⌘− / ⌘0Make the interface larger / smaller / default size — see Interface size
⌘QQuit

The editor's own, which behave as in any text field:

ShortcutAction
⌘F / ⇧⌘FFind / replace in the editor
⌘Z / ⇧⌘ZUndo / redo
⌘ASelect all
⌘C / ⌘X / ⌘VCopy / cut / paste
⌥⌘↑ / ⌥⌘↓Add a cursor above / below
⌘← / ⌘→ / ⌥← / ⌥→Move by line / word
⌘↑ / ⌘↓Move to start / end of document
⌘⌫ / ⌥⌫Delete to start of line / previous word

The menu bar holds every window command with its shortcut:

MenuCommands
DuckLocalCommand line & AI, Check for Updates…, Check for Updates at Launch, Show the guide, Open logs folder, Quit DuckLocal
FileNew query, Open data, Save, Close tab, Next tab, Previous tab
EditUndo, Redo, Cut, Copy, Paste, Select all
QueryRun, Stop
ViewShow or hide sidebar, Larger interface, Smaller interface, Default size, Online base map (OpenStreetMap)

Windows and Linux have no menu bar; there, Show the guide and Open logs folder are on the right-click menu of the version at the right end of the status bar.

Online base map (OpenStreetMap) is a check item; see Charts. Rows in the schema sidebar have a right-click menu too; see Schema and history. There is no command palette.

Released under the Apache-2.0 License.