Skip to content

fix(mysql): display all result sets from stored procedures returning multiple result sets#415

Open
debba wants to merge 1 commit into
mainfrom
fix/mysql-multi-result-sets
Open

fix(mysql): display all result sets from stored procedures returning multiple result sets#415
debba wants to merge 1 commit into
mainfrom
fix/mysql-multi-result-sets

Conversation

@debba

@debba debba commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Fixes #414

Problem

When executing a MySQL statement that returns multiple result sets — typically a CALL to a stored procedure whose body contains several SELECTs — Tabularis only displayed the first result set. MySQL Workbench shows all of them.

DELIMITER //
CREATE PROCEDURE sp_test()
BEGIN
    SELECT 'First result' AS message;
    SELECT 'Second result' AS message;
    SELECT 'Third result' AS message;
END//
DELIMITER ;

CALL sp_test();  -- Tabularis showed only "First result"

Root cause

exec_on_mysql_conn consumed the wire stream with sqlx's fetch(), which yields a flat stream of rows with no result-set boundaries: column metadata was taken from the first row and everything was folded into a single QueryResult { columns, rows }. The data model itself had no way to represent more than one result set per statement. This is the same thing MySQL Workbench handles by looping mysql_next_result() after enabling CLIENT_MULTI_RESULTS.

Fix

Backend

  • exec_on_mysql_conn now uses sqlx's fetch_many(), whose event stream interleaves rows with one terminator per result set.
  • New pure helper drivers/mysql/multi_result.rs (ResultSetCollector) folds that stream back into discrete sets; the per-page row cap now applies to each result set independently.
  • QueryResult gains an optional additional_results: Option<Vec<QueryResult>>. The first result set stays in columns / rows, so every consumer unaware of multi-result statements keeps working unchanged; the field is skipped in JSON when absent, leaving Postgres/SQLite/plugin drivers untouched.

Frontend

  • QueryResult TS type mirrors the new field.
  • When execute_query returns additional result sets, runQuery renders them through the existing multi-result tab UI (the one used for multi-statement runs): one tab per result set, labelled "Result 1..N" via the new editor.multiResult.resultSetPrefix i18n key (added to all 8 locales).
  • Row-editing metadata (activeTable / pkColumns) is intentionally skipped — procedure output is not row-editable.

Note on DELIMITER

Creating the procedure still requires the usual client-side DELIMITER dance (see the snippet above): DELIMITER is not server SQL, it only tells the client's statement splitter to stop splitting on the ; inside the procedure body. Tabularis' SQL splitter already supports DELIMITER // for the MySQL dialect, exactly like the mysql CLI and Workbench — so when testing this PR, remember to wrap the CREATE PROCEDURE in DELIMITER //END//, otherwise the procedure itself won't be created (that part is expected behaviour, not part of this bug).

Testing

  • End-to-end: ran the actual driver path (drivers::mysql::execute_query) against a live MariaDB with the reproducer procedure from the issue — the call now returns the first set as primary plus 2 additional_results; a plain SELECT is byte-for-byte identical to before (no extras, pagination unchanged).
  • cargo test (mysql driver suite): 30 passed, including 7 new unit tests for ResultSetCollector (set splitting, per-set truncation, empty-set handling, unterminated stream flush).
  • pnpm test: 2711 passed, including 7 new tests for createEntriesFromResultSets.
  • cargo check clean (no deprecated API), tsc --noEmit clean.

Known limitations

  • A result set that produces zero rows is dropped: sqlx exposes no column metadata without rows, which makes it indistinguishable from the trailing OK packet of a CALL. Same pre-existing limitation as a rowless single query.
  • The batch path (multiple statements in one run) already receives additional_results from the backend, but its UI still shows one result per statement; expanding extra sets there is left as a follow-up.
  • Pre-existing gap spotted while translating: zh.json is missing several editor.multiResult.* keys (queryPrefix, viewTabs, …) — only the new key was added here.

…e result sets

A single MySQL statement can stream back several result sets — e.g. a
CALL to a stored procedure whose body holds multiple SELECTs. The driver
consumed the stream with sqlx fetch(), which flattens everything into
one columns/rows pair, so only the first result set ever reached the UI.

Switch exec_on_mysql_conn to fetch_many(), whose event stream marks the
boundary between result sets, and fold it with a new ResultSetCollector
(drivers/mysql/multi_result.rs). The first set stays in QueryResult
columns/rows; the rest travel in a new optional additional_results field
(skipped in JSON when absent, so other drivers and plugins are
unaffected). The per-page row cap now applies to each result set
independently.

On the frontend, execute_query results carrying additional_results are
rendered through the existing multi-result tab UI (one tab per result
set, labelled via the new editor.multiResult.resultSetPrefix i18n key)
instead of the single grid.

Known limitation: result sets that produce no rows are dropped — sqlx
exposes no column metadata without rows, making them indistinguishable
from the trailing OK packet of a CALL. The batch path already receives
additional_results but its UI still shows one result per statement.

Fixes #414
@kilo-code-bot

kilo-code-bot Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (17 files)
  • src-tauri/src/drivers/mysql/mod.rs
  • src-tauri/src/drivers/mysql/multi_result.rs
  • src-tauri/src/drivers/mysql/tests.rs
  • src-tauri/src/drivers/postgres/mod.rs
  • src-tauri/src/drivers/sqlite/mod.rs
  • src-tauri/src/models.rs
  • src/i18n/locales/de.json
  • src/i18n/locales/en.json
  • src/i18n/locales/es.json
  • src/i18n/locales/fr.json
  • src/i18n/locales/it.json
  • src/i18n/locales/ja.json
  • src/i18n/locales/ru.json
  • src/i18n/locales/zh.json
  • src/pages/Editor.tsx
  • src/types/editor.ts
  • src/utils/multiResult.ts
  • tests/utils/multiResult.test.ts

Reviewed by nemotron-3-nano-30b-a3b:free · Input: 593.4K · Output: 5.5K · Cached: 111.6K

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: MySQL stored procedures returning multiple result sets only display the first result set

1 participant