| 1656 | |
| 1657 | namespace { |
| 1658 | void printExprTree( |
| 1659 | const exec::Expr& expr, |
| 1660 | const std::string& indent, |
| 1661 | bool withStats, |
| 1662 | std::stringstream& out, |
| 1663 | std::unordered_map<const exec::Expr*, uint32_t>& uniqueExprs) { |
| 1664 | auto it = uniqueExprs.find(&expr); |
| 1665 | if (it != uniqueExprs.end()) { |
| 1666 | // Common sub-expression. Print the full expression, but skip the stats. |
| 1667 | // Add ID of the expression it duplicates. |
| 1668 | out << indent << expr.toString(true) << " -> " << expr.type()->toString(); |
| 1669 | out << " [CSE #" << it->second << "]" << std::endl; |
| 1670 | return; |
| 1671 | } |
| 1672 | |
| 1673 | uint32_t id = uniqueExprs.size() + 1; |
| 1674 | uniqueExprs.insert({&expr, id}); |
| 1675 | |
| 1676 | const auto& stats = expr.stats(); |
| 1677 | out << indent << expr.toString(false); |
| 1678 | if (withStats) { |
| 1679 | out << " [cpu time: " << succinctNanos(stats.timing.cpuNanos) |
| 1680 | << ", rows: " << stats.numProcessedRows |
| 1681 | << ", batches: " << stats.numProcessedVectors << "]"; |
| 1682 | } |
| 1683 | out << " -> " << expr.type()->toString() << " [#" << id << "]" << std::endl; |
| 1684 | |
| 1685 | auto newIndent = indent + " "; |
| 1686 | for (const auto& input : expr.inputs()) { |
| 1687 | printExprTree(*input, newIndent, withStats, out, uniqueExprs); |
| 1688 | } |
| 1689 | } |
| 1690 | } // namespace |
| 1691 | |
| 1692 | std::string Expr::toString(bool recursive) const { |