提交 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.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.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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论