Skip to content

Commit 2fdc987

Browse files
eltfshrmrigger
andauthored
Refactor UpdateGenerator classes using AbstractUpdateGenerator class (#662)
* Add AbstractUpdateGenerator class * Refactor UpdateGenerator classes * Add ExpectedErrors to AbstractUpdateGenerator Co-authored-by: Manuel Rigger <rigger@nus.edu.sg>
1 parent 4d42dad commit 2fdc987

File tree

11 files changed

+276
-229
lines changed

11 files changed

+276
-229
lines changed

src/sqlancer/cockroachdb/gen/CockroachDBUpdateGenerator.java

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,36 +9,35 @@
99
import sqlancer.cockroachdb.CockroachDBSchema.CockroachDBDataType;
1010
import sqlancer.cockroachdb.CockroachDBSchema.CockroachDBTable;
1111
import sqlancer.cockroachdb.CockroachDBVisitor;
12-
import sqlancer.common.query.ExpectedErrors;
12+
import sqlancer.common.gen.AbstractUpdateGenerator;
1313
import sqlancer.common.query.SQLQueryAdapter;
1414

15-
public final class CockroachDBUpdateGenerator {
15+
public final class CockroachDBUpdateGenerator extends AbstractUpdateGenerator<CockroachDBColumn> {
1616

17-
private CockroachDBUpdateGenerator() {
17+
private final CockroachDBGlobalState globalState;
18+
private CockroachDBExpressionGenerator gen;
19+
20+
private CockroachDBUpdateGenerator(CockroachDBGlobalState globalState) {
21+
this.globalState = globalState;
1822
}
1923

2024
public static SQLQueryAdapter gen(CockroachDBGlobalState globalState) {
21-
ExpectedErrors errors = new ExpectedErrors();
25+
return new CockroachDBUpdateGenerator(globalState).generate();
26+
}
27+
28+
private SQLQueryAdapter generate() {
2229
CockroachDBTable table = globalState.getSchema().getRandomTable(t -> !t.isView());
2330
List<CockroachDBColumn> columns = table.getRandomNonEmptyColumnSubset();
24-
CockroachDBExpressionGenerator gen = new CockroachDBExpressionGenerator(globalState).setColumns(columns);
25-
StringBuilder sb = new StringBuilder("UPDATE ");
31+
gen = new CockroachDBExpressionGenerator(globalState).setColumns(columns);
32+
sb.append("UPDATE ");
2633
sb.append(table.getName());
2734
if (Randomly.getBoolean()) {
2835
sb.append("@{FORCE_INDEX=");
2936
sb.append(Randomly.fromList(table.getIndexes()).getIndexName());
3037
sb.append("}");
3138
}
3239
sb.append(" SET ");
33-
int i = 0;
34-
for (CockroachDBColumn c : columns) {
35-
if (i++ != 0) {
36-
sb.append(", ");
37-
}
38-
sb.append(c.getName());
39-
sb.append("=");
40-
sb.append(CockroachDBVisitor.asString(gen.generateExpression(c.getType())));
41-
}
40+
updateColumns(columns);
4241
if (Randomly.getBoolean()) {
4342
sb.append(" WHERE ");
4443
sb.append(CockroachDBVisitor.asString(gen.generateExpression(CockroachDBDataType.BOOL.get())));
@@ -55,4 +54,9 @@ public static SQLQueryAdapter gen(CockroachDBGlobalState globalState) {
5554
return new SQLQueryAdapter(sb.toString(), errors);
5655
}
5756

57+
@Override
58+
protected void updateValue(CockroachDBColumn column) {
59+
sb.append(CockroachDBVisitor.asString(gen.generateExpression(column.getType())));
60+
}
61+
5862
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package sqlancer.common.gen;
2+
3+
import java.util.List;
4+
5+
import sqlancer.common.query.ExpectedErrors;
6+
import sqlancer.common.schema.AbstractTableColumn;
7+
8+
public abstract class AbstractUpdateGenerator<C extends AbstractTableColumn<?, ?>> {
9+
10+
protected final ExpectedErrors errors = new ExpectedErrors();
11+
protected StringBuilder sb = new StringBuilder();
12+
13+
protected void updateColumns(List<C> columns) {
14+
for (int nrColumn = 0; nrColumn < columns.size(); nrColumn++) {
15+
if (nrColumn != 0) {
16+
sb.append(", ");
17+
}
18+
sb.append(columns.get(nrColumn).getName());
19+
sb.append("=");
20+
updateValue(columns.get(nrColumn));
21+
}
22+
}
23+
24+
protected abstract void updateValue(C column);
25+
26+
}

src/sqlancer/duckdb/gen/DuckDBUpdateGenerator.java

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import sqlancer.Randomly;
66
import sqlancer.common.ast.newast.Node;
7-
import sqlancer.common.query.ExpectedErrors;
7+
import sqlancer.common.gen.AbstractUpdateGenerator;
88
import sqlancer.common.query.SQLQueryAdapter;
99
import sqlancer.duckdb.DuckDBErrors;
1010
import sqlancer.duckdb.DuckDBProvider.DuckDBGlobalState;
@@ -13,36 +13,41 @@
1313
import sqlancer.duckdb.DuckDBToStringVisitor;
1414
import sqlancer.duckdb.ast.DuckDBExpression;
1515

16-
public final class DuckDBUpdateGenerator {
16+
public final class DuckDBUpdateGenerator extends AbstractUpdateGenerator<DuckDBColumn> {
1717

18-
private DuckDBUpdateGenerator() {
18+
private final DuckDBGlobalState globalState;
19+
private DuckDBExpressionGenerator gen;
20+
21+
private DuckDBUpdateGenerator(DuckDBGlobalState globalState) {
22+
this.globalState = globalState;
1923
}
2024

2125
public static SQLQueryAdapter getQuery(DuckDBGlobalState globalState) {
22-
StringBuilder sb = new StringBuilder("UPDATE ");
23-
ExpectedErrors errors = new ExpectedErrors();
26+
return new DuckDBUpdateGenerator(globalState).generate();
27+
}
28+
29+
private SQLQueryAdapter generate() {
2430
DuckDBTable table = globalState.getSchema().getRandomTable(t -> !t.isView());
31+
List<DuckDBColumn> columns = table.getRandomNonEmptyColumnSubset();
32+
gen = new DuckDBExpressionGenerator(globalState).setColumns(table.getColumns());
33+
sb.append("UPDATE ");
2534
sb.append(table.getName());
26-
DuckDBExpressionGenerator gen = new DuckDBExpressionGenerator(globalState).setColumns(table.getColumns());
2735
sb.append(" SET ");
28-
List<DuckDBColumn> columns = table.getRandomNonEmptyColumnSubset();
29-
for (int i = 0; i < columns.size(); i++) {
30-
if (i != 0) {
31-
sb.append(", ");
32-
}
33-
sb.append(columns.get(i).getName());
34-
sb.append("=");
35-
Node<DuckDBExpression> expr;
36-
if (Randomly.getBooleanWithSmallProbability()) {
37-
expr = gen.generateExpression();
38-
DuckDBErrors.addExpressionErrors(errors);
39-
} else {
40-
expr = gen.generateConstant();
41-
}
42-
sb.append(DuckDBToStringVisitor.asString(expr));
43-
}
36+
updateColumns(columns);
4437
DuckDBErrors.addInsertErrors(errors);
4538
return new SQLQueryAdapter(sb.toString(), errors);
4639
}
4740

41+
@Override
42+
protected void updateValue(DuckDBColumn column) {
43+
Node<DuckDBExpression> expr;
44+
if (Randomly.getBooleanWithSmallProbability()) {
45+
expr = gen.generateExpression();
46+
DuckDBErrors.addExpressionErrors(errors);
47+
} else {
48+
expr = gen.generateConstant();
49+
}
50+
sb.append(DuckDBToStringVisitor.asString(expr));
51+
}
52+
4853
}

src/sqlancer/h2/H2UpdateGenerator.java

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,33 @@
33
import java.util.List;
44

55
import sqlancer.Randomly;
6-
import sqlancer.common.query.ExpectedErrors;
6+
import sqlancer.common.gen.AbstractUpdateGenerator;
77
import sqlancer.common.query.SQLQueryAdapter;
88
import sqlancer.h2.H2Provider.H2GlobalState;
99
import sqlancer.h2.H2Schema.H2Column;
1010
import sqlancer.h2.H2Schema.H2Table;
1111

12-
public final class H2UpdateGenerator {
12+
public final class H2UpdateGenerator extends AbstractUpdateGenerator<H2Column> {
1313

14-
private H2UpdateGenerator() {
14+
private final H2GlobalState globalState;
15+
private H2ExpressionGenerator gen;
16+
17+
private H2UpdateGenerator(H2GlobalState globalState) {
18+
this.globalState = globalState;
1519
}
1620

1721
public static SQLQueryAdapter getQuery(H2GlobalState globalState) {
18-
StringBuilder sb = new StringBuilder("UPDATE ");
19-
ExpectedErrors errors = new ExpectedErrors();
22+
return new H2UpdateGenerator(globalState).generate();
23+
}
24+
25+
private SQLQueryAdapter generate() {
2026
H2Table table = globalState.getSchema().getRandomTable(t -> !t.isView());
27+
List<H2Column> columns = table.getRandomNonEmptyColumnSubset();
28+
gen = new H2ExpressionGenerator(globalState).setColumns(table.getColumns());
29+
sb.append("UPDATE ");
2130
sb.append(table.getName());
22-
H2ExpressionGenerator gen = new H2ExpressionGenerator(globalState).setColumns(table.getColumns());
2331
sb.append(" SET ");
24-
List<H2Column> columns = table.getRandomNonEmptyColumnSubset();
25-
for (int i = 0; i < columns.size(); i++) {
26-
if (i != 0) {
27-
sb.append(", ");
28-
}
29-
sb.append(columns.get(i).getName());
30-
sb.append("=");
31-
sb.append(H2ToStringVisitor.asString(gen.generateConstant()));
32-
}
32+
updateColumns(columns);
3333
H2Errors.addInsertErrors(errors);
3434
H2Errors.addDeleteErrors(errors);
3535
if (Randomly.getBoolean()) {
@@ -40,4 +40,9 @@ public static SQLQueryAdapter getQuery(H2GlobalState globalState) {
4040
return new SQLQueryAdapter(sb.toString(), errors);
4141
}
4242

43+
@Override
44+
protected void updateValue(H2Column column) {
45+
sb.append(H2ToStringVisitor.asString(gen.generateConstant()));
46+
}
47+
4348
}

src/sqlancer/hsqldb/gen/HSQLDBUpdateGenerator.java

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,54 +4,53 @@
44

55
import sqlancer.Randomly;
66
import sqlancer.common.ast.newast.Node;
7-
import sqlancer.common.query.ExpectedErrors;
7+
import sqlancer.common.gen.AbstractUpdateGenerator;
88
import sqlancer.common.query.SQLQueryAdapter;
99
import sqlancer.hsqldb.HSQLDBErrors;
1010
import sqlancer.hsqldb.HSQLDBProvider;
1111
import sqlancer.hsqldb.HSQLDBSchema;
12+
import sqlancer.hsqldb.HSQLDBSchema.HSQLDBColumn;
13+
import sqlancer.hsqldb.HSQLDBSchema.HSQLDBCompositeDataType;
14+
import sqlancer.hsqldb.HSQLDBSchema.HSQLDBDataType;
1215
import sqlancer.hsqldb.HSQLDBToStringVisitor;
1316
import sqlancer.hsqldb.ast.HSQLDBExpression;
1417

15-
public final class HSQLDBUpdateGenerator {
18+
public final class HSQLDBUpdateGenerator extends AbstractUpdateGenerator<HSQLDBColumn> {
1619

17-
private static final ExpectedErrors EXPECTED_ERRORS = new ExpectedErrors();
1820
private final HSQLDBProvider.HSQLDBGlobalState globalState;
21+
private HSQLDBExpressionGenerator gen;
1922

2023
private HSQLDBUpdateGenerator(HSQLDBProvider.HSQLDBGlobalState globalState) {
2124
this.globalState = globalState;
2225
}
2326

2427
public static SQLQueryAdapter getQuery(HSQLDBProvider.HSQLDBGlobalState globalState) {
25-
return new HSQLDBUpdateGenerator(globalState).getQuery();
28+
return new HSQLDBUpdateGenerator(globalState).generate();
2629
}
2730

28-
private SQLQueryAdapter getQuery() {
29-
StringBuilder sb = new StringBuilder("UPDATE ");
31+
private SQLQueryAdapter generate() {
3032
HSQLDBSchema.HSQLDBTable table = globalState.getSchema().getRandomTable(t -> !t.isView());
33+
List<HSQLDBSchema.HSQLDBColumn> columns = table.getRandomNonEmptyColumnSubset();
34+
gen = new HSQLDBExpressionGenerator(globalState).setColumns(table.getColumns());
35+
sb.append("UPDATE ");
3136
sb.append(table.getName());
32-
HSQLDBExpressionGenerator gen = new HSQLDBExpressionGenerator(globalState).setColumns(table.getColumns());
3337
sb.append(" SET ");
34-
ExpectedErrors errors = new ExpectedErrors();
35-
List<HSQLDBSchema.HSQLDBColumn> columns = table.getRandomNonEmptyColumnSubset();
36-
for (int i = 0; i < columns.size(); i++) {
37-
if (i != 0) {
38-
sb.append(", ");
39-
}
40-
sb.append(columns.get(i).getName());
41-
sb.append("=");
42-
Node<HSQLDBExpression> expr;
43-
expr = gen.generateConstant(columns.get(i).getType());
44-
sb.append(HSQLDBToStringVisitor.asString(expr));
45-
if (Randomly.getBooleanWithSmallProbability()) {
46-
sb.append(" WHERE ");
47-
expr = gen.generateExpression(columns.get(i).getType());
48-
sb.append(HSQLDBToStringVisitor.asString(expr));
49-
errors.add("data type of expression is not boolean");
50-
HSQLDBErrors.addExpressionErrors(errors);
51-
}
52-
38+
updateColumns(columns);
39+
if (Randomly.getBooleanWithSmallProbability()) {
40+
sb.append(" WHERE ");
41+
sb.append(HSQLDBToStringVisitor.asString(
42+
gen.generateExpression(HSQLDBCompositeDataType.getRandomWithType(HSQLDBDataType.BOOLEAN))));
43+
errors.add("data type of expression is not boolean");
44+
HSQLDBErrors.addExpressionErrors(errors);
5345
}
54-
return new SQLQueryAdapter(sb.toString(), EXPECTED_ERRORS);
46+
return new SQLQueryAdapter(sb.toString(), errors);
47+
}
48+
49+
@Override
50+
protected void updateValue(HSQLDBColumn column) {
51+
Node<HSQLDBExpression> expr;
52+
expr = gen.generateConstant(column.getType());
53+
sb.append(HSQLDBToStringVisitor.asString(expr));
5554
}
5655

5756
}

src/sqlancer/oceanbase/gen/OceanBaseUpdateGenerator.java

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,18 @@
33
import java.util.List;
44

55
import sqlancer.Randomly;
6-
import sqlancer.common.query.ExpectedErrors;
6+
import sqlancer.common.gen.AbstractUpdateGenerator;
77
import sqlancer.common.query.SQLQueryAdapter;
88
import sqlancer.oceanbase.OceanBaseErrors;
99
import sqlancer.oceanbase.OceanBaseGlobalState;
1010
import sqlancer.oceanbase.OceanBaseSchema;
11+
import sqlancer.oceanbase.OceanBaseSchema.OceanBaseColumn;
1112
import sqlancer.oceanbase.OceanBaseVisitor;
1213

13-
public class OceanBaseUpdateGenerator {
14+
public class OceanBaseUpdateGenerator extends AbstractUpdateGenerator<OceanBaseColumn> {
1415

15-
private final StringBuilder sb = new StringBuilder();
1616
private final OceanBaseGlobalState globalState;
17+
private OceanBaseExpressionGenerator gen;
1718
private final Randomly r;
1819

1920
public OceanBaseUpdateGenerator(OceanBaseGlobalState globalState) {
@@ -26,29 +27,16 @@ public static SQLQueryAdapter update(OceanBaseGlobalState globalState) {
2627
}
2728

2829
private SQLQueryAdapter generate() {
29-
ExpectedErrors errors = new ExpectedErrors();
3030
OceanBaseSchema.OceanBaseTable table = globalState.getSchema().getRandomTable(t -> !t.isView());
31-
OceanBaseExpressionGenerator gen = new OceanBaseExpressionGenerator(globalState).setColumns(table.getColumns());
31+
List<OceanBaseSchema.OceanBaseColumn> columns = table.getRandomNonEmptyColumnSubset();
32+
gen = new OceanBaseExpressionGenerator(globalState).setColumns(table.getColumns());
3233
sb.append("UPDATE ");
3334
if (Randomly.getBoolean()) {
3435
sb.append(" /*+parallel(" + r.getInteger(0, 10) + ") enable_parallel_dml*/ ");
3536
}
3637
sb.append(table.getName());
3738
sb.append(" SET ");
38-
List<OceanBaseSchema.OceanBaseColumn> columns = table.getRandomNonEmptyColumnSubset();
39-
for (int i = 0; i < columns.size(); i++) {
40-
if (i != 0) {
41-
sb.append(", ");
42-
}
43-
sb.append(columns.get(i).getName());
44-
sb.append("=");
45-
if (Randomly.getBoolean()) {
46-
sb.append(gen.generateConstant(columns.get(i)));
47-
} else {
48-
sb.append(OceanBaseVisitor.asString(gen.generateExpression()));
49-
OceanBaseErrors.addExpressionErrors(errors);
50-
}
51-
}
39+
updateColumns(columns);
5240
if (Randomly.getBoolean()) {
5341
sb.append(" WHERE ");
5442
OceanBaseErrors.addExpressionErrors(errors);
@@ -60,4 +48,14 @@ private SQLQueryAdapter generate() {
6048

6149
return new SQLQueryAdapter(sb.toString(), errors);
6250
}
51+
52+
@Override
53+
protected void updateValue(OceanBaseColumn column) {
54+
if (Randomly.getBoolean()) {
55+
sb.append(gen.generateConstant(column));
56+
} else {
57+
sb.append(OceanBaseVisitor.asString(gen.generateExpression()));
58+
OceanBaseErrors.addExpressionErrors(errors);
59+
}
60+
}
6361
}

0 commit comments

Comments
 (0)