提交 c12cf0a7 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 83b8c103
...@@ -117,6 +117,16 @@ ...@@ -117,6 +117,16 @@
</copy> </copy>
</target> </target>
<target name="compileCoverage" depends="compile">
<copy todir="bin" overwrite="true">
<fileset dir="src/main"/>
</copy>
<java classname="org.h2.test.coverage.Coverage" classpath="bin" dir="bin" fork="true">
<arg line="-e org/h2/web -e org/h2/jdbcx -e org/h2/bnf -r org/h2"/>
</java>
<javac target="${jdk}" source="${jdk}" executable="${javac}" srcdir="bin" destdir="bin" debug="true" includes="org/h2/**"/>
</target>
<target name="compileTest" unless="java.version.ok"> <target name="compileTest" unless="java.version.ok">
<echo message="Java version is ${java.specification.version} but source code is switched to ${jdk}."/> <echo message="Java version is ${java.specification.version} but source code is switched to ${jdk}."/>
<echo message="Run ant codeswitchJdk... first."/> <echo message="Run ant codeswitchJdk... first."/>
...@@ -303,14 +313,7 @@ ...@@ -303,14 +313,7 @@
<java classname="org.h2.test.TestAll" fork="true" classpath="bin" /> <java classname="org.h2.test.TestAll" fork="true" classpath="bin" />
</target> </target>
<target name="testCoverage" depends="compile"> <target name="testCoverage" depends="compileCoverage">
<copy todir="bin" overwrite="true">
<fileset dir="src/main"/>
</copy>
<java classname="org.h2.test.coverage.Coverage" classpath="bin" dir="bin" fork="true">
<arg line="-e org/h2/web -e org/h2/jdbcx -e org/h2/bnf -r org/h2"/>
</java>
<javac target="${jdk}" source="${jdk}" executable="${javac}" srcdir="bin" destdir="bin" debug="true" includes="org/h2/**"/>
<java classname="org.h2.test.TestAll" fork="true" classpath="bin" dir="bin"> <java classname="org.h2.test.TestAll" fork="true" classpath="bin" dir="bin">
<arg line="codeCoverage"/> <arg line="codeCoverage"/>
</java> </java>
......
...@@ -3302,6 +3302,9 @@ public class Parser { ...@@ -3302,6 +3302,9 @@ public class Parser {
long increment = readLong(); long increment = readLong();
command.setIncrement(increment); command.setIncrement(increment);
} }
if (readIf("CACHE")) {
command.setCacheSize(readLong());
}
if (readIf("BELONGS_TO_TABLE")) { if (readIf("BELONGS_TO_TABLE")) {
command.setBelongsToTable(true); command.setBelongsToTable(true);
} }
......
...@@ -19,6 +19,7 @@ public class CreateSequence extends SchemaCommand { ...@@ -19,6 +19,7 @@ public class CreateSequence extends SchemaCommand {
private boolean ifNotExists; private boolean ifNotExists;
private long start = 1; private long start = 1;
private long increment = 1; private long increment = 1;
private long cacheSize = Sequence.DEFAULT_CACHE_SIZE;
private boolean belongsToTable; private boolean belongsToTable;
public CreateSequence(Session session, Schema schema) { public CreateSequence(Session session, Schema schema) {
...@@ -46,6 +47,7 @@ public class CreateSequence extends SchemaCommand { ...@@ -46,6 +47,7 @@ public class CreateSequence extends SchemaCommand {
Sequence sequence = new Sequence(getSchema(), id, sequenceName, belongsToTable); Sequence sequence = new Sequence(getSchema(), id, sequenceName, belongsToTable);
sequence.setStartValue(start); sequence.setStartValue(start);
sequence.setIncrement(increment); sequence.setIncrement(increment);
sequence.setCacheSize(cacheSize);
db.addSchemaObject(session, sequence); db.addSchemaObject(session, sequence);
return 0; return 0;
} }
...@@ -66,4 +68,8 @@ public class CreateSequence extends SchemaCommand { ...@@ -66,4 +68,8 @@ public class CreateSequence extends SchemaCommand {
this.belongsToTable = belongsToTable; this.belongsToTable = belongsToTable;
} }
public void setCacheSize(long cacheSize) {
this.cacheSize = cacheSize;
}
} }
...@@ -21,7 +21,6 @@ import org.h2.message.TraceSystem; ...@@ -21,7 +21,6 @@ import org.h2.message.TraceSystem;
*/ */
public class SysProperties { public class SysProperties {
public static final boolean MVCC = getBooleanSetting("h2.mvcc", false);
public static final int MIN_WRITE_DELAY = getIntSetting("h2.minWriteDelay", 5); public static final int MIN_WRITE_DELAY = getIntSetting("h2.minWriteDelay", 5);
public static final boolean CHECK = getBooleanSetting("h2.check", true); public static final boolean CHECK = getBooleanSetting("h2.check", true);
public static final boolean CHECK2 = getBooleanSetting("h2.check2", false); public static final boolean CHECK2 = getBooleanSetting("h2.check2", false);
......
...@@ -176,7 +176,7 @@ public class Database implements DataHandler { ...@@ -176,7 +176,7 @@ public class Database implements DataHandler {
if (ignoreSummary != null) { if (ignoreSummary != null) {
this.recovery = true; this.recovery = true;
} }
this.multiVersion = ci.removeProperty("MVCC", false) || SysProperties.MVCC; this.multiVersion = ci.removeProperty("MVCC", false);
boolean closeAtVmShutdown = ci.removeProperty("DB_CLOSE_ON_EXIT", true); boolean closeAtVmShutdown = ci.removeProperty("DB_CLOSE_ON_EXIT", true);
int traceLevelFile = ci.getIntProperty(SetTypes.TRACE_LEVEL_FILE, TraceSystem.DEFAULT_TRACE_LEVEL_FILE); int traceLevelFile = ci.getIntProperty(SetTypes.TRACE_LEVEL_FILE, TraceSystem.DEFAULT_TRACE_LEVEL_FILE);
int traceLevelSystemOut = ci.getIntProperty(SetTypes.TRACE_LEVEL_SYSTEM_OUT, int traceLevelSystemOut = ci.getIntProperty(SetTypes.TRACE_LEVEL_SYSTEM_OUT,
......
...@@ -71,6 +71,7 @@ public class Session implements SessionInterface { ...@@ -71,6 +71,7 @@ public class Session implements SessionInterface {
private boolean autoCommitAtTransactionEnd; private boolean autoCommitAtTransactionEnd;
private String currentTransactionName; private String currentTransactionName;
private boolean isClosed; private boolean isClosed;
private boolean rollbackMode;
public Session() { public Session() {
} }
...@@ -252,7 +253,12 @@ public class Session implements SessionInterface { ...@@ -252,7 +253,12 @@ public class Session implements SessionInterface {
public void rollbackTo(int index) throws SQLException { public void rollbackTo(int index) throws SQLException {
while (undoLog.size() > index) { while (undoLog.size() > index) {
UndoLogRecord entry = undoLog.getAndRemoveLast(); UndoLogRecord entry = undoLog.getAndRemoveLast();
rollbackMode = true;
try {
entry.undo(this); entry.undo(this);
} finally {
rollbackMode = false;
}
} }
if (savepoints != null) { if (savepoints != null) {
String[] names = new String[savepoints.size()]; String[] names = new String[savepoints.size()];
...@@ -588,4 +594,8 @@ public class Session implements SessionInterface { ...@@ -588,4 +594,8 @@ public class Session implements SessionInterface {
autoCommit = false; autoCommit = false;
} }
public boolean getRollbackMode() {
return rollbackMode;
}
} }
...@@ -237,7 +237,9 @@ public class LinkedIndex extends BaseIndex { ...@@ -237,7 +237,9 @@ public class LinkedIndex extends BaseIndex {
j++; j++;
} }
} }
prep.executeUpdate(); int count = prep.executeUpdate();
// this has no effect but at least it allows to debug the update count
rowCount = rowCount + count - count;
} catch (SQLException e) { } catch (SQLException e) {
throw wrapException(sql, e); throw wrapException(sql, e);
} }
......
...@@ -120,6 +120,9 @@ public class MultiVersionCursor implements Cursor { ...@@ -120,6 +120,9 @@ public class MultiVersionCursor implements Cursor {
return true; return true;
} }
} }
int test;
this.index.debug("error", session, deltaRow);
System.exit(1);
throw Message.getInternalError(); throw Message.getInternalError();
} }
int compare = index.compareRows(deltaRow, baseRow); int compare = index.compareRows(deltaRow, baseRow);
......
...@@ -33,11 +33,13 @@ public class MultiVersionIndex implements Index { ...@@ -33,11 +33,13 @@ public class MultiVersionIndex implements Index {
} }
public void add(Session session, Row row) throws SQLException { public void add(Session session, Row row) throws SQLException {
int test;
debug("add", session, row);
synchronized (sync) { synchronized (sync) {
base.add(session, row); base.add(session, row);
if (removeIfExists(session, row)) {
// for example rolling back an delete operation // for example rolling back an delete operation
removeIfExists(session, row); } else if (row.getSessionId() != 0) {
if (row.getSessionId() != 0) {
// don't insert rows that are added when creating an index // don't insert rows that are added when creating an index
delta.add(session, row); delta.add(session, row);
} }
...@@ -51,6 +53,8 @@ public class MultiVersionIndex implements Index { ...@@ -51,6 +53,8 @@ public class MultiVersionIndex implements Index {
} }
public Cursor find(Session session, SearchRow first, SearchRow last) throws SQLException { public Cursor find(Session session, SearchRow first, SearchRow last) throws SQLException {
int test;
debug("find", session, first);
synchronized (sync) { synchronized (sync) {
Cursor baseCursor = base.find(session, first, last); Cursor baseCursor = base.find(session, first, last);
Cursor deltaCursor = delta.find(session, first, last); Cursor deltaCursor = delta.find(session, first, last);
...@@ -59,6 +63,7 @@ public class MultiVersionIndex implements Index { ...@@ -59,6 +63,7 @@ public class MultiVersionIndex implements Index {
} }
public boolean canGetFirstOrLast(boolean first) { public boolean canGetFirstOrLast(boolean first) {
// TODO in many cases possible, but more complicated
return false; return false;
} }
...@@ -75,19 +80,26 @@ public class MultiVersionIndex implements Index { ...@@ -75,19 +80,26 @@ public class MultiVersionIndex implements Index {
} }
private boolean removeIfExists(Session session, Row row) throws SQLException { private boolean removeIfExists(Session session, Row row) throws SQLException {
int test;
debug("removeIfExists ", session, row);
// maybe it was inserted by the same session just before // maybe it was inserted by the same session just before
Cursor c = delta.find(session, row, row); Cursor c = delta.find(session, row, row);
while (c.next()) { while (c.next()) {
Row r = c.get(); Row r = c.get();
if (r.getPos() == row.getPos()) { if (r.getPos() == row.getPos()) {
debug(" >remove", session, null);
delta.remove(session, row); delta.remove(session, row);
debug(" >return true", session, null);
return true; return true;
} }
} }
debug(" >return false", session, null);
return false; return false;
} }
public void remove(Session session, Row row) throws SQLException { public void remove(Session session, Row row) throws SQLException {
int test;
debug("remove", session, row);
synchronized (sync) { synchronized (sync) {
base.remove(session, row); base.remove(session, row);
if (removeIfExists(session, row)) { if (removeIfExists(session, row)) {
...@@ -105,6 +117,8 @@ public class MultiVersionIndex implements Index { ...@@ -105,6 +117,8 @@ public class MultiVersionIndex implements Index {
} }
public void truncate(Session session) throws SQLException { public void truncate(Session session) throws SQLException {
int test;
debug("truncate", session, null);
synchronized (sync) { synchronized (sync) {
delta.truncate(session); delta.truncate(session);
base.truncate(session); base.truncate(session);
...@@ -112,6 +126,8 @@ public class MultiVersionIndex implements Index { ...@@ -112,6 +126,8 @@ public class MultiVersionIndex implements Index {
} }
public void commit(int operation, Row row) throws SQLException { public void commit(int operation, Row row) throws SQLException {
int test;
debug("commit", null, row);
synchronized (sync) { synchronized (sync) {
removeIfExists(null, row); removeIfExists(null, row);
} }
...@@ -256,4 +272,8 @@ public class MultiVersionIndex implements Index { ...@@ -256,4 +272,8 @@ public class MultiVersionIndex implements Index {
base.setTemporary(temporary); base.setTemporary(temporary);
} }
void debug(String s, Session session, SearchRow row) throws SQLException {
// System.out.println(this + " " + s + " sess:" + (session == null ? -1: session.getId()) + " " + (row == null ? "" : row.getValue(0).getString()));
}
} }
...@@ -177,6 +177,8 @@ public class ScanIndex extends BaseIndex { ...@@ -177,6 +177,8 @@ public class ScanIndex extends BaseIndex {
firstFree = key; firstFree = key;
} }
if (database.isMultiVersion()) { if (database.isMultiVersion()) {
// if storage is null, the delete flag is not yet set
row.setDeleted(true);
if (delta == null) { if (delta == null) {
delta = new HashSet(); delta = new HashSet();
} }
......
...@@ -423,8 +423,11 @@ CREATE SCHEMA TEST_SCHEMA AUTHORIZATION SA ...@@ -423,8 +423,11 @@ CREATE SCHEMA TEST_SCHEMA AUTHORIZATION SA
CREATE SEQUENCE [IF NOT EXISTS] newSequenceName CREATE SEQUENCE [IF NOT EXISTS] newSequenceName
[START WITH long] [START WITH long]
[INCREMENT BY long] [INCREMENT BY long]
[CACHE long]
"," ","
Creates a new sequence. The data type of a sequence is BIGINT. Creates a new sequence. The data type of a sequence is BIGINT.
The cache is the number of pre-allocated numbers. If the system crashes without closing the
database, at most this many numbers are lost. The default cache size is 32.
"," ","
CREATE SEQUENCE SEQ_ID CREATE SEQUENCE SEQ_ID
" "
......
...@@ -15,10 +15,11 @@ import org.h2.message.Trace; ...@@ -15,10 +15,11 @@ import org.h2.message.Trace;
import org.h2.table.Table; import org.h2.table.Table;
public class Sequence extends SchemaObjectBase { public class Sequence extends SchemaObjectBase {
private static final int BLOCK_INCREMENT = 32; public static final int DEFAULT_CACHE_SIZE = 32;
private long value = 1; private long value = 1;
private long valueWithMargin; private long valueWithMargin;
private long increment = 1; private long increment = 1;
private long cacheSize = DEFAULT_CACHE_SIZE;
private boolean belongsToTable; private boolean belongsToTable;
public Sequence(Schema schema, int id, String name, boolean belongsToTable) { public Sequence(Schema schema, int id, String name, boolean belongsToTable) {
...@@ -67,6 +68,10 @@ public class Sequence extends SchemaObjectBase { ...@@ -67,6 +68,10 @@ public class Sequence extends SchemaObjectBase {
buff.append(" INCREMENT BY "); buff.append(" INCREMENT BY ");
buff.append(increment); buff.append(increment);
} }
if (cacheSize != DEFAULT_CACHE_SIZE) {
buff.append(" CACHE ");
buff.append(cacheSize);
}
if (belongsToTable) { if (belongsToTable) {
buff.append(" BELONGS_TO_TABLE"); buff.append(" BELONGS_TO_TABLE");
} }
...@@ -75,7 +80,7 @@ public class Sequence extends SchemaObjectBase { ...@@ -75,7 +80,7 @@ public class Sequence extends SchemaObjectBase {
public synchronized long getNext() throws SQLException { public synchronized long getNext() throws SQLException {
if ((increment > 0 && value >= valueWithMargin) || (increment < 0 && value <= valueWithMargin)) { if ((increment > 0 && value >= valueWithMargin) || (increment < 0 && value <= valueWithMargin)) {
valueWithMargin += increment * BLOCK_INCREMENT; valueWithMargin += increment * cacheSize;
flush(); flush();
} }
long v = value; long v = value;
...@@ -125,4 +130,12 @@ public class Sequence extends SchemaObjectBase { ...@@ -125,4 +130,12 @@ public class Sequence extends SchemaObjectBase {
this.belongsToTable = b; this.belongsToTable = b;
} }
public void setCacheSize(long cacheSize) {
this.cacheSize = cacheSize;
}
public long getCacheSize() {
return cacheSize;
}
} }
...@@ -202,6 +202,7 @@ public class MetaTable extends Table { ...@@ -202,6 +202,7 @@ public class MetaTable extends Table {
"INCREMENT BIGINT", "INCREMENT BIGINT",
"IS_GENERATED BIT", "IS_GENERATED BIT",
"REMARKS", "REMARKS",
"CACHE BIGINT",
"ID INT" "ID INT"
}); });
break; break;
...@@ -783,6 +784,7 @@ public class MetaTable extends Table { ...@@ -783,6 +784,7 @@ public class MetaTable extends Table {
String.valueOf(s.getIncrement()), // INCREMENT String.valueOf(s.getIncrement()), // INCREMENT
s.getBelongsToTable() ? "TRUE" : "FALSE", // IS_GENERATED s.getBelongsToTable() ? "TRUE" : "FALSE", // IS_GENERATED
replaceNullWithEmpty(s.getComment()), // REMARKS replaceNullWithEmpty(s.getComment()), // REMARKS
String.valueOf(s.getCacheSize()), // CACHE
"" + s.getId() // ID "" + s.getId() // ID
}); });
} }
......
...@@ -59,6 +59,7 @@ import org.h2.test.jdbc.TestTransactionIsolation; ...@@ -59,6 +59,7 @@ import org.h2.test.jdbc.TestTransactionIsolation;
import org.h2.test.jdbc.TestUpdatableResultSet; import org.h2.test.jdbc.TestUpdatableResultSet;
import org.h2.test.jdbc.TestZloty; import org.h2.test.jdbc.TestZloty;
import org.h2.test.jdbc.xa.TestXA; import org.h2.test.jdbc.xa.TestXA;
import org.h2.test.mvcc.TestMVCC;
import org.h2.test.server.TestNestedLoop; import org.h2.test.server.TestNestedLoop;
import org.h2.test.synth.TestBtreeIndex; import org.h2.test.synth.TestBtreeIndex;
import org.h2.test.synth.TestKillRestart; import org.h2.test.synth.TestKillRestart;
...@@ -125,7 +126,7 @@ java org.h2.test.TestAll timer ...@@ -125,7 +126,7 @@ java org.h2.test.TestAll timer
*/ */
public boolean smallLog, big, networked, memory, ssl, textStorage, diskUndo, diskResult, deleteIndex, traceSystemOut; public boolean smallLog, big, networked, memory, ssl, textStorage, diskUndo, diskResult, deleteIndex, traceSystemOut;
public boolean codeCoverage; public boolean codeCoverage, mvcc;
public int logMode = 1, traceLevelFile, throttle; public int logMode = 1, traceLevelFile, throttle;
public String cipher; public String cipher;
...@@ -139,20 +140,17 @@ java org.h2.test.TestAll timer ...@@ -139,20 +140,17 @@ java org.h2.test.TestAll timer
TestAll test = new TestAll(); TestAll test = new TestAll();
test.printSystem(); test.printSystem();
//int testMVCC;
// System.setProperty("h2.mvcc", "true");
/* /*
---- ----
A file is sent although the Japanese translation has not been completed yet. A file is sent although the Japanese translation has not been completed yet.
---- ----
Code coverage
At startup, when corrupted, say if LOG=0 was used before At startup, when corrupted, say if LOG=0 was used before
add MVCC add more MVCC tests
slow: slow:
select ta.attname, ia.attnum, ic.relname select ta.attname, ia.attnum, ic.relname
...@@ -369,6 +367,7 @@ write tests using the PostgreSQL JDBC driver ...@@ -369,6 +367,7 @@ write tests using the PostgreSQL JDBC driver
traceLevelFile = throttle = 0; traceLevelFile = throttle = 0;
logMode = 1; logMode = 1;
cipher = null; cipher = null;
mvcc = false;
testAll(); testAll();
diskUndo = false; diskUndo = false;
...@@ -382,6 +381,7 @@ write tests using the PostgreSQL JDBC driver ...@@ -382,6 +381,7 @@ write tests using the PostgreSQL JDBC driver
traceLevelFile = throttle = 0; traceLevelFile = throttle = 0;
logMode = 1; logMode = 1;
cipher = null; cipher = null;
mvcc = false;
testAll(); testAll();
big = false; big = false;
...@@ -397,6 +397,7 @@ write tests using the PostgreSQL JDBC driver ...@@ -397,6 +397,7 @@ write tests using the PostgreSQL JDBC driver
traceLevelFile = 0; traceLevelFile = 0;
throttle = 0; throttle = 0;
cipher = null; cipher = null;
mvcc = false;
testAll(); testAll();
diskUndo = true; diskUndo = true;
...@@ -410,6 +411,7 @@ write tests using the PostgreSQL JDBC driver ...@@ -410,6 +411,7 @@ write tests using the PostgreSQL JDBC driver
traceLevelFile = 3; traceLevelFile = 3;
throttle = 1; throttle = 1;
cipher = "XTEA"; cipher = "XTEA";
mvcc = false;
testAll(); testAll();
diskUndo = false; diskUndo = false;
...@@ -426,6 +428,7 @@ write tests using the PostgreSQL JDBC driver ...@@ -426,6 +428,7 @@ write tests using the PostgreSQL JDBC driver
traceLevelFile = 1; traceLevelFile = 1;
throttle = 0; throttle = 0;
cipher = null; cipher = null;
mvcc = false;
testAll(); testAll();
big = true; big = true;
...@@ -441,6 +444,7 @@ write tests using the PostgreSQL JDBC driver ...@@ -441,6 +444,7 @@ write tests using the PostgreSQL JDBC driver
traceLevelFile = 2; traceLevelFile = 2;
throttle = 0; throttle = 0;
cipher = null; cipher = null;
mvcc = false;
testAll(); testAll();
big = true; big = true;
...@@ -456,12 +460,16 @@ write tests using the PostgreSQL JDBC driver ...@@ -456,12 +460,16 @@ write tests using the PostgreSQL JDBC driver
traceLevelFile = 0; traceLevelFile = 0;
throttle = 0; throttle = 0;
cipher = "AES"; cipher = "AES";
mvcc = false;
testAll(); testAll();
} smallLog = big = networked = memory = ssl = textStorage = diskResult = deleteIndex = traceSystemOut = false;
traceLevelFile = throttle = 0;
logMode = 1;
cipher = null;
mvcc = true;
testAll();
public boolean isMVCC() {
return SysProperties.MVCC;
} }
void testAll() throws Exception { void testAll() throws Exception {
...@@ -495,9 +503,12 @@ write tests using the PostgreSQL JDBC driver ...@@ -495,9 +503,12 @@ write tests using the PostgreSQL JDBC driver
} }
void testDatabase() throws Exception { void testDatabase() throws Exception {
System.out.println("test big:"+big+" net:"+networked+" cipher:"+cipher+" memory:"+memory+" log:"+logMode+" diskResult:"+diskResult); System.out.println("test big:"+big+" net:"+networked+" cipher:"+cipher+" memory:"+memory+" log:"+logMode+" diskResult:"+diskResult + " mvcc:" + mvcc);
beforeTest(); beforeTest();
// int testMvcc;
// mvcc = true;
// db // db
new TestScriptSimple().runTest(this); new TestScriptSimple().runTest(this);
new TestScript().runTest(this); new TestScript().runTest(this);
...@@ -514,18 +525,14 @@ write tests using the PostgreSQL JDBC driver ...@@ -514,18 +525,14 @@ write tests using the PostgreSQL JDBC driver
new TestCsv().runTest(this); new TestCsv().runTest(this);
new TestFunctions().runTest(this); new TestFunctions().runTest(this);
new TestIndex().runTest(this); new TestIndex().runTest(this);
if (!SysProperties.MVCC) {
new TestLinkedTable().runTest(this); new TestLinkedTable().runTest(this);
}
new TestListener().runTest(this); new TestListener().runTest(this);
new TestLob().runTest(this); new TestLob().runTest(this);
new TestLogFile().runTest(this); new TestLogFile().runTest(this);
new TestMemoryUsage().runTest(this); new TestMemoryUsage().runTest(this);
new TestMultiConn().runTest(this); new TestMultiConn().runTest(this);
new TestMultiDimension().runTest(this); new TestMultiDimension().runTest(this);
if (!SysProperties.MVCC) {
new TestMultiThread().runTest(this); new TestMultiThread().runTest(this);
}
new TestOpenClose().runTest(this); new TestOpenClose().runTest(this);
new TestOptimizations().runTest(this); new TestOptimizations().runTest(this);
new TestPowerOff().runTest(this); new TestPowerOff().runTest(this);
...@@ -560,6 +567,9 @@ write tests using the PostgreSQL JDBC driver ...@@ -560,6 +567,9 @@ write tests using the PostgreSQL JDBC driver
new TestXA().runTest(this); new TestXA().runTest(this);
new TestZloty().runTest(this); new TestZloty().runTest(this);
// mvcc
new TestMVCC().runTest(this);
// synthetic // synthetic
new TestKillRestart().runTest(this); new TestKillRestart().runTest(this);
......
...@@ -135,6 +135,9 @@ public abstract class TestBase { ...@@ -135,6 +135,9 @@ public abstract class TestBase {
if (config.diskUndo && admin) { if (config.diskUndo && admin) {
url += ";MAX_MEMORY_UNDO=3"; url += ";MAX_MEMORY_UNDO=3";
} }
if (config.mvcc) {
url += ";MVCC=TRUE";
}
if (config.diskResult && admin) { if (config.diskResult && admin) {
url += ";MAX_MEMORY_ROWS=100;CACHE_SIZE=0"; url += ";MAX_MEMORY_ROWS=100;CACHE_SIZE=0";
} }
......
db1 = H2, org.h2.Driver, jdbc:h2:data/test;LOCK_TIMEOUT=10000;LOCK_MODE=3, sa, sa db1 = H2, org.h2.Driver, jdbc:h2:data/test;LOCK_TIMEOUT=10000;LOCK_MODE=3, sa, sa
#db1 = H2 (MVCC), org.h2.Driver, jdbc:h2:data/test_mvcc;MVCC=TRUE, sa, sa
#db2 = H2 (MVCC), org.h2.Driver, jdbc:h2:data/test_mvcc;MVCC=TRUE, sa, sa
#xdb2 = H2 (XTEA), org.h2.Driver, jdbc:h2:data/test_xtea;LOCK_TIMEOUT=10000;LOCK_MODE=3;CIPHER=XTEA, sa, sa 123 #xdb2 = H2 (XTEA), org.h2.Driver, jdbc:h2:data/test_xtea;LOCK_TIMEOUT=10000;LOCK_MODE=3;CIPHER=XTEA, sa, sa 123
#xdb3 = H2 (AES), org.h2.Driver, jdbc:h2:data/test_aes;LOCK_TIMEOUT=10000;LOCK_MODE=3;CIPHER=AES, sa, sa 123 #xdb3 = H2 (AES), org.h2.Driver, jdbc:h2:data/test_aes;LOCK_TIMEOUT=10000;LOCK_MODE=3;CIPHER=AES, sa, sa 123
#xdb4 = H2, org.h2.Driver, jdbc:h2:data/test;LOCK_TIMEOUT=10000;LOCK_MODE=3;write_mode_log=rws;write_delay=0, sa, sa #xdb4 = H2, org.h2.Driver, jdbc:h2:data/test;LOCK_TIMEOUT=10000;LOCK_MODE=3;write_mode_log=rws;write_delay=0, sa, sa
......
...@@ -131,6 +131,25 @@ public class TestLinkedTable extends TestBase { ...@@ -131,6 +131,25 @@ public class TestLinkedTable extends TestBase {
stat2.executeUpdate("UPDATE TEST_LINK_DI SET ID=ID+1"); stat2.executeUpdate("UPDATE TEST_LINK_DI SET ID=ID+1");
stat2.executeUpdate("UPDATE TEST_LINK_U SET NAME=NAME || ID"); stat2.executeUpdate("UPDATE TEST_LINK_U SET NAME=NAME || ID");
ResultSet rs; ResultSet rs;
rs = stat2.executeQuery("SELECT * FROM TEST_LINK_DI ORDER BY ID");
rs.next();
check(rs.getInt(1), 2);
check(rs.getString(2), "Hello2");
rs.next();
check(rs.getInt(1), 3);
check(rs.getString(2), "World3");
checkFalse(rs.next());
rs = stat2.executeQuery("SELECT * FROM TEST_LINK_U ORDER BY ID");
rs.next();
check(rs.getInt(1), 2);
check(rs.getString(2), "Hello2");
rs.next();
check(rs.getInt(1), 3);
check(rs.getString(2), "World3");
checkFalse(rs.next());
rs = stat.executeQuery("SELECT * FROM TEST ORDER BY ID"); rs = stat.executeQuery("SELECT * FROM TEST ORDER BY ID");
rs.next(); rs.next();
check(rs.getInt(1), 2); check(rs.getInt(1), 2);
......
...@@ -13,6 +13,36 @@ import org.h2.test.TestBase; ...@@ -13,6 +13,36 @@ import org.h2.test.TestBase;
public class TestSequence extends TestBase { public class TestSequence extends TestBase {
public void test() throws Exception { public void test() throws Exception {
testCache();
testTwo();
}
private void testCache() throws Exception {
if (config.memory) {
return;
}
deleteDb("sequence");
Connection conn = getConnection("sequence");
Statement stat = conn.createStatement();
stat.execute("create sequence testSequence");
stat.execute("create sequence testSequence3 cache 3");
conn.close();
conn = getConnection("sequence");
stat = conn.createStatement();
stat.execute("call next value for testSequence");
stat.execute("call next value for testSequence3");
ResultSet rs = stat.executeQuery("select * from information_schema.sequences");
rs.next();
check(rs.getString("SEQUENCE_NAME"), "TESTSEQUENCE3");
check(rs.getString("CACHE"), "3");
rs.next();
check(rs.getString("SEQUENCE_NAME"), "TESTSEQUENCE");
check(rs.getString("CACHE"), "32");
checkFalse(rs.next());
conn.close();
}
private void testTwo() throws Exception {
deleteDb("sequence"); deleteDb("sequence");
Connection conn = getConnection("sequence"); Connection conn = getConnection("sequence");
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
......
...@@ -14,7 +14,7 @@ public class TestTransactionIsolation extends TestBase { ...@@ -14,7 +14,7 @@ public class TestTransactionIsolation extends TestBase {
Connection conn1, conn2; Connection conn1, conn2;
public void test() throws Exception { public void test() throws Exception {
if (config.isMVCC()) { if (config.mvcc) {
// no tests yet // no tests yet
} else { } else {
testTableLevelLocking(); testTableLevelLocking();
......
...@@ -7,22 +7,23 @@ package org.h2.test.mvcc; ...@@ -7,22 +7,23 @@ package org.h2.test.mvcc;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.util.Random; import java.util.Random;
import org.h2.constant.ErrorCode;
import org.h2.test.TestBase;
import org.h2.tools.DeleteDbFiles; import org.h2.tools.DeleteDbFiles;
public class TestMVCC { public class TestMVCC extends TestBase {
Connection c1, c2; Connection c1, c2;
Statement s1, s2; Statement s1, s2;
public static void main(String[] args) throws Exception { public void test() throws Exception {
TestMVCC app = new TestMVCC(); if (!config.mvcc) {
app.test(); return;
} }
void test() throws Exception {
// TODO Prio 1: make unit test work // TODO Prio 1: make unit test work
// TODO Prio 1: document: exclusive table lock still used when altering tables, adding indexes, select ... for update; table level locks are checked // TODO Prio 1: document: exclusive table lock still used when altering tables, adding indexes, select ... for update; table level locks are checked
// TODO Prio 1: free up disk space (for deleted rows and old versions of updated rows) on commit // TODO Prio 1: free up disk space (for deleted rows and old versions of updated rows) on commit
...@@ -37,7 +38,6 @@ public class TestMVCC { ...@@ -37,7 +38,6 @@ public class TestMVCC {
// TODO test: one thread appends, the other selects new data (select * from test where id > ?) and deletes // TODO test: one thread appends, the other selects new data (select * from test where id > ?) and deletes
// System.setProperty("h2.mvcc", "true");
DeleteDbFiles.execute(null, "test", true); DeleteDbFiles.execute(null, "test", true);
Class.forName("org.h2.Driver"); Class.forName("org.h2.Driver");
c1 = DriverManager.getConnection("jdbc:h2:test;MVCC=TRUE", "sa", "sa"); c1 = DriverManager.getConnection("jdbc:h2:test;MVCC=TRUE", "sa", "sa");
...@@ -47,7 +47,6 @@ public class TestMVCC { ...@@ -47,7 +47,6 @@ public class TestMVCC {
c1.setAutoCommit(false); c1.setAutoCommit(false);
c2.setAutoCommit(false); c2.setAutoCommit(false);
s1.execute("create table test(id int primary key, name varchar(255))"); s1.execute("create table test(id int primary key, name varchar(255))");
s2.execute("insert into test values(4, 'Hello')"); s2.execute("insert into test values(4, 'Hello')");
c2.rollback(); c2.rollback();
...@@ -196,7 +195,11 @@ public class TestMVCC { ...@@ -196,7 +195,11 @@ public class TestMVCC {
s.execute("INSERT INTO TEST VALUES(" + i + ", 'Hello')"); s.execute("INSERT INTO TEST VALUES(" + i + ", 'Hello')");
break; break;
case 1: case 1:
try {
s.execute("UPDATE TEST SET NAME=" + i + " WHERE ID=" + random.nextInt(i)); s.execute("UPDATE TEST SET NAME=" + i + " WHERE ID=" + random.nextInt(i));
} catch (SQLException e) {
check(e.getErrorCode(), ErrorCode.CONCURRENT_UPDATE_1);
}
break; break;
case 2: case 2:
s.execute("DELETE FROM TEST WHERE ID=" + random.nextInt(i)); s.execute("DELETE FROM TEST WHERE ID=" + random.nextInt(i));
...@@ -249,6 +252,37 @@ public class TestMVCC { ...@@ -249,6 +252,37 @@ public class TestMVCC {
c1.commit(); c1.commit();
c2.commit(); c2.commit();
s1.execute("create table test(id int primary key, name varchar(255))");
s1.execute("insert into test values(1, 'Hello'), (2, 'World')");
c1.commit();
try {
s1.execute("update test set id=2 where id=1");
error("unexpected success");
} catch (SQLException e) {
checkNotGeneralException(e);
}
ResultSet rs = s1.executeQuery("select * from test order by id");
check(rs.next());
check(rs.getInt(1), 1);
check(rs.getString(2), "Hello");
check(rs.next());
check(rs.getInt(1), 2);
check(rs.getString(2), "World");
checkFalse(rs.next());
rs = s2.executeQuery("select * from test order by id");
check(rs.next());
check(rs.getInt(1), 1);
check(rs.getString(2), "Hello");
check(rs.next());
check(rs.getInt(1), 2);
check(rs.getString(2), "World");
checkFalse(rs.next());
s1.execute("drop table test");
c1.commit();
c2.commit();
c1.close(); c1.close();
c2.close(); c2.close();
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论