Skip to content

Commit 02fc4b7

Browse files
committed
Add AST dumper.
Dumps ASTs in graphml. Available via --dump-all-graphs. Stylesheet to turn it into graphviz included.
1 parent 1ca1167 commit 02fc4b7

File tree

10 files changed

+184
-8
lines changed

10 files changed

+184
-8
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
config.h
22
*.o
33
sqlsmith
4+
*.xml

Makefile

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
all: sqlsmith
22

3-
OBJECTS = relmodel.o schema.o random.o expr.o grammar.o log.o sqlsmith.o
3+
OBJECTS = relmodel.o schema.o random.o expr.o grammar.o log.o dump.o sqlsmith.o
44

55
CXXFLAGS = -O3 -g
66

@@ -25,4 +25,7 @@ sqlsmith: $(OBJECTS)
2525
$(CXX) $(CXXFLAGS) -std=c++11 -Wall -c $< -o $@
2626

2727
clean:
28-
rm -f sqlsmith *.o config.h
28+
rm -f sqlsmith *.o config.h *.xml
29+
30+
%.v: %.xml
31+
xsltproc dump.xsl $< | dot -Tx11

dump.cc

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#include <typeinfo>
2+
#include <string>
3+
#include <sstream>
4+
5+
#include "dump.hh"
6+
7+
using namespace std;
8+
9+
std::string graphml_dumper::type(struct prod *p)
10+
{
11+
ostringstream os;
12+
os << typeid(*p).name();
13+
string s = os.str();
14+
while(s[0] <= '9')
15+
s.erase(s.begin());
16+
return s;
17+
}
18+
19+
std::string graphml_dumper::id(struct prod *p)
20+
{
21+
ostringstream os;
22+
os << type(p) << "_" << p;
23+
return os.str();
24+
}
25+
26+
graphml_dumper::graphml_dumper(ostream &out)
27+
: o(out)
28+
{
29+
o << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl <<
30+
"<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" " <<
31+
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " <<
32+
"xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns " <<
33+
"http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">" << endl;
34+
35+
o << "<key id=\"retries\" for=\"node\" "
36+
"attr.name=\"retries\" attr.type=\"double\" />" << endl;
37+
o << "<key id=\"label\" for=\"node\" "
38+
"attr.name=\"label\" attr.type=\"string\" />" << endl;
39+
40+
o << "<graph id=\"ast\" edgedefault=\"directed\">" << endl;
41+
42+
}
43+
44+
void graphml_dumper::visit(struct prod *p)
45+
{
46+
o << "<node id=\"" << id(p) << "\">";
47+
o << "<data key=\"retries\">" << p->retries << "</data>";
48+
o << "<data key=\"label\">" << type(p) << "</data>";
49+
o << "</node>" << endl;
50+
if (p->pprod) {
51+
o << "<edge source=\"" << id(p) << "\" target=\"" << id(p->pprod) << "\"/>";
52+
}
53+
o << endl;
54+
}
55+
56+
graphml_dumper::~graphml_dumper()
57+
{
58+
o << "</graph></graphml>" << endl;
59+
}
60+
61+
void ast_logger::generated(prod &query)
62+
{
63+
string filename("");
64+
filename += "sqlsmith-";
65+
filename += to_string(queries);
66+
filename += ".xml";
67+
ofstream os(filename);
68+
graphml_dumper visitor(os);
69+
query.accept(&visitor);
70+
queries++;
71+
}

dump.hh

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#ifndef DUMP_HH
2+
#define DUMP_HH
3+
4+
#include <iostream>
5+
#include <fstream>
6+
#include <string>
7+
8+
#include "prod.hh"
9+
#include "log.hh"
10+
11+
struct graphml_dumper : prod_visitor {
12+
std::ostream &o;
13+
virtual void visit(struct prod *p);
14+
graphml_dumper(std::ostream &out);
15+
std::string id(prod *p);
16+
std::string type(struct prod *p);
17+
virtual ~graphml_dumper();
18+
};
19+
20+
struct ast_logger : logger {
21+
int queries = 0;
22+
virtual void generated(prod &query);
23+
};
24+
25+
#endif

dump.xsl

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?xml version='1.0'?>
2+
<!-- translates sqlsmith graphml output into graphviz -->
3+
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
4+
xmlns:g="http://graphml.graphdrawing.org/xmlns"
5+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
6+
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
7+
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"
8+
version='1.0'>
9+
10+
<xsl:output method="text" />
11+
12+
<xsl:template match="/g:graphml/g:graph">
13+
<xsl:text>digraph ast {</xsl:text>
14+
<xsl:apply-templates select="@*|node()"/>
15+
<xsl:text>}</xsl:text>
16+
</xsl:template>
17+
18+
<xsl:template match="g:data">
19+
<xsl:choose>
20+
<xsl:when test="@key = 'label'">
21+
<xsl:text>label=</xsl:text>
22+
<xsl:value-of select="text()"/>
23+
<xsl:text>,</xsl:text>
24+
</xsl:when>
25+
<xsl:when test="@key = 'retries'">
26+
<xsl:choose>
27+
<xsl:when test="text() > 1000">
28+
<xsl:text>fillcolor=firebrick,style=filled</xsl:text>
29+
</xsl:when>
30+
<xsl:when test="text() > 500">
31+
<xsl:text>fillcolor=red,style=filled</xsl:text>
32+
</xsl:when>
33+
<xsl:when test="text() > 100">
34+
<xsl:text>fillcolor=salmon,style=filled</xsl:text>
35+
</xsl:when>
36+
<xsl:when test="text() > 50">
37+
<xsl:text>fillcolor=wheat,style=filled</xsl:text>
38+
</xsl:when>
39+
<xsl:when test="text() > 10">
40+
<xsl:text>fillcolor=springgreen,style=filled</xsl:text>
41+
</xsl:when>
42+
<xsl:when test="text() > 1">
43+
<xsl:text>fillcolor=gainsboro,style=filled</xsl:text>
44+
</xsl:when>
45+
<xsl:otherwise>
46+
<xsl:text>fillcolor=white,style=filled</xsl:text>
47+
</xsl:otherwise>
48+
</xsl:choose>
49+
<xsl:text>,</xsl:text>
50+
</xsl:when>
51+
<xsl:otherwise>
52+
</xsl:otherwise>
53+
</xsl:choose>
54+
</xsl:template>
55+
56+
<xsl:template match="g:node">
57+
<xsl:value-of select="@id"/>
58+
<xsl:text>[</xsl:text>
59+
<xsl:apply-templates select="g:data"/>
60+
<xsl:text>];
61+
</xsl:text>
62+
</xsl:template>
63+
64+
<xsl:template match="g:edge">
65+
66+
<xsl:value-of select="@source"/>
67+
<xsl:text> -> </xsl:text>
68+
<xsl:value-of select="@target"/>
69+
<xsl:text>;
70+
</xsl:text>
71+
</xsl:template>
72+
73+
</xsl:transform>

expr.hh

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
#include "prod.hh"
55

6+
using std::shared_ptr;
7+
68
struct value_expr: prod {
79
sqltype *type;
810
virtual void out(std::ostream &out) = 0;

grammar.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ select_list::select_list(query_spec *q) : prod(q)
135135
ostringstream name;
136136
name << "c" << columns++;
137137
derived_table.columns().push_back(column(name.str(), e->type));
138-
} while (d6() > 1);
138+
} while (d6() > 2);
139139
}
140140

141141
void select_list::out(std::ostream &out)

log.hh

-2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,4 @@ struct pqxx_logger : stats_collecting_logger {
3838
virtual void error(prod &query, const pqxx::sql_error &e);
3939
};
4040

41-
42-
4341
#endif

prod.hh

-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
#ifndef PROD_HH
22
#define PROD_HH
33

4-
using std::shared_ptr;
5-
64
struct prod_visitor {
75
virtual void visit(struct prod *p) = 0;
86
virtual ~prod_visitor() { }

sqlsmith.cc

+6-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "config.h"
1717

1818
#include "log.hh"
19+
#include "dump.hh"
1920

2021
using namespace std;
2122
using namespace pqxx;
@@ -53,7 +54,7 @@ int main(int argc, char *argv[])
5354
cerr << "sqlsmith " << GITREV << endl;
5455

5556
map<string,string> options;
56-
regex optregex("--(help|log-to|verbose|target|version)(?:=((?:.|\n)*))?");
57+
regex optregex("--(help|log-to|verbose|target|version|dump-all-graphs)(?:=((?:.|\n)*))?");
5758

5859
for(char **opt = argv+1 ;opt < argv+argc; opt++) {
5960
smatch match;
@@ -70,6 +71,7 @@ int main(int argc, char *argv[])
7071
cerr <<
7172
" --log-to=connstr log errors to database" << endl <<
7273
" --target=connstr database to send queries to" << endl <<
74+
" --dump-all-graphs dump generated ASTs" << endl <<
7375
" --verbose emit progress output" << endl <<
7476
" --version show version information" << endl;
7577
return 0;
@@ -95,6 +97,9 @@ int main(int argc, char *argv[])
9597

9698
if (options.count("verbose"))
9799
loggers.push_back(make_shared<cerr_logger>());
100+
101+
if (options.count("dump-all-graphs"))
102+
loggers.push_back(make_shared<ast_logger>());
98103

99104
{
100105
work w(c);

0 commit comments

Comments
 (0)