Querya Desktop 0.4.17
[0.4.17] - 2026-09-20
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.
Fixed
- 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 implicitrowidis applied only after a successful schema load. - SQLite implicit rowid Table Browser (#774) — Tables with no declared PRIMARY KEY (
CREATE TABLE t (name TEXT)) use implicitrowidas the DML key. BrowseSELECTprojects"rowid", *so Save canUPDATE … WHERE rowid. Status is no longer “no primary key”.WITHOUT ROWIDtables keep their declared PK. - Mongo 0-match write (#776) —
updateOne/replaceOne/deleteOnethrow whennMatched/nRemovedis 0 (wrong_idtype, deleted doc). Inspector and JSON editor surface Save Failed instead of a success toast. An identical$set(nModified == 0) still counts as a match. - Mongo full-document Save (#778) — JSON editor Save uses
replaceOne(whole document,_idlocked) instead of$set, so fields deleted in JSON — including nested keys — are removed on the server. - Mongo document editor Back (#782) — Dirty JSON in
MongoDocumentEditoris registered withUnsavedWorkRegistry. Breadcrumb Back, Home, Close, and tree navigation confirm before discarding; Cancel keeps the editor. - Mongo JSON filter ObjectId / DateTime (#783) — Document list filter parses Extended JSON (
$oid,$date) and wraps a 24-character hex_idasObjectId. A leftover string_idwith zero matches shows how to write{ "_id": { "$oid": "…" } }. - Postgres open-transaction probe (#787) —
BEGIN+SELECTdoes not assign an XID, sopg_current_xact_id_if_assignedstayed NULL (SQL-tab badge off; autocommit-off prepended a secondBEGIN). The session tracks BEGIN/COMMIT/ROLLBACK and otherwise probespg_stat_activity.xact_start(PG 9+). Implicit BEGIN when autocommit is off stays a separateexecute. - Postgres Table Browser paging (#788) — Browse stays on
PgSessionMode.readOnly.SELECTusesORDER BYprimary-key columns when a PK exists. Row totals come frompg_class.reltuplesinstead of a blockingCOUNT(*)before first paint (stale estimates below the current page are ignored so Next still works). Save / REFRESH stay ontableWrite. - Postgres timestamptz / bytea / jsonb / arrays (#789) — Table Browser and SQL results encode cells as PG literals (ISO timestamps,
\xhex for bytea, JSON text for jsonb,{1,2,3}for arrays) instead ofObject.toString. Schema usesudt_namesoARRAY/USER-DEFINEDround-trip throughformatLiteral. - Postgres host/port SSL (#790) — Host/port Use SSL/TLS stays
sslmode=require(encrypt, no CA check) unless a Root CA is set, thenverify-full. A URIsslmode=value still wins. The form documents the MITM tradeoff and writessslmode=verify-fullwhen saving a Root CA. - Postgres custom-SQL allowlist (#791) — Table Browser SQL dialog classifies the first statement after comments instead of substring
contains('insert ').SELECT inserted_atis allowed;SELECT 1; DELETE FROM tis rejected.WITH … INSERTis a write;TABLE/VALUES/(SELECT …)stay allowed. - SQLite getObjectDdl bind (#796) — DDL lookup uses
WHERE name = ?with a positional list.:nameplus[objectName]did not bind, so the dialog showed No definition found for tables that exist. - SQLite WITH / PRAGMA (#797) —
executeclassifies the first statement after comments:WITH … INSERTis a write (Dart read-only guard +executeinstead ofrawQuery). AssignmentPRAGMA name=valueis a write;PRAGMA busy_timeoutstays a query. SQL workspace injectsLIMITonly for read-only statements. - SQLite missing file (#798) — Test Connection and opening a saved connection no longer create an empty
.dbwhen 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. - SQLite Table Browser paging (#799) — Browse
SELECTusesORDER BYprimary-key columns, orrowidwhen the table has implicit rowid. First paint skips blockingCOUNT(*)(Next stays available when the page is full). SQL workspace has an optional statement timeout matching Postgres/MySQL. - SQLite BLOB / TEXT grid (#800) — Table Browser and SQL results show BLOB as
X'hex'(notUint8List.toString()) and persist the same. Declared TEXT stays a quoted string even when it looks numeric (00123). - MySQL Table Browser session lock (#803) — Browse stays on
MysqlSessionMode.readOnly. Title-bar lock is passed intoMysqlTableView: staging / Save stay off and Save does not acquiretableWrite.SET SESSION TRANSACTION READ ONLYis documented as a next-transaction hint (weaker than a read-only user; MariaDB vs MySQL 8). - MySQL ssl-mode (#805) —
ssl-mode=preferenables TLS (same asrequire) instead of turning it off.verify_ca/verify_identityfail closed withoutsslrootcertand ask the driver to check the CA (and hostname for identity). Form Use SSL stays encrypt-only. - MySQL BOOLEAN / BIT / BLOB / JSON grid (#806) — Schema uses
COLUMN_TYPEso BOOLEAN istinyint(1)(TRUE/FALSE on Save). BIT/BLOB/BINARY cells display as0xhex and persist asX'…'; JSON stays quoted text. The MySQL driver decodes charset-63 payloads as latin1 so invalid UTF-8 no longer throws. - MySQL Table Browser paging (#807) — Browse
SELECTusesORDER BYprimary-key columns when a PK exists. Row totals come frominformation_schema.TABLES.TABLE_ROWSinstead of a blockingCOUNT(*)before first paint (stale estimates that are below the current page are ignored so Next still works). - Redis URL paste (#819) — Paste
redis:///rediss://stores the raw URI onconnectionString(like Postgres/MySQL/Mongo), sosslrootcert/sslcert/sslkeyreachRedisConnection.connect. - 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. - Redis stream/unknown GET-SET (#817) — Stream, module, and
unknownkeys are not opened withGETor saved withSET. Save stays onstringonly;unknownretriesTYPEbefore treating the value as a string. - SQL toolbar overflow — MySQL / Postgres Query + History + Execute wrap instead of overflowing at ~700px (widget tests treat RenderFlex overflow as failure).
- Redis collection paging (#816) — Hash / list / set / zset editors load the first 200 members (
HSCAN/LRANGE/SSCAN/ZRANGE) with Load more, instead ofHGETALL/LRANGE 0 -1/SMEMBERS/ZRANGE 0 -1. Keys with 10k+ members show a large-key warning. - Redis URI Test/sidebar (#815) — Test Connection and the sidebar keyspace probe parse
redis:///rediss://viafromConnectionRow(host, port, TLS, cert query params) instead of hitting localhost:6379. The probe keepsid: -1so it does not replace workspace sockets. - 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. - 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. - 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
READONLYafter AUTH when locked (ignored on standalone / older servers). - SQLite Table Browser read-only (#793) — Connection-form Read only (
useSSL) opens the file withSQLITE_OPEN_READONLYeven for Save (tableWrite). Title-bar session lock is passed intoSqliteTableView: staging / Save stay off and the grid does not acquire a writable handle. - MySQL SQL tx toolbar (#809) — Begin / Commit / Rollback run
START TRANSACTION/COMMIT/ROLLBACKon the SQL socket without replacing the editor buffer. The toolbar shows Transaction open/none. Table Browser Save stays on thetableWritesocket from #802 (no nestedSTART TRANSACTION); opening a table still warns while SQL has an open transaction. - MySQL SQL-grid Save (#804) — Result-grid Save runs only for a simple single-table
SELECTwith a PK in the result (getTableSchema). JOIN, comma-FROM, and no-PK results stay read-only. DML uses the PK andcolumnDataTypes; applies still wrapSTART TRANSACTION/COMMIT/ROLLBACK(join an already-open SQL transaction). - SQLite SQL-grid Save (#795) — Result-grid Save runs only for a simple single-table
SELECTwith a PK in the result (getTableSchema). JOIN, comma-FROM, and no-PK results stay read-only. DML uses the PK andcolumnDataTypes; applies still wrapBEGIN TRANSACTION/COMMIT/ROLLBACK(join an already-openBEGIN). - Postgres SQL-grid Save (#786) — Result-grid Save runs only for a simple single-table
SELECTwith a PK present in the result (getTableSchema). JOIN, comma-FROM, subqueries, and VALUES stay read-only. DMLWHEREuses the PK andcolumnDataTypesinstead of every displayed column. - Redis Overview/Explorer sockets (#812) — Overview INFO and Explorer SCAN/GET/
SELECTuse separate pooled sockets (statsvsexplorer) so opening a DB no longer kills keep-alive Overview, and Home Refresh no longer steals Explorer. User Disconnect closes both roles. - MySQL Table Browser session (#802) — Browse uses a read-only pool slot; Save uses a dedicated
tableWritesocket so SQLSTART TRANSACTION/SET/USEdo not leak into the grid. SQL-grid Save joins an already-open transaction instead of nestingSTART TRANSACTION. Opening a table on the same database (and Overview↔SQL) warns while SQL has an open transaction. - SQLite Table Browser session (#794) — Browse uses a read-only
Database; Save uses a dedicatedtableWritehandle so SQLBEGIN/ATTACHdo not leak into the grid (no nestedBEGIN). SQL-grid Save joins an already-open transaction instead of starting another. Opening a table (and Overview↔SQL) warns while SQL has an openBEGIN. - Postgres Table Browser session (#785) — Browse uses a read-only pool slot; Save and
REFRESH MATERIALIZED VIEWuse a dedicatedtableWritesocket so they do not share the SQL editor’s TCP session. Statement-timeoutforceCloseon SQL no longer kills the grid. Opening a table while SQL has an open transaction on the same database warns, matching Overview↔SQL. - Mongo inspector Apply (#775) — With Save to DB wired, Apply and Ctrl/Cmd+Enter persist through the same
$setcallback instead of only closing the dialog. SQL-grid Apply (no callback) still stages locally. - Mongo field codec (#777) — Inspector Save keeps BSON type: strings that look like numbers stay strings; ObjectId, DateTime, Int64, and Decimal128 round-trip.
$setof_idstays blocked. - Mongo document editor (#779) — Documents encode as relaxed Extended JSON (
$oid,$date, …) instead ofJsonEncoder/toString(). Save decodes EJSON so the_idfilter stays anObjectId, not a string. - 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.
- 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.
- 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 toTTLthenSET … EX. A key that already expired is not recreated. - MySQL SELECT cap (#808) — SQL Workspace injects/clamps
LIMITlike Postgres and drains leftoverrowsStreamrows instead of cancelling, so the session is ready for the next statement. Table Browser custom SQL gets the same LIMIT clamp soexecutedoes not buffer an unbounded result. - Postgres Save (#784) — Table Browser and SQL-grid Save run
BEGIN, each DML statement, andCOMMITas separate extended-protocol executes (Parse cannot contain multiple commands). Autocommit-off SQL starts a transaction with its ownBEGINinstead of concatenatingBEGIN;onto the user query. - Mongo session auth (#780) — After
scrubCredentials(), find/update/list still authenticate from an in-memory session URI (getters stay null; nothing is written back). OneDbis reused per database instead of open/close on every call. - Table Browser INSERT (#792, #810) — Skip
GENERATED ALWAYS/ identity-always /AUTO_INCREMENTcolumns and omit empty cells that have a server default, so new rows do not sendidor''. - SQLite WAL (#801) — Open writable user databases with
PRAGMA journal_mode=WAL(falls back if the FS cannot create the WAL file) and surfaceSQLITE_BUSYas a retryable error instead of a generic execute failure.
Downloads
Portable (zip — run from folder, no installer)
- Linux:
Querya-Desktop-0.4.17-linux.zip - Windows:
Querya-Desktop-0.4.17-windows.zip - macOS:
Querya-Desktop-0.4.17-macos.zip(signed, notarized and stapled.appwhen Apple Developer secrets are configured; otherwise unsigned)
Optional USB-style profile: set QUERYA_PORTABLE=1 or create a QueryaData/ folder next to the binary (see docs/packaging.md).
Installable
- Linux AppImage:
Querya-Desktop-0.4.17-linux.AppImage(chmod +xthen run) - Linux .deb (Debian/Ubuntu):
Querya-Desktop-0.4.17-linux.deb—sudo apt install ./Querya-Desktop-0.4.17-linux.deb - Linux .rpm (Fedora/RHEL):
Querya-Desktop-0.4.17-linux.rpm—sudo dnf install ./Querya-Desktop-0.4.17-linux.rpm - Linux Flatpak:
Querya-Desktop-0.4.17-linux.flatpak—flatpak install --user ./Querya-Desktop-0.4.17-linux.flatpak - Windows setup:
Querya-Desktop-0.4.17-windows-setup.exe(Inno Setup)
Arch (AUR): querya-desktop — yay -S querya-desktop (auto-published when AUR_SSH_PRIVATE_KEY is configured).
Verify checksums: SHA256SUMS.txt
Build info
- pubspec: 0.4.17+1
- Commit: 0581df1