new feature: EXPLAIN (format sql) ..query..#11
Open
peterboncz wants to merge 2 commits into
Open
Conversation
will now explain the query as a SQL stetement (similar to how this works in Umbra)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add EXPLAIN (FORMAT SQL)
Summary
Adds a new
EXPLAINformat, SQL, that returns the query's optimized logical plan rendered back as equivalent CTE-based SQL (the LPTS output) — analogous to how Umbra can print a plan as SQL.It behaves like a genuine
EXPLAINfor every client: the CLI renders it borderless (raw multi-line text, no duckbox, no escaped \n), and JDBC/Python/ADBC receive the same two-column (explain_key, explain_value)result they get from any
EXPLAIN, with the SQL in explain_value.Motivation
DuckDB supports
EXPLAIN (FORMAT json|html|text|…)but has no sql format. The goal was for EXPLAIN (FORMAT SQL) Q to be treated identically to a nativeEXPLAINby all clients and by the CLI renderer — not alook-alike result set that the CLI boxes.
How it works
EXPLAIN (FORMAT SQL) Qis not a libpg syntax error — libpg parses it, then transform throws Invalid Input Error: "sql" is not a valid FORMAT argument. So the parse_function parser-extension flow never fires. Twocooperating hooks handle it instead, with no changes to the duckdb/ submodule:
EXPLAIN ( FORMAT SQL )token prefix (via Parser::Tokenize, so comments/whitespace are handled correctly) and returns a real ExplainStatement. Because the overridehas no ClientContext (and therefore can't run LPTS), it carries the inner query to the next stage via a sentinel string constant embedded in the explain's inner statement. Declines everything else, so all other
queries — including normal
EXPLAIN— are untouched.LogicalExplaincarrying the sentinel, it runs the existing LPTS pipeline (PlanQuery → LogicalPlanToAst → AstToCteList → ToQuery, identical to PRAGMAlpts) and replaces the plan with a LogicalColumnDataGet emitting a single ("logical_opt", ) row.
Since the statement type stays
EXPLAIN_STATEMENT, the CLI's ModeExplainRenderer prints the value verbatim and clients see the standardEXPLAINresult shape. Conversion failures (catalog errors, unsupportedoperators) propagate as normal query errors.
The override requires allow_parser_override_extension = FALLBACK, which the extension enables on load.
Testing
for native
EXPLAIN, EXPLAIN (FORMAT JSON), unknown formats, and normal queries.