fix(mysql): display all result sets from stored procedures returning multiple result sets#415
fix(mysql): display all result sets from stored procedures returning multiple result sets#415debba wants to merge 3 commits into
Conversation
…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
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Files Reviewed (17 files)
Reviewed by nemotron-3-nano-30b-a3b:free · Input: 593.4K · Output: 5.5K · Cached: 111.6K |
|
Hi @debba |
|
if you'd like to test the fix before it lands in a release, you can build the app on your machine. Tabularis is a Tauri 2 app (Rust backend + React frontend), so you'll need:
Then, in PowerShell: git clone https://github.com/TabularisDB/tabularis.git If you want a standalone binary instead of the dev mode, use: pnpm tauri build --no-bundle and you'll find the portable executable at src-tauri\target\release\tabularis.exe (--no-bundle also skips the updater-signing step that would otherwise require our private signing key). Let us know if the fix works with your real stored procedures! |
Fixes #414
Problem
When executing a MySQL statement that returns multiple result sets — typically a
CALLto a stored procedure whose body contains severalSELECTs — Tabularis only displayed the first result set. MySQL Workbench shows all of them.Root cause
exec_on_mysql_connconsumed the wire stream with sqlx'sfetch(), 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 singleQueryResult { 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 loopingmysql_next_result()after enablingCLIENT_MULTI_RESULTS.Fix
Backend
exec_on_mysql_connnow uses sqlx'sfetch_many(), whose event stream interleaves rows with one terminator per result set.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.QueryResultgains an optionaladditional_results: Option<Vec<QueryResult>>. The first result set stays incolumns/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
QueryResultTS type mirrors the new field.execute_queryreturns additional result sets,runQueryrenders 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 neweditor.multiResult.resultSetPrefixi18n key (added to all 8 locales).activeTable/pkColumns) is intentionally skipped — procedure output is not row-editable.Note on
DELIMITERCreating the procedure still requires the usual client-side
DELIMITERdance (see the snippet above):DELIMITERis not server SQL, it only tells the client's statement splitter to stop splitting on the;inside the procedure body. Tabularis' SQL splitter already supportsDELIMITER //for the MySQL dialect, exactly like themysqlCLI and Workbench — so when testing this PR, remember to wrap theCREATE PROCEDUREinDELIMITER //…END//, otherwise the procedure itself won't be created (that part is expected behaviour, not part of this bug).Testing
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 2additional_results; a plainSELECTis byte-for-byte identical to before (no extras, pagination unchanged).cargo test(mysql driver suite): 30 passed, including 7 new unit tests forResultSetCollector(set splitting, per-set truncation, empty-set handling, unterminated stream flush).pnpm test: 2711 passed, including 7 new tests forcreateEntriesFromResultSets.cargo checkclean (no deprecated API),tsc --noEmitclean.Known limitations
CALL. Same pre-existing limitation as a rowless single query.additional_resultsfrom the backend, but its UI still shows one result per statement; expanding extra sets there is left as a follow-up.zh.jsonis missing severaleditor.multiResult.*keys (queryPrefix,viewTabs, …) — only the new key was added here.