Skip to content

Commit ca6cb96

Browse files
committed
[OceanBase] Use common NoREC oracle
1 parent 47e7ab7 commit ca6cb96

2 files changed

Lines changed: 33 additions & 200 deletions

File tree

src/sqlancer/oceanbase/OceanBaseErrors.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.ArrayList;
44
import java.util.List;
5+
import java.util.regex.Pattern;
56

67
import sqlancer.common.query.ExpectedErrors;
78

@@ -25,6 +26,13 @@ public static List<String> getExpressionErrors() {
2526
return errors;
2627
}
2728

29+
public static List<Pattern> getExpressionErrorsRegex() {
30+
ArrayList<Pattern> errors = new ArrayList<>();
31+
errors.add(Pattern.compile("Unknown column '.+' in 'order clause'"));
32+
33+
return errors;
34+
}
35+
2836
public static void addExpressionErrors(ExpectedErrors errors) {
2937
errors.addAll(getExpressionErrors());
3038
}
Lines changed: 25 additions & 200 deletions
Original file line numberDiff line numberDiff line change
@@ -1,224 +1,49 @@
11
package sqlancer.oceanbase.oracle;
22

33
import java.sql.SQLException;
4-
import java.util.Arrays;
5-
import java.util.Collections;
6-
import java.util.List;
7-
import java.util.stream.Collectors;
84

9-
import sqlancer.Randomly;
10-
import sqlancer.common.oracle.NoRECBase;
5+
import sqlancer.Reproducer;
6+
import sqlancer.common.oracle.NoRECOracle;
117
import sqlancer.common.oracle.TestOracle;
12-
import sqlancer.common.query.SQLQueryAdapter;
13-
import sqlancer.common.query.SQLancerResultSet;
8+
import sqlancer.common.query.ExpectedErrors;
9+
import sqlancer.oceanbase.OceanBaseErrors;
1410
import sqlancer.oceanbase.OceanBaseGlobalState;
1511
import sqlancer.oceanbase.OceanBaseSchema;
16-
import sqlancer.oceanbase.OceanBaseVisitor;
17-
import sqlancer.oceanbase.ast.OceanBaseAggregate;
18-
import sqlancer.oceanbase.ast.OceanBaseBinaryLogicalOperation;
19-
import sqlancer.oceanbase.ast.OceanBaseColumnName;
20-
import sqlancer.oceanbase.ast.OceanBaseComputableFunction;
21-
import sqlancer.oceanbase.ast.OceanBaseComputableFunction.OceanBaseFunction;
22-
import sqlancer.oceanbase.ast.OceanBaseConstant;
12+
import sqlancer.oceanbase.OceanBaseSchema.OceanBaseColumn;
13+
import sqlancer.oceanbase.OceanBaseSchema.OceanBaseTable;
2314
import sqlancer.oceanbase.ast.OceanBaseExpression;
15+
import sqlancer.oceanbase.ast.OceanBaseJoin;
2416
import sqlancer.oceanbase.ast.OceanBaseSelect;
25-
import sqlancer.oceanbase.ast.OceanBaseTableReference;
26-
import sqlancer.oceanbase.ast.OceanBaseText;
27-
import sqlancer.oceanbase.ast.OceanBaseUnaryPostfixOperation;
28-
import sqlancer.oceanbase.ast.OceanBaseUnaryPrefixOperation;
2917
import sqlancer.oceanbase.gen.OceanBaseExpressionGenerator;
3018

31-
public class OceanBaseNoRECOracle extends NoRECBase<OceanBaseGlobalState> implements TestOracle<OceanBaseGlobalState> {
19+
public class OceanBaseNoRECOracle implements TestOracle<OceanBaseGlobalState> {
3220

33-
// SELECT COUNT(*) FROM t0 WHERE <cond>;
34-
// SELECT SUM(count) FROM (SELECT <cond> IS TRUE as count FROM t0);
35-
// SELECT (SELECT COUNT(*) FROM t0 WHERE c0 IS NOT 0) = (SELECT COUNT(*) FROM
36-
// (SELECT c0 is NOT 0 FROM t0));
37-
private final OceanBaseSchema s;
38-
private String firstQueryString;
39-
private static final int NOT_FOUND = -1;
40-
41-
private enum Option {
42-
TRUE, FALSE_NULL, NOT_NOT_TRUE, NOT_FALSE_NOT_NULL, IF, IFNULL, COALESCE
43-
};
21+
NoRECOracle<OceanBaseSelect, OceanBaseJoin, OceanBaseExpression, OceanBaseSchema, OceanBaseTable, OceanBaseColumn, OceanBaseGlobalState> oracle;
4422

4523
public OceanBaseNoRECOracle(OceanBaseGlobalState globalState) {
46-
super(globalState);
47-
this.s = globalState.getSchema();
48-
errors.add("is out of range");
49-
// regex
50-
errors.add("unmatched parentheses");
51-
errors.add("nothing to repeat at offset");
52-
errors.add("missing )");
53-
errors.add("missing terminating ]");
54-
errors.add("range out of order in character class");
55-
errors.add("unrecognized character after ");
56-
errors.add("Got error '(*VERB) not recognized or malformed");
57-
errors.add("must be followed by");
58-
errors.add("malformed number or name after");
59-
errors.add("digit expected after");
24+
OceanBaseExpressionGenerator gen = new OceanBaseExpressionGenerator(globalState);
25+
ExpectedErrors errors = ExpectedErrors.newErrors().with(OceanBaseErrors.getExpressionErrors())
26+
.withRegex(OceanBaseErrors.getExpressionErrorsRegex())
27+
.with("canceling statement due to statement timeout").with("unmatched parentheses")
28+
.with("nothing to repeat at offset").with("missing )").with("missing terminating ]")
29+
.with("range out of order in character class").with("unrecognized character after ")
30+
.with("Got error '(*VERB) not recognized or malformed").with("must be followed by")
31+
.with("malformed number or name after").with("digit expected after").build();
32+
this.oracle = new NoRECOracle<>(globalState, gen, errors);
6033
}
6134

6235
@Override
6336
public void check() throws SQLException {
64-
OceanBaseSchema.OceanBaseTable randomTable = s.getRandomTable();
65-
List<OceanBaseSchema.OceanBaseColumn> columns = randomTable.getColumns();
66-
OceanBaseExpressionGenerator gen = new OceanBaseExpressionGenerator(state).setColumns(columns);
67-
OceanBaseExpression randomWhereCondition = gen.generateExpression();
68-
List<OceanBaseExpression> groupBys = Collections.emptyList(); // getRandomExpressions(columns);
69-
List<OceanBaseExpression> tableList = Arrays.asList(randomTable).stream()
70-
.map(t -> new OceanBaseTableReference(t)).collect(Collectors.toList());
71-
int firstCount = getFirstQueryCount(tableList, randomWhereCondition, groupBys);
72-
int secondCount = getSecondQuery(tableList, randomWhereCondition, groupBys);
73-
if (firstCount != secondCount && firstCount != NOT_FOUND && secondCount != NOT_FOUND) {
74-
String queryFormatString = "-- %s;\n-- count: %d";
75-
String firstQueryStringWithCount = String.format(queryFormatString, optimizedQueryString, firstCount);
76-
String secondQueryStringWithCount = String.format(queryFormatString, unoptimizedQueryString, secondCount);
77-
state.getState().getLocalState()
78-
.log(String.format("%s\n%s", firstQueryStringWithCount, secondQueryStringWithCount));
79-
String assertionMessage = String.format("the counts mismatch (%d and %d)!\n%s\n%s", firstCount, secondCount,
80-
firstQueryStringWithCount, secondQueryStringWithCount);
81-
throw new AssertionError(assertionMessage);
82-
}
37+
oracle.check();
8338
}
8439

85-
private int getSecondQuery(List<OceanBaseExpression> tableList, OceanBaseExpression randomWhereCondition,
86-
List<OceanBaseExpression> groupBys) throws SQLException {
87-
OceanBaseSelect select = new OceanBaseSelect();
88-
select.setGroupByClause(groupBys);
89-
OceanBaseExpression expr = getTrueExpr(randomWhereCondition);
90-
91-
OceanBaseText asText = new OceanBaseText(expr, " as count", false);
92-
select.setFetchColumns(Arrays.asList(asText));
93-
select.setFromList(tableList);
94-
select.setSelectType(OceanBaseSelect.SelectType.ALL);
95-
int secondCount = 0;
96-
97-
unoptimizedQueryString = "SELECT SUM(count) FROM (" + OceanBaseVisitor.asString(select) + ") as asdf";
98-
SQLQueryAdapter q = new SQLQueryAdapter(unoptimizedQueryString, errors);
99-
SQLancerResultSet rs;
100-
if (options.logEachSelect()) {
101-
logger.writeCurrent(unoptimizedQueryString);
102-
}
103-
try {
104-
rs = q.executeAndGet(state);
105-
} catch (Exception e) {
106-
throw new AssertionError(optimizedQueryString, e);
107-
}
108-
if (rs == null) {
109-
return -1;
110-
}
111-
if (rs.next()) {
112-
secondCount += rs.getLong(1);
113-
}
114-
rs.close();
115-
return secondCount;
116-
}
117-
118-
private int getFirstQueryCount(List<OceanBaseExpression> tableList, OceanBaseExpression randomWhereCondition,
119-
List<OceanBaseExpression> groupBys) throws SQLException {
120-
OceanBaseSelect select = new OceanBaseSelect();
121-
select.setGroupByClause(groupBys);
122-
// SELECT COUNT(t1.c3) FROM t1 WHERE (- (t1.c2));
123-
// SELECT SUM(count) FROM (SELECT ((- (t1.c2)) IS TRUE) as count FROM t1);;
124-
OceanBaseAggregate aggr = new OceanBaseAggregate(new OceanBaseColumnName(
125-
new OceanBaseSchema.OceanBaseColumn("*", OceanBaseSchema.OceanBaseDataType.INT, false, 0, false)),
126-
OceanBaseAggregate.OceanBaseAggregateFunction.COUNT);
127-
select.setFetchColumns(Arrays.asList(aggr));
128-
select.setFromList(tableList);
129-
select.setWhereClause(randomWhereCondition);
130-
select.setSelectType(OceanBaseSelect.SelectType.ALL);
131-
int firstCount = 0;
132-
optimizedQueryString = OceanBaseVisitor.asString(select);
133-
SQLQueryAdapter q = new SQLQueryAdapter(optimizedQueryString, errors);
134-
SQLancerResultSet rs;
135-
if (options.logEachSelect()) {
136-
logger.writeCurrent(optimizedQueryString);
137-
}
138-
try {
139-
rs = q.executeAndGet(state);
140-
} catch (Exception e) {
141-
throw new AssertionError(firstQueryString, e);
142-
}
143-
if (rs == null) {
144-
return -1;
145-
}
146-
if (rs.next()) {
147-
firstCount += rs.getLong(1);
148-
}
149-
rs.close();
150-
return firstCount;
40+
@Override
41+
public Reproducer<OceanBaseGlobalState> getLastReproducer() {
42+
return oracle.getLastReproducer();
15143
}
15244

153-
private OceanBaseExpression getTrueExpr(OceanBaseExpression randomWhereCondition) {
154-
// we can treat "is true" as combinations of "is flase" and "not","is not true" and "not",etc.
155-
OceanBaseUnaryPostfixOperation isTrue = new OceanBaseUnaryPostfixOperation(randomWhereCondition,
156-
OceanBaseUnaryPostfixOperation.UnaryPostfixOperator.IS_TRUE, false);
157-
158-
OceanBaseUnaryPostfixOperation isFalse = new OceanBaseUnaryPostfixOperation(randomWhereCondition,
159-
OceanBaseUnaryPostfixOperation.UnaryPostfixOperator.IS_FALSE, false);
160-
161-
OceanBaseUnaryPostfixOperation isNotFalse = new OceanBaseUnaryPostfixOperation(randomWhereCondition,
162-
OceanBaseUnaryPostfixOperation.UnaryPostfixOperator.IS_FALSE, true);
163-
164-
OceanBaseUnaryPostfixOperation isNULL = new OceanBaseUnaryPostfixOperation(randomWhereCondition,
165-
OceanBaseUnaryPostfixOperation.UnaryPostfixOperator.IS_NULL, false);
166-
167-
OceanBaseUnaryPostfixOperation isNotNULL = new OceanBaseUnaryPostfixOperation(randomWhereCondition,
168-
OceanBaseUnaryPostfixOperation.UnaryPostfixOperator.IS_NULL, true);
169-
170-
OceanBaseExpression expr = OceanBaseConstant.createNullConstant();
171-
Option a = Randomly.fromOptions(Option.values());
172-
switch (a) {
173-
case TRUE:
174-
expr = isTrue;
175-
break;
176-
case FALSE_NULL:
177-
// not((is false) or (is null))
178-
expr = new OceanBaseUnaryPrefixOperation(
179-
new OceanBaseBinaryLogicalOperation(isFalse, isNULL,
180-
OceanBaseBinaryLogicalOperation.OceanBaseBinaryLogicalOperator.OR),
181-
OceanBaseUnaryPrefixOperation.OceanBaseUnaryPrefixOperator.NOT);
182-
break;
183-
case NOT_NOT_TRUE:
184-
// not(not(is true)))
185-
expr = new OceanBaseUnaryPrefixOperation(
186-
new OceanBaseUnaryPrefixOperation(isTrue,
187-
OceanBaseUnaryPrefixOperation.OceanBaseUnaryPrefixOperator.NOT),
188-
OceanBaseUnaryPrefixOperation.OceanBaseUnaryPrefixOperator.NOT);
189-
break;
190-
case NOT_FALSE_NOT_NULL:
191-
// (is not false) and (is not null)
192-
expr = new OceanBaseBinaryLogicalOperation(isNotFalse, isNotNULL,
193-
OceanBaseBinaryLogicalOperation.OceanBaseBinaryLogicalOperator.AND);
194-
break;
195-
case IF:
196-
// if(1, xx is true, 0)
197-
OceanBaseExpression[] args = new OceanBaseExpression[3];
198-
args[0] = OceanBaseConstant.createIntConstant(1);
199-
args[1] = isTrue;
200-
args[2] = OceanBaseConstant.createIntConstant(0);
201-
expr = new OceanBaseComputableFunction(OceanBaseFunction.IF, args);
202-
break;
203-
case IFNULL:
204-
// ifnull(null, xx is true)
205-
OceanBaseExpression[] ifArgs = new OceanBaseExpression[2];
206-
ifArgs[0] = OceanBaseConstant.createNullConstant();
207-
ifArgs[1] = isTrue;
208-
expr = new OceanBaseComputableFunction(OceanBaseFunction.IFNULL, ifArgs);
209-
break;
210-
case COALESCE:
211-
// coalesce(null, xx is true)
212-
OceanBaseExpression[] coalesceArgs = new OceanBaseExpression[2];
213-
coalesceArgs[0] = OceanBaseConstant.createNullConstant();
214-
coalesceArgs[1] = isTrue;
215-
expr = new OceanBaseComputableFunction(OceanBaseFunction.COALESCE, coalesceArgs);
216-
break;
217-
default:
218-
expr = isTrue;
219-
break;
220-
}
221-
return expr;
45+
@Override
46+
public String getLastQueryString() {
47+
return oracle.getLastQueryString();
22248
}
223-
22449
}

0 commit comments

Comments
 (0)