提交 65f044a0 authored 作者: Thomas Mueller's avatar Thomas Mueller

Issue 284: If the query cache was used (enabled by default in version 1.3.x),…

Issue 284: If the query cache was used (enabled by default in version 1.3.x), and multiple threads used the same connection, and the same query but different prepared statements, parameters of one prepared statement could be overwritten by another.
上级 f3786d43
......@@ -44,6 +44,8 @@ public abstract class Command implements CommandInterface {
private final String sql;
private boolean canReuse;
public Command(Parser parser, String sql) {
this.session = parser.getSession();
this.sql = sql;
......@@ -266,7 +268,7 @@ public abstract class Command implements CommandInterface {
}
public void close() {
// nothing to do
canReuse = true;
}
public void cancel() {
......@@ -281,4 +283,17 @@ public abstract class Command implements CommandInterface {
return false;
}
public boolean canReuse() {
return canReuse;
}
public void reuse() {
canReuse = false;
ArrayList<? extends ParameterInterface> parameters = getParameters();
for (int i = 0, size = parameters.size(); i < size; i++) {
ParameterInterface param = parameters.get(i);
param.setValue(null, true);
}
}
}
......@@ -416,7 +416,8 @@ public class Session extends SessionWithState {
queryCache = SmallLRUCache.newInstance(queryCacheSize);
} else {
command = queryCache.get(sql);
if (command != null) {
if (command != null && command.canReuse()) {
command.reuse();
return command;
}
}
......
......@@ -19,6 +19,7 @@ import java.util.TreeSet;
import org.h2.test.TestBase;
import org.h2.tools.SimpleResultSet;
import org.h2.util.New;
import org.h2.util.Task;
/**
* Test various optimizations (query cache, optimization for MIN(..), and
......@@ -37,6 +38,8 @@ public class TestOptimizations extends TestBase {
public void test() throws Exception {
deleteDb("optimizations");
testQueryCacheConcurrentUse();
testQueryCacheResetParams();
testRowId();
testSortIndex();
testAutoAnalyze();
......@@ -63,6 +66,58 @@ public class TestOptimizations extends TestBase {
deleteDb("optimizations");
}
private void testQueryCacheConcurrentUse() throws Exception {
final Connection conn = getConnection("optimizations");
Statement stat = conn.createStatement();
stat.execute("create table test(id int primary key, data clob)");
stat.execute("insert into test values(0, space(10000))");
stat.execute("insert into test values(1, space(10001))");
Task[] tasks = new Task[2];
for (int i = 0; i < tasks.length; i++) {
tasks[i] = new Task() {
public void call() throws Exception {
PreparedStatement prep = conn.prepareStatement("select * from test where id = ?");
while (!stop) {
int x = (int) (Math.random() * 2);
prep.setInt(1, x);
ResultSet rs = prep.executeQuery();
rs.next();
String data = rs.getString(2);
if (data.length() != 10000 + x) {
throw new Exception(data.length() + " != " + x);
}
rs.close();
}
}
};
tasks[i].execute();
}
Thread.sleep(1000);
for (Task t : tasks) {
t.get();
}
stat.execute("drop table test");
conn.close();
}
private void testQueryCacheResetParams() throws SQLException {
Connection conn = getConnection("optimizations");
PreparedStatement prep;
prep = conn.prepareStatement("select ?");
prep.setString(1, "Hello");
prep.execute();
prep.close();
prep = conn.prepareStatement("select ?");
try {
prep.execute();
fail("Parameter value still set");
} catch (SQLException e) {
assertKnownException(e);
}
prep.close();
conn.close();
}
private void testRowId() throws SQLException {
if (config.memory) {
return;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论