Skip to content

Results ​

A run answers in a grid under the editor. The grid streams and virtualizes: rows paint while the query drains, counts are exact, and the result is kept whole on the server side, so the last row of a very large result is as reachable as the first.

The grid ​

Rows arrive as the server sends them; what does not fit the memory window (results.spoolMemory, 32 MB by default) spills to disk, with a free-disk reserve (results.spoolReserve) guarding the machine. There is no row cap.

Selection is by cell, range, row, column or all, with full keyboard navigation, and Ctrl+C copies what is selected. Hovering a column header says which table and column it came from, and an extension type names itself there (geometry(Point,4326)).

Filters, freeze, peek ​

The funnel on a header opens a per-column filter; chips over the grid show the active ones with honest counts ("12 of 3,520 rows"). Filters run over the spooled rows and never touch your SQL. The column picker hides columns (a hidden one leaves a seam), columns resize, and columns freeze at either edge, rows at the top. Cells can be multi-line with per-row heights. Space peeks at a value; a value can also open in a tab of its own with raw, pretty, lines and EWKT faces.

Copy and save ​

Copy comes in the shape you chose (results.copyFormat, TSV by default): TSV with spreadsheet-safe quoting, CSV (RFC 4180), JSON arrays, JSON objects typed by column, or a Markdown table. Save All and Save Selection stream from the server's own copy of the result into a file through the native dialog (results.saveFormat, CSV by default), so the copy row cap does not apply.

Row editing ​

Rows edit in place. A row is keyed on the primary key, else the best NOT NULL unique index, else a content match on ctid and xmin. Every write is a fully parameterized UPDATE or DELETE, refused when more than one row would match, with optimistic concurrency (a row changed by someone else is refused) and an Undo on every write. New row, Edit and Delete sit on the toolbar; Enter or F2 edits, Alt+N adds, Delete deletes.

A value longer than results.inlineEditLimit (100 kB) stays out of the form's own input: the field shows its size, and the expand button opens it in an editor tab built for large values. Writes run on the tab's own session, inside whatever transaction the tab has open, and count into its totals like any other data change, so the commit gate applies to them; the generated statement goes to the Log with an Undo.

Cancel ​

Cancel stops the running statement through the wire protocol and keeps the backend alive, so the tab's session state, its temporary tables and its transaction survive. The status bar's activity dot beats while a query drains or any other background work runs.

The row form ​

The form knows the column types: a boolean is a switch, an enum has its picker, an array edits one element per line, a foreign key picks from the referenced table's rows, a large value such as JSON opens in its own editor tab, and a geometry previews a sketch. The same form serves an extension's inputs and a script's run parameters.

Browse Data ​

Browse Data, from a table's row menu or its DDL header, opens the table's rows as a result document ordered by primary key, the first 1,000 rows (results.browseRows) with a picker for more.

Result documents, Compare and foreign key trails ​

A result can be promoted into a tab of its own, with its rows kept server side. It offers Refresh, Focus Command and Open as Script. Compare With puts two results side by side with synchronized scrolling. A foreign key cell follows into the referenced row, with Back and Forward and a crumb trail, and the object tree walks with it.

Messages and Problems ​

Beside Results sit two more tabs. Messages shows the wire protocol verbatim, one field per column, every message linked to its line in the editor; in a script tab the server's statement errors live here, verbatim. Problems lists the dynamic parser's findings. The side by side layout pairs the grid with Messages or with any result view, and Split Vertically stacks them. The active tab of each script is remembered per workspace.

Result views and charts ​

A grid extension (.plumesql.js) can declare a result view, a chart or a table drawn from the rows in a sandboxed iframe with no network of its own. A view can ask for its inputs (a column pick narrowed to a type family, a choice, a number, text), carry header buttons, page through the rows past the window (extensions.viewRowCap), and be copied as an image or SVG. -- @view in a script opens a query straight on its chart, -- @inputs answers the picks in the file, and -- @refresh keeps the chart live.

Starters ship for a no-library bar chart, Chart.js, Vega-Lite, ECharts, μPlot, SandDance, a WebGL scatter for a million points, a gallery of Observable Plot charts, a Pivot and a Column profile. A chart tab switched away from and back to is still the chart; a fresh run returns the grid. A view that loads a library from a CDN needs the host on extensions.remoteScriptHosts, which is empty by default.

Extension types in cells ​

PostGIS geometries decode client side into hover cards, peeks, EWKT faces and a whole-column sketch with validity. pgvector's vector, halfvec and sparsevec cells show dimensions, norm and a sparkline. JSON cells get a card, and grid extension starters format booleans, amounts, byte sizes, dates, durations, UUIDs, arrays and more.

See also ​

PlumeSQL is a hercstack product.