如何使用 HQL 将 oracle regexp_substr 转换为 PostgreSQL

How do I convert oracle regexp_substr to PostgreSQL using HQL

我正在尝试将以下 OracleDB HQL where 子句转换为 PosgreSQL。 HQL 使用的是 PosgreSQL 方言。

这两个查询都可以直接在数据库上运行,没有任何问题。

甲骨文数据库:

...
where  
( LPAD(regexp_substr(someTable.someColumn, '\d+', 1,1), 3, ' ') = ' 40' 
AND LPAD(regexp_substr(someTable.someColumn, '\d+', 1,2), 3, ' ') = ' 20');

PosgreSQL:

...
where
( LPAD(( SELECT array_to_string(a, '') from regexp_matches(someTable.someColumn, '\d+', 'g') as a limit 1 offset 0), 3, ' ') = ' 40' 
AND LPAD(( SELECT array_to_string(a, '') from regexp_matches(someTable.someColumn, '\d+', 'g') as a limit 1 offset 1), 3, ' ') = ' 20' );

更改代码后,我在运行时一直出现以下 hql 异常:

java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: 
unexpected token: regexp_matches near line 1

我也注册了下面的函数自定义方言 class 但它也没有用:

public class CustomPostgresqlDialect extends PostgreSQL82Dialect  {

    public CustomPostgresqlDialect() {
    super();
    registerFunction( "regexp_matches", new StandardSQLFunction( "regexp_matches", StandardBasicTypes.STRING ) );
    }   
}

如果我继续使用原始的 regexp_substr 版本,就会出现 PostgreSQL 异常:

org.postgresql.util.PSQLException: ERROR: function regexp_substr(character varying, unknown, integer, integer) does not exist

请建议是否有一种方法可以转换此类查询,以便 HQL 不会无法解析它。 此外,我无法切换到本机查询创建,因为 HQL 生成了很大一部分。

非常感谢

您似乎想从同一个正则表达式中检查多个匹配项。在 Postgres 中,这样做的方法是在正则表达式上使用 g 标志,这样它 returns 你所有的匹配项,而不仅仅是第一个。

我认为不是这个:

LPAD(( SELECT array_to_string(a, '') from regexp_matches(someTable.someColumn, '\d+', 'g') as a limit 1 offset 1)

你可以做到这一点

LPAD(regexp_matches(someTable.someColumn, '\d+', 'g')[1])

对于第一种方法,您必须更改传递给 HQL 函数的索引。另一个问题是 StandardSQLFunction class 不适合这个,因为您的实现太自定义了。您必须实现自己的渲染器。

public class PgRegexMatcher implements SQLFunction {

    public boolean hasArguments() { return true; }
    public boolean hasParenthesesIfNoArguments() { return true; }
    public Type getReturnType(Type firstArgumentType, Mapping mapping) throws QueryException {
        return StandardBasicTypes.STRING;
    }

    public String render(Type firstArgumentType, List arguments, SessionFactoryImplementor factory) throws QueryException {
        StringBuilder sb = new StringBuilder()
        sb.append("regexp_matches(")
          .append(arguments.get(0))
          .append(", '\d+', 'g')[")
          .append(arguments.get(1))
          .append("]");
        return sb.toString();
    }
}

现在在 HQL 中,您可以将它用作 regexp_func(sometable.column1, x)regexp_func 是您注册的任何名称),它会在您的 Postgresql 方言中生成 regexp_matches(sometable.column1, '\d+', 'g')[x],您似乎已经找到适合您的 Oracle 方言的那个。

因为这里的数组索引从 1 开始,所以您可以在不调整方言之间的值的情况下执行此操作。