Skip to content

Web UI: open a table's query in a new tab on middle click, Shift+click, or the platform's new-tab modifier click#109246

Merged
alexey-milovidov merged 15 commits into
masterfrom
web-ui-open-table-in-new-tab
Jul 14, 2026
Merged

Web UI: open a table's query in a new tab on middle click, Shift+click, or the platform's new-tab modifier click#109246
alexey-milovidov merged 15 commits into
masterfrom
web-ui-open-table-in-new-tab

Conversation

@alexey-milovidov

@alexey-milovidov alexey-milovidov commented Jul 3, 2026

Copy link
Copy Markdown
Member

In the Web UI (play.html) databases/tables panel, clicking a table with the middle mouse button, with Shift held, or with the platform's new-tab modifier held (Cmd on macOS, Ctrl elsewhere) — the gestures that conventionally open a link in a new tab — now opens the corresponding query in a new Web UI tab instead of replacing the query in the current one. This also applies to the size/rows addendum (opens system.tables properties) and the engine label (opens SHOW TABLE).

A plain click keeps the previous behavior (loads the query into the current tab), and a second click on an already-loaded query still runs it, regardless of the button or modifiers used. On macOS, Ctrl+Click is the secondary (context-menu) click rather than a new-tab gesture, so it is left entirely to the browser: it neither opens a tab nor activates the query.

Middle clicks fire auxclick rather than click, so both events are wired up, and the middle-click autoscroll is suppressed. On Linux/X11 the middle button additionally pastes the primary selection into the freshly-focused query editor; this is suppressed for exactly that one paste, so no clipboard content is appended after the query. A normal Ctrl+V is unaffected.

Changelog category (leave one):

  • Improvement

Changelog entry (a user-readable short description of the changes that goes into CHANGELOG.md):

In the Web UI, clicking a table in the databases panel with the middle mouse button, with Shift, or with the platform's new-tab modifier (Cmd on macOS, Ctrl elsewhere) now opens its query in a new Web UI tab.

Version info

  • Merged into: 26.7.1.911 (included in 26.7 and later)

In the databases/tables panel, clicking a table (or its size/rows/engine
addendum) with the middle mouse button, or with Shift/Ctrl/Cmd held - the
gestures that conventionally open a link in a new tab - now opens the
corresponding query in a new Web UI tab instead of replacing the current
query. A plain click keeps the previous behavior, and a second click on an
already-loaded query still runs it, regardless of the button or modifiers.

Middle clicks fire `auxclick` rather than `click`, so both events are wired
up. On Linux/X11 the middle button additionally pastes the primary selection
into the freshly-focused query editor; this is suppressed for exactly that
one paste so no clipboard content is appended after the query.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@clickhouse-gh

clickhouse-gh Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Workflow [PR], commit [b06362d]

Summary:


AI Review

Summary

This PR teaches the Web UI databases panel to open table-related queries in a new Web UI tab for middle/Shift/modifier clicks, plus the Linux/X11 paste suppression needed around the focused editor. The event-routing and paste-guard fixes from the earlier review threads are present in the current code, but the remaining contract text is still inconsistent with the final macOS behavior: the new helper comment and the PR changelog wording still advertise Ctrl+Click generically even though macOS Ctrl+Click is now intentionally a no-op for query activation.

PR Metadata
  • Changelog category: Improvement is correct for the actual change.
  • Changelog entry: required for Improvement, but the current text is no longer accurate because it implies Ctrl+Click opens a new Web UI tab on every platform. The implementation now deliberately excludes macOS Ctrl+Click.
  • Suggested replacement:
    In the Web UI, middle-clicking a table in the databases panel, or Shift+clicking it (Cmd+Click on macOS, Ctrl+Click elsewhere), now opens its query in a new Web UI tab.
Missing context / blind spots
  • ⚠️ There is still no automated browser-level harness for play.html; the middle-click / modifier-click routing and Linux/X11 PRIMARY paste behavior remain validated only by the committed manual matrix in programs/server/play.html.
Final Verdict

⚠️ Request changes: the code paths from the earlier findings look consistent now, but the remaining contract text should be tightened so the PR description/changelog and the in-file helper comment match the shipped macOS behavior.

@clickhouse-gh clickhouse-gh Bot added the pr-improvement Pull request with some product improvements label Jul 3, 2026
Comment thread programs/server/play.html Outdated
…focus

Addresses the code review on #109246: the guard that swallows the Linux/X11
`PRIMARY` paste after a middle-click new-tab open was armed in `auxclick` and
cleared by a fixed 500 ms timeout. That timeout was decoupled from the moment
the new tab's editor is actually focused - `openQueryInNewTab` goes through
`activateTab`, which awaits `restoreFromHistory` (and thus `updateQueryParams`
/`tokenize`) before `query_area.focus` runs. On a cold first activation or a
slow query, the window could expire before focus, so the unwanted paste still
landed; and the flag also stayed armed on the already-loaded (`postOne`) path
where no new-tab focus happens, so a later genuine `Ctrl+V` could be swallowed.

Now the guard is armed right around the real `query_area.focus` in the new-tab
activation path, only for a genuine middle click, and cleared by the paste
itself or a short post-focus fallback. A slow activation can no longer let the
guard expire before focus, and non-new-tab paths never arm it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread programs/server/play.html
…d paste

The X11 `PRIMARY` paste guard armed around `query_area.focus()` in the
new-tab path relied on a 250ms fallback to disarm when no synthetic paste
arrived. On platforms/cases where a middle click never produces a `PRIMARY`
paste (macOS, Windows, empty selection), that window let the guard swallow a
real `Ctrl+V` / `Cmd+V` issued within 250ms of a middle-click new-tab open.

Discriminate by keystroke instead of timing: the X11 `PRIMARY` paste is
mouse-driven and carries no keystroke, while a real `Ctrl+V` / `Cmd+V` is
always preceded by its own paste-shortcut `keydown`. Disarm the guard on that
`keydown` (which fires before the resulting `paste`), so a genuine keyboard
paste is never eaten regardless of timing or platform.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread programs/server/play.html Outdated
The keydown-based discrimination for the X11 `PRIMARY` middle-click paste
guard only disarmed `suppress_middleclick_paste` on `Ctrl`/`Cmd`+`V`. But
`Shift+Insert` is also a standard keyboard paste shortcut on Linux/Windows,
and it fires its own `keydown` before the resulting `paste` just like
`Ctrl`+`V` does. Without disarming on it, a real `Shift+Insert` paste issued
within the 250 ms post-focus fallback window after a middle-click new-tab
open was swallowed, violating the invariant that the guard only ever eats
the synthetic X11 `PRIMARY` paste and never a real keyboard paste.

Disarm the guard on `Shift+Insert` as well. The change is additive: the X11
`PRIMARY` paste is mouse-driven and carries no keystroke, so it is still
swallowed; only keyboard-originated pastes gain the extra shortcut.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread programs/server/play.html
alexey-milovidov and others added 2 commits July 3, 2026 10:35
On macOS, `Ctrl+Click` is the secondary (context-menu) click, not the
"open in a new tab" gesture - that role belongs to `Cmd+Click`. The
table-row activation handler in `play.html` treated any `ctrlKey` click
as a new-tab open, so a normal macOS context click on a table row or its
size/rows/engine addendum created a new Web UI tab instead of showing the
context menu.

Make the modifier-open check platform-aware, reusing the existing `isMac`
constant: the new-tab modifier is `metaKey` (Cmd) on macOS and `ctrlKey`
elsewhere, matching how browsers themselves choose the new-tab modifier.
Middle click and Shift+click stay new-tab gestures on every platform.

This addresses the AI-Review "Request changes" verdict on commit
906c6f2.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread programs/server/play.html
The Web UI gesture routing (plain click replaces the current tab;
middle/Shift/Cmd/Ctrl click opens a new tab; re-activating an
already-loaded query still runs it) and the Linux/X11 middle-click paste
guard depend on browser- and OS-specific event ordering across `click`,
`auxclick`, modifier dispatch, the focus-triggered `PRIMARY` paste, and
the `keydown`/`paste` discrimination. There is no browser-level test
harness for `play.html` in the repository (the only automated coverage,
`01528_play.sh`, just checks that the `/play` endpoint serves the page),
so this contract is verified by hand.

Commit the manual test matrix next to `onTableActivate` so the exact
gestures and their expected outcomes - including the case where a real
keyboard paste right after a middle-click new-tab open must be preserved
while only the synthetic `PRIMARY` paste is swallowed - are the recorded,
re-runnable contract for anyone touching `set_query_or_run`,
`openQueryInNewTab`/`activateTab`, or `suppress_middleclick_paste`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread programs/server/play.html Outdated
Address review (`play.html`, `clickhouse-gh`): the X11 PRIMARY paste guard
`suppress_middleclick_paste` is a single shared bit, but each middle-click
new-tab open scheduled its own uncancelled 250ms fallback timer. Two
overlapping opens (open table A, then table B within that window) both armed
the same bit; A's stale timeout could then fire and clear the bit that B had
re-armed, before B's focus-triggered PRIMARY paste arrived - so B's paste
landed in the editor.

Keep the handle of the single fallback timer (`middleclick_paste_timeout`)
and cancel it whenever the guard is re-armed or consumed (`disarmMiddleclickPaste`),
so an older open's timeout can never clear a newer open's guard. Also extended
the committed manual test matrix with the overlapping-open case.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@alexey-milovidov
alexey-milovidov requested a review from pamarcos July 3, 2026 19:59
@alexey-milovidov

Copy link
Copy Markdown
Member Author

@groeneai, what's with 03532_window_function_and_null_source_max_threads? Who broke it? What to revert?

@groeneai

groeneai commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

@alexey-milovidov Answers to the three questions:

What's with it: the test asserts that a "crazy max_threads" (max_threads = 2000) cross-join + window EXPLAIN PIPELINE must raise server error 290 (LIMIT_EXCEEDED), because the pipeline multiplies streams past the parallelism limit. The failure is The query succeeded but the server error '290' was expected: under some randomized settings the plan collapses the streams (Resize 2 -> 1), so the limit is never crossed and 290 is never raised.

Who broke it: nobody, in code. It is a test-robustness gap under CI settings randomization, not a regression. CIDB shows 0 failures on master in 30 days and PR-only failures spread across 12 unrelated PRs. Deterministic local repro (debug): original test + --query_plan_optimize_join_order_randomize <seed> fails 20/20, while no seed passes 5/5. The pipeline shape depends on the JOIN plan, so it is sensitive to two independent randomized settings: query_plan_optimize_join_order_randomize and join_algorithm (a plain hash join also collapses the pipeline, even with the randomize seed pinned to 0).

What to revert: nothing. The fix is to pin both settings in the test. That is already in flight in #109330 (pins query_plan_optimize_join_order_randomize = 0 and join_algorithm = 'parallel_hash' in all three queries). We validated it locally: 290 is raised deterministically even under competing join_algorithm and seeds.

This PR (play.html only) does not touch the pipeline and cannot cause it.

Example failing run: https://s3.amazonaws.com/clickhouse-test-reports/json.html?PR=96130&sha=68fa461995b63b0bd29db51fccc36b5fbad79585&name_0=PR&name_1=Stateless%20tests%20%28arm_asan_ubsan%2C%20targeted%29

@pamarcos pamarcos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've manually tested it and it works just as the description states 🚀

@pamarcos pamarcos self-assigned this Jul 6, 2026
alexey-milovidov and others added 6 commits July 8, 2026 16:48
Address AI review (⚠️ Request changes): on macOS, `Ctrl+Click` is the
secondary (context-menu) click, not a new-tab or activation gesture. The
new-tab branch already used the platform-aware modifier (`metaKey` on macOS,
`ctrlKey` elsewhere), so a macOS `Ctrl+Click` was not opening a new tab - but
it still fell through to the plain-click `query_area.value = value` path, and a
macOS `Ctrl+Click` on the already-loaded row still hit `postOne`. That
contradicts the documented secondary-click contract.

Short-circuit macOS `Ctrl+Click` at the top of `set_query_or_run` so it neither
opens a new tab, replaces the editor, nor runs the query, leaving the gesture
entirely to the browser (so the native context menu can appear). A middle click
(button 1) is excluded so `Ctrl` + middle click still opens a new tab. Updated
the in-file manual test matrix (case 6) and the branch comments to match.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@alexey-milovidov

Copy link
Copy Markdown
Member Author

@groeneai, investigate the failure: https://s3.amazonaws.com/clickhouse-test-reports/json.html?PR=109246&sha=52be366e5cc6bbd0fe2016d997940ceea424d62f&name_0=PR&name_1=Integration%20tests%20%28amd_tsan%2C%206%2F6%29 and provide a fix in a separate PR. If the fix is already in progress, link it here.

All 8 parameterizations of test_storage_delta_disks/test.py::test_single_log_file failed (the first after 333 s, the rest instantly — it looks like a session-scoped fixture / cluster startup failure cascading). This PR only touches programs/server/play.html, so the failure is unrelated. I found no open tracking issue for this test.

@groeneai

Copy link
Copy Markdown
Contributor

Investigated. Fix in a separate PR: #110300.

Root cause: not this PR. The session-scoped started_cluster fixture times out in cluster.start(). The server starts, then aborts at metadata load because disk disk_s3_0_with_cache fails its startup S3 access check with a transient 403 AccessDenied writing the probe object (MinIO: "signature check failed ... time skew ... adjust the signer", one retry, then gives up). The identical-cred sibling disks disk_s3_0_common/disk_s3_1_common pass their checks ~80 ms earlier, so it is a transient race during the concurrent 3-node TSAN startup, not a config error. The failed fixture cascades to all 8 parameterizations (first after the ~333 s start timeout, the rest instantly).

Fix: skip the startup access check for the s3 disks, mirroring the azure disks in the same config that already set skip_access_check=true.

No open tracking issue existed; no competing fix PR.

Comment thread programs/server/play.html
@alexey-milovidov
alexey-milovidov merged commit 6b3d04a into master Jul 14, 2026
176 of 177 checks passed
@alexey-milovidov
alexey-milovidov deleted the web-ui-open-table-in-new-tab branch July 14, 2026 13:39
@robot-clickhouse robot-clickhouse added the pr-synced-to-cloud The PR is synced to the cloud repo label Jul 14, 2026
@alexey-milovidov alexey-milovidov changed the title Web UI: open a table's query in a new tab on middle/Shift/Ctrl click Web UI: open a table's query in a new tab on middle click, Shift+click, or the platform's new-tab modifier click Jul 14, 2026
CurtizJ pushed a commit to CurtizJ/ClickHouse that referenced this pull request Jul 16, 2026
Follow-up to ClickHouse#109246: the final
implementation deliberately does not treat macOS `Ctrl+Click` as a new-tab
gesture (it is the secondary/context-menu click there and is left to the
browser), but the `openQueryInNewTab` helper comment still said
"Shift/Ctrl/Cmd click". Spell out the actual contract: middle click,
Shift+click, or the platform's new-tab modifier click - Cmd+click on macOS,
Ctrl+click elsewhere - and point to the manual matrix above `onTableActivate`.

Addresses the remaining review comment on ClickHouse#109246.
raimannma pushed a commit to raimannma/ClickHouse that referenced this pull request Jul 17, 2026
Duplicating a tab with a middle click focuses the query editor. On Linux/X11
the middle button additionally pastes the PRIMARY selection into the freshly
focused editor, appending clipboard junk after the duplicated query.

Guard against exactly that one paste, mirroring the mechanism in
ClickHouse#109246: `activateTab` arms
`suppress_middleclick_paste` around `query_area.focus()` for a genuine middle
click, the editor's `paste` handler swallows that paste, and a real keyboard
paste shortcut (Ctrl/Cmd+V or Shift+Insert) disarms the guard first so it is
never eaten. A short fallback timer bounds how long a never-consumed guard
can linger.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr-improvement Pull request with some product improvements pr-synced-to-cloud The PR is synced to the cloud repo

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants