提交 729d931d authored 作者: Thomas Mueller's avatar Thomas Mueller

MERGE: if a unique key was violated (but not the primary key or the key columns…

MERGE: if a unique key was violated (but not the primary key or the key columns of the merge itself), the wrong exception was thrown.
上级 61fdac05
......@@ -18,7 +18,9 @@ Change Log
<h1>Change Log</h1>
<h2>Next Version (unreleased)</h2>
<ul><li>IBM DB2 and Apache Derby compatibility: support the pseudo-table SYSIBM.SYSDUMMY1.
<ul><li>MERGE: if a unique key was violated (but not the primary key or the key columns of the merge itself),
the wrong exception was thrown.
</li><li>IBM DB2 and Apache Derby compatibility: support the pseudo-table SYSIBM.SYSDUMMY1.
</li><li>ROWNUM() did not work in combination with IN(..). The following query did not work as expected:
select * from (select rownum r from test) where r in (1, 2).
</li><li>H2 Console autocomplete: the autocomplete feature didn't support quoted names.
......
......@@ -162,9 +162,25 @@ public class Merge extends Prepared {
}
} catch (DbException e) {
if (e.getErrorCode() == ErrorCode.DUPLICATE_KEY_1) {
// concurrent merge or insert
// possibly a concurrent merge or insert
Index index = (Index) e.getSource();
if (index != null) {
// verify the index columns match the key
Column[] indexColumns = index.getColumns();
boolean indexMatchesKeys = false;
if (indexColumns.length <= keys.length) {
for (int i = 0; i < indexColumns.length; i++) {
if (indexColumns[i] != keys[i]) {
indexMatchesKeys = false;
break;
}
}
}
if (indexMatchesKeys) {
throw DbException.get(ErrorCode.CONCURRENT_UPDATE_1, table.getName());
}
}
}
throw e;
}
} else if (count != 1) {
......
......@@ -78,7 +78,9 @@ public abstract class BaseIndex extends SchemaObjectBase implements Index {
*/
DbException getDuplicateKeyException() {
String sql = getName() + " ON " + table.getSQL() + "(" + getColumnListSQL() + ")";
return DbException.get(ErrorCode.DUPLICATE_KEY_1, sql);
DbException e = DbException.get(ErrorCode.DUPLICATE_KEY_1, sql);
e.setSource(this);
return e;
}
public String getPlanSQL() {
......
......@@ -155,7 +155,9 @@ public class PageDataIndex extends PageIndex {
if (mainIndexColumn >= 0 && mainIndexColumn < indexColumns.length) {
sql += "(" + indexColumns[mainIndexColumn].getSQL() + ")";
}
return DbException.get(ErrorCode.DUPLICATE_KEY_1, sql);
DbException e = DbException.get(ErrorCode.DUPLICATE_KEY_1, sql);
e.setSource(this);
return e;
}
private void addTry(Session session, Row row) {
......
......@@ -31,6 +31,8 @@ public class DbException extends RuntimeException {
private static final Properties MESSAGES = new Properties();
private Object source;
static {
try {
byte[] messages = Utils.getResource("/org/h2/res/_messages_en.prop");
......@@ -348,4 +350,12 @@ public class DbException extends RuntimeException {
return io;
}
public Object getSource() {
return source;
}
public void setSource(Object source) {
this.source = source;
}
}
......@@ -8,8 +8,11 @@ package org.h2.test.mvcc;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.concurrent.CountDownLatch;
import org.h2.constant.ErrorCode;
import org.h2.test.TestBase;
import org.h2.util.Task;
......@@ -28,12 +31,30 @@ public class TestMvccMultiThreaded extends TestBase {
}
public void test() throws Exception {
testMergeWithUniqueKeyViolation();
testConcurrentMerge();
testConcurrentUpdate("");
// not supported currently
// testConcurrentUpdate(";MULTI_THREADED=TRUE");
}
private void testMergeWithUniqueKeyViolation() throws Exception {
deleteDb("mvccMultiThreaded");
Connection conn = getConnection("mvccMultiThreaded");
Statement stat = conn.createStatement();
stat.execute("create table test(x int primary key, y int unique)");
stat.execute("insert into test values(1, 1)");
try {
stat.execute("merge into test values(2, 1)");
fail();
} catch (SQLException e) {
assertEquals(ErrorCode.DUPLICATE_KEY_1, e.getErrorCode());
}
stat.execute("merge into test values(1, 2)");
conn.close();
}
private void testConcurrentMerge() throws Exception {
deleteDb("mvccMultiThreaded");
int len = 3;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论