8000 Add DeleteGenerator for MariaDB by Mohab-Sobhy · Pull Request #1275 · sqlancer/sqlancer · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/sqlancer/mariadb/MariaDBProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import sqlancer.common.DBMSCommon;
import sqlancer.common.query.SQLQueryAdapter;
import sqlancer.mariadb.MariaDBProvider.MariaDBGlobalState;
import sqlancer.mariadb.gen.MariaDBDeleteGenerator;
import sqlancer.mariadb.gen.MariaDBIndexGenerator;
import sqlancer.mariadb.gen.MariaDBInsertGenerator;
import sqlancer.mariadb.gen.MariaDBSetGenerator;
Expand Down Expand Up @@ -47,6 +48,7 @@ enum Action {
SET, //
TRUNCATE, //
UPDATE, //
DELETE,
}

@Override
Expand Down Expand Up @@ -77,6 +79,9 @@ public void generateDatabase(MariaDBGlobalState globalState) throws Exception {
case CREATE_INDEX:
nrPerformed = globalState.getRandomly().getInteger(0, 2);
break;
case DELETE:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we could also generate them with a low probability? This logic will include 10 DELETE statements into every test case, rather than probabilistically generate some for some test cases, so tables are likely to be empty for many test cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mrigger Thanks for the suggestion — I’ve updated the DELETE logic accordingly.
Sorry for the late reply, I was caught up with midterm exams.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries, thanks for the PR!

nrPerformed = globalState.getRandomly().getInteger(0, 2);
break;
case SET:
nrPerformed = 20;
break;
Expand Down Expand Up @@ -140,6 +145,9 @@ public void generateDatabase(MariaDBGlobalState globalState) throws Exception {
case SET:
query = MariaDBSetGenerator.set(globalState.getRandomly(), options);
break;
case DELETE:
query = MariaDBDeleteGenerator.delete(globalState.getSchema(), globalState.getRandomly());
break;
default:
throw new AssertionError(nextAction);
}
Expand Down
93 changes: 93 additions & 0 deletions src/sqlancer/mariadb/gen/MariaDBDeleteGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package sqlancer.mariadb.gen;

import java.util.Collections;

import sqlancer.Randomly;
import sqlancer.common.query.ExpectedErrors;
import sqlancer.common.query.SQLQueryAdapter;
import sqlancer.common.schema.AbstractTables;
import sqlancer.mariadb.MariaDBSchema;
import sqlancer.mariadb.MariaDBSchema.MariaDBColumn;
import sqlancer.mariadb.MariaDBSchema.MariaDBTable;
import sqlancer.mariadb.ast.MariaDBVisitor;

public final class MariaDBDeleteGenerator {

private MariaDBDeleteGenerator() {
}

public static SQLQueryAdapter delete(MariaDBSchema schema, Randomly r) {
MariaDBTable table = schema.getRandomTable();

MariaDBExpressionGenerator expressionGenerator = new MariaDBExpressionGenerator(r);

AbstractTables<MariaDBTable, MariaDBColumn> tablesAndColumns = new AbstractTables<>(
Collections.singletonList(table));
expressionGenerator.setTablesAndColumns(tablesAndColumns);

ExpectedErrors errors = new ExpectedErrors();

errors.add("foreign key constraint fails");
errors.add("cannot delete or update a parent row");
errors.add("Data truncated");
errors.add("Division by 0");
errors.add("Incorrect value");

StringBuilder sb = new StringBuilder("DELETE");

if (Randomly.getBooleanWithRatherLowProbability()) {
sb.append(" LOW_PRIORITY");
}
if (Randomly.getBooleanWithRatherLowProbability()) {
sb.append(" QUICK");
}
if (Randomly.getBooleanWithRatherLowProbability()) {
sb.append(" IGNORE");
}

sb.append(" FROM ");
sb.append(table.getName());

if (Randomly.getBoolean()) {
sb.append(" WHERE ");
if (Randomly.getBooleanWithRatherLowProbability()) {
sb.append(MariaDBVisitor.asString(MariaDBExpressionGenerator.getRandomConstant(r)));
} else {
sb.append(MariaDBVisitor.asString(expressionGenerator.getRandomExpression()));
}
}

// ORDER BY + LIMIT
if (Randomly.getBooleanWithRatherLowProbability() && !table.getColumns().isEmpty()) {
sb.append(" ORDER BY ");
sb.append(Randomly.fromList(table.getColumns()).getName());
if (Randomly.getBoolean()) {
sb.append(Randomly.getBoolean() ? " ASC" : " DESC");
}
}

if (Randomly.getBooleanWithRatherLowProbability()) {
sb.append(" LIMIT ");
sb.append(Randomly.getNotCachedInteger(1, 10));
}

// RETURNING clause (MariaDB >= 10.5)
if (Randomly.getBooleanWithRatherLowProbability()) {
sb.append(" RETURNING ");
if (Randomly.getBooleanWithRatherLowProbability()) {
sb.append(MariaDBVisitor.asString(MariaDBExpressionGenerator.getRandomConstant(r)));
} else {
sb.append(MariaDBVisitor.asString(expressionGenerator.getRandomExpression()));
}
}

String query = sb.toString();
if (query.contains("RLIKE") || query.contains("REGEXP")) {
errors.add("Regex error");
errors.add("quantifier does not follow a repeatable item");
errors.add("Got error");
}

return new SQLQueryAdapter(query, errors);
}
}
Loading
0