7#define q(X) '"' << X << '"'
8#define id(X) q(std::hex << &X << std::dec)
21 indent() <<
"forcelabels=true;";
22 indent() <<
"graph [fontname = \"DejaVu Sans\"];";
23 indent() <<
"node [fontname = \"DejaVu Sans\"];";
24 indent() <<
"edge [fontname = \"DejaVu Sans\"];";
31 out <<
"\n}" << std::endl;
34void ASTDot::cluster(Const<Clause> &c,
const char *name,
const char *label,
const char *color)
36 indent() <<
"subgraph cluster_" << name <<
'_' << &c;
39 indent() <<
"style=\"rounded,filled\";";
40 indent() <<
"color=\"" << color <<
"\";";
41 indent() <<
"penwidth=\"4\";";
42 indent() <<
id(c) <<
" [label=\"" << label <<
"\"];";
53void ASTDot::operator()(Const<ErrorExpr> &e)
55 indent() <<
id(e) <<
" [label=<<FONT COLOR=\"red\"><B>ErrorExpr</B></FONT>>];";
58void ASTDot::operator()(Const<Designator> &e)
60 indent() <<
id(e) <<
" [label=<<B>";
62 if (e.has_explicit_table_name())
out << e.table_name.text <<
'.';
63 out << e.attr_name.text <<
"</B>";
65 std::ostringstream oss;
68 if (
auto pt = cast<const PrimitiveType>(e.type()))
69 out <<
"<SUB>" << (pt->is_scalar() ?
"s" :
"v") <<
"</SUB>";
75 const auto &t = e.target();
76 if (
auto val = std::get_if<const Attribute*>(&t)) {
79 <<
" [style=\"dashed\",dir=\"forward\",color=\"#404040\"];";
80 }
else if (
auto val = std::get_if<const Expr*>(&t)) {
82 indent() <<
id(e) <<
EDGE <<
id(*expr) <<
" [style=\"dashed\",dir=\"forward\",color=\"crimson\"];";
86void ASTDot::operator()(Const<Constant> &e)
98 std::ostringstream oss;
100 out <<
"<FONT POINT-SIZE=\"11\"><I> : " <<
html_escape(oss.str()) <<
"</I></FONT>";
106void ASTDot::operator()(Const<FnApplicationExpr> &e)
112 std::ostringstream oss;
114 out <<
"<FONT POINT-SIZE=\"11\"><I> : " <<
html_escape(oss.str()) <<
"</I></FONT>";
120 for (
auto &arg : e.args) {
126void ASTDot::operator()(Const<UnaryExpr> &e)
132 std::ostringstream oss;
134 out <<
"<FONT POINT-SIZE=\"11\"><I> : " <<
html_escape(oss.str()) <<
"</I></FONT>";
141void ASTDot::operator()(Const<BinaryExpr> &e)
148 std::ostringstream oss;
150 out <<
"<FONT POINT-SIZE=\"11\"><I> : " <<
html_escape(oss.str()) <<
"</I></FONT>";
158void ASTDot::operator()(Const<QueryExpr> &e)
161 indent() <<
id(e) <<
" [label=<QueryExpr";
164 std::ostringstream oss;
166 out <<
"<FONT POINT-SIZE=\"11\"><I> : " <<
html_escape(oss.str()) <<
"</I></FONT>";
176void ASTDot::operator()(Const<ErrorClause> &c)
178 indent() <<
id(c) <<
" [label=\"ErrorClause\"];";
181void ASTDot::operator()(Const<SelectClause> &c)
185 indent() <<
q(std::hex << c <<
'*') <<
"[label=\"*\"];";
188 for (
auto &s : c.select) {
192 indent() <<
id(s.second) <<
" [label=\"AS " << s.second.text <<
"\"];";
201void ASTDot::operator()(Const<FromClause> &c)
203 for (
auto &t : c.from) {
205 if (
auto name = std::get_if<Token>(&t.source)) {
207 indent() <<
id(t.alias) <<
" [label=\"AS " << t.alias.text <<
"\"];";
208 indent() <<
id (*name) <<
" [label=\"" << name->text <<
"\"];";
211 indent() <<
id(*name) <<
" [label=\"" << name->text <<
"\"];";
214 }
else if (
auto stmt = std::get_if<Stmt*>(&t.source)) {
215 M_insist(t.alias,
"nested statements must have an alias");
216 indent() <<
id(t.alias) <<
" [label=\"AS " << t.alias.text <<
"\"];";
223 M_insist(std::holds_alternative<Token>(t.source));
224 auto &name = std::get<Token>(t.source);
226 indent() <<
id(name) <<
EDGE << R.name() <<
":n [dir=\"forward\",color=\"#404040\"];";
231void ASTDot::operator()(Const<WhereClause> &c)
238void ASTDot::operator()(Const<GroupByClause> &c)
240 for (
auto &[grp, alias] : c.group_by) {
247void ASTDot::operator()(Const<HavingClause> &c)
254void ASTDot::operator()(Const<OrderByClause> &c)
256 for (
auto &o : c.order_by) {
259 indent() <<
id(o.second) <<
" [label=\"ASC\"];";
261 indent() <<
id(o.second) <<
" [label=\"DESC\"];";
268void ASTDot::operator()(Const<LimitClause> &c)
271 indent() <<
id(c.limit) <<
" [label=<<B>" << c.limit.text <<
"</B>>];";
276 indent() <<
id(c.offset) <<
" [label=<OFFSET <B>" << c.offset.text <<
"</B>>];";
284void ASTDot::operator()(Const<PrimaryKeyConstraint> &c)
286 indent() <<
id(c) <<
" [label=<<B>PRIMARY KEY</B>>];";
289void ASTDot::operator()(Const<UniqueConstraint> &c)
291 indent() <<
id(c) <<
" [label=<<B>UNIQUE</B>>];";
294void ASTDot::operator()(Const<NotNullConstraint> &c)
296 indent() <<
id(c) <<
" [label=<<B>NOT NULL</B>>];";
299void ASTDot::operator()(Const<CheckConditionConstraint> &c)
302 indent() <<
id(c) <<
" [label=<<B>CHECK()</B>>];";
306void ASTDot::operator()(Const<ReferenceConstraint> &c)
308 indent() <<
id(c) <<
" [label=<<B>REFERENCES " << c.table_name.text <<
'(' << c.attr_name.text <<
")</B>>];";
317 std::ostringstream oss;
324void ASTDot::operator()(Const<ErrorStmt>&)
329void ASTDot::operator()(Const<EmptyStmt>&)
334void ASTDot::operator()(Const<CreateDatabaseStmt>&)
339void ASTDot::operator()(Const<DropDatabaseStmt>&)
344void ASTDot::operator()(Const<UseDatabaseStmt>&)
349void ASTDot::operator()(Const<CreateTableStmt>&)
354void ASTDot::operator()(Const<DropTableStmt>&)
359void ASTDot::operator()(Const<CreateIndexStmt>&)
364void ASTDot::operator()(Const<DropIndexStmt>&)
369void ASTDot::operator()(Const<SelectStmt> &s)
372 std::ostringstream oss;
373 indent() <<
id(s) <<
" [label=\"SelectStmt\"];";
377 indent() <<
"subgraph sources";
380 if (
auto f = cast<FromClause>(s.from.get())) {
381 for (
auto &t : f->from) {
385 indent() << R.name() <<
"[shape=none,style=filled,fillcolor=white,label=<";
389 indent() <<
"<TR><TD BORDER=\"0\"><B>" << R.name() <<
"</B></TD></TR>";
395 <<
"<FONT POINT-SIZE=\"11\"><I> : " <<
html_escape(oss.str()) <<
"</I></FONT>"
410 cluster(*s.select,
"select",
"SELECT",
"#e6194B20");
413#define DOT(NAME, LABEL, COLOR) \
416 cluster(*s.NAME, #NAME, LABEL, COLOR); \
417 indent() << id(s) << EDGE << id(*s.NAME) << ';'; \
419 DOT(from,
"FROM",
"#bfef4550");
420 DOT(where,
"WHERE",
"#42d4f430");
421 DOT(group_by,
"GROUP BY",
"#3cb44b30");
422 DOT(having,
"HAVING",
"#aaffc350");
423 DOT(order_by,
"ORDER BY",
"#ffe11950");
424 DOT(limit,
"LIMIT",
"#80800040");
428void ASTDot::operator()(Const<InsertStmt>&)
433void ASTDot::operator()(Const<UpdateStmt>&)
438void ASTDot::operator()(Const<DeleteStmt>&)
443void ASTDot::operator()(Const<DSVImportStmt>&)
#define DOT(NAME, LABEL, COLOR)
#define M_unreachable(MSG)
std::ostream & indent(std::ostream &out, unsigned indentation)
Start a new line with proper indentation.
::wasm::Expression * expr()
Moves the underlying Binaryen ::wasm::Expression out of this.
std::string M_EXPORT html_escape(std::string str)
Escapes special characters in a string to be printable in HTML documents.
const PrimitiveType * type
the type of the attribute
const Table & table
the table the attribute belongs to
ThreadSafePooledString name
the name of the attribute
virtual const ThreadSafePooledString & name() const =0
Returns the name of the Table.
static constexpr const char *const GRAPH_TYPE
ASTDot(std::ostream &out, int indent=0)
std::ostream & out
the output stream to print to
static constexpr const char *const EDGE
int indent_
the current indentation for pretty printing
Token tok
the token of the Instruction; starts with \
ThreadSafePooledOptionalString text
declared as optional for dummy tokens