I am trying to create a JRT function that accepts a parameter of type INTERVAL
.
My query can provide any type of INTERVAL
but I'd prefer to use INTERVAL DAY
type if possible.
According to the HSQL documentation, my function should look something like:
public static String exampleHsqlFunction(final java.time.Period duration) {
return "In example function, arg: " + duration.toString();
}
Then, the function needs to be registered. There is no INTERVAL DAY
type specified in the table from documentation so I will use INTERVAL MONTH
instead:
CREATE FUNCTION EXAMPLE_FUNCTION (duration INTERVAL MONTH)
RETURNS CHAR VARYING(100)
LANGUAGE JAVA DETERMINISTIC NO SQL
EXTERNAL NAME 'CLASSPATH:hsqltest.HsqlIntervalFunctionTest.exampleHsqlFunction';
So far so good, my function is registered properly and no errors are shown.
I will now create a dummy table so I have something to SELECT
from when testing the function:
CREATE TABLE DUMMY(id INT); INSERT INTO DUMMY VALUES (0);
Finally, I can try calling the function itself:
SELECT EXAMPLE_FUNCTION(INTERVAL '3' MONTH) FROM DUMMY;
aaand I'm getting an error:
java.lang.IllegalArgumentException: argument type mismatch
I did some debugging, put a breakpoint in java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
and it turns out that HSQL passes org.hsqldb.types.IntervalMonthData
as argument to the method (or org.hsqldb.types.IntervalSecondData
for INTERVAL SECOND
type).
When the parameter type of Java method is changed to IntervalMonthData
, however, HSQL is not able to recognize it:
org.hsqldb.HsqlException: Java execution: unresolved class name, method name or signature
I also tried some silly stuff, such as passing INTERVAL '3' DAY
as argument. Then the following exception is thrown:
org.hsqldb.HsqlException: data exception: interval field overflow
The function works if we change the parameter to some other type, for example INT
and corresponding Integer
. It's only INTERVAL
that seems to be flaky.
I am using HSQL in version 2.5.0
(newest in Maven Central), minimal working example:
package hsqltest;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public final class HsqlIntervalFunctionTest {
public static String exampleHsqlFunction(final java.time.Period duration) {
return "In example function, arg: " + duration.toString();
}
public static void main(final String... args) throws SQLException {
try (
final Connection connection = DriverManager.getConnection(
"jdbc:hsqldb:mem:testdb",
"sa",
"sa"
);
final Statement statement = connection.createStatement()
) {
// create function and link it to Java method
statement.executeUpdate(
"CREATE FUNCTION EXAMPLE_FUNCTION (duration INTERVAL MONTH)"
+ " RETURNS CHAR VARYING(100)"
+ " LANGUAGE JAVA DETERMINISTIC NO SQL"
+ " EXTERNAL NAME 'CLASSPATH:hsqltest.HsqlIntervalFunctionTest.exampleHsqlFunction';"
);
// create dummy table so we have something to SELECT from
statement.executeUpdate("CREATE TABLE DUMMY(id INT);");
statement.executeUpdate("INSERT INTO DUMMY VALUES (0);");
// use the function and print the result
final ResultSet result = statement.executeQuery(
"SELECT EXAMPLE_FUNCTION(INTERVAL '3' MONTH) FROM DUMMY;"
);
while (result.next()) {
System.out.println(result.getString(1));
}
}
}
}