Skip to content
Tinker
Download

The data grid

One implementation serves table tabs and query results: an AppKit NSTableView with fixed row heights, server-side paging and an edit buffer that turns into SQL you read before it runs.

Pages, not endless scroll

A table tab shows one page of at most 1,000 rows. The pager in the status bar moves first, previous, next and last, and names the row range on screen. Moving between pages re-reads from the server; the grid never holds more than the current page. When a table has a single-column integer primary key and no user sort, deep pages switch from OFFSET to keyset paging, because OFFSET degrades. The status bar tooltip tells you which was used.

Query results are different: a result set is what the statement returned, so it streams in batches as rows arrive. Beyond 200,000 rows the stream pauses and a banner offers to load more, export the remainder straight to a file, or cancel.

Note
Row counts shown for a table are the planner’s estimate and are labelled ~. A filter with an exact count, or a short final page, shows the real number. An estimate is never presented as a count.

Sorting and filtering

Two conditions on orders, joined by OR. The SQL toggle on the right shows the generated WHERE clause.

Click a column header to cycle none, ascending, descending; ⇧-click adds a secondary sort. ⌘⇧F opens the filter bar. Each condition is a column, an operator and a value; conditions combine with AND or OR. Operators cover =, , <, , >, , contains, starts with, ends with, is null, is not null, in (…) and between. Values are always sent as parameters, never interpolated. Sort and filter both run on the server and reset to page 1, because both change what page 2 would mean. The state persists per table per connection.

Editing

Editing is enabled when the table has a primary key or a unique NOT NULL index. Otherwise the grid is read-only and the status bar says why. Double-click or ↩ starts an inline edit with an editor that fits the column type: a text field for strings and numbers, a toggle for booleans, a date and time picker with a raw-text fallback for temporal types, and the cell inspector for JSON and long text. ⌘⌫ sets NULL, Esc cancels, Tab moves right.

Edits are held in a buffer and coloured: changed cells yellow, new rows green, rows marked for deletion red with strikethrough. Nothing is sent until you commit (⌘⇧S) or discard. With auto-commit on, a non-production connection writes each edit as it is made; production connections always buffer.

The commit preview

Commit generates statements and shows every one of them in a sheet, syntax-highlighted, with a count summary. Only after you press Execute do they run, inside one transaction. On success the buffer clears and the affected rows refresh in place. On any failure everything rolls back, the buffer stays intact, and the error is shown against the statement that caused it.

UPDATE orders SET status = $1 WHERE id = $2;         -- only changed columns; WHERE uses the original PK values
DELETE FROM orders WHERE id = $1;
INSERT INTO orders (customer_id, total) VALUES ($1, $2) RETURNING *;
The shapes of generated DML. Each UPDATE and DELETE is followed by an affected-row check.
Careful
If an UPDATE or DELETE touches anything other than exactly one row, the whole transaction is rolled back and Tinker reports “Expected 1 row, got N — data may have changed since load”.

Selection, copy and paste

  • Cell, row, column and rectangular range selection, like a spreadsheet.
  • ⌘C copies TSV. ⌘⌥C copies the selected rows as INSERT statements in the connection’s dialect. The context menu also offers CSV, JSON, a Markdown table and a WHERE-IN list.
  • ⌘V pastes TSV into an editable grid starting at the anchor cell, creating rows past the end. Invalid values are flagged, never dropped.

The cell inspector

⌘⌥I opens the inspector: column name, native type, constraints and the raw value, editable.

The inspector shows the focused cell in full: JSON pretty-printed with a Copy formatted button, binary as a hex dump with Save as file, and long text without the 512-character in-cell truncation. Values that carry precision, such as decimal and timestamp, keep the server’s text end to end. They are never routed through Double or Date.

Geometry on a map

A table with a geometry column gains a Map tab. Points, lines and polygons are drawn on Apple Maps; click one to select its row.