Support EXPLAIN FORMAT JSON for Table Model#17430
Open
JackieTien97 wants to merge 8 commits intomasterfrom
Open
Support EXPLAIN FORMAT JSON for Table Model#17430JackieTien97 wants to merge 8 commits intomasterfrom
JackieTien97 wants to merge 8 commits intomasterfrom
Conversation
- Fix ExplainAnalyzeOperator to only instantiate the needed drawer (TEXT or JSON), avoiding wasted work - Replace hand-concatenated JSON in mergeExplainResultsJson with Gson to prevent injection from unescaped CTE names - Add proper imports in PlanGraphJsonPrinter, replace FQN with simple class names - Use JsonArray for list-type properties instead of String.valueOf() - Fix ExplainAnalyze.equals()/hashCode() to include outputFormat and verbose - Add Javadoc to ExplainOutputFormat documenting valid formats per statement - Default MPPQueryContext.explainOutputFormat to TEXT instead of null - Mark old 5-arg ExplainAnalyzeOperator constructor @deprecated - Improve testExplainInvalidFormat to assert on error message content - Add common pitfalls section to CLAUDE.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #17430 +/- ##
============================================
- Coverage 39.75% 39.74% -0.02%
Complexity 312 312
============================================
Files 5134 5138 +4
Lines 346907 347385 +478
Branches 44194 44267 +73
============================================
+ Hits 137907 138054 +147
- Misses 209000 209331 +331 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
JackieTien97
added a commit
to JackieTien97/iotdb-profiler
that referenced
this pull request
Apr 3, 2026
Requires apache/iotdb#17430 to be merged for EXPLAIN (FORMAT JSON) support.
The grammar change added optional '(' FORMAT identifier ')' to EXPLAIN
and EXPLAIN ANALYZE rules, so '(' is now a valid expected token in
parser error messages.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
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.




Summary
FORMAToption toEXPLAINandEXPLAIN ANALYZEstatements in the Table Model, allowing users to choose the output format (JSON, GRAPHVIZ, or TEXT)Syntax
Supported formats:
GRAPHVIZTEXTJSONExamples
1. EXPLAIN (FORMAT JSON)
Output (single row, single JSON object representing the distributed plan tree):
{ "name": "OutputNode-12", "id": "12", "properties": { "OutputColumns": ["time", "deviceid", "voltage"], "OutputSymbols": ["time", "deviceid", "voltage"] }, "children": [ { "name": "CollectNode-11", "id": "11", "children": [ { "name": "ExchangeNode-9", "id": "9", "children": [ { "name": "DeviceTableScanNode-7", "id": "7", "properties": { "QualifiedTableName": "testdb.testtb", "OutputSymbols": ["time", "deviceid", "voltage"], "DeviceNumber": "1", "ScanOrder": "ASC", "PushDownOffset": "0", "PushDownLimit": "0", "PushDownLimitToEachDevice": "false", "RegionId": "4" } } ] } ] } ] }2. EXPLAIN (FORMAT JSON) with CTE
When CTEs are present, the JSON wraps the plan with
cteQueriesandmainQuery:{ "cteQueries": [ { "name": "cte1", "plan": { "name": "OutputNode-...", "id": "...", ... } } ], "mainQuery": { "name": "OutputNode-...", "id": "...", "properties": { ... }, "children": [ ... ] } }3. EXPLAIN ANALYZE (FORMAT JSON)
Output (single row, single JSON object with plan statistics + fragment instances):
{ "planStatistics": { "analyzeCostMs": 12.5, "fetchPartitionCostMs": 1.2, "fetchSchemaCostMs": 0.8, "logicalPlanCostMs": 3.1, "logicalOptimizationCostMs": 2.0, "distributionPlanCostMs": 1.5, "dispatchCostMs": 0.9 }, "fragmentInstancesCount": 3, "fragmentInstances": [ { "id": "queryId.fragmentId.instanceId", "ip": "127.0.0.1:10730", "dataRegion": "virtual_data_region", "state": "FINISHED", "totalWallTimeMs": 50.0, "initDataQuerySourceCostMs": 5.0, "seqFileUnclosed": 0, "seqFileClosed": 0, "unseqFileUnclosed": 0, "unseqFileClosed": 0, "readyQueuedTimeMs": 1.0, "blockQueuedTimeMs": 0.5, "queryStatistics": { "timeSeriesIndexFilteredRows": 0, "chunkIndexFilteredRows": 0, "pageIndexFilteredRows": 0 }, "operators": { "planNodeId": "1", "nodeType": "IdentitySinkNode", "operatorType": "IdentitySinkOperator", "cpuTimeMs": 2.0, "outputRows": 5, "hasNextCalledCount": 5, "nextCalledCount": 4, "estimatedMemorySize": 1024, "specifiedInfo": { "DownStreamPlanNodeId": "2" }, "children": [ ... ] } } ] }4. EXPLAIN ANALYZE VERBOSE (FORMAT JSON)
Same structure as
EXPLAIN ANALYZE (FORMAT JSON), butqueryStatisticsincludes additional verbose fields:{ "queryStatistics": { "loadBloomFilterFromCacheCount": 0, "loadBloomFilterFromDiskCount": 0, "loadBloomFilterActualIOSize": 0, "loadBloomFilterTimeMs": 0.0, "loadTimeSeriesMetadataFromCacheCount": 0, "loadTimeSeriesMetadataFromDiskCount": 0, "loadTimeSeriesMetadataActualIOSize": 0, "loadChunkFromCacheCount": 0, "loadChunkFromDiskCount": 0, "loadChunkActualIOSize": 0, "timeSeriesIndexFilteredRows": 0, "chunkIndexFilteredRows": 0, "pageIndexFilteredRows": 0, "rowScanFilteredRows": 0, "loadTimeSeriesMetadataAlignedMemSeqCount": 2, "loadTimeSeriesMetadataAlignedMemSeqTimeMs": 0.1, "pageReadersDecodeAlignedMemCount": 2, "pageReadersDecodeAlignedMemTimeMs": 0.05 } }5. Invalid format produces clear error
Key Design Decisions
{ "name", "id", "properties", "children" }, mirroring the existing GRAPHVIZ box-drawing format.operatorsfield uses a nested{ "planNodeId", "nodeType", "operatorType", "cpuTimeMs", "outputRows", ..., "children" }structure with runtime statistics.(FORMAT ...)clause is entirely optional.Test Plan
PlanGraphJsonPrinter(plan node → JSON conversion)ExplainFormatTest(SQL parsing of FORMAT clause)EXPLAIN (FORMAT JSON)basic queryEXPLAIN ANALYZE (FORMAT JSON)with plan statistics and fragment instancesEXPLAIN ANALYZE VERBOSE (FORMAT JSON)with verbose query statisticsFORMAT GRAPHVIZandFORMAT TEXT🤖 Generated with Claude Code