From 560777329966dd7385e3232f874a46f89ec359bd Mon Sep 17 00:00:00 2001 From: Adrian Bonpin Date: Fri, 11 Sep 2026 17:20:41 +0000 Subject: [PATCH] 0.8.0: MariaDB + PlanetScale, TimescaleDB, multi-result sets, streaming export, schema diff (#27) --- AGENTS.md | 11 +- README.md | 30 +- ROADMAP.md | 128 ++- desktop/package.json | 2 +- desktop/src-tauri/Cargo.lock | 3 +- desktop/src-tauri/Cargo.toml | 3 +- desktop/src-tauri/src/commands/connections.rs | 6 +- .../src/commands/connections.test.rs | 47 + desktop/src-tauri/src/commands/db_viewer.rs | 62 +- .../src-tauri/src/commands/db_viewer.test.rs | 73 ++ .../src-tauri/src/commands/import_export.rs | 2 +- desktop/src-tauri/src/commands/mod.rs | 2 + desktop/src-tauri/src/commands/query.rs | 507 ++++++++- desktop/src-tauri/src/commands/query.test.rs | 134 +++ .../src-tauri/src/commands/query_export.rs | 539 ++++++++++ .../src/commands/query_export.test.rs | 235 +++++ desktop/src-tauri/src/commands/schema_diff.rs | 82 ++ .../src/commands/schema_diff.test.rs | 25 + .../src-tauri/src/commands/test_connection.rs | 7 +- .../src/commands/test_connection.test.rs | 54 + desktop/src-tauri/src/db/introspection.rs | 120 +++ desktop/src-tauri/src/db/mod.rs | 2 + desktop/src-tauri/src/db/mysql.rs | 62 +- desktop/src-tauri/src/db/schema_diff.rs | 992 ++++++++++++++++++ desktop/src-tauri/src/db/schema_diff.test.rs | 362 +++++++ desktop/src-tauri/src/db/sql_split.rs | 212 ++++ desktop/src-tauri/src/db/sql_split.test.rs | 86 ++ desktop/src-tauri/src/lib.rs | 6 +- desktop/src-tauri/src/models/db_viewer.rs | 152 +++ desktop/src-tauri/tauri.conf.json | 2 +- .../connections/DetailedConnectionForm.tsx | 2 +- .../src/components/connections/GeneralTab.tsx | 4 +- .../connections/NewConnectionScreen.tsx | 12 +- .../connections/ProviderSetupGuide.tsx | 5 +- .../connections/ProviderTabsGrid.tsx | 2 +- .../db-viewer/DbViewerScreen.test.tsx | 42 +- .../components/db-viewer/DbViewerScreen.tsx | 175 +-- .../db-viewer/HypertableDetail.test.tsx | 43 + .../components/db-viewer/HypertableDetail.tsx | 48 + .../db-viewer/ObjectExplorerPage.tsx | 37 +- .../components/db-viewer/ObjectTree.test.tsx | 17 + .../src/components/db-viewer/ObjectTree.tsx | 43 +- .../db-viewer/ResultSetPanels.test.tsx | 38 + .../components/db-viewer/ResultSetPanels.tsx | 42 + .../db-viewer/SchemaDiffPage.test.tsx | 69 ++ .../components/db-viewer/SchemaDiffPage.tsx | 275 +++++ .../db-viewer/StreamExportDialog.test.tsx | 44 + .../db-viewer/StreamExportDialog.tsx | 160 +++ .../components/db-viewer/TableControls.tsx | 18 + .../src/components/db-viewer/ToolsPage.tsx | 5 +- .../db-viewer/objects/ObjectDetail.tsx | 4 + .../src/components/editor/QueryToolbar.tsx | 1 + .../layout/DbTypeFilterDropdown.tsx | 1 + desktop/src/lib/bundle-config.test.ts | 6 +- desktop/src/lib/commands.ts | 40 +- desktop/src/lib/connectionString.test.ts | 53 + desktop/src/lib/connectionString.ts | 9 +- desktop/src/lib/dbCapabilities.test.ts | 10 + desktop/src/lib/dbCapabilities.ts | 1 + desktop/src/lib/dbIcons.tsx | 10 +- desktop/src/lib/docs-coverage.test.ts | 18 +- desktop/src/lib/exportData.test.ts | 24 +- desktop/src/lib/exportData.ts | 30 +- desktop/src/lib/providers.test.ts | 27 +- desktop/src/lib/providers.ts | 17 +- desktop/src/lib/types.ts | 54 +- desktop/src/lib/utils.ts | 2 +- desktop/src/lib/version.test.ts | 4 +- desktop/src/stores/dbViewerStore.diff.test.ts | 30 + desktop/src/stores/dbViewerStore.ts | 33 +- package.json | 2 +- www/public/landing.js | 2 +- www/src/data/changelog.ts | 12 + www/src/pages/index.astro | 2 +- 74 files changed, 5182 insertions(+), 239 deletions(-) create mode 100644 desktop/src-tauri/src/commands/connections.test.rs create mode 100644 desktop/src-tauri/src/commands/db_viewer.test.rs create mode 100644 desktop/src-tauri/src/commands/query.test.rs create mode 100644 desktop/src-tauri/src/commands/query_export.rs create mode 100644 desktop/src-tauri/src/commands/query_export.test.rs create mode 100644 desktop/src-tauri/src/commands/schema_diff.rs create mode 100644 desktop/src-tauri/src/commands/schema_diff.test.rs create mode 100644 desktop/src-tauri/src/commands/test_connection.test.rs create mode 100644 desktop/src-tauri/src/db/schema_diff.rs create mode 100644 desktop/src-tauri/src/db/schema_diff.test.rs create mode 100644 desktop/src-tauri/src/db/sql_split.rs create mode 100644 desktop/src-tauri/src/db/sql_split.test.rs create mode 100644 desktop/src/components/db-viewer/HypertableDetail.test.tsx create mode 100644 desktop/src/components/db-viewer/HypertableDetail.tsx create mode 100644 desktop/src/components/db-viewer/ObjectTree.test.tsx create mode 100644 desktop/src/components/db-viewer/ResultSetPanels.test.tsx create mode 100644 desktop/src/components/db-viewer/ResultSetPanels.tsx create mode 100644 desktop/src/components/db-viewer/SchemaDiffPage.test.tsx create mode 100644 desktop/src/components/db-viewer/SchemaDiffPage.tsx create mode 100644 desktop/src/components/db-viewer/StreamExportDialog.test.tsx create mode 100644 desktop/src/components/db-viewer/StreamExportDialog.tsx create mode 100644 desktop/src/stores/dbViewerStore.diff.test.ts diff --git a/AGENTS.md b/AGENTS.md index 6b80a91..bbc6ddb 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -237,8 +237,9 @@ Planned work is prioritized in the [Project Roadmap](./ROADMAP.md) (source of tr ### Connection Management | Feature | Status | Details | | :--- | :---: | :--- | -| Connections CRUD (PostgreSQL, MySQL, SQLite, Redis) | ✅ | Full create/read/update/delete with form validation | -| New Connection screen (revamped) | ✅ | Two-stage entry → configured flow: Connection URI + 6-card provider grid (PostgreSQL / MySQL / SQLite / Redis / Supabase / NeonDB) with an OR divider → expands into label + tags/env/folder + General|SSH·SSL tabs. Supabase & NeonDB are managed-PostgreSQL presets (persist as `postgresql`) with in-app setup guides + SSL hints; SQLite swaps the URI field for a file-path + Browse input (v0.7.0) | +| Connections CRUD (PostgreSQL, MySQL, SQLite, Redis, MariaDB) | ✅ | Full create/read/update/delete with form validation | +| MariaDB connections | ✅ | First-class db_type on the MySQL driver path (v0.8.0) | +| New Connection screen (revamped) | ✅ | Two-stage entry → configured flow: Connection URI + 6-card provider grid (PostgreSQL / MySQL / SQLite / Redis / Supabase / NeonDB) with an OR divider → expands into label + tags/env/folder + General|SSH·SSL tabs. Supabase & NeonDB are managed-PostgreSQL presets (persist as `postgresql`) with in-app setup guides + SSL hints; PlanetScale is a managed-MySQL (Vitess) preset (persists as `mysql`) with a setup guide + `.psdb.cloud` host detection (v0.8.0); SQLite swaps the URI field for a file-path + Browse input (v0.7.0) | | Connection testing (all DB types) | ✅ | PostgreSQL, MySQL, SQLite, Redis all testable | | DB Viewer: PostgreSQL browse + query | ✅ | Schemas, tables, paginated data, FK preview, JSON viewer | | DB Viewer: SQLite browse + query | ✅ | Full support via rusqlite | @@ -295,7 +296,7 @@ Planned work is prioritized in the [Project Roadmap](./ROADMAP.md) (source of tr | Column show/hide | ✅ | Toggle visibility per column | | Column resize (drag handle) | ✅ | Double-click to auto-fit | | Row selection (checkboxes + select all) | ✅ | Bulk copy (JSON/CSV/SQL) and delete | -| Export toolbar (JSON, CSV, SQL, Markdown, Excel (.xlsx)) | ✅ | Client-side Blob download of visible rows; Excel (.xlsx) via client-side workbook generation (v0.7.8) | +| Export toolbar (JSON, CSV, SQL, Markdown, Excel (.xlsx)) | ✅ | Client-side Blob download of visible rows; Excel (.xlsx) via client-side workbook generation (v0.7.8); plus Rust-side **Export all rows to file…** (full-result CSV/JSONL/JSON streaming with progress + cancel) (v0.8.0) | | Excel (.xlsx) export | ✅ | Client-side .xlsx export of visible rows alongside JSON/CSV/SQL/Markdown (v0.7.8) | | Auto-refresh timer | ✅ | Configurable interval in settings | | Changes queue (INSERT, UPDATE, DELETE, bulk_insert, empty_table, drop_table) | ✅ | Stage → **Commit All**. Tab bar **Changes** button (amber border + count badge when pending) toggles a **popover** anchored to it: header with **Visual/SQL** toggle (cards showing op badge + table + description + per-change **Revert**, or a generated-SQL preview via `buildChangeSql`), footer **Clear All** + **Commit All (N)** with **⌘S/Ctrl+S** shortcut. Committed cards show a green ✓ (failed ✗); committing `drop_table` auto-closes open tabs of that table. **Insert Row** adds an editable pending row at the top of the grid (accent outline); committing inserts only the filled columns so serial/identity/generated defaults apply | @@ -346,6 +347,7 @@ Planned work is prioritized in the [Project Roadmap](./ROADMAP.md) (source of tr | Schema visualizer (ER diagram) | ✅ | Full React Flow ER diagram with dagre auto-layout, crow's foot notation, schema selector, legend with cardinality colors, collapsible columns (PK/FK/unique-only), cross-schema FK support. PostgreSQL (single round-trip LATERAL query) + SQLite (PRAGMA). Uses @xyflow/react + dagre. | | Create/Edit table + column-diff + rebuild | ✅ | Create Table + Edit Table column-diff editor (ADD/DROP/RENAME/ALTER TYPE/SET|DROP DEFAULT/SET|DROP NOT NULL, staged one-per-queue-item); atomic column-reorder table rebuild in a single transaction, preserving constraints/indexes/FKs/grants/sequences (v0.7.7) | | Relationships (FK CRUD, cross-schema, ON DELETE/UPDATE) | ✅ | FK create/edit/drop with cross-schema references and ON DELETE/UPDATE actions (v0.7.7) | +| TimescaleDB hypertables | ✅ | Objects view type on PG connections with the extension; runtime availability gating (v0.8.0) | ### Query Editor | Feature | Status | Details | @@ -355,7 +357,7 @@ Planned work is prioritized in the [Project Roadmap](./ROADMAP.md) (source of tr | Destructive query guard | ✅ | Confirmation dialog for INSERT/UPDATE/DELETE/DROP/ALTER/TRUNCATE/CREATE/REPLACE (`isDestructiveQuery` + `DestructiveQueryDialog`) | | Query history / recent queries | ✅ | v5 `query_history` table + v6 `favorite` column; consecutive-identical dedup + retention pruning (500/connection); `get_query_history`/`clear_query_history`/`set_history_favorite` commands; **QueryHistoryDropdown** in the query toolbar (load / run / favorite / clear, lazy fetch, loading + error states) | | SQL autocomplete (keywords, tables, columns) | ✅ | Completion provider in `src/lib/monacoSetup.ts` backed by `src/lib/sqlCompletion.ts` (pure, unit-tested): keywords (~60) + table names from the active schema; typing `table.` or `schema.table.` suggests that table's columns (introspected via `get_schema_graph`, cached per schema in memory, `incomplete: true` warm-up on first use) | -| Multiple result sets | ❌ | | +| Multiple result sets | ✅ | Stacked panels per statement via execute_query_multi; DML/DDL notices; stop-at-first-error (v0.8.0) | | Cancel long-running queries | ✅ | Per-connection cancel from the query toolbar (`pg_cancel_backend` / MySQL `KILL` / SQLite interruption) instead of waiting or killing the app (v0.7.8) | | Saved queries (named, organized) | ✅ | v6 `queries` table (nullable `connection_id` for global queries, `folder` field, `ON DELETE CASCADE`); `save_query`/`get_saved_queries`/`update_saved_query`/`delete_saved_query` commands with validation (name ≤200, folder ≤100, text ≤1MB); **SaveQueryDialog** (name + folder, empty-name guard); managed in the Queries view Saved tab | | Query favorites / pinning | ✅ | Star toggle per history entry via `set_history_favorite`; favorites-only filter in the Queries view History tab | @@ -374,6 +376,7 @@ Planned work is prioritized in the [Project Roadmap](./ROADMAP.md) (source of tr | Bundled PostgreSQL client tools | ✅ | Static pg_dump/pg_restore/psql shipped as Tauri resources; system-first, bundled-fallback resolution via resource_dir (v0.7.5) | | SQLite .dump (backup/restore) | ✅ | Backup a SQLite database to a portable SQL dump and restore it back, matching the pg_dump UX (v0.7.8) | | Backup / Restore / Sync for MySQL & SQLite | ✅ | MySQL backup/restore via mysqldump (system-first); DB-to-DB sync extended beyond PostgreSQL (v0.7.8) | +| Schema diff / compare | ✅ | Tools → Schema Diff; same-engine snapshot diff; safe items stage into the changes queue (v0.8.0) | | Table structure export (DDL) | ❌ | | ### Settings diff --git a/README.md b/README.md index 9f1032f..b088773 100644 --- a/README.md +++ b/README.md @@ -30,16 +30,16 @@ ## Download -Grab the installer for your OS from the [latest release](https://git.ranio.xyz/adrianbonpin/gridline/releases/latest) — the links below point at the current release (**v0.7.15**): +Grab the installer for your OS from the [latest release](https://git.ranio.xyz/adrianbonpin/gridline/releases/latest) — the links below point at the current release (**v0.8.0**): | OS | Architecture | Download | | :--------------------------- | :--------------------------- | :----------------------------------------------------------------------------------------------------------------------------------- | -| **macOS** | Apple Silicon (M1/M2/M3/M4…) | [Gridline_0.7.15_aarch64.dmg](https://git.ranio.xyz/adrianbonpin/gridline/releases/download/v0.7.15/Gridline_0.7.15_aarch64.dmg) | -| **macOS** | Intel | [Gridline_0.7.15_x64.dmg](https://git.ranio.xyz/adrianbonpin/gridline/releases/download/v0.7.15/Gridline_0.7.15_x64.dmg) | -| **Windows** | x64 | [Gridline_0.7.15_x64-setup.exe](https://git.ranio.xyz/adrianbonpin/gridline/releases/download/v0.7.15/Gridline_0.7.15_x64-setup.exe) | -| **Debian / Ubuntu** | amd64 | [Gridline_0.7.15_amd64.deb](https://git.ranio.xyz/adrianbonpin/gridline/releases/download/v0.7.15/Gridline_0.7.15_amd64.deb) | -| **Fedora / RHEL / openSUSE** | x86_64 | [Gridline-0.7.15-1.x86_64.rpm](https://git.ranio.xyz/adrianbonpin/gridline/releases/download/v0.7.15/Gridline-0.7.15-1.x86_64.rpm) | -| **Other Linux** | amd64 | [Gridline_0.7.15_amd64.AppImage](https://git.ranio.xyz/adrianbonpin/gridline/releases/download/v0.7.15/Gridline_0.7.15_amd64.AppImage) | +| **macOS** | Apple Silicon (M1/M2/M3/M4…) | [Gridline_0.8.0_aarch64.dmg](https://git.ranio.xyz/adrianbonpin/gridline/releases/download/v0.8.0/Gridline_0.8.0_aarch64.dmg) | +| **macOS** | Intel | [Gridline_0.8.0_x64.dmg](https://git.ranio.xyz/adrianbonpin/gridline/releases/download/v0.8.0/Gridline_0.8.0_x64.dmg) | +| **Windows** | x64 | [Gridline_0.8.0_x64-setup.exe](https://git.ranio.xyz/adrianbonpin/gridline/releases/download/v0.8.0/Gridline_0.8.0_x64-setup.exe) | +| **Debian / Ubuntu** | amd64 | [Gridline_0.8.0_amd64.deb](https://git.ranio.xyz/adrianbonpin/gridline/releases/download/v0.8.0/Gridline_0.8.0_amd64.deb) | +| **Fedora / RHEL / openSUSE** | x86_64 | [Gridline-0.8.0-1.x86_64.rpm](https://git.ranio.xyz/adrianbonpin/gridline/releases/download/v0.8.0/Gridline-0.8.0-1.x86_64.rpm) | +| **Other Linux** | amd64 | [Gridline_0.8.0_amd64.AppImage](https://git.ranio.xyz/adrianbonpin/gridline/releases/download/v0.8.0/Gridline_0.8.0_amd64.AppImage) | **macOS via Homebrew** (recommended for Mac users): @@ -57,7 +57,7 @@ The cask installs the app directly. The DMGs are Developer-ID signed and notariz > **macOS first launch:** Gridline is Developer-ID signed and notarized, so macOS opens it without a Gatekeeper prompt. Not sure if your Mac is Intel or Apple Silicon? See [Which file should I download?](#which-file-should-i-download) below.