1111import java .util .Arrays ;
1212import java .util .List ;
1313
14+ import sqlancer .AbstractAction ;
1415import sqlancer .GlobalState ;
1516import sqlancer .IgnoreMeException ;
16- import sqlancer .MainOptions ;
1717import sqlancer .ProviderAdapter ;
1818import sqlancer .Query ;
1919import sqlancer .QueryAdapter ;
2020import sqlancer .QueryProvider ;
2121import sqlancer .Randomly ;
2222import sqlancer .StateToReproduce ;
2323import sqlancer .StateToReproduce .SQLite3StateToReproduce ;
24+ import sqlancer .StatementExecutor ;
2425import sqlancer .TestOracle ;
2526import sqlancer .sqlite3 .SQLite3Provider .SQLite3GlobalState ;
2627import sqlancer .sqlite3 .gen .SQLite3AnalyzeGenerator ;
@@ -61,7 +62,7 @@ public SQLite3Provider() {
6162 super (SQLite3GlobalState .class , SQLite3Options .class );
6263 }
6364
64- public enum Action {
65+ public enum Action implements AbstractAction < SQLite3GlobalState > {
6566 PRAGMA (SQLite3PragmaGenerator ::insertPragma ), //
6667 INDEX (SQLite3IndexGenerator ::insertIndex ), //
6768 INSERT (SQLite3InsertGenerator ::insertRow ), //
@@ -147,6 +148,7 @@ public enum Action {
147148 this .queryProvider = queryProvider ;
148149 }
149150
151+ @ Override
150152 public Query getQuery (SQLite3GlobalState state ) throws SQLException {
151153 return queryProvider .getQuery (state );
152154 }
@@ -175,10 +177,61 @@ private enum TableType {
175177 NORMAL , FTS , RTREE
176178 }
177179
180+ private static int mapActions (SQLite3GlobalState globalState , Action a ) {
181+ int nrPerformed = 0 ;
182+ Randomly r = globalState .getRandomly ();
183+ switch (a ) {
184+ case CREATE_VIEW :
185+ nrPerformed = r .getInteger (0 , 2 );
186+ break ;
187+ case DELETE :
188+ case DROP_VIEW :
189+ case DROP_INDEX :
190+ nrPerformed = r .getInteger (0 , 0 );
191+ break ;
192+ case ALTER :
193+ nrPerformed = r .getInteger (0 , 0 );
194+ break ;
195+ case EXPLAIN :
196+ case CREATE_TRIGGER :
197+ case DROP_TABLE :
198+ nrPerformed = r .getInteger (0 , 0 );
199+ break ;
200+ case VACUUM :
201+ case CHECK_RTREE_TABLE :
202+ nrPerformed = r .getInteger (0 , 3 );
203+ break ;
204+ case INSERT :
205+ nrPerformed = r .getInteger (0 , globalState .getOptions ().getMaxNumberInserts ());
206+ break ;
207+ case MANIPULATE_STAT_TABLE :
208+ nrPerformed = r .getInteger (0 , 5 );
209+ break ;
210+ case INDEX :
211+ nrPerformed = r .getInteger (0 , 5 );
212+ break ;
213+ case VIRTUAL_TABLE_ACTION :
214+ case UPDATE :
215+ nrPerformed = r .getInteger (0 , 30 );
216+ break ;
217+ case PRAGMA :
218+ nrPerformed = r .getInteger (0 , 20 );
219+ break ;
220+ case TRANSACTION_START :
221+ case REINDEX :
222+ case ANALYZE :
223+ case ROLLBACK_TRANSACTION :
224+ case COMMIT :
225+ default :
226+ nrPerformed = r .getInteger (1 , 10 );
227+ break ;
228+ }
229+ return nrPerformed ;
230+ }
231+
178232 @ Override
179233 public void generateDatabase (SQLite3GlobalState globalState ) throws SQLException {
180234 SQLite3Options sqliteOptions = globalState .getDmbsSpecificOptions ();
181- MainOptions options = globalState .getOptions ();
182235 Randomly r = new Randomly (SQLite3SpecialStringGenerator ::generate );
183236 globalState .setSqliteOptions (sqliteOptions );
184237 globalState .setRandomly (r );
@@ -205,92 +258,14 @@ public void generateDatabase(SQLite3GlobalState globalState) throws SQLException
205258 "CREATE VIRTUAL TABLE IF NOT EXISTS stat USING dbstat(main)" );
206259 globalState .executeStatement (tableQuery );
207260 }
208- int [] nrRemaining = new int [Action .values ().length ];
209- List <Action > actions = new ArrayList <>();
210- int total = 0 ;
211- for (i = 0 ; i < Action .values ().length ; i ++) {
212- Action action = Action .values ()[i ];
213- int nrPerformed = 0 ;
214- switch (action ) {
215- case CREATE_VIEW :
216- nrPerformed = r .getInteger (0 , 2 );
217- break ;
218- case DELETE :
219- case DROP_VIEW :
220- case DROP_INDEX :
221- nrPerformed = r .getInteger (0 , 0 );
222- break ;
223- case ALTER :
224- nrPerformed = r .getInteger (0 , 0 );
225- break ;
226- case EXPLAIN :
227- case CREATE_TRIGGER :
228- case DROP_TABLE :
229- nrPerformed = r .getInteger (0 , 0 );
230- break ;
231- case VACUUM :
232- case CHECK_RTREE_TABLE :
233- nrPerformed = r .getInteger (0 , 3 );
234- break ;
235- case INSERT :
236- nrPerformed = r .getInteger (0 , options .getMaxNumberInserts ());
237- break ;
238- case MANIPULATE_STAT_TABLE :
239- nrPerformed = r .getInteger (0 , 5 );
240- break ;
241- case INDEX :
242- nrPerformed = r .getInteger (0 , 5 );
243- break ;
244- case VIRTUAL_TABLE_ACTION :
245- case UPDATE :
246- nrPerformed = r .getInteger (0 , 30 );
247- break ;
248- case PRAGMA :
249- nrPerformed = r .getInteger (0 , 20 );
250- break ;
251- case TRANSACTION_START :
252- case REINDEX :
253- case ANALYZE :
254- case ROLLBACK_TRANSACTION :
255- case COMMIT :
256- default :
257- nrPerformed = r .getInteger (1 , 10 );
258- break ;
259- }
260- if (nrPerformed != 0 ) {
261- actions .add (action );
262- }
263- nrRemaining [action .ordinal ()] = nrPerformed ;
264- total += nrPerformed ;
265- }
266- while (total != 0 ) {
267- Action nextAction = null ;
268- int selection = r .getInteger (0 , total );
269- int previousRange = 0 ;
270- for (i = 0 ; i < nrRemaining .length ; i ++) {
271- if (previousRange <= selection && selection < previousRange + nrRemaining [i ]) {
272- nextAction = Action .values ()[i ];
273- break ;
274- } else {
275- previousRange += nrRemaining [i ];
276- }
277- }
278- assert nextAction != null ;
279- assert nrRemaining [nextAction .ordinal ()] > 0 ;
280- nrRemaining [nextAction .ordinal ()]--;
281- Query query = null ;
282- try {
283- query = nextAction .getQuery (globalState );
284- globalState .executeStatement (query );
285- } catch (IgnoreMeException e ) {
261+ StatementExecutor <SQLite3GlobalState , Action > se = new StatementExecutor <>(globalState , Action .values (),
262+ SQLite3Provider ::mapActions , (q ) -> {
263+ if (q .couldAffectSchema () && globalState .getSchema ().getDatabaseTables ().isEmpty ()) {
264+ throw new IgnoreMeException ();
265+ }
266+ });
267+ se .executeStatements ();
286268
287- }
288- if (query != null && query .couldAffectSchema ()
289- && globalState .getSchema ().getDatabaseTables ().isEmpty ()) {
290- throw new IgnoreMeException ();
291- }
292- total --;
293- }
294269 Query query = SQLite3TransactionGenerator .generateCommit (globalState );
295270 globalState .executeStatement (query );
296271
0 commit comments