2015-05-26 16 views
12

... o la domanda del punto interrogativo.jsonb operatori esistenziali con query parametrizzate

Attualmente sto implementando la funzionalità di ricerca per un database postgres, in php, che utilizza il nuovo tipo jsonb.

Per raggiungere questo obiettivo eseguo dichiarazioni preparate con segnaposti denominati.

Tuttavia ho incontrato un problema interessante pur cercando di utilizzare alcune delle nuove postgres JSON containment and existence operators insieme con i segnaposto con nome.

La base del problema è che gli stessi operatori utilizzano il punto interrogativo ? come parte della loro sintassi. vale a dire

? Ha la stringa chiave/elemento esiste all'interno del valore JSON?

?| fare nessuna di queste stringhe chiave/elemento non esiste?

?& fare tutte queste stringhe chiave/elemento non esiste?

Ciò significa che ho istruzioni simili a questo in PHP.

Ciò non riesce perché il punto interrogativo viene interpretato come segnaposto. Per ovviare a questo ho cercato di rendere l'operatore stesso un parametro chiamato così.

$sth = $dbh->prepare("SELECT * FROM stuff WHERE meta :operator :value"); 
$sth->bindValue(1, $operator, PDO::PARAM_STR); 
$sth->bindValue(2, $value, PDO::PARAM_STR); 
$sth->execute(); 

Tuttavia, questo getta solo lo stesso errore utilizzando l'operatore nuda, cioè

ERROR: syntax error at or near \"$1\"1

Qualcun altro ha incontrato questo problema o chiunque può pensare ad una buona soluzione?

C'è un modo per sfuggire o passare il punto di domanda in modo che si può usare postgres jsonb operatori di contenimento e di esistenza con query con parametri DOP?

risposta

18

è possibile utilizzare le funzioni corrispondenti al posto di operatori (jsonb_exists, jsonb_exists_any, jsonb_exists_all). per esempio eseguire \do+ "?" in psql per vedere il nome della funzione di? operatore.

o definire il proprio operatore senza "?" simbolo invece.

Ad esempio:

CREATE OPERATOR [email protected] (LEFTARG = jsonb, RIGHTARG = text, PROCEDURE = jsonb_exists)  
CREATE OPERATOR [email protected]| (LEFTARG = jsonb, RIGHTARG = text[], PROCEDURE = jsonb_exists_any) 
CREATE OPERATOR [email protected]& (LEFTARG = jsonb, RIGHTARG = text[], PROCEDURE = jsonb_exists_all) 

In modo che si può usare, rispettivamente [email protected], [email protected]| e [email protected]& al posto di ?, ?| e ?&. per esempio.

$sth = $dbh->prepare("SELECT * FROM stuff WHERE meta [email protected] :value"); 
$sth->bindValue(1, $value, PDO::PARAM_STR); 
$sth->execute(); 
+0

Ha! Davvero non ci avevo ancora pensato, proveremo subito, molte grazie! – Fraser

+0

Brillante, la definizione dell'operatore è una soluzione ideale in quanto significa che posso utilizzare la stessa struttura senza dover gestire alcuna chiamata di funzione. Lo apprezzo davvero, mi ha graffiato la testa per un bel po 'di ore a pensarci dal PDO piuttosto che alla fine del db. Ancora una volta, molte grazie. – Fraser

+0

Nota.Nella documentazione non ci sono funzioni come jsonb_exists, jsonb_exists_any, jsonb_exists_all ma in realtà funzionano come jsonb_exists (jsonb, text) – Swayok