提交 6ef1f15c authored 作者: Thomas Mueller's avatar Thomas Mueller

Cluster: an open transaction was committed when a cluster node was stopped

(because disabling the cluster executes SET CLUSTER '', which committed the transaction).
Transaction are no longer committed when calling SET CLUSTER.
Cluster: non-admin users couldn't connect to the cluster and couldn't disable the cluster. Issue 201.
上级 1d38ee4f
...@@ -47,6 +47,7 @@ public class Set extends Prepared { ...@@ -47,6 +47,7 @@ public class Set extends Prepared {
public boolean isTransactional() { public boolean isTransactional() {
switch (type) { switch (type) {
case SetTypes.CLUSTER:
case SetTypes.VARIABLE: case SetTypes.VARIABLE:
case SetTypes.QUERY_TIMEOUT: case SetTypes.QUERY_TIMEOUT:
case SetTypes.LOCK_TIMEOUT: case SetTypes.LOCK_TIMEOUT:
...@@ -81,9 +82,17 @@ public class Set extends Prepared { ...@@ -81,9 +82,17 @@ public class Set extends Prepared {
addOrUpdateSetting(name, null, getIntValue()); addOrUpdateSetting(name, null, getIntValue());
break; break;
case SetTypes.CLUSTER: { case SetTypes.CLUSTER: {
session.getUser().checkAdmin(); String value = StringUtils.quoteStringSQL(stringValue);
database.setCluster(StringUtils.quoteStringSQL(stringValue)); if (!value.equals(database.getCluster()) && !value.equals("''")) {
addOrUpdateSetting(name, StringUtils.quoteStringSQL(stringValue), 0); // anybody can disable the cluster
// (if he can't access a cluster node)
session.getUser().checkAdmin();
}
database.setCluster(value);
// use the system session so that the current transaction
// (if any) is not committed
addOrUpdateSetting(database.getSystemSession(), name, value, 0);
database.getSystemSession().commit(true);
break; break;
} }
case SetTypes.COLLATION: { case SetTypes.COLLATION: {
...@@ -352,6 +361,10 @@ public class Set extends Prepared { ...@@ -352,6 +361,10 @@ public class Set extends Prepared {
} }
private void addOrUpdateSetting(String name, String s, int v) { private void addOrUpdateSetting(String name, String s, int v) {
addOrUpdateSetting(session, name, s, v);
}
private void addOrUpdateSetting(Session session, String name, String s, int v) {
Database database = session.getDatabase(); Database database = session.getDatabase();
if (database.isReadOnly()) { if (database.isReadOnly()) {
return; return;
......
...@@ -62,6 +62,8 @@ public class TestCluster extends TestBase { ...@@ -62,6 +62,8 @@ public class TestCluster extends TestBase {
stat = conn.createStatement(); stat = conn.createStatement();
stat.execute("create table test(id int primary key, name varchar) as " + stat.execute("create table test(id int primary key, name varchar) as " +
"select x, 'Data' || x from system_range(0, " + (len - 1) + ")"); "select x, 'Data' || x from system_range(0, " + (len - 1) + ")");
stat.execute("create user test password 'test'");
stat.execute("grant all on test to test");
// start the second server // start the second server
Server n2 = org.h2.tools.Server.createTcpServer("-tcpPort", "" + port2 , "-baseDir", getBaseDir() + "/node2").start(); Server n2 = org.h2.tools.Server.createTcpServer("-tcpPort", "" + port2 , "-baseDir", getBaseDir() + "/node2").start();
...@@ -83,9 +85,18 @@ public class TestCluster extends TestBase { ...@@ -83,9 +85,18 @@ public class TestCluster extends TestBase {
Connection connApp = DriverManager.getConnection(urlCluster + ";AUTO_RECONNECT=TRUE", user, password); Connection connApp = DriverManager.getConnection(urlCluster + ";AUTO_RECONNECT=TRUE", user, password);
check(connApp, len, "'" + serverList + "'"); check(connApp, len, "'" + serverList + "'");
// delete the rows, but don't commit
connApp.setAutoCommit(false);
connApp.createStatement().execute("delete from test");
// stop server 2, and test if only one server is available // stop server 2, and test if only one server is available
n2.stop(); n2.stop();
// rollback the transaction
connApp.createStatement().executeQuery("select count(*) from test");
connApp.rollback();
check(connApp, len, "''"); check(connApp, len, "''");
connApp.setAutoCommit(true);
// re-create the cluster // re-create the cluster
n2 = org.h2.tools.Server.createTcpServer("-tcpPort", "" + port2, "-baseDir", getBaseDir() + "/node2").start(); n2 = org.h2.tools.Server.createTcpServer("-tcpPort", "" + port2, "-baseDir", getBaseDir() + "/node2").start();
...@@ -95,6 +106,11 @@ public class TestCluster extends TestBase { ...@@ -95,6 +106,11 @@ public class TestCluster extends TestBase {
// test the cluster connection // test the cluster connection
check(connApp, len, "'" + serverList + "'"); check(connApp, len, "'" + serverList + "'");
// test a non-admin user
String user2 = "test", password2 = getPassword("test");
connApp = DriverManager.getConnection(urlCluster, user2, password2);
check(connApp, len, "'" + serverList + "'");
n1.stop(); n1.stop();
n2.stop(); n2.stop();
deleteFiles(); deleteFiles();
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论