package sqlancer; import sqlancer.common.query.Query; import sqlancer.common.query.SQLancerResultSet; import sqlancer.common.schema.AbstractSchema; import sqlancer.common.schema.AbstractTable; public abstract class GlobalState, S extends AbstractSchema, ?>, C extends SQLancerDBConnection> { protected C databaseConnection; private Randomly r; private MainOptions options; private O dbmsSpecificOptions; private S schema; private Main.StateLogger logger; private StateToReproduce state; private Main.QueryManager manager; private String databaseName; public void setConnection(C con) { this.databaseConnection = con; } public C getConnection() { return databaseConnection; } @SuppressWarnings("unchecked") public void setDbmsSpecificOptions(Object dbmsSpecificOptions) { this.dbmsSpecificOptions = (O) dbmsSpecificOptions; } public O getDbmsSpecificOptions() { return dbmsSpecificOptions; } public void setRandomly(Randomly r) { this.r = r; } public Randomly getRandomly() { return r; } public MainOptions getOptions() { return options; } public void setMainOptions(MainOptions options) { this.options = options; } public void setStateLogger(Main.StateLogger logger) { this.logger = logger; } public Main.StateLogger getLogger() { return logger; } public void setState(StateToReproduce state) { this.state = state; } public StateToReproduce getState() { return state; } public Main.QueryManager getManager() { return manager; } public void setManager(Main.QueryManager manager) { this.manager = manager; } public String getDatabaseName() { return databaseName; } public void setDatabaseName(String databaseName) { this.databaseName = databaseName; } private ExecutionTimer executePrologue(Query> q) throws Exception { boolean logExecutionTime = getOptions().logExecutionTime(); ExecutionTimer timer = null; if (logExecutionTime) { timer = new ExecutionTimer().start(); } if (getOptions().printAllStatements()) { System.out.println(q.getLogString()); } if (getOptions().logEachSelect()) { if (logExecutionTime) { getLogger().writeCurrentNoLineBreak(q.getLogString()); } else { getLogger().writeCurrent(q.getLogString()); } } return timer; } protected abstract void executeEpilogue(Query> q, boolean success, ExecutionTimer timer) throws Exception; public boolean executeStatement(Query q, String... fills) throws Exception { ExecutionTimer timer = executePrologue(q); boolean success = manager.execute(q, fills); executeEpilogue(q, success, timer); return success; } public SQLancerResultSet executeStatementAndGet(Query q, String... fills) throws Exception { ExecutionTimer timer = executePrologue(q); SQLancerResultSet result = manager.executeAndGet(q, fills); boolean success = result != null; if (success) { result.registerEpilogue(() -> { try { executeEpilogue(q, success, timer); } catch (Exception e) { throw new AssertionError(e); } }); } return result; } public S getSchema() { if (schema == null) { try { updateSchema(); } catch (Exception e) { throw new AssertionError(e.getMessage()); } } return schema; } protected void setSchema(S schema) { this.schema = schema; } public void updateSchema() throws Exception { setSchema(readSchema()); for (AbstractTable, ?, ?> table : schema.getDatabaseTables()) { table.recomputeCount(); } } protected abstract S readSchema() throws Exception; }