PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Indice GIN sulla colonna smallint[] non utilizzato o l'operatore di errore non è univoco

Soluzione

Molto probabilmente, la soluzione consiste nel qualificare lo schema dell'operatore:

SELECT *
FROM   test
WHERE  tagged OPERATOR([email protected]>) '{11}'::int2[]
ORDER  BY id
LIMIT  100;

Perché?

È un problema di risoluzione dell'operatore (in combinazione con la risoluzione del tipo e il contesto del cast).

In Postgres standard, esiste un solo operatore candidato anyarray @> anyarray , è quello che vuoi.

La tua configurazione funzionerebbe perfettamente se non avessi installato intarray modulo aggiuntivo (la mia ipotesi), che fornisce un altro operatore per integer[] @> integer[] .

Quindi, un'altra soluzione sarebbe usare integer[] invece e avere un indice GIN con gin__int_ops classe operatore. Oppure prova il (predefinito per intarray) gist__int_ops indice. Entrambi potrebbero essere più veloci, ma entrambi non consentono valori NULL.
Oppure potresti rinominare l'intarray operatore @> disambiguare. (Non lo farei. Ne derivano problemi di aggiornamento e portabilità.)

Per le espressioni che coinvolgono almeno un operando di tipo integer[] , Postgres sa quale operatore scegliere:l'operatore intraray. Ma allora l'indice non è applicabile , perché l'operatore intarray opera solo su integer (int4 ) non int2 . E gli indici sono strettamente legati agli operatori:

  • PostgreSQL può indicizzare le colonne dell'array?
  • Comportamento di PostgreSQL in presenza di due diversi tipi di indici sulla stessa colonna

Ma per int2[] @> int2[] , Postgres non è in grado di decidere il miglior operatore. Entrambi sembrano ugualmente applicabili. Poiché l'operatore predefinito è fornito nel pg_catalog schema e l'operatore intraray è fornito in public schema (per impostazione predefinita - o ovunque tu abbia installato l'estensione), puoi aiutare a risolvere l'enigma qualificando lo schema dell'operatore con OPERATOR() costruire. Correlati:

  • Confronta gli array per l'uguaglianza, ignorando l'ordine degli elementi

Il messaggio di errore che ricevi è un po' fuorviante. Ma se guardi da vicino, c'è un HINT riga aggiunta che indica (tada!) nella giusta direzione:

ERROR:  operator is not unique: smallint[] @> smallint[]
LINE 1: SELECT NULL::int2[] @> NULL::int2[]
                            ^
HINT:  Could not choose a best candidate operator. You might need to add explicit type casts.

Puoi esaminare gli operatori candidati esistenti per @> con:

SELECT o.oid, *, oprleft::regtype, oprright::regtype, n.nspname
FROM   pg_operator o
JOIN   pg_namespace n ON n.oid = o.oprnamespace
WHERE  oprname = '@>';

Un'altra soluzione alternativa sarebbe quella di impostare temporaneamente(!) un percorso_ricerca diverso, in modo che venga trovato solo l'operatore desiderato. Nella stessa transazione:

SET LOCAL search_path = pg_catalog;
SELECT ...

Ma poi devi qualificare per schema tutte le tabelle nella query.

Informazioni sul contesto del cast:

  • Genera serie di date - utilizzando il tipo di data come input

Potresti cambia il castcontext di int2 -> int4 . Ma lo sconsiglio vivamente. Troppi possibili effetti collaterali:

  • C'è un modo per eseguire il cast del tipo di dati postgresql 9.3 in modo che possa interessare solo un lato