Skip to content

Commit 7b7c5b3

Browse files
committed
[TiDB] Add support for the DEFAULT() function and case expression
1 parent df14ae0 commit 7b7c5b3

7 files changed

Lines changed: 94 additions & 4 deletions

File tree

src/sqlancer/tidb/TiDBErrors.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ public static void addExpressionErrors(Set<String> errors) {
1010
errors.add("BIGINT UNSIGNED value is out of range");
1111
errors.add("Data truncation: Truncated incorrect time value");
1212
errors.add("Data truncation: Incorrect time value");
13+
errors.add("overflows double");
1314
errors.add("overflows bigint");
1415
errors.add("strconv.ParseFloat: parsing");
1516
errors.add("in 'order clause'"); // int constants in order by clause
1617

1718
// functions
1819
errors.add("BIGINT value is out of range");
20+
errors.add("doesn't have a default value"); // default
1921

2022
// known issue: https://github.com/pingcap/tidb/issues/14819
2123
errors.add("Wrong plan type for dataReaderBuilder");
@@ -53,6 +55,9 @@ public static void addInsertErrors(Set<String> errors) {
5355
errors.add("cannot be null");
5456
errors.add("doesn't have a default value");
5557
errors.add("Out of range value");
58+
errors.add("Incorrect double value");
59+
errors.add("Incorrect float value");
60+
errors.add("Incorrect int value");
5661
errors.add("Incorrect tinyint value");
5762
errors.add("Data truncation");
5863
errors.add("Bad Number");

src/sqlancer/tidb/TiDBExpressionGenerator.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package sqlancer.tidb;
22

33
import java.util.ArrayList;
4+
import java.util.Arrays;
45
import java.util.List;
56

67
import sqlancer.IgnoreMeException;
@@ -17,6 +18,7 @@
1718
import sqlancer.tidb.ast.TiDBBinaryComparisonOperation.TiDBComparisonOperator;
1819
import sqlancer.tidb.ast.TiDBBinaryLogicalOperation;
1920
import sqlancer.tidb.ast.TiDBBinaryLogicalOperation.TiDBBinaryLogicalOperator;
21+
import sqlancer.tidb.ast.TiDBCase;
2022
import sqlancer.tidb.ast.TiDBCastOperation;
2123
import sqlancer.tidb.ast.TiDBCollate;
2224
import sqlancer.tidb.ast.TiDBColumnReference;
@@ -51,7 +53,9 @@ private static enum Gen {
5153
FUNCTION,
5254
BINARY_LOGICAL,
5355
BINARY_BIT,
54-
CAST
56+
CAST,
57+
DEFAULT,
58+
CASE
5559
// BINARY_ARITHMETIC
5660
}
5761

@@ -66,6 +70,15 @@ protected TiDBExpression generateExpression(int depth) {
6670
return new TiDBAggregate(args, func);
6771
}
6872
switch (Randomly.fromOptions(Gen.values())) {
73+
case DEFAULT:
74+
if (true) {
75+
// https://github.com/tidb-challenge-program/bug-hunting-issue/issues/15
76+
throw new IgnoreMeException();
77+
}
78+
if (globalState.getSchema().getDatabaseTables().isEmpty()) {
79+
throw new IgnoreMeException();
80+
}
81+
return new TiDBFunctionCall(TiDBFunction.DEFAULT, Arrays.asList(generateColumn()));
6982
case UNARY_POSTFIX:
7083
return new TiDBUnaryPostfixOperation(generateExpression(depth + 1), TiDBUnaryPostfixOperator.getRandom());
7184
case UNARY_PREFIX:
@@ -98,6 +111,11 @@ protected TiDBExpression generateExpression(int depth) {
98111
// return new TiDBBinaryArithmeticOperation(generateExpression(depth + 1), generateExpression(depth + 1), TiDBBinaryArithmeticOperator.getRandom());
99112
case CAST:
100113
return new TiDBCastOperation(generateExpression(depth + 1), Randomly.fromOptions("BINARY", "CHAR", /*"DATE", "DATETIME", "TIME", https://github.com/tidb-challenge-program/bug-hunting-issue/issues/13 */ "DECIMAL", "SIGNED", "UNSIGNED"));
114+
case CASE:
115+
int nr = Randomly.fromOptions(1, 2);
116+
return new TiDBCase(generateExpression(depth + 1),
117+
generateExpressions(depth + 1, nr), generateExpressions(depth + 1, nr),
118+
generateExpression(depth + 1));
101119
default:
102120
throw new AssertionError();
103121
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package sqlancer.tidb.ast;
2+
3+
import java.util.List;
4+
5+
public class TiDBCase implements TiDBExpression {
6+
7+
private List<TiDBExpression> conditions;
8+
private List<TiDBExpression> expressions;
9+
private TiDBExpression elseExpr;
10+
private TiDBExpression switchCondition;
11+
12+
public TiDBCase(TiDBExpression switchCondition, List<TiDBExpression> conditions, List<TiDBExpression> expressions, TiDBExpression elseExpr) {
13+
this.switchCondition = switchCondition;
14+
this.conditions = conditions;
15+
this.expressions = expressions;
16+
this.elseExpr = elseExpr;
17+
if (conditions.size() != expressions.size()) {
18+
throw new IllegalArgumentException();
19+
}
20+
}
21+
22+
public TiDBExpression getSwitchCondition() {
23+
return switchCondition;
24+
}
25+
26+
public List<TiDBExpression> getConditions() {
27+
return conditions;
28+
}
29+
public List<TiDBExpression> getExpressions() {
30+
return expressions;
31+
}
32+
33+
public TiDBExpression getElseExpr() {
34+
return elseExpr;
35+
}
36+
37+
}

src/sqlancer/tidb/ast/TiDBFunctionCall.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public int getNrArgs() {
100100
UPPER(1),
101101

102102

103-
COALESCE(1, true);
103+
COALESCE(1, true), DEFAULT(-1);
104104

105105
private int nrArgs;
106106
private boolean isVariadic;
@@ -115,7 +115,13 @@ public int getNrArgs() {
115115
}
116116

117117
public static TiDBFunction getRandom() {
118-
return Randomly.fromOptions(values());
118+
while (true) {
119+
TiDBFunction func = Randomly.fromOptions(values());
120+
if (func.getNrArgs() != -1) {
121+
// special functions that need to be created manually (e.g., DEFAULT)
122+
return func;
123+
}
124+
}
119125
}
120126

121127
public int getNrArgs() {

src/sqlancer/tidb/gen/TiDBTableGenerator.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ private void createNewTable(TiDBExpressionGenerator gen, StringBuilder sb) {
120120
errors.add("A UNIQUE INDEX must include all columns in the table's partitioning function");
121121
errors.add("is of a not allowed type for this type of partitioning");
122122
errors.add("The PARTITION function returns the wrong type");
123+
errors.add("UnknownType: *ast.WhenClause"); // https://github.com/tidb-challenge-program/bug-hunting-issue/issues/16
123124
}
124125
}
125126

src/sqlancer/tidb/visitor/TiDBToStringVisitor.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import sqlancer.IgnoreMeException;
44
import sqlancer.Randomly;
55
import sqlancer.tidb.ast.TiDBAggregate;
6+
import sqlancer.tidb.ast.TiDBCase;
67
import sqlancer.tidb.ast.TiDBCastOperation;
78
import sqlancer.tidb.ast.TiDBColumnReference;
89
import sqlancer.tidb.ast.TiDBConstant;
@@ -44,7 +45,7 @@ public void visit(TiDBColumnReference c) {
4445
public void visit(TiDBTableReference expr) {
4546
sb.append(expr.getTable().getName());
4647
}
47-
48+
4849
@Override
4950
public void visit(TiDBSelect select) {
5051
sb.append("SELECT ");
@@ -167,4 +168,21 @@ public void visit(TiDBCastOperation cast) {
167168
sb.append(cast.getType());
168169
sb.append(")");
169170
}
171+
172+
@Override
173+
public void visit(TiDBCase op) {
174+
sb.append("(CASE ");
175+
visit(op.getSwitchCondition());
176+
for (int i = 0; i < op.getConditions().size(); i++) {
177+
sb.append(" WHEN ");
178+
visit(op.getConditions().get(i));
179+
sb.append(" THEN ");
180+
visit(op.getExpressions().get(i));
181+
}
182+
if (op.getElseExpr() != null) {
183+
sb.append(" ELSE ");
184+
visit(op.getElseExpr());
185+
}
186+
sb.append(" END )");
187+
}
170188
}

src/sqlancer/tidb/visitor/TiDBVisitor.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package sqlancer.tidb.visitor;
22

33
import sqlancer.tidb.ast.TiDBAggregate;
4+
import sqlancer.tidb.ast.TiDBCase;
45
import sqlancer.tidb.ast.TiDBCastOperation;
56
import sqlancer.tidb.ast.TiDBColumnReference;
67
import sqlancer.tidb.ast.TiDBConstant;
@@ -32,13 +33,17 @@ public default void visit(TiDBExpression expr) {
3233
visit((TiDBAggregate) expr);
3334
} else if (expr instanceof TiDBCastOperation) {
3435
visit((TiDBCastOperation) expr);
36+
} else if (expr instanceof TiDBCase) {
37+
visit((TiDBCase) expr);
3538
}
3639

3740
else {
3841
throw new AssertionError(expr.getClass());
3942
}
4043
}
4144

45+
void visit(TiDBCase caseExpr);
46+
4247
void visit(TiDBCastOperation cast);
4348

4449
void visit(TiDBAggregate aggr);

0 commit comments

Comments
 (0)