Class PlanEstimates

java.lang.Object
com.darkcollective.relix.plan.PlanEstimates

public final class PlanEstimates extends Object
The estimated row count the planner computed for each node of a physical plan — the numbers behind Planner.buildSide and the merge-versus-hash choice, kept so :explain can show them.

Why beside the plan and not on it

PhysicalNode is a sealed hierarchy of records. Carrying the estimate as a component would touch every arm and every construction site, and — the deciding argument — it would make the estimate part of node identity: two structurally identical plans costed under different statistics would stop being equals, which is a property the plan itself has no business having. A side table keeps the nodes clean and matches what SchemaAnnotations already does for logical nodes.

Identity, not equality

The map is an IdentityHashMap, because two sibling nodes of a plan can easily be equals — A ⨝ A is a legal self-join, and its two Scans are equal records — while being estimated in different contexts. Keying on equality would let one overwrite the other.

Unknown is not zero

rows returns OptionalLong.empty() both for a node the planner never estimated and for one whose estimate the cost model declined to make. That is deliberately not collapsed to 0: the estimator is documented as honest, returning empty rather than fabricating a number when a contributing leaf has no row count, and a plan step that will produce nothing is a materially different claim from one nobody costed. Renderers must keep the two apart — rows=? versus rows=0, null versus 0 in JSON.

Instances are mutable during planning and effectively immutable afterwards; they are not thread-safe, and a Planner plans one root.

  • Constructor Details

    • PlanEstimates

      public PlanEstimates()
      Creates an empty set of estimates.
  • Method Details

    • none

      public static PlanEstimates none()
      Returns a shared empty instance — every lookup is unknown. Use it where a plan is rendered outside a planning run (a hand-built plan in a test, or a printer call that has no estimates to hand).
      Returns:
      the empty estimates; never null
    • record

      public void record(PhysicalNode node, OptionalLong estimate)
      Records estimate for node, if it is present. An absent estimate is not stored, so "unknown" has exactly one representation.
      Parameters:
      node - the plan node; must not be null
      estimate - the estimated row count, or empty if the cost model declined
    • rows

      public OptionalLong rows(PhysicalNode node)
      Returns the estimated row count for node.
      Parameters:
      node - the plan node; must not be null
      Returns:
      the estimate, or empty when unknown — which is not zero
    • isEmpty

      public boolean isEmpty()
      Returns whether any estimate at all was recorded — the cheap test a renderer uses to decide whether to add a numeric column.
      Returns:
      true if at least one node has a known estimate