Soluzione
Molto probabilmente, la soluzione consiste nel qualificare lo schema dell'operatore:
SELECT *
FROM test
WHERE tagged OPERATOR(example@sqldat.com>) '{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