提交 0381d824 authored 作者: Thomas Mueller's avatar Thomas Mueller

Java functions: array component types are now preserved, so that a…

Java functions: array component types are now preserved, so that a ResultSet.getObject() will return Integer[] if the Java functions returns Integer[]. Thanks to Noel Grandin for the patch.
上级 7501daeb
...@@ -18,7 +18,9 @@ Change Log ...@@ -18,7 +18,9 @@ Change Log
<h1>Change Log</h1> <h1>Change Log</h1>
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul><li>Recover tool: the script generated by the recover tool didn't work <ul><li>Java functions: array component types are now preserved, so that a ResultSet.getObject()
will return Integer[] if the Java functions returns Integer[]. Thanks to Noel Grandin for the patch.
</li><li>Recover tool: the script generated by the recover tool didn't work
if fulltext search was used, because the triggers were created before the primary keys. if fulltext search was used, because the triggers were created before the primary keys.
</li><li>Issue 321: the database does not expect XA rollback without XA prepare </li><li>Issue 321: the database does not expect XA rollback without XA prepare
(an exception was unnecessarily written into the .trace.db file). (an exception was unnecessarily written into the .trace.db file).
......
...@@ -30,6 +30,7 @@ import org.h2.util.StringUtils; ...@@ -30,6 +30,7 @@ import org.h2.util.StringUtils;
import org.h2.util.Utils; import org.h2.util.Utils;
import org.h2.value.DataType; import org.h2.value.DataType;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueArray;
import org.h2.value.ValueNull; import org.h2.value.ValueNull;
/** /**
...@@ -352,6 +353,14 @@ public class FunctionAlias extends SchemaObjectBase { ...@@ -352,6 +353,14 @@ public class FunctionAlias extends SchemaObjectBase {
Object o; Object o;
if (Value.class.isAssignableFrom(paramClass)) { if (Value.class.isAssignableFrom(paramClass)) {
o = v; o = v;
} else if (v.getType() == Value.ARRAY && paramClass.isArray() && paramClass.getComponentType() != Object.class) {
Value[] array = ((ValueArray) v).getList();
Object[] objArray = (Object[]) Array.newInstance(paramClass.getComponentType(), array.length);
int componentType = DataType.getTypeFromClass(paramClass.getComponentType());
for (int i = 0; i < objArray.length; i++) {
objArray[i] = array[i].convertTo(componentType).getObject();
}
o = objArray;
} else { } else {
v = v.convertTo(type); v = v.convertTo(type);
o = v.getObject(); o = v.getObject();
......
...@@ -917,7 +917,7 @@ public class DataType { ...@@ -917,7 +917,7 @@ public class DataType {
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
v[i] = convertToValue(session, o[i], type); v[i] = convertToValue(session, o[i], type);
} }
return ValueArray.get(v); return ValueArray.get(x.getClass().getComponentType(), v);
} else if (x instanceof Character) { } else if (x instanceof Character) {
return ValueStringFixed.get(((Character) x).toString()); return ValueStringFixed.get(((Character) x).toString());
} else { } else {
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
*/ */
package org.h2.value; package org.h2.value;
import java.lang.reflect.Array;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.util.ArrayList; import java.util.ArrayList;
import org.h2.engine.Constants; import org.h2.engine.Constants;
...@@ -18,12 +19,18 @@ import org.h2.util.StatementBuilder; ...@@ -18,12 +19,18 @@ import org.h2.util.StatementBuilder;
*/ */
public class ValueArray extends Value { public class ValueArray extends Value {
private final Class<?> componentType;
private final Value[] values; private final Value[] values;
private int hash; private int hash;
private ValueArray(Value[] list) { private ValueArray(Class<?> componentType, Value[] list) {
this.componentType = componentType;
this.values = list; this.values = list;
} }
private ValueArray(Value[] list) {
this(Object.class, list);
}
/** /**
* Get or create a array value for the given value array. * Get or create a array value for the given value array.
...@@ -36,6 +43,17 @@ public class ValueArray extends Value { ...@@ -36,6 +43,17 @@ public class ValueArray extends Value {
return new ValueArray(list); return new ValueArray(list);
} }
/**
* Get or create a array value for the given value array.
* Do not clone the data.
*
* @param list the value array
* @return the value
*/
public static ValueArray get(Class<?> componentType, Value[] list) {
return new ValueArray(componentType, list);
}
public int hashCode() { public int hashCode() {
if (hash != 0) { if (hash != 0) {
return hash; return hash;
...@@ -55,6 +73,10 @@ public class ValueArray extends Value { ...@@ -55,6 +73,10 @@ public class ValueArray extends Value {
public int getType() { public int getType() {
return Value.ARRAY; return Value.ARRAY;
} }
public Class<?> getComponentType() {
return componentType;
}
public long getPrecision() { public long getPrecision() {
long p = 0; long p = 0;
...@@ -94,7 +116,7 @@ public class ValueArray extends Value { ...@@ -94,7 +116,7 @@ public class ValueArray extends Value {
public Object getObject() { public Object getObject() {
int len = values.length; int len = values.length;
Object[] list = new Object[len]; Object[] list = (Object[]) Array.newInstance(componentType, len);
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
list[i] = values[i].getObject(); list[i] = values[i].getObject();
} }
......
...@@ -578,6 +578,30 @@ public abstract class TestBase { ...@@ -578,6 +578,30 @@ public abstract class TestBase {
} }
} }
/**
* Check if two values are equal, and if not throw an exception.
*
* @param expected the expected value
* @param actual the actual value
* @throws AssertionError if the values are not equal
*/
public void assertEquals(Object[] expected, Object[] actual) {
if (expected == null || actual == null) {
assertTrue(expected == actual);
return;
}
assertEquals(expected.length, actual.length);
for (int i = 0; i < expected.length; i++) {
if (expected[i] == null || actual[i] == null) {
if (expected[i] != actual[i]) {
fail("[" + i + "]: expected: " + expected[i] + " actual: " + actual[i]);
}
} else if (!expected[i].equals(actual[i])) {
fail("[" + i + "]: expected: " + expected[i] + " actual: " + actual[i]);
}
}
}
/** /**
* Check if two readers are equal, and if not throw an exception. * Check if two readers are equal, and if not throw an exception.
* *
......
...@@ -13,6 +13,7 @@ import java.io.OutputStream; ...@@ -13,6 +13,7 @@ import java.io.OutputStream;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.Array; import java.sql.Array;
import java.sql.Blob; import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DatabaseMetaData; import java.sql.DatabaseMetaData;
import java.sql.DriverManager; import java.sql.DriverManager;
...@@ -50,6 +51,7 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -50,6 +51,7 @@ public class TestFunctions extends TestBase implements AggregateFunction {
public void test() throws Exception { public void test() throws Exception {
deleteDb("functions"); deleteDb("functions");
testArrayParameters();
testDefaultConnection(); testDefaultConnection();
testFunctionInSchema(); testFunctionInSchema();
testGreatest(); testGreatest();
...@@ -731,6 +733,33 @@ public class TestFunctions extends TestBase implements AggregateFunction { ...@@ -731,6 +733,33 @@ public class TestFunctions extends TestBase implements AggregateFunction {
conn.close(); conn.close();
} }
private void testArrayParameters() throws SQLException {
deleteDb("functions");
Connection conn = getConnection("functions");
Statement stat = conn.createStatement();
ResultSet rs;
stat.execute("create alias array_test AS "
+ "$$ Integer[] array_test(Integer[] in_array) "
+ "{ return in_array; } $$;");
PreparedStatement stmt = conn.prepareStatement("select array_test(?) from dual");
stmt.setObject(1, new Integer[] { 1, 2 });
rs = stmt.executeQuery();
rs.next();
assertEquals(Integer[].class.getName(), rs.getObject(1).getClass().getName());
CallableStatement call = conn.prepareCall("{ ? = call array_test(?) }");
call.setObject(2, new Integer[] { 2, 1 });
call.registerOutParameter(1, Types.ARRAY);
call.execute();
assertEquals(Integer[].class.getName(), call.getArray(1).getArray().getClass().getName());
assertEquals(new Integer[] { 2, 1 }, (Integer[]) call.getObject(1));
stat.execute("drop alias array_test");
conn.close();
}
private void assertCallResult(String expected, Statement stat, String sql) throws SQLException { private void assertCallResult(String expected, Statement stat, String sql) throws SQLException {
ResultSet rs = stat.executeQuery("CALL " + sql); ResultSet rs = stat.executeQuery("CALL " + sql);
rs.next(); rs.next();
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论