Skip to content

plantree: expose machine-readable plan tree output #30

Description

@apstndb

Problem

The current renderers are optimized for terminal/table output. plantree.ProcessPlan returns rows that are useful for ASCII rendering, but richer web UIs would benefit from a structured tree representation that does not require reverse-parsing rendered prefixes or table text.

Proposed design

Add an additive public API in plantree that exposes the visible relational plan tree as machine-readable data before ASCII row rendering.

Suggested type shape:

type PlanTreeNode struct {
    ID             int32                     `json:"id"`
    Text           string                    `json:"text"`
    LinkType       string                    `json:"linkType,omitempty"`
    Predicates     []PlanTreePredicate       `json:"predicates,omitempty"`
    ScalarLinks    map[string][]ScalarLink   `json:"scalarLinks,omitempty"`
    ExecutionStats stats.ExecutionStats      `json:"executionStats,omitempty"`
    Children       []*PlanTreeNode           `json:"children,omitempty"`
}

type PlanTreePredicate struct {
    Type        string `json:"type"`
    Description string `json:"description"`
    NodeID      int32  `json:"nodeId"`
}

type ScalarLink struct {
    Type        string `json:"type,omitempty"`
    Variable    string `json:"variable,omitempty"`
    NodeID      int32  `json:"nodeId"`
    Description string `json:"description"`
}

Add a public builder:

func ProcessPlanTree(qp *spannerplan.QueryPlan, opts ...Option) (*PlanTreeNode, error)

The function should use the same title formatting options as ProcessPlan, including WithQueryPlanOptions and EnableCompact, but it should not apply line wrapping or table rendering. Wrapping remains a renderer concern.

Semantics

  • Only visible relational nodes should appear as Children, matching ProcessPlan traversal.
  • Predicate function nodes should be represented in Predicates on their parent row/node, not as visible children.
  • Scalar child links should be represented in ScalarLinks, with enough information for UIs to display parameters without protobuf traversal.
  • Text should be the unwrapped node title including node-local link prefixes such as [Input] and [Map] when applicable.
  • LinkType should expose the link type separately so UIs do not have to parse [Input] out of Text.

Implementation notes

There is already an internal renderedNode tree used before ASCII rendering. The implementation can either:

  • convert that internal tree into the public PlanTreeNode shape, or
  • refactor the builder to produce the public structure first and derive render rows from it.

The first option is likely safer for an initial PR because it avoids broad renderer churn.

Tests

Add tests covering:

  • a small plan with input/map children keeps tree structure
  • predicates are attached to the expected node
  • scalar child links are exposed in ScalarLinks
  • formatting options affect Text consistently with ProcessPlan

Documentation

Document this as the preferred API for web UIs or other consumers that need structured data rather than rendered ASCII.

Notes

This should be additive and can coexist with RowWithPredicates and ProcessPlan.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions