我尝试在 H2 中为具有两个数组参数的函数创建别名。
参数:数组sourceArray, 数组子数组 返回布尔值: 如果 sourceArray 包含 subArray 的所有元素,则为 TRUE。 否则错误
我声明了函数:
CREATE ALIAS IF NOT EXISTS array_contains_all AS '
boolean arrayContainsAll(java.util.HashSet sourceArray, java.util.HashSet subArray) {
return sourceArray.containsAll(subArray);
}';
我称这个函数为:
SELECT array_contains_all (Array['HELLO', 'WORLD', 'FRIEND'], Array['HELLO', 'WORLD']);
我期望是真的。 但它抛出错误:
十六进制字符串包含非十六进制字符:“[HELLO,WORLD,FRIEND]”。
然后我尝试:
CREATE ALIAS IF NOT EXISTS array_contains_all AS '
boolean arrayContainsAll(java.sql.Array sourceArray, java.sql.Array subArray) {
java.util.List<Object> sourceArrayList = java.util.Arrays.asList((Object[]) sourceArray.getArray());
java.util.List<Object> subArrayList = java.util.Arrays.asList((Object[]) subArray.getArray());
return sourceArrayList.containsAll(subArrayList);
}';
它抛出同样的错误:
十六进制字符串包含非十六进制字符:“[HELLO,WORLD,FRIEND]”。
如何纠正这个问题?
您需要将 H2 版本升级到 2.*.* 并使用 Java 数组声明一个具有某些精确数据类型的元素的函数:
CREATE ALIAS IF NOT EXISTS ARRAY_CONTAINS_ALL AS '
import java.util.*;
@CODE
Boolean arrayContainsAll(String[] sourceArray, String[] subArray) {
if (sourceArray == null || subArray == null) {
return null;
}
if (subArray.length == 0) {
return true;
}
HashSet<String> subSet = new HashSet<>(Arrays.asList(subArray));
if (subSet.contains(null)) {
return null;
}
HashSet<String> sourceSet = new HashSet<>(Arrays.asList(sourceArray));
if (sourceSet.containsAll(subSet)) {
return true;
}
if (sourceSet.contains(null)) {
return null;
}
return false;
}
';
如果需要支持多种数据类型,可以尝试写一个同名不同参数方法的Java类,放入H2的classpath中,然后用
CREATE ALIAS … FOR 'package.class.method'
加载。
真正旧版本的 H2 有奇怪的
ARRAY
数据类型实现,与任何内容都不兼容。在这些版本中,你只能搞乱 H2 的内部类,它只能将数组传递给用户定义的函数,如 org.h2.value.Value
。