自定义Doctrine DQL函数,问号被转换为参数

时间:2015-06-25 16:19:10

标签: doctrine dql

我正在使用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'

最重要的是,只有一般程序是相同的,但具体答案是不同的(你需要使用不同的功能)

2 个答案:

答案 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库。