Skip to content

feat(studio): dump a database to the filesystem from the connection context menu - #255

Merged
remcostoeten merged 2 commits into
masterfrom
feat/dump-database-to-file
Sep 16, 2026
Merged

remcostoeten merged 2 commits into
masterfrom
feat/dump-database-to-file

Conversation

@remcostoeten

@remcostoeten remcostoeten commented Sep 16, 2026 •

Copy link
Copy Markdown
Owner

Adds a Dump to File entry to the connection context menu, enabled only while the connection is live, and fixes the dumps so the output can actually be re-imported.

What was broken

The dump_database backend command already existed but was surfaced only as "Backup". Its output was not re-importable: the Postgres, MySQL and libsql dumps wrote bare INSERTs with no DDL, and the Postgres value formatter turned timestamps, uuid, jsonb, arrays and bytea into NULL.

What changed

Each dump now emits DDL first, then data, then foreign keys, so rows load before any constraint is enforced.

  • Postgres resolves column types through format_type — information_schema reports "ARRAY" and "USER-DEFINED" — emits CREATE TYPE for the enums the dumped columns use, and setval for sequences.
  • MySQL uses SHOW CREATE TABLE and brackets the data with FOREIGN_KEY_CHECKS toggles.
  • libsql takes its DDL from sqlite_master and loads inside a transaction.
  • Values are formatted binary-safely; writes are buffered.

The save target follows the engine: .sql for Postgres/MySQL/libsql, .sqlite for SQLite, and a folder for DuckDB, whose EXPORT DATABASE writes schema and Parquet side by side. SQLite and DuckDB were already correct and are untouched.

Capability fixes

Two runtime gaps found by reading the capability set, both invisible to the test suite because it never goes through the UI:

  • The DuckDB folder picker calls open({ directory: true }), but only dialog:allow-save was granted — the call would have been rejected.
  • handleRestoreDatabase calls open, ask and readTextFile, and none of the three were permitted. Restore was broken at runtime. Adds dialog:allow-ask and fs:allow-read-text-file.

Verification

cargo test --lib 291 passed; DORA_LIVE_DB_TESTS=1 live suite 10/10; studio typecheck clean; vitest 1117 passed; oxfmt/oxlint clean. New round-trip tests for Postgres and MySQL dump, drop, restore, compare every value, then assert foreign keys and sequences still work. Dump and Restore were also exercised by hand in the running app.

Summary by Sourcery

Enable database dumps from the desktop connection menu and produce reliable, re-importable exports across supported engines.

New Features:

  • Add a Dump to File action to live connection context menus, with engine-appropriate file or folder destinations.

Bug Fixes:

  • Make PostgreSQL, MySQL, and libSQL dumps self-contained and re-importable by preserving schema, data, constraints, sequences, and binary or complex values.
  • Restore database operations and DuckDB directory dumps work with the required desktop runtime permissions.

Enhancements:

  • Generate database dumps with buffered output and engine-specific schema and data export handling.

Tests:

  • Add PostgreSQL and MySQL live round-trip tests covering value preservation, foreign keys, and sequences.

Summary by CodeRabbit

  • New Features

    • Added an option to dump connected databases to a selected file from the connection menu.
    • Supports database-specific output formats, including SQL files, SQLite files, and DuckDB directories.
    • Added desktop dialog and file-access permissions required for database exports.
  • Bug Fixes

    • Improved database dumps to be self-contained and restorable, including schema, relationships, sequences, enums, binary values, and special characters.
    • Corrected PostgreSQL bigint auto-increment schema generation.

…ontext menu

Adds a "Dump to File" entry to the connection context menu, enabled only
while the connection is live. The save target follows the engine: a .sql
file for Postgres, MySQL and libsql, a .sqlite file for SQLite, and a
folder for DuckDB, whose EXPORT DATABASE writes schema and Parquet side
by side.

The backend command already existed but its output was not re-importable.
The Postgres, MySQL and libsql dumps wrote bare INSERTs with no DDL, and
the Postgres value formatter turned timestamps, uuid, jsonb, arrays and
bytea into NULL. Each dump now emits DDL first, then data, then foreign
keys, so rows load before any constraint is enforced:

- Postgres resolves column types through format_type, since
  information_schema reports "ARRAY" and "USER-DEFINED"; emits CREATE TYPE
  for the enums the dumped columns use, and setval for sequences.
- MySQL uses SHOW CREATE TABLE and brackets the data with
  FOREIGN_KEY_CHECKS toggles.
- libsql takes its DDL from sqlite_master and loads inside a transaction.

Values are formatted binary-safely and writes are buffered.

Round-trip tests for Postgres and MySQL dump, drop, restore, compare every
value, and then assert that foreign keys and sequences still work.
handleRestoreDatabase opens a file picker, asks for confirmation and reads
the selected file, but the capability set granted none of those: only
dialog:allow-save and fs:allow-write-text-file were present, so every one
of the three calls was rejected at runtime.

Adds dialog:allow-ask and fs:allow-read-text-file; dialog:allow-open
arrived with the dump feature in the previous commit.
@vercel

vercel Bot commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
dora Ready Ready Preview Sep 16, 2026 7:41am UTC

@remcostoeten remcostoeten added the feat New user-facing feature label Sep 16, 2026
@remcostoeten
remcostoeten merged commit d31a85f into master Sep 16, 2026
5 of 6 checks passed

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @remcostoeten, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 4 days and 16 hours by commenting @sourcery-ai review. Upgrade to get a review now.

@remcostoeten
remcostoeten deleted the feat/dump-database-to-file branch September 16, 2026 07:39
@coderabbitai

coderabbitai Bot commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: fa2968e8-28a3-40bc-a413-083522c3b23c

📥 Commits

Reviewing files that changed from the base of the PR and between e50a690 and ce32847.

📒 Files selected for processing (8)
  • apps/desktop/src-tauri/capabilities/default.json
  • apps/desktop/src-tauri/src/database/maintenance.rs
  • apps/desktop/src-tauri/src/database/services/schema_export.rs
  • apps/desktop/src-tauri/tests/live_db_tests.rs
  • packages/studio/src/features/connections/components/connection-switcher.tsx
  • packages/studio/src/features/sidebar/database-sidebar.tsx
  • packages/studio/src/pages/workspace/use-connection-actions.ts
  • packages/studio/src/pages/workspace/workspace-shell.tsx

📝 Walkthrough

Walkthrough

The PR adds self-contained PostgreSQL, SQLite, and MySQL dump generation with restore tests. It adds a desktop connection action that selects an output path, invokes the dump command, and reports the result.

Changes

Database dump export

Layer / File(s) Summary
Dump foundation and PostgreSQL export
apps/desktop/src-tauri/src/database/maintenance.rs, apps/desktop/src-tauri/src/database/services/schema_export.rs
Shared writers and SQL literal helpers support PostgreSQL schema, enum, data, foreign-key, and sequence export. PostgreSQL type resolution preserves enum and bigint auto-increment definitions.
SQLite and MySQL dump restoration
apps/desktop/src-tauri/src/database/maintenance.rs, apps/desktop/src-tauri/tests/live_db_tests.rs
SQLite dumps include definitions and transaction guards. MySQL dumps include SHOW CREATE TABLE definitions and foreign-key guards. Binary values use hex literals. Live tests restore PostgreSQL and MySQL dumps and validate rows, foreign keys, and sequences.
Desktop dump action
apps/desktop/src-tauri/capabilities/default.json, packages/studio/src/features/connections/components/connection-switcher.tsx, packages/studio/src/features/sidebar/database-sidebar.tsx, packages/studio/src/pages/workspace/use-connection-actions.ts, packages/studio/src/pages/workspace/workspace-shell.tsx
Connected connections expose a “Dump to File” action. The action selects a directory for DuckDB or a file for other databases, invokes commands.dumpDatabase, and reports success or failure. Desktop dialog and filesystem permissions are enabled.

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant ConnectionSwitcher
  participant DatabaseSidebar
  participant useConnectionActions
  participant TauriDialog
  participant commands.dumpDatabase
  ConnectionSwitcher->>DatabaseSidebar: select Dump to File
  DatabaseSidebar->>useConnectionActions: handleDumpConnection(connectionId)
  useConnectionActions->>TauriDialog: select output path
  TauriDialog-->>useConnectionActions: selected path
  useConnectionActions->>commands.dumpDatabase: dump connection to path
  commands.dumpDatabase-->>useConnectionActions: dump result
Loading
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/dump-database-to-file

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sourcery-ai

sourcery-ai Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Adds a desktop-only, live-connection “Dump to File” workflow with engine-specific output targets and rebuilds PostgreSQL, MySQL, and libSQL exports as buffered, re-importable dumps containing schema, data, and correctly ordered constraints. The change also fixes Tauri permissions and adds round-trip and formatting coverage.

Sequence diagram for dumping a live database to a file

sequenceDiagram
    actor User
    participant Sidebar
    participant Actions as useConnectionActions
    participant Dialog as TauriDialog
    participant Backend as dumpDatabase
    participant File as DumpFile

    User->>Sidebar: Select Dump to File
    Sidebar->>Actions: handleDumpConnection(connectionId)
    Actions->>Dialog: save or open
    Dialog-->>Actions: outputPath
    Actions->>Backend: dumpDatabase(connectionId, outputPath)
    Backend->>File: write DDL, data, constraints
    File-->>Backend: DumpResult
    Backend-->>Actions: DumpResult
    Actions-->>User: Dump complete toast
Loading

Flow diagram for re-importable SQL dump generation

flowchart TD
    Start["Start dump"] --> Schema["Read and resolve schema"]
    Schema --> DDL["Write DDL"]
    DDL --> Data["Write buffered INSERT data"]
    Data --> Constraints["Write foreign keys and sequence resets"]
    Constraints --> Flush["Flush output"]
    Flush --> Result["Return DumpResult"]
Loading

File-Level Changes

Change Details Files
Adds a live-connection context-menu flow for dumping databases to engine-appropriate filesystem targets.
  • Adds a disabled-while-offline “Dump to File” action and propagates it through the sidebar and workspace action layers.
  • Opens a save dialog for SQL/SQLite files and a directory picker for DuckDB exports.
  • Invokes the dump command with progress, success, cancellation, and error toasts; sanitizes default filenames.
packages/studio/src/features/connections/components/connection-switcher.tsx
packages/studio/src/features/sidebar/database-sidebar.tsx
packages/studio/src/pages/workspace/use-connection-actions.ts
packages/studio/src/pages/workspace/workspace-shell.tsx
Reworks PostgreSQL, MySQL, and libSQL dumps into buffered, self-contained, re-importable exports.
  • Emits database-specific DDL before data and defers foreign keys until after inserts.
  • Preserves PostgreSQL types, enums, sequences, and complex values through catalog resolution and text-safe formatting.
  • Uses MySQL SHOW CREATE TABLE, foreign-key checks, and binary-safe literals.
  • Uses sqlite_master definitions, explicit value handling, and a transaction for libSQL.
  • Centralizes buffered writing, flushing, result reporting, and SQL literal/hex encoding helpers.
apps/desktop/src-tauri/src/database/maintenance.rs
apps/desktop/src-tauri/src/database/services/schema_export.rs
Expands verification around dump fidelity and restore behavior.
  • Adds PostgreSQL and MySQL live round-trip tests covering complex values, constraints, and sequences.
  • Adds unit coverage for binary escaping, ANSI literals, and deferred foreign-key DDL generation.
apps/desktop/src-tauri/tests/live_db_tests.rs
apps/desktop/src-tauri/src/database/maintenance.rs
Corrects Tauri runtime permissions required by dump and restore flows.
  • Allows directory selection for DuckDB dumps.
  • Grants dialog confirmation and text-file read permissions used by restore.
apps/desktop/src-tauri/capabilities/default.json

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

This branch was successfully deployed

1 active deployment
Preview — ce328473 Deployed Sep 16, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat New user-facing feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant