带有参数化查询的 jsonb 存在运算符

jsonb existential operators with parameterised queries

...或问号问题。

我目前正在 php 中实现 postgres 数据库的搜索功能,它使用新的 jsonb 类型。

为了实现这一点,我正在执行带有命名占位符的准备好的语句。

然而,在尝试使用一些新的 postgres JSON containment and existence operators 以及命名占位符时,我遇到了一个有趣的问题 运行。

问题的基础是运算符本身使用问号 ? 作为其语法的一部分。即

? key/element 字符串是否存在于 JSON 值中?

?| 这些 key/element 字符串是否存在?

?& 这些 key/element 字符串都存在吗?

这意味着我在 PHP 中有这样的语句。

$sth = $dbh->prepare("SELECT * FROM stuff WHERE meta ? :value");
$sth->bindValue(1, $value, PDO::PARAM_STR);
$sth->execute();

这失败了,因为问号被解释为占位符。 为了解决这个问题,我尝试让运算符本身成为一个命名参数。

$sth = $dbh->prepare("SELECT * FROM stuff WHERE meta :operator :value");
$sth->bindValue(1, $operator, PDO::PARAM_STR);
$sth->bindValue(2, $value, PDO::PARAM_STR);
$sth->execute();

然而,这只会抛出与使用裸运算符相同的错误,即

ERROR: syntax error at or near \"\"1

有没有其他人遇到过这个问题或者有没有人能想到一个好的解决方法?

有没有办法转义或传递问号,以便可以将 postgres jsonb 包含和存在运算符与 PDO 参数化查询一起使用?

您可以使用相应的函数代替运算符(jsonb_exists、jsonb_exists_any、jsonb_exists_all)。例如 运行 \do+ "?" 在 psql 中查看函数名称 ?运算符。

或定义您自己的不带“?”的运算符符号代替。

例如:

CREATE OPERATOR ~@ (LEFTARG = jsonb, RIGHTARG = text, PROCEDURE = jsonb_exists)    
CREATE OPERATOR ~@| (LEFTARG = jsonb, RIGHTARG = text[], PROCEDURE = jsonb_exists_any)
CREATE OPERATOR ~@& (LEFTARG = jsonb, RIGHTARG = text[], PROCEDURE = jsonb_exists_all)  

这样就可以用~@~@|~@&分别代替??|?&。例如

$sth = $dbh->prepare("SELECT * FROM stuff WHERE meta ~@ :value");
$sth->bindValue(1, $value, PDO::PARAM_STR);
$sth->execute();