From c58cc468cca9a89de59add149aa7af845fbebfcc Mon Sep 17 00:00:00 2001 From: Mohab-Sobhy Date: Thu, 18 Sep 2025 23:25:09 +0300 Subject: [PATCH 1/4] Add DeleteGenerator for MariaDB --- src/sqlancer/mariadb/MariaDBProvider.java | 15 +-- .../mariadb/gen/MariaDBDeleteGenerator.java | 94 +++++++++++++++++++ 2 files changed, 102 insertions(+), 7 deletions(-) create mode 100644 src/sqlancer/mariadb/gen/MariaDBDeleteGenerator.java diff --git a/src/sqlancer/mariadb/MariaDBProvider.java b/src/sqlancer/mariadb/MariaDBProvider.java index 48254b8ec..8f7eb78ad 100644 --- a/src/sqlancer/mariadb/MariaDBProvider.java +++ b/src/sqlancer/mariadb/MariaDBProvider.java @@ -19,13 +19,7 @@ import sqlancer.common.DBMSCommon; import sqlancer.common.query.SQLQueryAdapter; import sqlancer.mariadb.MariaDBProvider.MariaDBGlobalState; -import sqlancer.mariadb.gen.MariaDBIndexGenerator; -import sqlancer.mariadb.gen.MariaDBInsertGenerator; -import sqlancer.mariadb.gen.MariaDBSetGenerator; -import sqlancer.mariadb.gen.MariaDBTableAdminCommandGenerator; -import sqlancer.mariadb.gen.MariaDBTableGenerator; -import sqlancer.mariadb.gen.MariaDBTruncateGenerator; -import sqlancer.mariadb.gen.MariaDBUpdateGenerator; +import sqlancer.mariadb.gen.*; @AutoService(DatabaseProvider.class) public class MariaDBProvider extends SQLProviderAdapter { @@ -47,6 +41,7 @@ enum Action { SET, // TRUNCATE, // UPDATE, // + DELETE, } @Override @@ -77,6 +72,9 @@ public void generateDatabase(MariaDBGlobalState globalState) throws Exception { case CREATE_INDEX: nrPerformed = globalState.getRandomly().getInteger(0, 2); break; + case DELETE: + nrPerformed = 10; + break; case SET: nrPerformed = 20; break; @@ -140,6 +138,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); } diff --git a/src/sqlancer/mariadb/gen/MariaDBDeleteGenerator.java b/src/sqlancer/mariadb/gen/MariaDBDeleteGenerator.java new file mode 100644 index 000000000..d1f3d2600 --- /dev/null +++ b/src/sqlancer/mariadb/gen/MariaDBDeleteGenerator.java @@ -0,0 +1,94 @@ +package sqlancer.mariadb.gen; + +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.MariaDBTable; +import sqlancer.mariadb.MariaDBSchema.MariaDBColumn; +import sqlancer.mariadb.ast.MariaDBVisitor; + +import java.util.Collections; + +public final class MariaDBDeleteGenerator { + + private MariaDBDeleteGenerator() { + } + + public static SQLQueryAdapter delete(MariaDBSchema schema, Randomly r) { + MariaDBTable table = schema.getRandomTable(); + + MariaDBExpressionGenerator expressionGenerator = new MariaDBExpressionGenerator(r); + + AbstractTables 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() + )); + } + } + + return new SQLQueryAdapter(sb.toString(), errors); + } +} From fde4da74ad9222ac537a6e9ad3f0bfd55daa95a8 Mon Sep 17 00:00:00 2001 From: Mohab-Sobhy Date: Wed, 8 Oct 2025 10:59:55 +0300 Subject: [PATCH 2/4] Format code to fix linter error --- .../mariadb/gen/MariaDBDeleteGenerator.java | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/sqlancer/mariadb/gen/MariaDBDeleteGenerator.java b/src/sqlancer/mariadb/gen/MariaDBDeleteGenerator.java index d1f3d2600..28136eb08 100644 --- a/src/sqlancer/mariadb/gen/MariaDBDeleteGenerator.java +++ b/src/sqlancer/mariadb/gen/MariaDBDeleteGenerator.java @@ -21,8 +21,8 @@ public static SQLQueryAdapter delete(MariaDBSchema schema, Randomly r) { MariaDBExpressionGenerator expressionGenerator = new MariaDBExpressionGenerator(r); - AbstractTables tablesAndColumns = - new AbstractTables<>(Collections.singletonList(table)); + AbstractTables tablesAndColumns = new AbstractTables<>( + Collections.singletonList(table)); expressionGenerator.setTablesAndColumns(tablesAndColumns); ExpectedErrors errors = new ExpectedErrors(); @@ -51,13 +51,9 @@ public static SQLQueryAdapter delete(MariaDBSchema schema, Randomly r) { if (Randomly.getBoolean()) { sb.append(" WHERE "); if (Randomly.getBooleanWithRatherLowProbability()) { - sb.append(MariaDBVisitor.asString( - MariaDBExpressionGenerator.getRandomConstant(r) - )); + sb.append(MariaDBVisitor.asString(MariaDBExpressionGenerator.getRandomConstant(r))); } else { - sb.append(MariaDBVisitor.asString( - expressionGenerator.getRandomExpression() - )); + sb.append(MariaDBVisitor.asString(expressionGenerator.getRandomExpression())); } } @@ -79,13 +75,9 @@ public static SQLQueryAdapter delete(MariaDBSchema schema, Randomly r) { if (Randomly.getBooleanWithRatherLowProbability()) { sb.append(" RETURNING "); if (Randomly.getBooleanWithRatherLowProbability()) { - sb.append(MariaDBVisitor.asString( - MariaDBExpressionGenerator.getRandomConstant(r) - )); + sb.append(MariaDBVisitor.asString(MariaDBExpressionGenerator.getRandomConstant(r))); } else { - sb.append(MariaDBVisitor.asString( - expressionGenerator.getRandomExpression() - )); + sb.append(MariaDBVisitor.asString(expressionGenerator.getRandomExpression())); } } From 18ab56017c46be4ea0309b57ce990f176ac72dbe Mon Sep 17 00:00:00 2001 From: Mohab-Sobhy Date: Mon, 3 Nov 2025 01:11:36 +0200 Subject: [PATCH 3/4] Fix Checkstyle violations and add expected errors for invalid regex in MariaDBDeleteGenerator --- src/sqlancer/mariadb/MariaDBProvider.java | 9 ++++++++- .../mariadb/gen/MariaDBDeleteGenerator.java | 15 +++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/sqlancer/mariadb/MariaDBProvider.java b/src/sqlancer/mariadb/MariaDBProvider.java index 8f7eb78ad..c8037c019 100644 --- a/src/sqlancer/mariadb/MariaDBProvider.java +++ b/src/sqlancer/mariadb/MariaDBProvider.java @@ -19,7 +19,14 @@ import sqlancer.common.DBMSCommon; import sqlancer.common.query.SQLQueryAdapter; import sqlancer.mariadb.MariaDBProvider.MariaDBGlobalState; -import sqlancer.mariadb.gen.*; +import sqlancer.mariadb.gen.MariaDBDeleteGenerator; +import sqlancer.mariadb.gen.MariaDBIndexGenerator; +import sqlancer.mariadb.gen.MariaDBInsertGenerator; +import sqlancer.mariadb.gen.MariaDBSetGenerator; +import sqlancer.mariadb.gen.MariaDBTableAdminCommandGenerator; +import sqlancer.mariadb.gen.MariaDBTableGenerator; +import sqlancer.mariadb.gen.MariaDBTruncateGenerator; +import sqlancer.mariadb.gen.MariaDBUpdateGenerator; @AutoService(DatabaseProvider.class) public class MariaDBProvider extends SQLProviderAdapter { diff --git a/src/sqlancer/mariadb/gen/MariaDBDeleteGenerator.java b/src/sqlancer/mariadb/gen/MariaDBDeleteGenerator.java index 28136eb08..6d85eb891 100644 --- a/src/sqlancer/mariadb/gen/MariaDBDeleteGenerator.java +++ b/src/sqlancer/mariadb/gen/MariaDBDeleteGenerator.java @@ -1,16 +1,16 @@ 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.MariaDBTable; import sqlancer.mariadb.MariaDBSchema.MariaDBColumn; +import sqlancer.mariadb.MariaDBSchema.MariaDBTable; import sqlancer.mariadb.ast.MariaDBVisitor; -import java.util.Collections; - public final class MariaDBDeleteGenerator { private MariaDBDeleteGenerator() { @@ -81,6 +81,13 @@ public static SQLQueryAdapter delete(MariaDBSchema schema, Randomly r) { } } - return new SQLQueryAdapter(sb.toString(), errors); + 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); } } From 35105ec31d873b0309e86b6563a7f02ff00e409e Mon Sep 17 00:00:00 2001 From: Mohab-Sobhy Date: Thu, 20 Nov 2025 08:43:50 +0200 Subject: [PATCH 4/4] Modify DELETE generation probability --- src/sqlancer/mariadb/MariaDBProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sqlancer/mariadb/MariaDBProvider.java b/src/sqlancer/mariadb/MariaDBProvider.java index c8037c019..a9737f549 100644 --- a/src/sqlancer/mariadb/MariaDBProvider.java +++ b/src/sqlancer/mariadb/MariaDBProvider.java @@ -80,7 +80,7 @@ public void generateDatabase(MariaDBGlobalState globalState) throws Exception { nrPerformed = globalState.getRandomly().getInteger(0, 2); break; case DELETE: - nrPerformed = 10; + nrPerformed = globalState.getRandomly().getInteger(0, 2); break; case SET: nrPerformed = 20;