提交 54e3a90a authored 作者: Noel Grandin's avatar Noel Grandin 提交者: GitHub

Merge pull request #382 from vitalus/master

Recover for "page store" H2   breaks LOBs consistency
......@@ -456,6 +456,8 @@ public class LobStorageBackend implements LobStorageInterface {
synchronized (conn.getSession()) {
try {
init();
ValueLobDb v = null;
if(!old.isRecoveryReference()){
long lobId = getNextLobId();
String sql = "INSERT INTO " + LOB_MAP + "(LOB, SEQ, POS, HASH, BLOCK) " +
"SELECT ?, SEQ, POS, HASH, BLOCK FROM " + LOB_MAP + " WHERE LOB = ?";
......@@ -474,7 +476,11 @@ public class LobStorageBackend implements LobStorageInterface {
prep.executeUpdate();
reuse(sql, prep);
ValueLobDb v = ValueLobDb.create(type, database, tableId, lobId, null, length);
v = ValueLobDb.create(type, database, tableId, lobId, null, length);
}else{
//Recovery process, no need to copy LOB using normal infrastructure
v = ValueLobDb.create(type, database, tableId, oldLobId, null, length);
}
return v;
} catch (SQLException e) {
throw DbException.convert(e);
......
......@@ -218,8 +218,10 @@ public class Recover extends Tool implements DataHandler {
long precision) {
DataHandler h = ((JdbcConnection) conn).getSession().getDataHandler();
verifyPageStore(h);
return ValueLobDb.create(Value.BLOB, h, LobStorageFrontend.TABLE_TEMP,
ValueLobDb lob = ValueLobDb.create(Value.BLOB, h, LobStorageFrontend.TABLE_TEMP,
lobId, null, precision);
lob.setRecoveryReference(true);
return lob;
}
private static void verifyPageStore(DataHandler h) {
......@@ -237,8 +239,10 @@ public class Recover extends Tool implements DataHandler {
long precision) {
DataHandler h = ((JdbcConnection) conn).getSession().getDataHandler();
verifyPageStore(h);
return ValueLobDb.create(Value.CLOB, h, LobStorageFrontend.TABLE_TEMP,
ValueLobDb lob = ValueLobDb.create(Value.CLOB, h, LobStorageFrontend.TABLE_TEMP,
lobId, null, precision);
lob.setRecoveryReference(true);
return lob;
}
/**
......
......@@ -55,6 +55,11 @@ public class ValueLobDb extends Value implements Value.ValueClob,
private int tableId;
private int hash;
//Arbonaut: 13.07.2016
// Fix for recovery tool.
private boolean isRecoveryReference = false;
private ValueLobDb(int type, DataHandler handler, int tableId, long lobId,
byte[] hmac, long precision) {
this.type = type;
......@@ -664,4 +669,12 @@ public class ValueLobDb extends Value implements Value.ValueClob,
return new ValueLobDb(type, small, precision);
}
public void setRecoveryReference(boolean isRecoveryReference) {
this.isRecoveryReference = isRecoveryReference;
}
public boolean isRecoveryReference() {
return isRecoveryReference;
}
}
......@@ -114,6 +114,7 @@ import org.h2.test.mvcc.TestMvcc3;
import org.h2.test.mvcc.TestMvcc4;
import org.h2.test.mvcc.TestMvccMultiThreaded;
import org.h2.test.poweroff.TestReorderWrites;
import org.h2.test.recover.RecoverLobTest;
import org.h2.test.rowlock.TestRowLocks;
import org.h2.test.server.TestAutoServer;
import org.h2.test.server.TestInit;
......@@ -858,6 +859,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
addTest(new TestReader());
addTest(new TestRecovery());
addTest(new TestScriptReader());
addTest(new RecoverLobTest());
addTest(createTest("org.h2.test.unit.TestServlet"));
addTest(new TestSecurity());
addTest(new TestShell());
......@@ -873,6 +875,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
addTest(new TestValueHashMap());
addTest(new TestWeb());
runAddedTests();
// serial
......
package org.h2.test.recover;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import org.h2.test.TestBase;
import org.h2.tools.DeleteDbFiles;
import org.h2.tools.Recover;
public class RecoverLobTest extends TestBase {
public static void main(String... a) throws Exception {
TestBase.createCaller().init().test();
}
@Override
public TestBase init() throws Exception {
TestBase tb = super.init();
config.mvStore=false;
return tb;
}
@Override
public void test() throws Exception {
testRecoverClob();
}
public void testRecoverClob() throws Exception {
DeleteDbFiles.execute(getBaseDir(), "recovery", true);
Connection conn = getConnection("recovery");
Statement stat = conn.createStatement();
stat.execute("create table test(id int, data clob)");
stat.execute("insert into test values(1, space(10000))");
stat.execute("insert into test values(2, space(20000))");
stat.execute("insert into test values(3, space(30000))");
stat.execute("insert into test values(4, space(40000))");
stat.execute("insert into test values(5, space(50000))");
stat.execute("insert into test values(6, space(60000))");
stat.execute("insert into test values(7, space(70000))");
stat.execute("insert into test values(8, space(80000))");
conn.close();
Recover.main("-dir", getBaseDir(), "-db", "recovery");
DeleteDbFiles.execute(getBaseDir(), "recovery", true);
conn = getConnection(
"recovery;init=runscript from '" +
getBaseDir() + "/recovery.h2.sql'");
stat = conn.createStatement();
ResultSet rs = stat.executeQuery("select * from test");
while(rs.next()){
int id = rs.getInt(1);
String data = rs.getString(2);
assertTrue(data != null);
assertTrue(data.length() == 10000 * id);
}
rs.close();
conn.close();
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论