Løsning
Sandsynligvis løsningen er at skemakvalificere operatøren:
SELECT *
FROM test
WHERE tagged OPERATOR([email protected]>) '{11}'::int2[]
ORDER BY id
LIMIT 100;
Hvorfor?
Det er et problem med operatøropløsning (i kombination med typeopløsning og cast-kontekst).
I standard Postgres er der kun en enkelt kandidatoperator anyarray @> anyarray
, det er den, du vil have.
Din opsætning ville fungere fint, hvis du ikke havde installeret det ekstra modul intarray (min antagelse), som giver en anden operator for integer[] @> integer[]
.
Derfor ville en anden løsning være at bruge integer[]
i stedet og have et GIN-indeks med gin__int_ops
operatørklasse. Eller prøv (standard for intarray) gist__int_ops
indeks. Begge kan være hurtigere, men begge tillader ikke NULL-værdier.
Eller du kan omdøbe intarray
operatør @>
at tvetydige. (Det ville jeg ikke gøre. Problemer med opgradering og portabilitet opstår.)
For udtryk, der involverer mindst én operand af typen integer[]
, Postgres ved, hvilken operatør der skal vælges:Intarray-operatoren. Men så er indekset ikke anvendeligt , fordi intarray-operatoren kun fungerer på integer
(int4
) ikke int2
. Og indekser er strengt bundet til operatører:
- Kan PostgreSQL indeksere array-kolonner?
- PostgreSQL-adfærd ved tilstedeværelse af to forskellige typer indekser i samme kolonne
Men for int2[] @> int2[]
, Postgres er ikke i stand til at bestemme den bedste operatør. Begge virker lige anvendelige. Da standardoperatøren er angivet i pg_catalog
skemaet og intarray-operatoren findes i public
skema (som standard - eller hvor end du har installeret udvidelsen), kan du hjælpe med at løse gåden ved at skemakvalificere operatøren med OPERATOR()
konstruere. Relateret:
- Sammenlign arrays for lighed, ignorer rækkefølgen af elementer
Den fejlmeddelelse du får er en smule misvisende. Men hvis du ser godt efter, er der et HINT
linje tilføjet, som antyder (tada!) i den rigtige retning:
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.
Du kan undersøge eksisterende operatørkandidater for @>
med:
SELECT o.oid, *, oprleft::regtype, oprright::regtype, n.nspname
FROM pg_operator o
JOIN pg_namespace n ON n.oid = o.oprnamespace
WHERE oprname = '@>';
En anden alternativ løsning ville være midlertidigt(!) at indstille en anden søgesti, så kun den ønskede operator findes. I samme transaktion:
SET LOCAL search_path = pg_catalog;
SELECT ...
Men så skal du skema-kvalificere alle tabeller i forespørgslen.
Om rollebesætningskontekst:
- Generer serier af datoer - brug datotype som input
Du kunne ændre castcontext
af int2
-> int4
. Men jeg fraråder det kraftigt. For mange mulige bivirkninger:
- Er der nogen måde at caste postgresql 9.3 datatype, så den kun kan påvirke den ene side