From da4697ade518f2ff335ff6103ccc456fe937531e Mon Sep 17 00:00:00 2001 From: Boris Tyshkevich Date: Tue, 30 Jun 2026 15:42:10 +0000 Subject: [PATCH] feat(results): cap SELECT result rows (default 500) with a 100/500/1k/5k/10k selector MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A normal SELECT no longer pulls every row over the wire — it fetches at most a selected cap (default 500). Hybrid mechanism per #86: ClickHouse stops cleanly server-side (`max_result_rows` + `result_overflow_mode='break'`), and a small client-side guard in `applyStreamLine` trims the block-boundary overage `break` can leave, flagging `result.capped`. - `src/state.js` — `KEYS.resultRowLimit` + `resultRowLimit` (default 500, read from localStorage), `RESULT_ROW_LIMIT_OPTIONS`, and a pure `normalizeRowLimit` that snaps a stored/selected value back to a known option. - `src/net/ch-client.js` — `runQuery` honors `o.resultRowLimit`, adding the cap params via the existing `extra` dict. Scope is decided by the caller (app.js passes 0 for EXPLAIN/PIPELINE/ESTIMATE, which also run as `Table` and so can't be told apart by format here). - `src/core/stream.js` — `newResult(fmt, rowLimit=0)` carries the cap + `capped`; `applyStreamLine` stops pushing past the cap and flags `capped`. Pure, 100%. - `src/ui/results.js` — a row-limit ` capping how many rows a normal query fetches (the global, persisted + * preference). Changing it re-runs the current query with the new server-side + * cap, so a higher limit genuinely fetches more. The caller hides it for EXPLAIN + * views (small output a cap would truncate oddly). + */ +function rowLimitSelect(app) { + const sel = h('select', { + class: 'row-limit-select', + title: 'Max rows to fetch — changing re-runs the query', + onchange: (e) => app.actions.setResultRowLimit(Number(e.target.value)), + }); + for (const n of RESULT_ROW_LIMIT_OPTIONS) { + sel.appendChild(h('option', { value: String(n) }, String(n))); + } + // Reflect the current limit by value (set after the options are attached so the + //