Skip to content

Explain panel fails on Doris, StarRocks and TiDB: JSON format is a per-provider constant, not a per-engine capability #574

Closed

Description

@kaya-abdullah

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

  1. Connect LibreDB Studio to an Apache Doris, StarRocks or TiDB cluster as a MySQL connection.
  2. Run any query in the SQL editor, including a plain SELECT.
  3. 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

  1. added theissue type on Sep 6, 2026
  2. self-assigned this
    on Sep 6, 2026
  3. cevheri commented on Sep 6, 2026

    @cevheri
    Member

    Sibling case on the PostgreSQL side, filed as #597: postgres-json.ts sends EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON) and Materialize rejects the parenthesised option list, while a plain EXPLAIN works 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.ts leaves the identical gap in the other strategy.

  4. dchaudhari7177 commented on Sep 6, 2026

    @dchaudhari7177
    Contributor

    Taking this one. Plan: make explainFormat a 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.

  5. cevheri commented on Sep 6, 2026

    @cevheri
    Member

    Taking this one. Plan: make explainFormat a 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.

    sorry @dchaudhari7177, I started to develop :( 1hour ago

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions