提交 72497459 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Add and use SimpleResult for ValueResultSet

上级 9ca5bd10
...@@ -5,14 +5,12 @@ ...@@ -5,14 +5,12 @@
*/ */
package org.h2.command.dml; package org.h2.command.dml;
import java.sql.ResultSet;
import org.h2.command.CommandInterface; import org.h2.command.CommandInterface;
import org.h2.command.Prepared; import org.h2.command.Prepared;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.expression.Expression; import org.h2.expression.Expression;
import org.h2.expression.ExpressionVisitor; import org.h2.expression.ExpressionVisitor;
import org.h2.result.LocalResult; import org.h2.result.LocalResult;
import org.h2.result.LocalResultFactory;
import org.h2.result.ResultInterface; import org.h2.result.ResultInterface;
import org.h2.value.Value; import org.h2.value.Value;
...@@ -65,9 +63,7 @@ public class Call extends Prepared { ...@@ -65,9 +63,7 @@ public class Call extends Prepared {
setCurrentRowNumber(1); setCurrentRowNumber(1);
Value v = expression.getValue(session); Value v = expression.getValue(session);
if (isResultSet) { if (isResultSet) {
v = v.convertTo(Value.RESULT_SET); return v.getResult();
ResultSet rs = v.getResultSet();
return LocalResultFactory.read(session, rs, maxrows);
} }
LocalResult result = session.getDatabase().getResultFactory().create(session, expressions, 1); LocalResult result = session.getDatabase().getResultFactory().create(session, expressions, 1);
Value[] row = { v }; Value[] row = { v };
......
...@@ -5,17 +5,13 @@ ...@@ -5,17 +5,13 @@
*/ */
package org.h2.expression; 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.Database;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.message.DbException; import org.h2.result.ResultInterface;
import org.h2.table.Column; import org.h2.table.Column;
import org.h2.table.ColumnResolver; import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter; import org.h2.table.TableFilter;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import org.h2.value.DataType;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueArray; import org.h2.value.ValueArray;
...@@ -352,29 +348,24 @@ public abstract class Expression { ...@@ -352,29 +348,24 @@ public abstract class Expression {
* Extracts expression columns from the given result set. * Extracts expression columns from the given result set.
* *
* @param session the session * @param session the session
* @param rs the result set * @param result the result
* @return an array of expression columns * @return an array of expression columns
*/ */
public static Expression[] getExpressionColumns(Session session, ResultSet rs) { public static Expression[] getExpressionColumns(Session session, ResultInterface result) {
try { int columnCount = result.getVisibleColumnCount();
ResultSetMetaData meta = rs.getMetaData(); Expression[] expressions = new Expression[columnCount];
int columnCount = meta.getColumnCount(); Database db = session == null ? null : session.getDatabase();
Expression[] expressions = new Expression[columnCount]; for (int i = 0; i < columnCount; i++) {
Database db = session == null ? null : session.getDatabase(); String name = result.getColumnName(i);
for (int i = 0; i < columnCount; i++) { int type = result.getColumnType(i);
String name = meta.getColumnLabel(i + 1); long precision = result.getColumnPrecision(i);
int type = DataType.getValueTypeFromResultSet(meta, i + 1); int scale = result.getColumnScale(i);
int precision = meta.getPrecision(i + 1); int displaySize = result.getDisplaySize(i);
int scale = meta.getScale(i + 1); Column col = new Column(name, type, precision, scale, displaySize);
int displaySize = meta.getColumnDisplaySize(i + 1); Expression expr = new ExpressionColumn(db, col);
Column col = new Column(name, type, precision, scale, displaySize); expressions[i] = expr;
Expression expr = new ExpressionColumn(db, col);
expressions[i] = expr;
}
return expressions;
} catch (SQLException e) {
throw DbException.convert(e);
} }
return expressions;
} }
/** /**
......
...@@ -1532,8 +1532,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -1532,8 +1532,7 @@ public class Function extends Expression implements FunctionCall {
String[] columns = StringUtils.arraySplit(columnList, String[] columns = StringUtils.arraySplit(columnList,
fieldSeparator, true); fieldSeparator, true);
try { try {
result = ValueResultSet.get(csv.read(fileName, result = ValueResultSet.get(session, csv.read(fileName, columns, charset), Integer.MAX_VALUE);
columns, charset));
} catch (SQLException e) { } catch (SQLException e) {
throw DbException.convert(e); throw DbException.convert(e);
} }
...@@ -1545,7 +1544,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -1545,7 +1544,7 @@ public class Function extends Expression implements FunctionCall {
ResultSet rs = LinkSchema.linkSchema(conn, v0.getString(), ResultSet rs = LinkSchema.linkSchema(conn, v0.getString(),
v1.getString(), v2.getString(), v3.getString(), v1.getString(), v2.getString(), v3.getString(),
v4.getString(), v5.getString()); v4.getString(), v5.getString());
result = ValueResultSet.get(rs); result = ValueResultSet.get(session, rs, Integer.MAX_VALUE);
break; break;
} }
case CSVWRITE: { case CSVWRITE: {
...@@ -2679,7 +2678,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -2679,7 +2678,7 @@ public class Function extends Expression implements FunctionCall {
ValueResultSet x; ValueResultSet x;
try { try {
rs = csv.read(fileName, columns, charset); rs = csv.read(fileName, columns, charset);
x = ValueResultSet.getCopy(rs, 0); x = ValueResultSet.get(session, rs, 0);
} catch (SQLException e) { } catch (SQLException e) {
throw DbException.convert(e); throw DbException.convert(e);
} finally { } finally {
......
...@@ -173,7 +173,7 @@ public class JavaFunction extends Expression implements FunctionCall { ...@@ -173,7 +173,7 @@ public class JavaFunction extends Expression implements FunctionCall {
switch (getType()) { switch (getType()) {
case Value.RESULT_SET: case Value.RESULT_SET:
ValueResultSet rs = getValueForColumnList(session, getArgs()); ValueResultSet rs = getValueForColumnList(session, getArgs());
return getExpressionColumns(session, rs.getResultSet()); return getExpressionColumns(session, rs.getResult());
case Value.ARRAY: case Value.ARRAY:
return getExpressionColumns(session, (ValueArray) getValue(session)); return getExpressionColumns(session, (ValueArray) getValue(session));
} }
......
...@@ -13,10 +13,7 @@ import org.h2.engine.Session; ...@@ -13,10 +13,7 @@ import org.h2.engine.Session;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.result.LocalResult; import org.h2.result.LocalResult;
import org.h2.table.Column; import org.h2.table.Column;
import org.h2.tools.SimpleResultSet;
import org.h2.util.MathUtils;
import org.h2.util.StatementBuilder; import org.h2.util.StatementBuilder;
import org.h2.value.DataType;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueArray; import org.h2.value.ValueArray;
import org.h2.value.ValueNull; import org.h2.value.ValueNull;
...@@ -124,33 +121,7 @@ public class TableFunction extends Function { ...@@ -124,33 +121,7 @@ public class TableFunction extends Function {
} }
} }
result.done(); result.done();
return ValueResultSet.get(getSimpleResultSet(result, return ValueResultSet.get(result, Integer.MAX_VALUE);
Integer.MAX_VALUE));
}
private static SimpleResultSet getSimpleResultSet(LocalResult rs,
int maxrows) {
int columnCount = rs.getVisibleColumnCount();
SimpleResultSet simple = new SimpleResultSet();
simple.setAutoClose(false);
for (int i = 0; i < columnCount; i++) {
String name = rs.getColumnName(i);
DataType dataType = DataType.getDataType(rs.getColumnType(i));
int sqlType = dataType.sqlType;
String sqlTypeName = dataType.name;
int precision = MathUtils.convertLongToInt(rs.getColumnPrecision(i));
int scale = rs.getColumnScale(i);
simple.addColumn(name, sqlType, sqlTypeName, precision, scale);
}
rs.reset();
for (int i = 0; i < maxrows && rs.next(); i++) {
Object[] list = new Object[columnCount];
for (int j = 0; j < columnCount; j++) {
list[j] = rs.currentRow()[j].getObject();
}
simple.addRow(list);
}
return simple;
} }
public long getRowCount() { public long getRowCount() {
...@@ -159,8 +130,7 @@ public class TableFunction extends Function { ...@@ -159,8 +130,7 @@ public class TableFunction extends Function {
@Override @Override
public Expression[] getExpressionColumns(Session session) { public Expression[] getExpressionColumns(Session session) {
return getExpressionColumns(session, return getExpressionColumns(session, getTable(session, getArgs(), true, false).getResult());
getTable(session, getArgs(), true, false).getResultSet());
} }
} }
...@@ -5,13 +5,9 @@ ...@@ -5,13 +5,9 @@
*/ */
package org.h2.index; package org.h2.index;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.message.DbException; import org.h2.result.ResultInterface;
import org.h2.result.SearchRow; import org.h2.result.SearchRow;
import org.h2.value.DataType;
import org.h2.value.Value; import org.h2.value.Value;
/** /**
...@@ -19,35 +15,25 @@ import org.h2.value.Value; ...@@ -19,35 +15,25 @@ import org.h2.value.Value;
*/ */
public class FunctionCursorResultSet extends AbstractFunctionCursor { public class FunctionCursorResultSet extends AbstractFunctionCursor {
private final ResultSet result; private final ResultInterface result;
private final ResultSetMetaData meta;
FunctionCursorResultSet(FunctionIndex index, SearchRow first, SearchRow last, Session session, ResultSet result) { FunctionCursorResultSet(FunctionIndex index, SearchRow first, SearchRow last, Session session, ResultInterface result) {
super(index, first, last, session); super(index, first, last, session);
this.result = result; this.result = result;
try {
this.meta = result.getMetaData();
} catch (SQLException e) {
throw DbException.convert(e);
}
} }
@Override @Override
boolean nextImpl() { boolean nextImpl() {
row = null; row = null;
try { if (result != null && result.next()) {
if (result != null && result.next()) { int columnCount = result.getVisibleColumnCount();
int columnCount = meta.getColumnCount(); Value[] currentRow = result.currentRow();
values = new Value[columnCount]; values = new Value[columnCount];
for (int i = 0; i < columnCount; i++) { for (int i = 0; i < columnCount; i++) {
int type = DataType.getValueTypeFromResultSet(meta, i + 1); values[i] = currentRow[i];
values[i] = DataType.readValue(session, result, i + 1, type);
}
} else {
values = null;
} }
} catch (SQLException e) { } else {
throw DbException.convert(e); values = null;
} }
return values != null; return values != null;
} }
......
...@@ -53,6 +53,7 @@ import org.h2.value.Value; ...@@ -53,6 +53,7 @@ import org.h2.value.Value;
import org.h2.value.ValueBytes; import org.h2.value.ValueBytes;
import org.h2.value.ValueInt; import org.h2.value.ValueInt;
import org.h2.value.ValueNull; import org.h2.value.ValueNull;
import org.h2.value.ValueResultSet;
import org.h2.value.ValueString; import org.h2.value.ValueString;
/** /**
...@@ -2061,6 +2062,10 @@ public class JdbcConnection extends TraceObject ...@@ -2061,6 +2062,10 @@ public class JdbcConnection extends TraceObject
session.getDataHandler()); session.getDataHandler());
} }
break; break;
case Value.RESULT_SET: {
int id = getNextId(TraceObject.RESULT_SET);
return new JdbcResultSet(this, null, null, ((ValueResultSet) v).getResult(), id, false, true, false);
}
case Value.BYTE: case Value.BYTE:
case Value.SHORT: case Value.SHORT:
if (!SysProperties.OLD_RESULT_SET_GET_OBJECT) { if (!SysProperties.OLD_RESULT_SET_GET_OBJECT) {
......
...@@ -8,9 +8,6 @@ package org.h2.mvstore.db; ...@@ -8,9 +8,6 @@ package org.h2.mvstore.db;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Arrays; import java.util.Arrays;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.api.IntervalQualifier; import org.h2.api.IntervalQualifier;
...@@ -22,10 +19,12 @@ import org.h2.mvstore.WriteBuffer; ...@@ -22,10 +19,12 @@ import org.h2.mvstore.WriteBuffer;
import org.h2.mvstore.rtree.SpatialDataType; import org.h2.mvstore.rtree.SpatialDataType;
import org.h2.mvstore.rtree.SpatialKey; import org.h2.mvstore.rtree.SpatialKey;
import org.h2.mvstore.type.DataType; import org.h2.mvstore.type.DataType;
import org.h2.result.ResultInterface;
import org.h2.result.SimpleResult;
import org.h2.result.SortOrder; import org.h2.result.SortOrder;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.tools.SimpleResultSet;
import org.h2.util.JdbcUtils; import org.h2.util.JdbcUtils;
import org.h2.util.MathUtils;
import org.h2.util.Utils; import org.h2.util.Utils;
import org.h2.value.CompareMode; import org.h2.value.CompareMode;
import org.h2.value.Value; import org.h2.value.Value;
...@@ -405,33 +404,23 @@ public class ValueDataType implements DataType { ...@@ -405,33 +404,23 @@ public class ValueDataType implements DataType {
} }
case Value.RESULT_SET: { case Value.RESULT_SET: {
buff.put((byte) type); buff.put((byte) type);
try { ResultInterface result = ((ValueResultSet) v).getResult();
ResultSet rs = ((ValueResultSet) v).getResultSet(); int columnCount = result.getVisibleColumnCount();
rs.beforeFirst(); buff.putVarInt(columnCount);
ResultSetMetaData meta = rs.getMetaData(); for (int i = 0; i < columnCount; i++) {
int columnCount = meta.getColumnCount(); writeString(buff, result.getColumnName(i));
buff.putVarInt(columnCount); buff.putVarInt(org.h2.value.DataType.getDataType(result.getColumnType(i)).sqlType).
putVarInt(MathUtils.convertLongToInt(result.getColumnPrecision(i))).
putVarInt(result.getColumnScale(i));
}
while (result.next()) {
buff.put((byte) 1);
Value[] row = result.currentRow();
for (int i = 0; i < columnCount; i++) { for (int i = 0; i < columnCount; i++) {
writeString(buff, meta.getColumnName(i + 1)); writeValue(buff, row[i]);
buff.putVarInt(meta.getColumnType(i + 1)).
putVarInt(meta.getPrecision(i + 1)).
putVarInt(meta.getScale(i + 1));
}
while (rs.next()) {
buff.put((byte) 1);
for (int i = 0; i < columnCount; i++) {
int t = org.h2.value.DataType.
getValueTypeFromResultSet(meta, i + 1);
Value val = org.h2.value.DataType.readValue(
null, rs, i + 1, t);
writeValue(buff, val);
}
} }
buff.put((byte) 0);
rs.beforeFirst();
} catch (SQLException e) {
throw DbException.convert(e);
} }
buff.put((byte) 0);
break; break;
} }
case Value.GEOMETRY: { case Value.GEOMETRY: {
...@@ -629,19 +618,17 @@ public class ValueDataType implements DataType { ...@@ -629,19 +618,17 @@ public class ValueDataType implements DataType {
return ValueArray.get(list); return ValueArray.get(list);
} }
case Value.RESULT_SET: { case Value.RESULT_SET: {
SimpleResultSet rs = new SimpleResultSet(); SimpleResult rs = new SimpleResult();
rs.setAutoClose(false);
int columns = readVarInt(buff); int columns = readVarInt(buff);
for (int i = 0; i < columns; i++) { for (int i = 0; i < columns; i++) {
rs.addColumn(readString(buff), String name = readString(buff);
readVarInt(buff), rs.addColumn(name, name, org.h2.value.DataType.convertSQLTypeToValueType(readVarInt(buff)),
readVarInt(buff), readVarInt(buff), readVarInt(buff), Integer.MAX_VALUE);
readVarInt(buff));
} }
while (buff.get() != 0) { while (buff.get() != 0) {
Object[] o = new Object[columns]; Value[] o = new Value[columns];
for (int i = 0; i < columns; i++) { for (int i = 0; i < columns; i++) {
o[i] = ((Value) readValue(buff)).getObject(); o[i] = (Value) readValue(buff);
} }
rs.addRow(o); rs.addRow(o);
} }
......
...@@ -5,13 +5,8 @@ ...@@ -5,13 +5,8 @@
*/ */
package org.h2.result; package org.h2.result;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.expression.Expression; import org.h2.expression.Expression;
import org.h2.message.DbException;
import org.h2.value.DataType;
import org.h2.value.Value;
/** /**
* Creates local result. * Creates local result.
...@@ -38,35 +33,6 @@ public abstract class LocalResultFactory { ...@@ -38,35 +33,6 @@ public abstract class LocalResultFactory {
*/ */
public abstract LocalResult create(); public abstract LocalResult create();
/**
* Construct a local result set by reading all data from a regular result
* set.
*
* @param session the session
* @param rs the result set
* @param maxrows the maximum number of rows to read (0 for no limit)
* @return the local result set
*/
public static LocalResult read(Session session, ResultSet rs, int maxrows) {
Expression[] cols = Expression.getExpressionColumns(session, rs);
int columnCount = cols.length;
LocalResult result = session.getDatabase().getResultFactory().create(session, cols, columnCount);
try {
for (int i = 0; (maxrows == 0 || i < maxrows) && rs.next(); i++) {
Value[] list = new Value[columnCount];
for (int j = 0; j < columnCount; j++) {
int type = result.getColumnType(j);
list[j] = DataType.readValue(session, rs, j + 1, type);
}
result.addRow(list);
}
} catch (SQLException e) {
throw DbException.convert(e);
}
result.done();
return result;
}
/** /**
* Default implementation of local result factory. * Default implementation of local result factory.
*/ */
......
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.result;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import org.h2.engine.SessionInterface;
import org.h2.util.Utils;
import org.h2.value.Value;
/**
* Simple in-memory result.
*/
public class SimpleResult implements ResultInterface {
private static final class Column {
final String alias;
final String columnName;
final int columnType;
final long columnPrecision;
final int columnScale;
final int displaySize;
Column(String alias, String columnName, int columnType, long columnPrecision, int columnScale,
int displaySize) {
this.alias = alias;
this.columnName = columnName;
this.columnType = columnType;
this.columnPrecision = columnPrecision;
this.columnScale = columnScale;
this.displaySize = displaySize;
}
}
private final ArrayList<Column> columns;
private final ArrayList<Value[]> rows;
private int rowId = -1;
/**
* Creates new instance of simple result.
*/
public SimpleResult() {
this.columns = Utils.newSmallArrayList();
this.rows = new ArrayList<>();
this.rowId = -1;
}
private SimpleResult(ArrayList<Column> columns, ArrayList<Value[]> rows) {
this.columns = columns;
this.rows = rows;
this.rowId = -1;
}
public void addColumn(String alias, String columnName, int columnType, long columnPrecision, int columnScale,
int displaySize) {
assert rows.isEmpty();
columns.add(new Column(alias, columnName, columnType, columnPrecision, columnScale, displaySize));
}
public void addRow(Value... values) {
assert values.length == columns.size();
rows.add(values);
}
@Override
public void reset() {
rowId = -1;
}
@Override
public Value[] currentRow() {
return rows.get(rowId);
}
@Override
public boolean next() {
if (rowId < rows.size() - 1) {
rowId++;
return true;
}
return false;
}
@Override
public int getRowId() {
return rowId;
}
@Override
public boolean isAfterLast() {
return rowId >= rows.size();
}
@Override
public int getVisibleColumnCount() {
return columns.size();
}
@Override
public int getRowCount() {
return rows.size();
}
@Override
public boolean hasNext() {
return rowId < rows.size();
}
@Override
public boolean needToClose() {
return false;
}
@Override
public void close() {
// Do nothing for now
}
@Override
public String getAlias(int i) {
return columns.get(i).alias;
}
@Override
public String getSchemaName(int i) {
return "";
}
@Override
public String getTableName(int i) {
return "";
}
@Override
public String getColumnName(int i) {
return columns.get(i).columnName;
}
@Override
public int getColumnType(int i) {
return columns.get(i).columnType;
}
@Override
public long getColumnPrecision(int i) {
return columns.get(i).columnPrecision;
}
@Override
public int getColumnScale(int i) {
return columns.get(i).columnScale;
}
@Override
public int getDisplaySize(int i) {
return columns.get(i).displaySize;
}
@Override
public boolean isAutoIncrement(int i) {
return false;
}
@Override
public int getNullable(int i) {
return ResultSetMetaData.columnNullableUnknown;
}
@Override
public void setFetchSize(int fetchSize) {
// Ignored
}
@Override
public int getFetchSize() {
return 1;
}
@Override
public boolean isLazy() {
return false;
}
@Override
public boolean isClosed() {
return false;
}
@Override
public ResultInterface createShallowCopy(SessionInterface targetSession) {
return new SimpleResult(columns, rows);
}
}
...@@ -13,16 +13,15 @@ import java.io.OutputStream; ...@@ -13,16 +13,15 @@ import java.io.OutputStream;
import java.io.Reader; import java.io.Reader;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.Arrays; import java.util.Arrays;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.api.IntervalQualifier; import org.h2.api.IntervalQualifier;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.tools.SimpleResultSet; import org.h2.result.ResultInterface;
import org.h2.result.SimpleResult;
import org.h2.util.Bits; import org.h2.util.Bits;
import org.h2.util.DateTimeUtils; import org.h2.util.DateTimeUtils;
import org.h2.util.JdbcUtils; import org.h2.util.JdbcUtils;
...@@ -630,31 +629,24 @@ public class Data { ...@@ -630,31 +629,24 @@ public class Data {
} }
case Value.RESULT_SET: { case Value.RESULT_SET: {
writeByte((byte) type); writeByte((byte) type);
try { ResultInterface result = ((ValueResultSet) v).getResult();
ResultSet rs = ((ValueResultSet) v).getResultSet(); result.reset();
rs.beforeFirst(); int columnCount = result.getVisibleColumnCount();
ResultSetMetaData meta = rs.getMetaData(); writeVarInt(columnCount);
int columnCount = meta.getColumnCount(); for (int i = 0; i < columnCount; i++) {
writeVarInt(columnCount); writeString(result.getColumnName(i));
writeVarInt(DataType.getDataType(result.getColumnType(i)).sqlType);
writeVarInt(MathUtils.convertLongToInt(result.getColumnPrecision(i)));
writeVarInt(result.getColumnScale(i));
}
while (result.next()) {
writeByte((byte) 1);
Value[] row = result.currentRow();
for (int i = 0; i < columnCount; i++) { for (int i = 0; i < columnCount; i++) {
writeString(meta.getColumnName(i + 1)); writeValue(row[i]);
writeVarInt(meta.getColumnType(i + 1));
writeVarInt(meta.getPrecision(i + 1));
writeVarInt(meta.getScale(i + 1));
} }
while (rs.next()) {
writeByte((byte) 1);
for (int i = 0; i < columnCount; i++) {
int t = DataType.getValueTypeFromResultSet(meta, i + 1);
Value val = DataType.readValue(null, rs, i + 1, t);
writeValue(val);
}
}
writeByte((byte) 0);
rs.beforeFirst();
} catch (SQLException e) {
throw DbException.convert(e);
} }
writeByte((byte) 0);
break; break;
} }
case Value.INTERVAL_YEAR: case Value.INTERVAL_YEAR:
...@@ -864,16 +856,17 @@ public class Data { ...@@ -864,16 +856,17 @@ public class Data {
return ValueArray.get(list); return ValueArray.get(list);
} }
case Value.RESULT_SET: { case Value.RESULT_SET: {
SimpleResultSet rs = new SimpleResultSet(); SimpleResult rs = new SimpleResult();
rs.setAutoClose(false);
int columns = readVarInt(); int columns = readVarInt();
for (int i = 0; i < columns; i++) { for (int i = 0; i < columns; i++) {
rs.addColumn(readString(), readVarInt(), readVarInt(), readVarInt()); String name = readString();
rs.addColumn(name, name, DataType.convertSQLTypeToValueType(readVarInt()), readVarInt(), readVarInt(),
Integer.MAX_VALUE);
} }
while (readByte() != 0) { while (readByte() != 0) {
Object[] o = new Object[columns]; Value[] o = new Value[columns];
for (int i = 0; i < columns; i++) { for (int i = 0; i < columns; i++) {
o[i] = readValue().getObject(); o[i] = readValue();
} }
rs.addRow(o); rs.addRow(o);
} }
...@@ -1100,31 +1093,24 @@ public class Data { ...@@ -1100,31 +1093,24 @@ public class Data {
} }
case Value.RESULT_SET: { case Value.RESULT_SET: {
int len = 1; int len = 1;
try { ResultInterface result = ((ValueResultSet) v).getResult();
ResultSet rs = ((ValueResultSet) v).getResultSet(); int columnCount = result.getVisibleColumnCount();
rs.beforeFirst(); len += getVarIntLen(columnCount);
ResultSetMetaData meta = rs.getMetaData(); for (int i = 0; i < columnCount; i++) {
int columnCount = meta.getColumnCount(); len += getStringLen(result.getColumnName(i));
len += getVarIntLen(columnCount); len += getVarIntLen(DataType.getDataType(result.getColumnType(i)).sqlType);
for (int i = 0; i < columnCount; i++) { len += getVarIntLen(MathUtils.convertLongToInt(result.getColumnPrecision(i)));
len += getStringLen(meta.getColumnName(i + 1)); len += getVarIntLen(result.getColumnScale(i));
len += getVarIntLen(meta.getColumnType(i + 1)); }
len += getVarIntLen(meta.getPrecision(i + 1)); while (result.next()) {
len += getVarIntLen(meta.getScale(i + 1)); len++;
} Value[] row = result.currentRow();
while (rs.next()) { for (int i = 0; i < columnCount; i++) {
len++; Value val = row[i];
for (int i = 0; i < columnCount; i++) { len += getValueLen(val, handler);
int t = DataType.getValueTypeFromResultSet(meta, i + 1); }
Value val = DataType.readValue(null, rs, i + 1, t); }
len += getValueLen(val, handler); len++;
}
}
len++;
rs.beforeFirst();
} catch (SQLException e) {
throw DbException.convert(e);
}
return len; return len;
} }
case Value.INTERVAL_YEAR: case Value.INTERVAL_YEAR:
......
...@@ -5,9 +5,6 @@ ...@@ -5,9 +5,6 @@
*/ */
package org.h2.table; package org.h2.table;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.engine.Session; import org.h2.engine.Session;
...@@ -18,12 +15,9 @@ import org.h2.index.FunctionIndex; ...@@ -18,12 +15,9 @@ import org.h2.index.FunctionIndex;
import org.h2.index.Index; import org.h2.index.Index;
import org.h2.index.IndexType; import org.h2.index.IndexType;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.result.LocalResult;
import org.h2.result.LocalResultFactory;
import org.h2.result.ResultInterface; import org.h2.result.ResultInterface;
import org.h2.result.Row; import org.h2.result.Row;
import org.h2.schema.Schema; import org.h2.schema.Schema;
import org.h2.value.DataType;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueNull; import org.h2.value.ValueNull;
import org.h2.value.ValueResultSet; import org.h2.value.ValueResultSet;
...@@ -37,7 +31,7 @@ public class FunctionTable extends Table { ...@@ -37,7 +31,7 @@ public class FunctionTable extends Table {
private final FunctionCall function; private final FunctionCall function;
private final long rowCount; private final long rowCount;
private Expression functionExpr; private Expression functionExpr;
private LocalResult cachedResult; private ResultInterface cachedResult;
private Value cachedValue; private Value cachedValue;
public FunctionTable(Schema schema, Session session, public FunctionTable(Schema schema, Session session,
...@@ -69,21 +63,17 @@ public class FunctionTable extends Table { ...@@ -69,21 +63,17 @@ public class FunctionTable extends Table {
throw DbException.get( throw DbException.get(
ErrorCode.FUNCTION_MUST_RETURN_RESULT_SET_1, function.getName()); ErrorCode.FUNCTION_MUST_RETURN_RESULT_SET_1, function.getName());
} }
ResultSet rs = template.getResultSet(); ResultInterface result = template.getResult();
try { int columnCount = result.getVisibleColumnCount();
ResultSetMetaData meta = rs.getMetaData(); Column[] cols = new Column[columnCount];
int columnCount = meta.getColumnCount(); for (int i = 0; i < columnCount; i++) {
Column[] cols = new Column[columnCount]; cols[i] = new Column(result.getColumnName(i),
for (int i = 0; i < columnCount; i++) { result.getColumnType(i),
cols[i] = new Column(meta.getColumnName(i + 1), result.getColumnPrecision(i),
DataType.getValueTypeFromResultSet(meta, i + 1), result.getColumnScale(i),
meta.getPrecision(i + 1), result.getDisplaySize(i));
meta.getScale(i + 1), meta.getColumnDisplaySize(i + 1));
}
setColumns(cols);
} catch (SQLException e) {
throw DbException.convert(e);
} }
setColumns(cols);
} }
@Override @Override
...@@ -195,7 +185,7 @@ public class FunctionTable extends Table { ...@@ -195,7 +185,7 @@ public class FunctionTable extends Table {
cachedResult.reset(); cachedResult.reset();
return cachedResult; return cachedResult;
} }
LocalResult result = LocalResultFactory.read(session, v.getResultSet(), 0); ResultInterface result = v.getResult();
if (function.isDeterministic()) { if (function.isDeterministic()) {
cachedResult = result; cachedResult = result;
cachedValue = v; cachedValue = v;
...@@ -207,11 +197,11 @@ public class FunctionTable extends Table { ...@@ -207,11 +197,11 @@ public class FunctionTable extends Table {
* Read the result set from the function. This method doesn't cache. * Read the result set from the function. This method doesn't cache.
* *
* @param session the session * @param session the session
* @return the result set * @return the result
*/ */
public ResultSet getResultSet(Session session) { public ResultInterface getResultSet(Session session) {
ValueResultSet v = getValueResultSet(session); ValueResultSet v = getValueResultSet(session);
return v == null ? null : v.getResultSet(); return v == null ? null : v.getResult();
} }
private ValueResultSet getValueResultSet(Session session) { private ValueResultSet getValueResultSet(Session session) {
......
...@@ -38,7 +38,6 @@ import org.h2.jdbc.JdbcClob; ...@@ -38,7 +38,6 @@ import org.h2.jdbc.JdbcClob;
import org.h2.jdbc.JdbcConnection; import org.h2.jdbc.JdbcConnection;
import org.h2.jdbc.JdbcLob; import org.h2.jdbc.JdbcLob;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.tools.SimpleResultSet;
import org.h2.util.JdbcUtils; import org.h2.util.JdbcUtils;
import org.h2.util.LocalDateTimeUtils; import org.h2.util.LocalDateTimeUtils;
import org.h2.util.Utils; import org.h2.util.Utils;
...@@ -779,7 +778,7 @@ public class DataType { ...@@ -779,7 +778,7 @@ public class DataType {
if (x == null) { if (x == null) {
return ValueNull.INSTANCE; return ValueNull.INSTANCE;
} }
return ValueResultSet.get(x); return ValueResultSet.get(session, x, Integer.MAX_VALUE);
} }
case Value.GEOMETRY: { case Value.GEOMETRY: {
Object x = rs.getObject(columnIndex); Object x = rs.getObject(columnIndex);
...@@ -1252,10 +1251,7 @@ public class DataType { ...@@ -1252,10 +1251,7 @@ public class DataType {
throw DbException.convert(e); throw DbException.convert(e);
} }
} else if (x instanceof ResultSet) { } else if (x instanceof ResultSet) {
if (x instanceof SimpleResultSet) { return ValueResultSet.get(session, (ResultSet) x, Integer.MAX_VALUE);
return ValueResultSet.get((ResultSet) x);
}
return ValueResultSet.getCopy((ResultSet) x, Integer.MAX_VALUE);
} else if (x instanceof UUID) { } else if (x instanceof UUID) {
return ValueUuid.get((UUID) x); return ValueUuid.get((UUID) x);
} }
......
...@@ -14,19 +14,17 @@ import java.io.Reader; ...@@ -14,19 +14,17 @@ import java.io.Reader;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.Socket; import java.net.Socket;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Timestamp; import java.sql.Timestamp;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.api.IntervalQualifier; import org.h2.api.IntervalQualifier;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.engine.SessionInterface; import org.h2.engine.SessionInterface;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.result.ResultInterface;
import org.h2.result.SimpleResult;
import org.h2.security.SHA256; import org.h2.security.SHA256;
import org.h2.store.Data; import org.h2.store.Data;
import org.h2.store.DataReader; import org.h2.store.DataReader;
import org.h2.tools.SimpleResultSet;
import org.h2.util.Bits; import org.h2.util.Bits;
import org.h2.util.DateTimeUtils; import org.h2.util.DateTimeUtils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
...@@ -479,31 +477,23 @@ public class Transfer { ...@@ -479,31 +477,23 @@ public class Transfer {
break; break;
} }
case Value.RESULT_SET: { case Value.RESULT_SET: {
try { ResultInterface result = ((ValueResultSet) v).getResult();
ResultSet rs = ((ValueResultSet) v).getResultSet(); int columnCount = result.getVisibleColumnCount();
rs.beforeFirst(); writeInt(columnCount);
ResultSetMetaData meta = rs.getMetaData(); for (int i = 0; i < columnCount; i++) {
int columnCount = meta.getColumnCount(); writeString(result.getColumnName(i));
writeInt(columnCount); writeInt(result.getColumnType(i));
writeInt(MathUtils.convertLongToInt(result.getColumnPrecision(i)));
writeInt(result.getColumnScale(i));
}
while (result.next()) {
writeBoolean(true);
Value[] row = result.currentRow();
for (int i = 0; i < columnCount; i++) { for (int i = 0; i < columnCount; i++) {
writeString(meta.getColumnName(i + 1)); writeValue(row[i]);
writeInt(meta.getColumnType(i + 1));
writeInt(meta.getPrecision(i + 1));
writeInt(meta.getScale(i + 1));
}
while (rs.next()) {
writeBoolean(true);
for (int i = 0; i < columnCount; i++) {
int t = DataType.getValueTypeFromResultSet(meta, i + 1);
Value val = DataType.readValue(session, rs, i + 1, t);
writeValue(val);
}
} }
writeBoolean(false);
rs.beforeFirst();
} catch (SQLException e) {
throw DbException.convertToIOException(e);
} }
writeBoolean(false);
break; break;
} }
case Value.GEOMETRY: case Value.GEOMETRY:
...@@ -684,16 +674,17 @@ public class Transfer { ...@@ -684,16 +674,17 @@ public class Transfer {
return ValueArray.get(componentType, list); return ValueArray.get(componentType, list);
} }
case Value.RESULT_SET: { case Value.RESULT_SET: {
SimpleResultSet rs = new SimpleResultSet(); SimpleResult rs = new SimpleResult();
rs.setAutoClose(false);
int columns = readInt(); int columns = readInt();
for (int i = 0; i < columns; i++) { for (int i = 0; i < columns; i++) {
rs.addColumn(readString(), readInt(), readInt(), readInt()); String name = readString();
rs.addColumn(name, name, DataType.convertSQLTypeToValueType(readInt()), readInt(), readInt(),
Integer.MAX_VALUE);
} }
while (readBoolean()) { while (readBoolean()) {
Object[] o = new Object[columns]; Value[] o = new Value[columns];
for (int i = 0; i < columns; i++) { for (int i = 0; i < columns; i++) {
o[i] = readValue().getObject(); o[i] = readValue();
} }
rs.addRow(o); rs.addRow(o);
} }
......
...@@ -14,23 +14,21 @@ import java.math.BigDecimal; ...@@ -14,23 +14,21 @@ import java.math.BigDecimal;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
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;
import java.sql.Types;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.api.IntervalQualifier; import org.h2.api.IntervalQualifier;
import org.h2.engine.Mode; import org.h2.engine.Mode;
import org.h2.engine.SysProperties; import org.h2.engine.SysProperties;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.result.ResultInterface;
import org.h2.result.SimpleResult;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.tools.SimpleResultSet;
import org.h2.util.Bits; import org.h2.util.Bits;
import org.h2.util.DateTimeUtils; import org.h2.util.DateTimeUtils;
import org.h2.util.IntervalUtils; import org.h2.util.IntervalUtils;
import org.h2.util.JdbcUtils; import org.h2.util.JdbcUtils;
import org.h2.util.MathUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
/** /**
...@@ -1290,12 +1288,10 @@ public abstract class Value { ...@@ -1290,12 +1288,10 @@ public abstract class Value {
} }
private ValueResultSet convertToResultSet() { private ValueResultSet convertToResultSet() {
String s = getString(); SimpleResult result = new SimpleResult();
SimpleResultSet rs = new SimpleResultSet(); result.addColumn("X", "X", getType(), getPrecision(), getScale(), getDisplaySize());
rs.setAutoClose(false); result.addRow(this);
rs.addColumn("X", Types.VARCHAR, s.length(), 0); return ValueResultSet.get(result);
rs.addRow(s);
return ValueResultSet.get(rs);
} }
private DbException getDataConversionError(int targetType) { private DbException getDataConversionError(int targetType) {
...@@ -1535,12 +1531,16 @@ public abstract class Value { ...@@ -1535,12 +1531,16 @@ public abstract class Value {
return this; return this;
} }
public ResultSet getResultSet() { /**
SimpleResultSet rs = new SimpleResultSet(); * Returns result for result set value, or single-row result with this value
rs.setAutoClose(false); * in column X for other values.
rs.addColumn("X", DataType.convertTypeToSQLType(getType()), *
MathUtils.convertLongToInt(getPrecision()), getScale()); * @return result
rs.addRow(getObject()); */
public ResultInterface getResult() {
SimpleResult rs = new SimpleResult();
rs.addColumn("X", "X", getType(), getPrecision(), getScale(), getDisplaySize());
rs.addRow(this);
return rs; return rs;
} }
......
...@@ -9,68 +9,97 @@ import java.sql.PreparedStatement; ...@@ -9,68 +9,97 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.ResultSetMetaData; import java.sql.ResultSetMetaData;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.engine.SessionInterface;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.tools.SimpleResultSet; import org.h2.result.ResultInterface;
import org.h2.util.StatementBuilder; import org.h2.result.SimpleResult;
/** /**
* Implementation of the RESULT_SET data type. * Implementation of the RESULT_SET data type.
*/ */
public class ValueResultSet extends Value { public class ValueResultSet extends Value {
private final ResultSet result; private final SimpleResult result;
private ValueResultSet(ResultSet rs) { private ValueResultSet(SimpleResult result) {
this.result = rs; this.result = result;
} }
/** /**
* Create a result set value for the given result set. * Create a result set value.
* The result set will be wrapped.
* *
* @param rs the result set * @param result the result
* @return the value * @return the value
*/ */
public static ValueResultSet get(ResultSet rs) { public static ValueResultSet get(SimpleResult result) {
return new ValueResultSet(rs); return new ValueResultSet(result);
} }
/** /**
* Create a result set value for the given result set. The result set will * Create a result set value for the given result set. The result set will
* be fully read in memory. The original result set is not closed. * be fully read in memory. The original result set is not closed.
* *
* @param session the session
* @param rs the result set * @param rs the result set
* @param maxrows the maximum number of rows to read (0 to just read the * @param maxrows the maximum number of rows to read (0 to just read the
* meta data) * meta data)
* @return the value * @return the value
*/ */
public static ValueResultSet getCopy(ResultSet rs, int maxrows) { public static ValueResultSet get(SessionInterface session, ResultSet rs, int maxrows) {
try { try {
ResultSetMetaData meta = rs.getMetaData(); ResultSetMetaData meta = rs.getMetaData();
int columnCount = meta.getColumnCount(); int columnCount = meta.getColumnCount();
SimpleResultSet simple = new SimpleResultSet(); SimpleResult simple = new SimpleResult();
simple.setAutoClose(false);
ValueResultSet val = new ValueResultSet(simple);
for (int i = 0; i < columnCount; i++) { for (int i = 0; i < columnCount; i++) {
String name = meta.getColumnLabel(i + 1); String alias = meta.getColumnLabel(i + 1);
int sqlType = meta.getColumnType(i + 1); String name = meta.getColumnName(i + 1);
int columnType = DataType.convertSQLTypeToValueType(meta.getColumnType(i + 1));
int precision = meta.getPrecision(i + 1); int precision = meta.getPrecision(i + 1);
int scale = meta.getScale(i + 1); int scale = meta.getScale(i + 1);
simple.addColumn(name, sqlType, precision, scale); int displaySize = meta.getColumnDisplaySize(i + 1);
simple.addColumn(alias, name, columnType, precision, scale, displaySize);
} }
for (int i = 0; i < maxrows && rs.next(); i++) { for (int i = 0; i < maxrows && rs.next(); i++) {
Object[] list = new Object[columnCount]; Value[] list = new Value[columnCount];
for (int j = 0; j < columnCount; j++) { for (int j = 0; j < columnCount; j++) {
list[j] = rs.getObject(j + 1); list[j] = DataType.convertToValue(session, rs.getObject(j + 1), simple.getColumnType(j));
} }
simple.addRow(list); simple.addRow(list);
} }
return val; return new ValueResultSet(simple);
} catch (SQLException e) { } catch (SQLException e) {
throw DbException.convert(e); throw DbException.convert(e);
} }
} }
/**
* Create a result set value for the given result. The result will be fully
* read in memory. The original result is not closed.
*
* @param result result
* @param maxrows the maximum number of rows to read (0 to just read the
* meta data)
* @return the value
*/
public static ValueResultSet get(ResultInterface result, int maxrows) {
int columnCount = result.getVisibleColumnCount();
SimpleResult simple = new SimpleResult();
for (int i = 0; i < columnCount; i++) {
simple.addColumn(result.getAlias(i), result.getColumnName(i), result.getColumnType(i),
result.getColumnPrecision(i), result.getColumnScale(i), result.getDisplaySize(i));
}
result.reset();
for (int i = 0; i < maxrows && result.next(); i++) {
Value[] list = new Value[columnCount];
for (int j = 0; j < columnCount; j++) {
Value[] row = result.currentRow();
list[j] = row[j];
}
simple.addRow(list);
}
return new ValueResultSet(simple);
}
@Override @Override
public int getType() { public int getType() {
return Value.RESULT_SET; return Value.RESULT_SET;
...@@ -89,30 +118,24 @@ public class ValueResultSet extends Value { ...@@ -89,30 +118,24 @@ public class ValueResultSet extends Value {
@Override @Override
public String getString() { public String getString() {
try { StringBuilder buff = new StringBuilder("(");
StatementBuilder buff = new StatementBuilder("("); ResultInterface result = this.result.createShallowCopy(null);
result.beforeFirst(); int columnCount = result.getVisibleColumnCount();
ResultSetMetaData meta = result.getMetaData(); for (int i = 0; result.next(); i++) {
int columnCount = meta.getColumnCount(); if (i > 0) {
for (int i = 0; result.next(); i++) { buff.append(", ");
if (i > 0) { }
buff.append('(');
Value[] row = result.currentRow();
for (int j = 0; j < columnCount; j++) {
if (j > 0) {
buff.append(", "); buff.append(", ");
} }
buff.append('('); buff.append(row[j].getString());
buff.resetCount();
for (int j = 0; j < columnCount; j++) {
buff.appendExceptFirst(", ");
int t = DataType.getValueTypeFromResultSet(meta, j + 1);
Value v = DataType.readValue(null, result, j + 1, t);
buff.append(v.getString());
}
buff.append(')');
} }
result.beforeFirst(); buff.append(')');
return buff.append(')').toString();
} catch (SQLException e) {
throw DbException.convert(e);
} }
return buff.append(')').toString();
} }
@Override @Override
...@@ -127,17 +150,17 @@ public class ValueResultSet extends Value { ...@@ -127,17 +150,17 @@ public class ValueResultSet extends Value {
@Override @Override
public int hashCode() { public int hashCode() {
return 0; return System.identityHashCode(this);
} }
@Override @Override
public Object getObject() { public Object getObject() {
return result; return getString();
} }
@Override @Override
public ResultSet getResultSet() { public ResultInterface getResult() {
return result; return result.createShallowCopy(null);
} }
@Override @Override
...@@ -155,9 +178,7 @@ public class ValueResultSet extends Value { ...@@ -155,9 +178,7 @@ public class ValueResultSet extends Value {
if (!force) { if (!force) {
return this; return this;
} }
SimpleResultSet rs = new SimpleResultSet(); return ValueResultSet.get(new SimpleResult());
rs.setAutoClose(false);
return ValueResultSet.get(rs);
} }
} }
...@@ -125,8 +125,6 @@ public class TestMetaData extends TestDb { ...@@ -125,8 +125,6 @@ public class TestMetaData extends TestDb {
assertEquals(DataType.TYPE_RESULT_SET, rsMeta.getColumnType(1)); assertEquals(DataType.TYPE_RESULT_SET, rsMeta.getColumnType(1));
rs.next(); rs.next();
assertTrue(rs.getObject(1) instanceof java.sql.ResultSet); assertTrue(rs.getObject(1) instanceof java.sql.ResultSet);
assertEquals("org.h2.tools.SimpleResultSet",
rs.getObject(1).getClass().getName());
stat.executeUpdate("drop alias x"); stat.executeUpdate("drop alias x");
rs = stat.executeQuery("select 1 from dual"); rs = stat.executeQuery("select 1 from dual");
......
...@@ -198,6 +198,7 @@ public class TestPreparedStatement extends TestDb { ...@@ -198,6 +198,7 @@ public class TestPreparedStatement extends TestDb {
testParameterMetaData(conn); testParameterMetaData(conn);
testColumnMetaDataWithEquals(conn); testColumnMetaDataWithEquals(conn);
testColumnMetaDataWithIn(conn); testColumnMetaDataWithIn(conn);
testValueResultSet(conn);
conn.close(); conn.close();
testPreparedStatementWithLiteralsNone(); testPreparedStatementWithLiteralsNone();
testPreparedStatementWithIndexedParameterAndLiteralsNone(); testPreparedStatementWithIndexedParameterAndLiteralsNone();
...@@ -1698,4 +1699,18 @@ public class TestPreparedStatement extends TestDb { ...@@ -1698,4 +1699,18 @@ public class TestPreparedStatement extends TestDb {
ps.getParameterMetaData().getParameterType(1)); ps.getParameterMetaData().getParameterType(1));
stmt.execute("DROP TABLE TEST"); stmt.execute("DROP TABLE TEST");
} }
private void testValueResultSet(Connection conn) throws SQLException {
for (int i = 0; i < 2; i++) {
try (PreparedStatement stmt = conn.prepareStatement("SELECT TABLE(X INT = (1))")) {
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
try (ResultSet rs2 = (ResultSet) rs.getObject(1)) {
assertEquals(1, rs2.getMetaData().getColumnCount());
}
}
}
}
}
} }
...@@ -8,16 +8,15 @@ package org.h2.test.unit; ...@@ -8,16 +8,15 @@ package org.h2.test.unit;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.Date; import java.sql.Date;
import java.sql.Time; import java.sql.Time;
import java.sql.Types;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.h2.api.JavaObjectSerializer; import org.h2.api.JavaObjectSerializer;
import org.h2.result.SimpleResult;
import org.h2.store.Data; import org.h2.store.Data;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.store.LobStorageBackend; import org.h2.store.LobStorageBackend;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.tools.SimpleResultSet;
import org.h2.util.SmallLRUCache; import org.h2.util.SmallLRUCache;
import org.h2.util.TempFileDeleter; import org.h2.util.TempFileDeleter;
import org.h2.value.CompareMode; import org.h2.value.CompareMode;
...@@ -208,13 +207,12 @@ public class TestDataPage extends TestBase implements DataHandler { ...@@ -208,13 +207,12 @@ public class TestDataPage extends TestBase implements DataHandler {
testValue(ValueArray.get(new Value[] { ValueBoolean.TRUE, testValue(ValueArray.get(new Value[] { ValueBoolean.TRUE,
ValueInt.get(10) })); ValueInt.get(10) }));
SimpleResultSet rs = new SimpleResultSet(); SimpleResult rs = new SimpleResult();
rs.setAutoClose(false); rs.addColumn("ID", "ID", Value.INT, 0, 0, ValueInt.DISPLAY_SIZE);
rs.addColumn("ID", Types.INTEGER, 0, 0); rs.addColumn("NAME", "NAME", Value.STRING, 255, 0, 255);
rs.addColumn("NAME", Types.VARCHAR, 255, 0); rs.addRow(ValueInt.get(1), ValueString.get("Hello"));
rs.addRow(1, "Hello"); rs.addRow(ValueInt.get(2), ValueString.get("World"));
rs.addRow(2, "World"); rs.addRow(ValueInt.get(3), ValueString.get("Peace"));
rs.addRow(3, "Peace");
testValue(ValueResultSet.get(rs)); testValue(ValueResultSet.get(rs));
} }
......
...@@ -22,7 +22,6 @@ import org.h2.util.DateTimeUtils; ...@@ -22,7 +22,6 @@ import org.h2.util.DateTimeUtils;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueDate; import org.h2.value.ValueDate;
import org.h2.value.ValueDouble; import org.h2.value.ValueDouble;
import org.h2.value.ValueInt;
import org.h2.value.ValueTime; import org.h2.value.ValueTime;
import org.h2.value.ValueTimestamp; import org.h2.value.ValueTimestamp;
......
...@@ -28,6 +28,8 @@ import org.h2.engine.Database; ...@@ -28,6 +28,8 @@ import org.h2.engine.Database;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.jdbc.JdbcConnection; import org.h2.jdbc.JdbcConnection;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.result.ResultInterface;
import org.h2.result.SimpleResult;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.test.TestDb; import org.h2.test.TestDb;
...@@ -41,6 +43,7 @@ import org.h2.value.ValueBytes; ...@@ -41,6 +43,7 @@ import org.h2.value.ValueBytes;
import org.h2.value.ValueDecimal; import org.h2.value.ValueDecimal;
import org.h2.value.ValueDouble; import org.h2.value.ValueDouble;
import org.h2.value.ValueFloat; import org.h2.value.ValueFloat;
import org.h2.value.ValueInt;
import org.h2.value.ValueJavaObject; import org.h2.value.ValueJavaObject;
import org.h2.value.ValueLobDb; import org.h2.value.ValueLobDb;
import org.h2.value.ValueNull; import org.h2.value.ValueNull;
...@@ -200,12 +203,14 @@ public class TestValue extends TestDb { ...@@ -200,12 +203,14 @@ public class TestValue extends TestDb {
assertEquals(32, v.convertPrecision(10, false).getBytes()[9]); assertEquals(32, v.convertPrecision(10, false).getBytes()[9]);
assertEquals(10, v.convertPrecision(10, true).getPrecision()); assertEquals(10, v.convertPrecision(10, true).getPrecision());
ResultSet rs = new SimpleResultSet(); SimpleResult rs = new SimpleResult();
rs.addColumn("X", "X", Value.INT, 0, 0, ValueInt.DISPLAY_SIZE);
rs.addRow(ValueInt.get(1));
v = ValueResultSet.get(rs); v = ValueResultSet.get(rs);
assertEquals(Integer.MAX_VALUE, v.getPrecision()); assertEquals(Integer.MAX_VALUE, v.getPrecision());
assertEquals(Integer.MAX_VALUE, v.convertPrecision(10, false).getPrecision()); assertEquals(Integer.MAX_VALUE, v.convertPrecision(10, false).getPrecision());
assertTrue(rs == v.convertPrecision(10, false).getObject()); assertEquals(1, v.convertPrecision(10, false).getResult().getRowCount());
assertFalse(rs == v.convertPrecision(10, true).getObject()); assertEquals(0, v.convertPrecision(10, true).getResult().getRowCount());
assertEquals(Integer.MAX_VALUE, v.convertPrecision(10, true).getPrecision()); assertEquals(Integer.MAX_VALUE, v.convertPrecision(10, true).getPrecision());
v = ValueString.get(spaces); v = ValueString.get(spaces);
...@@ -225,35 +230,52 @@ public class TestValue extends TestDb { ...@@ -225,35 +230,52 @@ public class TestValue extends TestDb {
rs.addRow(2, "World"); rs.addRow(2, "World");
rs.addRow(3, "Peace"); rs.addRow(3, "Peace");
ValueResultSet v; testValueResultSetTest(ValueResultSet.get(null, rs, Integer.MAX_VALUE), Integer.MAX_VALUE, true);
v = ValueResultSet.get(rs);
assertTrue(rs == v.getObject());
v = ValueResultSet.getCopy(rs, 2);
assertEquals(0, v.hashCode());
assertEquals(Integer.MAX_VALUE, v.getDisplaySize());
assertEquals(Integer.MAX_VALUE, v.getPrecision());
assertEquals(0, v.getScale());
assertEquals("", v.getSQL());
assertEquals(Value.RESULT_SET, v.getType());
assertEquals("((1, Hello), (2, World))", v.getString());
rs.beforeFirst();
ValueResultSet v2 = ValueResultSet.getCopy(rs, 2);
assertTrue(v.equals(v));
assertFalse(v.equals(v2));
rs.beforeFirst(); rs.beforeFirst();
testValueResultSetTest(ValueResultSet.get(null, rs, 2), 2, true);
ResultSet rs2 = v.getResultSet(); SimpleResult result = new SimpleResult();
rs2.next(); result.addColumn("ID", "ID", Value.INT, 0, 0, ValueInt.DISPLAY_SIZE);
rs.next(); result.addColumn("NAME", "NAME", Value.STRING, 255, 0, 255);
assertEquals(rs.getInt(1), rs2.getInt(1)); result.addRow(ValueInt.get(1), ValueString.get("Hello"));
assertEquals(rs.getString(2), rs2.getString(2)); result.addRow(ValueInt.get(2), ValueString.get("World"));
rs2.next(); result.addRow(ValueInt.get(3), ValueString.get("Peace"));
rs.next();
assertEquals(rs.getInt(1), rs2.getInt(1)); ValueResultSet v = ValueResultSet.get(result);
assertEquals(rs.getString(2), rs2.getString(2)); testValueResultSetTest(v, Integer.MAX_VALUE, false);
assertFalse(rs2.next());
assertTrue(rs.next()); testValueResultSetTest(ValueResultSet.get(v.getResult(), Integer.MAX_VALUE), Integer.MAX_VALUE, false);
testValueResultSetTest(ValueResultSet.get(v.getResult(), 2), 2, false);
}
private void testValueResultSetTest(ValueResultSet v, int count, boolean fromSimple) {
ResultInterface res = v.getResult();
assertEquals(2, res.getVisibleColumnCount());
assertEquals("ID", res.getAlias(0));
assertEquals("ID", res.getColumnName(0));
assertEquals(Value.INT, res.getColumnType(0));
assertEquals(0, res.getColumnPrecision(0));
assertEquals(0, res.getColumnScale(0));
assertEquals(fromSimple ? 15 : ValueInt.DISPLAY_SIZE, res.getDisplaySize(0));
assertEquals("NAME", res.getAlias(1));
assertEquals("NAME", res.getColumnName(1));
assertEquals(Value.STRING, res.getColumnType(1));
assertEquals(255, res.getColumnPrecision(1));
assertEquals(0, res.getColumnScale(1));
assertEquals(fromSimple ? 15 : 255, res.getDisplaySize(1));
if (count >= 1) {
assertTrue(res.next());
assertEquals(new Value[] {ValueInt.get(1), ValueString.get("Hello")}, res.currentRow());
if (count >= 2) {
assertTrue(res.next());
assertEquals(new Value[] {ValueInt.get(2), ValueString.get("World")}, res.currentRow());
if (count >= 3) {
assertTrue(res.next());
assertEquals(new Value[] {ValueInt.get(3), ValueString.get("Peace")}, res.currentRow());
}
}
}
assertFalse(res.next());
} }
private void testDataType() { private void testDataType() {
......
...@@ -16,12 +16,12 @@ import java.util.Random; ...@@ -16,12 +16,12 @@ import java.util.Random;
import org.h2.api.IntervalQualifier; import org.h2.api.IntervalQualifier;
import org.h2.api.JavaObjectSerializer; import org.h2.api.JavaObjectSerializer;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.result.SimpleResult;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.store.LobStorageFrontend; import org.h2.store.LobStorageFrontend;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.test.utils.MemoryFootprint; import org.h2.test.utils.MemoryFootprint;
import org.h2.tools.SimpleResultSet;
import org.h2.util.SmallLRUCache; import org.h2.util.SmallLRUCache;
import org.h2.util.TempFileDeleter; import org.h2.util.TempFileDeleter;
import org.h2.util.Utils; import org.h2.util.Utils;
...@@ -217,7 +217,7 @@ public class TestValueMemory extends TestBase implements DataHandler { ...@@ -217,7 +217,7 @@ public class TestValueMemory extends TestBase implements DataHandler {
return ValueArray.get(list); return ValueArray.get(list);
} }
case Value.RESULT_SET: case Value.RESULT_SET:
return ValueResultSet.get(new SimpleResultSet()); return ValueResultSet.get(new SimpleResult());
case Value.JAVA_OBJECT: case Value.JAVA_OBJECT:
return ValueJavaObject.getNoCopy(null, randomBytes(random.nextInt(100)), this); return ValueJavaObject.getNoCopy(null, randomBytes(random.nextInt(100)), this);
case Value.UUID: case Value.UUID:
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论