提交 24cd4aac authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 7a8bcd54
/*
* 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.samples;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import org.h2.tools.Backup;
import org.h2.tools.DeleteDbFiles;
import org.h2.tools.RunScript;
public class Compact {
public static void main(String[] args) throws Exception {
DeleteDbFiles.execute(null, "test", true);
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:test", "sa", "");
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR)");
stat.execute("INSERT INTO TEST VALUES(1, 'Hello'), (2, 'World');");
conn.close();
System.out.println("Compacting...");
compact(null, "test", "sa", "");
System.out.println("Done.");
}
public static void compact(String dir, String dbName, String user, String password) throws Exception {
String url = "jdbc:h2:" + dbName;
String script = "test.sql";
Backup.execute(url, user, password, script);
DeleteDbFiles.execute(dir, dbName, true);
RunScript.execute(url, user, password, script, null, false);
}
}
/*
* 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.samples;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Types;
import org.h2.tools.Csv;
import org.h2.tools.SimpleResultSet;
public class CsvSample {
public static void main(String[] args) throws Exception {
CsvSample.write();
CsvSample.read();
}
static void write() throws Exception {
SimpleResultSet rs = new SimpleResultSet();
rs.addColumn("NAME", Types.VARCHAR, 255, 0);
rs.addColumn("EMAIL", Types.VARCHAR, 255, 0);
rs.addColumn("PHONE", Types.VARCHAR, 255, 0);
rs.addRow(new String[] { "Bob Meier", "bob.meier@abcde.fgh", "+41123456789" });
rs.addRow(new String[] { "John Jones", "johnjones@abcde.fgh", "+41976543210" });
Csv.getInstance().write("test.csv", rs, null);
}
static void read() throws Exception {
ResultSet rs = Csv.getInstance().read("test.csv", null, null);
ResultSetMetaData meta = rs.getMetaData();
while (rs.next()) {
for (int i = 0; i < meta.getColumnCount(); i++) {
System.out.println(meta.getColumnLabel(i + 1) + ": " + rs.getString(i + 1));
}
System.out.println();
}
rs.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.samples;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class FileFunctions {
public static void main(String[] args) throws Exception {
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:mem:", "sa", "");
Statement stat = conn.createStatement();
stat.execute("CREATE ALIAS READ_TEXT_FILE FOR \"org.h2.samples.FileFunctions.readTextFile\" ");
stat.execute("CREATE ALIAS READ_TEXT_FILE_WITH_ENCODING FOR \"org.h2.samples.FileFunctions.readTextFileWithEncoding\" ");
stat.execute("CREATE ALIAS READ_FILE FOR \"org.h2.samples.FileFunctions.readFile\" ");
ResultSet rs = stat.executeQuery("CALL READ_FILE('test.txt')");
rs.next();
byte[] data = rs.getBytes(1);
System.out.println("length: " + data.length);
rs = stat.executeQuery("CALL READ_TEXT_FILE('test.txt')");
rs.next();
String text = rs.getString(1);
System.out.println("text: " + text);
conn.close();
}
public static String readTextFile(String fileName) throws IOException {
byte[] buff = readFile(fileName);
String s = new String(buff);
return s;
}
public static String readTextFileWithEncoding(String fileName, String encoding) throws IOException {
byte[] buff = readFile(fileName);
String s = new String(buff, encoding);
return s;
}
public static byte[] readFile(String fileName) throws IOException {
RandomAccessFile file = new RandomAccessFile(fileName, "r");
try {
byte[] buff = new byte[(int)file.length()];
file.readFully(buff);
return buff;
} finally {
file.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.samples;
import java.math.BigInteger;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import org.h2.tools.SimpleResultSet;
public class Function {
public static void main(String[] args) throws Exception {
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:mem:", "sa", "");
Statement stat = conn.createStatement();
stat.execute("CREATE ALIAS ISPRIME FOR \"org.h2.samples.Function.isPrime\" ");
ResultSet rs;
rs = stat.executeQuery("SELECT ISPRIME(X), X FROM SYSTEM_RANGE(1, 20) ORDER BY X");
while(rs.next()) {
boolean isPrime = rs.getBoolean(1);
if(isPrime) {
int x = rs.getInt(2);
System.out.println(x + " is prime");
}
}
conn.close();
}
public static boolean isPrime(int value) {
return new BigInteger(String.valueOf(value)).isProbablePrime(100);
}
public static ResultSet query(Connection conn, String sql) throws SQLException {
return conn.createStatement().executeQuery(sql);
}
public static ResultSet simpleResultSet() throws SQLException {
SimpleResultSet rs = new SimpleResultSet();
rs.addColumn("ID", Types.INTEGER, 10, 0);
rs.addColumn("NAME", Types.VARCHAR, 255, 0);
rs.addRow(new Object[] { new Integer(0), "Hello" });
return rs;
}
public static ResultSet getMatrix(Connection conn, Integer id) throws SQLException {
SimpleResultSet rs = new SimpleResultSet();
rs.addColumn("X", Types.INTEGER, 10, 0);
rs.addColumn("Y", Types.INTEGER, 10, 0);
if(id == null) {
return rs;
}
for(int x = 0; x < id.intValue(); x++) {
for(int y = 0; y < id.intValue(); y++) {
rs.addRow(new Object[] { new Integer(x), new Integer(y) });
}
}
return rs;
}
}
/*
* 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.samples;
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.sql.Types;
import org.h2.tools.SimpleResultSet;
public class FunctionMultiReturn {
public static void main(String[] args) throws Exception {
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:mem:", "sa", "");
Statement stat = conn.createStatement();
stat.execute("CREATE ALIAS P2C FOR \"org.h2.samples.FunctionMultiReturn.polar2Cartesian\" ");
PreparedStatement prep = conn.prepareStatement("SELECT X, Y FROM P2C(?, ?)");
prep.setDouble(1, 5.0);
prep.setDouble(2, 0.5);
ResultSet rs = prep.executeQuery();
while(rs.next()) {
double x = rs.getDouble(1);
double y = rs.getDouble(2);
System.out.println("result: (x=" + x + ", y="+y+")");
}
stat.execute("CREATE TABLE TEST(ID IDENTITY, R DOUBLE, A DOUBLE)");
stat.execute("INSERT INTO TEST(R, A) VALUES(5.0, 0.5), (10.0, 0.6)");
stat.execute("CREATE ALIAS P2C_SET FOR \"org.h2.samples.FunctionMultiReturn.polar2CartesianSet\" ");
rs = conn.createStatement().executeQuery("SELECT * FROM P2C_SET('SELECT * FROM TEST')");
while(rs.next()) {
double r = rs.getDouble("R");
double a = rs.getDouble("A");
double x = rs.getDouble("X");
double y = rs.getDouble("Y");
System.out.println("(r="+r+" a="+a+") : (x=" + x + ", y="+y+")");
}
stat.execute("CREATE ALIAS P2C_A FOR \"org.h2.samples.FunctionMultiReturn.polar2CartesianArray\" ");
rs = conn.createStatement().executeQuery("SELECT R, A, P2C_A(R, A) FROM TEST");
while(rs.next()) {
double r = rs.getDouble(1);
double a = rs.getDouble(2);
Object o = rs.getObject(3);
Object[] xy = (Object[]) o;
double x = ((Double)xy[0]).doubleValue();
double y = ((Double)xy[1]).doubleValue();
System.out.println("(r="+r+" a="+a+") : (x=" + x + ", y="+y+")");
}
rs = conn.createStatement().executeQuery("SELECT R, A, ARRAY_GET(E, 1), ARRAY_GET(E, 2) FROM (SELECT R, A, P2C_A(R, A) E FROM TEST)");
while(rs.next()) {
double r = rs.getDouble(1);
double a = rs.getDouble(2);
double x = rs.getDouble(3);
double y = rs.getDouble(4);
System.out.println("(r="+r+" a="+a+") : (x=" + x + ", y="+y+")");
}
conn.close();
}
/**
* The function may be called twice, once to retrieve the result columns (with null parameters),
* and the second time to return the data.
*/
public static ResultSet polar2Cartesian(Double r, Double alpha) throws SQLException {
SimpleResultSet rs = new SimpleResultSet();
rs.addColumn("X", Types.DOUBLE, 0, 0);
rs.addColumn("Y", Types.DOUBLE, 0, 0);
if(r != null && alpha != null) {
double x = r.doubleValue() * Math.cos(alpha.doubleValue());
double y = r.doubleValue() * Math.sin(alpha.doubleValue());
rs.addRow(new Object[] { new Double(x), new Double(y) });
}
return rs;
}
/**
* The function may be called twice, once to retrieve the result columns (with null parameters),
* and the second time to return the data.
*/
public static Object[] polar2CartesianArray(Double r, Double alpha) throws SQLException {
double x = r.doubleValue() * Math.cos(alpha.doubleValue());
double y = r.doubleValue() * Math.sin(alpha.doubleValue());
return new Object[]{new Double(x), new Double(y)};
}
public static ResultSet polar2CartesianSet(Connection conn, String query) throws SQLException {
SimpleResultSet result = new SimpleResultSet();
result.addColumn("R", Types.DOUBLE, 0, 0);
result.addColumn("A", Types.DOUBLE, 0, 0);
result.addColumn("X", Types.DOUBLE, 0, 0);
result.addColumn("Y", Types.DOUBLE, 0, 0);
if(query != null) {
ResultSet rs = conn.createStatement().executeQuery(query);
while(rs.next()) {
double r = rs.getDouble("R");
double alpha = rs.getDouble("A");
double x = r * Math.cos(alpha);
double y = r * Math.sin(alpha);
result.addRow(new Object[] { new Double(r), new Double(alpha), new Double(x), new Double(y) });
}
}
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.samples;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import org.h2.tools.RunScript;
import org.h2.util.StringUtils;
public class Newsfeed {
public static void main(String[] args) throws Exception {
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:mem:", "sa", "");
InputStream in = Newsfeed.class.getResourceAsStream("newsfeed.sql");
ResultSet rs = RunScript.execute(conn, new InputStreamReader(in, "ISO-8859-1"));
while(rs.next()) {
String file = rs.getString("FILE");
String content = rs.getString("CONTENT");
if(file.equals("-newsletter-")) {
System.out.println(convertHtml2Text(content));
} else {
FileOutputStream out = new FileOutputStream(file);
Writer writer = new OutputStreamWriter(out, "UTF-8");
writer.write(content);
writer.close();
out.close();
}
}
conn.close();
}
private static String convertHtml2Text(String html) {
String s = html;
s = StringUtils.replaceAll(s, "<b>", "");
s = StringUtils.replaceAll(s, "</b>", "");
s = StringUtils.replaceAll(s, "<ul>", "");
s = StringUtils.replaceAll(s, "</ul>", "");
s = StringUtils.replaceAll(s, "<li>", "- ");
s = StringUtils.replaceAll(s, "<a href=\"", "( ");
s = StringUtils.replaceAll(s, "\">", " ) ");
s = StringUtils.replaceAll(s, "</a>", "");
s = StringUtils.replaceAll(s, "<br/>", "");
if(s.indexOf('<') >= 0 || s.indexOf('>') >= 0) {
throw new Error("Unsupported HTML Tag: < or > in " + s);
}
return s;
}
}
/*
* 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.samples;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;
/**
* @author Thomas
*/
public class SecurePassword {
public static void main(String[] argv) throws Exception {
Class.forName("org.h2.Driver");
String url = "jdbc:h2:simple";
String user = "sam";
char[] password = {'t', 'i', 'a', 'E', 'T', 'r', 'p'};
// 'unsafe' way to connect
// the password may reside in the main memory for an undefined time
// or even written to disk (swap file)
// Connection conn = DriverManager.getConnection(url, user, new String(password));
// 'safe' way to connect
// the password is overwritten after use
Properties prop = new Properties();
prop.setProperty("user", user);
prop.put("password", password);
Connection conn = DriverManager.getConnection(url, prop);
Statement stat = conn.createStatement();
stat.execute("DROP TABLE IF EXISTS TEST");
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR)");
stat.executeUpdate("INSERT INTO TEST VALUES(1, 'Hello')");
ResultSet rs = stat.executeQuery("SELECT * FROM TEST");
while(rs.next()) {
System.out.println(rs.getString("NAME"));
}
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.samples;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import org.h2.api.DatabaseEventListener;
import org.h2.jdbc.JdbcConnection;
public class ShowProgress implements DatabaseEventListener {
private long last, start;
public ShowProgress() {
start = last = System.currentTimeMillis();
}
public static void main(String[] args) throws Exception {
new ShowProgress().test();
}
void test() throws Exception {
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:test;LOG=2", "sa", "");
Statement stat = conn.createStatement();
stat.execute("DROP TABLE IF EXISTS TEST");
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR)");
PreparedStatement prep = conn.prepareStatement("INSERT INTO TEST VALUES(?, 'Test' || SPACE(100))");
long time;
time = System.currentTimeMillis();
int len = 1000;
for(int i=0; i<len; i++) {
long last = System.currentTimeMillis();
if(last > time+1000) {
time = last;
System.out.println("Inserting " + (100L*i/len) + "%");
}
prep.setInt(1, i);
prep.execute();
}
boolean abnormalTermination = true;
if(abnormalTermination) {
((JdbcConnection)conn).setPowerOffCount(1);
try {
stat.execute("INSERT INTO TEST VALUES(-1, 'Test' || SPACE(100))");
} catch(SQLException e) {
}
} else {
conn.close();
}
System.out.println("Open connection...");
time = System.currentTimeMillis();
conn = DriverManager.getConnection("jdbc:h2:test;LOG=2;DATABASE_EVENT_LISTENER='" + getClass().getName() + "'", "sa", "");
time = System.currentTimeMillis() - time;
System.out.println("Done after " + time + " ms");
conn.close();
}
public void diskSpaceIsLow(long stillAvailable) throws SQLException {
System.out.println("diskSpaceIsLow stillAvailable="+stillAvailable);
}
public void exceptionThrown(SQLException e) {
e.printStackTrace();
}
public void setProgress(int state, String name, int current, int max) {
long time = System.currentTimeMillis();
if(time < last+5000) {
return;
}
last = time;
String stateName = "?";
switch(state) {
case STATE_SCAN_FILE:
stateName = "Scan " + name;
break;
case STATE_CREATE_INDEX:
stateName = "Create Index " + name;
break;
case STATE_RECOVER:
stateName = "Recover";
break;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
System.out.println("State: " + stateName + " " + (100*current/max) + "% (" + current+" of " + max + ") " + (time-start)+" ms");
}
public void closingDatabase() {
System.out.println("Closing the database");
}
public void init(String url) {
System.out.println("Initializing the event listener for database " + 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.samples;
public class ShutdownServer {
public static void main(String[] args) throws Exception {
org.h2.tools.Server.shutdownTcpServer("tcp://localhost:9094", "", false);
}
}
/*
* 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.samples;
import java.math.BigDecimal;
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 org.h2.api.Trigger;
public class TriggerSample {
public static void main(String[] args) throws Exception {
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:mem:", "sa", "");
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE INVOICE(ID INT PRIMARY KEY, AMOUNT DECIMAL)");
stat.execute("CREATE TABLE INVOICE_SUM(AMOUNT DECIMAL)");
stat.execute("INSERT INTO INVOICE_SUM VALUES(0.0)");
stat.execute("CREATE TRIGGER INV_INS AFTER INSERT ON INVOICE FOR EACH ROW CALL \"org.h2.samples.TriggerSample$MyTrigger\" ");
stat.execute("CREATE TRIGGER INV_UPD AFTER UPDATE ON INVOICE FOR EACH ROW CALL \"org.h2.samples.TriggerSample$MyTrigger\" ");
stat.execute("CREATE TRIGGER INV_DEL AFTER DELETE ON INVOICE FOR EACH ROW CALL \"org.h2.samples.TriggerSample$MyTrigger\" ");
stat.execute("INSERT INTO INVOICE VALUES(1, 10.0)");
stat.execute("INSERT INTO INVOICE VALUES(2, 19.95)");
stat.execute("UPDATE INVOICE SET AMOUNT=20.0 WHERE ID=2");
stat.execute("DELETE FROM INVOICE WHERE ID=1");
ResultSet rs;
rs = stat.executeQuery("SELECT AMOUNT FROM INVOICE_SUM");
rs.next();
System.out.println("The sum is " + rs.getBigDecimal(1));
conn.close();
}
public static class MyTrigger implements Trigger {
public void init(Connection conn, String schemaName, String triggerName, String tableName) {
// System.out.println("Initializing trigger " + triggerName + " for table " + tableName);
}
public void fire(Connection conn,
Object[] oldRow, Object[] newRow)
throws SQLException {
BigDecimal diff = null;
if(newRow != null) {
diff = (BigDecimal)newRow[1];
}
if(oldRow != null) {
BigDecimal m = (BigDecimal)oldRow[1];
diff = diff == null ? m.negate() : diff.subtract(m);
}
PreparedStatement prep = conn.prepareStatement(
"UPDATE INVOICE_SUM SET AMOUNT=AMOUNT+?");
prep.setBigDecimal(1, diff);
prep.execute();
}
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
// Example using the 'native' fulltext search implementation
CREATE ALIAS IF NOT EXISTS FT_INIT FOR "org.h2.fulltext.FullText.init";
CALL FT_INIT();
DROP TABLE IF EXISTS TEST;
CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR);
INSERT INTO TEST VALUES(1, 'Hello World');
CALL FT_CREATE_INDEX('PUBLIC', 'TEST', NULL);
SELECT * FROM FT_SEARCH('Hello', 0, 0);
SELECT * FROM FT_SEARCH('Hallo', 0, 0);
INSERT INTO TEST VALUES(2, 'Hallo Welt');
SELECT * FROM FT_SEARCH('Hello', 0, 0);
SELECT * FROM FT_SEARCH('Hallo', 0, 0);
CALL FT_REINDEX();
SELECT * FROM FT_SEARCH('Hello', 0, 0);
SELECT * FROM FT_SEARCH('Hallo', 0, 0);
INSERT INTO TEST VALUES(3, 'Hello World');
INSERT INTO TEST VALUES(4, 'Hello World');
INSERT INTO TEST VALUES(5, 'Hello World');
SELECT * FROM FT_SEARCH('World', 0, 0);
SELECT * FROM FT_SEARCH('World', 1, 0);
SELECT * FROM FT_SEARCH('World', 0, 2);
SELECT * FROM FT_SEARCH('World', 2, 1);
SELECT * FROM FT_SEARCH('1');
CALL FT_DROP_ALL();
SELECT * FROM FT_SEARCH('World', 2, 1);
CALL FT_DROP_ALL();
// Example using the 'Lucene' fulltext search implementation
CREATE ALIAS IF NOT EXISTS FTL_INIT FOR "org.h2.fulltext.FullTextLucene.init";
CALL FTL_INIT();
DROP TABLE IF EXISTS TEST;
CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR);
INSERT INTO TEST VALUES(1, 'Hello World');
CALL FTL_CREATE_INDEX('PUBLIC', 'TEST', NULL);
SELECT * FROM FTL_SEARCH('Hello', 0, 0);
SELECT * FROM FTL_SEARCH('Hallo', 0, 0);
INSERT INTO TEST VALUES(2, 'Hallo Welt');
SELECT * FROM FTL_SEARCH('Hello', 0, 0);
SELECT * FROM FTL_SEARCH('Hallo', 0, 0);
CALL FTL_REINDEX();
SELECT * FROM FTL_SEARCH('Hello', 0, 0);
SELECT * FROM FTL_SEARCH('Hallo', 0, 0);
INSERT INTO TEST VALUES(3, 'Hello World');
INSERT INTO TEST VALUES(4, 'Hello World');
INSERT INTO TEST VALUES(5, 'Hello World');
SELECT * FROM FTL_SEARCH('World', 0, 0);
SELECT * FROM FTL_SEARCH('World', 1, 0);
SELECT * FROM FTL_SEARCH('World', 0, 2);
SELECT * FROM FTL_SEARCH('World', 2, 1);
SELECT * FROM FTL_SEARCH('1', 0, 0);
CALL FTL_DROP_ALL();
SELECT * FROM FTL_SEARCH('World', 2, 1);
CALL FTL_DROP_ALL();
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
*/
CREATE TABLE CHANNEL(TITLE VARCHAR, LINK VARCHAR, DESC VARCHAR,
LANGUAGE VARCHAR, PUB TIMESTAMP, LAST TIMESTAMP, AUTHOR VARCHAR);
INSERT INTO CHANNEL VALUES('H2 Database Engine' ,
'http://www.h2database.com', 'H2 Database Engine', 'en-us', NOW(), NOW(), 'Thomas Mueller');
CREATE TABLE ITEM(ID INT PRIMARY KEY, TITLE VARCHAR, ISSUED TIMESTAMP, DESC VARCHAR);
INSERT INTO ITEM VALUES(17,
'New version available: 1.0 / 2006-12-03', '2006-12-03 12:00:00',
'A new version of H2 is available for <a href="http://www.h2database.com">download</a>.
<br/>
<b>Changes and new functionality:</b>
<ul>
<li>New connection time setting CACHE_TYPE=TQ to use the 2Q page replacement
algorithm. 2Q should be more resistant to table scan.
<li>Improved performance for CREATE INDEX (about 10%).
<li>Optimization: The left and right side of a AND and OR conditions are now
ordered by the expected cost.
<li>Java functions returning a result set (such as CSVREAD) now can be used in
a SELECT statement like a table. The behaviour has been changed: Now first
call contains the values if set, but the connection URL is different
(jdbc:columnlist:connection instead of jdbc:default:connection).
<li>The service wrapper is now included in the default installation and documented.
<li>New system function SESSION_ID().
<li>Mixing certain data types in an operation, for example VARCHAR and
TIMESTAMP, now converts both expressions to TIMESTAMP.
<li>Change behaviour: If both sides of a comparison are parameters with unknown
data type, then an exception is thrown now. The same happens for UNION
SELECT if both columns are parameters.
</ul>
<b>Bugfixes:</b>
<ul>
<li>There was a bug in the database encryption algorithm.
Pattern of repeated encrypted bytes where generated for empty blocks in the
file. If you have an encrypted database, you will need to decrypt the database
using the org.h2.tools.ChangePassword (using the old database engine), and
encrypt the database using the new engine. Alternatively, you can use the
Backup and RunScript tools or the SQL commands SCRIPT and RUNSCRIPT.
<li>Deeply nested views where slow to execute, because the query was parsed
many times. Fixed.
<li>The SQL statement COMMENT did not work as expected. If you already have
comments in the database, it is recommended to backup and restore the
database, using the Backup and RunScript tools or the SQL commands SCRIPT
and RUNSCRIPT.
<li>Server: In some situations, calling close() on a ResultSet or Statement threw
an exception. This has been fixed.
</ul>
For future plans, see the new ''Roadmap'' page on the web site.
</ul>
');
INSERT INTO ITEM VALUES(16,
'New version available: 1.0 / 2006-11-20', '2006-11-20 12:00:00',
'A new version of H2 is available for <a href="http://www.h2database.com">download</a>.
<br/>
<b>Changes and new functionality:</b>
<ul>
<li>New SQL statement SET SCHEMA to change the current schema of this session.
<li>New system function SCHEMA() to get the current schema.
<li>SCRIPT: New option BLOCKSIZE to split BLOBs and CLOBs into separate blocks, to avoid OutOfMemory problems.
<li>CURRVAL and NEXTVAL functions: New optional sequence name parameter.
<li>The default cache size is now 65536 pages instead of 32768.
<li>New optimization to reuse subquery results. Can be disabled with SET OPTIMIZE_REUSE_RESULTS 0.
<li>EXPLAIN... results are now formatted on multiple lines so they are easier to read.
<li>The Spanish translation was completed by Miguel Angel. Thanks a lot! Translations to other languages are always welcome.
<li>The Recovery tool has been improved. It now creates a SQL script file that can be executed directly.
<li>LENGTH now returns the precision for CLOB, BLOB, and BINARY (and is therefore faster).
<li>The built-in FTP server can now access a virtual directory stored in a database.
</ul>
<b>Bugfixes:</b>
<ul>
<li>When using the READ_COMMITTED isolation level, a transaction now waits until there are no write locks.
<li>INSERT INTO ... SELECT ... and ALTER TABLE with CLOBs and/or BLOBs did not work.
<li>CSV tool: the methods setFieldSeparatorWrite and setRowSeparatorWrite where not accessible.
<li>ALTER TABLE ADD did throw a strange message if the table contained views. Now the message is better,
but it is still not possible to do that if views on this table exist.
<li>ALTER TABLE: If there was a foreign key in another table that references to the change table, the constraint was dropped.
<li>Direct links to the Javadoc were not working.
<li>Inserting rows into linked tables did not work for HSQLDB when the value was NULL.
<li>Oracle SYNONYM tables are now listed in the H2 Console.
<li>CREATE LINKED TABLE didn''t work for Oracle SYNONYM tables.
<li>When using the server version, when not closing result sets or using nested DatabaseMetaData result sets, the connection could break.
</ul>
For future plans, see the new ''Roadmap'' page on the web site.
</ul>
');
INSERT INTO ITEM VALUES(15,
'New version available: 1.0 / 2006-11-03', '2006-11-03 12:00:00',
'A new version of H2 is available for <a href="http://www.h2database.com">download</a>.
<br/>
<b>Changes and new functionality:</b>
<ul>
<li>New SQL statement COMMENT ON ... IS ...
<li>Two simple full text search implementations (Lucene and native) are now included.
This is work in progress, and currently undocumented.
See test/org/h2/samples/fullTextSearch.sql and History for more details.
<li>Index names of referential constraints are now prefixed with the constraint name.
<li>Improved search functionality in the HTML documentation (highlight).
<li>Triggers can now be defined on a list of actions.
<li>On some systems (for example, some Linux VFAT and USB flash disk drivers),
RandomAccessFile.setLength does not work correctly.
A workaround for this problem has been implemented.
<li>DatabaseMetaData.getTableTypes now also returns SYSTEM TABLE and TABLE VIEW.
Please tell me if this breaks other applications or tools.
<li>Java functions with Blob or Clob parameters are now supported.
<li>Added a ''remarks'' column to most system tables.
<li>New system table INFORMATION_SCHEMA.TRIGGERS
<li>PostgreSQL compatibility: Support for the date format 2006-09-22T13:18:17.061
<li>MySQL compatibility: ResultSet.getString("PEOPLE.NAME") is now supported.
<li>JDBC 4.0 driver auto discovery: When using JDK 1.6,
Class.forName("org.h2.Driver") is no longer required.
</ul>
<b>Bugfixes:</b>
<ul>
<li>Wide b-tree indexes (with large VARCHAR columns for example) could get corrupted.
<li>If a custom shutdown hook was installed, and the database was called at shutdown,
a NullPointException was thrown.
Now, a error message with instructions how to fix this is thrown.
<li>If SHUTDOWN was called and DB_CLOSE_DELAY was set, the database was not closed.
<li>Subqueries with order by outside the column list didn''t work correctly.
<li>Linked Tables: Only the first column was linked when linking to PostgreSQL.
<li>Sequences: When the database is not closed normally, the value was not set correctly.
<li>The optimization for IN(SELECT...) was too agressive.
<li>Blob.getBytes skipped the wrong number of bytes.
<li>Group by a function didn''t work if a column alias was specified in the select list.
<li>LOCK_MODE 0 (READ_UNCOMMITTED) did not work when using multiple connections.
</ul>
For future plans, see the new ''Roadmap'' page on the web site.
</ul>
');
INSERT INTO ITEM VALUES(14,
'New version available: 1.0 / 2006-10-10', '2006-10-10 12:00:00',
'A new version of H2 is available for <a href="http://www.h2database.com">download</a>.
<br/>
<b>Changes and new functionality:</b>
<ul>
<li>Support for DOMAIN (user defined data types).
<li>Support for UUID.
<li>Function aliases may now optionally include parameter classes.
<li>A small FTP server is now included (disabled by default).
<li>Can now compile everything with JDK 1.6 (however, only very few of the JDBC 4.0 features are implemented currently).
<li>The multi-threaded kernel can not be enabled using SET MULTI_THREADED 1.
A new tests has been written for this feature, and additional synchronization has been added.
</ul>
<b>Bugfixes:</b>
<ul>
<li>Could not re-connect to a database when ALLOW_LITERALS or COMPRESS_LOB was set.
<li>Opening and closing connections in many threads sometimes failed.
<li>Reconnect didn''t work after renaming a user if rights were granted for this user.
<li>GROUP BY an formula or function didn''t work if the same expression was used in the select list.
<li>Redundant () in a IN subquery is now supported: where id in ((select id from test)).
</ul>
For future plans, see the new ''Roadmap'' page on the web site.
</ul>
');
INSERT INTO ITEM VALUES(13,
'New version available: 1.0 / 2006-09-24', '2006-09-24 12:00:00',
'A new version of H2 is available for <a href="http://www.h2database.com">download</a>.
<br/>
<b>Changes and new functionality:</b>
<ul>
<li>Protection against SQL injection: New command SET ALLOW_LITERALS {NONE|ALL|NUMBERS}.
With SET ALLOW_LITERALS NONE, SQL injections are not possible because literals in SQL statements are rejected;
User input must be set using parameters (''?'') in this case.
<li>New concept ''Constants'': New SQL statements CREATE CONSTANT and DROP CONSTANT.
<li>CREATE TABLE ... AS SELECT ... is now supported.
<li>New data type OTHER (alternative names OBJECT and JAVA_OBJECT). When using this data type,
Java Objects are automatically serialized and deserialized in the JDBC layer.
<li>Improved performance for MetaData calls
<li>Improved BatchUpdateException
<li>DatabaseMetaData.getProcedures and getProcedureColumns are implemented now
<li>An exception is now thrown on unknown setting in the database URL (which are most likely typos)
<li>The log size is now automatically increased to at least 10% of the data file.
<li>Backup and Runscript tools now support options (for compression and so on)
<li>InetAddress.getByName("127.0.0.1") instead of InetAddress.getLocalHost() is now used to get the loopback address
<li>CREATE SCHEMA: The authorization part is now optional.
<li>DROP TABLE: Can now drop more than one column in one step: DROP TABLE A, B
<li>LOBs are now automatically converted to files by default.
<li> Optimizations for WHERE ... IN(...) and SELECT MIN(..), MAX(..) are now enabled by default.
<li>New system function LOCK_MODE()
<li>Connection.setTransactionIsolation and getTransactionIsolation now set / get the LOCK_MODE of the database.
<li>New LOCK_MODE 3 (READ_COMMITTED). Table level locking, but only when writing (no read locks).
</ul>
<b>Bugfixes:</b>
<ul>
<li>Wide b-tree indexes (with large VARCHAR columns for example) with a long common prefix (where many
rows start with the same text) could get corrupted. Fixed.
<li>Reading from compressed LOBs didn''t work in some cases. Fixed.
<li>CLOB / BLOB: Copying LOB data directly from one table to another, and altering a table with with LOBs did not work,
the BLOB data was deleted when the old table was deleted. Fixed.
<li>[NOT] EXISTS(SELECT ... EXCEPT SELECT ...) did not work in all cases. Fixed.
<li>Functions returning a result set are now called as documented.
</ul>
For future plans, see the new ''Roadmap'' page on the web site.
</ul>
');
INSERT INTO ITEM VALUES(12,
'New version available: 1.0 / 2006-09-10', '2006-09-10 12:00:00',
'A new version of H2 is available for <a href="http://www.h2database.com">download</a>.
<br/>
<b>Changes and new functionality:</b>
<ul>
<li>SET IGNORECASE is now supported for compatibility with HSQLDB.
<li>New SQL statement DROP ALL OBJECTS [DELETE FILES] to drop all tables, sequences and so on.
<li>Improved OpenOffice compatibility.
<li>New setting SET COMPRESS_LOB {NO|LZF|DEFLATE} to automatically compress BLOBs and CLOBs.
<li>The script can now be compressed. Syntax: SCRIPT TO ''file'' COMPRESSION {DEFLATE|LZF|ZIP|GZIP}.
<li>Now an exception is thrown when the an overflow occurs for mathematical operations (sum, multiply and so on) for the data type selected.
This was implemented in the previous version but is now enabled by default.
<li>Updated the performance test so that Firebird can be tested as well. Results are not included currently,
information how to best test Firebird should be sent to the support address or posted in the Forum.
</ul>
<b>Bugfixes:</b>
<ul>
<li>ORDER BY an expression didn''t work when using GROUP BY at the same time.
<li>A problem with referential constraints in the SCRIPT file has been fixed.
<li>Console: The setting ;hsqldb.default_table_type=cached was added to the H2 database instead of the HSQLDB database.
<li>Docs: The cross references in the SQL grammar docs where broken in the last release.
<li>Deleting many rows from a table with a self-referencing constraint with ''on delete cascade'' did not work.
<li>ROWNUM didn''t always work as expected when using subqueries.
<li>Correlated subqueries: It is now possible to use columns of the outer query in the select list of the inner query.
</ul>
For future plans, see the new ''Roadmap'' page on the web site.
</ul>
');
INSERT INTO ITEM VALUES(11,
'Article about the 1.0 release on InfoQ', '2006-09-05 12:00:00',
'There is an article about the 1.0 release at InfoQ:
See <a href="http://www.infoq.com/news/h2-released">http://www.infoq.com/news/h2-released</a>.
');
INSERT INTO ITEM VALUES(10,
'New version available: 1.0 / 2006-08-31', '2006-08-31 12:00:00',
'H2 version 1.0 is available for <a href="http://www.h2database.com">download</a>.
<br/>
<b>Bugfixes:</b>
<ul>
<li>In some situations, wide b-tree indexes (with large VARCHAR columns for example) could get corrupted. Fixed.
<li>ORDER BY was broken in the last release when using table aliases. Fixed.
</ul>
For details see also the history.
For future plans, see the new ''Roadmap'' page on the web site.
');
INSERT INTO ITEM VALUES(9,
'New version available: 1.0 RC 2 / 2006-08-28', '2006-08-28 12:00:00',
'A new version of H2 is available for <a href="http://www.h2database.com">download</a>.
<br/>
<b>Changes and new functionality:</b>
<ul>
<li>Linked tables: The table name is no longer quoted when accessing the foreign database.
This allows to use schema names, and possibly subqueries as table names (when used in queries).
Also, the compatibility with other databases has been improved.
<li>New setting MAX_LENGTH_INPLACE_LOB.
<li>LOB files where not deleted when the table was truncated or dropped. This is now done.
</ul>
<b>New Functionality (but currently disabled):</b>
These features are currently disabled. They will be enabled after release 1.0.
See the history for more details.
<li>Optimization for MIN and MAX: Queries such as SELECT MIN(ID), MAX(ID)+1, COUNT(*) FROM TEST can now use an index if one is available.
<li>When large strings or byte arrays where inserted into a LOB (CLOB or BLOB), or if the data was stored using
PreparedStatement.setBytes or setString, the data was stored in-place (no separate files where created).
Now distinct files are created if the size is larger than MAX_LENGTH_INPLACE_LOB.
</ul>
<b>Bugfixes:</b>
<ul>
<li>Outer join: Some incompatibilities with PostgreSQL and MySQL with more complex outer joins have been fixed.
<li>Subquery optimization: Constant subqueries are now only evaluated once (like this was before).
<li>DATEDIFF on seconds, minutes, hours did return different results in certain timezones (half-hour timezones) in certain situations. Fixed.
</ul>
For details see also the history. Version 1.0 is planned for 2006-08-29.
The plans for version 1.0 are:
<ul>
<li>Write more tests, bugfixes.
<li>For plans after release 1.0, see the new ''Roadmap'' page on the web site.
</ul>
');
INSERT INTO ITEM VALUES(8,
'New proposed license', '2006-08-25 12:00:00',
'A new proposed license is available at
<a href="http://www.h2database.com/html/proposed_license.html">h2database.com/html/proposed_license.html</a>.
This is still open for discussion at the <a href="http://www.h2database.com/ipowerb">license forum</a>.
');
INSERT INTO ITEM VALUES(7,
'New version available: 0.9 RC 1 / 2006-08-23', '2006-08-23 12:00:00',
'A new version of H2 is available for <a href="http://www.h2database.com">download</a>.
<br/>
<b>Changes and new functionality:</b>
<ul>
<li>Date and time constants outside the valid range (February 31 and so on) are no longer accepted.
<li>Improvements in the autocomplete feature. Thanks a lot to James Devenish for his very valuable feedback and testing!
</ul>
<b>New Functionality (but currently disabled):</b>
These features are currently disabled. They will be enabled after release 1.0.
See the history for more details.
<li>Optimization for IN(value list) and IN(subquery).
<li>Very large transactions are now supported.
<li>Arithmetic overflows in can now be detected for integer types.
</ul>
<b>Bugfixes:</b>
<ul>
<li>Bugfix for an outer join problem (too many rows where returned for a combined inner join / outer join).
<li>Local temporary tables where not included in the meta data.
<li>Database opening: Sometimes opening a database was very slow because indexes were re-created.
<li>Referential integrity: Fixed a stack overflow problem when using cascade delete.
<li>LIKE: If collation was set (SET COLLATION ...), it was ignored when using LIKE.
</ul>
For details see also the history. Release 1.0 is planned for 2006-08-28.
There will be another release candidate (RC 2) before.
The plans for the next release (RC 2) are:
<ul>
<li>Change the license to MPL.
<li>Write more tests, bugfixes.
<li>For plans after release 1.0, see the new ''Roadmap'' page on the web site.
</ul>
');
INSERT INTO ITEM VALUES(6,
'New version available: 0.9 Beta / 2006-08-14', '2006-08-14 12:00:00',
'A new version of H2 is available for <a href="http://www.h2database.com">download</a>.
<br/>
<b>Changes and new functionality:</b>
<ul>
<li>Autocomplete support in the H2 Console.
Three levels: Off, Normal (default; table and column names), Full (complete SQL grammar).
Schemas and quoted identifiers are not yet supported.
There are some browser issues, but everything should work in Firefox.
Please report any incompatibilities, problems and usability issues.
<li>Source code to support H2 in Resin is included.
For the complete patch, see http://forum.caucho.com/node/61
<li>Space is better re-used after deleting many records.
<li>Umlauts and chinese characters are now supported in identifier names.
<li>Performance optimization for outer join with comparison with constants in the where clause.
</ul>
<b>Bugfixes:</b>
<ul>
<li>SET LOG 0 didn''t work. Fixed.
<li>Fixed a problem when comparing BIGINT values with constants.
<li>Fixed NULL handling where there is a NULL value in the list.
<li>It is now possible to cancel a select statement with a (temporary) view.
</ul>
For details see also the history. The next release is planned for 2006-08-28.
If everything goes fine this will be 1.0 final (there might be a release candidate or two before this date).
The plans for the next release are:
<ul>
<li>Bugfixes, write more tests, more bugfixes, more tests.
<li>Proposal for changed license.
<li>For other plans, see the new ''Roadmap'' part on the web site.
</ul>
');
INSERT INTO ITEM VALUES(5,
'New version available: 0.9 Beta / 2006-07-29', '2006-07-30 12:00:00',
'A new version of H2 is available for <a href="http://www.h2database.com">download</a>.
<br/>
<b>Changes and new functionality:</b>
<ul>
<li>ParameterMetaData is now implemented
<li>Experimental auto-complete functionality in the H2 Console.
Does not yet work for all cases.
Press [Ctrl]+[Space] to activate, and [Esc] to deactivate it.
<li>1.0/3.0 is now 0.33333... and not 0.3 as before.
The scale of a DECIMAL division is adjusted automatically (up to current scale + 25).
<li>''SELECT * FROM TEST'' can now be written as ''FROM TEST SELECT *''
<li>New parameter schemaName in Trigger.init.
<li>New method DatabaseEventListener.init to pass the database URL.
<li> Opening a database that was not closed previously is now faster
(specially if using a database URL of the form jdbc:h2:test;LOG=2)
<li>Improved performance for Statement.getGeneratedKeys
</ul>
<b>Bugfixes:</b>
<ul>
<li>SCRIPT: The system generated indexes are not any more included in the script file.
Also, the drop statements for generated sequences are not included in the script any longer.
<li>Bugfix: IN(NULL) didn''t return NULL in every case. Fixed.
<li>Bugfix: DATEDIFF didn''t work correctly for hour, minute and second if one of the dates was before 1970.
<li>SELECT EXCEPT (or MINUS) did not work for some cases. Fixed.
<li>DATEDIFF now returns a BIGINT and not an INT
<li>DATEADD didn''t work for milliseconds.
<li>Could not connect to a database that was closing at the same time.
<li>C-style block comments /* */ are not parsed correctly when they contain * or /
</ul>
For details see also the history. The plans for the next release are:
<ul>
<li>Bugfixes, write more tests, more bugfixes, more tests.
<li>Proposal for changed license.
<li>For other plans, see the new ''Roadmap'' part on the web site.
</ul>
');
INSERT INTO ITEM VALUES(4,
'New version available: 0.9 Beta / 2006-07-14', '2006-07-14 12:00:00',
'A new version of H2 is available for <a href="http://www.h2database.com">download</a>.
<br/>
<b>Changes and new functionality:</b>
<ul>
<li>The cache size is now measured in blocks and no longer in rows.
Manually setting the cache size is no longer necessary in most cases.
<li>CREATE VIEW now supports a column list: CREATE VIEW TESTV(A, B) AS ...
<li>New column IS_GENERATED in the metadata tables SEQUENCES and INDEXES.
<li>ResultSetMetaData.isNullable is now implemented.
<li>Optimization: data conversion of constants was not optimized.
<li>Optimization: deterministic subqueries are evaluated only once.
<li>Compatibility: ''T'', ''Y'', ''YES'', ''F'', ''N'', ''NO'' (case insensitive) can now also be converted to boolean.
<li>Compatibility: SUBSTRING(string FROM start FOR length).
<li>Compatibility: TRIM(whitespace FROM string).
<li>LIKE ... ESCAPE: The escape character may now also be an expression.
<li>IF EXISTS / IF NOT EXISTS implemented for the remaining CREATE / DROP statements.
<li>An exception was thrown if a scalar subquery returned no rows. Now NULL is returned.
<li>Objects of unknown type are no longer serialized to a byte array.
<li>Reduced jar file size: The regression tests are no longer included in the jar file.
</ul>
<b>Bugfixes:</b>
<ul>
<li>Issue #123: The connection to the server is lost if an abnormal exception occurs.
<li>Issue #124: Adding a column didn''t work when the table contains a referential integrity check.
<li>Issue #125: Foreign key constraints of local temporary tables are not dropped when the table is dropped.
<li>Issue #126: It is possible to create multiple primary keys for the same table.
<li>A few bugs in the CSV tool have been fixed.
</ul>
For details see also the history. The plans for the next release are:
<ul>
<li>Bugfixes, write more tests, more bugfixes, more tests.
<li>Proposal for changed license.
<li>For other plans, see the new ''Roadmap'' part on the web site.
</ul>
');
INSERT INTO ITEM VALUES(3,
'New version available: 0.9 Beta / 2006-07-01', '2006-07-01 12:00:00',
'A new version of H2 is available for <a href="http://www.h2database.com">download</a>.
<br/>
<b>Changes and new functionality:</b>
<ul>
<li>Reduced memory usage: implemented a String cache and improved the Value cache.
Now uses a weak reference to avoid OutOfMemory.
(however the row cache could still cause OutOfMemory).
<li>New functions: MEMORY_FREE() and MEMORY_USED().
<li>Newsfeed sample application (used to create the newsfeed and newsletter).
<li>Server: changed the public API to allow an application to deal easier with start problems.
</ul>
<b>Bugfixes:</b>
<ul>
<li>Issue #116: Server: reduces memory usage. Reduced number of cached objects per connection.
<li>Issue #117: Server.start...Server sometimes returned before the server was started. Solved.
<li>Issue #118: ALTER TABLE RENAME COLUMN didn''t work correctly.
<li>Issue #119: If a table with autoincrement column is created in another schema,
it was not possible to connect to the database again.
<li>Issue #120: Some ALTER TABLE statements didn''t work when the table was in another than the main schema. Fixed.
<li>Issue #121: Using a quoted table or alias name in front of a column name (SELECT "TEST".ID FROM TEST) didn''t work.
<li>Database names are no longer case sensitive for the Windows operating system,
because there the files names are not case sensitive.
<li>Issue #122: Using OFFSET in big result sets (disk buffered result sets) did not work. Fixed.
<li>Outer joins did not always use an index even if this was possible.
</ul>
For details see also the history. The plans for the next release are:
<ul>
<li>Bugfixes, write more tests, more bugfixes, more tests
<li>Proposal for changed license (still pending...)
<li>For other plans, see the new ''Roadmap'' part on the web site
</ul>
');
INSERT INTO ITEM VALUES(2,
'New version available: 0.9 Beta / 2006-06-16', '2006-06-16 12:00:00',
'A new version of H2 is available for <a href="http://www.h2database.com">download</a>.
<br/>
<b>Changes and new functionality:</b>
<ul>
<li>It''s now Beta version; don''t expect much added functionality until 1.0
<li>New XML encoding functions (XMLTEXT, XMLATTR, XMLNODE,...).
<li>New functions FORMATDATETIME and PARSEDATETIME
<li>Performance: improved opening of a large databases
<li>Performance: improved creating and opening encrypted databases
<li>Blob.getLength() and Clob.getLength() are now fast operations
<li>Documented ALTER TABLE DROP COLUMN
<li>Implemented DROP TRIGGER
<li>Calling Server.start...Server now waits until the server is ready
<li>If a connection is closed while there is still an operation running, this operation is stopped
Implemented distributing lob files into directories, and only keep up to 255 files in one directory.
However this is disabled by default; it will be enabled the next time the file format changes
(maybe not before 1.1). It can be enabled by the application by setting
Constants.LOB_FILES_IN_DIRECTORIES = true
</ul>
<b>Bugfixes:</b>
<ul>
<li>Issue #110: PreparedStatement.setCharacterStream
<li>Issue #111: The catalog name was not uppercase
<li>Issue #112: Two threads could not open the same database at the same time
<li>Issue #113: Drop is now restricted
<li>Issue #114: Support large index data size
<li>Issue #115: Lock timeout for three or more threads
</ul>
For details see also the history. The plans for the next release are:
<ul>
<li>Bugfixes, write more tests, more bugfixes, more tests
<li>Proposal for changed license (still pending...)
<li>For other plans, see the new ''Roadmap'' part on the web site
</ul>
');
INSERT INTO ITEM VALUES(1,
'New version available: 0.9 Alpha / 2006-06-02', '2006-06-02 12:00:00',
'A new version of H2 is available for <a href="http://www.h2database.com">download</a>.
<br/>
<b>Changes and new functionality:</b>
<ul>
<li>The GCJ version for Windows is no longer included in the download.
It was not stable in this release.
<li>ORDER BY now uses an index if possible.
Queries with LIMIT with ORDER BY
are faster when the index can be used.
<li>Statements containing LIKE are now re-compiled when executed.
Depending on the data, an index on the column is used or not.
<li>New option to disable automatic closing of a database
when the virtual machine exists.
Database URL: jdbc:h2:test;db_close_on_exit=false
<li>New event: DatabaseEventListener.closingDatabase()
<li>Connection.getCatalog() now returns the database name
<li>The function DATABASE() now return the short name
<li>Automatic starting of a web browser for Mac OS X should work now.
</ul>
<b>Security:</b>
<ul>
<li>TCP Server: Can now specifiy a password (tcpPassword).
<li>New option -ifExists for the TCP and ODBC server
to disallow creating new databases.
</ul>
<b>Bugfixes:</b>
<ul>
<li>Issue #103: Shutdown of a TCP Server from command line
didn''t always work.
<li>Issue #104: A HAVING condition on a column
that was not in the GROUP BY list didn''t work.
<li>Issue #105: RUNSCRIPT (the command) didn''t commit
after each command if autocommit was on.
<li>Issue #106: SET commands where not persisted
<li>Issue# 107: When executing scripts that contained inserts
with many columns, an OutOfMemory error could occur.
<li>Issue #108: There is a concurrency problem when multi threads
access the same database.
<li>Issue #109: ALTER TABLE ADD COLUMN can make
the database unusable.
</ul>
For details see also the history. The plans for the next release are:
<ul>
<li>Bugfixes, write more tests, more bugfixes, more tests
<li>Define which modules are alpha, beta and production quality
<li>Proposal for changed license (still pending...)
<li>For other plans, see the new ''Roadmap'' part on the web site
</ul>
');
SELECT 'newsfeed-rss.xml' FILE,
XMLSTARTDOC() ||
XMLNODE('rss', XMLATTR('version', '2.0'),
XMLNODE('channel', NULL,
XMLNODE('title', NULL, C.TITLE) ||
XMLNODE('link', NULL, C.LINK) ||
XMLNODE('description', NULL, C.DESC) ||
XMLNODE('language', NULL, C.LANGUAGE) ||
XMLNODE('pubDate', NULL, FORMATDATETIME(C.PUB, 'EEE, d MMM yyyy HH:mm:ss z', 'en', 'GMT')) ||
XMLNODE('lastBuildDate', NULL, FORMATDATETIME(C.LAST, 'EEE, d MMM yyyy HH:mm:ss z', 'en', 'GMT')) ||
GROUP_CONCAT(
XMLNODE('item', NULL,
XMLNODE('title', NULL, I.TITLE) ||
XMLNODE('link', NULL, C.LINK) ||
XMLNODE('description', NULL, XMLCDATA(I.TITLE))
)
ORDER BY I.ID DESC SEPARATOR '')
)
) CONTENT
FROM CHANNEL C, ITEM I
UNION
SELECT 'newsfeed-atom.xml' FILE,
XMLSTARTDOC() ||
XMLNODE('feed', XMLATTR('version', '0.3') || XMLATTR('xmlns', 'http://purl.org/atom/ns#') || XMLATTR('xml:lang', C.LANGUAGE),
XMLNODE('title', XMLATTR('type', 'text/plain') || XMLATTR('mode', 'escaped'), C.TITLE) ||
XMLNODE('author', NULL, XMLNODE('name', NULL, C.AUTHOR)) ||
XMLNODE('link', XMLATTR('rel', 'alternate') || XMLATTR('type', 'text/html') || XMLATTR('href', C.LINK), NULL) ||
XMLNODE('modified', NULL, FORMATDATETIME(C.LAST, 'yyyy-MM-dd''T''HH:mm:ss.SSS', 'en', 'GMT')) ||
GROUP_CONCAT(
XMLNODE('entry', NULL,
XMLNODE('title', XMLATTR('type', 'text/plain') || XMLATTR('mode', 'escaped'), I.TITLE) ||
XMLNODE('link', XMLATTR('rel', 'alternate') || XMLATTR('type', 'text/html') || XMLATTR('href', C.LINK), NULL) ||
XMLNODE('id', NULL, XMLTEXT(C.LINK || '/' || I.ID)) ||
XMLNODE('issued', NULL, FORMATDATETIME(I.ISSUED, 'yyyy-MM-dd''T''HH:mm:ss.SSS', 'en', 'GMT')) ||
XMLNODE('modified', NULL, FORMATDATETIME(I.ISSUED, 'yyyy-MM-dd''T''HH:mm:ss.SSS', 'en', 'GMT')) ||
XMLNODE('content', XMLATTR('type', 'text/html') || XMLATTR('mode', 'escaped'), XMLCDATA(I.DESC))
)
ORDER BY I.ID DESC SEPARATOR '')
) CONTENT
FROM CHANNEL C, ITEM I
UNION
SELECT '-newsletter-' FILE, I.DESC CONTENT FROM ITEM I WHERE I.ID = (SELECT MAX(ID) FROM ITEM)
\ No newline at end of file
<?xml version="1.0"?>
<rss version="2.0">
<channel>
<title>H2 Database Engine</title>
<link>http://www.h2database.com</link>
<description>H2 Database Engine</description>
<language>en-us</language>
<pubDate>Thu, 15 Jun 2006 05:59:06 GMT</pubDate>
<lastBuildDate>Thu, 15 Jun 2006 05:59:06 GMT</lastBuildDate>
<item>
<title>New version available: 0.9 Alpha / 2006-06-02</title>
<link>http://www.h2database.com</link>
<description>
<![CDATA[A new version of H2 is available for download at http://www.h2database.com
Changes and new functionality:
- The GCJ version for Windows is no longer included in the download.
It was not stable in this release.
- ORDER BY now uses an index if possible.
Queries with LIMIT with ORDER BY
are faster when the index can be used.
- Statements containing LIKE are now re-compiled when executed.
Depending on the data, an index on the column is used or not.
- New option to disable automatic closing of a database
when the virtual machine exits.
Database URL: jdbc:h2:test;db_close_on_exit=false
- New event: DatabaseEventListener.closingDatabase()
- Connection.getCatalog() now returns the database name
- The function DATABASE() now return the short name
- Automatic starting of a web browser for Mac OS X should work now.
Security:
- TCP Server: Can now specifiy a password (tcpPassword).
- New option -ifExists for the TCP and ODBC server
to disallow creating new databases.
Bugfixes:
- Issue #103: Shutdown of a TCP Server from command line
didn't always work.
- Issue #104: A HAVING condition on a column
that was not in the GROUP BY list didn't work.
- Issue #105: RUNSCRIPT (the command) didn't commit
after each command if autocommit was on.
- Issue #106: SET commands where not persisted
- Issue# 107: When executing scripts that contained inserts
with many columns, an OutOfMemory error could occur.
- Issue #108: There is a concurrency problem when multi threads
access the same database.
- Issue #109: ALTER TABLE ADD COLUMN can make
the database unusable.
For details see also the history. The plans for the next release are:
- Bugfixes, write more tests, more bugfixes, more tests
- Define which modules are alpha, beta and production quality
- Proposal for changed license (still pending...)
- For other plans, see the new 'Roadmap' part on the web site
]]>
</description>
</item>
</channel>
</rss>
\ No newline at end of file
/*
* 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;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import org.h2.engine.Constants;
import org.h2.server.TcpServer;
import org.h2.test.jdbc.*;
import org.h2.test.db.*;
import org.h2.test.server.TestNestedLoop;
import org.h2.test.synth.TestBtreeIndex;
import org.h2.test.synth.TestCrashAPI;
import org.h2.test.synth.TestJoin;
import org.h2.test.synth.TestKill;
import org.h2.test.synth.TestMulti;
import org.h2.test.synth.TestRandomSQL;
import org.h2.test.synth.TestSynth;
import org.h2.test.unit.TestBitField;
import org.h2.test.unit.TestCache;
import org.h2.test.unit.TestCompress;
import org.h2.test.unit.TestDataPage;
import org.h2.test.unit.TestExit;
import org.h2.test.unit.TestFileLock;
import org.h2.test.unit.TestIntArray;
import org.h2.test.unit.TestIntIntHashMap;
import org.h2.test.unit.TestOverflow;
import org.h2.test.unit.TestPattern;
import org.h2.test.unit.TestReader;
import org.h2.test.unit.TestSampleApps;
import org.h2.test.unit.TestScriptReader;
import org.h2.test.unit.TestSecurity;
import org.h2.test.unit.TestStreams;
import org.h2.test.unit.TestStringCache;
import org.h2.test.unit.TestStringUtils;
import org.h2.test.unit.TestTools;
import org.h2.test.unit.TestValueHashMap;
import org.h2.tools.DeleteDbFiles;
import org.h2.tools.Server;
import org.h2.util.StringUtils;
/**
* @author Thomas
*/
public class TestAll {
// Snippets to run test code:
// java -cp .;%H2DRIVERS% org.h2.test.TestAll
// java -Xrunhprof:cpu=samples,depth=8 org.h2.test.TestAll
// java -Xrunhprof:heap=sites,depth=8 org.h2.test.TestAll
// C:\Programme\Java\jdk1.6.beta\bin\java
/*
Random test:
cd bin
del *.db
start cmd /k "java -cp .;%H2DRIVERS% org.h2.test.TestAll join >testJoin.txt"
start cmd /k "java org.h2.test.TestAll crash >testCrash.txt"
start cmd /k "java org.h2.test.TestAll synth >testSynth.txt"
start cmd /k "java org.h2.test.TestAll all >testAll.txt"
start cmd /k "java org.h2.test.TestAll random >testRandom.txt"
start cmd /k "java org.h2.test.TestAll btree >testBtree.txt"
java -Xmx512m -Xrunhprof:cpu=samples,depth=8 org.h2.tools.RunScript -url jdbc:h2:test;TRACE_LEVEL_FILE=3;LOG=2;MAX_LOG_SIZE=1000;DATABASE_EVENT_LISTENER='org.h2.samples.ShowProgress' -user sa -script test.sql
*/
public boolean smallLog, big, networked, memory, ssl, textStorage, diskUndo, diskResult, deleteIndex, traceSystemOut;
public boolean codeCoverage;
public int logMode = 1, traceLevelFile, throttle;
public String cipher;
public boolean traceTest, stopOnError;
public boolean jdk14 = true;
private Server server;
private int oldCacheMin;
public static void main(String[] args) throws Exception {
long time = System.currentTimeMillis();
TestAll test = new TestAll();
test.printSystem();
// code coverage
//max / hibernate
// Sorry, a typo by me. I don't specify any database name and then when
// I call getTables I get a catalog name that I pass on to getColumns and
// here getColumns does not return anything unless I null out the return
// catalog name.
// Check if new Hibernate dialect for H2 is ok
// http://opensource.atlassian.com/projects/hibernate/browse/HHH-2300
// open JPA test - submit patch
// ant mavenUploadLocal
// d:\data\h2test\openjpa\openjpa-persistence-jdbc\src\test\resources\META-INF\persistence.xml
// <!-- <property name="openjpa.ConnectionProperties"
// value="DriverClassName=org.apache.derby.jdbc.EmbeddedDriver,Url=jdbc:derby:target/database/openjpa-test-database;create=true,MaxActive=100,MaxWait=10000,TestOnBorrow=true"/>
//-->
// <property name="openjpa.ConnectionProperties"
// value="DriverClassName=org.h2.Driver,Url=jdbc:h2:c:/temp/openjpa,MaxActive=100,MaxWait=10000,TestOnBorrow=true"/>
// D:\data\h2test\openjpa\openjpa-persistence-jdbc>mvn test
// add H2 to maven
// OSGi Bundle (see Forum)
// Test and document JDK 1.6 QueryObjectFactory
// submit hibernate dialect
// clean build path (remove hibernate librarires)
// test with PostgreSQL Version 8.2
// create table testoe(id int primary key, name varchar(255))
// create user oe identified by merlin
// CREATE SCHEMA AUTHORIZATION oe
// CREATE TABLE new_product
// (color VARCHAR2(10) PRIMARY KEY, quantity NUMBER)
// CREATE VIEW new_product_view
// AS SELECT color, quantity FROM new_product WHERE color = 'RED'
// GRANT select ON new_product_view TO hr;
// http://dev.helma.org/Wiki/RhinoLoader
// use version numbers 1.0.4 and so on
// Fulltext search: Use reader for CLOB data, special reader tokenizer
// Checkstyle to verify HTML docs
// test multithreading access to blobs (one thread reads from the inputstream, the other deletes the row using the same connection)
// Dezign for Databases (http://www.datanamic.com
// SET LOCK_MODE 3 not persistent, document how to set it in the database URL
// http://eclipse-cs.sourceforge.net/
// http://andrei.gmxhome.de/anyedit/links.html
// Constants.ALLOW_EMTPY_BTREE_PAGES = true
// Test Hibernate / read committed transaction isolation:
// Data records retrieved by a query are not prevented from modification by some other transaction.
// Non-repeatable reads may occur, meaning data retrieved in a SELECT statement may be modified
// by some other transaction when it commits. In this isolation level, read locks are not acquired on selected data.
// test with garbage at the end of the log file (must be consistently detected as such)
// describe differences between databases (Migration Guide; HSQLDB most important)
// Maven
// http://maven.apache.org/guides/mini/guide-ibiblio-upload.html
// test LIKE: compare against other databases
// autocomplete: if I type the name of a table that does not exist (should say: syntax not supported)
// autocomplete: schema support: "Other Grammar","Table Expression","{[schemaName.]tableName | (select)} [[AS] newTableAlias]
// TestRandomSQL is too random; most statements fails
// extend the random join test that compared the result against PostgreSQL
// Donate a translation: I am looking for people who would help translating the H2 Console into other languages. Please tell me if you think you can help
// extend TestJoin
// TEST CASE FOR: embedded mode, create blob+clob, then use server mode, read blob+clob / update blob+clob
// long running test with the same database
// repeatable test with a very big database (making backups of the database files)
// check performance monitor Avg. Disk Write Queue Length, disk writes
// test case where the GCJ problem can be repeated
// OpenOffice docs:
// - Stop OpenOffice, including the autostart
// - Copy h2.jar into the directory <OpenOffice>\program\classes
// - Start OpenOffice Base
// - Connect to an existing database, select JDBC, [Next]
// - Datasource URL: jdbc:h2:c:/temp/test;TRACE_LEVEL_FILE=3
// - JDBC driver class: org.h2.Driver [Test class]
if(args.length>0) {
if("crash".equals(args[0])) {
new TestCrashAPI().runTest(test);
} else if("synth".equals(args[0])) {
new TestSynth().runTest(test);
} else if("kill".equals(args[0])) {
new TestKill().runTest(test);
} else if("random".equals(args[0])) {
new TestRandomSQL().runTest(test);
} else if("join".equals(args[0])) {
new TestJoin().runTest(test);
} else if("btree".equals(args[0])) {
new TestBtreeIndex().runTest(test);
} else if("all".equals(args[0])) {
test.testEverything();
} else if("codeCoverage".equals(args[0])) {
test.testCodeCoverage();
} else if("multiThread".equals(args[0])) {
new TestMulti().runTest(test);
}
} else {
test.runTests();
}
System.out.println("done ("+(System.currentTimeMillis()-time)+" ms)");
}
void runTests() throws Exception {
// TODO test set lock_mode=0, 1; max_trace_file_size; modes; collation; assert
// TODO test shutdown immediately
// smallLog = big = networked = memory = ssl = textStorage = diskResult = deleteIndex = traceSystemOut = false;
// logMode = 1; traceLevelFile = throttle = 0;
// deleteIndex = textStorage = true;
// cipher = null;
// codeCoverage = true;
// memory = true;
// new TestSpeed().runTest(this);
// new TestSpeed().runTest(this);
// new TestSpeed().runTest(this);
// new TestSpeed().runTest(this);
// smallLog = big = networked = memory = ssl = textStorage = diskResult = deleteIndex = traceSystemOut = diskUndo = false;
// traceLevelFile = throttle = 0;
// big = true;
// memory = false;
//
testQuick();
testCombination();
}
void testCodeCoverage() throws Exception {
this.codeCoverage = true;
runTests();
}
void testQuick() throws Exception {
smallLog = big = networked = memory = ssl = textStorage = diskResult = deleteIndex = traceSystemOut = diskUndo = false;
traceLevelFile = throttle = 0;
logMode = 1;
cipher = null;
testAll();
}
void testEverything() throws Exception {
for(int c = 0; c < 3; c++) {
if(c == 0) {
cipher = null;
} else if(c==1) {
cipher = "XTEA";
} else {
cipher = "AES";
}
for(int a = 0; a < 256; a++) {
smallLog = (a & 1) != 0;
big = (a & 2) != 0;
networked = (a & 4) != 0;
memory = (a & 8) != 0;
ssl = (a & 16) != 0;
textStorage = (a & 32) != 0;
diskResult = (a & 64) != 0;
deleteIndex = (a & 128) != 0;
for(logMode = 0; logMode < 3; logMode++) {
traceLevelFile = logMode;
TestBase.printTime("cipher:" + cipher +" a:" +a+" logMode:"+logMode);
testAll();
}
}
}
}
void testCombination() throws Exception {
smallLog = big = networked = memory = ssl = textStorage = diskResult = deleteIndex = traceSystemOut = false;
traceLevelFile = throttle = 0;
logMode = 1;
cipher = null;
testAll();
diskUndo = false;
smallLog = false;
big = false;
networked = true;
memory = true;
ssl = false;
textStorage = true;
diskResult = deleteIndex = traceSystemOut = false;
traceLevelFile = throttle = 0;
logMode = 1;
cipher = null;
testAll();
big = false;
smallLog = false;
networked = false;
memory = false;
ssl = false;
textStorage = false;
diskResult = false;
deleteIndex = false;
traceSystemOut = false;
logMode = 2;
traceLevelFile = 0;
throttle = 0;
cipher = null;
testAll();
diskUndo = true;
smallLog = false;
big = networked = memory = ssl = false;
textStorage = true;
diskResult = true;
deleteIndex = true;
traceSystemOut = false;
logMode = 1;
traceLevelFile = 3;
throttle = 1;
cipher = "XTEA";
testAll();
diskUndo = false;
big = true;
smallLog = false;
networked = false;
memory = false;
ssl = false;
textStorage = false;
diskResult = false;
deleteIndex = false;
traceSystemOut = false;
logMode = 1;
traceLevelFile = 1;
throttle = 0;
cipher = null;
testAll();
big = true;
smallLog = true;
networked = true;
memory = false;
ssl = true;
textStorage = false;
diskResult = false;
deleteIndex = false;
traceSystemOut = false;
logMode = 2;
traceLevelFile = 2;
throttle = 0;
cipher = null;
testAll();
big = true;
smallLog = false;
networked = true;
memory = false;
ssl = false;
textStorage = false;
diskResult = false;
deleteIndex = false;
traceSystemOut = false;
logMode = 0;
traceLevelFile = 0;
throttle = 0;
cipher = "AES";
testAll();
}
void testAll() throws Exception {
DeleteDbFiles.execute(TestBase.BASE_DIR, null, true);
testDatabase();
testUnit();
DeleteDbFiles.execute(TestBase.BASE_DIR, null, true);
}
void testUnit() {
new TestBitField().runTest(this);
new TestCompress().runTest(this);
new TestDataPage().runTest(this);
new TestExit().runTest(this);
new TestFileLock().runTest(this);
new TestIntArray().runTest(this);
new TestIntIntHashMap().runTest(this);
new TestOverflow().runTest(this);
new TestPattern().runTest(this);
new TestReader().runTest(this);
new TestSampleApps().runTest(this);
new TestScriptReader().runTest(this);
new TestSecurity().runTest(this);
new TestStreams().runTest(this);
new TestStringCache().runTest(this);
new TestStringUtils().runTest(this);
new TestTools().runTest(this);
new TestValueHashMap().runTest(this);
}
void testDatabase() throws Exception {
System.out.println("test big:"+big+" net:"+networked+" cipher:"+cipher+" memory:"+memory+" log:"+logMode+" diskResult:"+diskResult);
beforeTest();
// db
new TestScript().runTest(this);
new TestScriptSimple().runTest(this);
new TestAutoRecompile().runTest(this);
new TestBatchUpdates().runTest(this);
new TestBigDb().runTest(this);
new TestBigResult().runTest(this);
new TestCases().runTest(this);
new TestCheckpoint().runTest(this);
new TestCluster().runTest(this);
new TestCompatibility().runTest(this);
new TestCsv().runTest(this);
new TestFunctions().runTest(this);
new TestIndex().runTest(this);
new TestLinkedTable().runTest(this);
new TestListener().runTest(this);
new TestLob().runTest(this);
new TestLogFile().runTest(this);
new TestMemoryUsage().runTest(this);
new TestMultiConn().runTest(this);
new TestMultiDimension().runTest(this);
new TestMultiThread().runTest(this);
new TestOpenClose().runTest(this);
new TestOptimizations().runTest(this);
new TestPowerOff().runTest(this);
new TestReadOnly().runTest(this);
new TestRights().runTest(this);
new TestRunscript().runTest(this);
new TestSQLInjection().runTest(this);
new TestSequence().runTest(this);
new TestSpaceReuse().runTest(this);
new TestSpeed().runTest(this);
new TestTempTables().runTest(this);
new TestTransaction().runTest(this);
new TestTriggersConstraints().runTest(this);
new TestTwoPhaseCommit().runTest(this);
// server
new TestNestedLoop().runTest(this);
// jdbc
new TestCancel().runTest(this);
new TestDataSource().runTest(this);
new TestManyJdbcObjects().runTest(this);
new TestMetaData().runTest(this);
new TestNativeSQL().runTest(this);
new TestPreparedStatement().runTest(this);
new TestResultSet().runTest(this);
new TestStatement().runTest(this);
new TestTransactionIsolation().runTest(this);
new TestUpdatableResultSet().runTest(this);
afterTest();
}
public void beforeTest() throws SQLException {
if(networked) {
TcpServer.LOG_INTERNAL_ERRORS = true;
String[] args = ssl ? new String[]{"-tcpSSL", "true"} : new String[0];
server = Server.createTcpServer(args);
try {
server.start();
} catch(SQLException e) {
System.out.println("FAIL: can not start server (may already be running)");
server = null;
}
}
if(this.diskResult) {
oldCacheMin = Constants.CACHE_MIN_RECORDS;
Constants.CACHE_MIN_RECORDS = 0;
}
}
public void afterTest() {
if(networked && server != null) {
server.stop();
}
if(this.diskResult) {
Constants.CACHE_MIN_RECORDS = oldCacheMin;
}
}
private void printSystem() {
Properties prop = System.getProperties();
System.out.println("Java: " +
prop.getProperty("java.runtime.version") + ", " +
prop.getProperty("java.vm.name")+", " +
prop.getProperty("java.vendor"));
System.out.println("Env: " +
prop.getProperty("os.name") + ", " +
prop.getProperty("os.arch")+", "+
prop.getProperty("os.version")+", "+
prop.getProperty("sun.os.patch.level")+", "+
prop.getProperty("file.separator")+" "+
prop.getProperty("path.separator")+" "+
StringUtils.javaEncode( prop.getProperty("line.separator"))+" "+
prop.getProperty("user.country") + " " +
prop.getProperty("user.language") + " " +
prop.getProperty("user.variant")+" "+
prop.getProperty("file.encoding"));
}
}
/*
* 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;
import java.io.File;
import java.io.Reader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.text.SimpleDateFormat;
import java.util.Properties;
import org.h2.jdbc.JdbcConnection;
import org.h2.tools.DeleteDbFiles;
/**
* @author Thomas
*/
public abstract class TestBase {
protected static String BASE_DIR = "data";
protected TestAll config;
private long start;
protected void startServerIfRequired() throws SQLException {
config.beforeTest();
}
protected void stopServerIfRequired() {
config.afterTest();
}
public TestBase init(TestAll conf) throws Exception {
this.config = conf;
return this;
}
public void testCase(int i) throws Exception {
// do nothing
}
public void runTest(TestAll conf) {
try {
init(conf);
start = System.currentTimeMillis();
printlnWithTime("start");
test();
println("done ");
} catch(Exception e) {
println("FAIL " + e.toString());
e.printStackTrace();
if(config.stopOnError) {
throw new Error("ERROR");
}
}
}
public Connection getConnection(String name) throws Exception {
return getConnectionInternal(getURL(name, true), getUser(), getPassword());
}
protected Connection getConnection(String name, String user, String password) throws Exception {
return getConnectionInternal(getURL(name, false), user, password);
}
protected String getPassword() {
return "123";
}
private void deleteIndexFiles(String name) throws SQLException {
if(name.indexOf(";")>0) {
name = name.substring(0, name.indexOf(';'));
}
name += ".index.db";
if(new File(name).canWrite()) {
new File(name).delete();
}
}
protected String getURL(String name, boolean admin) throws SQLException {
String url;
if(name.startsWith("jdbc:")) {
return name;
}
if(config.memory) {
url = "mem:" + name;
} else {
if(!name.startsWith("inmemory:") && !name.startsWith(BASE_DIR + "/")) {
name = BASE_DIR + "/" + name;
}
if(config.deleteIndex) {
deleteIndexFiles(name);
}
if(config.networked) {
if(config.ssl) {
url = "ssl://localhost:9092/" + name;
} else {
url = "tcp://localhost:9092/" + name;
}
} else {
url = name;
}
if(config.traceSystemOut) {
url += ";TRACE_LEVEL_SYSTEM_OUT=2";
}
if(config.traceLevelFile>0 && admin) {
url += ";TRACE_LEVEL_FILE="+config.traceLevelFile;
}
}
if(config.throttle>0) {
url += ";THROTTLE=" + config.throttle;
}
if(config.textStorage) {
url += ";STORAGE=TEXT";
}
url += ";LOCK_TIMEOUT=50";
if(admin) {
url += ";LOG=" + config.logMode;
}
if(config.smallLog && admin) {
url += ";MAX_LOG_SIZE=1";
}
if(config.diskUndo && admin) {
url += ";MAX_MEMORY_UNDO=3";
}
if(config.diskResult && admin) {
url += ";MAX_MEMORY_ROWS=100;CACHE_SIZE=0";
}
return "jdbc:h2:"+url;
}
private Connection getConnectionInternal(String url, String user, String password) throws Exception {
Class.forName("org.h2.Driver");
// url += ";DEFAULT_TABLE_TYPE=1";
// Class.forName("org.hsqldb.jdbcDriver");
// return DriverManager.getConnection("jdbc:hsqldb:" + name, "sa", "");
Connection conn;
if(config.cipher != null) {
url += ";cipher=" + config.cipher;
password = "filePassword " + password;
Properties info = new Properties();
info.setProperty("user", user);
info.put("password", password.toCharArray());
conn = DriverManager.getConnection(url, info);
} else {
conn = DriverManager.getConnection(url, user, password);
}
return conn;
}
protected int getSize(int small, int big) throws Exception {
return config.big ? big : small;
}
protected String getUser() {
return "sa";
}
protected void trace(int x) {
trace(""+x);
}
public void trace(String s) {
if(config.traceTest) {
println(s);
}
}
protected void traceMemory() {
if(config.traceTest) {
trace("mem="+getMemoryUsed());
}
}
public void printTimeMemory(String s, long time) {
if(config.big) {
println(time+" ms; " + getMemoryUsed()+" MB: " + s);
}
}
public static int getMemoryUsed() {
Runtime rt = Runtime.getRuntime();
long memory = Long.MAX_VALUE;
for(int i=0; i<8; i++) {
rt.gc();
long memNow = rt.totalMemory() - rt.freeMemory();
if(memNow >= memory) {
break;
}
memory = memNow;
}
int mb = (int)(memory / 1024 / 1024);
return mb;
}
protected void error(String string) throws Exception {
println(string);
throw new Exception(string);
}
protected void println(String s) {
printlnWithTime(s);
}
private void printlnWithTime(String s) {
long time = System.currentTimeMillis() - start;
String t = " " + time;
t = t.substring(t.length()-6);
System.out.println(s+" ("+t+" ms) "+getClass().getName());
}
protected static void printTime(String s) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(new java.util.Date()) + " " + s);
}
protected void deleteDb(String name) throws Exception {
new DeleteDbFiles().processFiles(BASE_DIR, name, false);
}
protected void deleteDb(String dir, String name) throws Exception {
new DeleteDbFiles().processFiles(dir, name, false);
}
public abstract void test() throws Exception;
public void check(int a, int b) throws Exception {
if(a != b) {
error("int a: "+a+" b: "+b);
}
}
protected void check(byte[] a, byte[] b) throws Exception {
check(a.length == b.length);
for(int i=0; i<a.length; i++) {
if(a[i] != b[i]) {
error("byte["+i+"]: a="+(int)a[i]+" b="+(int)b[i]);
}
}
}
protected void check(String a, String b) throws Exception {
if(a==null && b==null) {
return;
} else if(a==null || b==null) {
error("string a: "+a+" b: "+b);
}
if(!a.equals(b)) {
for(int i=0; i<a.length(); i++) {
String s = a.substring(0, i);
if(!b.startsWith(s)) {
s = s.substring(0, i) + "<*>" + s.substring(i);
break;
}
}
error("string a: "+a+" ("+a.length()+") b: "+b+" (" + b.length() +")");
}
}
protected void checkFalse(String a, String b) throws Exception {
if(a.equals(b)) {
error("string false a: "+a+" b: "+b);
}
}
protected void check(long a, long b) throws Exception {
if(a != b) {
error("long a: "+a+" b: "+b);
}
}
protected void checkSmaller(long a, long b) throws Exception {
if(a >= b) {
error("a: "+a+" is not smaller than b: "+b);
}
}
protected void check(double a, double b) throws Exception {
if(a != b) {
error("double a: "+a+" b: "+b);
}
}
protected void check(float a, float b) throws Exception {
if(a != b) {
error("float a: "+a+" b: "+b);
}
}
protected void check(boolean a, boolean b) throws Exception {
if(a != b) {
error("boolean a: "+a+" b: "+b);
}
}
protected void check(boolean value) throws Exception {
if(!value) {
error("expected: true got: false");
}
}
protected void checkFalse(boolean value) throws Exception {
if(value) {
error("expected: false got: true");
}
}
protected void checkResultRowCount(ResultSet rs, int expected) throws Exception {
int i=0;
while(rs.next()) {
i++;
}
check(i, expected);
}
protected void checkSingleValue(Statement stat, String sql, int value) throws Exception {
ResultSet rs = stat.executeQuery(sql);
check(rs.next());
check(rs.getInt(1), value);
checkFalse(rs.next());
}
protected void testResultSetMeta(ResultSet rs, int columncount, String[] labels,
int[] datatypes, int[] precision, int[] scale) throws Exception {
ResultSetMetaData meta = rs.getMetaData();
int cc = meta.getColumnCount();
if (cc != columncount) {
error("result set contains " + cc + " columns not " + columncount);
}
for (int i = 0; i < columncount; i++) {
if (labels != null) {
String l = meta.getColumnLabel(i + 1);
if (!labels[i].equals(l)) {
error("column label " + i + " is " + l + " not "
+ labels[i]);
}
}
if (datatypes != null) {
int t = meta.getColumnType(i + 1);
if (datatypes[i] != t) {
error("column datatype " + i + " is " + t + " not "
+ datatypes[i] + " (prec="
+ meta.getPrecision(i + 1) + " scale="
+ meta.getScale(i + 1) + ")");
}
String typeName = meta.getColumnTypeName(i+1);
String className = meta.getColumnClassName(i+1);
switch(t) {
case Types.INTEGER:
check(typeName, "INTEGER");
check(className, "java.lang.Integer");
break;
case Types.VARCHAR:
check(typeName, "VARCHAR");
check(className, "java.lang.String");
break;
case Types.SMALLINT:
check(typeName, "SMALLINT");
check(className, "java.lang.Short");
break;
case Types.TIMESTAMP:
check(typeName, "TIMESTAMP");
check(className, "java.sql.Timestamp");
break;
case Types.DECIMAL:
check(typeName, "DECIMAL");
check(className, "java.math.BigDecimal");
break;
}
}
if (precision != null) {
int p = meta.getPrecision(i + 1);
if (precision[i] != p) {
error("column precision " + i + " is " + p + " not "
+ precision[i]);
}
}
if (scale != null) {
int s = meta.getScale(i + 1);
if (scale[i] != s) {
error("column scale " + i + " is " + s + " not " + scale[i]);
}
}
}
}
protected void testResultSetOrdered(ResultSet rs, String[][] data) throws Exception {
testResultSet(true, rs, data);
}
void testResultSetUnordered(ResultSet rs, String[][] data) throws Exception {
testResultSet(false, rs, data);
}
void testResultSet(boolean ordered, ResultSet rs, String[][] data)
throws Exception {
int len = rs.getMetaData().getColumnCount();
int rows = data.length;
if (rows == 0) {
// special case: no rows
if (rs.next()) {
error("testResultSet expected rowcount:" + rows + " got:0");
}
}
int len2 = data[0].length;
if (len < len2) {
error("testResultSet expected columncount:" + len2 + " got:" + len);
}
for (int i = 0; i < rows; i++) {
if (!rs.next()) {
error("testResultSet expected rowcount:" + rows + " got:" + i);
}
String[] row = getData(rs, len);
if (ordered) {
String[] good = data[i];
if (!testRow(good, row, good.length)) {
error("testResultSet row not equal, got:\n"
+ formatRow(row) + "\n" + formatRow(good));
}
} else {
boolean found = false;
for (int j = 0; j < rows; j++) {
String[] good = data[i];
if (testRow(good, row, good.length)) {
found = true;
break;
}
}
if (!found) {
error("testResultSet no match for row:" + formatRow(row));
}
}
}
if (rs.next()) {
String[] row = getData(rs, len);
error("testResultSet expected rowcount:" + rows + " got:>="
+ (rows + 1) + " data:" + formatRow(row));
}
}
boolean testRow(String[] a, String[] b, int len) {
for (int i = 0; i < len; i++) {
String sa = a[i];
String sb = b[i];
if (sa == null || sb == null) {
if (sa != sb) {
return false;
}
} else {
if (!sa.equals(sb)) {
return false;
}
}
}
return true;
}
String[] getData(ResultSet rs, int len) throws SQLException {
String[] data = new String[len];
for (int i = 0; i < len; i++) {
data[i] = rs.getString(i + 1);
// just check if it works
rs.getObject(i + 1);
}
return data;
}
String formatRow(String[] row) {
String sb = "";
for (int i = 0; i < row.length; i++) {
sb += "{" + row[i] + "}";
}
return "{" + sb + "}";
}
protected void crash(Connection conn) throws Exception {
((JdbcConnection)conn).setPowerOffCount(1);
try {
conn.createStatement().execute("SET WRITE_DELAY 0");
conn.createStatement().execute("CREATE TABLE AAA(ID INT)");
error("should be crashed already");
} catch(SQLException e) {
// expected
}
try {
conn.close();
} catch(SQLException e) {
// ignore
}
}
protected String readString(Reader reader) throws Exception {
if(reader==null) {
return null;
}
StringBuffer buffer=new StringBuffer();
try {
while(true) {
int c=reader.read();
if(c==-1) {
break;
}
buffer.append((char)c);
}
return buffer.toString();
} catch(Exception e) {
check(false);
return null;
}
}
protected void checkNotGeneralException(SQLException e) throws Exception {
if(e!=null && e.getSQLState().startsWith("HY000")) {
e.printStackTrace();
error("Unexpected General error: " + e.toString());
}
}
protected void check(Integer a, Integer b) throws Exception {
if(a == null || b == null) {
check(a==b);
} else {
check(a.intValue(), b.intValue());
}
}
}
/*
* 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.bench;
public interface Bench {
void init(Database db, int size) throws Exception;
void run() throws Exception;
String getName();
}
/*
* 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.bench;
import java.math.BigDecimal;
import java.sql.*;
import java.util.Random;
/**
* See also: http://www.tpc.org/tpca/spec/tpca_current.pdf
*/
public class BenchA implements Bench {
private Database db;
private int branches;
private int tellers = branches * 20;
private int accounts = branches * 100;
private int size;
private static final String FILLER = "abcdefghijklmnopqrstuvwxyz";
private static final int DELTA = 10000;
public void init(Database db, int size) throws Exception {
this.db = db;
this.size = size;
int scale = 1;
accounts = size * 50;
tellers = Math.max(accounts / 10, 1);
branches = Math.max(tellers / 10, 1);
db.start(this, "Init");
db.openConnection();
db.dropTable("BRANCHES");
db.dropTable("BRANCHES");
db.dropTable("TELLERS");
db.dropTable("ACCOUNTS");
db.dropTable("HISTORY");
String[] create = { "CREATE TABLE BRANCHES(BID INT NOT NULL PRIMARY KEY, BBALANCE DECIMAL(15,2), FILLER VARCHAR(88))",
"CREATE TABLE TELLERS(TID INT NOT NULL PRIMARY KEY, BID INT, TBALANCE DECIMAL(15,2), FILLER VARCHAR(84))",
"CREATE TABLE ACCOUNTS(AID INT NOT NULL PRIMARY KEY, BID INT, ABALANCE DECIMAL(15,2), FILLER VARCHAR(84))",
"CREATE TABLE HISTORY(TID INT, BID INT, AID INT, DELTA DECIMAL(15,2), HTIME DATETIME, FILLER VARCHAR(40))" };
for (int i = 0; i < create.length; i++) {
db.update(create[i]);
}
PreparedStatement prep;
db.setAutoCommit(false);
int commitEvery = 1000;
prep = db.prepare("INSERT INTO BRANCHES(BID,BBALANCE,FILLER) VALUES(?,10000.00,'" + FILLER + "')");
for (int i = 0; i < branches * scale; i++) {
prep.setInt(1, i);
db.update(prep);
if(i%commitEvery==0) {
db.commit();
}
}
db.commit();
prep = db.prepare("INSERT INTO TELLERS(TID,BID,TBALANCE,FILLER) VALUES(?,?,10000.00,'" + FILLER + "')");
for (int i = 0; i < tellers * scale; i++) {
prep.setInt(1, i);
prep.setInt(2, i / tellers);
db.update(prep);
if(i%commitEvery==0) {
db.commit();
}
}
db.commit();
int len = accounts * scale;
prep = db.prepare("INSERT INTO ACCOUNTS(AID,BID,ABALANCE,FILLER) VALUES(?,?,10000.00,'" + FILLER + "')");
for (int i = 0; i < len; i++) {
prep.setInt(1, i);
prep.setInt(2, i / accounts);
db.update(prep);
if(i%commitEvery==0) {
db.commit();
}
}
db.commit();
db.closeConnection();
db.end();
db.start(this, "Open/Close");
db.openConnection();
db.closeConnection();
db.end();
}
public void run() throws Exception {
db.start(this, "Transactions");
db.openConnection();
processTransactions();
db.closeConnection();
db.end();
db.openConnection();
processTransactions();
db.logMemory(this, "Memory Usage");
db.closeConnection();
}
private void processTransactions() throws Exception {
Random random = db.getRandom();
int branch = random.nextInt(branches);
int teller = random.nextInt(tellers);
int transactions = size * 30;
PreparedStatement updateAccount = db.prepare("UPDATE ACCOUNTS SET ABALANCE=ABALANCE+? WHERE AID=?");
PreparedStatement selectBalance = db.prepare("SELECT ABALANCE FROM ACCOUNTS WHERE AID=?");
PreparedStatement updateTeller = db.prepare("UPDATE TELLERS SET TBALANCE=TBALANCE+? WHERE TID=?");
PreparedStatement updateBranch = db.prepare("UPDATE BRANCHES SET BBALANCE=BBALANCE+? WHERE BID=?");
PreparedStatement insertHistory = db.prepare("INSERT INTO HISTORY(AID,TID,BID,DELTA,HTIME,FILLER) VALUES(?,?,?,?,?,?)");
int accountsPerBranch = accounts / branches;
db.setAutoCommit(false);
for (int i = 0; i < transactions; i++) {
int account;
if (random.nextInt(100) < 85) {
account = random.nextInt(accountsPerBranch) + branch * accountsPerBranch;
} else {
account = random.nextInt(accounts);
}
int max = BenchA.DELTA;
// delta: -max .. +max
BigDecimal delta = new BigDecimal("" + (random.nextInt(max * 2) - max));
long current = System.currentTimeMillis();
updateAccount.setBigDecimal(1, delta);
updateAccount.setInt(2, account);
db.update(updateAccount);
updateTeller.setBigDecimal(1, delta);
updateTeller.setInt(2, teller);
db.update(updateTeller);
updateBranch.setBigDecimal(1, delta);
updateBranch.setInt(2, branch);
db.update(updateBranch);
selectBalance.setInt(1, account);
db.queryReadResult(selectBalance);
insertHistory.setInt(1, account);
insertHistory.setInt(2, teller);
insertHistory.setInt(3, branch);
insertHistory.setBigDecimal(4, delta);
// TODO convert: should be able to convert date to timestamp (by using 0 for remaining fields)
// insertHistory.setDate(5, new java.sql.Date(current));
insertHistory.setTimestamp(5, new java.sql.Timestamp(current));
insertHistory.setString(6, BenchA.FILLER);
db.update(insertHistory);
db.commit();
}
updateAccount.close();
selectBalance.close();
updateTeller.close();
updateBranch.close();
insertHistory.close();
}
public String getName() {
return "BenchA";
}
}
/*
* 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.bench;
import java.sql.*;
import java.math.*;
public class BenchC implements Bench {
private Database db;
int warehouses = 1;
int items = 10000;
int districtsPerWarehouse = 10;
int customersPerDistrict = 300;
private int ordersPerDistrict = 300;
private BenchCRandom random;
private String action;
private int commitEvery = 1000;
// private final static String[] OPERATION_TEXT = { "Neworder", "Payment",
// "Order Status", "Delivery (deferred)", "Delivery (interactive)",
// "Stock-level" };
//
private static final String[] TABLES = new String[] { "WAREHOUSE",
"DISTRICT", "CUSTOMER", "HISTORY", "ORDERS", "NEW_ORDER", "ITEM",
"STOCK", "ORDER_LINE", "RESULTS" };
private static final String[] CREATE_SQL = new String[] {
"CREATE TABLE WAREHOUSE(\n" + " W_ID INT NOT NULL PRIMARY KEY,\n"
+ " W_NAME VARCHAR(10),\n" + " W_STREET_1 VARCHAR(20),\n"
+ " W_STREET_2 VARCHAR(20),\n" + " W_CITY VARCHAR(20),\n"
+ " W_STATE CHAR(2),\n" + " W_ZIP CHAR(9),\n"
+ " W_TAX DECIMAL(4, 4),\n" + " W_YTD DECIMAL(12, 2))",
"CREATE TABLE DISTRICT(\n" + " D_ID INT NOT NULL,\n" + " D_W_ID INT NOT NULL,\n"
+ " D_NAME VARCHAR(10),\n" + " D_STREET_1 VARCHAR(20),\n"
+ " D_STREET_2 VARCHAR(20),\n" + " D_CITY VARCHAR(20),\n"
+ " D_STATE CHAR(2),\n" + " D_ZIP CHAR(9),\n"
+ " D_TAX DECIMAL(4, 4),\n" + " D_YTD DECIMAL(12, 2),\n"
+ " D_NEXT_O_ID INT,\n"
+ " PRIMARY KEY (D_ID, D_W_ID))", //,\n"
// + " FOREIGN KEY (D_W_ID)\n"
// + " REFERENCES WAREHOUSE(W_ID))",
"CREATE TABLE CUSTOMER(\n" + " C_ID INT NOT NULL,\n" + " C_D_ID INT NOT NULL,\n"
+ " C_W_ID INT NOT NULL,\n" + " C_FIRST VARCHAR(16),\n"
+ " C_MIDDLE CHAR(2),\n" + " C_LAST VARCHAR(16),\n"
+ " C_STREET_1 VARCHAR(20),\n"
+ " C_STREET_2 VARCHAR(20),\n" + " C_CITY VARCHAR(20),\n"
+ " C_STATE CHAR(2),\n" + " C_ZIP CHAR(9),\n"
+ " C_PHONE CHAR(16),\n" + " C_SINCE TIMESTAMP,\n"
+ " C_CREDIT CHAR(2),\n"
+ " C_CREDIT_LIM DECIMAL(12, 2),\n"
+ " C_DISCOUNT DECIMAL(4, 4),\n"
+ " C_BALANCE DECIMAL(12, 2),\n"
+ " C_YTD_PAYMENT DECIMAL(12, 2),\n"
+ " C_PAYMENT_CNT DECIMAL(4),\n"
+ " C_DELIVERY_CNT DECIMAL(4),\n"
+ " C_DATA VARCHAR(500),\n"
+ " PRIMARY KEY (C_W_ID, C_D_ID, C_ID))", //,\n"
// + " FOREIGN KEY (C_W_ID, C_D_ID)\n"
// + " REFERENCES DISTRICT(D_W_ID, D_ID))",
"CREATE INDEX CUSTOMER_NAME ON CUSTOMER(C_LAST, C_D_ID, C_W_ID)",
"CREATE TABLE HISTORY(\n" + " H_C_ID INT,\n" + " H_C_D_ID INT,\n"
+ " H_C_W_ID INT,\n" + " H_D_ID INT,\n" + " H_W_ID INT,\n"
+ " H_DATE TIMESTAMP,\n" + " H_AMOUNT DECIMAL(6, 2),\n"
+ " H_DATA VARCHAR(24))", //,\n"
// + " FOREIGN KEY(H_C_W_ID, H_C_D_ID, H_C_ID)\n"
// + " REFERENCES CUSTOMER(C_W_ID, C_D_ID, C_ID),\n"
// + " FOREIGN KEY(H_W_ID, H_D_ID)\n"
// + " REFERENCES DISTRICT(D_W_ID, D_ID))",
"CREATE TABLE ORDERS(\n" + " O_ID INT NOT NULL,\n" + " O_D_ID INT NOT NULL,\n"
+ " O_W_ID INT NOT NULL,\n" + " O_C_ID INT,\n"
+ " O_ENTRY_D TIMESTAMP,\n" + " O_CARRIER_ID INT,\n"
+ " O_OL_CNT INT,\n" + " O_ALL_LOCAL DECIMAL(1),\n"
+ " PRIMARY KEY(O_W_ID, O_D_ID, O_ID))", // ,\n"
// + " FOREIGN KEY(O_W_ID, O_D_ID, O_C_ID)\n"
// + " REFERENCES CUSTOMER(C_W_ID, C_D_ID, C_ID))",
"CREATE INDEX ORDERS_OID ON ORDERS(O_ID)",
"CREATE TABLE NEW_ORDER(\n" + " NO_O_ID INT NOT NULL,\n" + " NO_D_ID INT NOT NULL,\n"
+ " NO_W_ID INT NOT NULL,\n"
+ " PRIMARY KEY(NO_W_ID, NO_D_ID, NO_O_ID))", //,\n"
// + " FOREIGN KEY(NO_W_ID, NO_D_ID, NO_O_ID)\n"
// + " REFERENCES ORDER(O_W_ID, O_D_ID, O_ID))",
"CREATE TABLE ITEM(\n" + " I_ID INT NOT NULL,\n" + " I_IM_ID INT,\n"
+ " I_NAME VARCHAR(24),\n" + " I_PRICE DECIMAL(5, 2),\n"
+ " I_DATA VARCHAR(50),\n" + " PRIMARY KEY(I_ID))",
"CREATE TABLE STOCK(\n" + " S_I_ID INT NOT NULL,\n" + " S_W_ID INT NOT NULL,\n"
+ " S_QUANTITY DECIMAL(4),\n" + " S_DIST_01 CHAR(24),\n"
+ " S_DIST_02 CHAR(24),\n" + " S_DIST_03 CHAR(24),\n"
+ " S_DIST_04 CHAR(24),\n" + " S_DIST_05 CHAR(24),\n"
+ " S_DIST_06 CHAR(24),\n" + " S_DIST_07 CHAR(24),\n"
+ " S_DIST_08 CHAR(24),\n" + " S_DIST_09 CHAR(24),\n"
+ " S_DIST_10 CHAR(24),\n" + " S_YTD DECIMAL(8),\n"
+ " S_ORDER_CNT DECIMAL(4),\n"
+ " S_REMOTE_CNT DECIMAL(4),\n" + " S_DATA VARCHAR(50),\n"
+ " PRIMARY KEY(S_W_ID, S_I_ID))", //,\n"
// + " FOREIGN KEY(S_W_ID)\n"
// + " REFERENCES WAREHOUSE(W_ID),\n"
// + " FOREIGN KEY(S_I_ID)\n" + " REFERENCES ITEM(I_ID))",
"CREATE TABLE ORDER_LINE(\n"
+ " OL_O_ID INT NOT NULL,\n"
+ " OL_D_ID INT NOT NULL,\n"
+ " OL_W_ID INT NOT NULL,\n"
+ " OL_NUMBER INT NOT NULL,\n"
+ " OL_I_ID INT,\n"
+ " OL_SUPPLY_W_ID INT,\n"
+ " OL_DELIVERY_D TIMESTAMP,\n"
+ " OL_QUANTITY DECIMAL(2),\n"
+ " OL_AMOUNT DECIMAL(6, 2),\n"
+ " OL_DIST_INFO CHAR(24),\n"
+ " PRIMARY KEY (OL_W_ID, OL_D_ID, OL_O_ID, OL_NUMBER))", //,\n"
// + " FOREIGN KEY(OL_W_ID, OL_D_ID, OL_O_ID)\n"
// + " REFERENCES ORDER(O_W_ID, O_D_ID, O_ID),\n"
// + " FOREIGN KEY(OL_SUPPLY_W_ID, OL_I_ID)\n"
// + " REFERENCES STOCK(S_W_ID, S_I_ID))",
"CREATE TABLE RESULTS(\n" + " ID INT NOT NULL PRIMARY KEY,\n"
+ " TERMINAL INT,\n" + " OPERATION INT,\n"
+ " RESPONSE_TIME INT,\n" + " PROCESSING_TIME INT,\n"
+ " KEYING_TIME INT,\n" + " THINK_TIME INT,\n"
+ " SUCCESSFULL INT,\n" + " NOW TIMESTAMP)" };
public void init(Database db, int size) throws Exception {
this.db = db;
random = new BenchCRandom();
items = size * 10;
warehouses = 1;
districtsPerWarehouse = Math.max(1, size / 100);
customersPerDistrict = Math.max(1, size / 100);
ordersPerDistrict = Math.max(1, size / 1000);
db.start(this, "Init");
db.openConnection();
load();
db.commit();
db.closeConnection();
db.end();
db.start(this, "Open/Close");
db.openConnection();
db.closeConnection();
db.end();
}
private void load() throws Exception {
for (int i = 0; i < TABLES.length; i++) {
db.dropTable(TABLES[i]);
}
for (int i = 0; i < CREATE_SQL.length; i++) {
db.update(CREATE_SQL[i]);
}
db.setAutoCommit(false);
loadItem();
loadWarehouse();
loadCustomer();
loadOrder();
db.commit();
trace("load done");
}
void trace(String s) {
action = s;
}
void trace(int i,int max) {
db.trace(action, i, max);
}
private void loadItem() throws Exception {
trace("load item");
boolean[] original = random.getBoolean(items, items / 10);
PreparedStatement prep = db.prepare("INSERT INTO ITEM(I_ID, I_IM_ID, I_NAME, I_PRICE, I_DATA) "
+ "VALUES(?, ?, ?, ?, ?)");
for (int i_id = 1; i_id <= items; i_id++) {
String i_name = random.getString(14, 24);
BigDecimal i_price = random.getBigDecimal(random.getInt(100, 10000), 2);
String i_data = random.getString(26, 50);
if (original[i_id - 1]) {
i_data = random.replace(i_data, "original");
}
prep.setInt(1, i_id);
prep.setInt(2, random.getInt(1, 10000));
prep.setString(3, i_name);
prep.setBigDecimal(4, i_price);
prep.setString(5, i_data);
db.update(prep);
trace(i_id, items);
if(i_id%commitEvery==0) {
db.commit();
}
}
}
private void loadWarehouse() throws Exception {
trace("loading warehouses");
PreparedStatement prep = db.prepare("INSERT INTO WAREHOUSE(W_ID, W_NAME, W_STREET_1, "
+ "W_STREET_2, W_CITY, W_STATE, W_ZIP, W_TAX, W_YTD) "
+ "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)");
for (int w_id = 1; w_id <= warehouses; w_id++) {
String w_name = random.getString(6, 10);
String[] address = random.getAddress();
String w_street_1 = address[0];
String w_street_2 = address[1];
String w_city = address[2];
String w_state = address[3];
String w_zip = address[4];
BigDecimal w_tax = random.getBigDecimal(random.getInt(0, 2000), 4);
BigDecimal w_ytd = new BigDecimal("300000.00");
prep.setInt(1, w_id);
prep.setString(2, w_name);
prep.setString(3, w_street_1);
prep.setString(4, w_street_2);
prep.setString(5, w_city);
prep.setString(6, w_state);
prep.setString(7, w_zip);
prep.setBigDecimal(8, w_tax);
prep.setBigDecimal(9, w_ytd);
db.update(prep);
loadStock(w_id);
loadDistrict(w_id);
if(w_id%commitEvery==0) {
db.commit();
}
}
}
private void loadCustomer() throws Exception {
trace("load customers");
int max = warehouses * districtsPerWarehouse;
int i = 0;
for (int w_id = 1; w_id <= warehouses; w_id++) {
for (int d_id = 1; d_id <= districtsPerWarehouse; d_id++) {
loadCustomerSub(d_id, w_id);
trace(i++, max);
if(i%commitEvery==0) {
db.commit();
}
}
}
}
private void loadCustomerSub(int d_id, int w_id) throws Exception {
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
PreparedStatement prepCustomer = db.prepare("INSERT INTO CUSTOMER(C_ID, C_D_ID, C_W_ID, "
+ "C_FIRST, C_MIDDLE, C_LAST, "
+ "C_STREET_1, C_STREET_2, C_CITY, C_STATE, C_ZIP, "
+ "C_PHONE, C_SINCE, C_CREDIT, "
+ "C_CREDIT_LIM, C_DISCOUNT, C_BALANCE, C_DATA, "
+ "C_YTD_PAYMENT, C_PAYMENT_CNT, C_DELIVERY_CNT) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
PreparedStatement prepHistory = db.prepare("INSERT INTO HISTORY(H_C_ID, H_C_D_ID, H_C_W_ID, "
+ "H_W_ID, H_D_ID, H_DATE, H_AMOUNT, H_DATA) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
for (int c_id = 1; c_id <= customersPerDistrict; c_id++) {
int c_d_id = d_id;
int c_w_id = w_id;
String c_first = random.getString(8, 16);
String c_middle = "OE";
String c_last;
if (c_id < 1000) {
c_last = random.getLastname(c_id);
} else {
c_last = random.getLastname(random.getNonUniform(255, 0, 999));
}
String[] address = random.getAddress();
String c_street_1 = address[0];
String c_street_2 = address[1];
String c_city = address[2];
String c_state = address[3];
String c_zip = address[4];
String c_phone = random.getNumberString(16, 16);
String c_credit;
if (random.getInt(0, 1) == 0) {
c_credit = "GC";
} else {
c_credit = "BC";
}
BigDecimal c_discount = random.getBigDecimal(random.getInt(0, 5000), 4);
BigDecimal c_balance = new BigDecimal("-10.00");
BigDecimal c_credit_lim = new BigDecimal("50000.00");
String c_data = random.getString(300, 500);
BigDecimal c_ytd_payment = new BigDecimal("10.00");
int c_payment_cnt = 1;
int c_delivery_cnt = 1;
prepCustomer.setInt(1, c_id);
prepCustomer.setInt(2, c_d_id);
prepCustomer.setInt(3, c_w_id);
prepCustomer.setString(4, c_first);
prepCustomer.setString(5, c_middle);
prepCustomer.setString(6, c_last);
prepCustomer.setString(7, c_street_1);
prepCustomer.setString(8, c_street_2);
prepCustomer.setString(9, c_city);
prepCustomer.setString(10, c_state);
prepCustomer.setString(11, c_zip);
prepCustomer.setString(12, c_phone);
prepCustomer.setTimestamp(13, timestamp);
prepCustomer.setString(14, c_credit);
prepCustomer.setBigDecimal(15, c_credit_lim);
prepCustomer.setBigDecimal(16, c_discount);
prepCustomer.setBigDecimal(17, c_balance);
prepCustomer.setString(18, c_data);
prepCustomer.setBigDecimal(19, c_ytd_payment);
prepCustomer.setInt(20, c_payment_cnt);
prepCustomer.setInt(21, c_delivery_cnt);
db.update(prepCustomer);
BigDecimal h_amount = new BigDecimal("10.00");
String h_data = random.getString(12, 24);
prepHistory.setInt(1, c_id);
prepHistory.setInt(2, c_d_id);
prepHistory.setInt(3, c_w_id);
prepHistory.setInt(4, c_w_id);
prepHistory.setInt(5, c_d_id);
prepHistory.setTimestamp(6, timestamp);
prepHistory.setBigDecimal(7, h_amount);
prepHistory.setString(8, h_data);
db.update(prepHistory);
}
}
private void loadOrder() throws Exception {
trace("load orders");
int max = warehouses * districtsPerWarehouse;
int i = 0;
for (int w_id = 1; w_id <= warehouses; w_id++) {
for (int d_id = 1; d_id <= districtsPerWarehouse; d_id++) {
loadOrderSub(d_id, w_id);
trace(i++, max);
}
}
}
private void loadOrderSub(int d_id, int w_id) throws Exception {
int o_d_id = d_id;
int o_w_id = w_id;
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
int[] orderid = random.getPermutation(ordersPerDistrict);
PreparedStatement prepOrder = db.prepare("INSERT INTO ORDERS(O_ID, O_C_ID, O_D_ID, O_W_ID, "
+ "O_ENTRY_D, O_CARRIER_ID, O_OL_CNT, O_ALL_LOCAL) "
+ "VALUES(?, ?, ?, ?, ?, ?, ?, 1)");
PreparedStatement prepNewOrder = db.prepare("INSERT INTO NEW_ORDER (NO_O_ID, NO_D_ID, NO_W_ID) "
+ "VALUES (?, ?, ?)");
PreparedStatement prepLine = db.prepare("INSERT INTO ORDER_LINE("
+ "OL_O_ID, OL_D_ID, OL_W_ID, OL_NUMBER, "
+ "OL_I_ID, OL_SUPPLY_W_ID, OL_QUANTITY, OL_AMOUNT, "
+ "OL_DIST_INFO, OL_DELIVERY_D)"
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL)");
for (int o_id = 1, i=0; o_id <= ordersPerDistrict; o_id++) {
int o_c_id = orderid[o_id - 1];
int o_carrier_id = random.getInt(1, 10);
int o_ol_cnt = random.getInt(5, 15);
prepOrder.setInt(1, o_id);
prepOrder.setInt(2, o_c_id);
prepOrder.setInt(3, o_d_id);
prepOrder.setInt(4, o_w_id);
prepOrder.setTimestamp(5, timestamp);
prepOrder.setInt(7, o_ol_cnt);
if (o_id <= 2100) {
prepOrder.setInt(6, o_carrier_id);
} else {
// the last 900 orders have not been delivered
prepOrder.setNull(6, Types.INTEGER);
prepNewOrder.setInt(1, o_id);
prepNewOrder.setInt(2, o_d_id);
prepNewOrder.setInt(3, o_w_id);
db.update(prepNewOrder);
}
db.update(prepOrder);
for (int ol = 1; ol <= o_ol_cnt; ol++) {
int ol_i_id = random.getInt(1, items);
int ol_supply_w_id = o_w_id;
int ol_quantity = 5;
String ol_dist_info = random.getString(24);
BigDecimal ol_amount;
if (o_id < 2101) {
ol_amount = random.getBigDecimal(0, 2);
} else {
ol_amount = random.getBigDecimal(random.getInt(0, 1000000), 2);
}
prepLine.setInt(1, o_id);
prepLine.setInt(2, o_d_id);
prepLine.setInt(3, o_w_id);
prepLine.setInt(4, ol);
prepLine.setInt(5, ol_i_id);
prepLine.setInt(6, ol_supply_w_id);
prepLine.setInt(7, ol_quantity);
prepLine.setBigDecimal(8, ol_amount);
prepLine.setString(9, ol_dist_info);
db.update(prepLine);
if(i++%commitEvery==0) {
db.commit();
}
}
}
}
private void loadStock(int w_id) throws Exception {
trace("load stock (warehouse " + w_id + ")");
int s_w_id = w_id;
boolean[] original = random.getBoolean(items, items / 10);
PreparedStatement prep = db.prepare("INSERT INTO STOCK(S_I_ID, S_W_ID, S_QUANTITY, "
+ "S_DIST_01, S_DIST_02, S_DIST_03, S_DIST_04, S_DIST_05, "
+ "S_DIST_06, S_DIST_07, S_DIST_08, S_DIST_09, S_DIST_10, "
+ "S_DATA, S_YTD, S_ORDER_CNT, S_REMOTE_CNT) "
+ "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
for (int s_i_id = 1; s_i_id <= items; s_i_id++) {
int s_quantity = random.getInt(10, 100);
String s_dist_01 = random.getString(24);
String s_dist_02 = random.getString(24);
String s_dist_03 = random.getString(24);
String s_dist_04 = random.getString(24);
String s_dist_05 = random.getString(24);
String s_dist_06 = random.getString(24);
String s_dist_07 = random.getString(24);
String s_dist_08 = random.getString(24);
String s_dist_09 = random.getString(24);
String s_dist_10 = random.getString(24);
String s_data = random.getString(26, 50);
if (original[s_i_id - 1]) {
s_data = random.replace(s_data, "original");
}
prep.setInt(1, s_i_id);
prep.setInt(2, s_w_id);
prep.setInt(3, s_quantity);
prep.setString(4, s_dist_01);
prep.setString(5, s_dist_02);
prep.setString(6, s_dist_03);
prep.setString(7, s_dist_04);
prep.setString(8, s_dist_05);
prep.setString(9, s_dist_06);
prep.setString(10, s_dist_07);
prep.setString(11, s_dist_08);
prep.setString(12, s_dist_09);
prep.setString(13, s_dist_10);
prep.setString(14, s_data);
prep.setInt(15, 0);
prep.setInt(16, 0);
prep.setInt(17, 0);
db.update(prep);
if(s_i_id%commitEvery==0) {
db.commit();
}
trace(s_i_id, items);
}
}
private void loadDistrict(int w_id) throws Exception {
int d_w_id = w_id;
BigDecimal d_ytd = new BigDecimal("300000.00");
int d_next_o_id = 3001;
PreparedStatement prep = db.prepare("INSERT INTO DISTRICT(D_ID, D_W_ID, D_NAME, "
+ "D_STREET_1, D_STREET_2, D_CITY, D_STATE, D_ZIP, "
+ "D_TAX, D_YTD, D_NEXT_O_ID) "
+ "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
for (int d_id = 1; d_id <= districtsPerWarehouse; d_id++) {
String d_name = random.getString(6, 10);
String[] address = random.getAddress();
String d_street_1 = address[0];
String d_street_2 = address[1];
String d_city = address[2];
String d_state = address[3];
String d_zip = address[4];
BigDecimal d_tax = random.getBigDecimal(random.getInt(0, 2000), 4);
prep.setInt(1, d_id);
prep.setInt(2, d_w_id);
prep.setString(3, d_name);
prep.setString(4, d_street_1);
prep.setString(5, d_street_2);
prep.setString(6, d_city);
prep.setString(7, d_state);
prep.setString(8, d_zip);
prep.setBigDecimal(9, d_tax);
prep.setBigDecimal(10, d_ytd);
prep.setInt(11, d_next_o_id);
db.update(prep);
trace(d_id, districtsPerWarehouse);
}
}
public void run() throws Exception {
db.start(this, "Transactions");
db.openConnection();
for(int i=0; i<70; i++) {
BenchCThread process = new BenchCThread(db, this, random, i);
process.process();
}
db.closeConnection();
db.end();
db.openConnection();
BenchCThread process = new BenchCThread(db, this, random, 0);
process.process();
db.logMemory(this, "Memory Usage");
db.closeConnection();
}
public String getName() {
return "BenchC";
}
}
/*
* 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.bench;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Random;
public class BenchCRandom {
private Random random = new Random(10);
int getNonUniform(int a, int min, int max) {
int c = 0;
return (((getInt(0, a) | getInt(min, max)) + c) % (max - min + 1))
+ min;
}
int getInt(int min, int max) {
return max <= min ? min : (random.nextInt(max - min) + min);
}
boolean[] getBoolean(int length, int trueCount) {
boolean[] data = new boolean[length];
for (int i = 0, pos; i < trueCount; i++) {
do {
pos = getInt(0, length);
} while (data[pos]);
data[pos] = true;
}
return data;
}
String replace(String text, String replacement) {
int pos = getInt(0, text.length() - replacement.length());
StringBuffer buffer = new StringBuffer(text);
buffer.replace(pos, pos + 7, replacement);
return buffer.toString();
}
String getNumberString(int min, int max) {
int len = getInt(min, max);
char[] buff = new char[len];
for (int i = 0; i < len; i++) {
buff[i] = (char) getInt('0', '9');
}
return new String(buff);
}
String[] getAddress() {
String str1 = getString(10, 20);
String str2 = getString(10, 20);
String city = getString(10, 20);
String state = getString(2);
String zip = getNumberString(9, 9);
return new String[] { str1, str2, city, state, zip };
}
String getString(int min, int max) {
return getString(getInt(min, max));
}
String getString(int len) {
char[] buff = new char[len];
for (int i = 0; i < len; i++) {
buff[i] = (char) getInt('A', 'Z');
}
return new String(buff);
}
int[] getPermutation(int length) {
int[] data = new int[length];
for (int i = 0; i < length; i++) {
data[i] = i;
}
for (int i = 0; i < length; i++) {
int j = getInt(0, length);
int temp = data[i];
data[i] = data[j];
data[j] = temp;
}
return data;
}
BigDecimal getBigDecimal(int value, int scale) {
return new BigDecimal(new BigInteger(String.valueOf(value)), scale);
}
String getLastname(int i) {
String[] n = { "BAR", "OUGHT", "ABLE", "PRI", "PRES", "ESE", "ANTI",
"CALLY", "ATION", "EING" };
StringBuffer buff = new StringBuffer();
buff.append(n[i / 100]);
buff.append(n[(i / 10) % 10]);
buff.append(n[i % 10]);
return buff.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.bench;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.util.HashMap;
public class BenchCThread {
private Database db;
private int warehouseId;
private int terminalId;
private HashMap prepared = new HashMap();
private static final int OP_NEW_ORDER = 0, OP_PAYMENT = 1,
OP_ORDER_STATUS = 2, OP_DELIVERY = 3,
OP_STOCK_LEVEL = 4;
private static final BigDecimal ONE = new BigDecimal("1");
private BenchCRandom random;
private BenchC bench;
BenchCThread(Database db, BenchC bench, BenchCRandom random, int terminal)
throws Exception {
this.db = db;
this.bench = bench;
this.terminalId = terminal;
db.setAutoCommit(false);
this.random = random;
warehouseId = random.getInt(1, bench.warehouses);
}
void process() throws Exception {
int[] deck = new int[] { OP_NEW_ORDER, OP_NEW_ORDER, OP_NEW_ORDER,
OP_NEW_ORDER, OP_NEW_ORDER, OP_NEW_ORDER, OP_NEW_ORDER,
OP_NEW_ORDER, OP_NEW_ORDER, OP_NEW_ORDER, OP_PAYMENT,
OP_PAYMENT, OP_PAYMENT, OP_PAYMENT, OP_PAYMENT, OP_PAYMENT,
OP_PAYMENT, OP_PAYMENT, OP_PAYMENT, OP_PAYMENT,
OP_ORDER_STATUS, OP_DELIVERY, OP_STOCK_LEVEL };
int len = deck.length;
for (int i = 0; i < len; i++) {
int temp = deck[i];
int j = random.getInt(0, len);
deck[i] = deck[j];
deck[j] = temp;
}
for (int i = 0; i < len; i++) {
int op = deck[i];
switch (op) {
case OP_NEW_ORDER:
processNewOrder();
break;
case OP_PAYMENT:
processPayment();
break;
case OP_ORDER_STATUS:
processOrderStatus();
break;
case OP_DELIVERY:
processDelivery();
break;
case OP_STOCK_LEVEL:
processStockLevel();
break;
default:
throw new Error("op=" + op);
}
}
}
private void processNewOrder() throws Exception {
int d_id = random.getInt(1, bench.districtsPerWarehouse);
int c_id = random.getNonUniform(1023, 1, bench.customersPerDistrict);
int o_ol_cnt = random.getInt(5, 15);
boolean rollback = random.getInt(1, 100) == 1;
int[] supply_w_id = new int[o_ol_cnt];
int[] item_id = new int[o_ol_cnt];
int[] quantity = new int[o_ol_cnt];
int o_all_local = 1;
for (int i = 0; i < o_ol_cnt; i++) {
int w;
if (bench.warehouses > 1 && random.getInt(1, 100) == 1) {
do {
w = random.getInt(1, bench.warehouses);
} while (w != warehouseId);
o_all_local = 0;
} else {
w = warehouseId;
}
supply_w_id[i] = w;
int item;
if (rollback && i == o_ol_cnt - 1) {
// unused order number
item = -1;
} else {
item = random.getNonUniform(8191, 1, bench.items);
}
item_id[i] = item;
quantity[i] = random.getInt(1, 10);
}
char[] bg = new char[o_ol_cnt];
int[] stock = new int[o_ol_cnt];
BigDecimal[] amt = new BigDecimal[o_ol_cnt];
Timestamp datetime = new Timestamp(System.currentTimeMillis());
PreparedStatement prep;
ResultSet rs;
prep = prepare("UPDATE DISTRICT SET D_NEXT_O_ID=D_NEXT_O_ID+1 "
+ "WHERE D_ID=? AND D_W_ID=?");
prep.setInt(1, d_id);
prep.setInt(2, warehouseId);
db.update(prep);
prep = prepare("SELECT D_NEXT_O_ID, D_TAX FROM DISTRICT "
+ "WHERE D_ID=? AND D_W_ID=?");
prep.setInt(1, d_id);
prep.setInt(2, warehouseId);
rs = db.query(prep);
rs.next();
int o_id = rs.getInt(1) - 1;
BigDecimal d_tax = rs.getBigDecimal(2);
rs.close();
// TODO optimizer: such cases can be optimized! A=1 AND B=A means
// also B=1!
// prep = prepare("SELECT C_DISCOUNT, C_LAST, C_CREDIT, W_TAX "
// + "FROM CUSTOMER, WAREHOUSE "
// + "WHERE C_ID=? AND W_ID=? AND C_W_ID=W_ID AND C_D_ID=?");
prep = prepare("SELECT C_DISCOUNT, C_LAST, C_CREDIT, W_TAX "
+ "FROM CUSTOMER, WAREHOUSE "
+ "WHERE C_ID=? AND C_W_ID=? AND C_W_ID=W_ID AND C_D_ID=?");
prep.setInt(1, c_id);
prep.setInt(2, warehouseId);
prep.setInt(3, d_id);
rs = db.query(prep);
rs.next();
BigDecimal c_discount = rs.getBigDecimal(1);
rs.getString(2); // c_last
rs.getString(3); // c_credit
BigDecimal w_tax = rs.getBigDecimal(4);
rs.close();
BigDecimal total = new BigDecimal("0");
for (int ol_number = 1; ol_number <= o_ol_cnt; ol_number++) {
int ol_i_id = item_id[ol_number - 1];
int ol_supply_w_id = supply_w_id[ol_number - 1];
int ol_quantity = quantity[ol_number - 1];
prep = prepare("SELECT I_PRICE, I_NAME, I_DATA "
+ "FROM ITEM WHERE I_ID=?");
prep.setInt(1, ol_i_id);
rs = db.query(prep);
if (!rs.next()) {
if (rollback) {
// item not found - correct behavior
db.rollback();
return;
}
throw new Exception("item not found: " + ol_i_id + " "
+ ol_supply_w_id);
}
BigDecimal i_price = rs.getBigDecimal(1);
rs.getString(2); // i_name
String i_data = rs.getString(3);
rs.close();
prep = prepare("SELECT S_QUANTITY, S_DATA, "
+ "S_DIST_01, S_DIST_02, S_DIST_03, S_DIST_04, S_DIST_05, "
+ "S_DIST_06, S_DIST_07, S_DIST_08, S_DIST_09, S_DIST_10 "
+ "FROM STOCK WHERE S_I_ID=? AND S_W_ID=?");
prep.setInt(1, ol_i_id);
prep.setInt(2, ol_supply_w_id);
rs = db.query(prep);
if (!rs.next()) {
if (rollback) {
// item not found - correct behavior
db.rollback();
return;
}
throw new Exception("item not found: " + ol_i_id + " "
+ ol_supply_w_id);
}
int s_quantity = rs.getInt(1);
String s_data = rs.getString(2);
String[] s_dist = new String[10];
for (int i = 0; i < 10; i++) {
s_dist[i] = rs.getString(3 + i);
}
rs.close();
String ol_dist_info = s_dist[d_id - 1];
stock[ol_number - 1] = s_quantity;
if ((i_data.indexOf("original") != -1)
&& (s_data.indexOf("original") != -1)) {
bg[ol_number - 1] = 'B';
} else {
bg[ol_number - 1] = 'G';
}
if (s_quantity > ol_quantity) {
s_quantity = s_quantity - ol_quantity;
} else {
s_quantity = s_quantity - ol_quantity + 91;
}
prep = prepare("UPDATE STOCK SET S_QUANTITY=? "
+ "WHERE S_W_ID=? AND S_I_ID=?");
prep.setInt(1, s_quantity);
prep.setInt(2, ol_supply_w_id);
prep.setInt(3, ol_i_id);
db.update(prep);
BigDecimal ol_amount = new BigDecimal(ol_quantity).multiply(
i_price).multiply(ONE.add(w_tax).add(d_tax)).multiply(
ONE.subtract(c_discount));
ol_amount = ol_amount.setScale(2, BigDecimal.ROUND_HALF_UP);
amt[ol_number - 1] = ol_amount;
total = total.add(ol_amount);
prep = prepare("INSERT INTO ORDER_LINE (OL_O_ID, OL_D_ID, OL_W_ID, OL_NUMBER, "
+ "OL_I_ID, OL_SUPPLY_W_ID, "
+ "OL_QUANTITY, OL_AMOUNT, OL_DIST_INFO) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
prep.setInt(1, o_id);
prep.setInt(2, d_id);
prep.setInt(3, warehouseId);
prep.setInt(4, ol_number);
prep.setInt(5, ol_i_id);
prep.setInt(6, ol_supply_w_id);
prep.setInt(7, ol_quantity);
prep.setBigDecimal(8, ol_amount);
prep.setString(9, ol_dist_info);
db.update(prep);
}
prep = prepare("INSERT INTO ORDERS (O_ID, O_D_ID, O_W_ID, O_C_ID, "
+ "O_ENTRY_D, O_OL_CNT, O_ALL_LOCAL) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?)");
prep.setInt(1, o_id);
prep.setInt(2, d_id);
prep.setInt(3, warehouseId);
prep.setInt(4, c_id);
prep.setTimestamp(5, datetime);
prep.setInt(6, o_ol_cnt);
prep.setInt(7, o_all_local);
db.update(prep);
prep = prepare("INSERT INTO NEW_ORDER (NO_O_ID, NO_D_ID, NO_W_ID) "
+ "VALUES (?, ?, ?)");
prep.setInt(1, o_id);
prep.setInt(2, d_id);
prep.setInt(3, warehouseId);
db.update(prep);
db.commit();
}
private void processPayment() throws Exception {
int d_id = random.getInt(1, bench.districtsPerWarehouse);
int c_w_id, c_d_id;
if (bench.warehouses > 1 && random.getInt(1, 100) <= 15) {
do {
c_w_id = random.getInt(1, bench.warehouses);
} while (c_w_id != warehouseId);
c_d_id = random.getInt(1, bench.districtsPerWarehouse);
} else {
c_w_id = warehouseId;
c_d_id = d_id;
}
boolean byname;
String c_last;
int c_id = 1;
if (random.getInt(1, 100) <= 60) {
byname = true;
c_last = random.getLastname(random.getNonUniform(255, 0, 999));
} else {
byname = false;
c_last = "";
c_id = random.getNonUniform(1023, 1, bench.customersPerDistrict);
}
BigDecimal h_amount = random.getBigDecimal(random.getInt(100, 500000),
2);
Timestamp datetime = new Timestamp(System.currentTimeMillis());
PreparedStatement prep;
ResultSet rs;
prep = prepare("UPDATE DISTRICT SET D_YTD = D_YTD+? "
+ "WHERE D_ID=? AND D_W_ID=?");
prep.setBigDecimal(1, h_amount);
prep.setInt(2, d_id);
prep.setInt(3, warehouseId);
db.update(prep);
prep = prepare("UPDATE WAREHOUSE SET W_YTD=W_YTD+? WHERE W_ID=?");
prep.setBigDecimal(1, h_amount);
prep.setInt(2, warehouseId);
db.update(prep);
prep = prepare("SELECT W_STREET_1, W_STREET_2, W_CITY, W_STATE, W_ZIP, W_NAME "
+ "FROM WAREHOUSE WHERE W_ID=?");
prep.setInt(1, warehouseId);
rs = db.query(prep);
rs.next();
rs.getString(1); // w_street_1
rs.getString(2); // w_street_2
rs.getString(3); // w_city
rs.getString(4); // w_state
rs.getString(5); // w_zip
String w_name = rs.getString(6);
rs.close();
prep = prepare("SELECT D_STREET_1, D_STREET_2, D_CITY, D_STATE, D_ZIP, D_NAME "
+ "FROM DISTRICT WHERE D_ID=? AND D_W_ID=?");
prep.setInt(1, d_id);
prep.setInt(2, warehouseId);
rs = db.query(prep);
rs.next();
rs.getString(1); // d_street_1
rs.getString(2); // d_street_2
rs.getString(3); // d_city
rs.getString(4); // d_state
rs.getString(5); // d_zip
String d_name = rs.getString(6);
rs.close();
BigDecimal c_balance;
String c_credit;
if (byname) {
prep = prepare("SELECT COUNT(C_ID) FROM CUSTOMER "
+ "WHERE C_LAST=? AND C_D_ID=? AND C_W_ID=?");
prep.setString(1, c_last);
prep.setInt(2, c_d_id);
prep.setInt(3, c_w_id);
rs = db.query(prep);
rs.next();
int namecnt = rs.getInt(1);
rs.close();
if (namecnt == 0) {
// TODO TPC-C: check if this can happen
db.rollback();
return;
}
prep = prepare("SELECT C_FIRST, C_MIDDLE, C_ID, "
+ "C_STREET_1, C_STREET_2, C_CITY, C_STATE, C_ZIP, "
+ "C_PHONE, C_CREDIT, C_CREDIT_LIM, "
+ "C_DISCOUNT, C_BALANCE, C_SINCE FROM CUSTOMER "
+ "WHERE C_LAST=? AND C_D_ID=? AND C_W_ID=? "
+ "ORDER BY C_FIRST");
prep.setString(1, c_last);
prep.setInt(2, c_d_id);
prep.setInt(3, c_w_id);
rs = db.query(prep);
// locate midpoint customer
if (namecnt % 2 != 0) {
namecnt++;
}
for (int n = 0; n < namecnt / 2; n++) {
rs.next();
}
rs.getString(1); // c_first
rs.getString(2); // c_middle
c_id = rs.getInt(3);
rs.getString(4); // c_street_1
rs.getString(5); // c_street_2
rs.getString(6); // c_city
rs.getString(7); // c_state
rs.getString(8); // c_zip
rs.getString(9); // c_phone
c_credit = rs.getString(10);
rs.getString(11); // c_credit_lim
rs.getBigDecimal(12); // c_discount
c_balance = rs.getBigDecimal(13);
rs.getTimestamp(14); // c_since
rs.close();
} else {
prep = prepare("SELECT C_FIRST, C_MIDDLE, C_LAST, "
+ "C_STREET_1, C_STREET_2, C_CITY, C_STATE, C_ZIP, "
+ "C_PHONE, C_CREDIT, C_CREDIT_LIM, "
+ "C_DISCOUNT, C_BALANCE, C_SINCE FROM CUSTOMER "
+ "WHERE C_ID=? AND C_D_ID=? AND C_W_ID=?");
prep.setInt(1, c_id);
prep.setInt(2, c_d_id);
prep.setInt(3, c_w_id);
rs = db.query(prep);
rs.next();
rs.getString(1); // c_first
rs.getString(2); // c_middle
c_last = rs.getString(3);
rs.getString(4); // c_street_1
rs.getString(5); // c_street_2
rs.getString(6); // c_city
rs.getString(7); // c_state
rs.getString(8);// c_zip
rs.getString(9); // c_phone
c_credit = rs.getString(10);
rs.getString(11); // c_credit_lim
rs.getBigDecimal(12); // c_discount
c_balance = rs.getBigDecimal(13);
rs.getTimestamp(14); // c_since
rs.close();
}
c_balance = c_balance.add(h_amount);
if (c_credit.equals("BC")) {
prep = prepare("SELECT C_DATA INTO FROM CUSTOMER "
+ "WHERE C_ID=? AND C_D_ID=? AND C_W_ID=?");
prep.setInt(1, c_id);
prep.setInt(2, c_d_id);
prep.setInt(3, c_w_id);
rs = db.query(prep);
rs.next();
String c_data = rs.getString(1);
rs.close();
String c_new_data = "| " + c_id + " " + c_d_id + " " + c_w_id
+ " " + d_id + " " + warehouseId + " " + h_amount + " "
+ c_data;
if (c_new_data.length() > 500) {
c_new_data = c_new_data.substring(0, 500);
}
prep = prepare("UPDATE CUSTOMER SET C_BALANCE=?, C_DATA=? "
+ "WHERE C_ID=? AND C_D_ID=? AND C_W_ID=?");
prep.setBigDecimal(1, c_balance);
prep.setString(2, c_new_data);
prep.setInt(3, c_id);
prep.setInt(4, c_d_id);
prep.setInt(5, c_w_id);
db.update(prep);
} else {
prep = prepare("UPDATE CUSTOMER SET C_BALANCE=? "
+ "WHERE C_ID=? AND C_D_ID=? AND C_W_ID=?");
prep.setBigDecimal(1, c_balance);
prep.setInt(2, c_id);
prep.setInt(3, c_d_id);
prep.setInt(4, c_w_id);
db.update(prep);
}
// MySQL bug?
// String h_data = w_name + " " + d_name;
String h_data = w_name + " " + d_name;
prep = prepare("INSERT INTO HISTORY (H_C_D_ID, H_C_W_ID, H_C_ID, H_D_ID, "
+ "H_W_ID, H_DATE, H_AMOUNT, H_DATA) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
prep.setInt(1, c_d_id);
prep.setInt(2, c_w_id);
prep.setInt(3, c_id);
prep.setInt(4, d_id);
prep.setInt(5, warehouseId);
prep.setTimestamp(6, datetime);
prep.setBigDecimal(7, h_amount);
prep.setString(8, h_data);
db.update(prep);
db.commit();
}
private void processOrderStatus() throws Exception {
int d_id = random.getInt(1, bench.districtsPerWarehouse);
boolean byname;
String c_last = null;
int c_id = -1;
if (random.getInt(1, 100) <= 60) {
byname = true;
c_last = random.getLastname(random.getNonUniform(255, 0, 999));
} else {
byname = false;
c_id = random.getNonUniform(1023, 1, bench.customersPerDistrict);
}
PreparedStatement prep;
ResultSet rs;
prep = prepare("UPDATE DISTRICT SET D_NEXT_O_ID=-1 WHERE D_ID=-1");
db.update(prep);
if (byname) {
prep = prepare("SELECT COUNT(C_ID) FROM CUSTOMER "
+ "WHERE C_LAST=? AND C_D_ID=? AND C_W_ID=?");
prep.setString(1, c_last);
prep.setInt(2, d_id);
prep.setInt(3, warehouseId);
rs = db.query(prep);
rs.next();
int namecnt = rs.getInt(1);
rs.close();
if (namecnt == 0) {
// TODO TPC-C: check if this can happen
db.rollback();
return;
}
prep = prepare("SELECT C_BALANCE, C_FIRST, C_MIDDLE, C_ID "
+ "FROM CUSTOMER "
+ "WHERE C_LAST=? AND C_D_ID=? AND C_W_ID=? "
+ "ORDER BY C_FIRST");
prep.setString(1, c_last);
prep.setInt(2, d_id);
prep.setInt(3, warehouseId);
rs = db.query(prep);
if (namecnt % 2 != 0) {
namecnt++;
}
for (int n = 0; n < namecnt / 2; n++) {
rs.next();
}
rs.getBigDecimal(1); // c_balance
rs.getString(2); // c_first
rs.getString(3); // c_middle
rs.close();
} else {
prep = prepare("SELECT C_BALANCE, C_FIRST, C_MIDDLE, C_LAST "
+ "FROM CUSTOMER "
+ "WHERE C_ID=? AND C_D_ID=? AND C_W_ID=?");
prep.setInt(1, c_id);
prep.setInt(2, d_id);
prep.setInt(3, warehouseId);
rs = db.query(prep);
rs.next();
rs.getBigDecimal(1); // c_balance
rs.getString(2); // c_first
rs.getString(3); // c_middle
c_last = rs.getString(4);
rs.close();
}
prep = prepare("SELECT MAX(O_ID) "
+ "FROM ORDERS WHERE O_C_ID=? AND O_D_ID=? AND O_W_ID=?");
prep.setInt(1, c_id);
prep.setInt(2, d_id);
prep.setInt(3, warehouseId);
rs = db.query(prep);
int o_id = -1;
if (rs.next()) {
o_id = rs.getInt(1);
if (rs.wasNull()) {
o_id = -1;
}
}
rs.close();
if (o_id != -1) {
prep = prepare("SELECT O_ID, O_CARRIER_ID, O_ENTRY_D "
+ "FROM ORDERS WHERE O_ID=?");
prep.setInt(1, o_id);
rs = db.query(prep);
rs.next();
o_id = rs.getInt(1);
rs.getInt(2); // o_carrier_id
rs.getTimestamp(3); // o_entry_d
rs.close();
prep = prepare("SELECT OL_I_ID, OL_SUPPLY_W_ID, OL_QUANTITY, "
+ "OL_AMOUNT, OL_DELIVERY_D FROM ORDER_LINE "
+ "WHERE OL_O_ID=? AND OL_D_ID=? AND OL_W_ID=?");
prep.setInt(1, o_id);
prep.setInt(2, d_id);
prep.setInt(3, warehouseId);
rs = db.query(prep);
while (rs.next()) {
rs.getInt(1); // o_i_id
rs.getInt(2); // ol_supply_w_id
rs.getInt(3); // ol_quantity
rs.getBigDecimal(4); // ol_amount
rs.getTimestamp(5); // ol_delivery_d
}
rs.close();
}
db.commit();
}
private void processDelivery() throws Exception {
int o_carrier_id = random.getInt(1, 10);
Timestamp datetime = new Timestamp(System.currentTimeMillis());
PreparedStatement prep;
ResultSet rs;
prep = prepare("UPDATE DISTRICT SET D_NEXT_O_ID=-1 WHERE D_ID=-1");
db.update(prep);
for (int d_id = 1; d_id <= bench.districtsPerWarehouse; d_id++) {
prep = prepare("SELECT MIN(NO_O_ID) FROM NEW_ORDER "
+ "WHERE NO_D_ID=? AND NO_W_ID=?");
prep.setInt(1, d_id);
prep.setInt(2, warehouseId);
rs = db.query(prep);
int no_o_id = -1;
if (rs.next()) {
no_o_id = rs.getInt(1);
if (rs.wasNull()) {
no_o_id = -1;
}
}
rs.close();
if (no_o_id != -1) {
prep = prepare("DELETE FROM NEW_ORDER "
+ "WHERE NO_O_ID=? AND NO_D_ID=? AND NO_W_ID=?");
prep.setInt(1, no_o_id);
prep.setInt(2, d_id);
prep.setInt(3, warehouseId);
db.update(prep);
prep = prepare("SELECT O_C_ID FROM ORDERS "
+ "WHERE O_ID=? AND O_D_ID=? AND O_W_ID=?");
prep.setInt(1, no_o_id);
prep.setInt(2, d_id);
prep.setInt(3, warehouseId);
rs = db.query(prep);
rs.next();
rs.getInt(1); // o_c_id
rs.close();
prep = prepare("UPDATE ORDERS SET O_CARRIER_ID=? "
+ "WHERE O_ID=? AND O_D_ID=? AND O_W_ID=?");
prep.setInt(1, o_carrier_id);
prep.setInt(2, no_o_id);
prep.setInt(3, d_id);
prep.setInt(4, warehouseId);
db.update(prep);
prep = prepare("UPDATE ORDER_LINE SET OL_DELIVERY_D=? "
+ "WHERE OL_O_ID=? AND OL_D_ID=? AND OL_W_ID=?");
prep.setTimestamp(1, datetime);
prep.setInt(2, no_o_id);
prep.setInt(3, d_id);
prep.setInt(4, warehouseId);
db.update(prep);
prep = prepare("SELECT SUM(OL_AMOUNT) FROM ORDER_LINE "
+ "WHERE OL_O_ID=? AND OL_D_ID=? AND OL_W_ID=?");
prep.setInt(1, no_o_id);
prep.setInt(2, d_id);
prep.setInt(3, warehouseId);
rs = db.query(prep);
rs.next();
BigDecimal ol_amount = rs.getBigDecimal(1);
rs.close();
prep = prepare("UPDATE CUSTOMER SET C_BALANCE=C_BALANCE+? "
+ "WHERE C_ID=? AND C_D_ID=? AND C_W_ID=?");
prep.setBigDecimal(1, ol_amount);
prep.setInt(2, no_o_id);
prep.setInt(3, d_id);
prep.setInt(4, warehouseId);
db.update(prep);
}
}
db.commit();
}
private void processStockLevel() throws Exception {
int d_id = (terminalId % bench.districtsPerWarehouse) + 1;
int threshold = random.getInt(10, 20);
PreparedStatement prep;
ResultSet rs;
prep = prepare("UPDATE DISTRICT SET D_NEXT_O_ID=-1 WHERE D_ID=-1");
db.update(prep);
prep = prepare("SELECT D_NEXT_O_ID FROM DISTRICT "
+ "WHERE D_ID=? AND D_W_ID=?");
prep.setInt(1, d_id);
prep.setInt(2, warehouseId);
rs = db.query(prep);
rs.next();
int o_id = rs.getInt(1);
rs.close();
// prep = prepare("SELECT COUNT(DISTINCT S_I_ID) "
// + "FROM ORDER_LINE, STOCK WHERE OL_W_ID=? AND "
// + "OL_D_ID=? AND OL_O_ID<? AND "
// + "OL_O_ID>=?-20 AND S_W_ID=? AND "
// + "S_I_ID=OL_I_ID AND S_QUANTITY<?");
// prep.setInt(1, warehouseId);
// prep.setInt(2, d_id);
// prep.setInt(3, o_id);
// prep.setInt(4, o_id);
prep = prepare("SELECT COUNT(DISTINCT S_I_ID) "
+ "FROM ORDER_LINE, STOCK WHERE OL_W_ID=? AND "
+ "OL_D_ID=? AND OL_O_ID<? AND "
+ "OL_O_ID>=? AND S_W_ID=? AND "
+ "S_I_ID=OL_I_ID AND S_QUANTITY<?");
prep.setInt(1, warehouseId);
prep.setInt(2, d_id);
prep.setInt(3, o_id);
prep.setInt(4, o_id-20);
prep.setInt(5, warehouseId);
prep.setInt(6, threshold);
// TODO this is where HSQLDB is very slow
rs = db.query(prep);
rs.next();
rs.getInt(1); // stockCount
rs.close();
db.commit();
}
private PreparedStatement prepare(String sql) throws Exception {
PreparedStatement prep = (PreparedStatement) prepared.get(sql);
if (prep == null) {
prep = db.prepare(sql);
prepared.put(sql, prep);
}
return prep;
}
}
/*
* 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.bench;
import java.sql.PreparedStatement;
import java.util.Random;
public class BenchSimple implements Bench {
Database db;
int records;
public void init(Database db, int size) throws Exception {
this.db = db;
this.records = size * 60;
db.start(this, "Init");
db.openConnection();
db.dropTable("TEST");
db.setAutoCommit(false);
int commitEvery = 1000;
db.update("CREATE TABLE TEST(ID INT NOT NULL PRIMARY KEY, NAME VARCHAR(255))");
db.commit();
PreparedStatement prep = db.prepare("INSERT INTO TEST VALUES(?, ?)");
for(int i=0; i<records; i++) {
prep.setInt(1, i);
prep.setString(2, "Hello World " + i);
db.update(prep);
if(i%commitEvery==0) {
db.commit();
}
}
db.commit();
db.closeConnection();
db.end();
db.start(this, "Open/Close");
db.openConnection();
db.closeConnection();
db.end();
}
public void run() throws Exception {
PreparedStatement prep;
Random random = db.getRandom();
db.openConnection();
db.start(this, "Query (random)");
prep = db.prepare("SELECT * FROM TEST WHERE ID=?");
for(int i=0; i<records; i++) {
prep.setInt(1, random.nextInt(records));
db.queryReadResult(prep);
}
db.end();
db.start(this, "Query (sequential)");
prep = db.prepare("SELECT * FROM TEST WHERE ID=?");
for(int i=0; i<records; i++) {
prep.setInt(1, i);
db.queryReadResult(prep);
}
db.end();
db.start(this, "Update (random)");
prep = db.prepare("UPDATE TEST SET NAME=? WHERE ID=?");
for(int i=0; i<records; i++) {
prep.setString(1, "Hallo Welt");
prep.setInt(2, i);
db.update(prep);
}
db.end();
db.start(this, "Delete (sequential)");
prep = db.prepare("DELETE FROM TEST WHERE ID=?");
// delete only 50%
for(int i=0; i<records; i+=2) {
prep.setInt(1, i);
db.update(prep);
}
db.end();
db.closeConnection();
db.openConnection();
prep = db.prepare("SELECT * FROM TEST WHERE ID=?");
for(int i=0; i<records; i++) {
prep.setInt(1, random.nextInt(records));
db.queryReadResult(prep);
}
db.logMemory(this, "Memory Usage");
db.closeConnection();
}
public String getName() {
return "Simple";
}
}
/*
* 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.bench;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Properties;
import java.util.Random;
import java.util.StringTokenizer;
import org.h2.test.TestBase;
import org.h2.tools.Server;
import org.h2.util.StringUtils;
class Database {
private TestPerformance test;
private int id;
private String name, url, user, password;
private ArrayList replace = new ArrayList();
private String action;
private long startTime;
private Connection conn;
private Statement stat;
private boolean trace = true;
private long lastTrace;
private Random random = new Random(1);
private ArrayList results = new ArrayList();
private int totalTime;
private int executedStatements;
private Server serverH2;
private Object serverDerby;
private boolean serverHSQLDB;
String getName() {
return name;
}
int getTotalTime() {
return totalTime;
}
ArrayList getResults() {
return results;
}
Random getRandom() {
return random;
}
void startServer() throws Exception {
if(url.startsWith("jdbc:h2:tcp:")) {
serverH2 = Server.createTcpServer(new String[0]).start();
Thread.sleep(100);
} else if(url.startsWith("jdbc:derby://")) {
serverDerby = Class.forName("org.apache.derby.drda.NetworkServerControl").newInstance();
Method m = serverDerby.getClass().getMethod("start", new Class[]{PrintWriter.class});
m.invoke(serverDerby, new Object[]{null});
// serverDerby = new NetworkServerControl();
// serverDerby.start(null);
Thread.sleep(100);
} else if(url.startsWith("jdbc:hsqldb:hsql:")) {
if(!serverHSQLDB) {
Class c = Class.forName("org.hsqldb.Server");
Method m = c.getMethod("main", new Class[]{String[].class});
m.invoke(null, new Object[]{new String[]{"-database.0", "data/mydb;hsqldb.default_table_type=cached", "-dbname.0", "xdb"}});
// org.hsqldb.Server.main(new String[]{"-database.0", "mydb", "-dbname.0", "xdb"});
serverHSQLDB = true;
Thread.sleep(100);
}
}
}
void stopServer() throws Exception {
if(serverH2 != null) {
serverH2.stop();
serverH2 = null;
}
if(serverDerby != null) {
Method m = serverDerby.getClass().getMethod("shutdown", new Class[]{});
m.invoke(serverDerby, null);
// serverDerby.shutdown();
serverDerby = null;
} else if(serverHSQLDB) {
// can not shut down (shutdown calls System.exit)
// openConnection();
// update("SHUTDOWN");
// closeConnection();
// serverHSQLDB = false;
}
}
static Database parse(TestPerformance test, int id, String dbString) {
try {
StringTokenizer tokenizer = new StringTokenizer(dbString, ",");
Database db = new Database();
db.id = id;
db.test = test;
db.name = tokenizer.nextToken().trim();
String driver = tokenizer.nextToken().trim();
Class.forName(driver);
db.url = tokenizer.nextToken().trim();
db.user = tokenizer.nextToken().trim();
db.password = "";
if(tokenizer.hasMoreTokens()) {
db.password = tokenizer.nextToken().trim();
}
System.out.println("Loaded successfully: " + db.name);
return db;
} catch(Exception e) {
System.out.println("Cannot load database " + dbString +" :" + e.toString());
return null;
}
}
Connection getConnection() throws Exception {
Connection conn = DriverManager.getConnection(url, user, password);
if(url.startsWith("jdbc:derby:")) {
// Derby: use higher cache size
conn.createStatement().execute("CALL SYSCS_UTIL.SYSCS_SET_DATABASE_PROPERTY('derby.storage.pageSize', '8192')");
}
return conn;
}
void openConnection() throws Exception {
conn = DriverManager.getConnection(url, user, password);
stat = conn.createStatement();
}
void closeConnection() throws Exception {
// if(!serverHSQLDB && url.startsWith("jdbc:hsqldb:")) {
// stat.execute("SHUTDOWN");
// }
conn.close();
stat = null;
conn = null;
}
public void setTranslations(Properties prop) {
String id = url.substring("jdbc:".length());
id = id.substring(0, id.indexOf(':'));
for(Iterator it = prop.keySet().iterator(); it.hasNext(); ) {
String key = (String)it.next();
if(key.startsWith(id + ".")) {
String pattern = key.substring(id.length()+1);
pattern = StringUtils.replaceAll(pattern, "_", " ");
pattern = StringUtils.toUpperEnglish(pattern);
String replacement = prop.getProperty(key);
replace.add(new String[]{pattern, replacement});
}
}
}
PreparedStatement prepare(String sql) throws Exception {
sql = getSQL(sql);
return conn.prepareStatement(sql);
}
public String getSQL(String sql) {
for(int i=0; i<replace.size(); i++) {
String[] pair = (String[]) replace.get(i);
String pattern = pair[0];
String replace = pair[1];
sql = StringUtils.replaceAll(sql, pattern, replace);
}
return sql;
}
void start(Bench bench, String action) {
this.action = bench.getName() + ": " + action;
this.startTime = System.currentTimeMillis();
}
void end() {
long time = System.currentTimeMillis() - startTime;
log(action, "ms", (int)time);
if(test.collect) {
totalTime += time;
}
}
void dropTable(String table) {
try {
update("DROP TABLE " + table);
} catch (Exception e) {
// ignore - table may not exist
}
}
public void update(PreparedStatement prep) throws Exception {
prep.executeUpdate();
executedStatements++;
}
public void update(String sql) throws Exception {
sql = getSQL(sql);
if(sql.trim().length()>0) {
stat.execute(sql);
} else {
System.out.println("?");
}
executedStatements++;
}
public void setAutoCommit(boolean b) throws Exception {
conn.setAutoCommit(b);
}
public void commit() throws Exception {
conn.commit();
}
public void rollback() throws Exception {
conn.rollback();
}
void trace(String action, int i, int max) {
if (trace) {
long time = System.currentTimeMillis();
if (i == 0 || lastTrace == 0) {
lastTrace = time;
} else if (time > lastTrace + 1000) {
System.out.println(action + ": " + ((100 * i / max) + "%"));
lastTrace = time;
}
}
}
void logMemory(Bench bench, String action) {
log(bench.getName() + ": " + action, "MB", TestBase.getMemoryUsed());
}
void log(String action, String scale, int value) {
if(test.collect) {
results.add(new Object[]{action, scale, new Integer(value)});
}
}
public ResultSet query(PreparedStatement prep) throws Exception {
// long time = System.currentTimeMillis();
ResultSet rs = prep.executeQuery();
// time = System.currentTimeMillis() - time;
// if(time > 100) {
// new Error("time="+time).printStackTrace();
// }
executedStatements++;
return rs;
}
public void queryReadResult(PreparedStatement prep) throws Exception {
ResultSet rs = prep.executeQuery();
ResultSetMetaData meta = rs.getMetaData();
int columnCount = meta.getColumnCount();
while(rs.next()) {
for(int i=0; i<columnCount; i++) {
rs.getString(i+1);
}
}
}
int getExecutedStatements() {
return executedStatements;
}
public int getId() {
return id;
}
}
/*
* 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.bench;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Properties;
import org.h2.test.TestBase;
public class TestPerformance {
boolean collect;
public static void main(String[] args) throws Exception {
new TestPerformance().test(args);
}
private Connection getResultConnection() throws Exception {
Class.forName("org.h2.Driver");
return DriverManager.getConnection("jdbc:h2:data/results");
}
private void openResults(boolean init) throws Exception {
Connection conn = getResultConnection();
if(init) {
conn.createStatement().execute("DROP TABLE IF EXISTS RESULTS");
}
conn.createStatement().execute("CREATE TABLE IF NOT EXISTS RESULTS(TESTID INT, TEST VARCHAR, "
+ "UNIT VARCHAR, DBID INT, DB VARCHAR, RESULT VARCHAR)");
conn.close();
}
private void test(String[] args) throws Exception {
boolean init = false;
int dbId = -1;
String out = "benchmark.html";
for(int i=0; i<args.length; i++) {
if(args[i].equals("-db")) {
dbId = Integer.parseInt(args[++i]);
} else if(args[i].equals("-init")) {
init = true;
} else if(args[i].equals("-out")) {
out = args[++i];
}
}
openResults(init);
Properties prop = new Properties();
prop.load(getClass().getResourceAsStream("test.properties"));
int size = Integer.parseInt(prop.getProperty("size"));
ArrayList dbs = new ArrayList();
for(int i=0; i<100; i++) {
if(dbId != -1 && i != dbId) {
continue;
}
String dbString = prop.getProperty("db" + i);
if(dbString != null) {
Database db = Database.parse(this, i, dbString);
if(db != null) {
db.setTranslations(prop);
dbs.add(db);
}
}
}
ArrayList tests = new ArrayList();
for(int i=0; i<100; i++) {
String testString = prop.getProperty("test" + i);
if(testString != null) {
Bench bench = (Bench)Class.forName(testString).newInstance();
tests.add(bench);
}
}
testAll(dbs, tests, size);
collect = false;
if(dbs.size() == 0) {
return;
}
ArrayList results = ((Database)dbs.get(0)).getResults();
Connection conn = getResultConnection();
PreparedStatement prep = conn.prepareStatement(
"INSERT INTO RESULTS(TESTID, TEST, UNIT, DBID, DB, RESULT) VALUES(?, ?, ?, ?, ?, ?)");
for(int i=0; i<results.size(); i++) {
Object[] res = (Object[])results.get(i);
prep.setInt(1, i);
prep.setString(2, res[0].toString());
prep.setString(3, res[1].toString());
for(int j=0; j<dbs.size(); j++) {
Database db = (Database)dbs.get(j);
prep.setInt(4, db.getId());
prep.setString(5, db.getName());
ArrayList r = db.getResults();
Object[] v = (Object[])r.get(i);
prep.setString(6, v[2].toString());
prep.execute();
}
}
PrintWriter writer = new PrintWriter(new FileWriter(out));
ResultSet rs = conn.createStatement().executeQuery(
"CALL '<table><tr><th>Test Case</th><th>Unit</th>' "
+"|| SELECT GROUP_CONCAT('<th>' || DB || '</th>' ORDER BY DBID SEPARATOR '') FROM "
+"(SELECT DISTINCT DBID, DB FROM RESULTS)"
+"|| '</tr>' || CHAR(10) "
+"|| SELECT GROUP_CONCAT('<tr><td>' || TEST || '</td><td>' || UNIT || '</td>' || ( "
+"SELECT GROUP_CONCAT('<td>' || RESULT || '</td>' ORDER BY DBID SEPARATOR '') FROM RESULTS R2 WHERE "
+"R2.TESTID = R1.TESTID) || '</tr>' ORDER BY TESTID SEPARATOR CHAR(10)) FROM "
+"(SELECT DISTINCT TESTID, TEST, UNIT FROM RESULTS) R1"
+"|| '</table>'"
);
rs.next();
String result = rs.getString(1);
writer.println(result);
conn.close();
// ResultSet rsDbs = conn.createStatement().executeQuery("SELECT DB RESULTS GROUP BY DBID, DB ORDER BY DBID");
// while(rsDbs.next()) {
// writer.println("<th>" + rsDbs.getString(1) + "</th>");
// }
// ResultSet rs = conn.createStatement().executeQuery("SELECT TEST, UNIT FROM RESULTS GROUP BY TESTID, TEST, UNIT ORDER BY TESTID");
// while(rs.next()) {
// writer.println("<tr><td>" + rs.getString(1) + "</td>");
// writer.println("<td>" + rs.getString(2) + "</td>");
// ResultSet rsRes = conn.createStatement().executeQuery("SELECT RESULT FROM RESULTS WHERE TESTID=? ORDER BY DBID");
//
//
// }
// PrintWriter writer = new PrintWriter(new FileWriter("benchmark.html"));
// writer.println("<table><tr><th>Test Case</th><th>Unit</th>");
// for(int j=0; j<dbs.size(); j++) {
// Database db = (Database)dbs.get(j);
// writer.println("<th>" + db.getName() + "</th>");
// }
// writer.println("</tr>");
// for(int i=0; i<results.size(); i++) {
// Object[] res = (Object[])results.get(i);
// writer.println("<tr><td>" + res[0] + "</td>");
// writer.println("<td>" + res[1] + "</td>");
// for(int j=0; j<dbs.size(); j++) {
// Database db = (Database)dbs.get(j);
// ArrayList r = db.getResults();
// Object[] v = (Object[])r.get(i);
// writer.println("<td style=\"text-align: right\">" + v[2] + "</td>");
// }
// writer.println("</tr>");
// }
// writer.println("</table>");
writer.close();
System.out.println("Test finished");
System.exit(0);
}
private void testAll(ArrayList dbs, ArrayList tests, int size) throws Exception {
for(int i=0; i<dbs.size(); i++) {
if(i>0) {
Thread.sleep(1000);
}
// calls garbage collection
TestBase.getMemoryUsed();
Database db = (Database)dbs.get(i);
System.out.println("testing " + db.getName());
db.startServer();
Connection conn = db.getConnection();
runDatabase(db, tests, 1);
runDatabase(db, tests, 1);
collect = true;
runDatabase(db, tests, size);
conn.close();
db.log("Executed Statements", "#", db.getExecutedStatements());
db.log("Total Time", "ms", db.getTotalTime());
db.log("Statement per Second", "#", db.getExecutedStatements()*1000/db.getTotalTime());
collect = false;
db.stopServer();
}
}
private void runDatabase(Database db, ArrayList tests, int size) throws Exception {
for(int j=0; j<tests.size(); j++) {
Bench bench = (Bench)tests.get(j);
runTest(db, bench, size);
}
}
private void runTest(Database db, Bench bench, int size) throws Exception {
bench.init(db, size);
bench.run();
}
}
db1 = H2, org.h2.Driver, jdbc:h2:data/test, sa, sa
db2 = HSQLDB, org.hsqldb.jdbcDriver, jdbc:hsqldb:data/test;hsqldb.default_table_type=cached, sa
db3 = Derby, org.apache.derby.jdbc.EmbeddedDriver, jdbc:derby:data/test;create=true, sa, sa
db4 = H2, org.h2.Driver, jdbc:h2:tcp://localhost/data/testServ, sa, sa
db5 = HSQLDB, org.hsqldb.jdbcDriver, jdbc:hsqldb:hsql://localhost/xdb, sa
db6 = Derby, org.apache.derby.jdbc.ClientDriver, jdbc:derby://localhost/data/testServ;create=true, sa, sa
db7 = PostgreSQL, org.postgresql.Driver, jdbc:postgresql:test, sa, sa
db8 = MySQL, com.mysql.jdbc.Driver, jdbc:mysql://localhost/test?jdbcCompliantTruncation=false, sa, sa
db9 = Firebird, org.firebirdsql.jdbc.FBDriver, jdbc:firebirdsql:localhost:c:/temp/firebird/test, sysdba, masterkey
xdb9 = OneDollarDB, in.co.daffodil.db.jdbc.DaffodilDBDriver, jdbc:daffodilDB_embedded:school;path=C:/temp;create=true, sa
xdb10 = Oracle, oracle.jdbc.driver.OracleDriver, jdbc:oracle:thin:@localhost:1521:test, scott, tiger
xdb11 = DB2, COM.ibm.db2.jdbc.net.DB2Driver, jdbc:db2://localhost/test, test, test
xdb12 = MSSQLServer, com.microsoft.jdbc.sqlserver.SQLServerDriver, jdbc:microsoft:sqlserver://127.0.0.1:1433;DatabaseName=test, test, test
firebirdsql.datetime = TIMESTAMP
postgresql.datetime = TIMESTAMP
derby.datetime = TIMESTAMP
test1 = org.h2.test.bench.BenchSimple
test2 = org.h2.test.bench.BenchA
test3 = org.h2.test.bench.BenchC
xsize = 500
xsize = 20
xsize=200
#bug with hsqldb (newest version) and size = 400
xsize = 200
#officialsize = 250
size = 400
MySQL
--------------------------------------------------------------------------------------------------------
ANSI mode can be set using SET GLOBAL sql_mode='ANSI'; 'TRADITIONAL' is default
SELECT @@global.sql_mode
Compare with NULL problem
drop table test;
create table test(id int);
insert into test values(1);
insert into test values(null);
-- 2 rows even in ANSI mode (correct is 1 row):
select * from test where id=id and 1=1;
PostgreSQL
--------------------------------------------------------------------------------------------------------
This source diff could not be displayed because it is too large. You can view the blob instead.
create schema testschema;
create table testschema.test(id int);
create sequence testschema.testseq;
select testschema.testseq.nextval;
> 1;
drop schema testschema;
create table test(id int);
create trigger testtrigger before insert on test call "org.h2.test.db.TestTriggersConstraints";
comment on trigger testtrigger is 'just testing';
select remarks from information_schema.triggers where trigger_name = 'TESTTRIGGER';
> just testing;
@reconnect;
select remarks from information_schema.triggers where trigger_name = 'TESTTRIGGER';
> just testing;
drop trigger testtrigger;
@reconnect;
create alias parselong for "java.lang.Long.parseLong";
comment on alias parselong is 'Parse a long with base';
select remarks from information_schema.function_aliases where alias_name = 'PARSELONG';
> Parse a long with base;
@reconnect;
select remarks from information_schema.function_aliases where alias_name = 'PARSELONG';
> Parse a long with base;
drop alias parselong;
@reconnect;
create role hr;
comment on role hr is 'Human Resources';
select remarks from information_schema.roles where name = 'HR';
> Human Resources;
@reconnect;
select remarks from information_schema.roles where name = 'HR';
> Human Resources;
create user abc password 'x';
grant hr to abc;
drop role hr;
@reconnect;
drop user abc;
create domain email as varchar(100) check instr(value, '@') > 0;
comment on domain email is 'must contain @';
select remarks from information_schema.domains where domain_name = 'EMAIL';
> must contain @;
@reconnect;
select remarks from information_schema.domains where domain_name = 'EMAIL';
> must contain @;
drop domain email;
@reconnect;
create schema tests;
set schema tests;
create sequence walk;
comment on schema tests is 'Test Schema';
comment on sequence walk is 'Walker';
select remarks from information_schema.schemata where schema_name = 'TESTS';
> Test Schema;
select remarks from information_schema.sequences where sequence_name = 'WALK';
> Walker;
@reconnect;
select remarks from information_schema.schemata where schema_name = 'TESTS';
> Test Schema;
select remarks from information_schema.sequences where sequence_name = 'WALK';
> Walker;
drop schema tests;
@reconnect;
create constant abc value 1;
comment on constant abc is 'One';
select remarks from information_schema.constants where constant_name = 'ABC';
> One;
@reconnect;
select remarks from information_schema.constants where constant_name = 'ABC';
> One;
drop constant abc;
drop table test;
@reconnect;
create table test(id int);
alter table test add constraint const1 unique(id);
create index idxid on test(id);
comment on constraint const1 is 'unique id';
comment on index idxid is 'idindex';
select remarks from information_schema.constraints where constraint_name = 'CONST1';
> unique id;
select remarks from information_schema.indexes where index_name = 'IDXID';
> idindex;
@reconnect;
select remarks from information_schema.constraints where constraint_name = 'CONST1';
> unique id;
select remarks from information_schema.indexes where index_name = 'IDXID';
> idindex;
drop table test;
@reconnect;
create user sales password '1';
comment on user sales is 'mr. money';
select remarks from information_schema.users where name = 'SALES';
> mr. money;
@reconnect;
select remarks from information_schema.users where name = 'SALES';
> mr. money;
alter user sales rename to salesuser;
select remarks from information_schema.users where name = 'SALESUSER';
> mr. money;
@reconnect;
select remarks from information_schema.users where name = 'SALESUSER';
> mr. money;
create table test(id int);
create linked table testlink('org.h2.Driver', 'jdbc:h2:mem:', 'sa', 'sa', 'DUAL');
comment on table testlink is '123';
select remarks from information_schema.tables where table_name = 'TESTLINK';
> 123;
@reconnect;
select remarks from information_schema.tables where table_name = 'TESTLINK';
> 123;
comment on table testlink is 'xyz';
select remarks from information_schema.tables where table_name = 'TESTLINK';
> xyz;
alter table testlink rename to testl;
select remarks from information_schema.tables where table_name = 'TESTL';
> xyz;
@reconnect;
select remarks from information_schema.tables where table_name = 'TESTL';
> xyz;
drop table test;
@reconnect;
create table test(id int);
create view testv as select * from test;
comment on table testv is 'abc';
select remarks from information_schema.tables where table_name = 'TESTV';
> abc;
@reconnect;
select remarks from information_schema.tables where table_name = 'TESTV';
> abc;
alter table testv rename to testview;
select remarks from information_schema.tables where table_name = 'TESTVIEW';
> abc;
@reconnect;
select remarks from information_schema.tables where table_name = 'TESTVIEW';
> abc;
drop table test;
@reconnect;
create table test(a int);
comment on table test is 'hi';
select remarks from information_schema.tables where table_name = 'TEST';
> hi;
alter table test add column b int;
select remarks from information_schema.tables where table_name = 'TEST';
> hi;
alter table test rename to test1;
select remarks from information_schema.tables where table_name = 'TEST1';
> hi;
@reconnect;
select remarks from information_schema.tables where table_name = 'TEST1';
> hi;
comment on table test1 is 'ho';
@reconnect;
select remarks from information_schema.tables where table_name = 'TEST1';
> ho;
drop table test1;
create table test(a int, b int);
comment on column test.b is 'test';
select remarks from information_schema.columns where table_name = 'TEST' and column_name = 'B';
> test;
@reconnect;
select remarks from information_schema.columns where table_name = 'TEST' and column_name = 'B';
> test;
alter table test drop column b;
@reconnect;
comment on column test.a is 'ho';
select remarks from information_schema.columns where table_name = 'TEST' and column_name = 'A';
> ho;
@reconnect;
select remarks from information_schema.columns where table_name = 'TEST' and column_name = 'A';
> ho;
drop table test;
@reconnect;
create table test(a int);
comment on column test.a is 'test';
alter table test rename to test2;
@reconnect;
select remarks from information_schema.columns where table_name = 'TEST2';
> test;
@reconnect;
select remarks from information_schema.columns where table_name = 'TEST2';
> test;
drop table test2;
@reconnect;
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论