LCOV - code coverage report
Current view: top level - src/parse - ASTDot.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 288 0.3 %
Date: 2025-03-25 01:19:55 Functions: 1 40 2.5 %
Branches: 0 542 0.0 %

           Branch data     Line data    Source code
       1                 :            : #include "parse/ASTDot.hpp"
       2                 :            : 
       3                 :            : #include <iomanip>
       4                 :            : #include <mutable/catalog/Schema.hpp>
       5                 :            : #include <sstream>
       6                 :            : 
       7                 :            : #define q(X) '"' << X << '"' // quote
       8                 :            : #define id(X) q(std::hex << &X << std::dec) // convert virtual address to identifier
       9                 :            : 
      10                 :            : 
      11                 :            : using namespace m;
      12                 :            : using namespace m::ast;
      13                 :            : 
      14                 :            : 
      15                 :          0 : ASTDot::ASTDot(std::ostream &out, int i)
      16                 :          0 :     : out(out)
      17                 :          0 :     , indent_(i)
      18                 :          0 : {
      19   [ #  #  #  # ]:          0 :     out << GRAPH_TYPE << " ast\n{";
      20                 :          0 :     ++indent_;
      21   [ #  #  #  # ]:          0 :     indent() << "forcelabels=true;";
      22   [ #  #  #  # ]:          0 :     indent() << "graph [fontname = \"DejaVu Sans\"];";
      23   [ #  #  #  # ]:          0 :     indent() << "node [fontname = \"DejaVu Sans\"];";
      24   [ #  #  #  # ]:          0 :     indent() << "edge [fontname = \"DejaVu Sans\"];";
      25                 :          0 : }
      26                 :            : 
      27                 :          0 : ASTDot::~ASTDot()
      28                 :          0 : {
      29                 :          0 :     --indent_;
      30         [ #  # ]:          0 :     M_insist(indent_ == 0);
      31   [ #  #  #  # ]:          0 :     out << "\n}" << std::endl;
      32                 :          0 : }
      33                 :            : 
      34                 :          0 : void ASTDot::cluster(Const<Clause> &c, const char *name, const char *label, const char *color)
      35                 :            : {
      36                 :          0 :     indent() << "subgraph cluster_" << name << '_' << &c;
      37                 :          0 :     indent() << '{';
      38                 :          0 :     ++indent_;
      39                 :          0 :     indent() << "style=\"rounded,filled\";";
      40                 :          0 :     indent() << "color=\"" << color << "\";";
      41                 :          0 :     indent() << "penwidth=\"4\";";
      42                 :          0 :     indent() << id(c) << " [label=\"" << label << "\"];";
      43                 :            : 
      44                 :          0 :     (*this)(c);
      45                 :            : 
      46                 :          0 :     --indent_;
      47                 :          0 :     indent() << '}';
      48                 :          0 : }
      49                 :            : 
      50                 :            : 
      51                 :            : /*--- Expressions ----------------------------------------------------------------------------------------------------*/
      52                 :            : 
      53                 :          0 : void ASTDot::operator()(Const<ErrorExpr> &e)
      54                 :            : {
      55                 :          0 :     indent() << id(e) << " [label=<<FONT COLOR=\"red\"><B>ErrorExpr</B></FONT>>];";
      56                 :          0 : }
      57                 :            : 
      58                 :          0 : void ASTDot::operator()(Const<Designator> &e)
      59                 :            : {
      60                 :          0 :     indent() << id(e) << " [label=<<B>";
      61                 :            : 
      62         [ #  # ]:          0 :     if (e.has_explicit_table_name()) out << e.table_name.text << '.';
      63                 :          0 :     out << e.attr_name.text << "</B>";
      64         [ #  # ]:          0 :     if (e.has_type()) {
      65                 :          0 :         std::ostringstream oss;
      66   [ #  #  #  # ]:          0 :         oss << *e.type();
      67   [ #  #  #  #  :          0 :         out << "<FONT POINT-SIZE=\"11\"><I> : " << html_escape(oss.str());
             #  #  #  # ]
      68   [ #  #  #  #  :          0 :         if (auto pt = cast<const PrimitiveType>(e.type()))
                   #  # ]
      69   [ #  #  #  #  :          0 :             out << "<SUB>" << (pt->is_scalar() ? "s" : "v") << "</SUB>";
          #  #  #  #  #  
                      # ]
      70         [ #  # ]:          0 :         out << "</I></FONT>";
      71                 :          0 :     }
      72                 :          0 :     out << ">];";
      73                 :            : 
      74                 :          1 :     /* Dot edge to table. */
      75                 :          0 :     const auto &t = e.target();
      76         [ #  # ]:          0 :     if (auto val = std::get_if<const Attribute*>(&t)) {
      77                 :          0 :         const Attribute &A = **val;
      78                 :          0 :         indent() << id(e) << EDGE << A.table.name() << ':' << A.name
      79                 :          0 :             << " [style=\"dashed\",dir=\"forward\",color=\"#404040\"];";
      80         [ #  # ]:          0 :     } else if (auto val = std::get_if<const Expr*>(&t)) {
      81                 :          0 :         const Expr *expr = *val;
      82                 :          0 :         indent() << id(e) << EDGE << id(*expr) << " [style=\"dashed\",dir=\"forward\",color=\"crimson\"];";
      83                 :          0 :     }
      84                 :          0 : }
      85                 :            : 
      86                 :          0 : void ASTDot::operator()(Const<Constant> &e)
      87                 :            : {
      88                 :          0 :     indent() << id(e) << " [label=<<B>";
      89                 :            : 
      90         [ #  # ]:          0 :     if (e.is_string()) {
      91   [ #  #  #  #  :          0 :         out << html_escape(*e.tok.text);
                   #  # ]
      92                 :          0 :     } else {
      93                 :          0 :         out << e.tok.text;
      94                 :            :     }
      95                 :          0 :     out << "</B>";
      96                 :            : 
      97         [ #  # ]:          0 :     if (e.has_type()) {
      98                 :          0 :         std::ostringstream oss;
      99   [ #  #  #  # ]:          0 :         oss << *e.type();
     100   [ #  #  #  #  :          0 :         out << "<FONT POINT-SIZE=\"11\"><I> : " << html_escape(oss.str()) << "</I></FONT>";
          #  #  #  #  #  
                      # ]
     101                 :          0 :     }
     102                 :            : 
     103                 :          0 :     out << ">];";
     104                 :          0 : }
     105                 :            : 
     106                 :          0 : void ASTDot::operator()(Const<FnApplicationExpr> &e)
     107                 :            : {
     108                 :          0 :     (*this)(*e.fn);
     109                 :          0 :     indent() << id(e) << " [label=<()";
     110                 :            : 
     111         [ #  # ]:          0 :     if (e.has_type()) {
     112                 :          0 :         std::ostringstream oss;
     113   [ #  #  #  # ]:          0 :         oss << *e.type();
     114   [ #  #  #  #  :          0 :         out << "<FONT POINT-SIZE=\"11\"><I> : " << html_escape(oss.str()) << "</I></FONT>";
          #  #  #  #  #  
                      # ]
     115                 :          0 :     }
     116                 :            : 
     117                 :          0 :     out << ">];";
     118                 :          0 :     indent() << id(e) << EDGE << id(*e.fn) << ';';
     119                 :            : 
     120         [ #  # ]:          0 :     for (auto &arg : e.args) {
     121                 :          0 :         (*this)(*arg);
     122                 :          0 :         indent() << id(e) << EDGE << id(*arg) << ';';
     123                 :            :     }
     124                 :          0 : }
     125                 :            : 
     126                 :          0 : void ASTDot::operator()(Const<UnaryExpr> &e)
     127                 :            : {
     128                 :          0 :     (*this)(*e.expr);
     129   [ #  #  #  #  :          0 :     indent() << id(e) << " [label=<" << html_escape(*e.op().text);
             #  #  #  # ]
     130                 :            : 
     131         [ #  # ]:          0 :     if (e.has_type()) {
     132                 :          0 :         std::ostringstream oss;
     133   [ #  #  #  # ]:          0 :         oss << *e.type();
     134   [ #  #  #  #  :          0 :         out << "<FONT POINT-SIZE=\"11\"><I> : " << html_escape(oss.str()) << "</I></FONT>";
          #  #  #  #  #  
                      # ]
     135                 :          0 :     }
     136                 :            : 
     137                 :          0 :     out << ">];";
     138                 :          0 :     indent() << id(e) << EDGE << id(*e.expr) << ';';
     139                 :          0 : }
     140                 :            : 
     141                 :          0 : void ASTDot::operator()(Const<BinaryExpr> &e)
     142                 :            : {
     143                 :          0 :     (*this)(*e.lhs);
     144                 :          0 :     (*this)(*e.rhs);
     145   [ #  #  #  #  :          0 :     indent() << id(e) << " [label=<" << html_escape(*e.op().text);
             #  #  #  # ]
     146                 :            : 
     147         [ #  # ]:          0 :     if (e.has_type()) {
     148                 :          0 :         std::ostringstream oss;
     149   [ #  #  #  # ]:          0 :         oss << *e.type();
     150   [ #  #  #  #  :          0 :         out << "<FONT POINT-SIZE=\"11\"><I> : " << html_escape(oss.str()) << "</I></FONT>";
          #  #  #  #  #  
                      # ]
     151                 :          0 :     }
     152                 :            : 
     153                 :          0 :     out << ">];";
     154                 :          0 :     indent() << id(e) << EDGE << id(*e.lhs) << ';';
     155                 :          0 :     indent() << id(e) << EDGE << id(*e.rhs) << ';';
     156                 :          0 : }
     157                 :            : 
     158                 :          0 : void ASTDot::operator()(Const<QueryExpr> &e)
     159                 :            : {
     160                 :          0 :     (*this)(*e.query);
     161                 :          0 :     indent() << id(e) << " [label=<QueryExpr";
     162                 :            : 
     163         [ #  # ]:          0 :     if (e.has_type()) {
     164                 :          0 :         std::ostringstream oss;
     165   [ #  #  #  # ]:          0 :         oss << *e.type();
     166   [ #  #  #  #  :          0 :         out << "<FONT POINT-SIZE=\"11\"><I> : " << html_escape(oss.str()) << "</I></FONT>";
          #  #  #  #  #  
                      # ]
     167                 :          0 :     }
     168                 :            : 
     169                 :          0 :     out << ">];";
     170                 :          0 :     indent() << id(e) << EDGE << id(*e.query) << ';';
     171                 :          0 : }
     172                 :            : 
     173                 :            : 
     174                 :            : /*--- Clauses --------------------------------------------------------------------------------------------------------*/
     175                 :            : 
     176                 :          0 : void ASTDot::operator()(Const<ErrorClause> &c)
     177                 :            : {
     178                 :          0 :     indent() << id(c) << " [label=\"ErrorClause\"];";
     179                 :          0 : }
     180                 :            : 
     181                 :          0 : void ASTDot::operator()(Const<SelectClause> &c)
     182                 :            : {
     183         [ #  # ]:          0 :     if (c.select_all) {
     184                 :          0 :         out << '\n';
     185                 :          0 :         indent() << q(std::hex << c << '*') << "[label=\"*\"];";
     186                 :          0 :         indent() << id(c) << EDGE << q(std::hex << c << '*') << ';';
     187                 :          0 :     }
     188         [ #  # ]:          0 :     for (auto &s : c.select) {
     189                 :          0 :         out << '\n';
     190                 :          0 :         (*this)(*s.first);
     191         [ #  # ]:          0 :         if (s.second) {
     192                 :          0 :             indent() << id(s.second) << " [label=\"AS " << s.second.text << "\"];";
     193                 :          0 :             indent() << id(c) << EDGE << id(s.second) << ';';
     194                 :          0 :             indent() << id(s.second) << EDGE << id(*s.first) << ';';
     195                 :          0 :         } else {
     196                 :          0 :             indent() << id(c) << EDGE << id(*s.first) << ';';
     197                 :            :         }
     198                 :            :     }
     199                 :          0 : }
     200                 :            : 
     201                 :          0 : void ASTDot::operator()(Const<FromClause> &c)
     202                 :            : {
     203         [ #  # ]:          0 :     for (auto &t : c.from) {
     204                 :          0 :         out << '\n';
     205         [ #  # ]:          0 :         if (auto name = std::get_if<Token>(&t.source)) {
     206         [ #  # ]:          0 :             if (t.alias) {
     207                 :          0 :                 indent() << id(t.alias) << " [label=\"AS " << t.alias.text << "\"];";
     208                 :          0 :                 indent() << id (*name) << " [label=\"" << name->text << "\"];";
     209                 :          0 :                 indent() << id(c) << EDGE << id(t.alias) << EDGE << id(*name) << ';';
     210                 :          0 :             } else {
     211                 :          0 :                 indent() << id(*name) << " [label=\"" << name->text << "\"];";
     212                 :          0 :                 indent() << id(c) << EDGE << id(*name) << ';';
     213                 :            :             }
     214         [ #  # ]:          0 :         } else if (auto stmt = std::get_if<Stmt*>(&t.source)) {
     215                 :          0 :             M_insist(t.alias, "nested statements must have an alias");
     216                 :          0 :             indent() << id(t.alias) << " [label=\"AS " << t.alias.text << "\"];";
     217                 :          0 :             (*this)(**stmt);
     218                 :          0 :             indent() << id(c) << EDGE << id(t.alias) << EDGE << id(**stmt) << ';';
     219                 :          0 :         } else {
     220                 :          0 :             M_unreachable("invalid variant");
     221                 :            :         }
     222         [ #  # ]:          0 :         if (t.has_table()) {
     223                 :          0 :             M_insist(std::holds_alternative<Token>(t.source));
     224                 :          0 :             auto &name = std::get<Token>(t.source);
     225                 :          0 :             auto &R = t.table();
     226                 :          0 :             indent() << id(name) << EDGE << R.name() << ":n [dir=\"forward\",color=\"#404040\"];";
     227                 :          0 :         }
     228                 :            :     }
     229                 :          0 : }
     230                 :            : 
     231                 :          0 : void ASTDot::operator()(Const<WhereClause> &c)
     232                 :            : {
     233                 :          0 :     out << '\n';
     234                 :          0 :     (*this)(*c.where);
     235                 :          0 :     indent() << id(c) << EDGE << id(*c.where) << ';';
     236                 :          0 : }
     237                 :            : 
     238                 :          0 : void ASTDot::operator()(Const<GroupByClause> &c)
     239                 :            : {
     240         [ #  # ]:          0 :     for (auto &[grp, alias] : c.group_by) {
     241                 :          0 :         out << '\n';
     242                 :          0 :         (*this)(*grp);
     243                 :          0 :         indent() << id(c) << EDGE << id(*grp) << ';';
     244                 :            :     }
     245                 :          0 : }
     246                 :            : 
     247                 :          0 : void ASTDot::operator()(Const<HavingClause> &c)
     248                 :            : {
     249                 :          0 :     out << '\n';
     250                 :          0 :     (*this)(*c.having);
     251                 :          0 :     indent() << id(c) << EDGE << id(*c.having) << ';';
     252                 :          0 : }
     253                 :            : 
     254                 :          0 : void ASTDot::operator()(Const<OrderByClause> &c)
     255                 :            : {
     256         [ #  # ]:          0 :     for (auto &o : c.order_by) {
     257                 :          0 :         out << '\n';
     258         [ #  # ]:          0 :         if (o.second)
     259                 :          0 :             indent() << id(o.second) << " [label=\"ASC\"];";
     260                 :            :         else
     261                 :          0 :             indent() << id(o.second) << " [label=\"DESC\"];";
     262                 :          0 :         indent() << id(c) << EDGE << id(o.second) << ';';
     263                 :          0 :         (*this)(*o.first);
     264                 :          0 :         indent() << id(o.second) << EDGE << id(*o.first) << ';';
     265                 :            :     }
     266                 :          0 : }
     267                 :            : 
     268                 :          0 : void ASTDot::operator()(Const<LimitClause> &c)
     269                 :            : {
     270                 :          0 :     out << '\n';
     271                 :          0 :     indent() << id(c.limit) << " [label=<<B>" << c.limit.text << "</B>>];";
     272                 :          0 :     indent() << id(c) << EDGE << id(c.limit) << ';';
     273                 :            : 
     274         [ #  # ]:          0 :     if (c.offset) {
     275                 :          0 :         out << '\n';
     276                 :          0 :         indent() << id(c.offset) << " [label=<OFFSET <B>" << c.offset.text << "</B>>];";
     277                 :          0 :         indent() << id(c) << EDGE << id(c.offset) << ';';
     278                 :          0 :     }
     279                 :          0 : }
     280                 :            : 
     281                 :            : 
     282                 :            : /*--- Constraints ----------------------------------------------------------------------------------------------------*/
     283                 :            : 
     284                 :          0 : void ASTDot::operator()(Const<PrimaryKeyConstraint> &c)
     285                 :            : {
     286                 :          0 :     indent() << id(c) << " [label=<<B>PRIMARY KEY</B>>];";
     287                 :          0 : }
     288                 :            : 
     289                 :          0 : void ASTDot::operator()(Const<UniqueConstraint> &c)
     290                 :            : {
     291                 :          0 :     indent() << id(c) << " [label=<<B>UNIQUE</B>>];";
     292                 :          0 : }
     293                 :            : 
     294                 :          0 : void ASTDot::operator()(Const<NotNullConstraint> &c)
     295                 :            : {
     296                 :          0 :     indent() << id(c) << " [label=<<B>NOT NULL</B>>];";
     297                 :          0 : }
     298                 :            : 
     299                 :          0 : void ASTDot::operator()(Const<CheckConditionConstraint> &c)
     300                 :            : {
     301                 :          0 :     (*this)(*c.cond);
     302                 :          0 :     indent() << id(c) << " [label=<<B>CHECK()</B>>];";
     303                 :          0 :     indent() << id(c) << EDGE << id(*c.cond) << ';';
     304                 :          0 : }
     305                 :            : 
     306                 :          0 : void ASTDot::operator()(Const<ReferenceConstraint> &c)
     307                 :            : {
     308                 :          0 :     indent() << id(c) << " [label=<<B>REFERENCES " << c.table_name.text << '(' << c.attr_name.text << ")</B>>];";
     309                 :          0 : }
     310                 :            : 
     311                 :            : 
     312                 :            : /*----- Instruction --------------------------------------------------------------------------------------------------*/
     313                 :            : 
     314                 :          0 : void ASTDot::operator()(const Instruction &inst)
     315                 :            : {
     316                 :          0 :     out << '\n';
     317                 :          0 :     std::ostringstream oss;
     318   [ #  #  #  #  :          0 :     indent() << id(inst) << " [label=\"" << inst.tok.text << "\"];";
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     319                 :          0 : }
     320                 :            : 
     321                 :            : 
     322                 :            : /*--- Stmt -----------------------------------------------------------------------------------------------------------*/
     323                 :            : 
     324                 :          0 : void ASTDot::operator()(Const<ErrorStmt>&)
     325                 :            : {
     326                 :            :     // TODO implement
     327                 :          0 : }
     328                 :            : 
     329                 :          0 : void ASTDot::operator()(Const<EmptyStmt>&)
     330                 :            : {
     331                 :            :     // TODO implement
     332                 :          0 : }
     333                 :            : 
     334                 :          0 : void ASTDot::operator()(Const<CreateDatabaseStmt>&)
     335                 :            : {
     336                 :            :     // TODO implement
     337                 :          0 : }
     338                 :            : 
     339                 :          0 : void ASTDot::operator()(Const<DropDatabaseStmt>&)
     340                 :            : {
     341                 :            :     // TODO implement
     342                 :          0 : }
     343                 :            : 
     344                 :          0 : void ASTDot::operator()(Const<UseDatabaseStmt>&)
     345                 :            : {
     346                 :            :     // TODO implement
     347                 :          0 : }
     348                 :            : 
     349                 :          0 : void ASTDot::operator()(Const<CreateTableStmt>&)
     350                 :            : {
     351                 :            :     // TODO implement
     352                 :          0 : }
     353                 :            : 
     354                 :          0 : void ASTDot::operator()(Const<DropTableStmt>&)
     355                 :            : {
     356                 :            :     // TODO implement
     357                 :          0 : }
     358                 :            : 
     359                 :          0 : void ASTDot::operator()(Const<CreateIndexStmt>&)
     360                 :            : {
     361                 :            :     // TODO implement
     362                 :          0 : }
     363                 :            : 
     364                 :          0 : void ASTDot::operator()(Const<DropIndexStmt>&)
     365                 :            : {
     366                 :            :     // TODO implement
     367                 :          0 : }
     368                 :            : 
     369                 :          0 : void ASTDot::operator()(Const<SelectStmt> &s)
     370                 :            : {
     371                 :          0 :     out << '\n';
     372                 :          0 :     std::ostringstream oss;
     373   [ #  #  #  #  :          0 :     indent() << id(s) << " [label=\"SelectStmt\"];";
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     374                 :            : 
     375         [ #  # ]:          0 :     if (s.from) {
     376                 :            :         /* Dot the accessed tables first. */
     377   [ #  #  #  # ]:          0 :         indent() << "subgraph sources";
     378   [ #  #  #  # ]:          0 :         indent() << '{';
     379                 :          0 :         ++indent_;
     380   [ #  #  #  # ]:          0 :         if (auto f = cast<FromClause>(s.from.get())) {
     381         [ #  # ]:          0 :             for (auto &t : f->from) {
     382   [ #  #  #  # ]:          0 :                 if (t.has_table()) {
     383         [ #  # ]:          0 :                     auto &R = t.table();
     384                 :            : 
     385   [ #  #  #  #  :          0 :                     indent() << R.name() << "[shape=none,style=filled,fillcolor=white,label=<";
             #  #  #  # ]
     386                 :          0 :                     ++indent_;
     387   [ #  #  #  # ]:          0 :                     indent() << "<TABLE>";
     388                 :          0 :                     ++indent_;
     389   [ #  #  #  #  :          0 :                     indent() << "<TR><TD BORDER=\"0\"><B>" << R.name() << "</B></TD></TR>";
          #  #  #  #  #  
                      # ]
     390                 :            : 
     391   [ #  #  #  #  :          0 :                     for (auto &A : R) {
          #  #  #  #  #  
                #  #  # ]
     392   [ #  #  #  # ]:          0 :                         oss.str("");
     393         [ #  # ]:          0 :                         oss << *A.type;
     394   [ #  #  #  #  :          0 :                         indent() << "<TR><TD PORT=\"" << A.name << "\">" << A.name
          #  #  #  #  #  
                      # ]
     395   [ #  #  #  #  :          0 :                                  << "<FONT POINT-SIZE=\"11\"><I> : " << html_escape(oss.str()) << "</I></FONT>"
          #  #  #  #  #  
                      # ]
     396         [ #  # ]:          0 :                                  << "</TD></TR>";
     397                 :            :                     }
     398                 :            : 
     399                 :          0 :                     --indent_;
     400   [ #  #  #  # ]:          0 :                     indent() << "</TABLE>";
     401                 :          0 :                     --indent_;
     402   [ #  #  #  # ]:          0 :                     indent() << ">];";
     403                 :          0 :                 }
     404                 :            :             }
     405                 :          0 :         }
     406                 :          0 :         --indent_;
     407   [ #  #  #  # ]:          0 :         indent() << "}\n";
     408                 :          0 :     }
     409                 :            : 
     410         [ #  # ]:          0 :     cluster(*s.select, "select", "SELECT", "#e6194B20");
     411   [ #  #  #  #  :          0 :     indent() << id(s) << EDGE << id(*s.select) << ';';
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     412                 :            : 
     413                 :            : #define DOT(NAME, LABEL, COLOR) \
     414                 :            :     if (s.NAME) { \
     415                 :            :         out << '\n'; \
     416                 :            :         cluster(*s.NAME, #NAME, LABEL, COLOR); \
     417                 :            :         indent() << id(s) << EDGE << id(*s.NAME) << ';'; \
     418                 :            :     }
     419   [ #  #  #  #  :          0 :     DOT(from,     "FROM",     "#bfef4550");
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     420   [ #  #  #  #  :          0 :     DOT(where,    "WHERE",    "#42d4f430");
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     421   [ #  #  #  #  :          0 :     DOT(group_by, "GROUP BY", "#3cb44b30");
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     422   [ #  #  #  #  :          0 :     DOT(having,   "HAVING",   "#aaffc350");
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     423   [ #  #  #  #  :          0 :     DOT(order_by, "ORDER BY", "#ffe11950");
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     424   [ #  #  #  #  :          0 :     DOT(limit,    "LIMIT",    "#80800040");
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     425                 :            : #undef DOT
     426                 :          0 : }
     427                 :            : 
     428                 :          0 : void ASTDot::operator()(Const<InsertStmt>&)
     429                 :            : {
     430                 :            :     // TODO implement
     431                 :          0 : }
     432                 :            : 
     433                 :          0 : void ASTDot::operator()(Const<UpdateStmt>&)
     434                 :            : {
     435                 :            :     // TODO implement
     436                 :          0 : }
     437                 :            : 
     438                 :          0 : void ASTDot::operator()(Const<DeleteStmt>&)
     439                 :            : {
     440                 :            :     // TODO implement
     441                 :          0 : }
     442                 :            : 
     443                 :          0 : void ASTDot::operator()(Const<DSVImportStmt>&)
     444                 :            : {
     445                 :            :     // TODO implement
     446                 :          0 : }

Generated by: LCOV version 1.16