提交 68bcd1cb authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 3e2897c4
/*
* 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.db;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.h2.api.DatabaseEventListener;
import org.h2.test.TestBase;
/**
* @author Thomas
*/
public class TestMultiConn extends TestBase implements DatabaseEventListener {
public void test() throws Exception {
// testCommitRollback();
try {
testConcurrentOpen();
} catch(SQLException e) {
e.printStackTrace();
System.exit(0); }
// testThreeThreads();
}
private static int wait;
private void testThreeThreads() throws Exception {
deleteDb("multiConn");
final Connection conn1 = getConnection("multiConn");
final Connection conn2 = getConnection("multiConn");
final Connection conn3 = getConnection("multiConn");
conn1.setAutoCommit(false);
conn2.setAutoCommit(false);
conn3.setAutoCommit(false);
final Statement s1 = conn1.createStatement();
final Statement s2 = conn2.createStatement();
final Statement s3 = conn3.createStatement();
s1.execute("CREATE TABLE TEST1(ID INT)");
s2.execute("CREATE TABLE TEST2(ID INT)");
s3.execute("CREATE TABLE TEST3(ID INT)");
s1.execute("INSERT INTO TEST1 VALUES(1)");
s2.execute("INSERT INTO TEST2 VALUES(2)");
s3.execute("INSERT INTO TEST3 VALUES(3)");
s1.execute("SET LOCK_TIMEOUT 1000");
s2.execute("SET LOCK_TIMEOUT 1000");
s3.execute("SET LOCK_TIMEOUT 1000");
Thread t1 = new Thread(new Runnable() {
public void run() {
try {
s3.execute("INSERT INTO TEST2 VALUES(4)");
conn3.commit();
} catch(SQLException e) {
e.printStackTrace();
}
}
});
t1.start();
Thread.sleep(20);
Thread t2 = new Thread(new Runnable() {
public void run() {
try {
s2.execute("INSERT INTO TEST1 VALUES(5)");
conn2.commit();
} catch(SQLException e) {
e.printStackTrace();
}
}
});
t2.start();
Thread.sleep(20);
conn1.commit();
t2.join(100);
t1.join(100);
ResultSet rs = s1.executeQuery("SELECT * FROM TEST1 ORDER BY ID");
rs.next();
check(rs.getInt(1), 1);
rs.next();
check(rs.getInt(1), 5);
checkFalse(rs.next());
conn1.close();
conn2.close();
conn3.close();
}
private void testConcurrentOpen() throws Exception {
if(config.memory) {
return;
}
deleteDb("multiConn");
Connection conn = getConnection("multiConn");
conn.createStatement().execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR)");
conn.createStatement().execute("INSERT INTO TEST VALUES(0, 'Hello'), (1, 'World')");
conn.createStatement().execute("SHUTDOWN");
conn.close();
final String listener = getClass().getName();
Runnable r = new Runnable() {
public void run() {
try {
Connection c1 = getConnection("multiConn;DATABASE_EVENT_LISTENER='"+listener+"';file_lock=socket");
c1.close();
} catch(Exception e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread(r);
thread.start();
Thread.sleep(10);
Connection c2 = getConnection("multiConn;file_lock=socket");
c2.close();
thread.join();
}
public void diskSpaceIsLow(long stillAvailable) throws SQLException {
}
public void exceptionThrown(SQLException e) {
}
public void setProgress(int state, String name, int x, int max) {
while(wait > 0) {
try {
Thread.sleep(wait);
wait = 0;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void closingDatabase() {
}
private void testCommitRollback() throws Exception {
deleteDb("multiConn");
Connection c1 = getConnection("multiConn");
Connection c2 = getConnection("multiConn");
c1.setAutoCommit(false);
c2.setAutoCommit(false);
Statement s1 = c1.createStatement();
s1.execute("DROP TABLE IF EXISTS MULTI_A");
s1.execute("CREATE TABLE MULTI_A(ID INT, NAME VARCHAR(255))");
s1.execute("INSERT INTO MULTI_A VALUES(0, '0-insert-A')");
Statement s2 = c2.createStatement();
s1.execute("DROP TABLE IF EXISTS MULTI_B");
s1.execute("CREATE TABLE MULTI_B(ID INT, NAME VARCHAR(255))");
s2.execute("INSERT INTO MULTI_B VALUES(0, '1-insert-B')");
c1.commit();
c2.rollback();
s1.execute("INSERT INTO MULTI_A VALUES(1, '0-insert-C')");
s2.execute("INSERT INTO MULTI_B VALUES(1, '1-insert-D')");
c1.rollback();
c2.commit();
c1.close();
c2.close();
if(!config.memory) {
Connection conn = getConnection("multiConn");
ResultSet rs;
rs = conn.createStatement().executeQuery("SELECT * FROM MULTI_A ORDER BY ID");
rs.next();
check(rs.getString("NAME"), "0-insert-A" );
checkFalse(rs.next());
rs = conn.createStatement().executeQuery("SELECT * FROM MULTI_B ORDER BY ID");
rs.next();
check(rs.getString("NAME"), "1-insert-D" );
checkFalse(rs.next());
conn.close();
}
}
public void init(String url) {
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.db;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Random;
import org.h2.test.TestBase;
import org.h2.tools.MultiDimension;
public class TestMultiDimension extends TestBase {
public void test() throws Exception {
Random rand = new Random(10);
for(int i=0; i<1000; i++) {
int x = rand.nextInt(1000), y = rand.nextInt(1000), z = rand.nextInt(1000);
MultiDimension tool = MultiDimension.getInstance();
long xyz = tool.interleave(new int[]{x, y, z});
check(x, tool.deinterleave(xyz, 3, 0));
check(y, tool.deinterleave(xyz, 3, 1));
check(z, tool.deinterleave(xyz, 3, 2));
}
deleteDb("multiDimension");
Connection conn;
conn = getConnection("multiDimension");
Statement stat = conn.createStatement();
stat.execute("CREATE ALIAS MAP FOR \"" + getClass().getName() + ".interleave\"");
stat.execute("CREATE TABLE TEST(X INT NOT NULL, Y INT NOT NULL, Z INT NOT NULL, XYZ BIGINT AS MAP(X, Y, Z), DATA VARCHAR)");
stat.execute("CREATE INDEX IDX_X ON TEST(X, Y, Z)");
stat.execute("CREATE INDEX IDX_XYZ ON TEST(XYZ)");
PreparedStatement prep = conn.prepareStatement("INSERT INTO TEST(X, Y, Z, DATA) VALUES(?, ?, ?, ?)");
// a reasonable value to see the performance difference is 60
int max = 10;
long time = System.currentTimeMillis();
for(int x=0; x<max; x++) {
for(int y=0; y<max; y++) {
for(int z=0; z<max; z++) {
long t2 = System.currentTimeMillis();
if(t2 - time > 1000) {
int percent = (int)(100.0 * ((double)x*x*x) / ((double)max * max * max));
trace(percent + "%");
time = t2;
try {
Thread.sleep(10);
} catch(Exception e) {}
}
prep.setInt(1, x);
prep.setInt(2, y);
prep.setInt(3, z);
prep.setString(4, "Test data");
prep.execute();
}
}
}
for(int i=0; i<50; i++) {
int size = rand.nextInt(max / 10);
int minX = rand.nextInt(max-size);
int minY = rand.nextInt(max-size);
int minZ = rand.nextInt(max-size);
int maxX = minX+size, maxY = minY+size, maxZ = minZ+size;
long time1 = System.currentTimeMillis();
String query1 = MultiDimension.getInstance().getMultiDimensionalQuery(
"TEST", "XYZ",
new String[]{"X", "Y", "Z"},
new int[]{minX, minY, minZ},
new int[]{minX+size, minY+size, minZ+size});
ResultSet rs1 = conn.createStatement().executeQuery(query1 + " ORDER BY X, Y, Z");
time1 = System.currentTimeMillis() - time1;
long time2 = System.currentTimeMillis();
String query2 = "SELECT * FROM TEST WHERE "
+"X BETWEEN " + minX + " AND " + maxX + " AND "
+"Y BETWEEN " + minY + " AND " + maxY + " AND "
+"Z BETWEEN " + minZ + " AND " + maxZ;
PreparedStatement prep2 = conn.prepareStatement(query2 + " ORDER BY X, Y, Z");
ResultSet rs2 = prep2.executeQuery();
time2 = System.currentTimeMillis() - time2;
while(rs1.next()) {
check(rs2.next());
check(rs1.getInt(1), rs2.getInt(1));
check(rs1.getInt(2), rs2.getInt(2));
}
checkFalse(rs2.next());
trace("t1="+time1+" t2="+time2+" size="+size);
}
conn.close();
}
public static long interleave(int x, int y, int z) {
return MultiDimension.getInstance().interleave(new int[]{x, y, z});
}
}
/*
* 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.db;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Random;
import org.h2.test.TestAll;
import org.h2.test.TestBase;
public class TestMultiThread extends TestBase implements Runnable {
private boolean stop;
private TestMultiThread parent;
private Random random;
private Connection conn;
private Statement stat;
public TestMultiThread() {
}
private TestMultiThread(TestAll config, TestMultiThread parent) throws Exception {
this.config = config;
this.parent = parent;
random = new Random();
conn = getConnection();
stat = conn.createStatement();
}
public void test() throws Exception {
Connection conn = getConnection();
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE TEST(ID IDENTITY, NAME VARCHAR)");
int len = getSize(10, 200);
Thread[] threads = new Thread[len];
for(int i=0; i<len; i++) {
threads[i] = new Thread(new TestMultiThread(config, this));
}
for(int i=0; i<len; i++) {
threads[i].start();
}
int sleep = getSize(400, 10000);
Thread.sleep(sleep);
this.stop = true;
for(int i=0; i<len; i++) {
threads[i].join();
}
ResultSet rs = stat.executeQuery("SELECT COUNT(*) FROM TEST");
rs.next();
trace("max id="+rs.getInt(1));
conn.close();
}
Connection getConnection() throws Exception {
return getConnection("jdbc:h2:mem:multiThread");
}
public void run() {
try {
while(!parent.stop) {
stat.execute("SELECT COUNT(*) FROM TEST");
stat.execute("INSERT INTO TEST VALUES(NULL, 'Hi')");
PreparedStatement prep = conn.prepareStatement("UPDATE TEST SET NAME='Hello' WHERE ID=?");
prep.setInt(1, random.nextInt(10000));
prep.execute();
prep = conn.prepareStatement("SELECT * FROM TEST WHERE ID=?");
prep.setInt(1, random.nextInt(10000));
ResultSet rs = prep.executeQuery();
while(rs.next()) {
rs.getString("NAME");
}
}
conn.close();
} catch(Exception e) {
e.printStackTrace();
System.exit(0);
}
}
}
/*
* 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.db;
import java.sql.*;
import org.h2.api.DatabaseEventListener;
import org.h2.test.TestBase;
public class TestOpenClose extends TestBase implements DatabaseEventListener {
int nextId = 10;
public static void main(String[] a) throws Exception {
new TestOpenClose().test();
}
public void test() throws Exception {
testCase();
testReconnectFast();
}
private void testReconnectFast() throws Exception {
deleteDb(BASE_DIR, "openClose");
String url = "jdbc:h2:"+BASE_DIR+"/openClose;DATABASE_EVENT_LISTENER='" + TestOpenClose.class.getName()+"'";
Connection conn = DriverManager.getConnection(url, "sa", "sa");
Statement stat = conn.createStatement();
try {
stat.execute("CREATE TABLE TEST(ID IDENTITY, NAME VARCHAR)");
stat.execute("SET MAX_MEMORY_UNDO 100000");
stat.execute("CREATE INDEX IDXNAME ON TEST(NAME)");
stat.execute("INSERT INTO TEST SELECT X, X || ' Data' FROM SYSTEM_RANGE(1, 1000)");
} catch (SQLException e) {
// ok
}
stat.close();
conn.close();
conn = DriverManager.getConnection(url, "sa", "sa");
stat = conn.createStatement();
ResultSet rs = stat.executeQuery("SELECT * FROM DUAL");
if (rs.next()) {
rs.getString(1);
}
rs.close();
stat.close();
conn.close();
conn = DriverManager.getConnection(url, "sa", "sa");
stat = conn.createStatement();
// stat.execute("SET DB_CLOSE_DELAY 0");
stat.executeUpdate("SHUTDOWN");
stat.close();
conn.close();
}
void testCase() throws Exception {
Class.forName("org.h2.Driver");
deleteDb(BASE_DIR, "openClose");
final String url = "jdbc:h2:"+BASE_DIR+"/openClose;FILE_LOCK=NO";
Connection conn = DriverManager.getConnection(url, "sa", "");
conn.createStatement().execute("drop table employee if exists");
conn.createStatement().execute("create table employee(id int primary key, name varchar, salary int)");
conn.close();
int len = this.getSize(200, 4000);
Thread[] threads = new Thread[len];
for(int i=0; i<len; i++) {
threads[i] = new Thread() {
public void run() {
try {
Connection conn = DriverManager.getConnection(url, "sa", "");
PreparedStatement prep = conn.prepareStatement("insert into employee values(?, ?, 0)");
int id = getNextId();
prep.setInt(1, id);
prep.setString(2, "emp " + id);
prep.execute();
conn.close();
} catch(Throwable e) {
// e.printStackTrace();
System.out.println("FAIL: " + e.toString());
}
}
};
threads[i].start();
}
// for(int i=0; i<len; i++) {
// threads[i].start();
// }
for(int i=0; i<len; i++) {
threads[i].join();
}
conn = DriverManager.getConnection(url, "sa", "");
ResultSet rs = conn.createStatement().executeQuery("select count(*) from employee");
rs.next();
check(rs.getInt(1), len);
conn.close();
}
synchronized int getNextId() {
return nextId++;
}
public void diskSpaceIsLow(long stillAvailable) throws SQLException {
throw new SQLException("unexpected");
}
public void exceptionThrown(SQLException e) {
throw new Error("unexpected: " + e);
}
public void setProgress(int state, String name, int current, int max) {
String stateName;
switch(state) {
case STATE_SCAN_FILE:
stateName = "Scan " + name + " " + current + "/" + max;
if(current > 0) {
throw new Error("unexpected: " + stateName);
}
break;
case STATE_CREATE_INDEX:
stateName = "Create Index " + name + " " + current + "/" + max;
if(!"SYS".equals(name)) {
throw new Error("unexpected: " + stateName);
}
break;
case STATE_RECOVER:
stateName = "Recover " + current + "/" + max;
break;
default:
stateName = "?";
}
// System.out.println(": " + stateName);
}
public void closingDatabase() {
}
public void init(String url) {
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.db;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
import java.util.TreeSet;
import org.h2.test.TestBase;
public class TestOptimizations extends TestBase {
public void test() throws Exception {
if(config.networked) {
return;
}
testQueryCacheSpeed();
testQueryCache(true);
testQueryCache(false);
testIn();
testMinMaxCountOptimization(true);
testMinMaxCountOptimization(false);
}
private void testQueryCacheSpeed() throws Exception {
deleteDb("optimizations");
Connection conn=getConnection("optimizations");
Statement stat = conn.createStatement();
testQuerySpeed(stat, "select sum(x) from system_range(1, 10000) a where a.x in (select b.x from system_range(1, 30) b)");
testQuerySpeed(stat, "select sum(a.n), sum(b.x) from system_range(1, 100) b, (select sum(x) n from system_range(1, 4000)) a");
conn.close();
}
private void testQuerySpeed(Statement stat, String sql) throws Exception {
stat.execute("set OPTIMIZE_REUSE_RESULTS 0");
stat.execute(sql);
long time = System.currentTimeMillis();
stat.execute(sql);
time = System.currentTimeMillis() - time;
stat.execute("set OPTIMIZE_REUSE_RESULTS 1");
stat.execute(sql);
long time2 = System.currentTimeMillis();
stat.execute(sql);
time2 = System.currentTimeMillis() - time2;
if(time2 > time) {
error("not optimized: " + time + " optimized: " + time2+ " sql:"+sql);
}
}
private void testQueryCache(boolean optimize) throws Exception {
deleteDb("optimizations");
Connection conn=getConnection("optimizations");
Statement stat = conn.createStatement();
if(optimize) {
stat.execute("set OPTIMIZE_REUSE_RESULTS 1");
} else {
stat.execute("set OPTIMIZE_REUSE_RESULTS 0");
}
stat.execute("create table test(id int)");
stat.execute("create table test2(id int)");
stat.execute("insert into test values(1), (1), (2)");
stat.execute("insert into test2 values(1)");
PreparedStatement prep = conn.prepareStatement("select * from test where id = (select id from test2)");
ResultSet rs1 = prep.executeQuery();
rs1.next();
check(rs1.getInt(1), 1);
rs1.next();
check(rs1.getInt(1), 1);
checkFalse(rs1.next());
stat.execute("update test2 set id = 2");
ResultSet rs2 = prep.executeQuery();
rs2.next();
check(rs2.getInt(1), 2);
conn.close();
}
private void testMinMaxCountOptimization(boolean memory) throws Exception {
deleteDb("optimizations");
Connection conn=getConnection("optimizations");
Statement stat = conn.createStatement();
stat.execute("create "+(memory?"memory":"") +" table test(id int primary key, value int)");
stat.execute("create index idxvalueid on test(value, id);");
int len = getSize(1000, 10000);
HashMap map = new HashMap();
TreeSet set = new TreeSet();
Random random = new Random(1);
for(int i=0; i<len ; i++) {
if(i==len / 2) {
if(!config.memory) {
conn.close();
conn=getConnection("optimizations");
stat = conn.createStatement();
}
}
switch(random.nextInt(10)) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
if(random.nextInt(1000)==1) {
stat.execute("insert into test values("+i+", null)");
map.put(new Integer(i), null);
} else {
int value = random.nextInt();
stat.execute("insert into test values("+i+", "+value+")");
map.put(new Integer(i), new Integer(value));
set.add(new Integer(value));
}
break;
case 6:
case 7:
case 8: {
if(map.size()>0) {
for(int j=random.nextInt(i), k=0; k<10; k++, j++) {
if(map.containsKey(new Integer(j))) {
Integer x = (Integer) map.remove(new Integer(j));
if(x != null) {
set.remove(x);
}
stat.execute("delete from test where id="+j);
}
}
}
break;
}
case 9: {
ArrayList list = new ArrayList(map.values());
int count = list.size();
Integer min = null, max = null;
if(count > 0) {
min = (Integer) set.first();
max = (Integer) set.last();
}
ResultSet rs = stat.executeQuery("select min(value), max(value), count(*) from test");
rs.next();
Integer minDb = (Integer)rs.getObject(1);
Integer maxDb = (Integer)rs.getObject(2);
int countDb = rs.getInt(3);
check(minDb, min);
check(maxDb, max);
check(countDb, count);
}
}
}
conn.close();
}
private void testIn() throws Exception {
deleteDb("optimizations");
Connection conn=getConnection("optimizations");
Statement stat = conn.createStatement();
stat.execute("create table test(id int primary key, name varchar)");
stat.execute("insert into test values(1, 'Hello')");
stat.execute("insert into test values(2, 'World')");
PreparedStatement prep;
ResultSet rs;
prep = conn.prepareStatement("select * from test t1 where t1.id in(?)");
prep.setInt(1, 1);
rs = prep.executeQuery();
rs.next();
check(rs.getInt(1), 1);
check(rs.getString(2), "Hello");
checkFalse(rs.next());
prep = conn.prepareStatement("select * from test t1 where t1.id in(?, ?) order by id");
prep.setInt(1, 1);
prep.setInt(2, 2);
rs = prep.executeQuery();
rs.next();
check(rs.getInt(1), 1);
check(rs.getString(2), "Hello");
rs.next();
check(rs.getInt(1), 2);
check(rs.getString(2), "World");
checkFalse(rs.next());
prep = conn.prepareStatement("select * from test t1 where t1.id in(select t2.id from test t2 where t2.id=?)");
prep.setInt(1, 2);
rs = prep.executeQuery();
rs.next();
check(rs.getInt(1), 2);
check(rs.getString(2), "World");
checkFalse(rs.next());
prep = conn.prepareStatement("select * from test t1 where t1.id in(select t2.id from test t2 where t2.id=? and t1.id<>t2.id)");
prep.setInt(1, 2);
rs = prep.executeQuery();
checkFalse(rs.next());
prep = conn.prepareStatement("select * from test t1 where t1.id in(select t2.id from test t2 where t2.id in(cast(?+10 as varchar)))");
prep.setInt(1, 2);
rs = prep.executeQuery();
checkFalse(rs.next());
conn.close();
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.db;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Random;
import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.jdbc.JdbcConnection;
import org.h2.test.TestBase;
import org.h2.tools.FileBase;
import org.h2.util.FileUtils;
public class TestPowerOff extends TestBase {
private String dbName = "powerOff";
private String dir, url;
private int maxPowerOffCount;
public void test() throws Exception {
if(config.memory || config.logMode==0) {
return;
}
if(config.big) {
dir = BASE_DIR;
} else {
dir = "inmemory:";
}
url = dir + "/" + dbName + ";file_lock=no";
testCrash();
testShutdown();
testNoIndexFile();
testMemoryTables();
testPersistentTables();
}
private void testCrash() throws Exception {
if(config.networked) {
return;
}
deleteDb(dir, dbName);
Random random = new Random(1);
Constants.RUN_FINALIZERS = false;
int repeat = getSize(1, 20);
for(int i=0; i<repeat; i++) {
Connection conn = getConnection(url);
conn.close();
conn = getConnection(url);
Statement stat = conn.createStatement();
stat.execute("SET WRITE_DELAY 0");
((JdbcConnection)conn).setPowerOffCount(random.nextInt(100));
try {
stat.execute("DROP TABLE IF EXISTS TEST");
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))");
conn.setAutoCommit(false);
int len = getSize(3, 100);
for (int j=0; j<len; j++) {
stat.execute("INSERT INTO TEST VALUES("+j+", 'Hello')");
if(random.nextInt(5) == 0) {
conn.commit();
}
if(random.nextInt(10) == 0) {
stat.execute("DROP TABLE IF EXISTS TEST");
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))");
}
}
stat.execute("DROP TABLE IF EXISTS TEST");
conn.close();
} catch(SQLException e) {
if(!e.getSQLState().equals("90098")) {
e.printStackTrace();
}
}
}
}
private void testShutdown() throws Exception {
deleteDb(dir, dbName);
Connection conn = getConnection(url);
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))");
stat.execute("INSERT INTO TEST VALUES(1, 'Hello')");
stat.execute("SHUTDOWN");
conn.close();
conn = getConnection(url);
stat = conn.createStatement();
ResultSet rs = stat.executeQuery("SELECT * FROM TEST");
check(rs.next());
checkFalse(rs.next());
conn.close();
}
private void testNoIndexFile() throws Exception {
if(config.networked) {
return;
}
deleteDb(dir, dbName);
Connection conn = getConnection(url);
Statement stat = conn.createStatement();
stat.execute("CREATE MEMORY TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))");
stat.execute("INSERT INTO TEST VALUES(1, 'Hello')");
((JdbcConnection)conn).setPowerOffCount(1);
try {
stat.execute("INSERT INTO TEST VALUES(2, 'Hello')");
stat.execute("CHECKPOINT");
error("should not work!");
} catch(SQLException e) {
// expected
}
boolean deleted = false;
ArrayList files = FileBase.getDatabaseFiles(dir, dbName, false);
for(int i=0; i<files.size(); i++) {
String fileName = (String) files.get(i);
if(fileName.endsWith(Constants.SUFFIX_INDEX_FILE)) {
FileUtils.delete(fileName);
deleted = true;
}
}
check(deleted);
conn = getConnection(url);
conn.close();
}
private void testMemoryTables() throws Exception {
if(config.networked) {
return;
}
deleteDb(dir, dbName);
Connection conn = getConnection(url);
Statement stat = conn.createStatement();
stat.execute("CREATE MEMORY TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))");
stat.execute("INSERT INTO TEST VALUES(1, 'Hello')");
stat.execute("CHECKPOINT");
((JdbcConnection)conn).setPowerOffCount(1);
try {
stat.execute("INSERT INTO TEST VALUES(2, 'Hello')");
stat.execute("INSERT INTO TEST VALUES(3, 'Hello')");
stat.execute("CHECKPOINT");
error("should have failed!");
} catch(Exception e) {
// ok
}
((JdbcConnection)conn).setPowerOffCount(0);
conn = getConnection(url);
stat = conn.createStatement();
ResultSet rs = stat.executeQuery("SELECT COUNT(*) FROM TEST");
rs.next();
check(rs.getInt(1), 1);
conn.close();
}
private void testPersistentTables() throws Exception {
if(config.networked) {
return;
}
deleteDb(dir, dbName);
// ((JdbcConnection)conn).setPowerOffCount(Integer.MAX_VALUE);
testRun(true);
int max = maxPowerOffCount;
trace("max="+max);
runTest(0, max, true);
recoverAndCheckConsistency();
runTest(0, max, false);
recoverAndCheckConsistency();
}
void runTest(int min, int max, boolean withConsistencyCheck) throws Exception {
for(int i=min; i<max; i++) {
deleteDb(dir, dbName);
Database.setInitialPowerOffCount(i);
int expect = testRun(false);
if(withConsistencyCheck) {
int got = recoverAndCheckConsistency();
trace("test "+i+" of "+max+" expect="+expect+" got="+got);
} else {
trace("test "+i+" of "+max+" expect="+expect);
}
}
Database.setInitialPowerOffCount(0);
}
int testRun(boolean init) throws Exception {
if(init) {
Database.setInitialPowerOffCount(Integer.MAX_VALUE);
}
int state = 0;
try {
Connection conn = getConnection(url);
Statement stat = conn.createStatement();
stat.execute("SET WRITE_DELAY 0");
stat.execute("CREATE TABLE IF NOT EXISTS TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))");
state = 1;
conn.setAutoCommit(false);
stat.execute("INSERT INTO TEST VALUES(1, 'Hello')");
stat.execute("INSERT INTO TEST VALUES(2, 'World')");
conn.commit();
state = 2;
stat.execute("UPDATE TEST SET NAME='Hallo' WHERE ID=1");
stat.execute("UPDATE TEST SET NAME='Welt' WHERE ID=2");
conn.commit();
state = 3;
stat.execute("DELETE FROM TEST WHERE ID=1");
stat.execute("DELETE FROM TEST WHERE ID=2");
conn.commit();
state = 1;
stat.execute("DROP TABLE TEST");
state = 0;
if(init) {
maxPowerOffCount = Integer.MAX_VALUE - ((JdbcConnection)conn).getPowerOffCount();
}
conn.close();
} catch(SQLException e) {
if(e.getSQLState().equals("90098")) {
// this is ok
} else {
throw e;
}
//log("error="+e);
// e.printStackTrace();
}
return state;
}
int recoverAndCheckConsistency() throws Exception {
int state;
Database.setInitialPowerOffCount(0);
Connection conn = getConnection(url);
if(((JdbcConnection)conn).getPowerOffCount() != 0) {
error("power off count is not 0");
}
Statement stat = conn.createStatement();
DatabaseMetaData meta = conn.getMetaData();
ResultSet rs = meta.getTables(null, null, "TEST", null);
if(!rs.next()) {
state = 0;
} else {
// table does not exist
rs = stat.executeQuery("SELECT * FROM TEST ORDER BY ID");
if(!rs.next()) {
state = 1;
} else {
check(rs.getInt(1), 1);
String name1 = rs.getString(2);
check(rs.next());
check(rs.getInt(1), 2);
String name2 = rs.getString(2);
checkFalse(rs.next());
if("Hello".equals(name1)) {
check(name2, "World");
state = 2;
} else {
check(name1, "Hallo");
check(name2, "Welt");
state = 3;
}
}
}
conn.close();
return state;
}
}
/*
* 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.db;
import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import org.h2.test.TestBase;
import org.h2.tools.FileBase;
public class TestReadOnly extends TestBase {
public void test() throws Exception {
if(config.memory) {
return;
}
deleteDb("readonly");
Connection conn = getConnection("readonly");
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR)");
stat.execute("INSERT INTO TEST VALUES(1, 'Hello')");
stat.execute("INSERT INTO TEST VALUES(2, 'World')");
conn.close();
setReadOnly();
conn = getConnection("readonly");
stat = conn.createStatement();
stat.execute("SELECT * FROM TEST");
try {
stat.execute("DELETE FROM TEST");
error("read only delete");
} catch(SQLException e) {
checkNotGeneralException(e);
}
conn.close();
conn = getConnection("readonly;DB_CLOSE_DELAY=1");
stat = conn.createStatement();
stat.execute("SELECT * FROM TEST");
try {
stat.execute("DELETE FROM TEST");
error("read only delete");
} catch(SQLException e) {
checkNotGeneralException(e);
}
conn.close();
}
private void setReadOnly() throws SQLException {
ArrayList list = FileBase.getDatabaseFiles(TestBase.BASE_DIR, "readonly", true);
for(int i=0; i<list.size(); i++) {
String fileName = (String) list.get(i);
File file = new File(fileName);
file.setReadOnly();
}
}
}
/*
* 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.db;
import java.sql.*;
import org.h2.test.TestBase;
public class TestRights extends TestBase {
Statement stat;
public void test() throws Exception {
if(config.memory) {
return;
}
deleteDb("rights");
Connection conn = getConnection("rights");
stat = conn.createStatement();
// default table type
testTableType(conn, "MEMORY");
testTableType(conn, "CACHED");
// rights on tables and views
executeSuccess("CREATE USER PASSREADER PASSWORD 'abc'");
executeSuccess("CREATE TABLE PASS(ID INT PRIMARY KEY, NAME VARCHAR, PASSWORD VARCHAR)");
executeSuccess("CREATE VIEW PASS_NAME AS SELECT ID, NAME FROM PASS");
executeSuccess("GRANT SELECT ON PASS_NAME TO PASSREADER");
conn.close();
conn = getConnection("rights", "PASSREADER", "abc");
stat = conn.createStatement();
executeSuccess("SELECT * FROM PASS_NAME");
executeError("SELECT * FROM PASS");
conn.close();
conn = getConnection("rights");
stat = conn.createStatement();
executeSuccess("CREATE USER TEST PASSWORD 'abc'");
executeSuccess("ALTER USER TEST ADMIN TRUE");
executeSuccess("CREATE TABLE TEST(ID INT)");
executeSuccess("CREATE SCHEMA SCHEMA_A AUTHORIZATION SA");
executeSuccess("CREATE TABLE SCHEMA_A.TABLE_B(ID INT)");
executeSuccess("GRANT ALL ON SCHEMA_A.TABLE_B TO TEST");
executeSuccess("CREATE TABLE HIDDEN(ID INT)");
executeSuccess("CREATE TABLE PUBTABLE(ID INT)");
executeSuccess("CREATE TABLE ROLETABLE(ID INT)");
executeSuccess("CREATE ROLE TESTROLE");
executeSuccess("GRANT SELECT ON ROLETABLE TO TESTROLE");
executeSuccess("GRANT UPDATE ON ROLETABLE TO TESTROLE");
executeSuccess("REVOKE UPDATE ON ROLETABLE FROM TESTROLE");
executeError("REVOKE SELECT, SUB1 ON ROLETABLE FROM TESTROLE");
executeSuccess("GRANT TESTROLE TO TEST");
executeSuccess("GRANT SELECT ON PUBTABLE TO PUBLIC");
executeSuccess("GRANT SELECT ON TEST TO TEST");
executeSuccess("CREATE ROLE SUB1");
executeSuccess("CREATE ROLE SUB2");
executeSuccess("CREATE TABLE SUBTABLE(ID INT)");
executeSuccess("GRANT ALL ON SUBTABLE TO SUB2");
executeSuccess("REVOKE UPDATE, DELETE ON SUBTABLE FROM SUB2");
executeSuccess("GRANT SUB2 TO SUB1");
executeSuccess("GRANT SUB1 TO TEST");
executeSuccess("ALTER USER TEST SET PASSWORD 'def'");
executeSuccess("CREATE USER TEST2 PASSWORD 'def' ADMIN");
executeSuccess("ALTER USER TEST ADMIN FALSE");
executeSuccess("SCRIPT TO '"+BASE_DIR+"/rights.sql' CIPHER XTEA PASSWORD 'test'");
conn.close();
try {
conn = getConnection("rights", "Test", "abc");
error("unexpected success (mixed case user name)");
} catch(SQLException e) {
checkNotGeneralException(e);
}
try {
conn = getConnection("rights", "TEST", "abc");
error("unexpected success (wrong password)");
} catch(SQLException e) {
checkNotGeneralException(e);
}
try {
conn = getConnection("rights", "TEST", null);
error("unexpected success (wrong password)");
} catch(SQLException e) {
checkNotGeneralException(e);
}
conn = getConnection("rights", "TEST", "def");
stat = conn.createStatement();
executeError("SET DEFAULT_TABLE_TYPE MEMORY");
executeSuccess("SELECT * FROM TEST");
executeSuccess("SELECT * FROM SYSTEM_RANGE(1,2)");
executeSuccess("SELECT * FROM SCHEMA_A.TABLE_B");
executeSuccess("SELECT * FROM PUBTABLE");
executeSuccess("SELECT * FROM ROLETABLE");
executeError("UPDATE ROLETABLE SET ID=0");
executeError("DELETE FROM ROLETABLE");
executeError("SELECT * FROM HIDDEN");
executeError("UPDATE TEST SET ID=0");
executeSuccess("SELECT * FROM SUBTABLE");
executeSuccess("INSERT INTO SUBTABLE VALUES(1)");
executeError("DELETE FROM SUBTABLE");
executeError("UPDATE FROM SUBTABLE");
executeError("CREATE USER TEST3 PASSWORD 'def'");
executeError("ALTER USER TEST2 ADMIN FALSE");
executeError("ALTER USER TEST2 SET PASSWORD 'ghi'");
executeError("ALTER USER TEST2 RENAME TO TEST_X");
executeError("ALTER USER TEST RENAME TO TEST_X");
executeSuccess("ALTER USER TEST SET PASSWORD 'ghi'");
executeError("DROP USER TEST2");
conn.close();
conn = getConnection("rights");
stat = conn.createStatement();
executeSuccess("DROP ROLE SUB1");
executeSuccess("DROP TABLE ROLETABLE");
executeSuccess("DROP USER TEST");
conn.close();
conn = getConnection("rights");
stat = conn.createStatement();
executeSuccess("DROP TABLE IF EXISTS TEST");
executeSuccess("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))");
executeSuccess("CREATE USER GUEST PASSWORD 'abc'");
executeSuccess("GRANT SELECT ON TEST TO GUEST");
executeSuccess("ALTER USER GUEST RENAME TO GAST");
conn.close();
conn = getConnection("rights");
conn.close();
}
private void testTableType(Connection conn, String type) throws Exception {
executeSuccess("SET DEFAULT_TABLE_TYPE " + type);
executeSuccess("CREATE TABLE TEST(ID INT)");
ResultSet rs = conn.createStatement().executeQuery("SELECT STORAGE_TYPE FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME='TEST'");
rs.next();
check(rs.getString(1), type);
executeSuccess("DROP TABLE TEST");
}
public void executeError(String sql) throws Exception {
try {
stat.execute(sql);
error("unexpected success (not admin)");
} catch(SQLException e) {
checkNotGeneralException(e);
}
}
public void executeSuccess(String sql) throws Exception {
if(stat.execute(sql)) {
ResultSet rs = stat.getResultSet();
// this will check if the resultset is updatable
rs.getConcurrency();
ResultSetMetaData meta = rs.getMetaData();
int columnCount = meta.getColumnCount();
for(int i=0; i<columnCount; i++) {
meta.getCatalogName(i+1);
meta.getColumnClassName(i+1);
meta.getColumnDisplaySize(i+1);
meta.getColumnLabel(i+1);
meta.getColumnName(i+1);
meta.getColumnType(i+1);
meta.getColumnTypeName(i+1);
meta.getPrecision(i+1);
meta.getScale(i+1);
meta.getSchemaName(i+1);
meta.getTableName(i+1);
}
while(rs.next()) {
for(int i=0; i<columnCount; i++) {
rs.getObject(i+1);
}
}
}
}
}
/*
* 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.db;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import org.h2.api.Trigger;
import org.h2.test.TestBase;
public class TestRunscript extends TestBase implements Trigger {
public void test() throws Exception {
test(false);
test(true);
}
public static int test(int a) {
return Math.abs(a);
}
private void test(boolean password) throws Exception {
deleteDb("runscript");
Connection conn1, conn2;
Statement stat1, stat2;
conn1 = getConnection("runscript");
stat1 = conn1.createStatement();
stat1.execute("create table test (id identity, name varchar(12))");
stat1.execute("insert into test (name) values ('first'), ('second')");
stat1.execute("create sequence testseq start with 100 increment by 10");
stat1.execute("create alias mytest for \""+getClass().getName()+".test\"");
stat1.execute("create trigger mytrigger before insert on test nowait call \""+getClass().getName()+"\"");
stat1.execute("create view testview as select * from test where 1=0 union all select * from test where 0=1");
stat1.execute("create user testadmin salt '00' hash '01' admin");
stat1.execute("create schema testschema authorization testadmin");
stat1.execute("create table testschema.parent(id int primary key, name varchar)");
stat1.execute("create index idxname on testschema.parent(name)");
stat1.execute("create table testschema.child(id int primary key, parentId int, name varchar, foreign key(parentId) references parent(id))");
stat1.execute("create user testuser salt '02' hash '03'");
stat1.execute("create role testrole");
stat1.execute("grant all on testschema.child to testuser");
stat1.execute("grant select, insert on testschema.parent to testrole");
stat1.execute("grant testrole to testuser");
String sql = "script to 'backup.2.sql'";
if(password) {
sql += " CIPHER AES PASSWORD 't1e2s3t4'";
}
stat1.execute(sql);
deleteDb("runscriptRestore");
conn2 = getConnection("runscriptRestore");
stat2 = conn2.createStatement();
sql = "runscript from 'backup.2.sql'";
if(password) {
sql += " CIPHER AES PASSWORD 'wrongpassword'";
}
if(password) {
try {
stat2.execute(sql);
error("should fail");
} catch(SQLException e) {
checkNotGeneralException(e);
}
}
sql = "runscript from 'backup.2.sql'";
if(password) {
sql += " CIPHER AES PASSWORD 't1e2s3t4'";
}
stat2.execute(sql);
stat2.execute("script to 'backup.3.sql'");
compareDatabases(stat1, stat2);
conn1.close();
conn2.close();
}
private void compareDatabases(Statement stat1, Statement stat2) throws Exception {
ResultSet rs1 = stat1.executeQuery("SCRIPT NOPASSWORDS");
ResultSet rs2 = stat2.executeQuery("SCRIPT NOPASSWORDS");
ArrayList list1 = new ArrayList();
ArrayList list2 = new ArrayList();
while(rs1.next()) {
check(rs2.next());
list1.add(rs1.getString(1));
list2.add(rs2.getString(1));
}
for(int i=0; i<list1.size(); i++) {
String s = (String)list1.get(i);
if(!list2.remove(s)) {
error("not found: " + s);
}
}
check(list2.size(), 0);
checkFalse(rs2.next());
}
public void init(Connection conn, String schemaName, String triggerName, String tableName) {
}
public void fire(Connection conn, Object[] oldRow, Object[] newRow) throws SQLException {
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.db;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.h2.test.TestBase;
public class TestSQLInjection extends TestBase {
Connection conn;
Statement stat;
public void test() throws Exception {
deleteDb("sqlinjection");
reconnect("sqlinjection");
stat.execute("DROP TABLE IF EXISTS USERS");
stat.execute("CREATE TABLE USERS(NAME VARCHAR PRIMARY KEY, PASSWORD VARCHAR, TYPE VARCHAR)");
stat.execute("CREATE SCHEMA CONST");
stat.execute("CREATE CONSTANT CONST.ACTIVE VALUE 'Active'");
stat.execute("INSERT INTO USERS VALUES('James', '123456', CONST.ACTIVE)");
check(checkPasswordInsecure("123456"));
checkFalse(checkPasswordInsecure("abcdef"));
check(checkPasswordInsecure("' OR ''='"));
check(checkPasswordSecure("123456"));
checkFalse(checkPasswordSecure("abcdef"));
checkFalse(checkPasswordSecure("' OR ''='"));
stat.execute("SET ALLOW_LITERALS NONE");
try {
check(checkPasswordInsecure("123456"));
error("Should fail now");
} catch(SQLException e) {
checkNotGeneralException(e);
}
check(checkPasswordSecure("123456"));
checkFalse(checkPasswordSecure("' OR ''='"));
conn.close();
if(config.memory) {
return;
}
reconnect("sqlinjection");
try {
check(checkPasswordInsecure("123456"));
error("Should fail now");
} catch(SQLException e) {
checkNotGeneralException(e);
}
check(checkPasswordSecure("123456"));
checkFalse(checkPasswordSecure("' OR ''='"));
conn.close();
}
boolean checkPasswordInsecure(String pwd) throws SQLException {
String sql = "SELECT * FROM USERS WHERE PASSWORD='"+pwd+"'";
ResultSet rs = conn.createStatement().executeQuery(sql);
return(rs.next());
}
boolean checkPasswordSecure(String pwd) throws Exception {
String sql = "SELECT * FROM USERS WHERE PASSWORD=?";
PreparedStatement prep = conn.prepareStatement(sql);
prep.setString(1, pwd);
ResultSet rs = prep.executeQuery();
return(rs.next());
}
private void reconnect(String name) throws Exception {
if(!config.memory) {
if(conn != null) {
conn.close();
conn = null;
}
}
if(conn == null) {
conn = getConnection(name);
stat = conn.createStatement();
}
}
}
/*
* 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.db;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.PrintStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import org.h2.test.TestAll;
import org.h2.test.TestBase;
import org.h2.util.StringUtils;
public class TestScript extends TestBase {
private boolean failFast;
private boolean alwaysReconnect;
private Connection conn;
private Statement stat;
private LineNumberReader in;
private int line;
private PrintStream out;
private ArrayList result = new ArrayList();
private String putback;
private StringBuffer errors;
private ArrayList statements;
private String fileName = "org/h2/test/test.in.txt";
public ArrayList getAllStatements(TestAll conf, String file) throws Exception {
config = conf;
fileName = file;
statements = new ArrayList();
test();
return statements;
}
public void test() throws Exception {
if(config.networked && config.big) {
return;
}
alwaysReconnect = false;
testScript();
if(!config.memory) {
if(config.big) {
alwaysReconnect = true;
testScript();
}
}
}
public void testScript() throws Exception {
deleteDb("script");
String outfile = "test.out.txt";
String infile = fileName;
conn = getConnection("script");
stat = conn.createStatement();
out = new PrintStream(new FileOutputStream(outfile));
errors = new StringBuffer();
testFile(infile);
conn.close();
if(errors.length()>0) {
throw new Exception("errors:\n" + errors.toString());
}
}
private String readLine() throws IOException {
if (putback != null) {
String s = putback;
putback = null;
return s;
}
while(true) {
String s = in.readLine();
if(s==null) {
return s;
}
s = s.trim();
if(s.length() > 0) {
return s;
}
}
}
private void testFile(String infile) throws Exception {
InputStream is = getClass().getClassLoader().getResourceAsStream(infile);
in = new LineNumberReader(new InputStreamReader(is, "Cp1252"));
StringBuffer buff = new StringBuffer();
while (true) {
String sql = readLine();
if (sql == null) {
break;
}
if (sql.startsWith("--")) {
write(sql);
} else if (sql.startsWith(">")) {
// do nothing
} else if (sql.endsWith(";")) {
write(sql);
buff.append(sql.substring(0, sql.length() - 1));
sql = buff.toString();
buff = new StringBuffer();
process(sql);
} else {
write(sql);
buff.append(sql);
buff.append('\n');
}
}
}
private boolean containsTempTables() throws SQLException {
ResultSet rs = conn.getMetaData().getTables(null, null, null, new String[]{"TABLE"});
while(rs.next()) {
String sql = rs.getString("SQL");
if(sql != null) {
if(sql.indexOf("TEMPORARY") >= 0) {
return true;
}
}
}
return false;
}
private void process(String sql) throws Exception {
if(alwaysReconnect) {
if(!containsTempTables()) {
boolean autocommit = conn.getAutoCommit();
if(autocommit) {
conn.close();
conn = getConnection("script");
conn.setAutoCommit(autocommit);
stat = conn.createStatement();
}
}
}
if(statements != null) {
statements.add(sql);
}
if (sql.indexOf('?') == -1) {
processStatement(sql);
} else {
String param = readLine();
write(param);
if (!param.equals("{")) {
throw new Error("expected '{', got " + param + " in " + sql);
}
try {
PreparedStatement prep = conn.prepareStatement(sql);
int count = 0;
while (true) {
param = readLine();
write(param);
if (param.startsWith("}")) {
break;
}
count += processPrepared(sql, prep, param);
}
writeResult("update count: " + count, null);
} catch (SQLException e) {
writeException(e);
}
}
write("");
}
private void setParameter(PreparedStatement prep, int i, String param)
throws SQLException {
if (param.equalsIgnoreCase("null")) {
param = null;
}
prep.setString(i, param);
}
private int processPrepared(String sql, PreparedStatement prep, String param)
throws Exception {
try {
StringBuffer buff = new StringBuffer();
int index = 0;
for (int i = 0; i < param.length(); i++) {
char c = param.charAt(i);
if (c == ',') {
setParameter(prep, ++index, buff.toString());
buff = new StringBuffer();
} else if (c == '"') {
while (true) {
c = param.charAt(++i);
if (c == '"') {
break;
}
buff.append(c);
}
} else if (c > ' ') {
buff.append(c);
}
}
if (buff.length() > 0) {
setParameter(prep, ++index, buff.toString());
}
if (prep.execute()) {
writeResultSet(sql, prep.getResultSet());
return 0;
}
return prep.getUpdateCount();
} catch (SQLException e) {
writeException(e);
return 0;
}
}
private int processStatement(String sql) throws Exception {
try {
if (stat.execute(sql)) {
writeResultSet(sql, stat.getResultSet());
} else {
int count = stat.getUpdateCount();
writeResult(count < 1 ? "ok" : "update count: " + count, null);
}
} catch (SQLException e) {
writeException(e);
}
return 0;
}
private String formatString(String s) {
if (s== null) {
return "null";
}
return s.replace('\n', ' ');
}
private void writeResultSet(String sql, ResultSet rs) throws Exception {
boolean ordered = StringUtils.toLowerEnglish(sql).indexOf("order by") >= 0;
ResultSetMetaData meta = rs.getMetaData();
int len = meta.getColumnCount();
int[] max = new int[len];
String[] head = new String[len];
for (int i = 0; i < len; i++) {
String label = formatString(meta.getColumnLabel(i + 1));
max[i] = label.length();
head[i] = label;
}
result.clear();
while (rs.next()) {
String[] row = new String[len];
for (int i = 0; i < len; i++) {
String data = formatString(rs.getString(i + 1));
if (max[i] < data.length()) {
max[i] = data.length();
}
row[i] = data;
}
result.add(row);
}
rs.close();
writeResult(format(head, max), null);
writeResult(format(null, max), null);
String[] array = new String[result.size()];
for (int i = 0; i < result.size(); i++) {
array[i] = format((String[]) result.get(i), max);
}
if (!ordered) {
sort(array);
}
int i = 0;
for (; i < array.length; i++) {
writeResult(array[i], null);
}
writeResult((ordered ? "rows (ordered): " : "rows: ") + i, null);
}
private String format(String[] row, int[] max) throws Exception {
int length = max.length;
StringBuffer buff = new StringBuffer();
for (int i = 0; i < length; i++) {
if(i>0) {
buff.append(' ');
}
if (row == null) {
for (int j = 0; j < max[i]; j++) {
buff.append('-');
}
} else {
int len = row[i].length();
buff.append(row[i]);
if(i < length - 1) {
for (int j = len; j < max[i]; j++) {
buff.append(' ');
}
}
}
}
return buff.toString();
}
private void writeException(SQLException e) throws Exception {
writeResult("exception", e);
}
private void writeResult(String s, SQLException e) throws Exception {
checkNotGeneralException(e);
s = ("> " + s).trim();
String compare = readLine();
if (compare != null && compare.startsWith(">")) {
if (!compare.equals(s)) {
errors.append("line: ");
errors.append(line);
errors.append("\nexp: ");
errors.append(compare);
errors.append("\ngot: ");
errors.append(s);
errors.append("\n");
if(e!=null) {
e.printStackTrace();
}
if(failFast) {
new Exception(errors.toString()).printStackTrace();
conn.close();
System.exit(1);
}
}
} else {
putback = compare;
}
write(s);
}
private void write(String s) throws Exception {
line++;
out.println(s);
}
private void sort(String[] a) {
for (int i = 1, j, len = a.length; i < len; i++) {
String t = a[i];
for (j = i - 1; j >= 0 && t.compareTo(a[j]) < 0; j--) {
a[j + 1] = a[j];
}
a[j + 1] = t;
}
}
}
/*
* 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.db;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.sql.Connection;
import java.sql.ResultSet;
import org.h2.test.TestBase;
import org.h2.util.ScriptReader;
public class TestScriptSimple extends TestBase {
private Connection conn;
public void test() throws Exception {
if(config.memory || config.big || config.networked) {
return;
}
deleteDb("scriptSimple");
reconnect();
String infile = "org/h2/test/testSimple.in.txt";
InputStream is = getClass().getClassLoader().getResourceAsStream(infile);
LineNumberReader lineReader = new LineNumberReader(new InputStreamReader(is, "Cp1252"));
ScriptReader reader = new ScriptReader(lineReader);
while(true) {
String sql = reader.readStatement();
if(sql == null) {
break;
}
sql = sql.trim();
// System.out.println(sql);
if("@reconnect".equals(sql)) {
reconnect();
} else if(sql.length() == 0) {
// ignore
} else if(sql.startsWith("select")) {
ResultSet rs = conn.createStatement().executeQuery(sql);
while(rs.next()) {
String expected = reader.readStatement().trim();
String got = "> " + rs.getString(1);
check(expected, got);
}
} else {
conn.createStatement().execute(sql);
}
}
conn.close();
}
private void reconnect() throws Exception {
if(conn != null) {
conn.close();
}
conn = getConnection("scriptSimple");
}
}
/*
* 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.db;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import org.h2.test.TestBase;
public class TestSequence extends TestBase {
public void test() throws Exception {
deleteDb("sequence");
Connection conn=getConnection("sequence");
Statement stat = conn.createStatement();
stat.execute("create sequence testseq");
conn.setAutoCommit(false);
Connection conn2=getConnection("sequence");
Statement stat2 = conn2.createStatement();
conn2.setAutoCommit(false);
long last = 0;
for(int i=0; i<100; i++) {
long v1 = getNext(stat);
check(v1 > last);
last = v1;
for(int j=0; j<100; j++) {
long v2 = getNext(stat2);
check(v2 > last);
last = v2;
}
}
conn2.close();
conn.close();
}
private long getNext(Statement stat) throws Exception {
ResultSet rs = stat.executeQuery("call next value for testseq");
rs.next();
long value = rs.getLong(1);
return value;
}
}
/*
* 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.db;
import java.io.*;
import java.sql.*;
import org.h2.test.TestBase;
public class TestSpaceReuse extends TestBase {
public void test() throws Exception {
if(config.memory) {
return;
}
deleteDb("spaceReuse");
long first = 0, now = 0;
for (int i = 0; i < 10; i++) {
Connection conn = getConnection("spaceReuse");
Statement stat = conn.createStatement();
stat.execute("create table if not exists t(i int)");
stat.execute("insert into t select x from system_range(1, 500)");
conn.close();
conn = getConnection("spaceReuse");
conn.createStatement().execute("delete from t");
conn.close();
now = new File(BASE_DIR + "/spaceReuse.data.db").length();
if(first == 0) {
first = now;
}
}
if(now > first) {
this.error("first: " + first + " now: " + now);
}
}
}
/*
* 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.db;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.Statement;
import org.h2.test.TestBase;
/**
* @author Thomas
*/
public class TestSpeed extends TestBase {
// java -cp .;..\..\hsqldb\lib\hsqldb.jar -Xrunhprof:heap=sites,depth=6 org.h2.test.TestAll
// java -Xrunhprof:heap=sites org.h2.test.TestAll
// java -Xprof org.h2.test.TestAll
// TODO test: here is more code, currently untested!
public void test() throws Exception {
deleteDb("speed");
Connection conn;
conn = getConnection("speed");
// conn = getConnection("speed;ASSERT=0;MAX_MEMORY_ROWS=1000000;MAX_LOG_SIZE=1000");
// Class.forName("org.hsqldb.jdbcDriver");
// conn = DriverManager.getConnection("jdbc:hsqldb:speed");
Statement stat = conn.createStatement();
stat.execute("DROP TABLE IF EXISTS TEST");
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))");
int len = getSize(1, 10000);
for(int i=0; i<len; i++) {
stat.execute("SELECT ID, NAME FROM TEST ORDER BY ID");
}
//drop table if exists test;
//CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255));
//@LOOP 100000 INSERT INTO TEST VALUES(?, 'Hello');
//@LOOP 100000 SELECT * FROM TEST WHERE ID = ?;
// stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))");
// for(int i=0; i<1000; i++) {
// stat.execute("INSERT INTO TEST VALUES("+i+", 'Hello')");
// }
// stat.execute("CREATE TABLE TESTA(ID INT PRIMARY KEY, NAME VARCHAR(255))");
// stat.execute("INSERT INTO TESTA VALUES(0, 'Hello')");
long time = System.currentTimeMillis();
// for(int i=1; i<8000; i*=2) {
// stat.execute("INSERT INTO TESTA SELECT ID+"+i+", NAME FROM TESTA");
//
//// stat.execute("INSERT INTO TESTA VALUES("+i+", 'Hello')");
// }
// for(int i=0; i<4; i++) {
// ResultSet rs = stat.executeQuery("SELECT * FROM TESTA");
// while(rs.next()) {
// rs.getInt(1);
// rs.getString(2);
// }
// }
// System.out.println(System.currentTimeMillis()-time);
//
// stat.execute("CREATE TABLE TESTB(ID INT PRIMARY KEY, NAME VARCHAR(255))");
// for(int i=0; i<80000; i++) {
// stat.execute("INSERT INTO TESTB VALUES("+i+", 'Hello')");
// }
// conn.close();
// System.exit(0);
// int testParser;
// java -Xrunhprof:cpu=samples,depth=8 -cp . org.h2.test.TestAll
//
// stat.execute("CREATE TABLE TEST(ID INT)");
// stat.execute("INSERT INTO TEST VALUES(1)");
// ResultSet rs = stat.executeQuery("SELECT ID OTHERID FROM TEST");
// rs.next();
// rs.getString("ID");
// stat.execute("DROP TABLE TEST");
// long time = System.currentTimeMillis();
stat.execute("DROP TABLE IF EXISTS TEST");
stat.execute("CREATE CACHED TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))");
PreparedStatement prep = conn.prepareStatement("INSERT INTO TEST VALUES(?, ?)");
int max = getSize(1, 10000);
for(int i=0; i<max; i++) {
prep.setInt(1, i);
prep.setString(2, "Helloasdfaldsjflajdflajdslfoajlskdfkjasdfadsfasdfadsfadfsalksdjflasjflajsdlkfjaksdjflkskd" + i);
//prep.setString(2, "Helloasdfaldsjflajdflajdslfoajlskdfkjasdfadsfasdfadsfadfsalksdjflasjflajsdlkfjaksdjflkskd");
prep.execute();
// System.out.println("i="+i);
// stat.execute("INSERT INTO TEST VALUES("+i+", 'Helloasdfaldsjflajdflajdslfaajlskdfkjasdfadsfasdfadsfadfsalksdjflasjflajsdlkfjaksdjflkskd"+i+"')");
// ResultSet rs = stat.executeQuery("SELECT * FROM TEST WHERE ID="+i);
// if(!rs.next()) {
// throw new Error("hey! i="+i);
// }
// if(rs.next()) {
// throw new Error("hey! i="+i);
// }
}
// System.exit(0);
// System.out.println("END "+Value.cacheHit+" "+Value.cacheMiss);
time = System.currentTimeMillis() - time;
trace(time+" insert");
//if(true) return;
// if(config.log) {
// System.gc();
// System.gc();
// log("mem="+(Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory())/1024);
// }
// conn.close();
time = System.currentTimeMillis();
prep = conn.prepareStatement("UPDATE TEST SET NAME='Another data row which is long' WHERE ID=?");
for(int i=0; i<max; i++) {
prep.setInt(1, i);
prep.execute();
// System.out.println("updated "+i);
// stat.execute("UPDATE TEST SET NAME='Another data row which is long' WHERE ID="+i);
// ResultSet rs = stat.executeQuery("SELECT * FROM TEST WHERE ID="+i);
// if(!rs.next()) {
// throw new Error("hey! i="+i);
// }
// if(rs.next()) {
// throw new Error("hey! i="+i);
// }
}
// for(int i=0; i<max; i++) {
// stat.execute("DELETE FROM TEST WHERE ID="+i);
// ResultSet rs = stat.executeQuery("SELECT * FROM TEST WHERE ID="+i);
// if(rs.next()) {
// throw new Error("hey!");
// }
// }
time = System.currentTimeMillis() - time;
trace(time+" update");
conn.close();
time = System.currentTimeMillis() - time;
trace(time+" close");
}
// private void testOuterJoin() throws Exception {
// Class.forName("org.h2.jdbc.jdbcDriver");
// Connection conn = DriverManager.getConnection("jdbc:h2:test");
// Class.forName("org.hsqldb.jdbcDriver");
// Connection conn = DriverManager.getConnection("jdbc:hsqldb:test");
// Connection conn = DriverManager.getConnection("jdbc:hsqldb:mem:.");
// Statement stat = conn.createStatement();
//
// int len = getSize(1, 10000);
// create table test(id int primary key, name varchar(255))
// insert into test values(1, 'b')
// insert into test values(2, 'c')
// insert into test values(3, 'a')
// select * from test order by name desc
// select min(id)+max(id) from test
// select abs(-1), id from test order by name desc
// select id from test group by id
// long start = System.currentTimeMillis();
//
// stat.executeUpdate("DROP TABLE IF EXISTS TEST");
// stat.executeUpdate("CREATE TABLE Test(" + "Id INTEGER PRIMARY KEY, "
// + "FirstName VARCHAR(20), " + "Name VARCHAR(50), "
// + "ZIP INTEGER)");
//
//
// stat.execute("create table a(a1 varchar(1), a2 int)");
// stat.execute("create table b(b1 varchar(1), b2 int)");
// stat.execute("insert into a values(null, 12)");
// stat.execute("insert into a values('a', 22)");
// stat.execute("insert into a values('b', 32)");
// stat.execute("insert into b values(null, 14)");
// stat.execute("insert into b values('a', 14)");
// stat.execute("insert into b values('c', 15)");
// create table a(a1 varchar(1), a2 int);
// create table b(b1 varchar(1), b2 int);
// insert into a values(null, 12);
// insert into a values('a', 22);
// insert into a values('b', 32);
// insert into b values(null, 14);
// insert into b values('a', 14);
// insert into b values('c', 15);
//query(stat, "select * from a left outer join b on a.a1=b.b1");
// should be 3 rows
// query(stat, "select * from a left outer join b on ((a.a1=b.b1) or (a.a1 is null and b.b1 is null))");
// A1 A2 B1 B2
// null 12 null 14
// a 22 a 14
// b 32 null null
// should be 3 rows
// query(stat, "select * from a left outer join b on ((a.a1=b.b1) or (a.a1 is null and b.b1 is null))");
// A1 A2 B1 B2
// 12 14
// a 22 a 14
// b 32
// should be 2 rows
// query(stat, "select * from a left outer join b on (1=1) where ((a.a1=b.b1) or (a.a1 is null and b.b1 is null))");
// A1 A2 B1 B2
// 12 14
// a 22 a 14
// should be 1 row
// query(stat, "select * from a left outer join b on (1=1) where a.a1=b.b1");
// should be 3 rows
// query(stat, "select * from a left outer join b on a.a1=b.b1 where (1=1)");
// if(true) return;
//query(stat, "SELECT T1.ID, T2.ID FROM TEST T1, TEST T2 WHERE T1.ID > T2.ID");
// PreparedStatement prep;
//
// prep = conn
// .prepareStatement("INSERT INTO Test VALUES(?,'Julia','Peterson-Clancy',?)");
//query(stat, "SELECT * FROM TEST WHERE NAME LIKE 'Ju%'");
// long time = System.currentTimeMillis();
//
// for (int i = 0; i < len; i++) {
// prep.setInt(1, i);
// prep.setInt(2, i);
// prep.execute();
//query(stat, "SELECT * FROM TEST");
//if(i % 2 == 0) {
// stat.executeUpdate("INSERT INTO Test VALUES("+i+",'Julia','Peterson-Clancy',"+i+")");
//} else {
// stat.executeUpdate("INSERT INTO TEST VALUES("+i+",'Julia','Peterson-Clancy',"+i+")");
//}
// }
// query(stat, "SELECT ABS(-1) FROM TEST");
// conn.close();
// if(true) return;
// stat.executeUpdate("UPDATE Test SET Name='Hans' WHERE Id=1");
//query(stat, "SELECT * FROM Test WHERE Id=1");
//stat.executeUpdate("DELETE FROM Test WHERE Id=1");
//query(stat, "SELECT * FROM TEST");
// conn.close();
//
// if(true) {
// return;
// }
// query(stat, "SELECT * FROM TEST WHERE ID = 182");
/*
for(int i=0; i<len; i++) {
query(stat, "SELECT * FROM TEST WHERE ID = "+i);
}
*/
// System.out.println("insert=" + (System.currentTimeMillis() - time));
// conn.setAutoCommit(false);
// prep = conn.prepareStatement("UPDATE Test SET FirstName='Hans' WHERE Id=?");
//
// time = System.currentTimeMillis();
//
// for (int i = 0; i < len; i++) {
// prep.setInt(1, i);
// if(i%10 == 0) {
// System.out.println(i+" ");
// }
// prep.execute();
// stat.executeUpdate("UPDATE Test SET FirstName='Hans' WHERE Id="+i);
// if(i==5) conn.close();
//query(stat, "SELECT * FROM TEST");
// }
// conn.rollback();
// System.out.println("update=" + (System.currentTimeMillis() - time));
//
// prep = conn.prepareStatement("SELECT * FROM Test WHERE Id=?");
//
// time = System.currentTimeMillis();
//
// for (int i = 0; i < len; i++) {
// prep.setInt(1, i);
// prep.execute();
//// stat.executeQuery("SELECT * FROM Test WHERE Id="+i);
// }
// System.out.println("select=" + (System.currentTimeMillis() - time));
// query(stat, "SELECT * FROM TEST");
// prep = conn.prepareStatement("DELETE FROM Test WHERE Id=?");
//
// time = System.currentTimeMillis();
//
// for (int i = 0; i < len; i++) {
//// stat.executeUpdate("DELETE FROM Test WHERE Id="+i);
// prep.setInt(1, i);
// //System.out.println("delete "+i);
// prep.execute();
// // query(stat, "SELECT * FROM TEST");
// }
// System.out.println("delete=" + (System.currentTimeMillis() - time));
// System.out.println("total=" + (System.currentTimeMillis() - start));
// stat.executeUpdate("DROP TABLE Test");
//
// conn.close();
/*
* stat.executeUpdate("CREATE TABLE TEST(ID INT PRIMARY KEY, VALUE
* DATE)"); stat.executeUpdate("INSERT INTO TEST VALUES(1, DATE
* '2004-12-19')"); stat.executeUpdate("INSERT INTO TEST VALUES(2, DATE
* '2004-12-20')"); query(stat, "SELECT * FROM TEST WHERE VALUE > DATE
* '2004-12-19'");
*/
/*
* stat.executeUpdate("CREATE TABLE TEST(ID INT PRIMARY KEY, VALUE
* BINARY(10))"); stat.executeUpdate("INSERT INTO TEST VALUES(1,
* X'0011')"); stat.executeUpdate("INSERT INTO TEST VALUES(2,
* X'01FFAA')"); query(stat, "SELECT * FROM TEST WHERE VALUE >
* X'0011'");
*/
/*
* stat.executeUpdate("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME
* VARCHAR(255))"); stat.executeUpdate("INSERT INTO TEST VALUES(1,
* 'Hallo')"); stat.executeUpdate("INSERT INTO TEST VALUES(2,
* 'World')");
*/
/*
* stat.executeUpdate("CREATE UNIQUE INDEX TEST_NAME ON TEST(NAME)");
* stat.executeUpdate("DROP INDEX TEST_NAME");
* stat.executeUpdate("INSERT INTO TEST VALUES(2, 'Hallo')");
* stat.executeUpdate("DELETE FROM TEST"); for(int i=0; i <100; i++) {
* stat.executeUpdate("INSERT INTO TEST VALUES("+i+", 'Test"+i+"')"); }
*/
/*
* query(stat, "SELECT T1.ID, T1.NAME FROM TEST T1"); query(stat,
* "SELECT T1.ID, T1.NAME, T2.ID, T2.NAME FROM TEST T1, TEST T2");
* query(stat, "SELECT T1.ID, T1.NAME, T2.ID, T2.NAME FROM TEST T1, TEST
* T2 WHERE T1.ID = T2.ID");
*/
/*
* query(stat, "SELECT * FROM TEST WHERE ID = 1");
* stat.executeUpdate("DELETE FROM TEST WHERE ID = 2"); query(stat,
* "SELECT * FROM TEST WHERE ID < 10"); query(stat, "SELECT * FROM TEST
* WHERE ID = 2"); stat.executeUpdate("UPDATE TEST SET NAME = 'World'
* WHERE ID = 5"); query(stat, "SELECT * FROM TEST WHERE ID = 5");
* query(stat, "SELECT * FROM TEST WHERE ID < 10");
*/
// }
// private static void query(Statement stat, String sql) throws SQLException {
// System.out.println("--------- " + sql);
// ResultSet rs = stat.executeQuery(sql);
// ResultSetMetaData meta = rs.getMetaData();
// while (rs.next()) {
// for (int i = 0; i < meta.getColumnCount(); i++) {
// System.out.print("[" + meta.getColumnLabel(i + 1) + "]="
// + rs.getString(i + 1) + " ");
// }
// System.out.println();
// }
// }
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.db;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.h2.test.TestBase;
public class TestTempTables extends TestBase {
public void test() throws Exception {
deleteDb("tempTables");
Connection c1 = getConnection("tempTables");
Connection c2 = getConnection("tempTables");
Statement s1 = c1.createStatement();
Statement s2 = c2.createStatement();
s1.execute("CREATE LOCAL TEMPORARY TABLE LT(A INT)");
s1.execute("CREATE GLOBAL TEMPORARY TABLE GT1(ID INT)");
s2.execute("CREATE GLOBAL TEMPORARY TABLE GT2(ID INT)");
s2.execute("CREATE LOCAL TEMPORARY TABLE LT(B INT)");
s2.execute("SELECT B FROM LT");
s1.execute("SELECT A FROM LT");
s1.execute("SELECT * FROM GT1");
s2.execute("SELECT * FROM GT1");
s1.execute("SELECT * FROM GT2");
s2.execute("SELECT * FROM GT2");
s2.execute("DROP TABLE GT1");
s2.execute("DROP TABLE GT2");
s2.execute("DROP TABLE LT");
s1.execute("DROP TABLE LT");
// temp tables: 'on commit' syntax is currently not documented, because not tested well
// and hopefully nobody is using it, as it looks like functional sugar
// (this features are here for compatibility only)
ResultSet rs;
c1.setAutoCommit(false);
s1.execute("create local temporary table testtemp(id int) on commit delete rows");
s1.execute("insert into testtemp values(1)");
rs = s1.executeQuery("select * from testtemp");
checkResultRowCount(rs, 1);
c1.commit();
rs = s1.executeQuery("select * from testtemp");
checkResultRowCount(rs, 0);
s1.execute("drop table testtemp");
s1.execute("create local temporary table testtemp(id int) on commit drop");
s1.execute("insert into testtemp values(1)");
rs = s1.executeQuery("select * from testtemp");
checkResultRowCount(rs, 1);
c1.commit();
try {
rs = s1.executeQuery("select * from testtemp");
error("testtemp should have been dropped automatically");
} catch(SQLException e) {
checkNotGeneralException(e);
}
c1.close();
c2.close();
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.db;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement;
import java.util.Random;
import java.util.Vector;
import org.h2.test.TestBase;
public class TestTransaction extends TestBase {
public void test() throws Exception {
testSavepoint();
testIsolation();
}
public void testSavepoint() throws Exception {
deleteDb("transaction");
Connection conn = getConnection("transaction");
Statement stat = conn.createStatement();
stat.execute("CREATE TABLE TEST0(ID IDENTITY, NAME VARCHAR)");
stat.execute("CREATE TABLE TEST1(NAME VARCHAR, ID IDENTITY, X TIMESTAMP DEFAULT CURRENT_TIMESTAMP)");
conn.setAutoCommit(false);
int[] count = new int[2];
int[] countCommitted = new int[2];
int[] countSave = new int[2];
int len = getSize(2000, 10000);
Random random = new Random(10);
Savepoint sp = null;
for(int i=0; i<len; i++) {
int tableId = random.nextInt(2);
String table="TEST" + tableId;
int op = random.nextInt(6);
switch(op) {
case 0:
stat.execute("INSERT INTO "+table+"(NAME) VALUES('op"+i+"')");
count[tableId]++;
break;
case 1:
if(count[tableId] > 0) {
stat.execute("DELETE FROM "+table+" WHERE ID=SELECT MIN(ID) FROM "+table);
count[tableId]--;
}
break;
case 2:
sp = conn.setSavepoint();
countSave[0] = count[0]; countSave[1] = count[1];
break;
case 3:
if(sp != null) {
conn.rollback(sp);
count[0] = countSave[0]; count[1] = countSave[1];
}
break;
case 4:
conn.commit();
sp = null;
countCommitted[0] = count[0]; countCommitted[1] = count[1];
break;
case 5:
conn.rollback();
sp = null;
count[0] = countCommitted[0]; count[1] = countCommitted[1];
break;
}
checkTableCount(stat, "TEST0", count[0]);
checkTableCount(stat, "TEST1", count[1]);
}
conn.close();
}
private void checkTableCount(Statement stat, String tableName, int count) throws Exception {
ResultSet rs;
rs = stat.executeQuery("SELECT COUNT(*) FROM " + tableName);
rs.next();
check(count, rs.getInt(1));
}
public void testIsolation() throws Exception {
Connection conn = getConnection("transaction");
trace("default TransactionIsolation="+conn.getTransactionIsolation());
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
check(conn.getTransactionIsolation()==Connection.TRANSACTION_READ_COMMITTED);
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
check(conn.getTransactionIsolation()==Connection.TRANSACTION_SERIALIZABLE);
Statement stat=conn.createStatement();
check(conn.getAutoCommit());
conn.setAutoCommit(false);
checkFalse(conn.getAutoCommit());
conn.setAutoCommit(true);
check(conn.getAutoCommit());
test(stat, "CREATE TABLE TEST(ID INT PRIMARY KEY)");
conn.commit();
test(stat, "INSERT INTO TEST VALUES(0)");
conn.rollback();
testValue(stat, "SELECT COUNT(*) FROM TEST","1");
conn.setAutoCommit(false);
test(stat, "DELETE FROM TEST");
//testValue("SELECT COUNT(*) FROM TEST", "0");
conn.rollback();
testValue(stat, "SELECT COUNT(*) FROM TEST", "1");
conn.commit();
conn.setAutoCommit(true);
testNestedResultSets(conn);
conn.setAutoCommit(false);
testNestedResultSets(conn);
conn.close();
}
void testNestedResultSets(Connection conn) throws Exception {
Statement stat = conn.createStatement();
test(stat, "CREATE TABLE NEST1(ID INT PRIMARY KEY,VALUE VARCHAR(255))");
test(stat, "CREATE TABLE NEST2(ID INT PRIMARY KEY,VALUE VARCHAR(255))");
DatabaseMetaData meta=conn.getMetaData();
Vector result;
ResultSet rs1,rs2;
result=new Vector();
rs1=meta.getTables(null,null,"NEST%",null);
while(rs1.next()) {
String table=rs1.getString("TABLE_NAME");
rs2=meta.getColumns(null,null,table,null);
while(rs2.next()) {
String column=rs2.getString("COLUMN_NAME");
trace("Table: "+table+" Column: "+column);
result.add(table+"."+column);
}
}
if(result.size()!=4) {
error("Wrong result, should be NEST1.ID, NEST1.NAME, NEST2.ID, NEST2.NAME but is "+result);
}
result=new Vector();
test(stat, "INSERT INTO NEST1 VALUES(1,'A')");
test(stat, "INSERT INTO NEST1 VALUES(2,'B')");
test(stat, "INSERT INTO NEST2 VALUES(1,'1')");
test(stat, "INSERT INTO NEST2 VALUES(2,'2')");
Statement s1=conn.createStatement();
Statement s2=conn.createStatement();
rs1=s1.executeQuery("SELECT * FROM NEST1 ORDER BY ID");
while(rs1.next()) {
rs2=s2.executeQuery("SELECT * FROM NEST2 ORDER BY ID");
while(rs2.next()) {
String v1=rs1.getString("VALUE");
String v2=rs2.getString("VALUE");
result.add(v1+"/"+v2);
}
}
if(result.size()!=4) {
error("Wrong result, should be A/1, A/2, B/1, B/2 but is "+result);
}
result=new Vector();
rs1=s1.executeQuery("SELECT * FROM NEST1 ORDER BY ID");
rs2=s1.executeQuery("SELECT * FROM NEST2 ORDER BY ID");
try {
rs1.next();
error("next worked on a closed result set");
} catch(SQLException e) {
checkNotGeneralException(e);
}
// this is already closed, so but closing again should no do any harm
rs1.close();
while(rs2.next()) {
String v1=rs2.getString("VALUE");
result.add(v1);
}
if(result.size()!=2) {
error("Wrong result, should be A, B but is "+result);
}
test(stat, "DROP TABLE NEST1");
test(stat, "DROP TABLE NEST2");
}
void testValue(Statement stat, String sql, String data) throws Exception {
ResultSet rs=stat.executeQuery(sql);
rs.next();
String s=rs.getString(1);
if(s==null ? (data!=null) : (!s.equals(data))) {
error("s= "+s+" should be: "+data);
}
}
void test(Statement stat, String sql) throws Exception {
trace(sql);
stat.execute(sql);
}
}
/*
* 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.db;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
import java.util.HashSet;
import org.h2.api.Trigger;
import org.h2.test.TestBase;
/**
* @author Thomas
*/
public class TestTriggersConstraints extends TestBase implements Trigger {
private static boolean mustNotCallTrigger;
public void test() throws Exception {
deleteDb("trigger");
testTriggers();
testConstraints();
}
private void testConstraints() throws Exception {
Connection conn = getConnection("trigger");
Statement stat = conn.createStatement();
stat.execute("DROP TABLE IF EXISTS TEST");
stat.execute("create table test(id int primary key, parent int)");
stat.execute("alter table test add constraint test_parent_id foreign key(parent) references test (id) on delete cascade");
stat.execute("insert into test select x, x/2 from system_range(0, 100)");
stat.execute("delete from test");
checkSingleValue(stat, "select count(*) from test", 0);
stat.execute("drop table test");
conn.close();
}
private void testTriggers() throws Exception {
mustNotCallTrigger = false;
Connection conn = getConnection("trigger");
Statement stat = conn.createStatement();
stat.execute("DROP TABLE IF EXISTS TEST");
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))");
// CREATE TRIGGER trigger {BEFORE|AFTER} {INSERT|UPDATE|DELETE} ON table [FOR EACH ROW] [QUEUE n] [NOWAIT] CALL triggeredClass
stat.execute("CREATE TRIGGER IF NOT EXISTS INS_BEFORE BEFORE INSERT ON TEST FOR EACH ROW NOWAIT CALL \""+getClass().getName()+"\"");
stat.execute("CREATE TRIGGER IF NOT EXISTS INS_BEFORE BEFORE INSERT ON TEST FOR EACH ROW NOWAIT CALL \""+getClass().getName()+"\"");
stat.execute("CREATE TRIGGER INS_AFTER AFTER INSERT ON TEST FOR EACH ROW NOWAIT CALL \""+getClass().getName()+"\"");
stat.execute("CREATE TRIGGER UPD_BEFORE BEFORE UPDATE ON TEST FOR EACH ROW NOWAIT CALL \""+getClass().getName()+"\"");
stat.execute("INSERT INTO TEST VALUES(1, 'Hello')");
ResultSet rs;
rs = stat.executeQuery("SCRIPT");
checkRows(rs, new String[]{
"CREATE TRIGGER PUBLIC.INS_BEFORE BEFORE INSERT ON PUBLIC.TEST FOR EACH ROW NOWAIT CALL \""+getClass().getName()+"\"",
"CREATE TRIGGER PUBLIC.INS_AFTER AFTER INSERT ON PUBLIC.TEST FOR EACH ROW NOWAIT CALL \""+getClass().getName()+"\"",
"CREATE TRIGGER PUBLIC.UPD_BEFORE BEFORE UPDATE ON PUBLIC.TEST FOR EACH ROW NOWAIT CALL \""+getClass().getName()+"\""
});
while(rs.next()) {
String sql = rs.getString(1);
if(sql.startsWith("CREATE TRIGGER")) {
System.out.println(sql);
}
}
rs = stat.executeQuery("SELECT * FROM TEST");
rs.next();
check(rs.getString(2), "Hello-updated");
checkFalse(rs.next());
stat.execute("UPDATE TEST SET NAME=NAME||'-upd'");
rs = stat.executeQuery("SELECT * FROM TEST");
rs.next();
check(rs.getString(2), "Hello-updated-upd-updated2");
checkFalse(rs.next());
mustNotCallTrigger = true;
stat.execute("DROP TRIGGER IF EXISTS INS_BEFORE");
stat.execute("DROP TRIGGER IF EXISTS INS_BEFORE");
try {
stat.execute("DROP TRIGGER INS_BEFORE");
error("must not work");
} catch(SQLException e) {
checkNotGeneralException(e);
}
stat.execute("DROP TRIGGER INS_AFTER");
stat.execute("DROP TRIGGER UPD_BEFORE");
stat.execute("UPDATE TEST SET NAME=NAME||'-upd-notrigger'");
stat.execute("INSERT INTO TEST VALUES(100, 'Insert-notrigger')");
conn.close();
conn = getConnection("trigger");
mustNotCallTrigger = false;
conn.close();
}
private void checkRows(ResultSet rs, String[] expected) throws Exception {
HashSet set = new HashSet(Arrays.asList(expected));
while(rs.next()) {
set.remove(rs.getString(1));
}
if(set.size()>0) {
error("set should be empty: " + set);
}
}
private String triggerName;
public void fire(Connection conn, Object[] oldRow, Object[] newRow) throws SQLException {
if(mustNotCallTrigger) {
throw new Error("must not be called now");
}
if(conn == null) {
throw new Error("connection is null");
}
if(triggerName.startsWith("INS_BEFORE")) {
newRow[1] = newRow[1] + "-updated";
} else if(triggerName.startsWith("INS_AFTER")) {
if(!newRow[1].toString().endsWith("-updated")) {
throw new Error("supposed to be updated");
}
} else if(triggerName.startsWith("UPD_BEFORE")) {
newRow[1] = newRow[1] + "-updated2";
} else if(triggerName.startsWith("UPD_AFTER")) {
if(!newRow[1].toString().endsWith("-updated2")) {
throw new Error("supposed to be updated2");
}
}
}
public void init(Connection conn, String schemaName, String triggerName, String tableName) {
this.triggerName = triggerName;
if(!"TEST".equals(tableName)) {
throw new Error("supposed to be TEST");
}
}
}
/*
* 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.db;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import org.h2.test.TestBase;
public class TestTwoPhaseCommit extends TestBase {
public void test() throws Exception {
if(config.memory || config.networked || config.logMode==0) {
return;
}
deleteDb("twoPhaseCommit");
prepare();
openWith(true);
test(true);
prepare();
openWith(false);
test(false);
}
void test(boolean rolledBack) throws Exception {
Connection conn = getConnection("twoPhaseCommit");
Statement stat = conn.createStatement();
stat.execute("SET WRITE_DELAY 0");
ResultSet rs = stat.executeQuery("SELECT * FROM TEST ORDER BY ID");
rs.next();
check(rs.getInt(1), 1);
check(rs.getString(2), "Hello");
if(rolledBack) {
} else {
rs.next();
check(rs.getInt(1), 2);
check(rs.getString(2), "World");
}
checkFalse(rs.next());
conn.close();
}
void openWith(boolean rollback) throws Exception {
Connection conn = getConnection("twoPhaseCommit");
Statement stat = conn.createStatement();
ArrayList list = new ArrayList();
ResultSet rs = stat.executeQuery("SELECT * FROM INFORMATION_SCHEMA.IN_DOUBT");
while(rs.next()) {
list.add(rs.getString("TRANSACTION"));
}
for(int i=0; i<list.size(); i++) {
String s = (String)list.get(i);
if(rollback) {
stat.execute("ROLLBACK TRANSACTION " + s);
} else {
stat.execute("COMMIT TRANSACTION " + s);
}
}
conn.close();
}
void prepare() throws Exception {
deleteDb("twoPhaseCommit");
Connection conn = getConnection("twoPhaseCommit");
Statement stat = conn.createStatement();
stat.execute("SET WRITE_DELAY 0");
conn.setAutoCommit(false);
stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR)");
stat.execute("INSERT INTO TEST VALUES(1, 'Hello')");
conn.commit();
stat.execute("INSERT INTO TEST VALUES(2, 'World')");
stat.execute("PREPARE COMMIT XID_TEST_TRANSACTION_WITH_LONG_NAME");
crash(conn);
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论