/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public 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.concurrent.atomic.AtomicLong;
import org.h2.api.DatabaseEventListener;
import org.h2.store.fs.FileUtils;
import org.h2.test.TestBase;
import org.h2.tools.Backup;
import org.h2.tools.Restore;
import org.h2.util.Task;
/**
* Test for the BACKUP SQL statement.
*/
public class TestBackup extends TestBase {
/**
* Run just this test.
*
* @param a ignored
*/
public static void main(String... a) throws Exception {
TestBase.createCaller().init().test();
}
public void test() throws SQLException {
if (config.memory) {
return;
}
testConcurrentBackup();
testBackupRestoreLobStatement();
testBackupRestoreLob();
testBackup();
deleteDb("backup");
FileUtils.delete(getBaseDir() + "/backup.zip");
}
private void testConcurrentBackup() throws SQLException {
if (config.networked || !config.big) {
return;
}
deleteDb("backup");
String url = getURL("backup;multi_threaded=true", true);
Connection conn = getConnection(url);
final Statement stat = conn.createStatement();
stat.execute("create table test(id int primary key, name varchar)");
stat.execute("insert into test select x, 'Hello' from system_range(1, 2)");
conn.setAutoCommit(false);
Connection conn1;
conn1 = getConnection(url);
final AtomicLong updateEnd = new AtomicLong();
final Statement stat1 = conn.createStatement();
Task task = new Task() {
public void call() throws Exception {
while (!stop) {
if (System.currentTimeMillis() < updateEnd.get()) {
stat.execute("update test set name = 'Hallo'");
stat1.execute("checkpoint");
stat.execute("update test set name = 'Hello'");
stat.execute("commit");
stat.execute("checkpoint");
} else {
Thread.sleep(10);
}
}
}
};
Connection conn2;
conn2 = getConnection(url + ";database_event_listener='" + BackupListener.class.getName() + "'");
Statement stat2 = conn2.createStatement();
task.execute();
for (int i = 0; i < 10; i++) {
updateEnd.set(System.currentTimeMillis() + 2000);
stat2.execute("backup to '"+getBaseDir()+"/backup.zip'");
stat2.execute("checkpoint");
Restore.execute(getBaseDir() + "/backup.zip", getBaseDir() + "/t2", "backup", true);
Connection conn3;
conn3 = getConnection("t2/backup");
Statement stat3 = conn3.createStatement();
stat3.execute("script");
ResultSet rs = stat3.executeQuery("select * from test where name='Hallo'");
while (rs.next()) {
fail();
}
conn3.close();
}
task.get();
conn.close();
conn1.close();
conn2.close();
}
/**
* A backup listener to test concurrent backup.
*/
public static class BackupListener implements DatabaseEventListener {
public void closingDatabase() {
// ignore
}
public void exceptionThrown(SQLException e, String sql) {
// ignore
}
public void init(String url) {
// ignore
}
public void opened() {
// ignore
}
public void setProgress(int state, String name, int x, int max) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// ignore
}
if (x % 400 == 0) {
// System.out.println("state: " + state +
// " name: " + name + " x:" + x + "/" + max);
}
}
}
private void testBackupRestoreLob() throws SQLException {
deleteDb("backup");
Connection conn = getConnection("backup");
conn.createStatement().execute("create table test(x clob) as select space(10000)");
conn.close();
Backup.execute(getBaseDir() + "/backup.zip", getBaseDir(), "backup", true);
deleteDb("backup");
Restore.execute(getBaseDir() + "/backup.zip", getBaseDir(), "backup", true);
}
private void testBackupRestoreLobStatement() throws SQLException {
deleteDb("backup");
Connection conn = getConnection("backup");
conn.createStatement().execute("create table test(x clob) as select space(10000)");
conn.createStatement().execute("backup to '" +getBaseDir() + "/backup.zip"+"'");
conn.close();
deleteDb("backup");
Restore.execute(getBaseDir() + "/backup.zip", getBaseDir(), "backup", true);
}
private void testBackup() throws SQLException {
deleteDb("backup");
deleteDb("restored");
Connection conn1, conn2, conn3;
Statement stat1, stat2, stat3;
conn1 = getConnection("backup");
stat1 = conn1.createStatement();
stat1.execute("create table test(id int primary key, name varchar(255))");
stat1.execute("insert into test values(1, 'first'), (2, 'second')");
stat1.execute("create table testlob(id int primary key, b blob, c clob)");
stat1.execute("insert into testlob values(1, space(10000), repeat('00', 10000))");
conn2 = getConnection("backup");
stat2 = conn2.createStatement();
stat2.execute("insert into test values(3, 'third')");
conn2.setAutoCommit(false);
stat2.execute("insert into test values(4, 'fourth (uncommitted)')");
stat2.execute("insert into testlob values(2, ' ', '00')");
stat1.execute("backup to '" + getBaseDir() + "/backup.zip'");
conn2.rollback();
assertEqualDatabases(stat1, stat2);
Restore.execute(getBaseDir() + "/backup.zip", getBaseDir(), "restored", true);
conn3 = getConnection("restored");
stat3 = conn3.createStatement();
assertEqualDatabases(stat1, stat3);
conn1.close();
conn2.close();
conn3.close();
deleteDb("restored");
}
}