Repository navigation
Explain panel fails on Doris, StarRocks and TiDB: JSON format is a per-provider constant, not a per-engine capability #574
Description
Description
The MySQL provider declares explainFormat: "mysql-json" as a fixed capability in getCapabilities() (src/lib/db/providers/sql/mysql.ts), so the Explain button always sends EXPLAIN FORMAT='json' for every engine this provider connects to. Three of the MySQL-wire relatives it serves reject that exact statement with a parse error even though they accept a plain EXPLAIN: TiDB, StarRocks and Apache Doris. The Explain tab fails on all three, on every query, including a plain SELECT.
This is already recorded as backlog item X14 in docs/BACKLOG.md for SingleStore (a fourth relative with a different failure shape: SingleStore's own grammar is EXPLAIN JSON <select>, not EXPLAIN FORMAT='json', and it fails on both the prepared and text protocol). X14 also names StarRocks as "a separate case again" with the same EXPLAIN FORMAT='json' parse failure, and that entry is the one this issue extends: the underlying gap is the same for StarRocks, TiDB and Doris, and it is an explain-format problem, not a protocol problem.
Steps to Reproduce
- Connect LibreDB Studio to an Apache Doris, StarRocks or TiDB cluster as a MySQL connection.
- Run any query in the SQL editor, including a plain
SELECT. - Click the Explain button (or open the Explain tab).
Expected Behavior
Either the Explain panel renders a plan on these engines, using the statement form each one's grammar actually accepts, or the panel is withheld on an engine whose grammar this provider's explain strategy cannot express, with the provider docs stating which engines those are (matching X14's own two acceptable outcomes).
Actual Behavior
The Explain tab shows a query error instead of a plan: mismatched input '=' expecting {<EOF>, ';'}(line 1, pos 14) on Doris. A plain EXPLAIN typed directly into the editor and run as a statement works normally and returns the engine's own text plan on all three engines.
Environment
- LibreDB Studio Version: 0.13.7
- Browser: Chrome
- OS: Linux
- Node.js/Bun Version: Bun 1.3.10
- Database Type: Apache Doris, StarRocks, TiDB (all MySQL wire protocol)
- Database Version: Apache Doris
4.1.3-rc02-7126cf65d96(apache/doris:all-in-one-4.1.3)
Additional Context
src/lib/explain/mysql-json.ts is one strategy per format, and the type-id it serves is mysql for every wire-compatible relative alike. Per X14's own analysis, reaching a second spelling means either sniffing the engine inside the strategy, which this repo's provider rules forbid (no === "doris" or === "starrocks" equivalent exists and none should), or a capability the connection carries at runtime, which is the shape ProviderCapabilities already uses for exactly this kind of divergence. None of these four relatives self-identify through VERSION() (see labelServerVersion() and SELF_IDENTIFYING_VERSION in mysql.ts), so any runtime detection would need a separate signal, for example Doris's own @@version_comment.
Possible Solution
Per X14's own done-when criteria: either make the Explain statement a capability the connection declares at runtime rather than a constant baked into one strategy class, so SingleStore, StarRocks, TiDB and Doris can each declare the statement form their own grammar accepts, or withhold the Explain panel on an engine whose grammar this provider's strategy cannot express, and record in docs/providers/mysql.md which engines those are. Either path touches all four affected relatives, so it should be probed and verified against live containers for each rather than fixed for one and assumed for the rest.
Logs
ERROR 1105 (HY000) at line 1: errCode = 2, detailMessage =
mismatched input '=' expecting {<EOF>, ';'}(line 1, pos 14)
Activity
cevheri commentedon Sep 6, 2026
Sibling case on the PostgreSQL side, filed as #597:
postgres-json.tssendsEXPLAIN (ANALYZE, BUFFERS, FORMAT JSON)and Materialize rejects the parenthesised option list, while a plainEXPLAINworks there.Same root cause this issue names: the explain statement is a per-strategy constant rather than something the connection declares. Worth knowing while designing the capability here, since a mechanism that only reaches
mysql-json.tsleaves the identical gap in the other strategy.dchaudhari7177 commentedon Sep 6, 2026
Taking this one. Plan: make
explainFormata per-engine capability resolved from the detected variant rather than a provider constant, so Doris/StarRocks/TiDB get the statement form their grammar accepts, with a unit test per variant and the provider doc updated.cevheri commentedon Sep 6, 2026
sorry @dchaudhari7177, I started to develop :( 1hour ago
fix(mysql): read SHOW STATUS bare and measure the EXPLAIN grammar at …
fix(explain): measure the PostgreSQL EXPLAIN grammar at connect (#597) (