'无效的架构名称' Doctrine抛出的错误,但原始SQL似乎有效

时间:2017-08-02 12:40:37

标签: doctrine-orm dql postgresql-9.5 doctrine-query

我使用一些自定义DQL函数来过滤PostgreSQL中的一些JSONB字段的行。这是我的查询功能:

private function findTopLevelResources(): array {
    return $this->createQueryBuilder('r')
        ->where("JSON_EXISTS(r.contents, '-1') = FALSE")
        ->getQuery()
        ->getResult();
}

运行此代码会产生DriverException的{​​{1}}:

AbstractPostgreSQLDriver

我尝试从PHPStorm手动执行原始SQL查询,但它没有错误。

如何在Doctrine中使用它?

为什么这个查询不能与Doctrine一起使用,但是当我手动测试时呢?

此处An exception occurred while executing 'SELECT r0_.id AS id_0, r0_.marking AS marking_1, r0_.contents AS contents_2, r0_.kind_id AS kind_id_3 FROM resource r0_ WHERE r0_.contents?'-1' = false': SQLSTATE[3F000]: Invalid schema name: 7 ERROR: schema "r0_" does not exist LINE 1: ... r0_.kind_id AS kind_id_3 FROM resource r0_ WHERE r0_.conten... ^ :(基于syslogic/doctrine-json-functions

JSON_EXISTS

通过Symfony的YAML配置注册如下:

class JsonExists extends FunctionNode
{
    const FUNCTION_NAME = 'JSON_EXISTS';
    const OPERATOR = '?';

    public $jsonData;
    public $jsonPath;

    public function getSql(SqlWalker $sqlWalker)
    {
        $jsonData = $sqlWalker->walkStringPrimary($this->jsonData);
        $jsonPath = $this->jsonPath->value;
        return $jsonData . self::OPERATOR . "'$jsonPath'";
    }

    public function parse(Parser $parser)
    {
        $parser->match(Lexer::T_IDENTIFIER);
        $parser->match(Lexer::T_OPEN_PARENTHESIS);

        $this->jsonData = $parser->StringPrimary();

        $parser->match(Lexer::T_COMMA);

        $this->jsonPath = $parser->StringPrimary();

        $parser->match(Lexer::T_CLOSE_PARENTHESIS);
    }
}

东西的版本:

  • PHP 7.1.1
  • doctrine / dbal v2.6.1
  • doctrine / orm dev-master e3ecec3(== 2.6.x-dev)
  • symfony / symfony v3.3.4

1 个答案:

答案 0 :(得分:1)

错误消息是错误的线索。

实际问题是由PDO引起的(这就是为什么它可以从PHPStorm运行)。当它看到这样的查询时:

SELECT * FROM foo WHERE contents?'bar'

它将其视为参数化查询,并将问号?视为参数。由于某种原因,它有时会导致无意义的错误消息。这个特定情况可以通过在问号后面添加一个空格来解决,但对于中间没有空格的运算符?|?&不起作用。

解决方案是使用与运算符(this question saved the day)对应的函数。人们可以通过这样的查询找出它们的调用方式:

SELECT oprname, oprcode FROM pg_operator WHERE oprname IN ('?', '?|', '?&')

以下是与JSON相关的结果部分:

  • ?jsonb_exists
  • ?|jsonb_exists_any
  • ?&jsonb_exists_all

因此,不是通过PDO导致问题的先前查询,而是可以使用这个等效的:

SELECT * FROM foo WHERE jsonb_exists(contents, 'bar')