Řešení
S největší pravděpodobností řešení je kvalifikovat operátor schématu:
SELECT *
FROM test
WHERE tagged OPERATOR([email protected]>) '{11}'::int2[]
ORDER BY id
LIMIT 100;
Proč?
Je to problém rozlišení operátora (v kombinaci s rozlišením typu a kontextem obsazení).
Ve standardním Postgresu existuje pouze jeden kandidátský operátor anyarray @> anyarray
, to je ten, který chcete.
Vaše nastavení by fungovalo dobře, pokud byste nenainstalovali přídavný modul intarray (můj předpoklad), který poskytuje další operátor pro integer[] @> integer[]
.
Dalším řešením by tedy bylo použití integer[]
místo toho a mít index GIN s gin__int_ops
třída operátorů. Nebo zkuste (výchozí pro intarray) gist__int_ops
index. Obě mohou být rychlejší, ale obě neumožňují hodnoty NULL.
Nebo můžete přejmenovat intarray
operátor @>
vyjasnit. (To bych neudělal. Následují problémy s upgradem a přenositelností.)
Pro výrazy obsahující alespoň jeden operand typu integer[]
, Postgres ví, který operátor vybrat:operátor intraray. Pak ale index nelze použít , protože operátor intarray pracuje pouze s integer
(int4
) ne int2
. A indexy jsou přísně vázány na operátory:
- Může PostgreSQL indexovat sloupce pole?
- Chování PostgreSQL v přítomnosti dvou různých typů indexů ve stejném sloupci
Ale pro int2[] @> int2[]
, Postgres není schopen rozhodnout o nejlepším operátorovi. Oba se zdají být stejně použitelné. Protože výchozí operátor je uveden v pg_catalog
schéma a operátor intarray jsou uvedeny v public
schéma (ve výchozím nastavení – nebo kdekoli, kam jste rozšíření nainstalovali), můžete vyřešit hlavolam tím, že operátor kvalifikujete podle schématu pomocí OPERATOR()
postavit. Související:
- Porovnejte pole pro rovnost, ignorujte pořadí prvků
Chybová zpráva, kterou dostanete, je trochu zavádějící. Ale když se podíváte pozorně, je tu HINT
přidán řádek, který naznačuje (tada!) správným směrem:
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.
Můžete prozkoumat stávající kandidáty na operátory pro @>
s:
SELECT o.oid, *, oprleft::regtype, oprright::regtype, n.nspname
FROM pg_operator o
JOIN pg_namespace n ON n.oid = o.oprnamespace
WHERE oprname = '@>';
Dalším alternativním řešením by bylo dočasně(!) nastavit jinou cestu hledání, aby byl nalezen pouze požadovaný operátor. Ve stejné transakci:
SET LOCAL search_path = pg_catalog;
SELECT ...
Pak ale musíte kvalifikovat všechny tabulky v dotazu podle schématu.
O kontextu cast:
- Generujte řadu dat – jako vstup použijte typ data
Mohli byste změnit castcontext
z int2
-> int4
. Ale důrazně to nedoporučuji. Příliš mnoho možných vedlejších účinků:
- Existuje nějaký způsob, jak přenést datový typ postgresql 9.3 tak, aby to mohlo ovlivnit pouze jednu stranu?