Lösning
Mest troligt är lösningen är att schemakvalificera operatören:
SELECT *
FROM test
WHERE tagged OPERATOR([email protected]>) '{11}'::int2[]
ORDER BY id
LIMIT 100;
Varför?
Det är ett problem med operatörsupplösning (i kombination med typupplösning och castkontext).
I standard Postgres finns det bara en enda kandidatoperator anyarray @> anyarray
, det är den du vill ha.
Din installation skulle fungera bra om du inte hade installerat extra modul intarray (mitt antagande), som tillhandahåller en annan operator för integer[] @> integer[]
.
Därför skulle en annan lösning vara att använda integer[]
istället och ha ett GIN-index med gin__int_ops
operatörsklass. Eller prova (standard för intarray) gist__int_ops
index. Båda kan vara snabbare, men båda tillåter inte NULL-värden.
Eller så kan du byta namn på intarray
operator @>
att disambiguera. (Jag skulle inte göra det. Uppgraderings- och portabilitetsproblem uppstår.)
För uttryck som involverar minst en operand av typen integer[]
, Postgres vet vilken operatör som ska väljas:intarray-operatorn. Men då är indexet inte tillämpligt , eftersom intarray-operatorn bara fungerar på integer
(int4
) inte int2
. Och index är strikt bundna till operatörer:
- Kan PostgreSQL indexera arraykolumner?
- PostgreSQL-beteende i närvaro av två olika typer av index i samma kolumn
Men för int2[] @> int2[]
, Postgres kan inte bestämma den bästa operatören. Båda verkar lika tillämpliga. Eftersom standardoperatorn finns i pg_catalog
schemat och intarray-operatorn tillhandahålls i public
schema (som standard - eller var du än installerade tillägget), kan du hjälpa till att lösa gåtan genom att schemakvalificera operatören med OPERATOR()
konstruera. Relaterat:
- Jämför matriser för likhet, ignorera ordningen på elementen
Felmeddelandet du får är lite missvisande. Men om du tittar noga så finns det ett HINT
rad tillagd som antyder (tada!) i rätt riktning:
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öka befintliga operatörskandidater för @>
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 annan alternativ lösning skulle vara att tillfälligt(!) ställa in en annan sökväg, så att endast den önskade operatorn hittas. I samma transaktion:
SET LOCAL search_path = pg_catalog;
SELECT ...
Men då måste du schemakvalificera alla tabeller i frågan.
Om medverkande sammanhang:
- Generera serier av datum - använd datumtyp som indata
Du kunde ändra castcontext
av int2
-> int4
. Men jag avråder starkt från det. För många möjliga biverkningar:
- Finns det något sätt att casta postgresql 9.3 datatyp så att den bara kan påverka en sida