提交 f97ba1cb authored 作者: Sergi Vladykin's avatar Sergi Vladykin

PreparedStatement.getMetaData() was not always consistent with resulting ResultSet.getMetaData().

上级 93a6e550
......@@ -18,7 +18,8 @@ Change Log
<h1>Change Log</h1>
<h2>Next Version (unreleased)</h2>
<ul><li>The build tool now uses JAVA_HOME for javac as well. Issue 233.
<ul><li>PreparedStatement.getMetaData() was not always consistent with resulting ResultSet.getMetaData().
</li><li>The build tool now uses JAVA_HOME for javac as well. Issue 233.
</li><li>Opening and closing encrypted databases is now much faster.
</li><li>H2 Console: new experimental feature to support file download and upload,
but only if there is a directory called "transfer" in the current working directory.
......
......@@ -11,11 +11,10 @@ import org.h2.command.CommandInterface;
import org.h2.command.Prepared;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionColumn;
import org.h2.expression.ExpressionVisitor;
import org.h2.message.DbException;
import org.h2.result.LocalResult;
import org.h2.result.ResultInterface;
import org.h2.table.Column;
import org.h2.value.Value;
import org.h2.value.ValueArray;
import org.h2.value.ValueResultSet;
......@@ -26,7 +25,6 @@ import org.h2.value.ValueResultSet;
*/
public class Call extends Prepared {
private Expression expression;
private Expression[] expressions;
......@@ -35,7 +33,14 @@ public class Call extends Prepared {
}
public ResultInterface queryMeta() {
LocalResult result = new LocalResult(session, expressions, 1);
int expressionType = expression.getType();
LocalResult result;
if (expressionType == Value.RESULT_SET || expressionType == Value.ARRAY) {
Expression[] expr = expression.getExpressionColumns(session);
result = new LocalResult(session, expr, expr.length);
} else {
result = new LocalResult(session, expressions, 1);
}
result.done();
return result;
}
......@@ -60,18 +65,17 @@ public class Call extends Prepared {
public ResultInterface query(int maxrows) {
setCurrentRowNumber(1);
Value v = expression.getValue(session);
if (v.getType() == Value.RESULT_SET) {
switch (expression.getType()) {
case Value.RESULT_SET:
ResultSet rs = ((ValueResultSet) v).getResultSet();
return LocalResult.read(session, rs, maxrows);
} else if (v.getType() == Value.ARRAY) {
case Value.ARRAY:
Value[] list = ((ValueArray) v).getList();
Expression[] expr = new Expression[list.length];
for (int i = 0; i < list.length; i++) {
Value e = list[i];
Column col = new Column("C" + (i + 1), e.getType(), e.getPrecision(), e.getScale(), e.getDisplaySize());
expr[i] = new ExpressionColumn(session.getDatabase(), col);
Expression[] expr = expression.getExpressionColumns(session);
if (expr.length != list.length) {
throw DbException.throwInternalError();
}
LocalResult result = new LocalResult(session, expr, list.length);
LocalResult result = new LocalResult(session, expr, expr.length);
result.addRow(list);
result.done();
return result;
......
......@@ -6,12 +6,18 @@
*/
package org.h2.expression;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.table.Column;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.util.StringUtils;
import org.h2.value.DataType;
import org.h2.value.Value;
import org.h2.value.ValueArray;
/**
* An expression is a operation, a value, or a function in a query.
......@@ -292,4 +298,58 @@ public abstract class Expression {
return getSQL();
}
/**
* If this expression consists of column expressions it should return them.
*
* @return array of expression columns if applicable, null otherwise
*/
public Expression[] getExpressionColumns(Session session) {
return null;
}
/**
* Extracts expression columns from ValueArray
*
* @param session the current session
* @param value the value to extract columns from
* @return array of expression columns
*/
public static Expression[] getExpressionColumns(Session session, ValueArray value) {
Value[] list = value.getList();
ExpressionColumn[] expr = new ExpressionColumn[list.length];
for (int i = 0; i < list.length; i++) {
Value v = list[i];
Column col = new Column("C" + (i + 1), v.getType(), v.getPrecision(), v.getScale(),
v.getDisplaySize());
expr[i] = new ExpressionColumn(session.getDatabase(), col);
}
return expr;
}
/**
* Extracts expression columns from the given result set.
*
* @param session the session
* @param rs the result set
* @return an array of expression columns
* @throws SQLException
*/
public static Expression[] getExpressionColumns(Session session, ResultSet rs) throws SQLException {
ResultSetMetaData meta = rs.getMetaData();
int columnCount = meta.getColumnCount();
Expression[] expressions = new Expression[columnCount];
Database db = session == null ? null : session.getDatabase();
for (int i = 0; i < columnCount; i++) {
String name = meta.getColumnLabel(i + 1);
int type = DataType.convertSQLTypeToValueType(meta.getColumnType(i + 1));
int precision = meta.getPrecision(i + 1);
int scale = meta.getScale(i + 1);
int displaySize = meta.getColumnDisplaySize(i + 1);
Column col = new Column(name, type, precision, scale, displaySize);
Expression expr = new ExpressionColumn(db, col);
expressions[i] = expr;
}
return expressions;
}
}
......@@ -7,6 +7,7 @@
package org.h2.expression;
import org.h2.engine.Session;
import org.h2.table.Column;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.util.StatementBuilder;
......@@ -108,4 +109,15 @@ public class ExpressionList extends Expression {
return cost;
}
public Expression[] getExpressionColumns(Session session) {
ExpressionColumn[] expr = new ExpressionColumn[list.length];
for (int i = 0; i < list.length; i++) {
Expression e = list[i];
Column col = new Column("C" + (i + 1), e.getType(), e.getPrecision(), e.getScale(),
e.getDisplaySize());
expr[i] = new ExpressionColumn(session.getDatabase(), col);
}
return expr;
}
}
......@@ -6,16 +6,19 @@
*/
package org.h2.expression;
import java.sql.SQLException;
import org.h2.command.Parser;
import org.h2.constant.SysProperties;
import org.h2.engine.Constants;
import org.h2.engine.FunctionAlias;
import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.util.StatementBuilder;
import org.h2.value.DataType;
import org.h2.value.Value;
import org.h2.value.ValueArray;
import org.h2.value.ValueNull;
import org.h2.value.ValueResultSet;
......@@ -154,4 +157,18 @@ public class JavaFunction extends Expression implements FunctionCall {
return functionAlias.isDeterministic();
}
public Expression[] getExpressionColumns(Session session) {
switch (getType()) {
case Value.RESULT_SET:
ValueResultSet vrs = getValueForColumnList(session, getArgs());
try {
return getExpressionColumns(session, vrs.getResultSet());
} catch (SQLException e) {
throw DbException.convert(e);
}
case Value.ARRAY:
return getExpressionColumns(session, (ValueArray) getValue(session));
}
return super.getExpressionColumns(session);
}
}
......@@ -6,6 +6,7 @@
*/
package org.h2.expression;
import java.util.ArrayList;
import org.h2.command.dml.Query;
import org.h2.constant.ErrorCode;
import org.h2.engine.Session;
......@@ -24,6 +25,7 @@ import org.h2.value.ValueNull;
public class Subquery extends Expression {
private Query query;
private Expression expression;
public Subquery(Query query) {
this.query = query;
......@@ -93,7 +95,20 @@ public class Subquery extends Expression {
}
private Expression getExpression() {
return query.getExpressions().get(0);
if (expression == null) {
ArrayList<Expression> exprs = query.getExpressions();
int columnCount = query.getColumnCount();
if (columnCount == 1) {
expression = exprs.get(0);
} else {
Expression[] list = new Expression[columnCount];
for (int i = 0; i < columnCount; i++) {
list[i] = exprs.get(i);
}
expression = new ExpressionList(list);
}
}
return expression;
}
public boolean isEverything(ExpressionVisitor visitor) {
......@@ -108,4 +123,7 @@ public class Subquery extends Expression {
return 10 + (int) (10 * query.getCost());
}
public Expression[] getExpressionColumns(Session session) {
return getExpression().getExpressionColumns(session);
}
}
......@@ -6,6 +6,7 @@
*/
package org.h2.expression;
import java.sql.SQLException;
import java.util.ArrayList;
import org.h2.constant.ErrorCode;
import org.h2.engine.Database;
......@@ -148,4 +149,11 @@ public class TableFunction extends Function {
return rowCount;
}
public Expression[] getExpressionColumns(Session session) {
try {
return getExpressionColumns(session, getTable(session, getArgs(), true, false).getResultSet());
} catch (SQLException e) {
throw DbException.convert(e);
}
}
}
......@@ -12,6 +12,7 @@ import org.h2.message.DbException;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.value.Value;
import org.h2.value.ValueArray;
import org.h2.value.ValueBoolean;
import org.h2.value.ValueNull;
......@@ -153,4 +154,10 @@ public class ValueExpression extends Expression {
return 0;
}
public Expression[] getExpressionColumns(Session session) {
if (getType() == Value.ARRAY) {
return getExpressionColumns(session, (ValueArray) getValue(session));
}
return super.getExpressionColumns(session);
}
}
......@@ -7,16 +7,12 @@
package org.h2.result;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import org.h2.constant.SysProperties;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionColumn;
import org.h2.message.DbException;
import org.h2.table.Column;
import org.h2.util.New;
import org.h2.util.ValueHashMap;
import org.h2.value.DataType;
......@@ -83,7 +79,7 @@ public class LocalResult implements ResultInterface {
*/
public static LocalResult read(Session session, ResultSet rs, int maxrows) {
try {
Expression[] cols = getExpressionColumns(session, rs);
Expression[] cols = Expression.getExpressionColumns(session, rs);
int columnCount = cols.length;
LocalResult result = new LocalResult(session, cols, columnCount);
for (int i = 0; (maxrows == 0 || i < maxrows) && rs.next(); i++) {
......@@ -101,24 +97,6 @@ public class LocalResult implements ResultInterface {
}
}
private static Expression[] getExpressionColumns(Session session, ResultSet rs) throws SQLException {
ResultSetMetaData meta = rs.getMetaData();
int columnCount = meta.getColumnCount();
Expression[] expressions = new Expression[columnCount];
Database db = session == null ? null : session.getDatabase();
for (int i = 0; i < columnCount; i++) {
String name = meta.getColumnLabel(i + 1);
int type = DataType.convertSQLTypeToValueType(meta.getColumnType(i + 1));
int precision = meta.getPrecision(i + 1);
int scale = meta.getScale(i + 1);
int displaySize = meta.getColumnDisplaySize(i + 1);
Column col = new Column(name, type, precision, scale, displaySize);
Expression expr = new ExpressionColumn(db, col);
expressions[i] = expr;
}
return expressions;
}
/**
* Create a shallow copy of the result set. The data and a temporary table
* (if there is any) is not copied.
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论