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.
Oracle 11g does not support FETCH FIRST / LIMIT syntax. Skip appending
pagination clauses at SQL level and rely on JDBC setMaxRows for row
limiting, which already works across all Oracle versions.
- 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)
`validate_file_path` now expands leading `~` to the user's home directory
before checking file existence, so paths like `~/.ssh/id_rsa` work on macOS
and Linux. Also fixes error messages that incorrectly said "Database file".
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>
SQLite and DuckDB do not support the `alias(col1, col2)` subquery column
naming syntax, which caused "near '(': syntax error" when sorting query
results on these databases.
The data grid header only showed column names, and column types were
available only via tableMeta (open-table view). Arbitrary query results
(e.g. `select * from pg_depend`) therefore showed no type at all, which
is exactly the case the reporter hit.
Backend: add `column_types` to QueryResult (serde-default, backward
compatible) and populate it for the native drivers where the type is
readily available — PostgreSQL, MySQL, SQL Server, ClickHouse. Other
drivers leave it empty for now (no behavior change); schemaless stores
(Mongo/Redis/ES) have no column types.
Frontend: render a type row under each column name in the grid header,
color-coded by type. The type is resolved from tableMeta first (richer,
includes precision) and falls back to the query result's column_types by
index. Add a `showColumnTypesInHeader` setting (default on) and keep the
msgpack tab-result cache compatible. The source-selection logic is
extracted to lib/dataGridColumnType.ts with unit tests.
Co-authored-by: vrustx <vrustx@vrustxdeMac-mini.local>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ClickHouse and Databend expect square-bracket array literals (unquoted),
while PostgreSQL/DuckDB/etc. use curly-brace quoted format. Previously
all array values were unconditionally rendered with `'{...}'` syntax,
which produced wrong INSERT/UPDATE statements for ClickHouse columns
of nested array types like `Array(Array(Point))`.