2017-08-02 57 views
0

我使用一些自定義的DQL函數來過濾PostgreSQL中的一些JSONB字段的行。這是我的查詢功能:原理拋出的'無效的模式名'錯誤,但原始的SQL似乎工作

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

運行在DriverException這段代碼的結果,從AbstractPostgreSQLDriver

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... 
                  ^

我試圖從PHPStorm手動執行的原始SQL查詢和它的工作,沒有錯誤。

我該如何得到它在Doctrine中工作?

爲什麼這個查詢不能使用Doctrine,但是當我手動測試時呢?


下面是JSON_EXISTS(基於syslogic/doctrine-json-functions

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); 
    } 
} 

通過的Symfony的YAML配置註冊這樣的:

doctrine: 
    orm: 
    dql: 
     numeric_functions: 
     json_exists: Syslogic\DoctrineJsonFunctions\Query\AST\Functions\Postgresql\JsonExists 

的東西版本:

  • PHP 7.1.1
  • 教義/ DBAL V2.6.1
  • 教義/ ORM DEV-主e3ecec3(== 2.6.x的-DEV)
  • 的symfony/symfony的v3.3.4

回答

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') 
相關問題