docs: public final void computeEstimatesRecursively(PlanStatistics stats,
                                                    DatabaseEstimates estimates,
                                                    ScalarValueHints[] paramHints)
      {
          assert(stats != null);
  
          m_outputColumnHints.clear();
          m_estimatedOutputTupleCount = 0;
  
          // recursively compute and collect stats from children
          long childOutputTupleCountEstimate = 0;
          for (AbstractPlanNode child : m_children) {
              child.computeEstimatesRecursively(stats, estimates, paramHints);
              m_outputColumnHints.addAll(child.m_outputColumnHints);
              childOutputTupleCountEstimate += child.m_estimatedOutputTupleCount;
          }
  
          // make sure any inlined scans (for NLIJ mostly) are costed as well
          for (Entry<PlanNodeType, AbstractPlanNode> entry : m_inlineNodes.entrySet()) {
              AbstractPlanNode inlineNode = entry.getValue();
              if (inlineNode instanceof AbstractScanPlanNode) {
                  inlineNode.computeCostEstimates(0, estimates, paramHints);
              }
          }
  
          computeCostEstimates(childOutputTupleCountEstimate, estimates, paramHints);
          stats.incrementStatistic(0, StatsField.TUPLES_READ, m_estimatedProcessedTupleCount);
      }