Skip to content

Commit d48ea1e

Browse files
David AndersonDavid Anderson
authored andcommitted
added code to generate LaTeX tables for some results. Added QCP4 dynamic query part grouping based on what role they take on in the query.
1 parent 2836402 commit d48ea1e

3 files changed

Lines changed: 124 additions & 90 deletions

File tree

QCPAnalysis/src/QCPAnalysis/QCP4SubcaseAnalysis.rsc

Lines changed: 68 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -39,78 +39,95 @@ public void analyzeQCP4(){
3939
println("Types of dynamic snippets: <types>");
4040
println("Counts for each type:\n <(n : size(d) | n <- groupDynamicSnippetsByType(ds), d := groupDynamicSnippetsByType(ds)[n])>");
4141
println("Counts for each role:\n <(n : size(d) | n <- groupDynamicSnippetsByRole(qcp4), d := groupDynamicSnippetsByRole(qcp4)[n])>");
42+
for(q <- groupDynamicSnippetsByRole(qcp4)["Other"]) println(q.dynamicpart@at);
4243
}
4344

44-
private map[str, list[QuerySnippet]] groupDynamicSnippetsByType(list[QuerySnippet] ds){
45+
public map[str, list[QuerySnippet]] groupDynamicSnippetsByType(list[QuerySnippet] ds){
4546
res = ();
4647

4748
// group vars
48-
res += ("var" : [d | d <- ds, dynamicsnippet(var(name(name(n)))) := d]);
49+
res += ("Variable" : [d | d <- ds, dynamicsnippet(var(name(name(n)))) := d]);
4950

5051
// group references to superglobals
51-
res += ("superglobal" : [d | d <- ds, dynamicsnippet(fetchArrayDim(var(name(name(n))), _)) := d, n in superglobals]);
52+
res += ("Fetch Superglobal Element" : [d | d <- ds, dynamicsnippet(fetchArrayDim(var(name(name(n))), _)) := d, n in superglobals]);
5253

5354
// group fetchArrayDim
54-
res += ("fetchArrayDim" : [d | d <- ds, dynamicsnippet(fetchArrayDim(var(name(name(n))),_)) := d, n notin superglobals]);
55+
res += ("Fetch Array Element" : [d | d <- ds, dynamicsnippet(fetchArrayDim(var(name(name(n))),_)) := d, n notin superglobals]);
5556
// needed case for 2-dimensional arrays
56-
res["fetchArrayDim"] += [d | d <- ds, dynamicsnippet(fetchArrayDim(fetchArrayDim(var(name(name(n))),_),_)) := d, n notin superglobals];
57+
res["Fetch Array Element"] += [d | d <- ds, dynamicsnippet(fetchArrayDim(fetchArrayDim(var(name(name(n))),_),_)) := d, n notin superglobals];
5758

5859
// group function calls
59-
res += ("call" : [d | d <- ds, dynamicsnippet(call(_,_)) := d]);
60+
res += ("Function Call" : [d | d <- ds, dynamicsnippet(call(_,_)) := d]);
6061

6162
// group ternary
62-
res += ("ternary" : [d | d <- ds, dynamicsnippet(ternary(_,_,_)) := d]);
63+
res += ("Ternary Operator" : [d | d <- ds, dynamicsnippet(ternary(_,_,_)) := d]);
6364

64-
if(size(ds) != size(res["var"]) + size(res["superglobal"]) + size(res["fetchArrayDim"]) + size(res["call"]) + size(res["ternary"])){
65+
if(size(ds) != size(res["Variable"]) + size(res["Fetch Superglobal Element"]) + size(res["Fetch Array Element"])
66+
+ size(res["Function Call"]) + size(res["Ternary Operator"])){
67+
6568
println("Warning: some dynamic snippets were not grouped. Type groupings may need additions.");
6669
}
6770
return res;
6871
}
6972

7073
// groups all QCP4 occurrences based on what role their dynamic snippets take on
7174
private map[str, list[QuerySnippet]] groupDynamicSnippetsByRole(set[QueryString] qs){
72-
res = ("param" : [], "name" : [], "other" : []);
75+
res = ("Parameter" : [], "Name" : [], "Other" : []);
7376
for(q <- qs){
7477
indexes = getDynamicSnippetIndexes(q);
7578

7679
// returns true if this dynamic snippet is used as a parameter
7780
bool paramSnippet(int i){
7881
// get previous static snippet
7982
if(staticsnippet(ss) := q.snippets[i - 1]){
80-
// perform regex matching on the static snippet to determine if the dynamic snippet is used as a parameter
81-
if(/^.*WHERE\s[\w\.\`]+\s?\=\s?[^\w\.\`]*$/i := ss){
83+
// perform regex matching on the static snippet to determine if the dynamic snippet at i is used as a parameter
84+
if(/.*[\w\`\.]+\s*\=|(\<\>)|(\!\=)|\<|\>|(\<\=)|(\>\=)\s*\'?\\?$/i := ss){
8285
return true;
8386
}
84-
else if(/^.*AND\s[\w\.\`]+\s?\=\s?[^\w\.\`]*$/i := ss){
87+
else if(/.*ORDER\sBY\s$/i := ss){
8588
return true;
8689
}
87-
else if(/^.*OR\s[\w\.\`]+\s?\=\s?[^\w\.\`]*$/i := ss){
90+
else if(/.*LIMIT\s$/i := ss){
8891
return true;
8992
}
90-
else if(/^.*NOT\s[\w\.\`]+\s?\=\s?[^\w\.\`]*$/i := ss){
93+
else{
94+
return false;
95+
}
96+
}
97+
else{
98+
return false;
99+
}
100+
}
101+
102+
// check for case of arithmetic in set clause
103+
bool setParamArithmetic(int i){
104+
if(staticsnippet(ss) := q.snippets[i - 1]){
105+
if(/.*<word:\w+>\s?\=\s?\(<word>\s?\+|\-\s?$/i := ss){
91106
return true;
92107
}
108+
else{
109+
return false;
110+
}
111+
}
112+
else{
113+
return false;
93114
}
94-
return false;
95115
}
96116

117+
97118
bool valuesParamSnippet(int index){
98119
boundaries = <-1,-1>;
99120
for(i <- [0..size(q.snippets)]){
100-
if(staticsnippet(ss1) := q.snippets[i] && /^.*VALUES\([^\)]*/i := ss1){
121+
if(staticsnippet(ss1) := q.snippets[i] && /VALUES/i := ss1){
101122
boundaries[0] = i;
102123
break;
103124
}
104125
}
105126
if(boundaries[0] != -1){
106-
for(i <- [boundaries[0]..size(q.snippets)]){
107-
//find right paren
108-
if(staticsnippet(ss2) := q.snippets[i] && /\)$/i := ss2){
109-
boundaries[1] = i;
110-
break;
111-
}
112-
}
113-
}
127+
// assume last snippet is the end of the VALUES clause
128+
boundaries[1] = size(q.snippets);
129+
}
130+
114131
if(boundaries[0] == -1 || boundaries[1] == -1){
115132
return false;
116133
}
@@ -123,48 +140,50 @@ private map[str, list[QuerySnippet]] groupDynamicSnippetsByRole(set[QueryString]
123140
}
124141
}
125142

126-
// returns true if this dynamic snippet is the parameter to a SET clause
127-
bool setParamSnippet(int index){
128-
//finds the beginning of the SET clause of q, if it exists
129-
setBegin = -1;
130-
for(i <- [0..size(q.snippets)]){
131-
if(staticsnippet(ss) := q.snippets[i] && /^.*SET\s[\w\.\`]+\s?\=\s?[^\w\.\`]*$/i := ss){
132-
setBegin = i;
133-
break;
143+
bool nameSnippet(int i){
144+
if(staticsnippet(ss) := q.snippets[i - 1]){
145+
// perform regex matching on the static snippet to determine if the dynamic snippet is used as a parameter
146+
if(/^.*FROM\s$/ := ss){
147+
return true;
134148
}
135-
}
136-
if(setBegin != -1){
137-
// check for the easy case of the dynamic snippet at index being the first assignment after the SET clause
138-
if(index == setBegin + 1 && dynamicsnippet(_) := q.snippets[setBegin + 1]){
149+
else if(/^UPDATE\s$/ := ss){
139150
return true;
140151
}
141-
// starting at the next snippet, look for <staticsnippet, dynamicsnippet> pairs of the form:
142-
// atributename = $dynamicsnippet
143-
else{
144-
setBegin = setBegin + 2;
145-
for(i <- [setBegin..size(q.snippets) - 1]){
146-
if(index == i + 1 && staticsnippet(s) := q.snippets[i] && /^\'?\\?\s?\,\s?[\w\.\`]+\s?\=\s?\\?\'?$/ := s){
147-
return true;
148-
}
149-
}
152+
else if(/^SELECT\s$/ := ss){
153+
return true;
154+
}
155+
else if(/^INSERT\sINTO\s$/ := ss){
156+
return true;
157+
}
158+
else if(/^.*DATABASE\s$/ := ss){
159+
return true;
160+
}
161+
else if(/^.*EXISTS\s$/ := ss){
162+
return true;
163+
}
164+
else if(/^.*USE\s$/ := ss){
165+
return true;
150166
}
151167
}
152168
return false;
153169
}
154170

155171
for(i <- indexes, ds := q.snippets[i]){
156-
if(paramSnippet(i) || setParamSnippet(i) || valuesParamSnippet(i)){
157-
res["param"] += ds;
172+
if(paramSnippet(i) || setParamArithmetic(i) || valuesParamSnippet(i)){
173+
res["Parameter"] += ds;
174+
}
175+
else if(nameSnippet(i)){
176+
res["Name"] += ds;
158177
}
159178
else{
160-
res["other"] += ds;
179+
res["Other"] += ds;
161180
}
162181
}
163182
}
164183
return res;
165184
}
166185
// gets all dynamic query snippets from each querystring in qs
167-
private list[QuerySnippet] getDynamicSnippets(set[QueryString] qs) = [s | q <- qs, s <- q.snippets, dynamicsnippet(_) := s];
186+
public list[QuerySnippet] getDynamicSnippets(set[QueryString] qs) = [s | q <- qs, s <- q.snippets, dynamicsnippet(_) := s];
168187

169188
// gets the names of all the types used in dynamicsnippets
170189
private set[str] getQCP4DynamicSnippetTypes(list[QuerySnippet] ds) = {getName(e) | d <- ds, dynamicsnippet(e) := d};

QCPAnalysis/src/QCPAnalysis/QueryStringAnalysis.rsc

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -132,15 +132,17 @@ private list[QuerySnippet] buildQG2Snippets(list[Expr] parts){
132132
return snippets;
133133
}
134134

135-
public void reportQCPCounts(){
135+
public lrel[str,int] reportQCPCounts(){
136136
qs = buildAndClassifyQueryStrings();
137-
println("Number of QCP1 cases: <size({q | q <- qs, q.flags.qcp1 == true})>");
138-
println("Number of QCP2 cases: <size({q | q <- qs, q.flags.qcp2 == true})>");
139-
println("Number of QCP3a cases: <size({q | q <- qs, q.flags.qcp3a == true})>");
140-
println("Number of QCP3b cases: <size({q | q <- qs, q.flags.qcp3b == true})>");
141-
println("Number of QCP4 cases: <size({q | q <- qs, q.flags.qcp4 == true})>");
142-
println("Number of QCP5 cases: <size({q | q <- qs, q.flags.qcp5 == true})>");
143-
println("Number of unclassified cases: <size({q | q <- qs, q.flags.unclassified == true})>");
137+
return [
138+
<"QCP1", size({q | q <- qs, q.flags.qcp1 == true})>,
139+
<"QCP2", size({q | q <- qs, q.flags.qcp2 == true})>,
140+
<"QCP3a", size({q | q <- qs, q.flags.qcp3a == true})>,
141+
<"QCP3b", size({q | q <- qs, q.flags.qcp3b == true})>,
142+
<"QCP4", size({q | q <- qs, q.flags.qcp4 == true})>,
143+
<"QCP5", size({q | q <- qs, q.flags.qcp5 == true})>,
144+
<"other", size({q | q <- qs, q.flags.unclassified == true})>
145+
];
144146
}
145147

146148
public set[QueryString] getQCP(str id){

QCPAnalysis/src/QCPAnalysis/WriteResults.rsc

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ module QCPAnalysis::WriteResults
77
import QCPAnalysis::QCPCorpus;
88
import QCPAnalysis::QueryGroups;
99
import QCPAnalysis::QueryStringAnalysis;
10+
import QCPAnalysis::QCP4SubcaseAnalysis;
1011

1112
import lang::php::ast::AbstractSyntax;
1213
import lang::php::util::Corpus;
@@ -15,45 +16,57 @@ import lang::php::util::Utils;
1516
import IO;
1617
import List;
1718
import String;
19+
import Set;
1820

19-
loc lists = |project://QCPAnalysis/results/lists/|;
20-
loc counts = |project://QCPAnalysis/results/counts/|;
21-
loc strings = |project://QCPAnalysis/results/querystrings.txt|;
21+
loc tables = |project://QCPAnalysis/results/tables/|;
2222

23-
// convenience function that performs all other functions in this module
24-
public void writeResults(){
25-
writeCounts();
26-
writeQG();
27-
writeQueryStrings();
28-
}
29-
// writes the counts from all QG analyses to a file in the results folder
30-
public void writeCounts(){
31-
loc file = counts + "countMysqlQuery.txt";
32-
iprintToFile(file, countMSQCorpus());
33-
34-
file = counts + "countQG.txt";
35-
iprintToFile(file, countQG());
23+
public str qcpCountsAsLatexTable(){
24+
str getLine(str pattern, int count) = "<pattern> & <count>";
25+
str res =
26+
"\\npaddmissingzero
27+
'\\npfourdigitsep
28+
'\\begin{table}
29+
'\\centering
30+
'\\caption{Counts of Each Query Construction Pattern\\label{tbl:php-corpus}}
31+
'\\ra{1.2}
32+
'\\begin{tabularx}{\\columnwidth}{Xrrr} \\toprule
33+
'Query Construction Pattern & Number of Occurrences\\\\ \\midrule
34+
'<for(<p,c> <- reportQCPCounts()){><getLine(p,c)> \\\\
35+
'<}>
36+
'\\bottomrule
37+
'\\end{tabularx}
38+
'\\end{table}
39+
'\\npfourdigitnosep
40+
'\\npnoaddmissingzero
41+
";
42+
return res;
3643
}
3744

38-
public void writeQG(){
39-
map[str, list[Expr]] qg1 = getQG(1);
40-
map[str, list[Expr]] qg2 = getQG(2);
41-
map[str, list[Expr]] qg3 = getQG(3);
42-
map[str, list[Expr]] qg4 = getQG(4);
43-
map[str, list[Expr]] unmatched = getQG(5);
44-
Corpus corpus = getCorpus();
45-
for(p <- corpus, v := corpus[p]){
46-
loc sys = lists + "<p>_<v>";
47-
iprintToFile(sys + "QG1", qg1["<p>_<v>"]);
48-
iprintToFile(sys + "QG2", qg2["<p>_<v>"]);
49-
iprintToFile(sys + "QG3", qg3["<p>_<v>"]);
50-
iprintToFile(sys + "QG4", qg4["<p>_<v>"]);
51-
iprintToFile(sys + "unmatched", unmatched["<p>_<v>"]);
52-
}
45+
public str qcp4TypesAsLatexTable(){
46+
typeGroups = groupDynamicSnippetsByType(getDynamicSnippets(getQCP("4")));
47+
str getLine(str t, int c) = "<t> & <c>";
48+
str res =
49+
"\\npaddmissingzero
50+
'\\npfourdigitsep
51+
'\\begin{table}
52+
'\\centering
53+
'\\caption{Counts of Each Type of Dynamic Query Part in QCP4 Occurrences\\label{tbl:php-qcp4-types}}
54+
'\\ra{1.2}
55+
'\\begin{tabularx}{\\columnwidth}{Xrrr} \\toprule
56+
'Type & Number of Occurrences\\\\ \\midrule
57+
'<for(p <- typeGroups, c := typeGroups[p]){><getLine(p,size(c))> \\\\
58+
'<}>
59+
'\\bottomrule
60+
'\\end{tabularx}
61+
'\\end{table}
62+
'\\npfourdigitnosep
63+
'\\npnoaddmissingzero
64+
";
65+
return res;
5366
}
5467

55-
public void writeQueryStrings(){
56-
iprintToFile(strings, {q | q <- buildAndClassifyQueryStrings(), q.flags.qcp5 == true});
68+
public str qcp4RolesAsLatexTable(){
69+
5770
}
5871

5972
public str corpusAsLatexTable() {

0 commit comments

Comments
 (0)