Skip to content

Commit aad5d66

Browse files
committed
Implement a local state class and replace the queryString in the state
1 parent df54b2e commit aad5d66

17 files changed

+84
-44
lines changed

src/sqlancer/ComparatorHelper.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public static void assumeResultSetsAreEqual(List<String> resultSet, List<String>
8989
String firstQueryString = String.format(queryFormatString, originalQueryString, resultSet.size());
9090
String secondQueryString = String.format(queryFormatString,
9191
combinedString.stream().collect(Collectors.joining(";")), secondResultSet.size());
92-
state.getState().queryString = String.format("%s\n%s", firstQueryString, secondQueryString);
92+
state.getState().getLocalState().log(String.format("%s\n%s", firstQueryString, secondQueryString));
9393
String assertionMessage = String.format("the size of the result sets mismatch (%d and %d)!\n%s\n%s",
9494
resultSet.size(), secondResultSet.size(), firstQueryString, secondQueryString);
9595
throw new AssertionError(assertionMessage);
@@ -108,7 +108,7 @@ public static void assumeResultSetsAreEqual(List<String> resultSet, List<String>
108108
String secondQueryString = String.format(queryFormatString,
109109
combinedString.stream().collect(Collectors.joining(";")), secondResultSetMisses);
110110
// update the SELECT queries to be logged at the bottom of the error log file
111-
state.getState().queryString = String.format("%s\n%s", firstQueryString, secondQueryString);
111+
state.getState().getLocalState().log(String.format("%s\n%s", firstQueryString, secondQueryString));
112112
String assertionMessage = String.format("the content of the result sets mismatch!\n%s\n%s",
113113
firstQueryString, secondQueryString);
114114
throw new AssertionError(assertionMessage);

src/sqlancer/Main.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -233,9 +233,6 @@ private void printState(FileWriter writer, StateToReproduce state) {
233233
}
234234
sb.append('\n');
235235
}
236-
if (state.getQueryString() != null) {
237-
sb.append(state.getQueryString() + ";\n");
238-
}
239236
try {
240237
writer.write(sb.toString());
241238
} catch (IOException e) {

src/sqlancer/ProviderAdapter.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import java.io.FileWriter;
44
import java.sql.SQLException;
55

6+
import sqlancer.StateToReproduce.OracleRunReproductionState;
7+
68
public abstract class ProviderAdapter<G extends GlobalState<O, ?>, O> implements DatabaseProvider<G, O> {
79

810
private final Class<G> globalClass;
@@ -41,11 +43,16 @@ public void generateAndTestDatabase(G globalState) throws SQLException {
4143

4244
TestOracle oracle = getTestOracle(globalState);
4345
for (int i = 0; i < globalState.getOptions().getNrQueries(); i++) {
44-
try {
45-
oracle.check();
46-
globalState.getManager().incrementSelectQueryCount();
47-
} catch (IgnoreMeException e) {
46+
try (OracleRunReproductionState localState = globalState.getState().createLocalState()) {
47+
assert localState != null;
48+
try {
49+
oracle.check();
50+
globalState.getManager().incrementSelectQueryCount();
51+
} catch (IgnoreMeException e) {
4852

53+
}
54+
assert localState != null;
55+
localState.executedWithoutError();
4956
}
5057
}
5158
} finally {

src/sqlancer/StateToReproduce.java

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package sqlancer;
22

3+
import java.io.Closeable;
34
import java.util.ArrayList;
45
import java.util.Collections;
56
import java.util.List;
@@ -22,12 +23,6 @@ public class StateToReproduce {
2223

2324
private final List<Query> statements = new ArrayList<>();
2425

25-
/**
26-
* The string printed at the bottom of the error log file, which contains the queries that caused the test to fail
27-
* and information about their results.
28-
*/
29-
public String queryString;
30-
3126
private final String databaseName;
3227

3328
public String databaseVersion;
@@ -42,6 +37,8 @@ public class StateToReproduce {
4237

4338
public String queryTargetedColumnsString;
4439

40+
public OracleRunReproductionState localState;
41+
4542
public StateToReproduce(String databaseName) {
4643
this.databaseName = databaseName;
4744
}
@@ -88,14 +85,20 @@ public List<Query> getStatements() {
8885
return Collections.unmodifiableList(statements);
8986
}
9087

91-
public String getQueryString() {
92-
return queryString;
93-
}
94-
9588
public long getSeedValue() {
9689
return seedValue;
9790
}
9891

92+
/**
93+
* Returns a local state in which a test oracle can save useful information about a single run. If the local state
94+
* is closed without indicating access to it, the local statements will be added to the global state.
95+
*
96+
* @return
97+
*/
98+
public OracleRunReproductionState getLocalState() {
99+
return localState;
100+
}
101+
99102
public static class MySQLStateToReproduce extends StateToReproduce {
100103

101104
public Map<MySQLColumn, MySQLConstant> randomRowValues;
@@ -181,4 +184,43 @@ public ClickHouseExpression getWhereClause() {
181184

182185
}
183186

187+
/**
188+
* State information that is logged if the test oracle finds a bug or if an exception is thrown.
189+
*/
190+
public class OracleRunReproductionState implements Closeable {
191+
192+
private final List<Query> statements = new ArrayList<>();
193+
194+
public boolean success;
195+
196+
public OracleRunReproductionState() {
197+
StateToReproduce.this.localState = this;
198+
}
199+
200+
public void executedWithoutError() {
201+
this.success = true;
202+
}
203+
204+
public void log(Query q) {
205+
statements.add(q);
206+
}
207+
208+
public void log(String s) {
209+
statements.add(new QueryAdapter(s));
210+
}
211+
212+
@Override
213+
public void close() {
214+
if (!success) {
215+
StateToReproduce.this.statements.addAll(statements);
216+
}
217+
218+
}
219+
220+
}
221+
222+
public OracleRunReproductionState createLocalState() {
223+
return new OracleRunReproductionState();
224+
}
225+
184226
}

src/sqlancer/clickhouse/oracle/tlp/ClickHouseTLPAggregateOracle.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ public void check() throws SQLException {
8989
// TODO
9090
throw new IgnoreMeException();
9191
}
92-
state.getState().queryString = "--" + originalQuery + "\n--" + metamorphicText + "\n-- " + firstResult + "\n-- "
93-
+ secondResult;
92+
state.getState().getLocalState()
93+
.log("--" + originalQuery + "\n--" + metamorphicText + "\n-- " + firstResult + "\n-- " + secondResult);
9494
if ((firstResult == null && secondResult != null
9595
|| firstResult != null && !firstResult.contentEquals(secondResult))
9696
&& !ComparatorHelper.isEqualDouble(firstResult, secondResult)) {

src/sqlancer/cockroachdb/oracle/CockroachDBNoRECOracle.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public void check() throws SQLException {
6060
throw new IgnoreMeException();
6161
}
6262
if (optimizableCount != nonOptimizableCount) {
63-
state.getState().queryString = optimizedQueryString + ";\n" + unoptimizedQueryString + ";";
63+
state.getState().getLocalState().log(optimizedQueryString + ";\n" + unoptimizedQueryString + ";");
6464
throw new AssertionError(CockroachDBVisitor.asString(whereCondition));
6565
}
6666
}

src/sqlancer/cockroachdb/oracle/tlp/CockroachDBTLPAggregateOracle.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ public void check() throws SQLException {
8484
metamorphicQuery = createMetamorphicUnionQuery(select, aggregate, from);
8585
secondResult = getAggregateResult(metamorphicQuery);
8686

87-
state.getState().queryString = "--" + originalQuery + ";\n--" + metamorphicQuery + "\n-- " + firstResult
88-
+ "\n-- " + secondResult;
87+
state.getState().getLocalState().log(
88+
"--" + originalQuery + ";\n--" + metamorphicQuery + "\n-- " + firstResult + "\n-- " + secondResult);
8989
if (firstResult == null && secondResult != null
9090
|| firstResult != null && (!firstResult.contentEquals(secondResult)
9191
&& !ComparatorHelper.isEqualDouble(firstResult, secondResult))) {

src/sqlancer/duckdb/test/DuckDBQueryPartitioningAggregateTester.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ public void check() throws SQLException {
6464
metamorphicQuery = createMetamorphicUnionQuery(select, aggregate, select.getFromList());
6565
secondResult = getAggregateResult(metamorphicQuery);
6666

67-
state.getState().queryString = "--" + originalQuery + ";\n--" + metamorphicQuery + "\n-- " + firstResult
68-
+ "\n-- " + secondResult;
67+
state.getState().getLocalState().log(
68+
"--" + originalQuery + ";\n--" + metamorphicQuery + "\n-- " + firstResult + "\n-- " + secondResult);
6969
if (firstResult == null && secondResult != null
7070
|| firstResult != null && (!firstResult.contentEquals(secondResult)
7171
&& !ComparatorHelper.isEqualDouble(firstResult, secondResult))) {

src/sqlancer/mariadb/oracle/MariaDBNoRECOracle.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public void check() throws SQLException {
6363
throw new IgnoreMeException();
6464
}
6565
if (optimizedCount != unoptimizedCount) {
66-
state.getState().queryString = optimizedQueryString + ";\n" + unoptimizedQueryString + ";";
66+
state.getState().getLocalState().log(optimizedQueryString + ";\n" + unoptimizedQueryString + ";");
6767
throw new AssertionError(optimizedCount + " " + unoptimizedCount);
6868
}
6969
}

src/sqlancer/mysql/oracle/MySQLPivotedQuerySynthesisOracle.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ private boolean isContainedIn(String queryString) throws SQLException {
219219
}
220220

221221
String resultingQueryString = sb.toString();
222-
state.queryString = resultingQueryString;
222+
state.getLocalState().log(resultingQueryString);
223223
if (globalState.getOptions().logEachSelect()) {
224224
globalState.getLogger().writeCurrent(resultingQueryString);
225225
}

0 commit comments

Comments
 (0)