Skip to content

Commit 389bd04

Browse files
committed
Introduce a command per DBMS
1 parent cd295b1 commit 389bd04

25 files changed

Lines changed: 180 additions & 137 deletions

src/sqlancer/DatabaseProvider.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import java.util.List;
1010
import java.util.Set;
1111

12-
public interface DatabaseProvider<G extends GlobalState> {
12+
public interface DatabaseProvider<G extends GlobalState<O>, O> {
1313

1414
void generateAndTestDatabase(G globalState) throws SQLException;
1515

@@ -22,6 +22,8 @@ public interface DatabaseProvider<G extends GlobalState> {
2222
void printDatabaseSpecificState(FileWriter writer, StateToReproduce state);
2323

2424
StateToReproduce getStateToReproduce(String databaseName);
25+
26+
O getCommand();
2527

2628
public static boolean isEqualDouble(String first, String second) {
2729
try {
@@ -41,7 +43,7 @@ public static boolean equals(double a, double b) {
4143
}
4244

4345

44-
public static List<String> getResultSetFirstColumnAsString(String queryString, Set<String> errors, Connection con, GlobalState state) throws SQLException {
46+
public static List<String> getResultSetFirstColumnAsString(String queryString, Set<String> errors, Connection con, GlobalState<?> state) throws SQLException {
4547
if (state.getOptions().logEachSelect()) {
4648
// TODO: refactor me
4749
state.getLogger().writeCurrent(queryString);

src/sqlancer/GlobalState.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,29 @@
55
import sqlancer.Main.QueryManager;
66
import sqlancer.Main.StateLogger;
77

8-
public class GlobalState {
8+
public class GlobalState<O> {
99

1010
private Connection con;
1111
private Randomly r;
1212
private MainOptions options;
13+
private O dmbsSpecificOptions;
1314
private StateLogger logger;
1415
private StateToReproduce state;
1516
private QueryManager manager;
1617
private String databaseName;
17-
18+
1819
public void setConnection(Connection con) {
1920
this.con = con;
2021
}
22+
23+
@SuppressWarnings("unchecked")
24+
public void setDmbsSpecificOptions(Object dmbsSpecificOptions) {
25+
this.dmbsSpecificOptions = (O) dmbsSpecificOptions;
26+
}
27+
28+
public O getDmbsSpecificOptions() {
29+
return dmbsSpecificOptions;
30+
}
2131

2232
public Connection getConnection() {
2333
return con;

src/sqlancer/Main.java

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@
1515
import java.text.SimpleDateFormat;
1616
import java.util.ArrayList;
1717
import java.util.Date;
18+
import java.util.HashMap;
1819
import java.util.List;
20+
import java.util.Map;
1921
import java.util.concurrent.ExecutorService;
2022
import java.util.concurrent.Executors;
2123
import java.util.concurrent.ScheduledExecutorService;
2224
import java.util.concurrent.TimeUnit;
2325
import java.util.concurrent.atomic.AtomicLong;
2426

2527
import com.beust.jcommander.JCommander;
28+
import com.beust.jcommander.JCommander.Builder;
2629

2730
import sqlancer.cockroachdb.CockroachDBProvider;
2831
import sqlancer.mariadb.MariaDBProvider;
@@ -56,7 +59,7 @@ public final static class StateLogger {
5659
public FileWriter currentFileWriter;
5760
private static final List<String> initializedProvidersNames = new ArrayList<>();
5861
private boolean logEachSelect = true;
59-
private DatabaseProvider provider;
62+
private DatabaseProvider<?, ?> provider;
6063

6164
private final static class AlsoWriteToConsoleFileWriter extends FileWriter {
6265

@@ -77,7 +80,7 @@ public void write(String str) throws IOException {
7780
}
7881
}
7982

80-
public StateLogger(String databaseName, DatabaseProvider provider, MainOptions options) {
83+
public StateLogger(String databaseName, DatabaseProvider<?, ?> provider, MainOptions options) {
8184
this.provider = provider;
8285
File dir = new File(LOG_DIRECTORY, provider.getLogFileSubdirectoryName());
8386
if (dir.exists() && !dir.isDirectory()) {
@@ -92,7 +95,7 @@ public StateLogger(String databaseName, DatabaseProvider provider, MainOptions o
9295
}
9396
}
9497

95-
private synchronized void ensureExistsAndIsEmpty(File dir, DatabaseProvider provider) {
98+
private synchronized void ensureExistsAndIsEmpty(File dir, DatabaseProvider<?, ?> provider) {
9699
if (initializedProvidersNames.contains(provider.getLogFileSubdirectoryName())) {
97100
return;
98101
}
@@ -289,9 +292,35 @@ public static void printArray(Object[] arr) {
289292
}
290293

291294
public static void main(String[] args) {
292-
295+
List<DatabaseProvider<?, ?>> providers = new ArrayList<>();
296+
providers.add(new SQLite3Provider());
297+
providers.add(new CockroachDBProvider());
298+
providers.add(new MySQLProvider());
299+
providers.add(new MariaDBProvider());
300+
providers.add(new TiDBProvider());
301+
providers.add(new PostgresProvider());
302+
providers.add(new TDEngineProvider());
303+
Map<String, DatabaseProvider<?, ?>> nameToProvider = new HashMap<>();
304+
Map<String, Object> nameToOptions = new HashMap<>();
293305
MainOptions options = new MainOptions();
294-
JCommander.newBuilder().addObject(options).build().parse(args);
306+
Builder commandBuilder = JCommander.newBuilder()
307+
.addObject(options);
308+
for (DatabaseProvider<?, ?> provider : providers) {
309+
String name = provider.getLogFileSubdirectoryName();
310+
Object command = provider.getCommand();
311+
if (command == null) {
312+
throw new IllegalStateException();
313+
}
314+
nameToProvider.put(name, provider);
315+
nameToOptions.put(name, command);
316+
commandBuilder = commandBuilder.addCommand(name, command);
317+
}
318+
JCommander jc = commandBuilder.build();
319+
jc.parse(args);
320+
if (jc.getParsedCommand() == null) {
321+
jc.usage();
322+
System.exit(-1);
323+
}
295324

296325
final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
297326
scheduler.scheduleAtFixedRate(new Runnable() {
@@ -336,59 +365,42 @@ public void run() {
336365

337366
StateToReproduce stateToRepro;
338367
StateLogger logger;
339-
DatabaseProvider<?> provider;
368+
DatabaseProvider<?, ?> provider;
340369

341370
@Override
342371
public void run() {
343-
switch (options.getDbms()) {
344-
case MariaDB:
345-
provider = new MariaDBProvider();
346-
break;
347-
case MySQL:
348-
provider = new MySQLProvider();
349-
break;
350-
case PostgreSQL:
351-
provider = new PostgresProvider();
352-
break;
353-
case SQLite3:
354-
provider = new SQLite3Provider();
355-
break;
356-
case TDEngine:
357-
provider = new TDEngineProvider();
358-
break;
359-
case CockroachDB:
360-
provider = new CockroachDBProvider();
361-
break;
362-
case TiDB:
363-
provider = new TiDBProvider();
364-
break;
365-
}
366372
runThread(databaseName);
367373
}
368374

369375
private void runThread(final String databaseName) {
370376
Thread.currentThread().setName(databaseName);
371377
while (true) {
378+
// create a new instance of the provider in case it has a global state
379+
try {
380+
provider = nameToProvider.get(jc.getParsedCommand()).getClass().newInstance();
381+
} catch (Exception e) {
382+
throw new AssertionError(e);
383+
}
372384
stateToRepro = provider.getStateToReproduce(databaseName);
373385
logger = new StateLogger(databaseName, provider, options);
374386
try (Connection con = provider.createDatabase(databaseName, stateToRepro)) {
375387
QueryManager manager = new QueryManager(con, stateToRepro);
376388
java.sql.DatabaseMetaData meta = con.getMetaData();
377389
stateToRepro.databaseVersion = meta.getDatabaseProductVersion();
378-
GlobalState state = (GlobalState) provider.generateGlobalState();
390+
GlobalState<?> state = (GlobalState<?>) provider.generateGlobalState();
379391
state.setState(stateToRepro);
380392
Randomly r = new Randomly();
381393
state.setDatabaseName(databaseName);
382394
state.setConnection(con);
383395
state.setRandomly(r);
384396
state.setMainOptions(options);
397+
Object dmbsSpecificOptions = nameToOptions.get(jc.getParsedCommand());
398+
state.setDmbsSpecificOptions(dmbsSpecificOptions);
385399
state.setStateLogger(logger);
386400
state.setManager(manager);
387401
Method method = provider.getClass().getMethod("generateAndTestDatabase", state.getClass());
388402
method.setAccessible(true);
389403
method.invoke(provider, state);
390-
// provider.generateAndTestDatabase(state);
391-
// provider.generateAndTestDatabase(databaseName, con, logger, state, manager, options);
392404
} catch (IgnoreMeException e) {
393405
continue;
394406
} catch (InvocationTargetException e) {

src/sqlancer/MainOptions.java

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import com.beust.jcommander.IStringConverter;
44
import com.beust.jcommander.Parameter;
5+
import com.beust.jcommander.Parameters;
56

7+
@Parameters(separators = "=", commandDescription = "Options applicable to all DBMS")
68
public class MainOptions {
79

810
@Parameter(names = {
@@ -26,12 +28,6 @@ public class MainOptions {
2628
@Parameter(names = "--log-each-select", description = "Logs every statement issued", arity = 1)
2729
private boolean logEachSelect = true;
2830

29-
@Parameter(names = "--dbms-specific-options")
30-
private String dbmsSpecificOptions = "";
31-
32-
@Parameter(names = "--dbms", converter = DBMSConverter.class, required = true)
33-
private DBMS dbms;
34-
3531
public int getMaxExpressionDepth() {
3632
return maxExpressionDepth;
3733
}
@@ -52,10 +48,6 @@ public boolean logEachSelect() {
5248
return logEachSelect;
5349
}
5450

55-
public String getDbmsOptions() {
56-
return dbmsSpecificOptions;
57-
}
58-
5951
public int getNrQueries() {
6052
return nrQueries;
6153
}
@@ -75,8 +67,4 @@ public DBMS convert(String value) {
7567
}
7668
}
7769

78-
public DBMS getDbms() {
79-
return dbms;
80-
}
81-
8270
}

src/sqlancer/cockroachdb/CockroachDBErrors.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ private static void addArrayErrors(Set<String> errors) {
246246

247247
errors.add("as bytes[], found type: varbit[]");
248248
errors.add("to be of type decimal[], found type float[]");
249+
errors.add("to be of type int[], found type decimal[]");
249250

250251
errors.add("to be of type unknown[]"); // IF with null array
251252
}

src/sqlancer/cockroachdb/CockroachDBOptions.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.sql.SQLException;
44

55
import com.beust.jcommander.Parameter;
6+
import com.beust.jcommander.Parameters;
67

78
import sqlancer.MainOptions.DBMSConverter;
89
import sqlancer.TestOracle;
@@ -14,6 +15,7 @@
1415
import sqlancer.cockroachdb.test.CockroachDBQueryPartitioningTester;
1516
import sqlancer.cockroachdb.test.CockroachDBQueryPartitioningWhereTester;
1617

18+
@Parameters(separators = "=", commandDescription = "Test CockroachDB")
1719
public class CockroachDBOptions {
1820

1921
@Parameter(names = "--oracle", converter = DBMSConverter.class)

0 commit comments

Comments
 (0)