Add internal/planrender adapter for query plan rendering - #94
Merged
Merged
Conversation
Wrap experimental spannerplan v0.3.0 and spannerplanviz v0.11.0 behind Format/Options/Render so the CLI can later emit text and graph plans without leaking library types. v0.11.0 is required for Go 1.25 and the occurrence-aware parent-link API. Linking the adapter into a scratch CLI adds about 124 KiB without Graphviz and about 6.0 MiB more for wazero; all eight CGO_ENABLED=0 release targets build.
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
internal/planrenderadapter renders Spanner query plans as text, DOT, Mermaid, D2, SVG, or PNG from a rows-less ResultSet envelope (metadata.rowType+stats).main.gobehavior change.--plan-format=text|dot|mermaid|d2|svg|pngwiring waits for the split-output feature.github.com/apstndb/spannerplan v0.3.0andgithub.com/apstndb/spannerplanviz v0.11.0. Nonographvizbuild tag in this PR.API
Package
internal/planrender(v0/experimental libraries stay behind this boundary; onlyspannerpbtypes leak):type Format stringwithFormatText,FormatDOT,FormatMermaid,FormatD2,FormatSVG,FormatPNGParseFormat(string) (Format, error)Format.IsBinary() bool(true for PNG)Format.NeedsGraphviz() bool(true for SVG/PNG)type Options struct { TextStyle, WrapWidth, PrintSections, Full, ShowQuery, ShowQueryStats, Query }TextStyle=current,WrapWidth=0,PrintSections=basicStructureBuildOptions;FullselectsFullBuildOptionsRender(ctx, w, format, rowType, stats, opts) errorreference.RenderTreeTableWithOptions(..., RenderModeAuto, ...)visualize.BuildPlan(rowType, stats, buildOpts)thendot/mermaid/d2renderers, orgraphviz.NewRenderer(...).Renderfor SVG/PNGExtractQueryPlanJSON round trip);rowTypemay be nilErrNoQueryPlan(--query-mode=PLAN, PROFILE, or WITH_PLAN_AND_STATS)Renderer.RenderDependencies
github.com/apstndb/spannerplangithub.com/apstndb/spannerplanvizv0.11.0 is the published tag (local checkout was v0.10.2). Indirectly pulls
goccy/go-graphviz v0.2.10andtetratelabs/wazero v1.10.1(pure Go,CGO_ENABLED=0).golang.org/x/textmovesv0.37.0→v0.38.0viagolang.org/x/image.Measurements
Scratch CLI builds that keep
planrender.Renderlive (not committed). Baseline isorigin/main5dbad3bin.tmp/baseline-main.origin/mainCLIdot/mermaid/d2/text)nographvizlater.Cross-compile (
CGO_ENABLED=0 go build ./internal/planrender/...andgo vet)linux/386 and windows/386 build; wazero has no optimizing compiler on 386 (interpreter fallback). Not benchmarked here.
govulncheck
govulncheck ./...exit 1 (findings). Same two call-site vulns onorigin/main:google.golang.org/grpc@v1.81.1(fixed v1.82.1)main.go/internal/grpctestgolang.org/x/text(fixed v0.39.0)< v0.39.0); this PR only moved 0.37.0 → 0.38.0No new vulnerability IDs. Not upgraded here (out of library-adapter scope).
Tests
go build ./...go vet ./...go test ./internal/planrender ./params/... ./jqresult/... ./resultset/...GOTOOLCHAIN=go1.25.13 golangci-lint rungolangci-lint run(host go1.27.1)samber/lo/math/rand/v2; reran with Go 1.25.13)govulncheck ./...DOCKER_HOST=unix://$HOME/.colima/default/docker.sock TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE=/var/run/docker.sock go test ./...planrender coverage: PROFILE and PLAN-style AUTO text goldens (
testdata/profile/singers_limit3.json); DOT/Mermaid/D2 smoke (root operator); one SVG (<svg) and one PNG (magic bytes) on a 1-node plan, skippable with-short; nil/empty plan, dangling childIndex, DAG repeated child, cycle, Unicode/control predicates, option validation matrix, cancelled graph context.Follow-up
CLI wiring after split-output lands:
--plan-format=text\|dot\|mermaid\|d2\|svg\|pngand the text/graph tuning flags fromdocs/design/plan-rendering.md, dispatchingjson/yamllocally and everything else toplanrender.Render.