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