提交 211fbd5d authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 d44bff9d
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.sql.*;
class Column {
private TestSynth config;
private String name;
private int type;
private int precision;
private int scale;
private boolean isNullable;
private boolean isPrimaryKey;
// TODO test isAutoincrement;
private static int[] TYPES = {
Types.INTEGER,
Types.VARCHAR,
Types.DECIMAL,
Types.DATE,
Types.TIME,
Types.TIMESTAMP,
Types.BOOLEAN,
Types.BINARY,
Types.VARBINARY,
Types.CLOB,
Types.BLOB,
Types.DOUBLE,
Types.BIGINT,
Types.TIMESTAMP,
Types.BIT,
Types.BOOLEAN,
};
Column(TestSynth config) {
this.config = config;
}
Column(ResultSetMetaData meta, int index) throws SQLException {
name = meta.getColumnLabel(index);
type = meta.getColumnType(index);
switch(type) {
case Types.DECIMAL:
precision = meta.getPrecision(index);
scale = meta.getScale(index);
break;
case Types.BLOB:
case Types.BINARY:
case Types.VARBINARY:
case Types.CLOB:
case Types.LONGVARCHAR:
case Types.DATE:
case Types.TIME:
case Types.INTEGER:
case Types.VARCHAR:
case Types.CHAR:
case Types.BIGINT:
case Types.NUMERIC:
case Types.TIMESTAMP:
case Types.NULL:
case Types.LONGVARBINARY:
case Types.DOUBLE:
case Types.REAL:
case Types.OTHER:
case Types.BIT:
case Types.BOOLEAN:
break;
default:
throw new Error("type="+type);
}
}
public static boolean isConditionType(TestSynth config, int type) {
switch(config.getMode()) {
case TestSynth.H2:
case TestSynth.H2_MEM:
return true;
case TestSynth.MYSQL:
case TestSynth.HSQLDB:
case TestSynth.POSTGRESQL:
switch(type) {
case Types.INTEGER:
case Types.VARCHAR:
case Types.DECIMAL:
case Types.DATE:
case Types.TIME:
case Types.TIMESTAMP:
case Types.DOUBLE:
case Types.BIGINT:
case Types.BOOLEAN:
case Types.BIT:
return true;
case Types.BINARY:
case Types.VARBINARY:
case Types.BLOB:
case Types.CLOB:
case Types.LONGVARCHAR:
case Types.LONGVARBINARY:
return false;
default:
throw new Error("type="+type);
}
default:
throw new Error("type="+type);
}
}
String getTypeName() {
switch(type) {
case Types.INTEGER:
return "INT";
case Types.VARCHAR:
return "VARCHAR("+precision+")";
case Types.DECIMAL:
return "NUMERIC("+precision+", "+scale+")";
case Types.DATE:
return "DATE";
case Types.TIME:
return "TIME";
case Types.TIMESTAMP:
return "TIMESTAMP";
case Types.BINARY:
case Types.VARBINARY:
if(config.is(TestSynth.POSTGRESQL)) {
return "BYTEA";
}
return "BINARY("+precision+")";
case Types.CLOB: {
if(config.is(TestSynth.HSQLDB)) {
return "LONGVARCHAR";
} else if(config.is(TestSynth.POSTGRESQL)) {
return "TEXT";
}
return "CLOB";
}
case Types.BLOB: {
if(config.is(TestSynth.HSQLDB)) {
return "LONGVARBINARY";
}
return "BLOB";
}
case Types.DOUBLE:
if(config.is(TestSynth.POSTGRESQL)) {
return "DOUBLE PRECISION";
}
return "DOUBLE";
case Types.BIGINT:
return "BIGINT";
case Types.BOOLEAN:
case Types.BIT:
return "BOOLEAN";
default:
throw new Error("type="+type);
}
}
public String getCreateSQL() {
String sql = name + " " + getTypeName();
if(!isNullable) {
sql += " NOT NULL";
}
return sql;
}
public String getName() {
return name;
}
public Value getRandomValue() {
return Value.getRandom(config, type, precision, scale, isNullable);
}
public Value getRandomValueNotNull() {
return Value.getRandom(config, type, precision, scale, false);
}
public static Column getRandomColumn(TestSynth config) {
Column column = new Column(config);
column.name = "C_" + config.randomIdentifier();
int randomType;
while(true) {
randomType = TYPES[config.random().getLog(TYPES.length)];
if(config.is(TestSynth.POSTGRESQL) && (randomType == Types.BINARY || randomType == Types.VARBINARY || randomType == Types.BLOB)) {
continue;
}
break;
}
column.type = randomType;
column.precision = config.random().getInt(20)+2;
column.scale = config.random().getInt(column.precision);
column.isNullable = config.random().getBoolean(50);
return column;
}
public boolean isPrimaryKey() {
return isPrimaryKey;
}
public void setPrimaryKey(boolean b) {
isPrimaryKey = b;
}
public void setNullable(boolean b) {
isNullable = b;
}
public int getType() {
return type;
}
}
差异被折叠。
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
class DbConnection implements DbInterface {
private TestSynth config;
private int id;
private String driver;
private String url;
private String user;
private String password;
private Connection conn;
private Connection sentinel;
private boolean useSentinel;
DbConnection(TestSynth config, String driver, String url, String user, String password, int id, boolean useSentinel) {
this.config = config;
this.driver = driver;
this.url = url;
this.user = user;
this.password = password;
this.id = id;
this.useSentinel = useSentinel;
log("url="+url);
}
public void reset() throws SQLException {
log("reset;");
DatabaseMetaData meta = conn.getMetaData();
Statement stat = conn.createStatement();
ArrayList tables = new ArrayList();
ResultSet rs = meta.getTables(null, null, null, new String[] { "TABLE"});
while (rs.next()) {
String schemaName = rs.getString("TABLE_SCHEM");
if(!"INFORMATION_SCHEMA".equals(schemaName)) {
tables.add(rs.getString("TABLE_NAME"));
}
}
while (tables.size() > 0) {
int dropped = 0;
for (int i = 0; i < tables.size(); i++) {
try {
String table = (String) tables.get(i);
stat.execute("DROP TABLE " + table);
dropped++;
tables.remove(i);
i--;
} catch (SQLException e) {
// maybe a referencial integrity
}
}
// could not drop any table and still tables to drop
if (dropped == 0 && tables.size() > 0) {
throw new Error("Cannot drop "+tables);
}
}
}
public void connect() throws Exception {
if(useSentinel && sentinel == null) {
sentinel = getConnection();
}
log("connect to "+url+";");
conn = getConnection();
}
private Connection getConnection() throws Exception {
log("(getConnection to "+url+");");
if(driver==null) {
return config.getConnection("synth");
} else {
Class.forName(driver);
return DriverManager.getConnection(url, user, password);
}
}
public void disconnect() throws SQLException {
log("disconnect "+url+";");
conn.close();
}
public void end() throws SQLException {
log("end "+url+";");
if(sentinel != null) {
sentinel.close();
sentinel = null;
}
}
public void createTable(Table table) throws SQLException {
execute(table.getCreateSQL());
}
public void dropTable(Table table) throws SQLException {
execute(table.getDropSQL());
}
public void createIndex(Index index) throws SQLException {
execute(index.getCreateSQL());
index.getTable().addIndex(index);
}
public void dropIndex(Index index) throws SQLException {
execute(index.getDropSQL());
index.getTable().removeIndex(index);
}
public Result insert(Table table, Column[] c, Value[] v) throws SQLException {
String sql = table.getInsertSQL(c, v);
execute(sql);
return new Result(sql, 1);
}
private void execute(String sql) throws SQLException {
log(sql+";");
conn.createStatement().execute(sql);
}
public Result select(String sql) throws SQLException {
log(sql+";");
Statement stat = conn.createStatement();
Result result = new Result(config, sql, stat.executeQuery(sql));
return result;
}
public Result delete(Table table, String condition) throws SQLException {
String sql = "DELETE FROM " + table.getName();
if(condition!=null) {
sql += " WHERE " + condition;
}
log(sql+";");
Statement stat = conn.createStatement();
Result result = new Result(sql, stat.executeUpdate(sql));
return result;
}
public Result update(Table table, Column[] columns, Value[] values, String condition) throws SQLException {
String sql = "UPDATE " + table.getName() + " SET ";
for(int i=0; i<columns.length; i++) {
if(i>0) {
sql += ", ";
}
sql += columns[i].getName() + "=" + values[i].getSQL();
}
if(condition!=null) {
sql += " WHERE " + condition;
}
log(sql+";");
Statement stat = conn.createStatement();
Result result = new Result(sql, stat.executeUpdate(sql));
return result;
}
public void setAutoCommit(boolean b) throws SQLException {
log("set autoCommit " + b+";");
conn.setAutoCommit(b);
}
public void commit() throws SQLException {
log("commit;");
conn.commit();
}
public void rollback() throws SQLException {
log("rollback;");
conn.rollback();
}
private void log(String s) {
config.log(id, s);
}
public String toString() {
return url;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.sql.SQLException;
public interface DbInterface {
void reset() throws SQLException;
void connect() throws Exception;
void disconnect() throws SQLException;
void end() throws SQLException;
void createTable(Table table) throws SQLException;
void dropTable(Table table) throws SQLException;
void createIndex(Index index) throws SQLException;
void dropIndex(Index index) throws SQLException;
Result insert(Table table, Column[] c, Value[] v) throws SQLException;
Result select(String sql) throws SQLException;
Result delete(Table table, String condition) throws SQLException;
Result update(Table table, Column[] columns, Value[] values, String condition) throws SQLException;
void setAutoCommit(boolean b) throws SQLException;
void commit() throws SQLException;
void rollback() throws SQLException;
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.sql.SQLException;
import java.util.ArrayList;
public class DbState implements DbInterface {
private TestSynth config;
private ArrayList tables = new ArrayList();
private ArrayList indexes = new ArrayList();
boolean connected;
boolean autoCommit;
DbState(TestSynth config) {
this.config = config;
}
public void reset() throws SQLException {
tables = new ArrayList();
indexes = new ArrayList();
}
public void connect() throws SQLException {
connected = true;
}
public void disconnect() throws SQLException {
connected = false;
}
public void createTable(Table table) throws SQLException {
tables.add(table);
}
public void dropTable(Table table) throws SQLException {
tables.remove(table);
}
public void createIndex(Index index) throws SQLException {
indexes.add(index);
}
public void dropIndex(Index index) throws SQLException {
indexes.remove(index);
}
public Result insert(Table table, Column[] c, Value[] v) throws SQLException {
return null;
}
public Result select(String sql) throws SQLException {
return null;
}
public Result delete(Table table, String condition) throws SQLException {
return null;
}
public Result update(Table table, Column[] columns, Value[] values, String condition) {
return null;
}
public void setAutoCommit(boolean b) throws SQLException {
autoCommit = b;
}
public void commit() throws SQLException {
}
public void rollback() throws SQLException {
}
public Table randomTable() {
if(tables.size() == 0) {
return null;
}
int i = config.random().getInt(tables.size());
return (Table) tables.get(i);
}
public void end() throws SQLException {
}
}
差异被折叠。
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
public class Index {
Table table;
String name;
Column[] columns;
boolean unique;
Index(Table table, String name, Column[] columns, boolean unique) {
this.table = table;
this.name = name;
this.columns = columns;
this.unique = unique;
}
public String getName() {
return name;
}
public String getCreateSQL() {
String sql = "CREATE ";
if(unique) {
sql += "UNIQUE ";
}
sql += "INDEX " + name + " ON " + table.getName() + "(";
for(int i=0; i<columns.length; i++) {
if(i>0) {
sql += ", ";
}
sql += columns[i].getName();
}
sql += ")";
return sql;
}
public String getDropSQL() {
return "DROP INDEX " + name;
}
public Table getTable() {
return table;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Random;
public class RandomGen {
private Random random = new Random();
// private TestSynth config;
public RandomGen(TestSynth config) {
// this.config = config;
random.setSeed(12);
}
public int getInt(int max) {
return max==0 ? 0 : random.nextInt(max);
}
public double nextGaussian() {
return random.nextGaussian();
}
public int getLog(int max) {
if(max==0) {
return 0;
}
while(true) {
int d = Math.abs((int)(random.nextGaussian()/2.*max));
if(d<max) {
return d;
}
}
}
public void getBytes(byte[] data) {
random.nextBytes(data);
}
public boolean getBoolean(int percent) {
return random.nextInt(100) <= percent;
}
public String randomString(int len) {
StringBuffer buff = new StringBuffer();
for(int i=0; i<len; i++) {
String from = (i%2==0)?"bdfghklmnpqrst":"aeiou";
buff.append(from.charAt(getInt(from.length())));
}
return buff.toString();
}
public int getRandomInt() {
switch(random.nextInt(10)) {
case 0:
return Integer.MAX_VALUE;
case 1:
return Integer.MIN_VALUE;
case 2:
return random.nextInt();
case 3:
case 4:
return 0;
case 5:
return (int)(random.nextGaussian()*2000)-200;
default:
return (int)(random.nextGaussian()*20)-5;
}
}
public long getRandomLong() {
switch(random.nextInt(10)) {
case 0:
return Long.MAX_VALUE;
case 1:
return Long.MIN_VALUE;
case 2:
return random.nextLong();
case 3:
case 4:
return 0;
case 5:
return (int)(random.nextGaussian()*20000)-2000;
default:
return (int)(random.nextGaussian()*200)-50;
}
}
public double getRandomDouble() {
switch(random.nextInt(10)) {
case 0:
return Double.MIN_VALUE;
case 1:
return Double.MAX_VALUE;
case 2:
return Float.MIN_VALUE;
case 3:
return Float.MAX_VALUE;
case 4:
return random.nextDouble();
case 5:
case 6:
return 0;
case 7:
return random.nextGaussian()*20000.-2000.;
default:
return random.nextGaussian()*200.-50.;
}
}
public boolean nextBoolean() {
return random.nextBoolean();
}
public int[] getIntArray() {
switch(random.nextInt(10)) {
case 0:
return null;
default:
int len = getInt(100);
int[] list = new int[len];
for(int i=0; i<len; i++) {
list[i] = getRandomInt();
}
return list;
}
}
public Object getByteArray() {
switch(random.nextInt(10)) {
case 0:
return null;
default:
int len = getInt(100);
byte[] list = new byte[len];
random.nextBytes(list);
return list;
}
}
public Time randomTime() {
if(random.nextInt(10)==0) {
return null;
}
StringBuffer buff = new StringBuffer();
buff.append(getInt(24));
buff.append(':');
buff.append(getInt(24));
buff.append(':');
buff.append(getInt(24));
return Time.valueOf(buff.toString());
}
public Timestamp randomTimestamp() {
if(random.nextInt(10)==0) {
return null;
}
StringBuffer buff = new StringBuffer();
buff.append(getInt(10) + 2000);
buff.append('-');
buff.append(getInt(12) + 1);
buff.append('-');
buff.append(getInt(29) + 1);
buff.append(' ');
buff.append(getInt(24));
buff.append(':');
buff.append(getInt(60));
buff.append(':');
buff.append(getInt(60));
// TODO test timestamp nanos
return Timestamp.valueOf(buff.toString());
}
public Date randomDate() {
if(random.nextInt(10)==0) {
return null;
}
StringBuffer buff = new StringBuffer();
buff.append(getInt(10) + 2000);
buff.append('-');
buff.append(getInt(11) + 1);
buff.append('-');
buff.append(getInt(29) + 1);
return Date.valueOf(buff.toString());
}
public String modify(String sql) {
int len = getLog(10);
for(int i=0; i<len; i++) {
int pos = getInt(sql.length());
if(getBoolean(50)) {
String badChars = "abcABCDEF\u00ef\u00f6\u00fcC1230=<>+\"\\*%&/()=?$_-.:,;{}[]"; // auml ouml uuml
char bad = badChars.charAt(getInt(badChars.length()));
sql = sql.substring(0, pos) + bad + sql.substring(pos);
} else {
if(pos >= sql.length()) {
sql = sql.substring(0, pos);
} else {
sql = sql.substring(0, pos) + sql.substring(pos+1);
}
}
}
return sql;
}
public void setSeed(int seed) {
random.setSeed(seed);
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.*;
import java.util.*;
class Result implements Comparable {
static final int SUCCESS=0, BOOLEAN=1, INT=2, EXCEPTION=3, RESULTSET=4;
private int type;
private boolean bool;
private int intValue;
private SQLException exception;
private ArrayList rows;
private ArrayList header;
String sql;
Result(String sql) {
this.sql = sql;
type = SUCCESS;
}
Result(String sql, SQLException e) {
this.sql = sql;
type = EXCEPTION;
exception = e;
}
Result(String sql, boolean b) {
this.sql = sql;
type = BOOLEAN;
this.bool = b;
}
Result(String sql, int i) {
this.sql = sql;
type = INT;
this.intValue = i;
}
Result(TestSynth config, String sql, ResultSet rs) {
this.sql = sql;
type = RESULTSET;
try {
rows = new ArrayList();
header = new ArrayList();
ResultSetMetaData meta = rs.getMetaData();
int len = meta.getColumnCount();
Column[] cols = new Column[len];
for(int i=0; i<len; i++) {
cols[i] = new Column(meta, i+1);
}
while(rs.next()) {
Row row = new Row(config, rs, len);
rows.add(row);
}
Collections.sort(rows);
} catch(SQLException e) {
// type = EXCEPTION;
// exception = e;
e.printStackTrace();
throw new Error("error reading result set");
}
}
public String toString() {
switch(type) {
case SUCCESS:
return "success";
case BOOLEAN:
return "boolean: " + this.bool;
case INT:
return "int: " + this.intValue;
case EXCEPTION: {
StringWriter w = new StringWriter();
exception.printStackTrace(new PrintWriter(w));
return "exception: "+exception.getSQLState()+": "+exception.getMessage() + "\r\n"+w.toString();
}
case RESULTSET:
String result = "ResultSet { // size=" + rows.size() + "\r\n ";
for(int i=0; i<header.size(); i++) {
Column column = (Column)header.get(i);
result += column.toString() + "; ";
}
result += "} = {\r\n";
for(int i=0; i<rows.size(); i++) {
Row row = (Row)rows.get(i);
result += " { " + row.toString() + "};\r\n";
}
return result + "}";
default:
throw new Error("internal");
}
}
public int compareTo(Object o) {
Result r = (Result)o;
switch(type) {
case EXCEPTION:
if(r.type != EXCEPTION) {
return 1;
}
return 0;
// return exception.getSQLState().compareTo(r.exception.getSQLState());
case BOOLEAN:
case INT:
case SUCCESS:
case RESULTSET:
return toString().compareTo(r.toString());
default:
throw new Error("internal");
}
}
public void log() {
switch(type) {
case SUCCESS:
System.out.println("> ok");
break;
case EXCEPTION:
System.out.println("> exception");
break;
case INT:
if(intValue==0) {
System.out.println("> ok");
} else {
System.out.println("> update count: "+intValue);
}
break;
case RESULTSET:
System.out.println("> rs "+rows.size());
break;
}
System.out.println();
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.sql.*;
class Row implements Comparable {
private Value[] data;
public Row(TestSynth config, ResultSet rs, int len) throws SQLException {
data = new Value[len];
for(int i = 0; i<len; i++) {
data[i] = Value.read(config, rs, i+1);
}
}
public String toString() {
String s = "";
for(int i = 0; i<data.length; i++) {
Object o = data[i];
s += o==null ? "NULL" : o.toString();
s += "; ";
}
return s;
}
public int compareTo(Object o) {
Row r2 = (Row)o;
int result = 0;
for(int i=0; i<data.length && result==0; i++) {
Object o1 = data[i];
Object o2 = r2.data[i];
if(o1==null) {
result = (o2==null) ? 0 : -1;
} else if(o2==null) {
result = 1;
} else {
result = o1.toString().compareTo(o2.toString());
}
}
return result;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.util.ArrayList;
class Table {
private TestSynth config;
private String name;
private boolean temporary;
private boolean globalTemporary;
private Column[] columns;
private Column[] primaryKeys;
private ArrayList indexes = new ArrayList();
Table(TestSynth config) {
this.config = config;
}
public static Table newRandomTable(TestSynth config) {
Table table = new Table(config);
table.name = "T_" + config.randomIdentifier();
// there is a difference between local temp tables for persistent and in-memory mode
// table.temporary = config.random().getBoolean(10);
// if(table.temporary) {
// if(config.getMode() == TestSynth.H2_MEM) {
// table.globalTemporary = false;
// } else {
// table.globalTemporary = config.random().getBoolean(50);
// }
// }
int len = config.random().getLog(10) + 1;
table.columns = new Column[len];
for(int i=0; i<len; i++) {
Column col = Column.getRandomColumn(config);
table.columns[i] = col;
}
if(config.random().getBoolean(90)) {
int pkLen = config.random().getLog(len);
table.primaryKeys = new Column[pkLen];
for(int i=0; i<pkLen; i++) {
Column pk = null;
do {
pk = table.columns[config.random().getInt(len)];
} while(pk.isPrimaryKey());
table.primaryKeys[i] = pk;
pk.setPrimaryKey(true);
pk.setNullable(false);
}
}
return table;
}
public Index newRandomIndex() {
String indexName = "I_" + config.randomIdentifier();
int len = config.random().getLog(getColumnCount()-1)+1;
boolean unique = config.random().getBoolean(50);
Column[] cols = getRandomColumns(len);
Index index = new Index(this, indexName, cols, unique);
return index;
}
public String getDropSQL() {
return "DROP TABLE " + name;
}
public String getCreateSQL() {
String sql = "CREATE ";
if(temporary) {
if(globalTemporary) {
sql += "GLOBAL ";
} else {
sql += "LOCAL ";
}
sql += "TEMPORARY ";
}
sql += "TABLE " + name + "(";
for(int i=0; i<columns.length; i++) {
if(i>0) {
sql += ", ";
}
Column column = columns[i];
sql += column.getCreateSQL();
if(primaryKeys!=null && primaryKeys.length==1 && primaryKeys[0]==column) {
sql += " PRIMARY KEY";
}
}
if(primaryKeys != null && primaryKeys.length>1) {
sql += ", ";
sql += "PRIMARY KEY(";
for(int i=0; i<primaryKeys.length; i++) {
if(i>0) {
sql += ", ";
}
Column column = primaryKeys[i];
sql += column.getName();
}
sql += ")";
}
sql += ")";
return sql;
}
public String getInsertSQL(Column[] c, Value[] v) {
String sql = "INSERT INTO " + name;
if(c!=null) {
sql += "(";
for(int i=0; i<c.length; i++) {
if(i>0) {
sql += ", ";
}
sql += c[i].getName();
}
sql += ")";
}
sql += " VALUES(";
for(int i=0; i<v.length; i++) {
if(i>0) {
sql += ", ";
}
sql += v[i].getSQL();
}
sql += ")";
return sql;
}
public String getName() {
return name;
}
public Column getRandomConditionColumn() {
ArrayList list = new ArrayList();
for(int i=0; i<columns.length; i++) {
if(Column.isConditionType(config, columns[i].getType())) {
list.add(columns[i]);
}
}
if(list.size() == 0) {
return null;
}
return (Column) list.get(config.random().getInt(list.size()));
}
public Column getRandomColumn() {
return columns[config.random().getInt(columns.length)];
}
public int getColumnCount() {
return columns.length;
}
public Column getRandomColumnOfType(int type) {
ArrayList list = new ArrayList();
for(int i=0; i<columns.length; i++) {
if(columns[i].getType()==type) {
list.add(columns[i]);
}
}
if(list.size() == 0) {
return null;
}
return (Column) list.get(config.random().getInt(list.size()));
}
public Column[] getRandomColumns(int len) {
int[] index = new int[columns.length];
for(int i=0; i<columns.length; i++) {
index[i] = i;
}
for(int i=0; i<columns.length; i++) {
int temp = index[i];
int r = index[config.random().getInt(columns.length)];
index[i] = index[r];
index[r] = temp;
}
Column[] c = new Column[len];
for(int i=0; i<len; i++) {
c[i] = columns[index[i]];
}
return c;
}
public Column[] getColumns() {
return columns;
}
public void addIndex(Index index) {
indexes.add(index);
}
public void removeIndex(Index index) {
indexes.remove(index);
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Random;
import org.h2.test.TestBase;
import org.h2.tools.DeleteDbFiles;
public class TestBtreeIndex extends TestBase {
public void test() throws Exception {
Random random = new Random();
while(true) {
int seed = random.nextInt();
testCase(seed);
}
}
public void testCase(int seed) throws Exception {
BASE_DIR = "dataIndex";
testOne(seed);
BASE_DIR = "data";
}
private void testOne(int seed) throws Exception {
Class.forName("org.h2.Driver");
printTime("testIndex " + seed);
Random random = new Random(seed);
int distinct, prefixLength;
if(random.nextBoolean()) {
distinct=random.nextInt(8000)+1;
prefixLength=random.nextInt(8000)+1;
} else if(random.nextBoolean()) {
distinct=random.nextInt(16000)+1;
prefixLength=random.nextInt(100)+1;
} else {
distinct=random.nextInt(10)+1;
prefixLength=random.nextInt(10)+1;
}
boolean delete = random.nextBoolean();
StringBuffer buff = new StringBuffer();
for(int j=0; j<prefixLength; j++) {
buff.append("x");
}
String prefix = buff.toString();
DeleteDbFiles.execute(BASE_DIR, null, true);
Connection conn = DriverManager.getConnection("jdbc:h2:" +BASE_DIR + "/index", "sa", "sa");
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE a(text VARCHAR PRIMARY KEY)");
PreparedStatement prepInsert = conn.prepareStatement("INSERT INTO a VALUES(?)");
PreparedStatement prepDelete = conn.prepareStatement("DELETE FROM a WHERE text=?");
PreparedStatement prepDeleteAllButOne = conn.prepareStatement("DELETE FROM a WHERE text <> ?");
int count=0;
for(int i=0; i<1000; i++) {
int y = random.nextInt(distinct);
try {
prepInsert.setString(1, prefix + y);
prepInsert.executeUpdate();
count ++;
} catch(SQLException e) {
if(e.getSQLState().equals("23001")) {
// ignore
} else {
e.printStackTrace();
break;
}
}
if(delete && random.nextInt(10) == 1) {
if(random.nextInt(4) == 1) {
try {
prepDeleteAllButOne.setString(1, prefix + y);
int deleted = prepDeleteAllButOne.executeUpdate();
if(deleted < count-1) {
System.out.println("ERROR deleted:"+deleted);
System.out.println("new TestBtreeIndex().");
}
count -= deleted;
} catch(SQLException e) {
e.printStackTrace();
break;
}
} else {
try {
prepDelete.setString(1, prefix + y);
int deleted = prepDelete.executeUpdate();
if(deleted > 1) {
System.out.println("ERROR deleted:"+deleted);
System.out.println("new TestIndex().");
}
count -= deleted;
} catch(SQLException e) {
e.printStackTrace();
break;
}
}
}
}
ResultSet rs = conn.createStatement().executeQuery("SELECT text FROM a ORDER BY text");
int testCount = 0;
while(rs.next()) {
testCount++;
}
if(testCount != count) {
System.out.println("ERROR count:"+count+" testCount:"+testCount);
System.out.println("new TestIndex().");
}
rs = conn.createStatement().executeQuery("SELECT text, count(*) FROM a GROUP BY text HAVING COUNT(*)>1");
if(rs.next()) {
System.out.println("ERROR");
System.out.println("new TestIndex().");
}
conn.close();
}
}
差异被折叠。
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Random;
import org.h2.test.TestBase;
public class TestKill extends TestBase {
Connection conn;
int accounts = 10;
Random random = new Random(1);
private String DIR = "synth";
public void test() throws Exception {
String connect = "";
connect = ";MAX_LOG_SIZE=10;THROTTLE=80";
String url = getURL(DIR+"/kill" + connect, true);
String user = getUser();
String password = getPassword();
String[] procDef = new String[]{
"java.exe", "-cp", "bin",
"org.h2.test.synth.TestKillProcess",
url, user, password,
BASE_DIR,
""+accounts
};
for(int i=0;; i++) {
printTime("TestKill " + i);
if(i % 10 == 0) {
trace("deleting db...");
deleteDb(BASE_DIR, "kill");
}
conn = getConnection(url);
createTables();
checkData();
initData();
conn.close();
Process proc = Runtime.getRuntime().exec(procDef);
// while(true) {
// int ch = proc.getErrorStream().read();
// if(ch < 0) {
// break;
// }
// System.out.print((char)ch);
// }
int runtime = random.nextInt(10000);
trace("running...");
Thread.sleep(runtime);
trace("stopping...");
proc.destroy();
proc.waitFor();
trace("stopped");
}
}
private void createTables() throws SQLException {
trace("createTables...");
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE IF NOT EXISTS ACCOUNT(ID INT PRIMARY KEY, SUM INT)");
stat.execute("CREATE TABLE IF NOT EXISTS LOG(ID IDENTITY, ACCOUNTID INT, AMOUNT INT, FOREIGN KEY(ACCOUNTID) REFERENCES ACCOUNT(ID))");
stat.execute("CREATE TABLE IF NOT EXISTS TEST_A(ID INT PRIMARY KEY, DATA VARCHAR)");
stat.execute("CREATE TABLE IF NOT EXISTS TEST_B(ID INT PRIMARY KEY, DATA VARCHAR)");
}
private void initData() throws SQLException {
trace("initData...");
conn.createStatement().execute("DROP TABLE LOG");
conn.createStatement().execute("DROP TABLE ACCOUNT");
conn.createStatement().execute("DROP TABLE TEST_A");
conn.createStatement().execute("DROP TABLE TEST_B");
createTables();
PreparedStatement prep = conn.prepareStatement("INSERT INTO ACCOUNT VALUES(?, 0)");
for(int i=0; i<accounts; i++) {
prep.setInt(1, i);
prep.execute();
}
PreparedStatement p1 = conn.prepareStatement("INSERT INTO TEST_A VALUES(?, '')");
PreparedStatement p2 = conn.prepareStatement("INSERT INTO TEST_B VALUES(?, '')");
for(int i=0; i<accounts; i++) {
p1.setInt(1, i);
p2.setInt(1, i);
p1.execute();
p2.execute();
}
}
private void checkData() throws Exception {
trace("checkData...");
ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM ACCOUNT ORDER BY ID");
PreparedStatement prep = conn.prepareStatement("SELECT SUM(AMOUNT) FROM LOG WHERE ACCOUNTID=?");
while(rs.next()) {
int account = rs.getInt(1);
int sum = rs.getInt(2);
prep.setInt(1, account);
ResultSet rs2 = prep.executeQuery();
rs2.next();
int sumLog = rs2.getInt(1);
check(sumLog, sum);
trace("account="+account+" sum="+sum);
}
PreparedStatement p1 = conn.prepareStatement("SELECT * FROM TEST_A WHERE ID=?");
PreparedStatement p2 = conn.prepareStatement("SELECT * FROM TEST_B WHERE ID=?");
for(int i=0; i<accounts; i++) {
p1.setInt(1, i);
p2.setInt(1, i);
ResultSet r1 = p1.executeQuery();
ResultSet r2 = p2.executeQuery();
boolean hasData = r1.next();
check(r2.next(), hasData);
if(hasData) {
String d1 = r1.getString("DATA");
String d2 = r2.getString("DATA");
check(d1, d2);
checkFalse(r1.next());
checkFalse(r2.next());
trace("test: data="+d1);
} else {
trace("test: empty");
}
}
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.Random;
import org.h2.tools.FileBase;
public class TestKillProcess {
public static void main(String[] args) throws Exception {
try {
Class.forName("org.h2.Driver");
String url = args[0], user = args[1], password= args[2];
String BASE_DIR = args[3];
int accounts = Integer.parseInt(args[4]);
Random random = new Random();
Connection conn1 = DriverManager.getConnection(url, user, password);
PreparedStatement prep1a = conn1.prepareStatement("INSERT INTO LOG(ACCOUNTID, AMOUNT) VALUES(?, ?)");
PreparedStatement prep1b = conn1.prepareStatement("UPDATE ACCOUNT SET SUM=SUM+? WHERE ID=?");
conn1.setAutoCommit(false);
long time = System.currentTimeMillis();
String d = null;
for(int i=0; ; i++) {
long t = System.currentTimeMillis();
if(t > time + 1000) {
ArrayList list = FileBase.getDatabaseFiles(BASE_DIR, "kill", true);
System.out.println("inserting... i:"+i+" d:" + d+" files:" + list.size());
time = t;
}
if(i>10000) {
// System.out.println("halt");
// Runtime.getRuntime().halt(0);
// conn.createStatement().execute("SHUTDOWN IMMEDIATELY");
// System.exit(0);
}
int account = random.nextInt(accounts);
int value = random.nextInt(100);
prep1a.setInt(1, account);
prep1a.setInt(2, value);
prep1a.execute();
prep1b.setInt(1, value);
prep1b.setInt(2, account);
prep1b.execute();
conn1.commit();
if(random.nextInt(100) < 2) {
d = "D" + random.nextInt(1000);
account = random.nextInt(accounts);
conn1.createStatement().execute("UPDATE TEST_A SET DATA='" + d + "' WHERE ID=" + account);
conn1.createStatement().execute("UPDATE TEST_B SET DATA='" + d + "' WHERE ID=" + account);
}
}
} catch(Throwable e) {
e.printStackTrace();
}
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import org.h2.test.TestBase;
public class TestMulti extends TestBase {
public volatile boolean stop;
public void test() throws Exception {
Class.forName("org.h2.Driver");
deleteDb(BASE_DIR, "openClose");
// int len = getSize(5, 100);
int len = 10;
TestMultiThread[] threads = new TestMultiThread[len];
for(int i=0; i<len; i++) {
threads[i] = new TestMultiNews(this);
}
threads[0].first();
for(int i=0; i<len; i++) {
threads[i].start();
}
Thread.sleep(10000);
this.stop = true;
for(int i=0; i<len; i++) {
threads[i].join();
}
threads[0].finalTest();
}
public Connection getConnection() throws SQLException {
final String url = "jdbc:h2:"+BASE_DIR+"/openClose;LOCK_MODE=3;DB_CLOSE_DELAY=-1";
Connection conn = DriverManager.getConnection(url, "sa", "");
return conn;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.sql.*;
public class TestMultiNews extends TestMultiThread {
private static final String PREFIX_URL = "http://feeds.wizbangblog.com/WizbangFullFeed?m=";
int len = 10000;
Connection conn;
TestMultiNews(TestMulti base) throws SQLException {
super(base);
conn = base.getConnection();
}
void operation() throws SQLException {
if(random.nextInt(10)==0) {
conn.close();
conn = base.getConnection();
} else if(random.nextInt(10)==0) {
if(random.nextBoolean()) {
conn.commit();
} else {
conn.rollback();
}
} else if(random.nextInt(10)==0) {
conn.setAutoCommit(random.nextBoolean());
} else {
if(random.nextBoolean()) {
PreparedStatement prep;
if(random.nextBoolean()) {
prep = conn.prepareStatement(
"SELECT * FROM NEWS WHERE FLINK = ?");
} else {
prep = conn.prepareStatement(
"SELECT * FROM NEWS WHERE FVALUE = ?");
}
prep.setString(1, PREFIX_URL + random.nextInt(len));
ResultSet rs = prep.executeQuery();
if(!rs.next()) {
throw new SQLException("expected one row, got none");
}
if(rs.next()) {
throw new SQLException("expected one row, got more");
}
} else {
PreparedStatement prep = conn.prepareStatement(
"UPDATE NEWS SET FSTATE = ? WHERE FID = ?");
prep.setInt(1, random.nextInt(100));
prep.setInt(2, random.nextInt(len));
int count = prep.executeUpdate();
if(count != 1) {
throw new SQLException("expected one row, got " + count);
}
}
}
}
void begin() throws SQLException {
}
void end() throws SQLException {
conn.close();
}
void finalTest() throws Exception {
}
void first() throws SQLException {
Connection conn = base.getConnection();
Statement stat = conn.createStatement();
stat.execute(
"CREATE TABLE TEST (ID IDENTITY, NAME VARCHAR)");
stat.execute(
"CREATE TABLE NEWS (FID NUMERIC(19) PRIMARY KEY, FCOMMENTS LONGVARCHAR, " +
"FLINK VARCHAR(255), FSTATE INTEGER, FVALUE VARCHAR(255))");
stat.execute(
"CREATE INDEX IF NOT EXISTS NEWS_GUID_VALUE_INDEX ON NEWS(FVALUE)");
stat.execute(
"CREATE INDEX IF NOT EXISTS NEWS_LINK_INDEX ON NEWS(FLINK)");
stat.execute(
"CREATE INDEX IF NOT EXISTS NEWS_STATE_INDEX ON NEWS(FSTATE)");
PreparedStatement prep = conn.prepareStatement(
"INSERT INTO NEWS (FID, FCOMMENTS, FLINK, FSTATE, FVALUE) VALUES " +
"(?, ?, ?, ?, ?) ");
PreparedStatement prep2 = conn.prepareStatement(
"INSERT INTO TEST (NAME) VALUES (?)");
for(int i=0; i<len; i++) {
int x = random.nextInt(10) * 128;
StringBuffer buff = new StringBuffer();
while(buff.length() < x) {
buff.append("Test ");
buff.append(buff.length());
buff.append(' ');
}
String comment = buff.toString();
prep.setInt(1, i); // FID
prep.setString(2, comment); // FCOMMENTS
prep.setString(3, PREFIX_URL + i); // FLINK
prep.setInt(4, 0); // FSTATE
prep.setString(5, PREFIX_URL + i); // FVALUE
prep.execute();
prep2.setString(1, comment);
prep2.execute();
}
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestMultiNewsSimple extends TestMultiThread {
Connection conn;
static int newsCount = 10000;
static int getNewsCount() {
return newsCount;
}
TestMultiNewsSimple(TestMulti base) throws SQLException {
super(base);
conn = base.getConnection();
}
void first() throws SQLException {
Connection conn = base.getConnection();
conn.createStatement().execute("create table news(fid identity, fstate int default 0, text varchar default '')");
PreparedStatement prep = conn.prepareStatement("insert into news() values()");
for(int i=0; i<newsCount; i++) {
prep.executeUpdate();
}
conn.createStatement().execute("update news set text = 'Text' || fid");
conn.close();
}
void begin() throws SQLException {
}
void end() throws SQLException {
conn.close();
}
void operation() throws SQLException {
if(random.nextInt(10)==0) {
conn.setAutoCommit(random.nextBoolean());
} else if(random.nextInt(10)==0) {
if(random.nextBoolean()) {
conn.commit();
} else {
// conn.rollback();
}
} else {
if(random.nextBoolean()) {
PreparedStatement prep = conn.prepareStatement("update news set fstate = ? where fid = ?");
prep.setInt(1, random.nextInt(getNewsCount()));
prep.setInt(2, random.nextInt(10));
prep.execute();
} else {
PreparedStatement prep = conn.prepareStatement("select * from news where fid = ?");
prep.setInt(1, random.nextInt(getNewsCount()));
ResultSet rs = prep.executeQuery();
if(!rs.next()) {
System.out.println("No row found");
// throw new Error("No row found");
}
if(rs.next()) {
System.out.println("Multiple rows found");
// throw new Error("Multiple rows found");
}
}
}
}
void finalTest() throws SQLException {
// TODO Auto-generated method stub
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Random;
public class TestMultiOrder extends TestMultiThread {
Connection conn;
PreparedStatement insertLine;
private static final String[] ITEMS = new String[]{"Apples", "Oranges", "Bananas", "Coffee"};
static int customerCount;
static int orderCount;
static int orderLineCount;
TestMultiOrder(TestMulti base) throws SQLException {
super(base);
conn = base.getConnection();
}
void begin() throws SQLException {
insertLine = conn.prepareStatement("insert into orderline(orderid, lineid, text, amount) values(?, ?, ?, ?)");
insertCustomer();
}
void end() throws SQLException {
conn.close();
}
void operation() throws SQLException {
if(random.nextInt(10)==0) {
insertCustomer();
} else {
insertOrder();
}
}
private void insertOrder() throws SQLException {
PreparedStatement prep = conn.prepareStatement("insert into orders(customer_id , total) values(?, ?)");
prep.setInt(1, random.nextInt(getCustomerCount()));
BigDecimal total = new BigDecimal("0");
prep.setBigDecimal(2, total);
prep.executeUpdate();
ResultSet rs = prep.getGeneratedKeys();
rs.next();
int orderId = rs.getInt(1);
int lines = random.nextInt(20);
for(int i=0; i<lines; i++) {
insertLine.setInt(1, orderId);
insertLine.setInt(2, i);
insertLine.setString(3, ITEMS[random.nextInt(ITEMS.length)]);
BigDecimal amount = new BigDecimal(random.nextInt(100) + "." + random.nextInt(10));
insertLine.setBigDecimal(4, amount);
total = total.add(amount);
insertLine.addBatch();
}
insertLine.executeBatch();
increaseOrderLines(lines);
prep = conn.prepareStatement("update orders set total = ? where id = ?");
prep.setBigDecimal(1, total);
prep.setInt(2, orderId);
increaseOrders();
prep.execute();
}
private void insertCustomer() throws SQLException {
PreparedStatement prep = conn.prepareStatement("insert into customer(id, name) values(?, ?)");
int customerId = getNextCustomerId();
prep.setInt(1, customerId);
prep.setString(2, getString(customerId));
prep.execute();
}
private String getString(int id) {
StringBuffer buff = new StringBuffer();
Random rnd = new Random(id);
int len = rnd.nextInt(40);
for(int i=0; i<len; i++) {
String s = "bcdfghklmnprstwz";
char c = s.charAt(rnd.nextInt(s.length()));
buff.append(i == 0 ? Character.toUpperCase(c) : c);
s = "aeiou ";
buff.append(s.charAt(rnd.nextInt(s.length())));
}
return buff.toString();
}
synchronized int getNextCustomerId() {
return customerCount++;
}
synchronized int increaseOrders() {
return orderCount++;
}
synchronized int increaseOrderLines(int count) {
return orderLineCount+=count;
}
public int getCustomerCount() {
return customerCount;
}
void first() throws SQLException {
Connection conn = base.getConnection();
conn.createStatement().execute("drop table customer if exists");
conn.createStatement().execute("drop table orders if exists");
conn.createStatement().execute("drop table orderline if exists");
conn.createStatement().execute("create table customer(id int primary key, name varchar, account decimal)");
conn.createStatement().execute("create table orders(id int identity primary key, customer_id int, total decimal)");
conn.createStatement().execute("create table orderline(orderid int, lineid int, text varchar, amount decimal, primary key(orderid, lineid))");
conn.close();
}
void finalTest() throws Exception {
conn = base.getConnection();
ResultSet rs = conn.createStatement().executeQuery("select count(*) from customer");
rs.next();
base.check(rs.getInt(1), customerCount);
// System.out.println("customers: " + rs.getInt(1));
rs = conn.createStatement().executeQuery("select count(*) from orders");
rs.next();
base.check(rs.getInt(1), orderCount);
// System.out.println("orders: " + rs.getInt(1));
rs = conn.createStatement().executeQuery("select count(*) from orderline");
rs.next();
base.check(rs.getInt(1), orderLineCount);
// System.out.println("orderlines: " + rs.getInt(1));
conn.close();
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.sql.SQLException;
import java.util.Random;
abstract class TestMultiThread extends Thread {
TestMulti base;
Random random = new Random();
TestMultiThread(TestMulti base) throws SQLException {
this.base = base;
}
abstract void first() throws SQLException;
abstract void operation() throws SQLException;
abstract void begin() throws SQLException;
abstract void end() throws SQLException;
abstract void finalTest() throws Exception;
public void run() {
try {
while(!base.stop) {
operation();
}
end();
} catch(Throwable e) {
e.printStackTrace();
System.out.println("FAIL: " + e.toString());
}
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import org.h2.bnf.Bnf;
import org.h2.bnf.RuleHead;
import org.h2.test.TestAll;
import org.h2.test.TestBase;
import org.h2.util.RandomUtils;
public class TestRandomSQL extends TestBase {
private int dbId;
private boolean showSQL = true;
private ArrayList statements;
private int seed;
private boolean exitOnError = true;
private Bnf bnf;
private void processException(String sql, SQLException e) {
if(e.getSQLState().equals("HY000")) {
System.out.println("new TestRandomSQL().init(test).testCase("+seed+"); // FAIL: " + e.toString());
e.printStackTrace();
if(exitOnError) {
new Error(sql, e).printStackTrace();
System.exit(0);
}
}
}
private String getDatabaseName() {
// return "dataSynth/randomsql" + dbId+";TRACE_LEVEL_FILE=3";
return "dataSynth/randomsql" + dbId;
}
private Connection connect() throws Exception {
while(true) {
try {
return getConnection(getDatabaseName());
} catch(SQLException e) {
dbId--;
try {
deleteDb(getDatabaseName());
} catch(Exception e2) {
// ignore
}
dbId++;
try {
deleteDb(getDatabaseName());
} catch(Exception e2) {
// ignore
}
dbId++;
try {
deleteDb(getDatabaseName());
} catch(SQLException e2) {
dbId++;
deleteDb(getDatabaseName());
}
}
}
}
public TestBase init(TestAll conf) throws Exception {
super.init(conf);
bnf = Bnf.getInstance(null);
bnf.linkStatements();
statements = bnf.getStatements();
// go backwards so we can append at the end
for(int i=statements.size() - 1; i>=0; i--) {
RuleHead r = (RuleHead) statements.get(i);
String topic = r.getTopic();
int weight = 0;
if(topic.equals("select")) {
weight = 50;
} else if(topic.equals("createtable")) {
weight = 20;
} else if(topic.equals("insert")) {
weight = 20;
} else if(topic.startsWith("update")) {
weight = 10;
} else if(topic.startsWith("delete")) {
weight = 5;
} else if(topic.startsWith("drop")) {
weight = 5;
}
if(showSQL) {
System.out.println(r.getTopic());
}
for(int j=0; j<weight; j++) {
statements.add(r);
}
}
return this;
}
private void testWithSeed(Bnf config) throws Exception {
config.getRandom().setSeed(seed);
Connection conn = null;
try {
conn = connect();
} catch(SQLException e) {
processException("connect", e);
conn = connect();
}
Statement stat = conn.createStatement();
for(int i=0; i<statements.size(); i++) {
int sid = config.getRandom().nextInt(statements.size());
RuleHead r = (RuleHead) statements.get(sid);
String rand = r.getRule().random(config, 0);
if(rand.length() > 0) {
try {
if(showSQL) {
System.out.println(i+" "+rand);
}
Thread.yield();
if(rand.indexOf("TRACE_LEVEL_SYSTEM_OUT") < 0) {
stat.execute(rand);
}
} catch(SQLException e) {
processException(rand, e);
}
}
}
try {
conn.close();
} catch(SQLException e) {
processException("conn.close", e);
}
}
public void testCase(int i) throws Exception {
seed = i;
try {
deleteDb(getDatabaseName());
} catch(SQLException e) {
processException("deleteDb", e);
}
testWithSeed(bnf);
}
public void test() throws Exception {
exitOnError = false;
showSQL = false;
for(int a=0; ; a++) {
int seed = RandomUtils.nextInt(Integer.MAX_VALUE);
System.out.println("a:" + a + " seed:" + seed);
testCase(seed);
}
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.h2.test.TestBase;
public class TestSimpleIndex extends TestBase {
Connection conn;
Statement stat;
RandomGen random;
public void test() throws Exception {
deleteDb("simpleIndex");
conn = getConnection("simpleIndex");
random = new RandomGen(null);
stat = conn.createStatement();
for(int i=0; i<10000; i++) {
testIndex(i);
}
}
private void testIndex(int seed) throws Exception {
random.setSeed(seed);
String unique = random.nextBoolean() ? "UNIQUE " : "";
int len = random.getInt(2) + 1;
StringBuffer buff = new StringBuffer();
for(int i=0; i<len; i++) {
if(i > 0) {
buff.append(", ");
}
buff.append((char)('A' + random.getInt(3)));
}
String cols = buff.toString();
execute("CREATE MEMORY TABLE TEST_M(A INT, B INT, C INT, DATA VARCHAR(255))");
execute("CREATE CACHED TABLE TEST_D(A INT, B INT, C INT, DATA VARCHAR(255))");
execute("CREATE MEMORY TABLE TEST_MI(A INT, B INT, C INT, DATA VARCHAR(255))");
execute("CREATE CACHED TABLE TEST_DI(A INT, B INT, C INT, DATA VARCHAR(255))");
execute("CREATE " + unique + "INDEX M ON TEST_MI("+cols+")");
execute("CREATE " + unique + "INDEX D ON TEST_DI("+cols+")");
for(int i=0; i<100; i++) {
println("i="+i);
testRows(i);
}
execute("DROP INDEX M");
execute("DROP INDEX D");
execute("DROP TABLE TEST_M");
execute("DROP TABLE TEST_D");
execute("DROP TABLE TEST_MI");
execute("DROP TABLE TEST_DI");
}
private void testRows(int id) throws Exception {
String a = randomValue(), b = randomValue(), c = randomValue();
String data = a + "/" + b + "/" + c;
String sql = "VALUES("+a+", "+b+", "+c+", '" + data + "')";
boolean em, ed;
// if(id==73) {
// print("halt");
// }
try {
execute("INSERT INTO TEST_MI " + sql);
em = false;
} catch(SQLException e) {
em = true;
}
try {
execute("INSERT INTO TEST_DI " + sql);
ed = false;
} catch(SQLException e) {
ed = true;
}
if(em != ed) {
error("different result: ");
}
if(!em) {
execute("INSERT INTO TEST_M " + sql);
execute("INSERT INTO TEST_D " + sql);
}
StringBuffer buff = new StringBuffer("WHERE 1=1");
int len = random.getLog(10);
for(int i=0; i<len; i++) {
buff.append(" AND ");
buff.append('A' + random.getInt(3));
switch(random.getInt(10)) {
case 0:
buff.append("<");
buff.append((random.getInt(100) - 50));
break;
case 1:
buff.append("<=");
buff.append((random.getInt(100) - 50));
break;
case 2:
buff.append(">");
buff.append((random.getInt(100) - 50));
break;
case 3:
buff.append(">=");
buff.append((random.getInt(100) - 50));
break;
case 4:
buff.append("<>");
buff.append((random.getInt(100) - 50));
break;
case 5:
buff.append(" IS NULL");
break;
case 6:
buff.append(" IS NOT NULL");
break;
default:
buff.append("=");
buff.append((random.getInt(100) - 50));
}
}
String where = buff.toString();
String r1 = getResult("SELECT DATA FROM TEST_M " + where + " ORDER BY DATA");
String r2 = getResult("SELECT DATA FROM TEST_D " + where + " ORDER BY DATA");
String r3 = getResult("SELECT DATA FROM TEST_MI " + where + " ORDER BY DATA");
String r4 = getResult("SELECT DATA FROM TEST_DI " + where + " ORDER BY DATA");
check(r1, r2);
check(r1, r3);
check(r1, r4);
}
private String getResult(String sql) throws Exception {
ResultSet rs = stat.executeQuery(sql);
StringBuffer buff = new StringBuffer();
while(rs.next()) {
buff.append(rs.getString(1));
buff.append("; ");
}
rs.close();
return buff.toString();
}
private String randomValue() {
return random.getInt(10) == 0 ? "NULL" : ""+(random.getInt(100) - 50);
}
private void execute(String sql) throws Exception {
try {
println(sql + ";");
stat.execute(sql);
println("> update count: 1");
} catch(SQLException e) {
println("> exception");
throw e;
}
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.util.ArrayList;
import org.h2.test.TestAll;
import org.h2.test.TestBase;
import org.h2.util.RandomUtils;
// TODO hsqldb: call 1||null should return 1 but returns null
// TODO hsqldb: call mod(1) should return invalid parameter count but returns null
public class TestSynth extends TestBase {
static final int H2 = 0, H2_MEM = 1, HSQLDB = 2, MYSQL = 3, POSTGRESQL = 4;
private DbState db = new DbState(this);
private ArrayList databases;
private ArrayList commands;
private RandomGen random = new RandomGen(this);
private boolean showError, showLog;
private boolean stopImmediately;
private int mode;
private String DIR = "synth";
public boolean is(int isType) {
return mode == isType;
}
public TestSynth() {
}
public RandomGen random() {
return random;
}
public String randomIdentifier() {
int len = random.getLog(8)+2;
while(true) {
return random.randomString(len);
}
}
private void add(Command command) throws Exception {
command.run(db);
commands.add(command);
}
private void addRandomCommands() throws Exception {
switch(random.getInt(20)) {
case 0: {
add(Command.getDisconnect(this));
add(Command.getConnect(this));
break;
}
case 1: {
Table table = Table.newRandomTable(this);
add(Command.getCreateTable(this, table));
break;
}
case 2: {
Table table = randomTable();
add(Command.getCreateIndex(this, table.newRandomIndex()));
break;
}
case 3:
case 4:
case 5: {
Table table = randomTable();
add(Command.getRandomInsert(this, table));
break;
}
case 6:
case 7:
case 8: {
Table table = randomTable();
add(Command.getRandomUpdate(this, table));
break;
}
case 9:
case 10: {
Table table = randomTable();
add(Command.getRandomDelete(this, table));
break;
}
default: {
Table table = randomTable();
add(Command.getRandomSelect(this, table));
}
}
}
private void testRun(int seed) throws Exception {
random.setSeed(seed);
commands = new ArrayList();
add(Command.getConnect(this));
add(Command.getReset(this));
for(int i=0; i<1; i++) {
Table table = Table.newRandomTable(this);
add(Command.getCreateTable(this, table));
add(Command.getCreateIndex(this, table.newRandomIndex()));
}
for(int i=0; i<100; i++) {
addRandomCommands();
}
// for (int i = 0; i < 20; i++) {
// Table table = randomTable();
// add(Command.getRandomInsert(this, table));
// }
// for (int i = 0; i < 100; i++) {
// Table table = randomTable();
// add(Command.getRandomSelect(this, table));
// }
// for (int i = 0; i < 10; i++) {
// Table table = randomTable();
// add(Command.getRandomUpdate(this, table));
// }
// for (int i = 0; i < 30; i++) {
// Table table = randomTable();
// add(Command.getRandomSelect(this, table));
// }
// for (int i = 0; i < 50; i++) {
// Table table = randomTable();
// add(Command.getRandomDelete(this, table));
// }
// for (int i = 0; i < 10; i++) {
// Table table = randomTable();
// add(Command.getRandomSelect(this, table));
// }
// while(true) {
// Table table = randomTable();
// if(table == null) {
// break;
// }
// add(Command.getDropTable(this, table));
// }
add(Command.getDisconnect(this));
add(Command.getEnd(this));
for(int i=0; i<commands.size(); i++) {
Command command = (Command) commands.get(i);
boolean stop = process(seed, i, command);
if(stop) {
break;
}
}
}
private boolean process(int seed, int id, Command command) throws Exception {
try {
ArrayList results = new ArrayList();
for(int i=0; i<databases.size(); i++) {
DbInterface db = (DbInterface)databases.get(i);
Result result = command.run(db);
results.add(result);
if(showError && i==0) {
// result.log();
}
}
compareResults(results);
} catch(Error e) {
if(showError) {
e.printStackTrace();
}
System.out.println("new TestSynth().init(test).testCase(" + seed+"); // id="+id +" " + e.toString());
if(stopImmediately) {
System.exit(0);
}
return true;
}
return false;
}
private void compareResults(ArrayList results) {
Result original = (Result) results.get(0);
for (int i = 1; i < results.size(); i++) {
Result copy = (Result) results.get(i);
if (original.compareTo(copy) != 0) {
if (showError) {
throw new Error("Results don't match: original (0): \r\n" + original + "\r\nother:\r\n" + copy);
} else {
throw new Error("Results don't match");
}
}
}
}
public Table randomTable() {
return db.randomTable();
}
public void log(int id, String s) {
if(showLog && id==0) {
System.out.println(s);
}
}
public int getMode() {
return mode;
}
private void addDatabase(String className, String url, String user, String password, boolean useSentinel) {
DbConnection db = new DbConnection(this, className, url, user, password, databases.size(), useSentinel);
databases.add(db);
}
// java -cp .;..\..\java\mysql.jar;..\..\java\ldbc.jar;..\..\java\postgresql-8.0-311.jdbc3.jar org.h2.test.TestAll
public TestBase init(TestAll conf) throws Exception {
super.init(conf);
BASE_DIR = "dataSynth";
deleteDb("synth");
databases = new ArrayList();
// mode = HSQLDB;
// addDatabase("org.hsqldb.jdbcDriver", "jdbc:hsqldb:test", "sa", "" );
// addDatabase("org.h2.Driver", "jdbc:h2:synth;mode=hsqldb", "sa", "");
// mode = POSTGRESQL;
// addDatabase("org.postgresql.Driver", "jdbc:postgresql:test", "sa", "sa");
// addDatabase("org.h2.Driver", "jdbc:h2:synth;mode=postgresql", "sa", "");
mode = H2_MEM;
Class.forName("org.h2.Driver");
addDatabase("org.h2.Driver", "jdbc:h2:mem:synth", "sa", "", true);
addDatabase("org.h2.Driver", "jdbc:h2:"+BASE_DIR+"/"+DIR+"/synth", "sa", "", false);
// addDatabase("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/test", "sa", "");
// addDatabase("org.h2.Driver", "jdbc:h2:synth;mode=mysql", "sa", "");
// addDatabase("com.mysql.jdbc.Driver", "jdbc:mysql://localhost/test", "sa", "");
// addDatabase("org.ldbc.jdbc.jdbcDriver", "jdbc:ldbc:mysql://localhost/test", "sa", "");
// addDatabase("org.h2.Driver", "jdbc:h2:inmemory:synth", "sa", "");
// MySQL: NOT is bound to column: NOT ID = 1 means (NOT ID) = 1 instead of NOT (ID=1)
for (int i = 0; i < databases.size(); i++) {
DbConnection conn = (DbConnection) databases.get(i);
System.out.println(i + " = " + conn.toString());
}
showError = true;
showLog = false;
// stopImmediately = true;
// showLog = true;
// testRun(110600); // id=27 java.lang.Error: Results don't match: original (0):
// System.exit(0);
BASE_DIR = "data";
return this;
}
public void testCase(int i) throws Exception {
BASE_DIR = "dataCrash";
deleteDb(BASE_DIR, DIR+"/synth");
try {
printTime("TestSynth " + i);
testRun(i);
} catch (Error e) {
System.out.println(e.toString());
e.printStackTrace();
System.exit(0);
}
BASE_DIR = "data";
}
public void test() throws Exception {
while(true) {
int seed = RandomUtils.nextInt(Integer.MAX_VALUE);
testCase(seed);
}
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Random;
import org.h2.test.TestBase;
public class TestThreads extends TestBase implements Runnable {
public TestThreads() {
}
public void test() throws Exception {
deleteDb("threads");
Connection conn = getConnection("threads;MAX_LOG_SIZE=1");
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE TEST_A(ID INT PRIMARY KEY, NAME VARCHAR)");
stat.execute("CREATE TABLE TEST_B(ID INT PRIMARY KEY, NAME VARCHAR)");
stat.execute("CREATE TABLE TEST_C(ID INT PRIMARY KEY, NAME VARCHAR)");
int len = 1000;
insertRows(conn, "TEST_A", len);
insertRows(conn, "TEST_B", len);
insertRows(conn, "TEST_C", len);
maxId = len;
int threadCount = 4;
Thread[] threads = new Thread[threadCount];
for(int i=0; i<threadCount; i++) {
String table = random.nextBoolean() ? null : getRandomTable();
int op = random.nextInt(OP_TYPES);
op = i % 2 == 1 ? RECONNECT : CHECKPOINT;
threads[i] = new Thread(new TestThreads(this, op, table));
}
for(int i=0; i<threadCount; i++) {
threads[i].start();
}
Thread.sleep(10000);
stop = true;
for(int i=0; i<threadCount; i++) {
threads[i].join();
}
conn.close();
conn = getConnection("threads");
checkTable(conn, "TEST_A");
checkTable(conn, "TEST_B");
checkTable(conn, "TEST_C");
conn.close();
}
private void insertRows(Connection conn, String tableName, int len) throws Exception {
PreparedStatement prep = conn.prepareStatement("INSERT INTO " +tableName+" VALUES(?, 'Hi')");
for(int i=0; i<len; i++) {
prep.setInt(1, i);
prep.execute();
}
}
private void checkTable(Connection conn, String tableName) throws Exception {
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery("SELECT * FROM "+tableName+" ORDER BY ID");
while(rs.next()) {
int id = rs.getInt(1);
String name = rs.getString(2);
System.out.println("id="+id+" name="+name);
}
}
private int maxId = 1;
private volatile boolean stop;
private TestThreads master;
private int type;
private String table;
private Random random = new Random();
private static final int INSERT=0, UPDATE=1, DELETE=2;
private static final int SELECT_ONE=3, SELECT_ALL=4, CHECKPOINT=5, RECONNECT=6;
private static final int OP_TYPES = RECONNECT+1;
private int getMaxId() {
return maxId;
}
private synchronized int incrementMaxId() {
return maxId++;
}
TestThreads(TestThreads master, int type, String table) {
this.master = master;
this.type = type;
this.table = table;
}
private String getRandomTable() {
return "TEST_" + (char)('A' + random.nextInt(3));
}
public void run() {
try {
String t = table == null ? getRandomTable() : table;
Connection conn = master.getConnection("threads");
Statement stat = conn.createStatement();
ResultSet rs;
int max = master.getMaxId();
int rid = random.nextInt(max);
for(int i=0; !master.stop; i++) {
switch(type) {
case INSERT:
max = master.incrementMaxId();
stat.execute("INSERT INTO "+t+"(ID, NAME) VALUES("+max+", 'Hello')");
break;
case UPDATE:
stat.execute("UPDATE "+t+" SET NAME='World "+rid+"' WHERE ID="+rid);
break;
case DELETE:
stat.execute("DELETE FROM "+t+" WHERE ID="+rid);
break;
case SELECT_ALL:
rs = stat.executeQuery("SELECT * FROM "+t+" ORDER BY ID");
while(rs.next()) {
// nothing
}
break;
case SELECT_ONE:
rs = stat.executeQuery("SELECT * FROM "+t+" WHERE ID=" + rid);
while(rs.next()) {
// nothing
}
break;
case CHECKPOINT:
stat.execute("CHECKPOINT");
break;
case RECONNECT:
conn.close();
conn = master.getConnection("threads");
break;
}
}
conn.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.synth;
import java.math.BigDecimal;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
public class Value {
private int type;
private Object data;
private TestSynth config;
private Value(TestSynth config, int type, Object data) {
this.config = config;
this.type = type;
this.data = data;
}
String getSQL() {
if(data == null) {
return "NULL";
}
switch(type) {
case Types.DECIMAL:
case Types.NUMERIC:
case Types.BIGINT:
case Types.INTEGER:
case Types.DOUBLE:
case Types.REAL:
return data.toString();
case Types.CLOB:
case Types.VARCHAR:
case Types.CHAR:
case Types.OTHER:
case Types.LONGVARCHAR:
return "'" + data.toString() + "'";
case Types.BLOB:
case Types.BINARY:
case Types.VARBINARY:
case Types.LONGVARBINARY:
return getBlobSQL();
case Types.DATE:
return getDateSQL((Date)data);
case Types.TIME:
return getTimeSQL((Time)data);
case Types.TIMESTAMP:
return getTimestampSQL((Timestamp)data);
case Types.BOOLEAN:
case Types.BIT:
return (String)data;
default:
throw new Error("type="+type);
}
}
private static Date randomDate(TestSynth config) {
return config.random().randomDate();
}
private static Double randomDouble(TestSynth config) {
return new Double(config.random().getInt(100)/10.);
}
private static Long randomLong(TestSynth config) {
return new Long(config.random().getInt(1000));
}
private static Time randomTime(TestSynth config) {
return config.random().randomTime();
}
private static Timestamp randomTimestamp(TestSynth config) {
return config.random().randomTimestamp();
}
private String getTimestampSQL(Timestamp ts) {
String s = "'"+ts.toString()+"'";
if(config.getMode() != TestSynth.HSQLDB) {
s = "TIMESTAMP " + s;
}
return s;
}
private String getDateSQL(Date date) {
String s = "'"+date.toString()+"'";
if(config.getMode() != TestSynth.HSQLDB) {
s = "DATE " + s;
}
return s;
}
private String getTimeSQL(Time time) {
String s = "'"+time.toString()+"'";
if(config.getMode() != TestSynth.HSQLDB) {
s = "TIME " + s;
}
return s;
}
private String getBlobSQL() {
byte[] bytes = (byte[]) data;
// StringBuffer buff = new StringBuffer("X'");
StringBuffer buff = new StringBuffer("'");
for(int i=0; i<bytes.length; i++) {
int c = bytes[i] & 0xff;
buff.append(Integer.toHexString(c >> 4 & 0xf));
buff.append(Integer.toHexString(c & 0xf));
}
buff.append("'");
return buff.toString();
}
public static Value read(TestSynth config, ResultSet rs, int index) throws SQLException {
ResultSetMetaData meta = rs.getMetaData();
Object data;
int type = meta.getColumnType(index);
switch(type) {
case Types.REAL:
case Types.DOUBLE:
data = new Double(rs.getDouble(index));
break;
case Types.BIGINT:
data = new Long(rs.getLong(index));
break;
case Types.DECIMAL:
case Types.NUMERIC:
data = rs.getBigDecimal(index);
break;
case Types.BLOB:
case Types.BINARY:
case Types.VARBINARY:
case Types.LONGVARBINARY:
data = rs.getBytes(index);
break;
case Types.OTHER:
case Types.CLOB:
case Types.VARCHAR:
case Types.LONGVARCHAR:
case Types.CHAR:
data = rs.getString(index);
break;
case Types.DATE:
data = rs.getDate(index);
break;
case Types.TIME:
data = rs.getTime(index);
break;
case Types.TIMESTAMP:
data = rs.getTimestamp(index);
break;
case Types.INTEGER:
data = new Integer(rs.getInt(index));
break;
case Types.NULL:
data = null;
break;
case Types.BOOLEAN:
case Types.BIT:
data = rs.getBoolean(index) ? "TRUE" : "FALSE";
break;
default:
throw new Error("type="+type);
}
if(rs.wasNull()) {
data = null;
}
return new Value(config, type, data);
}
public static Value getRandom(TestSynth config, int type, int precision, int scale, boolean mayBeNull) {
Object data;
if(mayBeNull && config.random().getBoolean(20)) {
return new Value(config, type, null);
}
switch(type) {
case Types.BIGINT:
data = randomLong(config);
break;
case Types.DOUBLE:
data = randomDouble(config);
break;
case Types.DECIMAL:
data = randomDecimal(config, precision, scale);
break;
case Types.VARBINARY:
case Types.BINARY:
case Types.BLOB:
data = randomBytes(config, precision);
break;
case Types.CLOB:
case Types.VARCHAR:
data = config.random().randomString(config.random().getInt(precision));
break;
case Types.DATE:
data = randomDate(config);
break;
case Types.TIME:
data = randomTime(config);
break;
case Types.TIMESTAMP:
data = randomTimestamp(config);
break;
case Types.INTEGER:
data = randomInt(config);
break;
case Types.BOOLEAN:
case Types.BIT:
data = config.random().getBoolean(50) ? "TRUE" : "FALSE";
break;
default:
throw new Error("type="+type);
}
return new Value(config, type, data);
}
private static Object randomInt(TestSynth config) {
int value;
if(config.is(TestSynth.POSTGRESQL)) {
value = config.random().getInt(1000000);
} else {
value = config.random().getRandomInt();
}
return new Integer(value);
}
private static byte[] randomBytes(TestSynth config, int max) {
int len = config.random().getLog(max);
byte[] data = new byte[len];
config.random().getBytes(data);
return data;
}
private static BigDecimal randomDecimal(TestSynth config, int precision, int scale) {
int len = config.random().getLog(precision-scale)+scale;
if(len==0) {
len++;
}
StringBuffer buff = new StringBuffer();
for(int i=0; i<len; i++) {
buff.append((char) ('0' + config.random().getInt(10)));
}
buff.insert(len - scale, '.');
if(config.random().getBoolean(20)) {
buff.insert(0, '-');
}
return new BigDecimal(buff.toString());
}
public int compareTo(Object o) {
Value v = (Value)o;
if(type != v.type) {
throw new Error("compare "+type+" "+v.type+" "+data+" "+v.data);
}
if(data==null) {
return (v.data==null) ? 0 : -1;
} else if(v.data==null) {
return 1;
}
switch(type) {
case Types.DECIMAL:
return ((BigDecimal)data).compareTo((BigDecimal)v.data);
case Types.BLOB:
case Types.VARBINARY:
case Types.BINARY:
return compareBytes((byte[])data, (byte[])v.data);
case Types.CLOB:
case Types.VARCHAR:
return data.toString().compareTo(v.data.toString());
case Types.DATE:
return ((Date)data).compareTo((Date)v.data);
case Types.INTEGER:
return ((Integer)data).compareTo((Integer)v.data);
default:
throw new Error("type="+type);
}
}
static int compareBytes(byte[] a, byte[] b) {
int al = a.length, bl = b.length;
int len = Math.min(al, bl);
for(int i=0; i<len; i++) {
int x = a[i] & 0xff;
int y = b[i] & 0xff;
if(x==y) {
continue;
}
return x>y ? 1 : -1;
}
return al==bl ? 0 : al > bl ? 1 : -1;
}
public String toString() {
return getSQL();
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论