1#pragma once
2
3#include <sstream>
4#include <common/logger_useful.h>
5#include <Poco/Util/Application.h>
6
7#include <Parsers/IAST.h>
8
9namespace DB
10{
11
12/// If output stream set dumps node with indents and some additional info. Do nothing otherwise.
13/// Allow to print kay-value pairs inside of tree dump.
14class DumpASTNode
15{
16public:
17 DumpASTNode(const IAST & ast_, std::ostream * ostr_, size_t & depth, const char * label_ = nullptr)
18 : ast(ast_),
19 ostr(ostr_),
20 indent(depth),
21 visit_depth(depth),
22 label(label_)
23 {
24 if (!ostr)
25 return;
26 if (label && visit_depth == 0)
27 (*ostr) << "-- " << label << std::endl;
28 ++visit_depth;
29
30 (*ostr) << String(indent, ' ');
31 printNode();
32 (*ostr) << std::endl;
33 }
34
35 ~DumpASTNode()
36 {
37 if (!ostr)
38 return;
39 --visit_depth;
40 if (label && visit_depth == 0)
41 (*ostr) << "--" << std::endl;
42 }
43
44 template <typename T, typename U>
45 void print(const T & name, const U & value, const char * str_indent = nullptr) const
46 {
47 if (!ostr)
48 return;
49
50 (*ostr) << (str_indent ? String(str_indent) : String(indent, ' '));
51 (*ostr) << '(' << name << ' ' << value << ')';
52 if (!str_indent)
53 (*ostr) << std::endl;
54 }
55
56 size_t & getDepth() { return visit_depth; }
57
58private:
59 const IAST & ast;
60 std::ostream * ostr;
61 size_t indent;
62 size_t & visit_depth; /// shared with children
63 const char * label;
64
65 String nodeId() const { return ast.getID(' '); }
66
67 void printNode() const
68 {
69 (*ostr) << nodeId();
70
71 String alias = ast.tryGetAlias();
72 if (!alias.empty())
73 print("alias", alias, " ");
74
75 if (!ast.children.empty())
76 print("children", ast.children.size(), " ");
77 }
78};
79
80inline void dumpAST(const IAST & ast, std::ostream & ostr, DumpASTNode * parent = nullptr)
81{
82 size_t depth = 0;
83 DumpASTNode dump(ast, &ostr, (parent ? parent->getDepth() : depth));
84
85 for (const auto & child : ast.children)
86 dumpAST(*child, ostr, &dump);
87}
88
89
90/// String stream dumped in dtor
91template <bool _enable>
92class DebugASTLog
93{
94public:
95 DebugASTLog()
96 : log(nullptr)
97 {
98 if constexpr (_enable)
99 log = &Poco::Logger::get("AST");
100 }
101
102 ~DebugASTLog()
103 {
104 if constexpr (_enable)
105 LOG_DEBUG(log, ss.str());
106 }
107
108 std::ostream * stream() { return (_enable ? &ss : nullptr); }
109
110private:
111 Poco::Logger * log;
112 std::stringstream ss;
113};
114
115
116}
117