You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Algorithm / first paint / 120 Hz: [#874](https://github.com/QueryaHub/Querya-Desktop/issues/874)–[#879](https://github.com/QueryaHub/Querya-Desktop/issues/879)
14
+
15
+
## [0.4.17] - 2026-09-20
16
+
17
+
Driver and grid correctness after 0.4.16: Table Browser schema vs missing PK, SQLite implicit `rowid`, Mongo write/filter/discard, and Postgres / MySQL / SQLite / Redis session, type, and Save fixes.
18
+
19
+
### Fixed
20
+
21
+
-**Table Browser schema load vs missing PK (#772)** — A failed `getTableSchema` (permissions, disconnect) is no longer shown as “Cannot edit: no primary key detected”. Status is “schema unavailable” plus the real error and Refresh retries schema. Editing stays off until schema loads. Genuine missing PKs still use the old copy. SQLite implicit `rowid` is applied only after a successful schema load.
22
+
-**SQLite implicit rowid Table Browser (#774)** — Tables with no declared PRIMARY KEY (`CREATE TABLE t (name TEXT)`) use implicit `rowid` as the DML key. Browse `SELECT` projects `"rowid", *` so Save can `UPDATE … WHERE rowid`. Status is no longer “no primary key”. `WITHOUT ROWID` tables keep their declared PK.
23
+
-**Mongo 0-match write (#776)** — `updateOne` / `replaceOne` / `deleteOne` throw when `nMatched` / `nRemoved` is 0 (wrong `_id` type, deleted doc). Inspector and JSON editor surface Save Failed instead of a success toast. An identical `$set` (`nModified == 0`) still counts as a match.
24
+
-**Mongo full-document Save (#778)** — JSON editor Save uses `replaceOne` (whole document, `_id` locked) instead of `$set`, so fields deleted in JSON — including nested keys — are removed on the server.
25
+
-**Mongo document editor Back (#782)** — Dirty JSON in `MongoDocumentEditor` is registered with `UnsavedWorkRegistry`. Breadcrumb Back, Home, Close, and tree navigation confirm before discarding; Cancel keeps the editor.
26
+
-**Mongo JSON filter ObjectId / DateTime (#783)** — Document list filter parses Extended JSON (`$oid`, `$date`) and wraps a 24-character hex `_id` as `ObjectId`. A leftover string `_id` with zero matches shows how to write `{ "_id": { "$oid": "…" } }`.
27
+
-**Postgres open-transaction probe (#787)** — `BEGIN` + `SELECT` does not assign an XID, so `pg_current_xact_id_if_assigned` stayed NULL (SQL-tab badge off; autocommit-off prepended a second `BEGIN`). The session tracks BEGIN/COMMIT/ROLLBACK and otherwise probes `pg_stat_activity.xact_start` (PG 9+). Implicit BEGIN when autocommit is off stays a separate `execute`.
28
+
-**Postgres Table Browser paging (#788)** — Browse stays on `PgSessionMode.readOnly`. `SELECT` uses `ORDER BY` primary-key columns when a PK exists. Row totals come from `pg_class.reltuples` instead of a blocking `COUNT(*)` before first paint (stale estimates below the current page are ignored so Next still works). Save / REFRESH stay on `tableWrite`.
29
+
-**Postgres timestamptz / bytea / jsonb / arrays (#789)** — Table Browser and SQL results encode cells as PG literals (ISO timestamps, `\x` hex for bytea, JSON text for jsonb, `{1,2,3}` for arrays) instead of `Object.toString`. Schema uses `udt_name` so `ARRAY` / `USER-DEFINED` round-trip through `formatLiteral`.
30
+
-**Postgres host/port SSL (#790)** — Host/port Use SSL/TLS stays `sslmode=require` (encrypt, no CA check) unless a Root CA is set, then `verify-full`. A URI `sslmode=` value still wins. The form documents the MITM tradeoff and writes `sslmode=verify-full` when saving a Root CA.
31
+
-**Postgres custom-SQL allowlist (#791)** — Table Browser SQL dialog classifies the first statement after comments instead of substring `contains('insert ')`. `SELECT inserted_at` is allowed; `SELECT 1; DELETE FROM t` is rejected. `WITH … INSERT` is a write; `TABLE` / `VALUES` / `(SELECT …)` stay allowed.
32
+
-**SQLite getObjectDdl bind (#796)** — DDL lookup uses `WHERE name = ?` with a positional list. `:name` plus `[objectName]` did not bind, so the dialog showed **No definition found** for tables that exist.
33
+
-**SQLite WITH / PRAGMA (#797)** — `execute` classifies the first statement after comments: `WITH … INSERT` is a write (Dart read-only guard + `execute` instead of `rawQuery`). Assignment `PRAGMA name=value` is a write; `PRAGMA busy_timeout` stays a query. SQL workspace injects `LIMIT` only for read-only statements.
34
+
-**SQLite missing file (#798)** — Test Connection and opening a saved connection no longer create an empty `.db` when the path is a typo. Errors distinguish file not found, permission, and corrupt. New-connection Save still creates the file if it does not exist.
35
+
-**SQLite Table Browser paging (#799)** — Browse `SELECT` uses `ORDER BY` primary-key columns, or `rowid` when the table has implicit rowid. First paint skips blocking `COUNT(*)` (Next stays available when the page is full). SQL workspace has an optional statement timeout matching Postgres/MySQL.
36
+
-**SQLite BLOB / TEXT grid (#800)** — Table Browser and SQL results show BLOB as `X'hex'` (not `Uint8List.toString()`) and persist the same. Declared TEXT stays a quoted string even when it looks numeric (`00123`).
37
+
-**MySQL Table Browser session lock (#803)** — Browse stays on `MysqlSessionMode.readOnly`. Title-bar lock is passed into `MysqlTableView`: staging / Save stay off and Save does not acquire `tableWrite`. `SET SESSION TRANSACTION READ ONLY` is documented as a next-transaction hint (weaker than a read-only user; MariaDB vs MySQL 8).
38
+
-**MySQL ssl-mode (#805)** — `ssl-mode=prefer` enables TLS (same as `require`) instead of turning it off. `verify_ca` / `verify_identity` fail closed without `sslrootcert` and ask the driver to check the CA (and hostname for identity). Form Use SSL stays encrypt-only.
39
+
-**MySQL BOOLEAN / BIT / BLOB / JSON grid (#806)** — Schema uses `COLUMN_TYPE` so BOOLEAN is `tinyint(1)` (TRUE/FALSE on Save). BIT/BLOB/BINARY cells display as `0x` hex and persist as `X'…'`; JSON stays quoted text. The MySQL driver decodes charset-63 payloads as latin1 so invalid UTF-8 no longer throws.
40
+
-**MySQL Table Browser paging (#807)** — Browse `SELECT` uses `ORDER BY` primary-key columns when a PK exists. Row totals come from `information_schema.TABLES.TABLE_ROWS` instead of a blocking `COUNT(*)` before first paint (stale estimates that are below the current page are ignored so Next still works).
41
+
-**Redis URL paste (#819)** — Paste `redis://` / `rediss://` stores the raw URI on `connectionString` (like Postgres/MySQL/Mongo), so `sslrootcert` / `sslcert` / `sslkey` reach `RedisConnection.connect`.
42
+
-**Redis binary bulk (#818)** — GET / SCAN / hash / list / set / zset decode bulk replies as bytes (`RedisParserBulkBinary`). Invalid UTF-8 is shown as hex / base64; Save as text is off so SET cannot write replacement characters.
43
+
-**Redis stream/unknown GET-SET (#817)** — Stream, module, and `unknown` keys are not opened with `GET` or saved with `SET`. Save stays on `string` only; `unknown` retries `TYPE` before treating the value as a string.
44
+
-**SQL toolbar overflow** — MySQL / Postgres Query + History + Execute wrap instead of overflowing at ~700px (widget tests treat RenderFlex overflow as failure).
45
+
-**Redis collection paging (#816)** — Hash / list / set / zset editors load the first 200 members (`HSCAN` / `LRANGE` / `SSCAN` / `ZRANGE`) with Load more, instead of `HGETALL` / `LRANGE 0 -1` / `SMEMBERS` / `ZRANGE 0 -1`. Keys with 10k+ members show a large-key warning.
46
+
-**Redis URI Test/sidebar (#815)** — Test Connection and the sidebar keyspace probe parse `redis://` / `rediss://` via `fromConnectionRow` (host, port, TLS, cert query params) instead of hitting localhost:6379. The probe keeps `id: -1` so it does not replace workspace sockets.
47
+
-**Redis DEL confirm (#814)** — Deleting a key (browser or editor) and removing a hash field / set member / zset member opens the same destructive-operation dialog as SQL. Cancel / Escape does not send `DEL` / `HDEL` / `SREM` / `ZREM`.
48
+
-**Mongo drop/delete confirm (#781)** — Drop database, drop collection, document Del, and editor Delete open the same destructive-operation dialog as SQL. Cancel / Escape does not call `dropDatabase` / `dropCollection` / `deleteOne`.
49
+
-**Redis title-bar read-only (#813)** — Session lock is passed into the key browser and editor. Save, DEL, HSET/HDEL, RPUSH, SADD/SREM, ZADD/ZREM, and TTL apply stay hidden; the explorer socket also refuses those writes and sends `READONLY` after AUTH when locked (ignored on standalone / older servers).
50
+
-**SQLite Table Browser read-only (#793)** — Connection-form Read only (`useSSL`) opens the file with `SQLITE_OPEN_READONLY` even for Save (`tableWrite`). Title-bar session lock is passed into `SqliteTableView`: staging / Save stay off and the grid does not acquire a writable handle.
51
+
-**MySQL SQL tx toolbar (#809)** — Begin / Commit / Rollback run `START TRANSACTION` / `COMMIT` / `ROLLBACK` on the SQL socket without replacing the editor buffer. The toolbar shows Transaction open/none. Table Browser Save stays on the `tableWrite` socket from #802 (no nested `START TRANSACTION`); opening a table still warns while SQL has an open transaction.
52
+
-**MySQL SQL-grid Save (#804)** — Result-grid Save runs only for a simple single-table `SELECT` with a PK in the result (`getTableSchema`). JOIN, comma-`FROM`, and no-PK results stay read-only. DML uses the PK and `columnDataTypes`; applies still wrap `START TRANSACTION` / `COMMIT` / `ROLLBACK` (join an already-open SQL transaction).
53
+
-**SQLite SQL-grid Save (#795)** — Result-grid Save runs only for a simple single-table `SELECT` with a PK in the result (`getTableSchema`). JOIN, comma-`FROM`, and no-PK results stay read-only. DML uses the PK and `columnDataTypes`; applies still wrap `BEGIN TRANSACTION` / `COMMIT` / `ROLLBACK` (join an already-open `BEGIN`).
54
+
-**Postgres SQL-grid Save (#786)** — Result-grid Save runs only for a simple single-table `SELECT` with a PK present in the result (`getTableSchema`). JOIN, comma-`FROM`, subqueries, and VALUES stay read-only. DML `WHERE` uses the PK and `columnDataTypes` instead of every displayed column.
55
+
-**Redis Overview/Explorer sockets (#812)** — Overview INFO and Explorer SCAN/GET/`SELECT` use separate pooled sockets (`stats` vs `explorer`) so opening a DB no longer kills keep-alive Overview, and Home Refresh no longer steals Explorer. User Disconnect closes both roles.
56
+
-**MySQL Table Browser session (#802)** — Browse uses a read-only pool slot; Save uses a dedicated `tableWrite` socket so SQL `START TRANSACTION` / `SET` / `USE` do not leak into the grid. SQL-grid Save joins an already-open transaction instead of nesting `START TRANSACTION`. Opening a table on the same database (and Overview↔SQL) warns while SQL has an open transaction.
57
+
-**SQLite Table Browser session (#794)** — Browse uses a read-only `Database`; Save uses a dedicated `tableWrite` handle so SQL `BEGIN` / `ATTACH` do not leak into the grid (no nested `BEGIN`). SQL-grid Save joins an already-open transaction instead of starting another. Opening a table (and Overview↔SQL) warns while SQL has an open `BEGIN`.
58
+
-**Postgres Table Browser session (#785)** — Browse uses a read-only pool slot; Save and `REFRESH MATERIALIZED VIEW` use a dedicated `tableWrite` socket so they do not share the SQL editor’s TCP session. Statement-timeout `forceClose` on SQL no longer kills the grid. Opening a table while SQL has an open transaction on the same database warns, matching Overview↔SQL.
59
+
-**Mongo inspector Apply (#775)** — With **Save to DB** wired, **Apply** and **Ctrl/Cmd+Enter** persist through the same `$set` callback instead of only closing the dialog. SQL-grid Apply (no callback) still stages locally.
60
+
-**Mongo field codec (#777)** — Inspector Save keeps BSON type: strings that look like numbers stay strings; ObjectId, DateTime, Int64, and Decimal128 round-trip. `$set` of `_id` stays blocked.
61
+
-**Mongo document editor (#779)** — Documents encode as relaxed Extended JSON (`$oid`, `$date`, …) instead of `JsonEncoder` / `toString()`. Save decodes EJSON so the `_id` filter stays an `ObjectId`, not a string.
62
+
-**0-row DML Save (#773)** — Table Browser and SQL-grid Save fail (and roll back) if any statement matches 0 rows instead of toasting success from statement count. The staging buffer is kept.
63
+
-**Table Browser navigation (#771)** — Home, Close workspace, tree/object changes, and the matching Command Palette actions confirm before discarding staged grid or SQL edits. Cancel leaves the staging buffer registered.
64
+
-**Redis SET TTL (#811)** — Saving a string key uses `SET … KEEPTTL XX` (Redis 6+) so an existing expiry is not cleared. Older servers fall back to `TTL` then `SET … EX`. A key that already expired is not recreated.
65
+
-**MySQL SELECT cap (#808)** — SQL Workspace injects/clamps `LIMIT` like Postgres and drains leftover `rowsStream` rows instead of cancelling, so the session is ready for the next statement. Table Browser custom SQL gets the same LIMIT clamp so `execute` does not buffer an unbounded result.
66
+
-**Postgres Save (#784)** — Table Browser and SQL-grid Save run `BEGIN`, each DML statement, and `COMMIT` as separate extended-protocol executes (Parse cannot contain multiple commands). Autocommit-off SQL starts a transaction with its own `BEGIN` instead of concatenating `BEGIN;` onto the user query.
67
+
-**Mongo session auth (#780)** — After `scrubCredentials()`, find/update/list still authenticate from an in-memory session URI (getters stay null; nothing is written back). One `Db` is reused per database instead of open/close on every call.
68
+
-**Table Browser INSERT (#792, #810)** — Skip `GENERATED ALWAYS` / identity-always / `AUTO_INCREMENT` columns and omit empty cells that have a server default, so new rows do not send `id` or `''`.
69
+
-**SQLite WAL (#801)** — Open writable user databases with `PRAGMA journal_mode=WAL` (falls back if the FS cannot create the WAL file) and surface `SQLITE_BUSY` as a retryable error instead of a generic execute failure.
70
+
10
71
## [0.4.16] - 2026-09-20
11
72
12
73
In-place editing in Table Browser (same DML staging as SQL Workspace), Command Palette and Quick Switcher, workspace chrome parity across drivers, connections-tree visual + FPS work, MongoDB per-field Save to DB, and a hardened in-app updater.
0 commit comments