HSQL Java 语言例程在调用时导致 "General Error" (S1000)
HSQL Java Language Routines cause "General Error" (S1000) when called
我正在尝试将旧应用程序从 HSQLDB 1.8.0.10 迁移到最新版本 2.5.1。
一切正常,但旧应用程序为静态 Java 方法添加了两个 ALIAS
:
statement.execute("CREATE ALIAS BigBitAnd FOR \"org.somedomain.ClassName.bigBitAnd\"");
statement.execute("CREATE ALIAS BigMod FOR \"org.somedomain.ClassName.bigMod\"");
和
public static long bigBitAnd(long a, long b) {
return a & b;
}
public static long bigMod(long a, long b) {
return a % b;
}
我试过将其翻译成函数定义如下:
statement.execute("CREATE FUNCTION BIGBITAND(a BIGINT, b BIGINT) RETURNS BIGINT LANGUAGE JAVA DETERMINISTIC NO SQL EXTERNAL NAME 'CLASSPATH:org.somedomain.ClassName.bigBitAnd'");
statement.execute("CREATE FUNCTION BIGBITAND(a BIGINT, b BIGINT) RETURNS BIGINT LANGUAGE JAVA DETERMINISTIC NO SQL EXTERNAL NAME 'CLASSPATH:org.somedomain.ClassName.bigMod'");
函数已成功创建,但是当它们通过 PreparedStatement.executeQuery()
应用于任何语句时,查询失败并出现“一般错误”(S1000)。 google 搜索告诉我这可能是由于某处的 NumberFormatException 而发生的。
出于测试目的,我还尝试了 hsqldb 2.3.6。由于 NullPointerException,它也因“一般错误”而失败。
我的函数声明是否有问题,或者函数调用与 hsql 1.8 别名不同?
更新:我尝试用 BIGAND
调用替换所有出现的 BIGBITAND
,并且错误不再发生。但是,这会导致其他问题,因为据我所知,BIGAND
不适用于 BIGINT
。
BIGMOD
自定义函数似乎不会导致一般错误。
更新 2:使用 HSQLDB 2.4.0 版,我得到了更详细的堆栈跟踪:
Caused by: java.lang.NullPointerException
at org.hsqldb.RoutineSchema.getSpecificRoutine(Unknown Source)
at org.hsqldb.FunctionSQLInvoked.resolveTypes(Unknown Source)
at org.hsqldb.ExpressionLogical.resolveTypes(Unknown Source)
at org.hsqldb.ExpressionLogical.resolveTypes(Unknown Source)
at org.hsqldb.ExpressionLogical.resolveTypes(Unknown Source)
at org.hsqldb.ExpressionLogical.resolveTypes(Unknown Source)
at org.hsqldb.QuerySpecification.resolveExpressionTypes(Unknown Source)
at org.hsqldb.QuerySpecification.resolveTypesPartOne(Unknown Source)
at org.hsqldb.QueryExpression.resolve(Unknown Source)
at org.hsqldb.ParserDQL.compileCursorSpecification(Unknown Source)
at org.hsqldb.ParserCommand.compilePart(Unknown Source)
at org.hsqldb.ParserCommand.compileStatement(Unknown Source)
at org.hsqldb.Session.compileStatement(Unknown Source)
at org.hsqldb.StatementManager.compile(Unknown Source)
我找到了解决方法:
准备将 ?
占位符作为函数参数的语句时,HSQLDB 连接器会尝试解析 ?
占位符的类型,但失败了。
解决方法是在准备语句之前手动替换 ?
占位符。不是很干净,但至少可以用。
有时CASEWHEN表达式的类型判断不正确或类型不完全正确。您始终可以将函数参数(包括变量占位符 ?
)转换为您需要的类型。例如:
BIGBITAND(CAST( CASEWHEN(BIGMOD(p.val,2)=0,p.val+1,p.val-1) AS BIGINT), CAST(? AS BIGINT) ) != 0
P.S。非特定的“一般错误”是在引擎报告实际错误时引起的,即:"routine signature not found for: PUBLIC.BIGBITAND(DECIMAL,null) in statement .."
。由于自动类型扩展,表达式 p.val+1
的数据类型为 DECIMAL。这会导致引擎查找不存在的例程签名。
我正在尝试将旧应用程序从 HSQLDB 1.8.0.10 迁移到最新版本 2.5.1。
一切正常,但旧应用程序为静态 Java 方法添加了两个 ALIAS
:
statement.execute("CREATE ALIAS BigBitAnd FOR \"org.somedomain.ClassName.bigBitAnd\"");
statement.execute("CREATE ALIAS BigMod FOR \"org.somedomain.ClassName.bigMod\"");
和
public static long bigBitAnd(long a, long b) {
return a & b;
}
public static long bigMod(long a, long b) {
return a % b;
}
我试过将其翻译成函数定义如下:
statement.execute("CREATE FUNCTION BIGBITAND(a BIGINT, b BIGINT) RETURNS BIGINT LANGUAGE JAVA DETERMINISTIC NO SQL EXTERNAL NAME 'CLASSPATH:org.somedomain.ClassName.bigBitAnd'");
statement.execute("CREATE FUNCTION BIGBITAND(a BIGINT, b BIGINT) RETURNS BIGINT LANGUAGE JAVA DETERMINISTIC NO SQL EXTERNAL NAME 'CLASSPATH:org.somedomain.ClassName.bigMod'");
函数已成功创建,但是当它们通过 PreparedStatement.executeQuery()
应用于任何语句时,查询失败并出现“一般错误”(S1000)。 google 搜索告诉我这可能是由于某处的 NumberFormatException 而发生的。
出于测试目的,我还尝试了 hsqldb 2.3.6。由于 NullPointerException,它也因“一般错误”而失败。
我的函数声明是否有问题,或者函数调用与 hsql 1.8 别名不同?
更新:我尝试用 BIGAND
调用替换所有出现的 BIGBITAND
,并且错误不再发生。但是,这会导致其他问题,因为据我所知,BIGAND
不适用于 BIGINT
。
BIGMOD
自定义函数似乎不会导致一般错误。
更新 2:使用 HSQLDB 2.4.0 版,我得到了更详细的堆栈跟踪:
Caused by: java.lang.NullPointerException
at org.hsqldb.RoutineSchema.getSpecificRoutine(Unknown Source)
at org.hsqldb.FunctionSQLInvoked.resolveTypes(Unknown Source)
at org.hsqldb.ExpressionLogical.resolveTypes(Unknown Source)
at org.hsqldb.ExpressionLogical.resolveTypes(Unknown Source)
at org.hsqldb.ExpressionLogical.resolveTypes(Unknown Source)
at org.hsqldb.ExpressionLogical.resolveTypes(Unknown Source)
at org.hsqldb.QuerySpecification.resolveExpressionTypes(Unknown Source)
at org.hsqldb.QuerySpecification.resolveTypesPartOne(Unknown Source)
at org.hsqldb.QueryExpression.resolve(Unknown Source)
at org.hsqldb.ParserDQL.compileCursorSpecification(Unknown Source)
at org.hsqldb.ParserCommand.compilePart(Unknown Source)
at org.hsqldb.ParserCommand.compileStatement(Unknown Source)
at org.hsqldb.Session.compileStatement(Unknown Source)
at org.hsqldb.StatementManager.compile(Unknown Source)
我找到了解决方法:
准备将 ?
占位符作为函数参数的语句时,HSQLDB 连接器会尝试解析 ?
占位符的类型,但失败了。
解决方法是在准备语句之前手动替换 ?
占位符。不是很干净,但至少可以用。
有时CASEWHEN表达式的类型判断不正确或类型不完全正确。您始终可以将函数参数(包括变量占位符 ?
)转换为您需要的类型。例如:
BIGBITAND(CAST( CASEWHEN(BIGMOD(p.val,2)=0,p.val+1,p.val-1) AS BIGINT), CAST(? AS BIGINT) ) != 0
P.S。非特定的“一般错误”是在引擎报告实际错误时引起的,即:"routine signature not found for: PUBLIC.BIGBITAND(DECIMAL,null) in statement .."
。由于自动类型扩展,表达式 p.val+1
的数据类型为 DECIMAL。这会导致引擎查找不存在的例程签名。