提交 b4699143 authored 作者: Thomas Mueller Graf's avatar Thomas Mueller Graf

CLOB and BLOB objects of removed rows were sometimes kept in the database file.

上级 f21d0c31
......@@ -21,6 +21,8 @@ Change Log
<h2>Next Version (unreleased)</h2>
<ul>
<li>CLOB and BLOB objects of removed rows were sometimes kept in the database file.
</li>
<li>Server mode: executing "shutdown" left a thread on the server.
</li>
<li>The condition "in(select...)" did not work correctly in some cases if the subquery had an "order by".
......
......@@ -1134,6 +1134,10 @@ public class Session extends SessionWithState {
if (SysProperties.CHECK && !v.isLinkedToTable()) {
DbException.throwInternalError();
}
if (removeLobMap == null) {
removeLobMap = New.hashMap();
removeLobMap.put(v.toString(), v);
}
}
/**
......
......@@ -104,7 +104,7 @@ public class LobStorageMap implements LobStorageInterface {
}
// search for the last block
// (in theory, only the latest lob can have unreferenced blocks,
// but the latest lob could by a copy of another one, and
// but the latest lob could be a copy of another one, and
// we don't know that, so we iterate over all lobs)
long lastUsedKey = -1;
for (Entry<Long, Object[]> e : lobMap.entrySet()) {
......
......@@ -28,7 +28,9 @@ import org.h2.api.ErrorCode;
import org.h2.engine.SysProperties;
import org.h2.jdbc.JdbcConnection;
import org.h2.message.DbException;
import org.h2.store.fs.FileUtils;
import org.h2.test.TestBase;
import org.h2.tools.Recover;
import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils;
import org.h2.util.StringUtils;
......@@ -57,6 +59,7 @@ public class TestLob extends TestBase {
@Override
public void test() throws Exception {
testRemoveAfterDeleteAndClose();
testRemovedAfterTimeout();
testConcurrentRemoveRead();
testCloseLobTwice();
......@@ -109,6 +112,33 @@ public class TestLob extends TestBase {
deleteDb("lob");
}
private void testRemoveAfterDeleteAndClose() throws Exception {
if (config.memory) {
return;
}
deleteDb("lob");
Connection conn = getConnection("lob");
Statement stat = conn.createStatement();
stat.execute("create table test(id int primary key, data clob)");
for (int i = 0; i < 10; i++) {
stat.execute("insert into test values(1, space(100000))");
if (i > 5) {
ResultSet rs = stat.executeQuery("select * from test");
rs.next();
Clob c = rs.getClob(2);
stat.execute("delete from test where id = 1");
c.getSubString(1, 10);
} else {
stat.execute("delete from test where id = 1");
}
}
// some clobs are removed only here (those that were queries for)
conn.close();
Recover.execute(getBaseDir(), "lob");
long size = FileUtils.size(getBaseDir() + "/lob.h2.sql");
assertTrue("size: " + size, size > 1000 && size < 10000);
}
private void testLargeClob() throws Exception {
deleteDb("lob");
Connection conn;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论