8000 support oceanbase by bashaojing · Pull Request #429 · sqlancer/sqlancer · GitHub
[go: up one dir, main page]

Skip to content
Merged
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ Since SQL dialects differ widely, each DBMS to be tested requires a separate imp
| DuckDB | Working | Untyped, Generic | |
| ClickHouse | Preliminary | Untyped, Generic | Implementing the different table engines was not convenient, which is why only a very preliminary implementation exists. |
| TDEngine | Removed | Untyped | We removed the TDEngine implementation since all but one of our bug reports were still unaddressed five months after we reported them. |
| OceanBase | Working | Untyped | |


# Using SQLancer
Expand Down
2 changes: 2 additions & 0 deletions src/sqlancer/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import sqlancer.mariadb.MariaDBProvider;
import sqlancer.mongodb.MongoDBProvider;
import sqlancer.mysql.MySQLProvider;
import sqlancer.oceanbase.OceanBaseProvider;
import sqlancer.postgres.PostgresProvider;
import sqlancer.sqlite3.SQLite3Provider;
import sqlancer.tidb.TiDBProvider;
Expand Down Expand Up @@ -560,6 +561,7 @@ private boolean run(MainOptions options, ExecutorService execService,
providers.add(new MongoDBProvider());
providers.add(new CosmosProvider());
providers.add(new ArangoDBProvider());
providers.add(new OceanBaseProvider());
return providers;
}

Expand Down
46 changes: 46 additions & 0 deletions src/sqlancer/oceanbase/OceanBaseErrors.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package sqlancer.oceanbase;

import sqlancer.common.query.ExpectedErrors;

public final class OceanBaseErrors {

private OceanBaseErrors() {
}

public static void addExpressionErrors(ExpectedErrors errors) {
errors.add("BIGINT value is out of range"); // e.g., CAST(-('-1e500') AS SIGNED)
errors.add("is not valid for CHARACTER SET");
errors.add("The observer or zone is not the master");
errors.add("Incorrect integer value");
errors.add("Truncated incorrect DOUBLE value");
errors.add("Invalid numeric");
errors.add("Data truncated for argument");
}

public static void addInsertErrors(ExpectedErrors errors) {
errors.add("Duplicate entry");
errors.add("cannot be null");
errors.add("doesn't have a default value");
errors.add("Out of range value");
errors.add("Incorrect double value");
errors.add("Incorrect float value");
errors.add("Incorrect int value");
errors.add("Incorrect tinyint value");
errors.add("Data truncation");
errors.add("Bad Number");
errors.add("The value specified for generated column"); // TODO: do not insert data into generated columns
errors.add("incorrect utf8 value");
errors.add("Data truncation: %s value is out of range in '%s'");
errors.add("Incorrect smallint value");
errors.add("Incorrect bigint value");
errors.add("Incorrect decimal value");
errors.add("error parsing regexp");
errors.add("The observer or zone is not the master");
errors.add("Incorrect integer value");
errors.add("Truncated incorrect DOUBLE value");
errors.add("Data truncated for argument");
errors.add("Invalid numeric");
errors.add("Miss column");

}
}
155 changes: 155 additions & 0 deletions src/sqlancer/oceanbase/OceanBaseExpectedValueVisitor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package sqlancer.oceanbase;

import sqlancer.IgnoreMeException;
import sqlancer.oceanbase.ast.OceanBaseAggregate;
import sqlancer.oceanbase.ast.OceanBaseBinaryComparisonOperation;
import sqlancer.oceanbase.ast.OceanBaseBinaryLogicalOperation;
import sqlancer.oceanbase.ast.OceanBaseCastOperation;
import sqlancer.oceanbase.ast.OceanBaseColumnName;
import sqlancer.oceanbase.ast.OceanBaseColumnReference;
import sqlancer.oceanbase.ast.OceanBaseComputableFunction;
import sqlancer.oceanbase.ast.OceanBaseConstant;
import sqlancer.oceanbase.ast.OceanBaseExists;
import sqlancer.oceanbase.ast.OceanBaseExpression;
import sqlancer.oceanbase.ast.OceanBaseInOperation;
import sqlancer.oceanbase.ast.OceanBaseOrderByTerm;
import sqlancer.oceanbase.ast.OceanBaseSelect;
import sqlancer.oceanbase.ast.OceanBaseStringExpression;
import sqlancer.oceanbase.ast.OceanBaseTableReference;
import sqlancer.oceanbase.ast.OceanBaseText;
import sqlancer.oceanbase.ast.OceanBaseUnaryPostfixOperation;
import sqlancer.oceanbase.ast.OceanBaseUnaryPrefixOperation;

public class OceanBaseExpectedValueVisitor implements OceanBaseVisitor {

private final StringBuilder sb = new StringBuilder();
private int nrTabs;

private void print(OceanBaseExpression expr) {
OceanBaseToStringVisitor v = new OceanBaseToStringVisitor();
v.visit(expr);
for (int i = 0; i < nrTabs; i++) {
sb.append("\t");
}
sb.append(v.get());
sb.append(" -- ");
sb.append(expr.getExpectedValue());
sb.append("\n");
}

@Override
public void visit(OceanBaseExpression expr) {
nrTabs++;
try {
OceanBaseVisitor.super.visit(expr);
} catch (IgnoreMeException e) {

}
nrTabs--;
}

@Override
public void visit(OceanBaseConstant constant) {
print(constant);
}

@Override
public void visit(OceanBaseColumnReference column) {
print(column);
}

@Override
public void visit(OceanBaseUnaryPostfixOperation op) {
print(op);
visit(op.getExpression());
}

@Override
public void visit(OceanBaseComputableFunction f) {
print(f);
for (OceanBaseExpression expr : f.getArguments()) {
visit(expr);
}
}

@Override
public void visit(OceanBaseBinaryLogicalOperation op) {
print(op);
visit(op.getLeft());
visit(op.getRight());
}

public String get() {
return sb.toString();
}

@Override
public void visit(OceanBaseSelect select) {
for (OceanBaseExpression j : select.getJoinList()) {
visit(j);
}
if (select.getWhereClause() != null) {
visit(select.getWhereClause());
}
}

@Override
public void visit(OceanBaseBinaryComparisonOperation op) {
print(op);
visit(op.getLeft());
visit(op.getRight());
}

@Override
public void visit(OceanBaseCastOperation op) {
print(op);
visit(op.getExpr());
}

@Override
public void visit(OceanBaseInOperation op) {
print(op);
visit(op.getExpr());
for (OceanBaseExpression right : op.getListElements()) {
visit(right);
}
}

@Override
public void visit(OceanBaseOrderByTerm op) {
}

@Override
public void visit(OceanBaseExists op) {
print(op);
visit(op.getExpr());
}

@Override
public void visit(OceanBaseStringExpression op) {
print(op);
}

@Override
public void visit(OceanBaseTableReference ref) {
}

@Override
public void visit(OceanBaseAggregate aggr) {
}

@Override
public void visit(OceanBaseColumnName aggr) {
}

@Override
public void visit(OceanBaseText func) {
}

@Override
public void visit(OceanBaseUnaryPrefixOperation op) {
print(op);
visit(op.getExpr());
}

}
20 changes: 20 additions & 0 deletions src/sqlancer/oceanbase/OceanBaseGlobalState.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

package sqlancer.oceanbase;

import java.sql.SQLException;

import sqlancer.SQLGlobalState;
import sqlancer.oceanbase.OceanBaseOptions.OceanBaseOracleFactory;

public class OceanBaseGlobalState extends SQLGlobalState<OceanBaseOptions, OceanBaseSchema> {

@Override
protected OceanBaseSchema readSchema() throws SQLException {
return OceanBaseSchema.fromConnection(getConnection(), getDatabaseName());
}

public boolean usesPQS() {
return getDbmsSpecificOptions().oracles.stream().anyMatch(o -> o == OceanBaseOracleFactory.PQS);
}

}
65 changes: 65 additions & 0 deletions src/sqlancer/oceanbase/OceanBaseOptions.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package sqlancer.oceanbase;

import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;

import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;

import sqlancer.DBMSSpecificOptions;
import sqlancer.OracleFactory;
import sqlancer.common.oracle.TestOracle;
import sqlancer.oceanbase.OceanBaseOptions.OceanBaseOracleFactory;
import sqlancer.oceanbase.oracle.OceanBaseNoRECOracle;
import sqlancer.oceanbase.oracle.OceanBasePivotedQuerySynthesisOracle;
import sqlancer.oceanbase.oracle.OceanBaseTLPWhereOracle;

@Parameters(separators = "=", commandDescription = "OceanBase (default port: " + OceanBaseOptions.DEFAULT_PORT
+ ", default host: " + OceanBaseOptions.DEFAULT_HOST)
public class OceanBaseOptions implements DBMSSpecificOptions<OceanBaseOracleFactory> {
public static final String DEFAULT_HOST = "localhost";
public static final int DEFAULT_PORT = 2881;

@Parameter(names = "--oracle")
public List<OceanBaseOracleFactory> oracles = Arrays.asList(OceanBaseOracleFactory.TLP_WHERE);

public enum OceanBaseOracleFactory implements OracleFactory<OceanBaseGlobalState> {

TLP_WHERE {
@Override
public TestOracle create(OceanBaseGlobalState globalState) throws SQLException {
return new OceanBaseTLPWhereOracle(globalState);
}
},
NoREC {
@Override
public TestOracle create(OceanBaseGlobalState globalState) throws SQLException {
return new OceanBaseNoRECOracle(globalState);
}
},
PQS {

@Override
public TestOracle create(OceanBaseGlobalState globalState) throws SQLException {
return new OceanBasePivotedQuerySynthesisOracle(globalState);
}

@Override
public boolean requiresAllTablesToContainRows() {
return true;
}
}
}

@Parameter(names = { "--query-timeout" }, description = "Query timeout")
public int queryTimeout = 1000000000;
@Parameter(names = { "--transaction-timeout" }, description = "Transaction timeout")
public int trxTimeout = 1000000000;

@Override
public List<OceanBaseOracleFactory> getTestOracleFactory() {
return oracles;
}

}
Loading
0