Symfony2-自定义DQL函数已注册但不存在


Symfony2 - Custom DQL Function Registered But Does Not Exist

我拼命想在Symfony2中包含LEVENSHTEIN函数,但我仍然收到错误。Specs+到目前为止我所做的:

  • PostgreSQL 9.3
  • 包含在fuzzystrmatch扩展中的LEVENSHTEIN
  • 通过shell执行测试了该函数。效果非常好:

    postgres=# SELECT levenshtein('test', 'text');
     levenshtein
    -------------
               1
    (1 row)
    
  • 增加了DQL:中的功能

    <?php
    namespace AppBundle'DQL;
    use Doctrine'ORM'Query'AST'Functions'FunctionNode;
    use Doctrine'ORM'Query'Lexer;
    use Doctrine'ORM'Query'Parser;
    use Doctrine'ORM'Query'SqlWalker;
    class LevenshteinFunction extends FunctionNode {
        public $firstStringExpression = null;
        public $secondStringExpression = null;
        public function getSql(SqlWalker $sqlWalker) {
            return 'LEVENSHTEIN(' . $this->firstStringExpression->dispatch($sqlWalker) . ', ' . $this->secondStringExpression->dispatch($sqlWalker) . ')';
        }
        public function parse(Parser $parser) {
            // levenshtein(str1, str2)
            $parser->match(Lexer::T_IDENTIFIER);
            $parser->match(Lexer::T_OPEN_PARENTHESIS);
            $this->firstStringExpression = $parser->StringPrimary();
            $parser->match(Lexer::T_COMMA);
            $this->secondStringExpression = $parser->StringPrimary();
            $parser->match(Lexer::T_CLOSE_PARENTHESIS);
        }
    }
    

    配置yml

    orm:
        auto_generate_proxy_classes: "%kernel.debug%"
        auto_mapping: true
        dql:
            numeric_functions:
                LEVENSHTEIN: AppBundle'DQL'LevenshteinFunction
    
  • 问题:在我的存储库中执行以下代码块时,会出现以下错误:

    $this->getEntityManager()->createQuery("SELECT LEVENSHTEIN('test', 'text') FROM AppBundle:User");
    return $query->getResult();
    

    SQLSTATE[44283]:未定义的函数:7错误:函数levenstein(未知,未知)不存在

我错过了什么?为什么DQL/Symfony/PDO/。。。识别功能?非常感谢您的帮助!

错误来自Postgres,似乎是可见性问题。

当然,必须安装附加模块fuzzystrmatch。您显然做到了,否则您的函数调用在psql中也无法工作。

  • 如何在导出中排除PL/pgSQL函数

如果它在psql中有效,但在你的应用程序中无效,那么只剩下一些可能的解释了。显而易见的第一个:

  • 是否连接到同一数据库?(相同的服务器,相同的端口,相同的数据库?)

  • 您正在与同一用户连接?可能而不是。。。

  • 如果与其他用户连接(但无论如何),请检查您是否使用相同的搜索路径。在任一连接中运行并比较:

    SHOW search_path;
    

    详细信息-以及如何设置search_path:

    • search_ path如何影响标识符解析和"搜索路径";当前模式"

请注意,扩展可以安装到您选择的任何模式。默认值是search_path中的第一个模式(安装时的"当前模式",通常是public,但我不知道您的安装。文档:

如果未指定,并且扩展名的控制文件未指定模式,则使用当前默认的对象创建模式。

运行此程序可以诊断以下几件事:

SELECT e.extname AS extension, nsp.nspname AS schema
     , r.rolname AS schema_owner, nsp.nspacl AS schema_acl
FROM   pg_extension e
JOIN   pg_namespace nsp ON nsp.oid = e.extnamespace
JOIN   pg_roles     r   ON r.oid = nsp.nspowner

你会得到这样的东西:

   extension   |   schema   | schema_owner |             schema_acl
---------------+------------+--------------+-------------------------------------
 adminpack     | pg_catalog | postgres     | {postgres=UC/postgres,=U/postgres}
 plpgsql       | pg_catalog | postgres     | {postgres=UC/postgres,=U/postgres}
 fuzzystrmatch | public     | postgres     | {postgres=UC/postgres,=UC/postgres}
 tablefunc     | public     | postgres     | {postgres=UC/postgres,=UC/postgres}
 ...

如果schema_acl包括=U/postgresU表示USAGE),则public角色具有访问权限,即每个人。

相应地为您的连接设置search_path,或者(重新)安装到一个可见的模式,它应该可以工作。

理论上,拥有角色或超级用户可能已经从函数本身吊销了EXECUTE权限。。。

您的函数类在我看来还可以,但您的配置可能是错误的。这就是我的CAST功能:

doctrine:
    orm:
        dql:
            string_functions:
                CAST: App'MyBundle'Doctrine'DBAL'Functions'Porgres'Cast

您应该注意,对于不同类型的函数,即string_functionsnumeric_functionsdatetime_functions,您有不同的集合。所有这些都列在官方文件中。

除此之外,清理缓存后,代码应该可以正常工作。