Skip to content

Commit

Permalink
fix & refactor: fix StoneDB implementation bugs and refactor code, Pa…
Browse files Browse the repository at this point in the history
…rt 2 (sqlancer#854)

* fix: add space when creating table

* fix: add expected errors and key length specification

* feat: generate comments randomly

* fix: add expected errors and key restriction

* feat: add support for more map actions

* fix: add space between INDEX and indexName

* fix: add space and {}

* fix: remove pre-added errors before testing

* refactor: rename delete useless as when deleting from table

* fix: add missing space

* fix: add missing (

* fix: add missing length for varbinary type

* fix: string generation strategy in comments

* fix: add provider

* fix: use global randomly

* fix: insert one row

* feat: add expected errors

* feat: no length

* feat: no length

* style: format

* fix: Tianmu engine does not support fulltext index.

* fix: fix alter table and getwithoutnull

* fix: add expected errors

* feat: support StringVisitor of StoneSelect

* fix: delete useless import

* fix: syntax error in index create

* style: run formate

* fix: syntax errors

* fix: delete AS in DELETE

* feat: add expectedErrors for all generator

* refactor: change cast operation to lambda and fix dataType toString error

* feat: add expected errors

* refactor: remove redundant identifier

* refactor: remove unused expected errors

* refactor: use parent StringBuilder

* refactor: add more expected errors

* feat: add some options according to docs

* refactor: change action perform times

* refactor: rename and change action perform times

* fix: delete unexcepted errors

* feat: add one expected error

* feat: add another option when assigning assignment list

* refactor: refactor append type, reused function

* refactor: refactor append type argus

* fix: fix null pointer exception

* refactor: delete useless code

* fix: fix cast operation bug in StoneDB

* feat: add some options according to docs

* feat: add one expected error

* feat: add another option when assigning assignment list

* fix: fix null pointer exception

* fix: fix cast operation bug in StoneDB

* fix: fix cast operation bug in StoneDB

* fix: Tianmu engine does not support fulltext index.

* feat: add expectedErrors for all generator

* refactor: remove unused expected errors

* refactor: delete useless code

* feat: add some options according to docs

* feat: add one expected error

* feat: add another option when assigning assignment list

* fix: fix null pointer exception

* fix: fix cast operation bug in StoneDB

* fix: fix cast operation bug in StoneDB

* fix: delete rename column

* feat: add expected errors

* refactor: reuse code

* refactor: refactor append type argus

* refactor: reuse code, rename, fix

* fix: syntax error

* fix: change / alter column error

* fix: change / alter column error

* fix: change / alter column error

* fix: duplicate data type when add column in alter table

* fix: duplicate data type when add column in alter table

* fix: no space error

* fix: fix as count in NoREC Oracle

* fix: fix as count in NoREC Oracle

* fix: fix as count in NoREC Oracle

* fix: fix bitwise operation

* fix: fix binary operation

* fix: fix in operation

* feat: add expected errors

* feat: add expected errors

* feat: fix errors in fetch size

* feat: add expected errors

* fix: regex match string

* feat: add expected errors

* git: merge main

* feat: disable delete order by

* feat: disable delete order by

* feat: disable delete order by
  • Loading branch information
zhenglin-charlie-li authored Jul 12, 2023
1 parent e3fbde0 commit 517e394
Show file tree
Hide file tree
Showing 10 changed files with 245 additions and 174 deletions.
81 changes: 81 additions & 0 deletions src/sqlancer/stonedb/StoneDBSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,87 @@ public static Node<StoneDBExpression> getRandomValue(StoneDBDataType dataType) {
}
return null;
}

public static String getTypeAndValue(StoneDBDataType dataType) {
StringBuilder sb = new StringBuilder();
switch (dataType) {
case TINYINT:
return "TINYINT";
case SMALLINT:
return "SMALLINT";
case MEDIUMINT:
return "MEDIUMINT";
case INT:
return "INT";
case BIGINT:
return "BIGINT";
case FLOAT:
sb.append("FLOAT");
optionallyAddPrecisionAndScale(sb);
return sb.toString();
case DOUBLE:
sb.append("DOUBLE");
optionallyAddPrecisionAndScale(sb);
return sb.toString();
case DECIMAL:
return "DECIMAL"; // The default value is P(10,0);
case YEAR:
return "YEAR";
case TIME:
return "TIME";
case DATE:
return "DATE";
case DATETIME:
return "DATETIME";
case TIMESTAMP:
return "TIMESTAMP";
case CHAR:
sb.append("CHAR").append(Randomly.fromOptions("", "(" + new Randomly().getInteger(0, 255) + ")"));
return sb.toString();
case VARCHAR:
sb.append("VARCHAR").append("(").append(new Randomly().getInteger(0, 65535)).append(")");
return sb.toString();
case TINYTEXT:
return "TINYTEXT";
case TEXT:
return "TEXT";
case MEDIUMTEXT:
return "MEDIUMTEXT";
case LONGTEXT:
return "LONGTEXT";
case BINARY:
return "BINARY";
case VARBINARY:
sb.append("VARBINARY").append("(").append(new Randomly().getInteger(0, 65535)).append(")");
return sb.toString();
case TINYBLOB:
return "TINYBLOB";
case BLOB:
return "BLOB";
case MEDIUMBLOB:
return "MEDIUMBLOB";
case LONGBLOB:
return "LONGBLOB";
default:
throw new AssertionError();
}
}

private static void optionallyAddPrecisionAndScale(StringBuilder sb) {
if (Randomly.getBoolean()) {
sb.append("(");
// The maximum number of digits (M) for DECIMAL is 65
long m = Randomly.getNotCachedInteger(1, 65);
sb.append(m);
sb.append(", ");
// The maximum number of supported decimals (D) is 30
long nCandidate = Randomly.getNotCachedInteger(1, 30);
// For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column 'c0').
long n = Math.min(nCandidate, m);
sb.append(n);
sb.append(")");
}
}
}

public static class StoneDBTable
Expand Down
12 changes: 12 additions & 0 deletions src/sqlancer/stonedb/StoneDBToStringVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

import sqlancer.common.ast.newast.NewToStringVisitor;
import sqlancer.common.ast.newast.Node;
import sqlancer.stonedb.StoneDBSchema.StoneDBDataType;
import sqlancer.stonedb.ast.StoneDBConstant;
import sqlancer.stonedb.ast.StoneDBExpression;
import sqlancer.stonedb.ast.StoneDBJoin;
import sqlancer.stonedb.ast.StoneDBSelect;
import sqlancer.stonedb.gen.StoneDBExpressionGenerator.StoneDBCastOperation;

public class StoneDBToStringVisitor extends NewToStringVisitor<StoneDBExpression> {
@Override
Expand All @@ -16,6 +18,8 @@ public void visitSpecific(Node<StoneDBExpression> expr) {
visit((StoneDBSelect) expr);
} else if (expr instanceof StoneDBJoin) {
visit((StoneDBJoin) expr);
} else if (expr instanceof StoneDBCastOperation) {
visit((StoneDBCastOperation) expr);
} else {
throw new AssertionError(expr.getClass());
}
Expand Down Expand Up @@ -81,6 +85,14 @@ private void visit(StoneDBJoin join) {
}
}

private void visit(StoneDBCastOperation cast) {
sb.append("CAST(");
visit(cast.getExpr());
sb.append(" AS ");
sb.append(cast.getType() == StoneDBDataType.INT ? "UNSIGNED" : cast.getType().toString());
sb.append(") ");
}

public static String asString(Node<StoneDBExpression> expr) {
StoneDBToStringVisitor visitor = new StoneDBToStringVisitor();
visitor.visit(expr);
Expand Down
53 changes: 39 additions & 14 deletions src/sqlancer/stonedb/gen/StoneDBExpressionGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import sqlancer.IgnoreMeException;
import sqlancer.Randomly;
import sqlancer.common.ast.BinaryOperatorNode.Operator;
import sqlancer.common.ast.newast.ColumnReferenceNode;
import sqlancer.common.ast.newast.NewBetweenOperatorNode;
import sqlancer.common.ast.newast.NewBinaryOperatorNode;
import sqlancer.common.ast.newast.NewCaseOperatorNode;
Expand All @@ -32,25 +35,35 @@ public StoneDBExpressionGenerator(StoneDBGlobalState globalState) {

private enum Expression {
UNARY_PREFIX, UNARY_POSTFIX, BINARY_COMPARISON, BINARY_LOGICAL, BINARY_ARITHMETIC, BINARY_BITWISE, BETWEEN, IN,
CASE
NOT_IN, CASE
}

public static class StoneDBCastOperation extends NewUnaryPostfixOperatorNode<StoneDBExpression> {
public static class StoneDBCastOperation implements Node<StoneDBExpression> {
Node<StoneDBExpression> expr;
StoneDBDataType type;

public StoneDBCastOperation(Node<StoneDBExpression> expr, StoneDBDataType type) {
super(expr, () -> "::" + type.toString());
this.expr = expr;
this.type = type;
}

public Node<StoneDBExpression> getExpr() {
return expr;
}

public StoneDBDataType getType() {
return type;
}
}

@Override
public Node<StoneDBExpression> negatePredicate(Node<StoneDBExpression> predicate) {
return null;
return new NewUnaryPrefixOperatorNode<>(predicate, StoneDBUnaryPrefixOperator.NOT);
}

@Override
public Node<StoneDBExpression> isNull(Node<StoneDBExpression> expr) {
return null;
return new NewUnaryPostfixOperatorNode<>(expr, StoneDBUnaryPostfixOperator.IS_NULL);
}

@Override
Expand Down Expand Up @@ -111,6 +124,12 @@ protected Node<StoneDBExpression> generateExpression(int depth) {
case BINARY_COMPARISON:
op = StoneDBBinaryComparisonOperator.getRandom();
return new NewBinaryOperatorNode<>(generateExpression(depth + 1), generateExpression(depth + 1), op);
case IN:
return new NewInOperatorNode<>(generateExpression(depth + 1),
generateExpressions(Randomly.smallNumber() + 1, depth + 1), false);
case NOT_IN:
return new NewInOperatorNode<>(generateExpression(depth + 1),
generateExpressions(Randomly.smallNumber() + 1, depth + 1), true);
case BINARY_LOGICAL:
op = StoneDBBinaryLogicalOperator.getRandom();
return new NewBinaryOperatorNode<>(generateExpression(depth + 1), generateExpression(depth + 1), op);
Expand All @@ -123,9 +142,6 @@ protected Node<StoneDBExpression> generateExpression(int depth) {
case BETWEEN:
return new NewBetweenOperatorNode<>(generateExpression(depth + 1), generateExpression(depth + 1),
generateExpression(depth + 1), Randomly.getBoolean());
case IN:
return new NewInOperatorNode<>(generateExpression(depth + 1),
generateExpressions(Randomly.smallNumber() + 1, depth + 1), Randomly.getBoolean());
case CASE:
int nr = Randomly.smallNumber() + 1;
return new NewCaseOperatorNode<>(generateExpression(depth + 1), generateExpressions(nr, depth + 1),
Expand All @@ -137,7 +153,17 @@ protected Node<StoneDBExpression> generateExpression(int depth) {

@Override
protected Node<StoneDBExpression> generateColumn() {
return null;
StoneDBColumn column = Randomly.fromList(columns);
return new ColumnReferenceNode<>(column);
}

protected List<Node<StoneDBExpression>> generateColumns() {
int size = globalState.getRandomly().getInteger(1, columns.size());
Set<Node<StoneDBExpression>> set = new HashSet<>();
while (set.size() < size) {
set.add(generateColumn());
}
return new ArrayList<>(set);
}

public enum StoneDBAggregateFunction {
Expand All @@ -160,7 +186,7 @@ public int getNrArgs() {

public enum StoneDBUnaryPrefixOperator implements Operator {

NOT("NOT"), PLUS("+"), MINUS("-");
NOT("NOT"), PLUS("+"), MINUS("-"), INVERSION("!");

private final String textRepr;

Expand Down Expand Up @@ -203,8 +229,7 @@ public static StoneDBUnaryPostfixOperator getRandom() {
*/
public enum StoneDBBinaryComparisonOperator implements Operator {
EQUAL("="), GREATER(">"), LESS("<"), GREATER_EQUAL(">="), LESS_EQUAL("<="),
NOT_EQUALS(Randomly.fromList(Arrays.asList("!=", "<>"))), NULL_SAFE_EQUAL("<=>"), IN("IN"), NOT_IN("NOT_IN"),
LIKE("LIKE"), IS_NULL("IS NULL"), IS_NOT_NULL("IS NOT NULL");
NOT_EQUALS(Randomly.fromList(Arrays.asList("!=", "<>"))), NULL_SAFE_EQUAL("<=>"), LIKE("LIKE");

private final String textRepr;

Expand All @@ -227,7 +252,7 @@ public String getTextRepresentation() {
*/
public enum StoneDBBinaryLogicalOperator implements Operator {

NOT("NOT"), AND("AND"), OR("OR"), XOR("XOR");
AND("AND"), OR("OR"), XOR("XOR");

private final String textRepr;

Expand Down Expand Up @@ -274,7 +299,7 @@ public String getTextRepresentation() {
* Bitwise operators supported by StoneDB: https://stonedb.io/docs/SQL-reference/operators/bitwise-operators
*/
public enum StoneDBBinaryBitwiseOperator implements Operator {
AND("&"), OR("|"), XOR("^"), INVERSION("!"), LEFTSHIFT("<<"), RIGHTSHIFT(">>");
AND("&"), OR("|"), XOR("^"), LEFTSHIFT("<<"), RIGHTSHIFT(">>");

private final String textRepr;

Expand Down
20 changes: 17 additions & 3 deletions src/sqlancer/stonedb/gen/StoneDBIndexCreateGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import sqlancer.common.query.ExpectedErrors;
import sqlancer.common.query.SQLQueryAdapter;
import sqlancer.stonedb.StoneDBProvider.StoneDBGlobalState;
import sqlancer.stonedb.StoneDBSchema.StoneDBColumn;
import sqlancer.stonedb.StoneDBSchema.StoneDBTable;

public class StoneDBIndexCreateGenerator {
Expand All @@ -30,10 +31,12 @@ private SQLQueryAdapter getQuery() {
sb.append(Randomly.fromOptions("UNIQUE", "FULLTEXT", "SPATIAL"));
sb.append(" INDEX ");
sb.append(globalState.getSchema().getFreeIndexName());
appendIndexType();
if (Randomly.getBoolean()) {
appendIndexType();
}
sb.append(" ON ");
sb.append(table.getName());
appendKeyPart();
appendKeyParts();
appendIndexOption();
appendAlgoOrLockOption();
addExpectedErrors();
Expand Down Expand Up @@ -67,9 +70,20 @@ private void appendIndexType() {
sb.append(Randomly.fromOptions("BTREE", "HASH"));
}

private void appendKeyParts() {
int numberOfKeyParts = Randomly.fromOptions(1, 1, 1, 1, table.getColumns().size());
for (int i = 0; i < numberOfKeyParts; i++) {
appendKeyPart();
}
}

private void appendKeyPart() {
sb.append("(");
sb.append(table.getRandomColumn().getName());
StoneDBColumn randomColumn = table.getRandomColumn();
sb.append(randomColumn.getName());
if (Randomly.getBoolean()) {
sb.append(" (").append(Randomly.smallNumber()).append(")");
}
if (Randomly.getBoolean()) {
sb.append(Randomly.fromOptions(" ASC", " DESC"));
}
Expand Down
Loading

0 comments on commit 517e394

Please sign in to comment.