{"slug": "v0-13-1-signed-macos-builds-a-postgres-explain-that-finally-runs-and-pagination", "title": "v0.13.1: Signed macOS Builds, a Postgres Explain That Finally Runs, and Pagination That Honors Your OFFSET", "summary": "TabularisDB released v0.13.1, fixing three major bugs: macOS builds are now signed and notarized, eliminating Gatekeeper warnings; PostgreSQL EXPLAIN plans now work after a column type mismatch was corrected; and pagination now respects user-specified OFFSET values. The release includes contributions from four external developers.", "body_md": "# v0.13.1: Signed macOS Builds, a Postgres Explain That Finally Runs, and Pagination That Honors Your OFFSET\n\n**v0.13.1** is a short follow-up to [v0.13.0](/blog/v0130-kubernetes-tunnels-quick-navigator-dml-tabs). Where the last release was about *reach* — Kubernetes tunnels, a Quick Navigator, MCP into plugin drivers — this one is about *correctness*: a sweep of features that shipped but quietly didn't work, plus the distribution-level fix Mac users have been asking for since the first DMG.\n\nNo new surface area. Several things that were broken, fixed. Four external contributors land in this tag.\n\n## Signed and Notarized on macOS\n\nUntil now, opening Tabularis on macOS meant a trip through Gatekeeper: the \"tabularis cannot be opened because the developer cannot be verified\" dialog, or an `xattr -c`\n\nincantation copied from the install docs. The app was never signed, so every Mac treated it as quarantined.\n\nPR [#289](https://github.com/TabularisDB/tabularis/pull/289) wires the release workflow to sign and notarize the macOS build. The `.app`\n\nand `.dmg`\n\nare now signed with a Developer ID Application certificate and submitted to Apple's notarization service during the release build — the App Store Connect API key is decoded from a secret into a temp file on the macOS runners only, and the Apple env vars are inert on the Linux and Windows jobs since Tauri only consumes them when bundling for macOS.\n\nWhat this means for you: a notarized `.dmg`\n\nopens with the normal \"downloaded from the internet\" confirmation and nothing more. No `xattr`\n\n, no Privacy & Security override, no \"unverified developer\" wall. If you've been keeping the workaround command in a note, you can delete it.\n\n## Postgres Explain Plan, Now Actually Running\n\nThe [Visual Explain](/wiki/visual-explain) feature has worked on MySQL, MariaDB, and SQLite since it shipped. On PostgreSQL it failed every single time with `error deserializing column 0`\n\n— and it turns out it never worked on any Postgres version.\n\n[@NewtTheWolf](https://github.com/NewtTheWolf) (Dominik Spitzli) and the maintainer track it down in PR [#279](https://github.com/TabularisDB/tabularis/pull/279) (closes [#276](https://github.com/TabularisDB/tabularis/issues/276)). `EXPLAIN (FORMAT JSON)`\n\nreturns the plan in a single column, and on Postgres that column is typed as `json`\n\n(OID 114), not `text`\n\n. The code read it straight into a `String`\n\n, and `tokio-postgres`\n\nrefuses to deserialize a `json`\n\ncolumn into a `String`\n\n— so the call errored out before the plan was ever parsed. This is server-side behavior that's been stable since the `FORMAT`\n\noption landed in PG 9.0, which is why the report reproduced on both PG 16 and PG 18.\n\nThe fix reads the column as a `serde_json::Value`\n\nand re-serializes it for the existing parser, with a `String`\n\nfallback for Postgres-compatible engines that hand the plan back as plain text. If you've ever clicked \"Explain Plan\" on a Postgres connection and gotten an error, that was this.\n\nVideo unavailable\n\n## Pagination That Honors Your OFFSET\n\nWhen the grid paginates a `SELECT`\n\n, it rewrites the query: it strips your trailing `LIMIT`\n\n/`OFFSET`\n\n, then re-appends `LIMIT <fetch> OFFSET <page offset>`\n\n. The rewriter only read back your `LIMIT`\n\n— the `OFFSET`\n\nwas dropped on the floor. On page 1 the per-page offset is `0`\n\n, so `LIMIT 1 OFFSET 1`\n\nquietly became `LIMIT 1 OFFSET 0`\n\n, and your OFFSET was ignored.\n\nPR [#275](https://github.com/TabularisDB/tabularis/pull/275) (fixes [#273](https://github.com/TabularisDB/tabularis/issues/273)) adds `extract_user_offset`\n\n, mirroring the existing token-aware `extract_user_limit`\n\nso an `OFFSET`\n\ninside an identifier or string literal isn't misread, and `build_paginated_query`\n\nnow adds your OFFSET to the per-page offset. Pagination walks the rows you actually asked for. Because all three SQL drivers share `build_paginated_query`\n\n, the fix lands on Postgres, MySQL, and SQLite at once — with regression tests including the exact case from the issue and OFFSET-without-LIMIT on both page 1 and page 2.\n\nThere was a folk remedy floating around: appending a trailing `--`\n\n\"fixed\" it. The reason is grimly funny — the comment broke the stripper's pattern match, so the appended pagination clause landed on the same line as the `--`\n\nand got swallowed as a comment, and the database ran your original query verbatim. Correct result, entirely by accident. You don't need the `--`\n\nanymore.\n\n## Connection Strings Stop Silently Failing\n\nPasting `postgresql://user@host/db`\n\ninto the New Connection modal did nothing: no fields populated, no error, and the green success indicator still rendered. The connection-string protocol registry was built only from each driver's id and example, so for PostgreSQL only `postgres`\n\nwas ever registered — `postgresql://`\n\nmatched nothing and was silently skipped.\n\nPR [#277](https://github.com/TabularisDB/tabularis/pull/277) (fixes [#260](https://github.com/TabularisDB/tabularis/issues/260)) registers well-known scheme aliases — `postgresql`\n\n↔ `postgres`\n\n, `mariadb`\n\n↔ `mysql`\n\n, `sqlite3`\n\n↔ `sqlite`\n\n— in a second pass that never overrides a protocol a driver registered explicitly, so a dedicated `mariadb`\n\nplugin would still win over the alias. The modal's `looksLikeConnectionString`\n\npre-filter is gone: input always runs through the parser now, an unrecognized scheme produces a real error (`Unsupported database driver: oracle. Supported: mariadb, mysql, postgres, postgresql, sqlite, sqlite3`\n\n), and the green check only appears when the string actually parsed and populated the form.\n\n## MCP: A Parenthesized SELECT Is a Read Again\n\nv0.13.0 [rebuilt the MCP safety gates](/blog/v0130-kubernetes-tunnels-quick-navigator-dml-tabs) to fail closed on multi-statement payloads. v0.13.1 fixes a false positive in the same classifier, reported and fixed by [@ymadd](https://github.com/ymadd) in PR [#272](https://github.com/TabularisDB/tabularis/pull/272).\n\n`(SELECT ...) UNION ALL (SELECT ...)`\n\n— the shape you get when each UNION branch needs its own `ORDER BY`\n\n/`LIMIT`\n\n— starts with a `(`\n\n, so `first_keyword`\n\nreturned empty and the query was classified as \"unknown\". That tripped both the [read-only mode](/wiki/mcp-readonly-mode) and the [write-approval gate](/wiki/mcp-approval-gates): a pure read raised a write prompt. The classifier now peels leading `(`\n\nand whitespace before reading the first keyword, so the inner `SELECT`\n\nis detected — while multi-statement detection still runs first (so `(SELECT 1); DROP ...`\n\nstays \"unknown\"), and the greedy peel never downgrades a parenthesized write or DDL to \"select\". Regression tests cover parenthesized UNION, nested and whitespace-padded parens, empty parens (which fail closed), parenthesized DDL/DML, and a writing CTE.\n\n## The Grid Stops Freezing on Large JSON\n\nOpen a table with a fat `JSON`\n\ncolumn — say a MySQL `JSON`\n\nfield holding a megabyte of nested data — and the grid would lock up. Each visible cell tokenized and rendered its **full** stringified value into thousands of DOM nodes, even though the cell is clipped to about 300px on screen and the full value is already one click away.\n\n[@NewtTheWolf](https://github.com/NewtTheWolf) (Dominik Spitzli) fixes it in PR [#285](https://github.com/TabularisDB/tabularis/pull/285) (closes [#283](https://github.com/TabularisDB/tabularis/issues/283)): a new `truncateCellPreview`\n\ncaps the inline preview at 300 characters *before* tokenization and render in both `JsonCell`\n\nand `TextCell`\n\n, and the native `<td>`\n\ntooltip is capped too. The cap is lossless — the inline expander and the JSON viewer both read the raw row value, not the truncated `displayText`\n\n, so the full content is always reachable. The MySQL and Postgres JSON demos gained a ~1 MB big-JSON row to reproduce the freeze and keep it fixed.\n\n## Editor: Theme Isolation and Focus on Open\n\nTwo Monaco fixes from the maintainer.\n\nPR [#282](https://github.com/TabularisDB/tabularis/pull/282) (closes [#281](https://github.com/TabularisDB/tabularis/issues/281)) stops the editor theme from leaking across instances. Monaco themes are global to the page, so every editor has to agree on the active theme — but each component resolved its own: most used the UI theme, the SQL editor and save-query modal honored the `editorTheme`\n\noverride, and the AI explain modal passed a theme id it never registered. Whichever editor mounted last won, so opening the AI explanation modal re-colored every other editor in the app. A new `useEditorTheme`\n\nhook now resolves the effective theme once (the `editorTheme`\n\noverride when set, otherwise the UI theme, with a fallback if the override points at a deleted theme), and all eleven Monaco usages route through it.\n\nPR [#280](https://github.com/TabularisDB/tabularis/pull/280) (closes [#274](https://github.com/TabularisDB/tabularis/issues/274)) focuses the editor when you open a new console tab — via `Ctrl`\n\n/`Cmd+T`\n\n, the `+`\n\nbutton, or a Quick Navigator action — so you can start typing immediately. Each tab mounts its own editor instance once, keyed by tab id, so a single `editor.focus()`\n\ncovers every creation path. The type check on `console`\n\ntabs avoids stealing focus when a table or query-builder tab opens.\n\nVideo unavailable\n\n## Quieter Keychain, Correct TLS Pools\n\nTwo connection-layer fixes that you feel as fewer interruptions and fewer surprises.\n\nOpening the **AI** settings tab on macOS used to fire the Keychain authorization prompt repeatedly — a single tab open issued eight or more keychain reads, one per provider across `SettingsProvider`\n\n, `AiTab`\n\n, and `get_ai_models`\n\n. [@ymadd](https://github.com/ymadd)'s PR [#269](https://github.com/TabularisDB/tabularis/pull/269) routes the AI key reads through the `CredentialCache`\n\nthat already backs DB and SSH credentials, so the keychain is read at most once per provider per session. As a bonus, `get_ai_key`\n\nnow distinguishes a definitive \"no entry\" from a denied or timed-out prompt, so a transient denial no longer caches a configured key as permanently missing until you restart.\n\n[@arsis-dev](https://github.com/arsis-dev) (Julien Barbe) follows the v0.13.0 MySQL SSL work with the Postgres equivalent in PR [#278](https://github.com/TabularisDB/tabularis/pull/278): the connection pool key now includes PostgreSQL TLS settings, so editing a connection from one SSL mode to another can no longer silently reuse a pool created under the old mode.\n\n## Smaller Things\n\n**MiniMax-M3 is the new default**([@octo-patch](https://github.com/octo-patch), PR[#270](https://github.com/TabularisDB/tabularis/pull/270)) —`MiniMax-M3`\n\n, the new flagship model, is added to`ai_models.yaml`\n\nand placed first, so it's auto-selected when only the MiniMax key is configured.`MiniMax-M2.7`\n\nand`MiniMax-M2.7-highspeed`\n\nstay available for anyone who prefers the previous generation.\n\n**Big-JSON demo rows**(part of PR[#285](https://github.com/TabularisDB/tabularis/pull/285)) — the MySQL and Postgres demo seeds gained ~1 MB JSON rows so the grid freeze stays reproducible and regression-tested.\n\n**Finding Tabularis useful?** Star it on GitHub — it takes a second and helps more developers discover the project. Star on GitHub## Thanks\n\nFour external contributors land in v0.13.1 — three returning, one new.\n\n** @ymadd** keeps refining the seams from v0.13.0: the parenthesized-SELECT classifier fix (\n\n[#272](https://github.com/TabularisDB/tabularis/pull/272)) that removes a false write-prompt without weakening the fail-closed gate, and the AI keychain caching (\n\n[#269](https://github.com/TabularisDB/tabularis/pull/269)) that finishes wiring the credential cache through the last read path that wasn't using it.\n\n** @NewtTheWolf (Dominik Spitzli)** returns with two correctness fixes: the grid freeze on large JSON cells (\n\n[#285](https://github.com/TabularisDB/tabularis/pull/285)) and co-authoring the Postgres Explain Plan fix (\n\n[#279](https://github.com/TabularisDB/tabularis/pull/279)) — the feature that errored on every Postgres connection it ever ran against.\n\n** @arsis-dev (Julien Barbe)** follows his v0.13.0 MySQL SSL and Codex work with the PostgreSQL TLS pool-key fix (\n\n[#278](https://github.com/TabularisDB/tabularis/pull/278)) — closing the same class of \"the pool ignored your TLS setting\" bug on the other major engine.\n\n** @octo-patch** is new to the contributor list and brings the MiniMax-M3 default upgrade (\n\n[#270](https://github.com/TabularisDB/tabularis/pull/270)). Welcome.\n\nIf you run Tabularis on macOS and were tired of the Gatekeeper dance, ever clicked \"Explain Plan\" on Postgres and got an error, lost rows to a paginated query that ignored your OFFSET, pasted a `postgresql://`\n\nstring into a void, watched the grid freeze on a fat JSON column, or got Keychain-prompted on every AI-tab open — this is the upgrade.\n\n*v0.13.1 is available now. Update via the in-app updater, or download from the releases page.*", "url": "https://wpnews.pro/news/v0-13-1-signed-macos-builds-a-postgres-explain-that-finally-runs-and-pagination", "canonical_source": "https://tabularis.dev/blog/v0131-signed-macos-postgres-explain-offset-pagination", "published_at": "2026-06-05 11:00:00+00:00", "updated_at": "2026-06-25 17:01:29.446488+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["TabularisDB", "PostgreSQL", "MySQL", "SQLite", "macOS", "Gatekeeper", "Dominik Spitzli", "NewtTheWolf"], "alternates": {"html": "https://wpnews.pro/news/v0-13-1-signed-macos-builds-a-postgres-explain-that-finally-runs-and-pagination", "markdown": "https://wpnews.pro/news/v0-13-1-signed-macos-builds-a-postgres-explain-that-finally-runs-and-pagination.md", "text": "https://wpnews.pro/news/v0-13-1-signed-macos-builds-a-postgres-explain-that-finally-runs-and-pagination.txt", "jsonld": "https://wpnews.pro/news/v0-13-1-signed-macos-builds-a-postgres-explain-that-finally-runs-and-pagination.jsonld"}}