如何使用 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 开始,所以您可以在不调整方言之间的值的情况下执行此操作。
我正在尝试将以下 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 开始,所以您可以在不调整方言之间的值的情况下执行此操作。