简体   繁体   English

如何使用包含问号“?”的 PostgreSQL JSON(B) 运算符通过 JDBC

[英]How do I use PostgreSQL JSON(B) operators containing a question mark "?" via JDBC

PostgreSQL knows a couple of funky ASCII-art operators that use the question mark character in their names, for instance these JSON operators : PostgreSQL 知道一些时髦的 ASCII 艺术运算符,它们在名称中使用问号字符,例如这些 JSON 运算符

  • ? does the string exist as a top-level key within the JSON value?该字符串是否作为 JSON 值中的顶级键存在?
  • ?| Do any of these array strings exist as top-level keys?这些数组字符串中的任何一个是否作为顶级键存在?
  • ?& Do all of these array strings exist as top-level keys? ?&所有这些数组字符串都作为顶级键存在吗?

The problem is that the official PostgreSQL JDBC driver does not seem to correctly parse SQL strings containing such operators.问题是官方的 PostgreSQL JDBC 驱动程序似乎无法正确解析包含此类运算符的 SQL 字符串。 It assumes that the question mark is an ordinary JDBC bind variable.它假定问号是一个普通的 JDBC 绑定变量。 The following code...下面的代码...

try (PreparedStatement s = c.prepareStatement("select '{}'::jsonb ?| array['a', 'b']");
     ResultSet rs = s.executeQuery()) {
     ...
}

... throws an exception: ...抛出异常:

org.postgresql.util.PSQLException: Für den Parameter 1 wurde kein Wert angegeben.
    at org.postgresql.core.v3.SimpleParameterList.checkAllParametersSet(SimpleParameterList.java:225)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:190)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:424)
    at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:161)
    at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:114)

How can I use this operator?如何使用此运算符?

There are two possible workarounds:有两种可能的解决方法:

Use static statements, instead of prepared statements使用静态语句,而不是准备好的语句

This is the simplest workaround, but you lose all the benefits from prepared statements (performance, SQL injection protection, etc.).这是最简单的解决方法,但您将失去准备好的语句的所有好处(性能、SQL 注入保护等)。 However, this will work但是,这将起作用

try (Statement s = c.createStatement();
     ResultSet rs = s.executeQuery("select '{}'::jsonb ?| array['a', 'b']")) {
     ...
}

Avoid the operator.避开运营商。 Use a function instead (note: indexes might not be used)改用函数(注意:可能不使用索引)

Operators are just syntax sugar for a backing function that exists in the pg_catalog .运算符只是存在于pg_catalog的支持函数的语法糖。 Here's how to find the name of these functions:以下是如何找到这些函数的名称:

SELECT 
  oprname, 
  oprcode || '(' || format_type(oprleft,  NULL::integer) || ', ' 
                 || format_type(oprright, NULL::integer) || ')' AS function
FROM pg_operator 
WHERE oprname = '?|';

The above yields:以上产生:

oprname  function
----------------------------------------------------------------------------------
?|       point_vert(point, point)
?|       lseg_vertical(-, lseg)
?|       line_vertical(-, line)
?|       jsonb_exists_any(jsonb, text[])    <--- this is the one we're looking for
?|       exists_any(hstore, text[])

So, the simplest workaround is to just not use the operator, but the corresponding function instead:因此,最简单的解决方法是不使用运算符,而是使用相应的函数:

try (PreparedStatement s = c.prepareStatement(
         "select jsonb_exists_any('{}'::jsonb, array['a', 'b']");
     ResultSet rs = s.executeQuery()) {
     ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM