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

A prepared statement if type CALL that returned a result set could throw a…

A prepared statement if type CALL that returned a result set could throw a NullPointerExecption if executed multiple times.
上级 1fb40cce
...@@ -15,7 +15,6 @@ import org.h2.expression.ExpressionVisitor; ...@@ -15,7 +15,6 @@ import org.h2.expression.ExpressionVisitor;
import org.h2.result.LocalResult; import org.h2.result.LocalResult;
import org.h2.result.ResultInterface; import org.h2.result.ResultInterface;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueResultSet;
/** /**
* This class represents the statement * This class represents the statement
...@@ -23,6 +22,7 @@ import org.h2.value.ValueResultSet; ...@@ -23,6 +22,7 @@ import org.h2.value.ValueResultSet;
*/ */
public class Call extends Prepared { public class Call extends Prepared {
private boolean isResultSet;
private Expression expression; private Expression expression;
private Expression[] expressions; private Expression[] expressions;
...@@ -31,9 +31,8 @@ public class Call extends Prepared { ...@@ -31,9 +31,8 @@ public class Call extends Prepared {
} }
public ResultInterface queryMeta() { public ResultInterface queryMeta() {
int expressionType = expression.getType();
LocalResult result; LocalResult result;
if (expressionType == Value.RESULT_SET) { if (isResultSet) {
Expression[] expr = expression.getExpressionColumns(session); Expression[] expr = expression.getExpressionColumns(session);
result = new LocalResult(session, expr, expr.length); result = new LocalResult(session, expr, expr.length);
} else { } else {
...@@ -62,8 +61,9 @@ public class Call extends Prepared { ...@@ -62,8 +61,9 @@ public class Call extends Prepared {
public ResultInterface query(int maxrows) { public ResultInterface query(int maxrows) {
setCurrentRowNumber(1); setCurrentRowNumber(1);
Value v = expression.getValue(session); Value v = expression.getValue(session);
if (v.getType() == Value.RESULT_SET) { if (isResultSet) {
ResultSet rs = ((ValueResultSet) v).getResultSet(); v = v.convertTo(Value.RESULT_SET);
ResultSet rs = v.getResultSet();
return LocalResult.read(session, rs, maxrows); return LocalResult.read(session, rs, maxrows);
} }
LocalResult result = new LocalResult(session, expressions, 1); LocalResult result = new LocalResult(session, expressions, 1);
...@@ -76,6 +76,10 @@ public class Call extends Prepared { ...@@ -76,6 +76,10 @@ public class Call extends Prepared {
public void prepare() { public void prepare() {
expression = expression.optimize(session); expression = expression.optimize(session);
expressions = new Expression[] { expression }; expressions = new Expression[] { expression };
isResultSet = expression.getType() == Value.RESULT_SET;
if (isResultSet) {
prepareAlways = true;
}
} }
public void setExpression(Expression expression) { public void setExpression(Expression expression) {
...@@ -99,4 +103,8 @@ public class Call extends Prepared { ...@@ -99,4 +103,8 @@ public class Call extends Prepared {
return CommandInterface.CALL; return CommandInterface.CALL;
} }
public boolean isCacheable() {
return !isResultSet;
}
} }
...@@ -13,6 +13,7 @@ import java.lang.ref.SoftReference; ...@@ -13,6 +13,7 @@ import java.lang.ref.SoftReference;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.Date; import java.sql.Date;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Time; import java.sql.Time;
import java.sql.Timestamp; import java.sql.Timestamp;
...@@ -24,6 +25,7 @@ import org.h2.store.DataHandler; ...@@ -24,6 +25,7 @@ import org.h2.store.DataHandler;
import org.h2.store.LobStorage; import org.h2.store.LobStorage;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.MathUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import org.h2.util.Utils; import org.h2.util.Utils;
...@@ -1068,6 +1070,13 @@ public abstract class Value { ...@@ -1068,6 +1070,13 @@ public abstract class Value {
return this; return this;
} }
public ResultSet getResultSet() {
SimpleResultSet rs = new SimpleResultSet();
rs.addColumn("X", DataType.convertTypeToSQLType(getType()), MathUtils.convertLongToInt(getPrecision()), getScale());
rs.addRow(getObject());
return rs;
}
/** /**
* A "binary large object". * A "binary large object".
*/ */
......
...@@ -44,6 +44,7 @@ public class TestPreparedStatement extends TestBase { ...@@ -44,6 +44,7 @@ public class TestPreparedStatement extends TestBase {
public void test() throws Exception { public void test() throws Exception {
deleteDb("preparedStatement"); deleteDb("preparedStatement");
Connection conn = getConnection("preparedStatement"); Connection conn = getConnection("preparedStatement");
testCallTablePrepared(conn);
testValues(conn); testValues(conn);
testToString(conn); testToString(conn);
testExecuteUpdateCall(conn); testExecuteUpdateCall(conn);
...@@ -80,6 +81,12 @@ public class TestPreparedStatement extends TestBase { ...@@ -80,6 +81,12 @@ public class TestPreparedStatement extends TestBase {
deleteDb("preparedStatement"); deleteDb("preparedStatement");
} }
private void testCallTablePrepared(Connection conn) throws SQLException {
PreparedStatement prep = conn.prepareStatement("call table(x int = (1))");
prep.executeQuery();
prep.executeQuery();
}
private void testValues(Connection conn) throws SQLException { private void testValues(Connection conn) throws SQLException {
PreparedStatement prep = conn.prepareStatement("values(?, ?)"); PreparedStatement prep = conn.prepareStatement("values(?, ?)");
prep.setInt(1, 1); prep.setInt(1, 1);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论