/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.jdbc;
import java.sql.Array;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Map;
import org.h2.constant.ErrorCode;
import org.h2.message.DbException;
import org.h2.message.TraceObject;
import org.h2.tools.SimpleResultSet;
import org.h2.value.Value;
/**
* Represents an ARRAY value.
*/
public class JdbcArray extends TraceObject implements Array {
private Value value;
private JdbcConnection conn;
/**
* INTERNAL
*/
JdbcArray(JdbcConnection conn, Value value, int id) {
setTrace(conn.getSession().getTrace(), TraceObject.ARRAY, id);
this.conn = conn;
this.value = value;
}
/**
* Returns the value as a Java array.
* This method always returns an Object[].
*
* @return the Object array
*/
public Object getArray() throws SQLException {
try {
debugCodeCall("getArray");
checkClosed();
return get();
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Returns the value as a Java array.
* This method always returns an Object[].
*
* @param map is ignored. Only empty or null maps are supported
* @return the Object array
*/
public Object getArray(Map<String, Class<?>> map) throws SQLException {
try {
debugCode("getArray("+quoteMap(map)+");");
checkMap(map);
checkClosed();
return get();
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Returns the value as a Java array. A subset of the array is returned,
* starting from the index (1 meaning the first element) and up to the given
* object count. This method always returns an Object[].
*
* @param index the start index of the subset (starting with 1)
* @param count the maximum number of values
* @return the Object array
*/
public Object getArray(long index, int count) throws SQLException {
try {
debugCode("getArray(" + index + ", " + count + ");");
checkClosed();
return get(index, count);
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Returns the value as a Java array. A subset of the array is returned,
* starting from the index (1 meaning the first element) and up to the given
* object count. This method always returns an Object[].
*
* @param index the start index of the subset (starting with 1)
* @param count the maximum number of values
* @param map is ignored. Only empty or null maps are supported
* @return the Object array
*/
public Object getArray(long index, int count, Map<String, Class<?>> map) throws SQLException {
try {
debugCode("getArray(" + index + ", " + count + ", " + quoteMap(map)+");");
checkClosed();
checkMap(map);
return get(index, count);
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Returns the base type of the array. This database does support mixed type
* arrays and therefore there is no base type.
*
* @return Types.NULL
*/
public int getBaseType() throws SQLException {
try {
debugCodeCall("getBaseType");
checkClosed();
return Types.NULL;
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Returns the base type name of the array. This database does support mixed
* type arrays and therefore there is no base type.
*
* @return "NULL"
*/
public String getBaseTypeName() throws SQLException {
try {
debugCodeCall("getBaseTypeName");
checkClosed();
return "NULL";
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Returns the value as a result set.
* The first column contains the index
* (starting with 1) and the second column the value.
*
* @return the result set
*/
public ResultSet getResultSet() throws SQLException {
try {
debugCodeCall("getResultSet");
checkClosed();
return getResultSet(get(), 0);
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Returns the value as a result set. The first column contains the index
* (starting with 1) and the second column the value.
*
* @param map is ignored. Only empty or null maps are supported
* @return the result set
*/
public ResultSet getResultSet(Map<String, Class<?>> map) throws SQLException {
try {
debugCode("getResultSet("+quoteMap(map)+");");
checkClosed();
checkMap(map);
return getResultSet(get(), 0);
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Returns the value as a result set. The first column contains the index
* (starting with 1) and the second column the value. A subset of the array
* is returned, starting from the index (1 meaning the first element) and
* up to the given object count.
*
* @param index the start index of the subset (starting with 1)
* @param count the maximum number of values
* @return the result set
*/
public ResultSet getResultSet(long index, int count) throws SQLException {
try {
debugCode("getResultSet("+index+", " + count+");");
checkClosed();
return getResultSet(get(index, count), index);
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Returns the value as a result set.
* The first column contains the index
* (starting with 1) and the second column the value.
* A subset of the array is returned, starting from the index
* (1 meaning the first element) and up to the given object count.
*
* @param index the start index of the subset (starting with 1)
* @param count the maximum number of values
* @param map is ignored. Only empty or null maps are supported
* @return the result set
*/
public ResultSet getResultSet(long index, int count, Map<String, Class<?>> map) throws SQLException {
try {
debugCode("getResultSet("+index+", " + count+", " + quoteMap(map)+");");
checkClosed();
checkMap(map);
return getResultSet(get(index, count), index);
} catch (Exception e) {
throw logAndConvert(e);
}
}
/**
* Release all resources of this object.
*/
public void free() {
debugCodeCall("free");
value = null;
}
private static ResultSet getResultSet(Object[] array, long offset) {
SimpleResultSet rs = new SimpleResultSet();
rs.addColumn("INDEX", Types.BIGINT, 0, 0);
// TODO array result set: there are multiple data types possible
rs.addColumn("VALUE", Types.NULL, 0, 0);
for (int i = 0; i < array.length; i++) {
rs.addRow(Long.valueOf(offset + i + 1), array[i]);
}
return rs;
}
private void checkClosed() {
conn.checkClosed();
if (value == null) {
throw DbException.get(ErrorCode.OBJECT_CLOSED);
}
}
private Object[] get() {
return (Object[]) value.convertTo(Value.ARRAY).getObject();
}
private Object[] get(long index, int count) {
Object[] array = get();
if (count < 0 || count > array.length) {
throw DbException.getInvalidValueException("count (1.."
+ array.length + ")", count);
}
if (index < 1 || index > array.length) {
throw DbException.getInvalidValueException("index (1.."
+ array.length + ")", index);
}
Object[] subset = new Object[count];
System.arraycopy(array, (int) (index - 1), subset, 0, count);
return subset;
}
private static void checkMap(Map<String, Class<?>> map) {
if (map != null && map.size() > 0) {
throw DbException.getUnsupportedException("map.size > 0");
}
}
/**
* INTERNAL
*/
public String toString() {
return getTraceObjectName() + ": " + value.getTraceSQL();
}
}