Skip to content

Releases: apstndb/spannerplan

v0.3.0

Choose a tag to compare

@apstndb apstndb released this 22 Jul 04:08
6ec3ae9

Highlights

  • Added tableless query-plan rendering through asciitable.RenderTableless, plantree/reference layout configuration, and rendertree --layout=tableless / --tableless. The existing table layout remains the default.
  • Added the experimental plantree.StructuralSignature API for deterministic, occurrence-ordered comparison of visible relational plan structure.
  • Plantree traversal now preserves repeated DAG occurrences, rejects relational cycles, applies conservative depth and occurrence budgets, and uses occurrence-local parent-link classification.
  • Added a machine-readable ecosystem matrix and a non-blocking pinned-reference integrity canary.

Breaking changes from v0.2.1

  • Removed the deprecated plantree.RowWithPredicates.Keys and .ChildLinks
    fields. Use ScalarChildLinks for typed scalar child-link data.
  • Removed plantree.ContinuationIndent, ContinuationIndentTree,
    ContinuationIndentNodePrefix, and WithContinuationIndent. Use
    WithHangingIndent() for node-prefix hanging; omit the option for the
    tree-aligned default.
  • Removed the nested github.com/apstndb/spannerplan/protoyaml compatibility package. Import github.com/apstndb/protoyaml directly.
  • Replaced QueryPlan.GetLinkType(link) with QueryPlan.LinkTypeInParent(parent, rawChildLinkIndex). Consumers that filter child links must preserve the index from the parent’s raw ChildLinks slice.
  • Removed the deprecated rendertree --custom and --full-scan forms. Use --custom-file or repeatable --custom-column, and use --known-flag for known flags.
  • Adding Layout to plantree/reference.RenderConfig can break unkeyed Go struct literals; use keyed literals.
  • Plantree rendering and StructuralSignature now reject plans deeper than 256
    edges from the root or containing more than 4,096 visible node occurrences.
    Handle these failures with
    errors.Is(err, plantree.ErrTraversalLimitExceeded) and inspect
    *plantree.TraversalLimitError when limit details are needed.

Compatibility and stability

This is the first non-prerelease release in the v0.3.0 train. It remains a ZeroVer (v0) release and does not promise v1 API stability. The structural-signature token remains spannerplan.structural_signature.v1alpha1 and may change in a future v0 release.

Existing rendering calls and serialized configurations continue to use the prior table layout when layout is omitted. The tableless output is human-oriented text: literal | characters are not escaped, trailing empty cells are omitted, and center-aligned cells are emitted without centering.

Downstream migrations were validated locally against v0.3.0-alpha.3, which
has the same library and CLI source as this release. The final source differs
from alpha.3 only in version-independent README release guidance. Consumers of
spannerplanviz need a version migrated from GetLinkType to occurrence-local
LinkTypeInParent; applications that depend on it transitively should upgrade
that dependency at the same time.

Verification

  • Release commit: 6ec3ae9e5e567c70efb5216995037f6f77bce156
  • Library and CLI source verified unchanged from v0.3.0-alpha.3; the only
    post-alpha.3 source change is README release guidance
  • go test -v ./... with Go 1.24.13
  • go vet ./... with Go 1.24.13
  • golangci-lint v2.12.2 with Go 1.24.13 — 0 issues
  • govulncheck v1.5.0 with Go 1.26.5 — no reachable vulnerabilities
  • Local alpha.3 migration gates for spanner-mycli, spannerplanviz, rendertree-web, spannerplan-rs, and the unpublished TUI
  • Hosted test and lint checks for the README-only PR #62

v0.3.0-alpha.3

v0.3.0-alpha.3 Pre-release
Pre-release

Choose a tag to compare

@apstndb apstndb released this 22 Jul 00:09
7138723

Highlights

  • Added asciitable.RenderTableless, which renders caller-defined rows without table borders or headers using a one-character | separator. Multiline cells, including empty physical lines, and display-width-aware right alignment are preserved without padding wide text columns back to table width.
  • Added rendertree --layout=tableless and the --tableless shortcut. The existing table layout remains the default.
  • Added plantree/reference.Layout, the LayoutTable and LayoutTableless constants, ParseLayout, WithLayout, and RenderConfig.Layout so Go, WebAssembly, and JSON-configured consumers can select the tableless layout.
  • Added focused coverage for multiline rows, empty cells, wrapped compact plans, inline execution statistics, CLI flag conflicts, and reference renderer configuration.

Compatibility

Existing callers and serialized configurations remain on the byte-compatible table layout when the layout field is omitted or empty. Go callers should use keyed reference.RenderConfig literals; adding the Layout field can break unkeyed literals. The tableless representation is human-oriented text rather than an escaped serialization format: literal | is not escaped, trailing empty cells are omitted, empty physical lines and all-empty logical rows are preserved, and physical lines may contain different field counts. Center alignment is not supported by the unpadded tableless representation: center-aligned cells are emitted without centering.

Stability

This remains an intentionally unstable v0 prerelease. The new layout APIs and textual representation are not a stable v1 compatibility promise and may evolve during the v0.3.0 prerelease train.

Verification

  • go test -v ./...
  • go vet ./...
  • golangci-lint v2.12.2 with Go 1.24.13 — 0 issues
  • Hosted pull-request test and lint checks on exact head edce8c7c7377d22b6a76a384fd98c1d5160e445b
  • Clean origin/main verification after squash merge

v0.3.0-alpha.2

v0.3.0-alpha.2 Pre-release
Pre-release

Choose a tag to compare

@apstndb apstndb released this 17 Jul 22:29
a92d753

Highlights

  • Added the experimental plantree.StructuralSignature API for deterministic, occurrence-ordered comparison of visible relational plan structure.
  • The current encoding token is spannerplan.structural_signature.v1alpha1. It includes operator display names, parent link types, recursively typed metadata, predicates, and ordered DAG occurrences while excluding PlanNode IDs and execution statistics.
  • Metadata encoding is byte-length framed and key-sorted. Invalid, non-JSON, or forward-unknown protobuf states fail closed instead of producing an ambiguous signature.
  • Added ecosystem/matrix.json as the machine-readable source for the ecosystem tables in ECOSYSTEM.md, with validation and rendering checks.
  • Added a non-blocking scheduled/manual canary that verifies recorded public consumer refs and their pinned go.mod dependency content without claiming current downstream compatibility.

Stability

This remains an intentionally unstable v0 prerelease. The structural signature is a v1alpha1 experiment, not a stable v1 or cross-version interchange contract; its field set and encoding may change in later alpha releases. It is separate from any future external structured Plantree DTO.

Verification

  • go test ./...
  • go vet ./...
  • golangci-lint v2.12.2 — 0 issues
  • go run ./ecosystem/cmd/canary -live — all three recorded public pins passed
  • Pull-request CI for the ecosystem matrix/canary and structural signature changes

v0.3.0-alpha.1

v0.3.0-alpha.1 Pre-release
Pre-release

Choose a tag to compare

@apstndb apstndb released this 17 Jul 20:39
517f4e6

Highlights

  • Removed deprecated Go compatibility aliases and legacy Plantree row fields before v1.
  • Removed the nested github.com/apstndb/spannerplan/protoyaml compatibility package. Use github.com/apstndb/protoyaml v0.1.1 directly.
  • Removed the deprecated rendertree --custom and --full-scan forms. Custom columns remain available through --custom-file and repeatable --custom-column; known flags use --known-flag.
  • Plantree traversal now preserves repeated DAG occurrences while rejecting relational cycles on the active traversal path.
  • Replaced the ambiguous QueryPlan.GetLinkType(link) API with occurrence-local QueryPlan.LinkTypeInParent(parent, rawChildLinkIndex), so shared and repeated child nodes receive the correct edge label.
  • Added conservative Plantree renderer budgets: depth 256 (root depth 0) and 4,096 visible occurrences. Budget failures are available as typed errors and may be raised non-breakingly as real Spanner captures justify it.

Compatibility

This is an intentionally breaking prerelease in the v0 line. Stable or v1 compatibility is not implied. Current first-party consumers have migrated from the removed surfaces.

Verification

  • go test ./...
  • go vet ./...
  • golangci-lint v2.12.2

v0.2.1

Choose a tag to compare

@apstndb apstndb released this 08 Jul 03:30
4e46764

v0.2.1

Documentation and internal dependency housekeeping. No behavior changes; all rendered output and error strings are unchanged.

Added

  • ECOSYSTEM.md (#50): defines the roles of spannerplan, spannerplan-rs, spannerplanviz, and rendertree-web, the "text in libraries, rasterize at the edge" principle, governance rules (Go-first semantics changes, release-train-pinned parity CI, v0 semver policy), and a compatibility matrix.

Changed

  • The input path (ExtractQueryPlan and friends) now uses the extracted github.com/apstndb/protoyaml module (#51). Semantics are identical by construction (goccy YAML → protojson with DiscardUnknown); all tests pass with zero golden changes.

Deprecated

  • The in-repo protoyaml package is frozen and marked Deprecated (#51). Its Marshal output format was never a designed artifact (an accident of reflection-based encoding). New code should use github.com/apstndb/protoyaml, which implements the canonical protojson-over-YAML mapping. The frozen package will be removed in v0.3.0 now that spanner-mycli has migrated (apstndb/spanner-mycli#784).

v0.2.0

Choose a tag to compare

@apstndb apstndb released this 06 Jul 03:31
f6fcb29

Breaking Changes

  • New now returns *ValidationError for plan validation failures, including empty plan input. Existing errors.Is(err, ErrEmptyPlanNodes) and other category sentinel checks continue to work, and existing error message text is preserved. Code that compared returned errors by direct equality, such as err == ErrEmptyPlanNodes, should switch to errors.Is.

New Features

  • Added ErrInvalidPlan, an umbrella sentinel that matches every validation failure returned by New.
  • Added ValidationError, a structured validation error with Kind, NodeIndex, and ChildIndex fields so callers can inspect invalid plan input without depending on message text.
  • New now wraps both ErrInvalidPlan and the specific category sentinel for each validation failure, so callers can choose either broad or specific errors.Is checks.
  • Added executable documentation through ExampleNew_invalidPlan, showing both errors.Is and errors.As usage.

Compatibility Notes

  • Existing validation error strings are intentionally preserved in this release.
  • Existing category sentinels still match through errors.Is.
  • There are no dependency, CLI, or rendering-output changes in this release.

Validation

  • go test -v ./...
  • go vet ./...
  • golangci-lint run --timeout=5m
  • git diff --check v0.1.11..HEAD

v0.1.11

Choose a tag to compare

@apstndb apstndb released this 17 May 20:16
f5e48aa

v0.1.11

Patch release after v0.1.10.

Added

  • Added intent-based scalar appendix print presets: basic, enhanced, full, and none (#45).
  • Added preset parsing for rendertree --print and plantree/reference.ParsePrintSections, while preserving comma-separated low-level section names (#45).
  • Added public plantree/reference.PrintPreset, ParsePrintPreset, PrintPreset.Sections, and NewPrintSections helpers so callers can preserve the nil default versus explicit-empty PrintSections distinction (#45).
  • Added regression coverage for preset parsing, explicit empty/blank appendix suppression, preset/list validation, CLI config behavior, and public reference helpers (#45).
  • Added repository-level Gemini Code Assist configuration with code_review.comment_severity_threshold: HIGH (#46).

Changed

  • Updated rendertree --print help and README documentation to describe the new preset values and explicit empty suppression behavior (#45).
  • Improved repository README navigation with a pkg.go.dev badge and clearer package, command, example, and helper directory overview (#42).
  • Reorganized cmd/rendertree README sections into a clearer hierarchy (#42).

Validation

  • git diff --check v0.1.10..origin/main
  • go test ./...
  • mise x -- golangci-lint run --timeout=5m

v0.1.11-alpha.1

v0.1.11-alpha.1 Pre-release
Pre-release

Choose a tag to compare

@apstndb apstndb released this 17 May 20:05
f5e48aa

v0.1.11-alpha.1

Alpha prerelease for the next patch release after v0.1.10.

Added

  • Added intent-based scalar appendix print presets: basic, enhanced, full, and none (#45).
  • Added preset parsing for rendertree --print and plantree/reference.ParsePrintSections, while preserving comma-separated low-level section names (#45).
  • Added public plantree/reference.PrintPreset, ParsePrintPreset, PrintPreset.Sections, and NewPrintSections helpers so callers can preserve the nil default versus explicit-empty PrintSections distinction (#45).
  • Added regression coverage for preset parsing, explicit empty/blank appendix suppression, preset/list validation, CLI config behavior, and public reference helpers (#45).
  • Added repository-level Gemini Code Assist configuration with code_review.comment_severity_threshold: HIGH (#46).

Changed

  • Updated rendertree --print help and README documentation to describe the new preset values and explicit empty suppression behavior (#45).
  • Improved repository README navigation with a pkg.go.dev badge and clearer package, command, example, and helper directory overview (#42).
  • Reorganized cmd/rendertree README sections into a clearer hierarchy (#42).

Validation

  • git diff --check v0.1.10..origin/main
  • go test ./...
  • mise x -- golangci-lint run --timeout=5m

v0.1.10

Choose a tag to compare

@apstndb apstndb released this 16 May 15:32
3b3bcc1

Patch release for the rendering-helper and scalar-appendix work merged after v0.1.9.

Added

  • Added the public treerender package for generic ASCII tree rendering.
    • Provides Render, RenderTree, and RenderTreeWithOptions.
    • Provides DefaultStyle and CompactStyle.
    • Supports wrapping through RenderOptions.WrapWidth.
    • Supports continuation indentation modes including fixed-prefix and anchor-based hanging indentation.
    • Exposes Row.Text, Row.TreePartLines, PrefixMetrics, and related helpers for callers that need stable tree-prefix handling.
  • Added the public asciitable package for aligned table and appendix rendering.
    • Provides RenderTable with typed TableSpec and Column definitions.
    • Provides RenderAppendix with typed AppendixSpec definitions.
    • Supports left, right, and center alignment.
    • Preserves multiline table cells without wrapping them unexpectedly.
  • Added examples/pgexplainjson, a dependency-free PostgreSQL EXPLAIN (ANALYZE, FORMAT JSON) renderer that demonstrates the generic treerender and asciitable helpers.
    • Supports compact tree output.
    • Supports total-width wrapping.
    • Generates preorder IDs for PostgreSQL plans, which do not provide stable plan-node IDs.
  • Added scalar child-link accessors and documentation in plantree.
    • RowWithPredicates.TreePartLines exposes tree prefixes as one line per rendered node-text line.
    • RowWithPredicates.ScalarChildLinks preserves scalar child links in original PlanNode.ChildLinks order.
    • ScalarChildLink carries child index, type, variable, description, and the scalar child node.
    • RowWithPredicates.Keys and RowWithPredicates.ChildLinks remain populated as compatibility mirrors.
  • Added scalar appendix controls to cmd/rendertree.
    • --print=predicates,ordering,aggregate selects semantic appendix sections.
    • --print=typed prints all typed scalar links as a raw debug dump.
    • --print=full prints all scalar links, including unnamed links, as a raw debug dump.
    • --print="" suppresses appendix output.
    • --show-vars shows scalar assignment variable names.
    • --resolve-vars resolves direct scalar variable aliases.
    • --resolve-vars-recursive recursively expands scalar variable aliases for investigation.
  • Added scalar appendix controls to plantree/reference.
    • Added PrintSection, PrintSections, ParsePrintSection, and ParsePrintSections.
    • Added WithPrintSections, WithShowScalarVars, WithResolveScalarVars, and WithResolveScalarVarsRecursive.
    • Extended RenderConfig with PrintSections, ShowScalarVars, ResolveScalarVars, and ResolveScalarVarsRecursive.
    • RenderConfig.PrintSections distinguishes omitted/null config from an explicit empty list, so JSON [] can intentionally suppress appendices.
  • Added the shared internal internal/scalarappendix package used by both cmd/rendertree and plantree/reference.
    • Centralizes scalar appendix parsing, validation, rendering, and scalar variable resolution.
    • Keeps public packages as facades rather than exposing internal symbols.
  • Added Gemini review style-guide guidance to avoid readability-reducing micro-optimizations and to treat JSON tags as API design choices.

Changed

  • cmd/rendertree now reuses the shared scalar appendix implementation instead of carrying its own separate section parsing and rendering logic.
  • plantree/reference now renders appendices through the shared scalar appendix implementation.
  • asciitable appendix rendering was generalized beyond predicates through AppendixSpec and RenderAppendix.
  • treerender is now public instead of only being available under an internal package.
  • The unreleased predicate-specific asciitable compatibility API from the development branch was replaced by the more general appendix API before release.
  • treerender hanging-indent validation now requires GetContinuationAnchor only when wrapping is active.
  • The golangci-lint GitHub Actions workflow is pinned to a concrete v2 release.
  • Local review scratch files are ignored by git.

Fixed

  • WithHangingIndent and RenderConfig{HangingIndent: true} no longer fail when no wrap width is configured; without wrapping, hanging indent is a no-op.
  • Empty print-section strings now parse as an explicit empty section list, allowing callers to suppress appendix output.
  • Scalar appendix JSON config preserves explicit empty printSections slices while still treating omitted/null as the default predicate appendix.

Merged PRs

  • #39: feat: expose generic render helpers
  • #40: feat: add scalar appendix sections
  • #41: refactor: share scalar appendix rendering

Validation

  • go test ./...
  • mise x -- golangci-lint run --timeout=5m
  • git diff --check v0.1.9..origin/main

v0.1.9

Choose a tag to compare

@apstndb apstndb released this 06 May 20:04
2059f91

Changes

Added

  • Added QueryPlan.ParentLinks(childIndex) to return every incoming parent child link for a plan node, preserving stable plan traversal order and each parent's ChildLinks order.
  • Added ResolvedParentLink, containing the parent PlanNode and the ChildLink that points to the child node.
  • Added support for treating scalar Full Text Search Search Predicate child links as predicates in QueryPlan.IsPredicate, so downstream renderers can surface Full Text Search predicates without custom plan-shape logic.
  • Added QueryPlan, plantree, and reference renderer tests for simple and compound Full Text Search predicate shapes.
  • Added tests covering duplicate incoming links from the same parent, incoming links from multiple parents, empty and out-of-range ParentLinks lookups, returned-slice isolation, and compatibility with existing single-parent lookup behavior.

Changed

  • Preserved existing GetParentNodeByChildIndex behavior while adding the all-parent-links API, keeping the existing single-parent map compatible for current callers.
  • Clarified QueryPlan.IsVisible documentation: it controls operator-tree child-link visibility, hides scalar plan nodes unless the child link type is Scalar, and treats nil links as the root node.

Full Changelog