feat: streaming Export — stream full query result to disk, uncapped (#87)#103
Merged
Conversation
) Adds an Export button to the editor toolbar that runs the current query uncapped and streams the response straight to a user-chosen file via the File System Access API, bypassing the result grid so memory stays flat regardless of result size. Format follows the query's own FORMAT clause (default TabSeparatedWithNames); a mid-stream ClickHouse exception is detected via the X-ClickHouse-Exception-Tag header + trailing frame and excised with a hold-back buffer so it never reaches the file. Replaces the old buffered CSV/TSV result-panel Export. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EfEGDNjwJcudck7Dzm82Pu
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Adds an Export button to the editor toolbar (next to Share) that runs the
current editor query uncapped and streams the response straight to a
user-chosen file via the File System Access API, bypassing the result grid
entirely — memory stays flat regardless of result size. Replaces the old
result-panel Export (a buffered CSV/TSV download of the already-loaded grid).
FORMAT <name>(ineither order relative to a
SETTINGSclause — ClickHouse allows both)streams verbatim with a matching extension; otherwise defaults to
TabSeparatedWithNames.so the HTTP status can't change) are detected via the
X-ClickHouse-Exception-Tagheader + trailing__exception__frame andexcised with a 32 KiB hold-back write buffer, so the error text is never
committed to the file — reported as "Export incomplete" instead. Verified
the tag header's presence against a real ClickHouse 26.3.10 build (see
Verification below).
query_id/AbortController+ progress banner — Cancel abortsthe stream and issues its own
KILL QUERY, entirely independent of thegrid run's cancel state; re-entrance is guarded synchronously so a second
click while the save dialog is open can't start a second export.
session_id(sessionParamsFor) soan export depending on an earlier
CREATE TEMPORARY TABLE/SETin thesame tab works like Run does.
EXPLAIN uses, rather than sending an invalid combined request.
showSaveFilePicker); the button staysvisible but
aria-disabledwith a tooltip elsewhere.Closes #87.
Verification
Beyond the unit suite, manually verified against the real
antalyaClickHouse 26.3.10 demo cluster (
npm run local), driving the actual UI withPlaywright + a stubbed
showSaveFilePickerso the real code path runsunmodified:
query_idtagging,correct toast.
X-ClickHouse-Exception-Tagis present on every response from this build.of incompressible row data before the failure), the connection fails with a
browser-level "network error" before ClickHouse's documented trailer frame
ever arrives — reproduced identically through the real UI and via a raw
fetchprobe, with and without compression, so it isn't a harness quirk.The app's generic failure path (abort the writable, report "Export
failed: network error", leave the partial file) handles this safely, but I
could not observe the graceful "excise the trailer, report Export
incomplete" path firing against a real server — only in unit tests
against the documented wire format. Flagging for a maintainer call: chase
this further (try another/newer real cluster) or accept the safe fallback.
Checklist
npm testpasses (the per-file coverage gate is non-negotiable) — 1183 tests, core/net files 100%,app.jswithin its documented floornpm run buildsucceeds (single-filedist/sql.html)src/core/, network insrc/net/(injected fetch), DOM insrc/ui/CHANGELOG.md([Unreleased]) updatedCo-Authored-By: Claude Sonnet 5 noreply@anthropic.com
https://claude.ai/code/session_01EfEGDNjwJcudck7Dzm82Pu