我正在尝试为大型代码库设置单元测试环境。对于这些单元测试,我使用H2数据库而不是生产中使用的IBM DB2数据库,并且我已经实现了一些UDF来将IBM DB2相关的函数映射到H2数据库。关于项目的更多细节:
- Java 8 JDK 321 64 Bit
- db2 12, DSN 12015
- H2 version 2.1.212 with
我正在尝试实现IBM Db2函数:strip() Reference Doc - IBM。这个函数是作为一个更大的select语句的一部分使用子句调用的:STRIP(T2)。Item_type_name_ger, b, ' ')。虽然我可以第一个和最后一个输入参数映射到一个Java函数和调用这个函数作为一个别名H2,我没能弄到第二参数以正确的方式解析为一个字符串或表达式。JDBC/H2引擎总是尝试将其映射到表列:
这是我的Java UDF:org.h2.jdbc.JdbcSQLSyntaxErrorException: Feld "B" nicht gefunden Column "B" not found; SQL statement: SELECT T1.ITEM_TYPE_KEY,T1.SUPER_ITM_TYPE_KEY,T2.ITM_TYPE_KEY_TRANS,T2.ITEM_TYPE_NAME,T2.COMPLEX_FLAG,T2.ITEM_CATEGORY,T2.HEADER_FLAG,T2.HEADER_NO ,T2.LEVEL_NO,strip(T2.ITEM_TYPE_NAME_GER, B, ' ') ,T2.LEVEL1_DISPLAY FROM public.AA752T T1, public.AA743T T2 WHERE T1.ITEM_TYPE_KEY NOT IN ('F4CO', 'F4CB', 'F4RB', 'F4SO', 'F4SB', 'F4RO') AND T1.ITEM_TYPE_KEY = T2.ITEM_TYPE_KEY ORDER BY T2.HEADER_NO,T2.HEADER_FLAG DESC,T2.LEVEL_NO,T1.SUPER_ITM_TYPE_KEY,T2.LEVEL_PRIORITY [42122-212] at org.h2.message.DbException.getJdbcSQLException(DbException.java:502) at org.h2.message.DbException.getJdbcSQLException(DbException.java:477) at org.h2.message.DbException.get(DbException.java:223) at org.h2.message.DbException.get(DbException.java:199) at org.h2.expression.ExpressionColumn.getColumnException(ExpressionColumn.java:244) at org.h2.expression.ExpressionColumn.optimizeOther(ExpressionColumn.java:226) at org.h2.expression.ExpressionColumn.optimize(ExpressionColumn.java:213) at org.h2.expression.function.JavaFunction.optimize(JavaFunction.java:59) at org.h2.command.query.Select.prepareExpressions(Select.java:1170) at org.h2.command.query.Query.prepare(Query.java:218) at org.h2.command.Parser.prepareCommand(Parser.java:574) at org.h2.engine.SessionLocal.prepareLocal(SessionLocal.java:631) at org.h2.engine.SessionLocal.prepareCommand(SessionLocal.java:554) at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1116) at org.h2.jdbc.JdbcPreparedStatement.(JdbcPreparedStatement.java:92) at org.h2.jdbc.JdbcConnection.prepareStatement(JdbcConnection.java:288) at com.db.cib.gbd.gps.pbs.pricing.StaticItemDetails.retriveItemDisplayDetails(StaticItemDetails.java:920)
public static String strip(String s, Expression loc, String trimConstant) { if (loc.toLowerCase() == "b" || loc.toLowerCase() == "both") { s = s.replaceAll("^[" + trimConstant + "]+|[ t]+$", ""); } else if (loc.toLowerCase() == "l" || loc.toLowerCase() == "leading") { s = s.replaceAll("^[" + trimConstant + "]+", ""); } else if (loc.toLowerCase() == "t" || loc.toLowerCase() == "trailing") { s = s.replaceAll("[" + trimConstant + "]+$", ""); } return s; }
是否有可能以正确的方式获得列的映射,或者您可以建议使用SQL函数作为UDF别名(这是如何使用的?)或解决此错误的方法?为了避免这个问题:我不能改变现有的sql语句。我必须为这个函数找到一个别名。
不可能在H2中创建带有特殊参数的用户定义函数,而且很可能在所有或几乎所有其他数据库系统中都是如此。用户定义的函数只接受普通的逗号分隔参数与文字或表达式。
(也不能将参数声明为org.h2.expression.Expression
)
TRIM
函数:
https://h2database.com/html/functions.html修剪https://www.ibm.com/docs/en/db2-for-zos/11?topic=functions-trim
TRIM(BOTH ' ' FROM T2.ITEM_TYPE_NAME_GER)
请注意,B
、L
和T
首字母缩略词是db2特有的扩展,在H2中只能使用标准的BOTH
、LEADING
和TRAILING
。
如果你不能改变你的查询,你只能修改H2的来源,并在STRIP
的支持下编译它自己的版本。但实际上你马上就会遇到其他问题。当您想要同时使用多个数据库系统时,您需要认识到它们彼此之间是非常不同的。H2为其他模式提供了兼容模式,但即使在这些模式中,兼容性也非常有限。这意味着您需要避免使用特定于供应商的函数和其他语法元素,并且在某些情况下,可能需要针对不同系统使用不同的SQL。
您也可以尝试创建常数B
,BOTH
,L
,LEADING
,T
和TRAILING
与一些值
CREATE CONSTANT B VALUE 1;
CREATE CONSTANT BOTH VALUE 1;
CREATE CONSTANT L VALUE 2;
…
并创建一个有三个参数的函数,第二个参数的类型为int
(或者其他,如果您决定选择其他数据类型的值)。但是,常量的名称可能与列名冲突,所以这种解决方法远非完美,在某些查询中可能根本不起作用。