diff --git a/CHANGELOG.md b/CHANGELOG.md index 995e0edd..f1cf9621 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,8 +17,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **`engines.querya_desktop` accepts several comparators** — `>=0.4.0 <3.0.0` (`>=`, `>`, `<=`, `<`, `=`, all must hold), as the ClickHouse driver declares. The app used to read only `>=x.y.z` and `^x.y.z`, so such an extension was shown on every version. - **Release hooks** — after a Release the registry and the template are told about the new version (`repository_dispatch`); needs the `QUERYA_DISPATCH_TOKEN` secret. +### Changed + +- **Faster result grids** — sorting a timestamp column of 50,000 rows ~400 ms → ~60 ms (#1533); choosing column types for a 5,000-row result ~3.5 ms → ~0.5 ms (#1548); selection statistics read `1,234.5` without copying the cell (#1520); copying a large result to the clipboard no longer stops the UI for 20–30 ms while it is handed to the background (#1537). + ### Fixed +- **Redis: a command can no longer run in another database** — every explorer of a connection shared one socket and sent `SELECT n` before each command, so switching to db3 while a folder delete in db0 was running sent the remaining deletes to db3, and a `SELECT` typed in the CLI was undone by the next key you opened while the prompt still showed the old database. Each database now has its own socket (selected again after a reconnect), and the CLI has its own. Folder delete uses `UNLINK` (falls back to `DEL` before Redis 4.0), pipelines its chunks and reloads the list if a chunk fails (#1569). +- **macOS in-app update no longer quits into a broken or missing app** — when the app could not be moved aside (no write access to its folder, a disk image, a copy macOS runs from a temporary location) the update copied the new app *into* the old one, and a failed copy left no app at all. The update dialog now says up front when the app cannot be replaced and offers the release page; otherwise the old app is restored if the copy fails, the failure is logged to `~/Library/Logs/Querya/querya-update.log` and the app opens again. The leftover `.old` bundle and the extracted update are removed (#1587). +- **macOS builds without Developer ID signing no longer run in the App Sandbox** — they did, unlike the signed build, so `~/.querya` (extensions, themes), `~/.ssh` keys, saved SQLite files, the MCP endpoint and in-app updates did not work. Unsigned and signed builds now differ only in how Gatekeeper treats them, and the release fails if the sandbox comes back (#1592). +- **Format SQL keeps PostgreSQL and SQLite literals that end in a backslash** — `'C:\'` was read with MySQL rules, so the next literal was taken for code and its keywords upper-cased; backslashes now follow the tab's database (#1566). +- **MongoDB queries with escapes, constructors or many documents** — in mongosh-style input, escapes stayed in the value (`"a\"b"` searched for `a\"b`), a string containing `ISODate(...)` broke the query, and an `insertMany` of 1,000 documents took seconds to parse; it is one pass now (#1513, #1539). +- **MongoDB: nested `ObjectId(...)`, `ISODate(...)` and Extended JSON are real BSON values** — `find({_id: ObjectId("…")})` matched nothing and inserts stored `{ $oid: … }` sub-documents. `ISODate` without a zone is UTC, as in mongosh (#1667). +- **ERD of one table in a large schema** — its columns could be missing when the schema had more than 200,000 catalog rows; the diagram and MCP `describe_table` / `sample_rows` now read only the tables they need (#1572). +- **README install steps** — the macOS Gatekeeper command pointed at `Querya.app`, but the app installs as `Querya Desktop.app`; and Fedora now uses `dnf install` so dependencies are installed (#1500). - **Extension manifest `id` is checked before it becomes a folder** — a sideloaded `.qext` with `"id": "../some/dir"` made the installer recursively delete and overwrite a folder outside the extensions directory. The id must now be letters, digits, `.`, `_` or `-` (starting with a letter or digit, no `..`), and every install / uninstall refuses a folder that is not inside the extensions directory (#1560). - **Format SQL no longer changes what the query means** — it uppercased keywords inside string literals (`'not null'` → `'NOT NULL'`), quoted identifiers (`"order"` → `"ORDER"`, a different column in PostgreSQL), comments and `$$` function bodies. It now touches code only, and the caret stays where it was instead of jumping to the end (#1566) diff --git a/test/features/workspace/generic_table_view_filter_calc_test.dart b/test/features/workspace/generic_table_view_filter_calc_test.dart index 2c06122b..b9056c86 100644 --- a/test/features/workspace/generic_table_view_filter_calc_test.dart +++ b/test/features/workspace/generic_table_view_filter_calc_test.dart @@ -152,14 +152,26 @@ void main() { }); group('calc bar', () { - testWidgets('shows aggregates for the selected cell', (tester) async { + testWidgets('shows aggregates for a numeric cell', (tester) async { await pumpGenericTableView(tester, FakeTableDataDelegate()); - await tester.tap(find.text('Alice')); + await tester.tap(find.text('1').first); await tester.pump(const Duration(milliseconds: 500)); await tester.pumpAndSettle(); expect(find.text('Count: '), findsOneWidget); }); + + testWidgets('stays collapsed for a single text cell', (tester) async { + await pumpGenericTableView(tester, FakeTableDataDelegate()); + + await tester.tap(find.text('Alice')); + await tester.pump(const Duration(milliseconds: 500)); + await tester.pumpAndSettle(); + + // One non-numeric value has nothing to aggregate: the bar is collapsed + // and, since #1674, its content is not built at all. + expect(find.text('Count: '), findsNothing); + }); }); }