Root cause: macOS emits a synthetic click event when the right mouse
button is released while holding Control. The outside-dismiss handler
was listening for click events in capture phase, which caught this
synthetic event and closed the menu right after it opened.
Fix: switch from click to pointerdown (with event.button === 0 guard)
for outside-dismiss detection. pointerdown fires on press before
contextmenu, so the right-button event (button:2) is filtered out
before the menu even opens, and the synthetic click is never seen.
MongoDB shell syntax like db.collection.find({}) was incorrectly
parsed as SQL, causing a "sql parser error" diagnostic in the editor.
Added MongoDB guards in shouldRunSqlSemanticDiagnostics and
refreshSemanticDiagnostics, matching existing Elasticsearch logic.
Also fix a pre-existing TiDB cloud URL param ordering test failure.
Row detail dialog was using displayableColumnIndexes instead of
visibleColumnIndexes, causing columns hidden via "hide null columns"
or manual hiding to still appear in the detail view.
- Add Navicat numeric ConnType codes (1-9) to typeMap for correct DB type mapping
- Add port-based inference fallback (6379→Redis, 27017→MongoDB, etc.)
- Expand typeMap with ClickHouse, Snowflake, KingbaseES, GaussDB, OceanBase
- Skip unrecognized connections instead of silently falling back to MySQL
- Extend hexToRgba() to handle rgba/rgb input passthrough
- Add pipette button with native color picker + text input in popover
- Custom color and preset colors are mutually exclusive
start_tunnel() and start_chain() had a check-then-act race condition:
multiple concurrent callers could all see an empty cache and each
spawn a new SSH tunnel. The tunnel that lost the insert race was
orphaned, causing queries routed through it to fail.
Use double-check locking with stale entry eviction: hold the lock for
the cache lookup, release it during the slow SSH handshake, then
re-check under the lock before inserting. If another caller already
created the tunnel, abort the duplicate and return the existing port.
Also check handle liveness on cache hits so that callers don't get a
dead port back when the background tunnel task has exited.
Add a matching re-check in the MongoDB connection pool creation path.
Add idle_timeout_secs connection option (default 60s) to preempt
server-side connection idle timeouts that cause "unexpected end of
file" errors on pooled MongoDB connections.
Reject MongoDB queries in the generic SQL execution path before any
pool or session-key creation. Previously, a typo in a MongoDB shell
command would fall through to executeMulti / execute_sql_statement,
which called get_or_create_pool_for_session and leaked a session-scoped
MongoDB Client (and SSH tunnel resources) before eventually returning
"Use MongoDB-specific commands".
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* feat(grid): add layer preview for geometry columns with Leaflet map
* fix: restore dev:backend script with env vars and cargo watch
* chore: update pnpm-lock.yaml for leaflet and dom-to-image-more dependencies
---------
Co-authored-by: dqn <someonegdeng@qq.com>
Frontend: add regex-based MongoDB URL parser to handle multi-host URIs
that the WHATWG URL parser rejects. Backend: separate
server_selection_timeout from connect_timeout for multi-host URIs to
prevent topology discovery from being cancelled by tokio timeout.
DOM mode: replace box-shadow with outline to avoid stacking with row border-b.
Canvas mode: draw row border before selected cell overlay so selection uses
uniform color on all four sides; clamp top edge to prevent canvas clipping.
coercePostgresArrayValue() only handled JSON [...] format but editor
outputs PG {...} format. When the user entered and exited edit mode
without changes, the string "{1,2,3}" failed to parse back to an
array, creating a false dirty detection via strict equality.
Add parsePostgresArrayText() recursive descent parser and return
oldValue reference when parsed result is equivalent.
- Route SELECT * FROM <index> through /_search for simple browses; aggregates/projections stay on /_sql
- Drive completion columns from /_mapping (flattened dotted fields, multi-fields)
- Switch editor completion to SQL when the active statement starts with SELECT/WITH on ES
- Skip generic SQL semantic diagnostics for ES (hyphenated wildcard indices caused 500s)
- Wire ES into server-side pagination plan; derive completion context from line blocks
- Fix result-grid pagination exceeding in-memory result sets (allRowsLoaded)
Three independent connection-list bugs:
1. Multi-select drag only moved one row. The drag system tracks a single
draggedId and ignored selectedTreeNodeIds. The drop callback now expands
to the full selection when the grabbed row is part of it, and the store
gains reorderSidebarEntries() to move them together.
2. Clicking the blank tree area didn't clear the selection (notably in
double-click activation mode). Row clicks now stopPropagation and the
tree containers clear the selection on click, so only blank clicks reset.
3. Creating a group then submitting an empty name dissolved ALL groups.
Enter (@keydown.enter) and the following @blur both fired finishRenameGroup;
the first call rebuilt the tree and recycled props.node onto another group,
so the second deleted the wrong one, cascading. Guard against double
invocation and treat an empty name as a cancel (never delete here — deleting
a group stays in the context menu).
Verified end-to-end on the web build: multi-select drag nests both
connections under the group; blank-click clears selection; empty-name Enter
keeps all groups intact. pnpm check is green.
Co-authored-by: vrustx <vrustx@vrustxdeMac-mini.local>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
After an app update (typically >15min since last use), the on-disk schema
tree cache is past its TTL and counts as stale. When "locate in sidebar"
loads the connection's databases, the stale cache is served synchronously
and an async `refreshStaleTreeNode` fires in the background; that refresh
replaces the database node with a fresh one whose tables haven't loaded
yet, evicting the node that locate just populated. By the time
`findNodePathForActiveTab` runs, the target table isn't in the tree, so
locate only reaches the database. After a restart the cache is fresh, no
refresh races, and locate works — matching the report.
Make `ensureTreeLoadedForTab` accept `{ force }` (loads everything via
awaited calls, bypassing the stale-cache fire-and-forget path) and, in
`locateActiveTabInSidebar`, retry once with force when the first
`findNodePath` misses. Fresh-cache locates still succeed on the first
pass and never force (no regression); `refreshStaleTreeNode` is untouched.
Co-authored-by: vrustx <vrustx@vrustxdeMac-mini.local>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>