Skip to content

Commit 422b41a

Browse files
nish-dmrigger
authored andcommitted
First commit for HSQLDB
1 parent 032a446 commit 422b41a

15 files changed

Lines changed: 1045 additions & 0 deletions

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,12 @@
352352
<artifactId>questdb</artifactId>
353353
<version>6.5.3</version>
354354
</dependency>
355+
<dependency>
356+
<groupId>org.hsqldb</groupId>
357+
<artifactId>hsqldb</artifactId>
358+
<version>2.7.1</version>
359+
<scope>runtime</scope>
360+
</dependency>
355361
</dependencies>
356362
<reporting>
357363
<plugins>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package sqlancer.hsqldb;
2+
3+
import sqlancer.common.query.ExpectedErrors;
4+
5+
public final class HSQLDBErrors {
6+
7+
private HSQLDBErrors() {
8+
}
9+
10+
public static void addExpressionErrors(ExpectedErrors errors) {
11+
}
12+
13+
private static void addRegexErrors(ExpectedErrors errors) {
14+
}
15+
16+
private static void addFunctionErrors(ExpectedErrors errors) {
17+
}
18+
19+
public static void addInsertErrors(ExpectedErrors errors) {
20+
addRegexErrors(errors);
21+
addFunctionErrors(errors);
22+
}
23+
24+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package sqlancer.hsqldb;
2+
3+
import com.beust.jcommander.Parameter;
4+
import sqlancer.DBMSSpecificOptions;
5+
import sqlancer.OracleFactory;
6+
import sqlancer.common.oracle.TestOracle;
7+
import sqlancer.hsqldb.test.HSQLDBQueryPartitioningBase;
8+
9+
import java.sql.SQLException;
10+
import java.util.List;
11+
12+
public class HSQLDBOptions implements DBMSSpecificOptions<HSQLDBOptions.HSQLDBOracleFactory> {
13+
14+
@Parameter(names = "--oracle")
15+
public List<HSQLDBOptions.HSQLDBOracleFactory> oracle = List.of(HSQLDBOracleFactory.WHERE);
16+
17+
public enum HSQLDBOracleFactory implements OracleFactory<HSQLDBProvider.HSQLDBGlobalState> {
18+
WHERE {
19+
@Override
20+
public TestOracle create(HSQLDBProvider.HSQLDBGlobalState globalState) throws SQLException {
21+
return new HSQLDBQueryPartitioningBase(globalState);
22+
}
23+
}
24+
}
25+
26+
@Override
27+
public List<HSQLDBOracleFactory> getTestOracleFactory() {
28+
return oracle;
29+
}
30+
31+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package sqlancer.hsqldb;
2+
3+
import com.google.auto.service.AutoService;
4+
import sqlancer.*;
5+
import sqlancer.common.query.SQLQueryAdapter;
6+
import sqlancer.common.query.SQLQueryProvider;
7+
import sqlancer.hsqldb.gen.HSQLDBInsertGenerator;
8+
import sqlancer.hsqldb.gen.HSQLDBTableGenerator;
9+
import sqlancer.hsqldb.gen.HSQLDBUpdateGenerator;
10+
11+
import java.sql.Connection;
12+
import java.sql.DriverManager;
13+
import java.sql.SQLException;
14+
import java.sql.Statement;
15+
16+
@AutoService(DatabaseProvider.class)
17+
public class HSQLDBProvider extends SQLProviderAdapter<HSQLDBProvider.HSQLDBGlobalState, HSQLDBOptions> {
18+
19+
private static final String HSQLDB = "hsqldb";
20+
21+
public HSQLDBProvider() {
22+
super(HSQLDBGlobalState.class, HSQLDBOptions.class);
23+
}
24+
25+
public enum Action implements AbstractAction<HSQLDBProvider.HSQLDBGlobalState> {
26+
INSERT(HSQLDBInsertGenerator::getQuery),
27+
UPDATE(HSQLDBUpdateGenerator::getQuery);
28+
29+
private final SQLQueryProvider<HSQLDBProvider.HSQLDBGlobalState> sqlQueryProvider;
30+
31+
Action(SQLQueryProvider<HSQLDBProvider.HSQLDBGlobalState> sqlQueryProvider) {
32+
this.sqlQueryProvider = sqlQueryProvider;
33+
}
34+
35+
@Override
36+
public SQLQueryAdapter getQuery(HSQLDBProvider.HSQLDBGlobalState state) throws Exception {
37+
return sqlQueryProvider.getQuery(state);
38+
}
39+
}
40+
41+
@Override
42+
public SQLConnection createDatabase(HSQLDBGlobalState globalState) throws Exception {
43+
String databaseName = globalState.getDatabaseName();
44+
String url = "jdbc:hsqldb:file:" + databaseName;
45+
MainOptions options = globalState.getOptions();
46+
Connection connection = DriverManager.getConnection(url, options.getUserName(), options.getPassword());
47+
//When a server instance is started, or when a connection is made to an in-process database,
48+
// a new, empty database is created if no database exists at the given path.
49+
try (Statement s = connection.createStatement()) {
50+
s.execute("DROP SCHEMA PUBLIC CASCADE");
51+
s.execute("SET DATABASE SQL DOUBLE NAN FALSE");
52+
}
53+
return new SQLConnection(connection);
54+
}
55+
56+
@Override
57+
public String getDBMSName() {
58+
return HSQLDB;
59+
}
60+
61+
@Override
62+
public void generateDatabase(HSQLDBGlobalState globalState) throws Exception {
63+
for (int i = 0; i < Randomly.fromOptions(1, 2); i++) {
64+
boolean success;
65+
do {
66+
SQLQueryAdapter qt = new HSQLDBTableGenerator().getQuery(globalState, null);
67+
success = globalState.executeStatement(qt);
68+
} while (!success);
69+
}
70+
if (globalState.getSchema().getDatabaseTables().isEmpty()) {
71+
throw new IgnoreMeException();
72+
}
73+
StatementExecutor<HSQLDBProvider.HSQLDBGlobalState, HSQLDBProvider.Action> se = new StatementExecutor<>(globalState, HSQLDBProvider.Action.values(),
74+
HSQLDBProvider::mapActions, (q) -> {
75+
if (globalState.getSchema().getDatabaseTables().isEmpty()) {
76+
throw new IgnoreMeException();
77+
}
78+
});
79+
se.executeStatements();
80+
}
81+
82+
private static int mapActions(HSQLDBProvider.HSQLDBGlobalState globalState, HSQLDBProvider.Action a) {
83+
Randomly r = globalState.getRandomly();
84+
switch (a) {
85+
case INSERT:
86+
return r.getInteger(0, globalState.getOptions().getMaxNumberInserts());
87+
case UPDATE:
88+
return r.getInteger(0, 1);
89+
default:
90+
throw new AssertionError(a);
91+
}
92+
}
93+
94+
public static class HSQLDBGlobalState extends SQLGlobalState<HSQLDBOptions, HSQLDBSchema> {
95+
96+
@Override
97+
protected HSQLDBSchema readSchema() throws SQLException {
98+
return HSQLDBSchema.fromConnection(getConnection(), getDatabaseName());
99+
}
100+
101+
}
102+
}
103+
104+
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package sqlancer.hsqldb;
2+
3+
import sqlancer.Randomly;
4+
import sqlancer.SQLConnection;
5+
import sqlancer.common.DBMSCommon;
6+
import sqlancer.common.schema.AbstractRelationalTable;
7+
import sqlancer.common.schema.AbstractSchema;
8+
import sqlancer.common.schema.AbstractTableColumn;
9+
import sqlancer.common.schema.TableIndex;
10+
11+
import java.sql.ResultSet;
12+
import java.sql.SQLException;
13+
import java.sql.Statement;
14+
import java.util.ArrayList;
15+
import java.util.Collections;
16+
import java.util.List;
17+
18+
public class HSQLDBSchema extends AbstractSchema<HSQLDBProvider.HSQLDBGlobalState, HSQLDBSchema.HSQLDBTable> {
19+
20+
public HSQLDBSchema(List<HSQLDBTable> databaseTables) {
21+
super(databaseTables);
22+
}
23+
24+
public static HSQLDBSchema fromConnection(SQLConnection connection, String databaseName) throws SQLException {
25+
List<HSQLDBSchema.HSQLDBTable> databaseTables = new ArrayList<>();
26+
List<String> tableNames = getTableNames(connection);
27+
for (String tableName : tableNames) {
28+
if (DBMSCommon.matchesIndexName(tableName)) {
29+
continue; // TODO: unexpected?
30+
}
31+
List<HSQLDBSchema.HSQLDBColumn> databaseColumns = getTableColumns(connection, tableName);
32+
boolean isView = tableName.startsWith("v");
33+
HSQLDBSchema.HSQLDBTable t = new HSQLDBSchema.HSQLDBTable(tableName, databaseColumns, isView);
34+
for (HSQLDBSchema.HSQLDBColumn c : databaseColumns) {
35+
c.setTable(t);
36+
}
37+
databaseTables.add(t);
38+
39+
}
40+
return new HSQLDBSchema(databaseTables);
41+
}
42+
43+
private static List<String> getTableNames(SQLConnection con) throws SQLException {
44+
List<String> tableNames = new ArrayList<>();
45+
try (Statement s = con.createStatement()) {
46+
try (ResultSet rs = s.executeQuery("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'PUBLIC';")) {
47+
while (rs.next()) {
48+
tableNames.add(rs.getString("TABLE_NAME"));
49+
}
50+
}
51+
}
52+
return tableNames;
53+
}
54+
55+
private static List<HSQLDBColumn> getTableColumns(SQLConnection con, String tableName) throws SQLException {
56+
List<HSQLDBColumn> tableNames = new ArrayList<>();
57+
try (Statement s = con.createStatement()) {
58+
String sql = "SELECT COLUMN_NAME, DATA_TYPE, TYPE_NAME, COLUMN_SIZE FROM INFORMATION_SCHEMA.SYSTEM_COLUMNS WHERE TABLE_NAME = '%s';";
59+
try (ResultSet rs = s.executeQuery(String.format(sql, tableName))) {
60+
while (rs.next()) {
61+
HSQLDBDataType dataType = HSQLDBDataType.from(rs.getString("TYPE_NAME"));
62+
HSQLDBCompositeDataType compositeDataType = new HSQLDBCompositeDataType(dataType, rs.getInt("COLUMN_SIZE"));
63+
HSQLDBColumn column = new HSQLDBColumn(rs.getString("COLUMN_NAME"), null, compositeDataType );
64+
tableNames.add(column);
65+
}
66+
}
67+
}
68+
return tableNames;
69+
}
70+
71+
public static class HSQLDBTable extends AbstractRelationalTable<HSQLDBSchema.HSQLDBColumn, TableIndex, HSQLDBProvider.HSQLDBGlobalState> {
72+
73+
public HSQLDBTable(String tableName, List<HSQLDBSchema.HSQLDBColumn> columns, boolean isView) {
74+
super(tableName, columns, Collections.emptyList(), isView);
75+
}
76+
77+
}
78+
79+
public static class HSQLDBColumn extends AbstractTableColumn<HSQLDBSchema.HSQLDBTable, HSQLDBSchema.HSQLDBCompositeDataType>
80+
{
81+
82+
public HSQLDBColumn(String name, HSQLDBTable table, HSQLDBCompositeDataType type) {
83+
super(name, table, type);
84+
}
85+
}
86+
87+
public enum HSQLDBDataType {
88+
89+
INTEGER, DOUBLE, BOOLEAN, CHAR, VARCHAR, BINARY, TIME, DATE, TIMESTAMP, NULL;
90+
91+
public static HSQLDBSchema.HSQLDBDataType getRandomWithoutNull() {
92+
HSQLDBSchema.HSQLDBDataType dt;
93+
do {
94+
dt = Randomly.fromOptions(values());
95+
} while (dt == HSQLDBSchema.HSQLDBDataType.NULL);
96+
return dt;
97+
}
98+
99+
public static HSQLDBDataType from(String type_name) {
100+
for( HSQLDBDataType value : HSQLDBDataType.values()) {
101+
if(value.name().equals(type_name)) {
102+
return value;
103+
}
104+
}
105+
return NULL;
106+
}
107+
}
108+
109+
public static class HSQLDBCompositeDataType{
110+
private final int size;
111+
private final HSQLDBDataType type;
112+
113+
public HSQLDBCompositeDataType(HSQLDBDataType type, int size) {
114+
this.type = type;
115+
this.size = size;
116+
}
117+
118+
119+
public static HSQLDBCompositeDataType getRandomWithoutNull() {
120+
HSQLDBSchema.HSQLDBDataType type = HSQLDBSchema.HSQLDBDataType.getRandomWithoutNull();
121+
int size;
122+
switch (type) {
123+
case VARCHAR:
124+
case CHAR:
125+
case TIME:
126+
case BINARY:
127+
case TIMESTAMP:
128+
size = Randomly.fromOptions(4,6,8);
129+
break;
130+
case BOOLEAN:
131+
case INTEGER:
132+
case DOUBLE:
133+
//case UUID:
134+
//case OTHER:
135+
case DATE:
136+
size = 0;
137+
break;
138+
default:
139+
throw new AssertionError(type);
140+
}
141+
142+
return new HSQLDBSchema.HSQLDBCompositeDataType(type, size);
143+
}
144+
145+
public HSQLDBDataType getType() {
146+
return type;
147+
}
148+
149+
public int getSize() {
150+
return size;
151+
}
152+
}
153+
}

0 commit comments

Comments
 (0)