Skip to content
Closed
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
18 changes: 12 additions & 6 deletions src/sqlancer/tidb/TiDBExpressionGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,19 @@ private enum Gen {
}

private final TiDBGlobalState globalState;
private TiDBSchema.TiDBRowValue rowVal;

private List<TiDBTable> tables;

public TiDBExpressionGenerator(TiDBGlobalState globalState) {
this.globalState = globalState;
}

public TiDBExpressionGenerator setRowVal(TiDBSchema.TiDBRowValue rowVal) {
this.rowVal = rowVal;
return this;
}

@Override
public TiDBExpression generateConstant() {
TiDBDataType type = TiDBDataType.getRandom();
Expand Down Expand Up @@ -175,9 +181,9 @@ public List<TiDBExpression> getTableRefs() {
public List<TiDBExpression> generateFetchColumns(boolean shouldCreateDummy) {
if (shouldCreateDummy && Randomly.getBoolean()) {
return List.of(new TiDBColumnReference(
new TiDBColumn("*", new TiDBCompositeDataType(TiDBDataType.INT), false, false, false)));
new TiDBColumn("*", new TiDBCompositeDataType(TiDBDataType.INT), false, false, false), null));
}
return Randomly.nonEmptySubset(this.columns).stream().map(c -> new TiDBColumnReference(c))
return Randomly.nonEmptySubset(this.columns).stream().map(c -> new TiDBColumnReference(c, null))
.collect(Collectors.toList());
}

Expand All @@ -199,7 +205,7 @@ protected TiDBExpression generateExpression(int depth) {
}
TiDBColumn column = Randomly.fromList(columns);
if (column.hasDefault()) {
return new TiDBFunctionCall(TiDBFunction.DEFAULT, Arrays.asList(new TiDBColumnReference(column)));
return new TiDBFunctionCall(TiDBFunction.DEFAULT, Arrays.asList(new TiDBColumnReference(column, null)));
}
throw new IgnoreMeException();
case UNARY_POSTFIX:
Expand Down Expand Up @@ -242,7 +248,7 @@ protected TiDBExpression generateExpression(int depth) {
@Override
protected TiDBExpression generateColumn() {
TiDBColumn column = Randomly.fromList(columns);
return new TiDBColumnReference(column);
return new TiDBColumnReference(column, null);
}

@Override
Expand Down Expand Up @@ -292,8 +298,8 @@ boolean mutateJoin(TiDBSelect select) {

JoinType newJoinType = TiDBJoin.JoinType.INNER;
if (join.getJoinType() == JoinType.LEFT || join.getJoinType() == JoinType.RIGHT) { // No invarient relation
// between LEFT and RIGHT
// join
// between LEFT and RIGHT
// join
newJoinType = JoinType.getRandomExcept(JoinType.NATURAL, JoinType.LEFT, JoinType.RIGHT);
} else {
newJoinType = JoinType.getRandomExcept(JoinType.NATURAL, join.getJoinType());
Expand Down
58 changes: 57 additions & 1 deletion src/sqlancer/tidb/TiDBSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import sqlancer.Randomly;
import sqlancer.SQLConnection;
import sqlancer.common.schema.AbstractRelationalTable;
import sqlancer.common.schema.AbstractRowValue;
import sqlancer.common.schema.AbstractSchema;
import sqlancer.common.schema.AbstractTableColumn;
import sqlancer.common.schema.AbstractTables;
import sqlancer.common.schema.TableIndex;
import sqlancer.tidb.ast.TiDBConstant;
import sqlancer.tidb.TiDBProvider.TiDBGlobalState;
import sqlancer.tidb.TiDBSchema.TiDBTable;

Expand Down Expand Up @@ -185,11 +191,54 @@ public boolean hasDefault() {
}

public static class TiDBTables extends AbstractTables<TiDBTable, TiDBColumn> {

public TiDBTables(List<TiDBTable> tables) {
super(tables);
}

public TiDBRowValue getRandomRowValue(SQLConnection con) throws SQLException {
String randomRow = String.format("SELECT %s FROM %s ORDER BY RAND() LIMIT 1", columnNamesAsString(
c -> c.getTable().getName() + "." + c.getName() + " AS " + c.getTable().getName() + c.getName()),
tableNamesAsString());
Map<TiDBColumn, TiDBConstant> values = new HashMap<>();
try (Statement s = con.createStatement()) {
ResultSet randomRowValues = s.executeQuery(randomRow);
if (!randomRowValues.next()) {
throw new AssertionError("could not find random row! " + randomRow + "\n");
}
for (int i = 0; i < getColumns().size(); i++) {
TiDBColumn column = getColumns().get(i);
Object value;
int columnIndex = randomRowValues.findColumn(column.getTable().getName() + column.getName());
assert columnIndex == i + 1;
TiDBConstant constant;
if (randomRowValues.getString(columnIndex) == null) {
constant = TiDBConstant.createNullConstant();
} else {
if (column.getType().equals(TiDBDataType.INT)) {
value = randomRowValues.getLong(columnIndex);
constant = TiDBConstant.createIntConstant((long) value);
} else if (column.getType().equals(TiDBDataType.CHAR)) {
value = randomRowValues.getString(columnIndex);
constant = TiDBConstant.createStringConstant((String) value);
} else {
throw new AssertionError(column.getType());
}
}
values.put(column, constant);
}
assert !randomRowValues.next();
return new TiDBRowValue(this, values);
}

}

public String columnNamesAsString(Function<TiDBColumn, String> function) {
return getColumns().stream().map(function).collect(Collectors.joining(", "));
}

public String tableNamesAsString() {
return super.getTables().stream().map(t -> t.getName()).collect(Collectors.joining(", "));
}
}

public TiDBSchema(List<TiDBTable> databaseTables) {
Expand All @@ -200,6 +249,13 @@ public TiDBTables getRandomTableNonEmptyTables() {
return new TiDBTables(Randomly.nonEmptySubset(getDatabaseTables()));
}

public static class TiDBRowValue extends AbstractRowValue<TiDBTables, TiDBColumn, TiDBConstant> {
TiDBRowValue(TiDBTables tables, Map<TiDBColumn, TiDBConstant> values) {
super(tables, values);
}

}

public int getIndexCount() {
int count = 0;
for (TiDBTable table : getDatabaseTables()) {
Expand Down
16 changes: 15 additions & 1 deletion src/sqlancer/tidb/ast/TiDBColumnReference.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,27 @@
public class TiDBColumnReference implements TiDBExpression {

private final TiDBColumn c;
private final TiDBConstant value;

public TiDBColumnReference(TiDBColumn c) {
public TiDBColumnReference(TiDBColumn c, TiDBConstant value) {
this.c = c;
this.value = value;
}

public static TiDBColumnReference create(TiDBColumn column, TiDBConstant value) {
return new TiDBColumnReference(column, value);
}

public TiDBColumn getColumn() {
return c;
}

public TiDBConstant getValue() {
return value;
}

@Override
public TiDBConstant getExpectedValue() {
return value;
}
}
8 changes: 8 additions & 0 deletions src/sqlancer/tidb/ast/TiDBConstant.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ public class TiDBConstant implements TiDBExpression {
private TiDBConstant() {
}

public boolean isInt() {
return false;
}

public boolean isNull() {
return false;
}

public static class TiDBNullConstant extends TiDBConstant {

@Override
Expand Down
4 changes: 3 additions & 1 deletion src/sqlancer/tidb/ast/TiDBExpression.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@
import sqlancer.tidb.TiDBSchema.TiDBColumn;

public interface TiDBExpression extends Expression<TiDBColumn> {

default TiDBConstant getExpectedValue() {
throw new AssertionError("PQS not supported for this operator");
}
}
32 changes: 32 additions & 0 deletions src/sqlancer/tidb/ast/TiDBSelect.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package sqlancer.tidb.ast;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

Expand All @@ -13,6 +14,37 @@ public class TiDBSelect extends SelectBase<TiDBExpression>
implements TiDBExpression, Select<TiDBJoin, TiDBExpression, TiDBTable, TiDBColumn> {

private TiDBExpression hint;
private SelectType fromOptions = SelectType.ALL;
private List<String> modifiers = Collections.emptyList();

public enum SelectType {
DISTINCT, ALL, DISTINCTROW
}

public void setSelectType(SelectType fromOptions) {
this.setFromOptions(fromOptions);
}

public SelectType getFromOptions() {
return fromOptions;
}

public void setFromOptions(SelectType fromOptions) {
this.fromOptions = fromOptions;
}

public void setModifiers(List<String> modifiers) {
this.modifiers = modifiers;
}

public List<String> getModifiers() {
return modifiers;
}

@Override
public TiDBConstant getExpectedValue() {
return null;
}

public void setHint(TiDBExpression hint) {
this.hint = hint;
Expand Down
17 changes: 17 additions & 0 deletions src/sqlancer/tidb/ast/TiDBUnaryPostfixOperation.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
public class TiDBUnaryPostfixOperation extends UnaryOperatorNode<TiDBExpression, TiDBUnaryPostfixOperator>
implements TiDBExpression {

private final TiDBExpression expression;
private final TiDBUnaryPostfixOperator operator;

public enum TiDBUnaryPostfixOperator implements Operator {
IS_NULL("IS NULL"), //
IS_NOT_NULL("IS NOT NULL"); //
Expand All @@ -26,6 +29,20 @@ public static TiDBUnaryPostfixOperator getRandom() {
public String getTextRepresentation() {
return s;
}

@Override
public TiDBConstant getExpectedValue() {
boolean val;
TiDBConstant expectedValue = expression.getExpectedValue();
switch (operator) {
case IS_NULL:
val = expectedValue.isNull();
break;
default:
throw new AssertionError(operator);
}
return TiDBConstant.createIntConstant(val ? 1 : 0);
}
}

public TiDBUnaryPostfixOperation(TiDBExpression expr, TiDBUnaryPostfixOperator op) {
Expand Down
Loading
Loading