2015-11-18 14 views
5

Sto cercando disperatamente di includere la funzione LEVENSHTEIN in Symfony2, tuttavia, continuo a ricevere errori. Spec + quello che ho fatto finora:Symfony2 - Funzione DQL personalizzata registrata ma non esiste

  • PostgreSQL 9.3
  • Levenshtein compresi nel fuzzystrmatch estensione
  • Testato la funzione tramite l'esecuzione di shell. Funziona perfettamente bene:

    postgres=# SELECT levenshtein('test', 'text'); 
    levenshtein 
    ------------- 
          1 
    (1 row) 
    
  • Aggiunta la funzione in 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); 
        } 
    } 
    

    config.yml

    orm: 
        auto_generate_proxy_classes: "%kernel.debug%" 
        auto_mapping: true 
        dql: 
         numeric_functions: 
          LEVENSHTEIN: AppBundle\DQL\LevenshteinFunction 
    
  • Problema: Quando si esegue il seguente codeblock nel mio Repository , si verificano i seguenti errori:

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

    SQLSTATE[42883]: Undefined function: 7 ERROR: function levenshtein(unknown, unknown) does not exist

Che cosa mi manca? Perché DQL/Symfony/PDO/... non riconosce la funzione? Qualsiasi aiuto è molto apprezzato!

risposta

1

L'errore deriva da Postgres, sembra un problema con la visibilità.

Il modulo aggiuntivo fuzzystrmatch deve essere installato, ovviamente. Ovviamente lo hai fatto, o la tua chiamata di funzione non funzionerebbe neanche in psql.

Se funziona in psql, ma non nella vostra applicazione, solo poche spiegazioni possibili rimangono. L'ovvio prima:

  • È sono collegati alla stessa base di dati? (Stesso server, stessa porta, stesso db?)

  • Stai effettuando la connessione con lo stesso utente? Probabilmente non ...

  • Se ci si collega con un utente diverso (ma in ogni caso), verificare se si sta lavorando sullo stesso percorso di ricerca. Eseguire in entrambe le connessione e confrontare:

    SHOW search_path; 
    

    Dettagli - e come impostare la search_path:

Essere consapevoli del fatto che le estensioni possono essere installate a qualsiasi schema di la tua scelta. Il valore predefinito è il primo schema nel search_path (il "schema corrente" al momento dell'installazione, che in genere è public, ma non so che circa l'installazione La documentazione:.

If not specified, and the extension's control file does not specify a schema either, the current default object creation schema is used.

Run questo la diagnosi di un paio di cose:

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 

si ottiene qualcosa di simile:

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

Se schema_acl include =U/postgres (U for USAGE), quindi il ruolo public ha accesso, ad esempio tutti.

Impostare il search_path per la connessione di conseguenza o (ri) installare in uno schema visibile e dovrebbe funzionare.

Teoricamente, il ruolo proprietaria o un superutente potrebbe aver revocato il permesso EXECUTE dalla funzione stessa ...

1

La classe di funzione mi sembra soddisfacente, ma la configurazione potrebbe essere errata. Questo è quello che ho per la mia funzione CAST:

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

Si dovrebbe notare che si hanno diverse collezioni per i diversi tipi di funzioni cioè string_functions, numeric_functions, datetime_functions. Tutti loro sono elencati nel documentation ufficiale.

Oltre a ciò, il codice dovrebbe funzionare correttamente dopo aver pulito la cache.

Problemi correlati