Solution
Très probablement, la solution est de qualifier schématiquement l'opérateur :
SELECT *
FROM test
WHERE tagged OPERATOR([email protected]>) '{11}'::int2[]
ORDER BY id
LIMIT 100;
Pourquoi ?
C'est un problème de résolution de l'opérateur (en combinaison avec la résolution de type et le contexte de conversion).
Dans Postgres standard, il n'y a qu'un seul opérateur candidat anyarray @> anyarray
, c'est celui que vous voulez.
Votre configuration fonctionnerait très bien si vous n'aviez pas installé le module supplémentaire intarray (mon hypothèse), qui fournit un autre opérateur pour integer[] @> integer[]
.
Par conséquent, une autre solution serait d'utiliser integer[]
à la place et avoir un index GIN avec le gin__int_ops
classe d'opérateur. Ou essayez le (par défaut pour intarray) gist__int_ops
indice. L'un ou l'autre peut être plus rapide, mais les deux n'autorisent pas les valeurs NULL.
Ou vous pouvez renommer le intarray
opérateur @>
pour lever l'ambiguïté. (Je ne ferais pas ça. Des problèmes de mise à niveau et de portabilité s'ensuivent.)
Pour les expressions comportant au moins un opérande de type integer[]
, Postgres sait quel opérateur choisir :l'opérateur intarray. Mais alors l'index n'est pas applicable , car l'opérateur intra-rayon n'opère que sur integer
(int4
) pas int2
. Et les index sont strictement liés aux opérateurs :
- Est-ce que PostgreSQL peut indexer les colonnes d'un tableau ?
- Comportement de PostgreSQL en présence de deux types d'index différents sur la même colonne
Mais pour int2[] @> int2[]
, Postgres est incapable de décider du meilleur opérateur. Les deux semblent également applicables. Puisque l'opérateur par défaut est fourni dans le pg_catalog
schéma et l'opérateur intraray est fourni dans le public
schema (par défaut - ou partout où vous avez installé l'extension), vous pouvez aider à résoudre l'énigme en qualifiant de schéma l'opérateur avec le OPERATOR()
construction. Connexe :
- Comparer les tableaux pour l'égalité, en ignorant l'ordre des éléments
Le message d'erreur que vous obtenez est un peu trompeur. Mais si vous regardez attentivement, il y a un HINT
ligne ajoutée qui indique (tada !) dans la bonne direction :
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.
Vous pouvez rechercher des candidats opérateurs existants pour @>
avec :
SELECT o.oid, *, oprleft::regtype, oprright::regtype, n.nspname
FROM pg_operator o
JOIN pg_namespace n ON n.oid = o.oprnamespace
WHERE oprname = '@>';
Une autre solution alternative serait de définir temporairement (!) un chemin de recherche différent, de sorte que seul l'opérateur souhaité soit trouvé. Dans la même transaction :
SET LOCAL search_path = pg_catalog;
SELECT ...
Mais ensuite, vous devez qualifier de schéma toutes les tables de la requête.
À propos du contexte de diffusion :
- Générer une série de dates - en utilisant le type de date comme entrée
Vous pourriez changer le castcontext
de int2
-> int4
. Mais je le déconseille fortement. Trop d'effets secondaires possibles :
- Existe-t-il un moyen de convertir le type de données postgresql 9.3 afin qu'il n'affecte qu'un seul côté