我正在使用Symfony 2.6和Doctrine 2.5,我正在尝试使用自定义DQL函数来实现“?” Postgres运算符(用于确定Postgres中jsonb字段内是否存在具有某个键的元素)http://www.postgresql.org/docs/9.4/static/functions-json.html
这是代码(从https://github.com/boldtrn/JsonbBundle的DQL代码复制,我刚刚更改了问号)
class HasElement extends FunctionNode
{
public $leftHandSide = null;
public $rightHandSide = null;
public function parse(\Doctrine\ORM\Query\Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->leftHandSide = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_COMMA);
$this->rightHandSide = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
{
return '(' .
$this->leftHandSide->dispatch($sqlWalker) . " ? " .
$this->rightHandSide->dispatch($sqlWalker) .
')';
}
}
但问号在创建查询时被视为参数占位符,我得到一个语法错误,在查询中,在设置参数之前它被$ 2替换。
SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "$2"
LINE 1: ...id = r1_.id WHERE r0_.file_id = $1 AND (r0_.attrs $2 $3)
查询应该是“(r0_attrs?$ 1)”
有没有办法在DQL中使用问号而不将其视为参数?我试过转义并用unicode序列替换但是没有用
编辑:虽然这个问题的答案与标记为重复的(使用函数而不是别名运算符)相同,但错误是不同的。 Doctrine的解析是在PDO参数赋值之前进行的,如果不是这样的话我将会得到这个错误:
PDOException: SQLSTATE[HY093]: Invalid parameter number: no parameters were bound: SELECT * FROM tbl WHERE hst ? 'foo'
最重要的是,只有一般程序是相同的,但具体答案是不同的(你需要使用不同的功能)
答案 0 :(得分:1)
我一直在寻找解决方案/替代方案,我发现?
是函数jsonb_exists(column_name, key)
的别名,这是我将在我的自定义DQL函数中使用的。
同样的事情适用于?|
和?&
所以课程就变成了这个
class JsonbExistence extends FunctionNode
{
public $leftHandSide = null;
public $rightHandSide = null;
public function parse(\Doctrine\ORM\Query\Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->leftHandSide = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_COMMA);
$this->rightHandSide = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
{
// We use a workaround to allow this statement in a WHERE. Doctrine relies on the existence of an ComparisonOperator
return 'jsonb_exists(' .
$this->leftHandSide->dispatch($sqlWalker) .', '.
$this->rightHandSide->dispatch($sqlWalker) .
')';
}
}
答案 1 :(得分:1)
这不是一个学说/ symfony问题,而是与PDO有关。
您可以查看How to prevent PDO from interpreting a question mark as a placeholder?
主要尝试使用相同的运算符但使用PHP PDO库。