提交 06d783cc authored 作者: Sven Schrader's avatar Sven Schrader
...@@ -6,4 +6,4 @@ jdk: ...@@ -6,4 +6,4 @@ jdk:
before_script: cd h2 before_script: cd h2
script: ./build.sh jar script: ./build.sh jar testFast
...@@ -20,8 +20,18 @@ Change Log ...@@ -20,8 +20,18 @@ Change Log
<h1>Change Log</h1> <h1>Change Log</h1>
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul><li>ResultSet.getObject(..., Class) threw a ClassNotFoundException if the JTS suite was not in the classpath. <ul>
</li></ul> <li>PR #389, Handle LocalTime with nanosecond resolution, patch by katzyn
</li>
<li>PR #382, Recover for "page store" H2 breaks LOBs consistency, patch by vitalus
</li>
<li>PR #393, Run tests on Travis, patch by marschall
</li>
<li>Fix bug in REGEX_REPLACE, not parsing the mode parameter
</li>
<li>ResultSet.getObject(..., Class) threw a ClassNotFoundException if the JTS suite was not in the classpath.
</li>
</ul>
<h2>Version 1.4.193 Beta (2016-10-31)</h2> <h2>Version 1.4.193 Beta (2016-10-31)</h2>
<ul> <ul>
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
package org.h2.expression; package org.h2.expression;
import java.util.HashMap; import java.util.HashMap;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.command.Parser; import org.h2.command.Parser;
import org.h2.command.dml.Select; import org.h2.command.dml.Select;
......
...@@ -1386,7 +1386,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -1386,7 +1386,7 @@ public class Function extends Expression implements FunctionCall {
String regexp = v1.getString(); String regexp = v1.getString();
String replacement = v2.getString(); String replacement = v2.getString();
String regexpMode = v3 == null || v3.getString() == null ? "" : String regexpMode = v3 == null || v3.getString() == null ? "" :
v2.getString(); v3.getString();
int flags = makeRegexpFlags(regexpMode); int flags = makeRegexpFlags(regexpMode);
try { try {
result = ValueString.get( result = ValueString.get(
......
...@@ -456,6 +456,8 @@ public class LobStorageBackend implements LobStorageInterface { ...@@ -456,6 +456,8 @@ public class LobStorageBackend implements LobStorageInterface {
synchronized (conn.getSession()) { synchronized (conn.getSession()) {
try { try {
init(); init();
ValueLobDb v = null;
if(!old.isRecoveryReference()){
long lobId = getNextLobId(); long lobId = getNextLobId();
String sql = "INSERT INTO " + LOB_MAP + "(LOB, SEQ, POS, HASH, BLOCK) " + String sql = "INSERT INTO " + LOB_MAP + "(LOB, SEQ, POS, HASH, BLOCK) " +
"SELECT ?, SEQ, POS, HASH, BLOCK FROM " + LOB_MAP + " WHERE LOB = ?"; "SELECT ?, SEQ, POS, HASH, BLOCK FROM " + LOB_MAP + " WHERE LOB = ?";
...@@ -474,7 +476,11 @@ public class LobStorageBackend implements LobStorageInterface { ...@@ -474,7 +476,11 @@ public class LobStorageBackend implements LobStorageInterface {
prep.executeUpdate(); prep.executeUpdate();
reuse(sql, prep); 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; return v;
} catch (SQLException e) { } catch (SQLException e) {
throw DbException.convert(e); throw DbException.convert(e);
......
...@@ -218,8 +218,10 @@ public class Recover extends Tool implements DataHandler { ...@@ -218,8 +218,10 @@ public class Recover extends Tool implements DataHandler {
long precision) { long precision) {
DataHandler h = ((JdbcConnection) conn).getSession().getDataHandler(); DataHandler h = ((JdbcConnection) conn).getSession().getDataHandler();
verifyPageStore(h); verifyPageStore(h);
return ValueLobDb.create(Value.BLOB, h, LobStorageFrontend.TABLE_TEMP, ValueLobDb lob = ValueLobDb.create(Value.BLOB, h, LobStorageFrontend.TABLE_TEMP,
lobId, null, precision); lobId, null, precision);
lob.setRecoveryReference(true);
return lob;
} }
private static void verifyPageStore(DataHandler h) { private static void verifyPageStore(DataHandler h) {
...@@ -237,8 +239,10 @@ public class Recover extends Tool implements DataHandler { ...@@ -237,8 +239,10 @@ public class Recover extends Tool implements DataHandler {
long precision) { long precision) {
DataHandler h = ((JdbcConnection) conn).getSession().getDataHandler(); DataHandler h = ((JdbcConnection) conn).getSession().getDataHandler();
verifyPageStore(h); verifyPageStore(h);
return ValueLobDb.create(Value.CLOB, h, LobStorageFrontend.TABLE_TEMP, ValueLobDb lob = ValueLobDb.create(Value.CLOB, h, LobStorageFrontend.TABLE_TEMP,
lobId, null, precision); lobId, null, precision);
lob.setRecoveryReference(true);
return lob;
} }
/** /**
......
...@@ -63,13 +63,15 @@ public class LocalDateTimeUtils { ...@@ -63,13 +63,15 @@ public class LocalDateTimeUtils {
// java.sql.Date#toLocalDate() // java.sql.Date#toLocalDate()
private static Method TO_LOCAL_DATE; private static Method TO_LOCAL_DATE;
// java.sql.Time#toLocalTime()
private static Method TO_LOCAL_TIME; // java.time.LocalTime#ofNanoOfDay()
private static Method LOCAL_TIME_OF_NANO;
// java.sql.Date#valueOf(LocalDate) // java.sql.Date#valueOf(LocalDate)
private static Method DATE_VALUE_OF; private static Method DATE_VALUE_OF;
// java.sql.Time#valueOf(LocalTime)
private static Method TIME_VALUE_OF; // java.time.LocalTime#toNanoOfDay()
private static Method LOCAL_TIME_TO_NANO;
// java.time.LocalDate#of(int, int, int) // java.time.LocalDate#of(int, int, int)
private static Method LOCAL_DATE_OF_YEAR_MONTH_DAY; private static Method LOCAL_DATE_OF_YEAR_MONTH_DAY;
...@@ -145,10 +147,12 @@ public class LocalDateTimeUtils { ...@@ -145,10 +147,12 @@ public class LocalDateTimeUtils {
Class<?> temporal = getClass("java.time.temporal.Temporal"); Class<?> temporal = getClass("java.time.temporal.Temporal");
TO_LOCAL_DATE = getMethod(java.sql.Date.class, "toLocalDate"); TO_LOCAL_DATE = getMethod(java.sql.Date.class, "toLocalDate");
TO_LOCAL_TIME = getMethod(java.sql.Time.class, "toLocalTime");
LOCAL_TIME_OF_NANO = getMethod(LOCAL_TIME, "ofNanoOfDay", long.class);
DATE_VALUE_OF = getMethod(java.sql.Date.class, "valueOf", LOCAL_DATE); DATE_VALUE_OF = getMethod(java.sql.Date.class, "valueOf", LOCAL_DATE);
TIME_VALUE_OF = getMethod(java.sql.Time.class, "valueOf", LOCAL_TIME);
LOCAL_TIME_TO_NANO = getMethod(LOCAL_TIME, "toNanoOfDay");
LOCAL_DATE_OF_YEAR_MONTH_DAY = getMethod(LOCAL_DATE, "of", LOCAL_DATE_OF_YEAR_MONTH_DAY = getMethod(LOCAL_DATE, "of",
int.class, int.class, int.class); int.class, int.class, int.class);
...@@ -390,26 +394,22 @@ public class LocalDateTimeUtils { ...@@ -390,26 +394,22 @@ public class LocalDateTimeUtils {
* @return the LocalTime * @return the LocalTime
*/ */
public static Object valueToLocalTime(Value value) { public static Object valueToLocalTime(Value value) {
return timeToLocalTime(value.getTime());
}
private static Object dateToLocalDate(Date date) {
try { try {
return TO_LOCAL_DATE.invoke(date); return LOCAL_TIME_OF_NANO.invoke(null, ((ValueTime) value.convertTo(Value.TIME)).getNanos());
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
throw DbException.convert(e); throw DbException.convert(e);
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
throw DbException.convertInvocation(e, "date conversion failed"); throw DbException.convertInvocation(e, "time conversion failed");
} }
} }
private static Object timeToLocalTime(Time time) { private static Object dateToLocalDate(Date date) {
try { try {
return TO_LOCAL_TIME.invoke(time); return TO_LOCAL_DATE.invoke(date);
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
throw DbException.convert(e); throw DbException.convert(e);
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
throw DbException.convertInvocation(e, "time conversion failed"); throw DbException.convertInvocation(e, "date conversion failed");
} }
} }
...@@ -495,8 +495,7 @@ public class LocalDateTimeUtils { ...@@ -495,8 +495,7 @@ public class LocalDateTimeUtils {
*/ */
public static Value localTimeToTimeValue(Object localTime) { public static Value localTimeToTimeValue(Object localTime) {
try { try {
Time time = (Time) TIME_VALUE_OF.invoke(null, localTime); return ValueTime.fromNanos((Long) LOCAL_TIME_TO_NANO.invoke(localTime));
return ValueTime.get(time);
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
throw DbException.convert(e); throw DbException.convert(e);
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
......
...@@ -55,6 +55,11 @@ public class ValueLobDb extends Value implements Value.ValueClob, ...@@ -55,6 +55,11 @@ public class ValueLobDb extends Value implements Value.ValueClob,
private int tableId; private int tableId;
private int hash; 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, private ValueLobDb(int type, DataHandler handler, int tableId, long lobId,
byte[] hmac, long precision) { byte[] hmac, long precision) {
this.type = type; this.type = type;
...@@ -664,4 +669,12 @@ public class ValueLobDb extends Value implements Value.ValueClob, ...@@ -664,4 +669,12 @@ public class ValueLobDb extends Value implements Value.ValueClob,
return new ValueLobDb(type, small, precision); 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; ...@@ -114,6 +114,7 @@ import org.h2.test.mvcc.TestMvcc3;
import org.h2.test.mvcc.TestMvcc4; import org.h2.test.mvcc.TestMvcc4;
import org.h2.test.mvcc.TestMvccMultiThreaded; import org.h2.test.mvcc.TestMvccMultiThreaded;
import org.h2.test.poweroff.TestReorderWrites; import org.h2.test.poweroff.TestReorderWrites;
import org.h2.test.recover.RecoverLobTest;
import org.h2.test.rowlock.TestRowLocks; import org.h2.test.rowlock.TestRowLocks;
import org.h2.test.server.TestAutoServer; import org.h2.test.server.TestAutoServer;
import org.h2.test.server.TestInit; import org.h2.test.server.TestInit;
...@@ -858,6 +859,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -858,6 +859,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
addTest(new TestReader()); addTest(new TestReader());
addTest(new TestRecovery()); addTest(new TestRecovery());
addTest(new TestScriptReader()); addTest(new TestScriptReader());
addTest(new RecoverLobTest());
addTest(createTest("org.h2.test.unit.TestServlet")); addTest(createTest("org.h2.test.unit.TestServlet"));
addTest(new TestSecurity()); addTest(new TestSecurity());
addTest(new TestShell()); addTest(new TestShell());
...@@ -873,6 +875,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -873,6 +875,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
addTest(new TestValueHashMap()); addTest(new TestValueHashMap());
addTest(new TestWeb()); addTest(new TestWeb());
runAddedTests(); runAddedTests();
// serial // serial
......
...@@ -11,7 +11,6 @@ import java.sql.ResultSet; ...@@ -11,7 +11,6 @@ import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.util.Random; import java.util.Random;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.Utils; import org.h2.util.Utils;
...@@ -88,7 +87,7 @@ public class TestMemoryUsage extends TestBase { ...@@ -88,7 +87,7 @@ public class TestMemoryUsage extends TestBase {
if (usedNow > used * 1.3) { if (usedNow > used * 1.3) {
// try to lower memory usage (because it might be wrong) // try to lower memory usage (because it might be wrong)
// by forcing OOME // by forcing OOME
for (int i = 1024;; i *= 2) { for (int i = 1024; i < (1 >> 31); i *= 2) {
try { try {
byte[] oome = new byte[1024 * 1024 * 256]; byte[] oome = new byte[1024 * 1024 * 256];
oome[0] = (byte) i; oome[0] = (byte) i;
......
...@@ -15,10 +15,13 @@ import java.sql.Statement; ...@@ -15,10 +15,13 @@ import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Random; import java.util.Random;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.h2.api.ErrorCode;
import org.h2.jdbc.JdbcSQLException;
import org.h2.test.TestAll; import org.h2.test.TestAll;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.SmallLRUCache; import org.h2.util.SmallLRUCache;
...@@ -354,7 +357,17 @@ public class TestMultiThread extends TestBase implements Runnable { ...@@ -354,7 +357,17 @@ public class TestMultiThread extends TestBase implements Runnable {
} }
// check for exceptions // check for exceptions
for (Future<Void> job : jobs) { for (Future<Void> job : jobs) {
try {
job.get(); job.get();
} catch (ExecutionException ex) {
// ignore timeout exceptions, happens periodically when the machine is really
// busy and it's not the thing we are trying to test
if (!(ex.getCause() instanceof JdbcSQLException)
|| ((JdbcSQLException) ex.getCause())
.getErrorCode() != ErrorCode.LOCK_TIMEOUT_1) {
throw ex;
}
}
} }
executor.shutdown(); executor.shutdown();
executor.awaitTermination(20, TimeUnit.SECONDS); executor.awaitTermination(20, TimeUnit.SECONDS);
......
...@@ -13,14 +13,12 @@ import java.sql.SQLException; ...@@ -13,14 +13,12 @@ import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.mvstore.MVStore; import org.h2.mvstore.MVStore;
import org.h2.store.fs.FilePath; import org.h2.store.fs.FilePath;
import org.h2.store.fs.FilePathMem; import org.h2.store.fs.FilePathMem;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.tools.DeleteDbFiles;
/** /**
* Tests out of memory situations. The database must not get corrupted, and * Tests out of memory situations. The database must not get corrupted, and
...@@ -48,6 +46,7 @@ public class TestOutOfMemory extends TestBase { ...@@ -48,6 +46,7 @@ public class TestOutOfMemory extends TestBase {
FilePath.register(new FilePathMem()); FilePath.register(new FilePathMem());
String fileName = "memFS:" + getTestName(); String fileName = "memFS:" + getTestName();
MVStore store = MVStore.open(fileName); MVStore store = MVStore.open(fileName);
try {
Map<Integer, byte[]> map = store.openMap("test"); Map<Integer, byte[]> map = store.openMap("test");
Random r = new Random(1); Random r = new Random(1);
try { try {
...@@ -59,10 +58,11 @@ public class TestOutOfMemory extends TestBase { ...@@ -59,10 +58,11 @@ public class TestOutOfMemory extends TestBase {
fail(); fail();
} catch (OutOfMemoryError e) { } catch (OutOfMemoryError e) {
// expected // expected
} catch (IllegalStateException e) {
// expected
} }
try { try {
store.close(); store.close();
fail();
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
// expected // expected
} }
...@@ -70,11 +70,17 @@ public class TestOutOfMemory extends TestBase { ...@@ -70,11 +70,17 @@ public class TestOutOfMemory extends TestBase {
store = MVStore.open(fileName); store = MVStore.open(fileName);
map = store.openMap("test"); map = store.openMap("test");
store.close(); store.close();
} finally {
// just in case, otherwise if this test suffers a spurious failure, succeeding tests will too
// because they will OOM
store.closeImmediately();
FileUtils.delete(fileName); FileUtils.delete(fileName);
} }
}
private void testDatabaseUsingInMemoryFileSystem() throws SQLException { private void testDatabaseUsingInMemoryFileSystem() throws SQLException {
String url = "jdbc:h2:memFS:" + getTestName(); String filename = "memFS:" + getTestName();
String url = "jdbc:h2:" + filename;
Connection conn = DriverManager.getConnection(url); Connection conn = DriverManager.getConnection(url);
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
try { try {
...@@ -94,7 +100,7 @@ public class TestOutOfMemory extends TestBase { ...@@ -94,7 +100,7 @@ public class TestOutOfMemory extends TestBase {
stat = conn.createStatement(); stat = conn.createStatement();
stat.execute("select 1"); stat.execute("select 1");
conn.close(); conn.close();
DeleteDbFiles.execute("memLZF:", getTestName(), true); FileUtils.delete(filename); // release the static data this test generates
} }
private void testUpdateWhenNearlyOutOfMemory() throws SQLException { private void testUpdateWhenNearlyOutOfMemory() throws SQLException {
......
...@@ -24,7 +24,6 @@ import java.sql.Statement; ...@@ -24,7 +24,6 @@ import java.sql.Statement;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.sql.Types; import java.sql.Types;
import java.util.UUID; import java.util.UUID;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.api.Trigger; import org.h2.api.Trigger;
import org.h2.test.TestBase; import org.h2.test.TestBase;
...@@ -621,6 +620,13 @@ public class TestPreparedStatement extends TestBase { ...@@ -621,6 +620,13 @@ public class TestPreparedStatement extends TestBase {
Object localTime2 = rs.getObject(1, LocalDateTimeUtils.getLocalTimeClass()); Object localTime2 = rs.getObject(1, LocalDateTimeUtils.getLocalTimeClass());
assertEquals(localTime, localTime2); assertEquals(localTime, localTime2);
rs.close(); rs.close();
localTime = LocalDateTimeUtils.parseLocalTime("04:05:06.123456789");
prep.setObject(1, localTime);
rs = prep.executeQuery();
rs.next();
localTime2 = rs.getObject(1, LocalDateTimeUtils.getLocalTimeClass());
assertEquals(localTime, localTime2);
rs.close();
} }
private void testDateTime8(Connection conn) throws SQLException { private void testDateTime8(Connection conn) throws SQLException {
...@@ -632,7 +638,7 @@ public class TestPreparedStatement extends TestBase { ...@@ -632,7 +638,7 @@ public class TestPreparedStatement extends TestBase {
prep.setObject(1, localDateTime); prep.setObject(1, localDateTime);
ResultSet rs = prep.executeQuery(); ResultSet rs = prep.executeQuery();
rs.next(); rs.next();
Object localDateTime2 = rs.getObject(1, LocalDateTimeUtils.getLocalDateClass()); Object localDateTime2 = rs.getObject(1, LocalDateTimeUtils.getLocalDateTimeClass());
assertEquals(localDateTime, localDateTime2); assertEquals(localDateTime, localDateTime2);
rs.close(); rs.close();
} }
......
...@@ -44,11 +44,12 @@ public class TestReorderWrites extends TestBase { ...@@ -44,11 +44,12 @@ public class TestReorderWrites extends TestBase {
private void testMVStore() { private void testMVStore() {
FilePathReorderWrites fs = FilePathReorderWrites.register(); FilePathReorderWrites fs = FilePathReorderWrites.register();
String fileName = "reorder:memFS:test.mv"; String fileName = "reorder:memFS:test.mv";
try {
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
log(i + " --------------------------------"); log(i + " --------------------------------");
Random r = new Random(i); // this test is not interested in power off failures during initial creation
fs.setPowerOffCountdown(100, i); fs.setPowerOffCountdown(0, 0);
FileUtils.delete(fileName); FileUtils.delete(fileName); // release the static data this test generates
MVStore store = new MVStore.Builder(). MVStore store = new MVStore.Builder().
fileName(fileName). fileName(fileName).
autoCommitDisabled().open(); autoCommitDisabled().open();
...@@ -57,6 +58,7 @@ public class TestReorderWrites extends TestBase { ...@@ -57,6 +58,7 @@ public class TestReorderWrites extends TestBase {
map.put(-1, new byte[1]); map.put(-1, new byte[1]);
store.commit(); store.commit();
store.getFileStore().sync(); store.getFileStore().sync();
Random r = new Random(i);
int stop = 4 + r.nextInt(20); int stop = 4 + r.nextInt(20);
log("countdown start"); log("countdown start");
fs.setPowerOffCountdown(stop, i); fs.setPowerOffCountdown(stop, i);
...@@ -118,6 +120,9 @@ public class TestReorderWrites extends TestBase { ...@@ -118,6 +120,9 @@ public class TestReorderWrites extends TestBase {
map.keySet(); map.keySet();
store.close(); store.close();
} }
} finally {
FileUtils.delete(fileName); // release the static data this test generates
}
} }
private static void log(String message) { private static void log(String message) {
...@@ -183,6 +188,7 @@ public class TestReorderWrites extends TestBase { ...@@ -183,6 +188,7 @@ public class TestReorderWrites extends TestBase {
} }
assertTrue(minSize < maxSize); assertTrue(minSize < maxSize);
assertTrue(minWritten < maxWritten); assertTrue(minWritten < maxWritten);
FileUtils.delete(fileName); // release the static data this test generates
} }
} }
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();
}
}
...@@ -15,7 +15,6 @@ import java.util.Random; ...@@ -15,7 +15,6 @@ import java.util.Random;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import org.h2.mvstore.Chunk; import org.h2.mvstore.Chunk;
import org.h2.mvstore.Cursor; import org.h2.mvstore.Cursor;
import org.h2.mvstore.DataUtils; import org.h2.mvstore.DataUtils;
...@@ -829,7 +828,7 @@ public class TestMVStore extends TestBase { ...@@ -829,7 +828,7 @@ public class TestMVStore extends TestBase {
} }
s.close(); s.close();
int[] expectedReadsForCacheSize = { int[] expectedReadsForCacheSize = {
3407, 2590, 1924, 1440, 1111, 956, 918 3407, 2590, 1924, 1440, 1330, 956, 918
}; };
for (int cacheSize = 0; cacheSize <= 6; cacheSize += 4) { for (int cacheSize = 0; cacheSize <= 6; cacheSize += 4) {
int cacheMB = 1 + 3 * cacheSize; int cacheMB = 1 + 3 * cacheSize;
......
...@@ -2126,6 +2126,12 @@ select x from dual where REGEXP_LIKE('A', '[a-z]', 'c'); ...@@ -2126,6 +2126,12 @@ select x from dual where REGEXP_LIKE('A', '[a-z]', 'c');
> - > -
> rows: 0 > rows: 0
select regexp_replace('Sylvain', 'S..', 'TOTO', 'mni') as X;
> X
> --------
> TOTOvain
> rows: 1
SELECT 'Hello' ~ 'He.*' T1, 'HELLO' ~ 'He.*' F2, CAST('HELLO' AS VARCHAR_IGNORECASE) ~ 'He.*' T3; SELECT 'Hello' ~ 'He.*' T1, 'HELLO' ~ 'He.*' F2, CAST('HELLO' AS VARCHAR_IGNORECASE) ~ 'He.*' T3;
> T1 F2 T3 > T1 F2 T3
> ---- ----- ---- > ---- ----- ----
......
...@@ -138,6 +138,12 @@ public class FilePathReorderWrites extends FilePathWrapper { ...@@ -138,6 +138,12 @@ public class FilePathReorderWrites extends FilePathWrapper {
return 45000; return 45000;
} }
@Override
public void delete() {
super.delete();
FilePath.get(getBase().toString() + ".copy").delete();
}
} }
/** /**
...@@ -378,7 +384,7 @@ class FileReorderWrites extends FileBase { ...@@ -378,7 +384,7 @@ class FileReorderWrites extends FileBase {
channel.truncate(position); channel.truncate(position);
return -1; return -1;
} }
// TODO support the case were part is not written // TODO support the case where part is not written
int len = channel.write(buffer, position); int len = channel.write(buffer, position);
buffer.flip(); buffer.flip();
return len; return len;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论