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

Add and use SimpleResult for ValueResultSet

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