H2 DB映射到IBM DB2数据库UDF缺失功能:strip

发布于 2025-02-10 23:00:07 字数 3208 浏览 0 评论 0原文

我正在尝试为大型代码库设置单元测试环境。对于这些单元测试,我使用H2数据库而不是IBM DB2数据库,该数据库用于生产中,我已经实现了一些UDF来将IBM DB2相关功能映射到H2数据库。 有关该项目的更多详细信息:

  • Java 8 JDK 321 64位
  • DB2 12,DSN 12015
  • H2版本2.1.212带有< mode = db2; default_null_ordering = high;

我正在尝试实现IBM DB2函数:strip()参考文档-IBM 。此功能称为带有子句的较大选择语句的一部分:strip(t2.item_type_name_ger,b,'')。虽然我可以将第一个和最后一个输入参数映射到Java函数,并将此函数称为H2中的别名,但我无法设法以正确的方式将第二个参数解释为字符串或表达式。 JDBC/H2引擎总是试图将其映射到表列:

 
    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) 

这是我的Java UDF:


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语句。我必须找到这个功能的别名。

I am trying to setup a unit test environment for a large codebase. For these unit tests I use H2 database instead of the IBM DB2 database, which is used in production and I already implemented a few UDF's to map IBM DB2 related functions to the H2 database.
Some more Details about the project:

  • Java 8 JDK 321 64 Bit
  • DB2 12, DSN 12015
  • H2 version 2.1.212 with <MODE=DB2;DEFAULT_NULL_ORDERING=HIGH;

I am trying to implement the IBM Db2 function: strip() Reference Doc - IBM. This function is called as part of a larger select statement with the clause: STRIP(T2.ITEM_TYPE_NAME_GER, B, ' '). While I can map the first and last input parameter to a Java function and call this function as an ALIAS in H2, I was not able to manage to get the 2nd parameter interpreted in the correct way as a String or Expression. The JDBC/H2 engine always tries to map it to a table column:

 
    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) 

This is my Java UDF:


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;
}

Is there a possibility to get the mapping of the column in the correct way, or can you suggest either a SQL function, which is usable as UDF alias (how is this usable?) or a way to solve this error?
To avoid this question: I cannot change the existing sql statement. I have to find an alias for this function.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

£烟消云散 2025-02-17 23:00:07

不可能在H2中使用特殊参数创建用户定义的函数,并且最有可能在所有或几乎所有其他数据库系统中。用户定义的功能仅接受具有文字或表达式的普通逗号分隔的参数。

(您也不能将参数声明为org.h2.expression.expression。)

此处的正确解决方案是使用SQL标准使用TRIM函数:

https://h2database.com/html/functions.htmllunctions.html#trim

//www.ibm.com/docs/en/db2-for-zos/11?topic=functions-trim“ rel =” nofollow noreferrer“> https://www.ibm.com/docs/docs/docs/en/en/db2-for -zos/11?topic = functions-trim

TRIM(BOTH ' ' FROM T2.ITEM_TYPE_NAME_GER)

请注意,blt缩写词是DB2特定的扩展名,在H2中,您只能使用标准,<代码>领导和tailting

如果您无法更改查询,则只能在支持strip的支持下修改H2的源并编译自己的版本。但是实际上,您可以立即遇到其他问题。当您想一次使用多个数据库系统时,您需要意识到它们彼此之间都非常不同。 H2为他人提供兼容模式,但是即使在这些模式下,兼容性也非常有限。这意味着您需要避免使用特定于供应商的功能和其他语法元素,在某些情况下,可能需要用于不同系统的不同SQL。


您还可以尝试创建常数bl领导t, and TRAILING with some values

CREATE CONSTANT B VALUE 1;
CREATE CONSTANT BOTH VALUE 1;
CREATE CONSTANT L VALUE 2;
…

and create a function with three arguments, second argument will be of type int (or other, if you'll decide to choose values of some其他数据类型)。但是常数的名称可能与列名相抵触,因此此解决方法远非完美,并且在某些查询中可能根本无法使用。

It isn't possible to create a user-defined function with special arguments in H2 and most likely in all or almost all other database systems. User-defined functions accept only plain comma-separated arguments with literals or expressions in them.

(You also cannot declare a parameter as org.h2.expression.Expression.)

The proper solution here is to use the TRIM function from the SQL Standard:

https://h2database.com/html/functions.html#trim

https://www.ibm.com/docs/en/db2-for-zos/11?topic=functions-trim

TRIM(BOTH ' ' FROM T2.ITEM_TYPE_NAME_GER)

Please note that B, L, and T acronyms is a DB2-specific extension, in H2 you can use only standard BOTH, LEADING, and TRAILING.

If you cannot change your query you can only modify sources of H2 and compile its own version with support of the STRIP. But actually you can run into some other issue immediately. When you want to use multiple database systems at once you need to realize that they all are very different from each other. H2 provides compatibility modes for others, but even in these modes there is a very limited compatibility. It means you need to avoid usage of vendor-specific functions and other grammar elements and in some cases different SQL for different systems may be required.


You also can try to create constants B, BOTH, L, LEADING, T, and TRAILING with some values

CREATE CONSTANT B VALUE 1;
CREATE CONSTANT BOTH VALUE 1;
CREATE CONSTANT L VALUE 2;
…

and create a function with three arguments, second argument will be of type int (or other, if you'll decide to choose values of some other data type). But names of constants may conflict with column names, so this workaround is far from being perfect and may not work at all in some queries.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文