Solución
Lo más probable es que la solución es calificar el esquema del operador:
SELECT *
FROM test
WHERE tagged OPERATOR([email protected]>) '{11}'::int2[]
ORDER BY id
LIMIT 100;
¿Por qué?
Es un problema de resolución del operador (en combinación con resolución de tipo y contexto de transmisión).
En Postgres estándar, solo hay un único operador candidato anyarray @> anyarray
, ese es el que quieres.
Su configuración funcionaría bien si no hubiera instalado el módulo adicional intarray (mi suposición), que proporciona otro operador para integer[] @> integer[]
.
Por lo tanto, otra solución sería usar integer[]
en su lugar y tener un índice GIN con el gin__int_ops
clase de operador. O pruebe el (predeterminado para intarray) gist__int_ops
índice. Cualquiera de los dos podría ser más rápido, pero ambos no permiten valores NULOS.
O podría cambiar el nombre del intarray
operador @>
para desambiguar. (Yo no haría eso. Se producen problemas de actualización y portabilidad).
Para expresiones que involucran al menos un operando de tipo integer[]
, Postgres sabe qué operador elegir:el operador intraray. Pero entonces el índice no es aplicable , porque el operador intraray solo opera en integer
(int4
) no int2
. Y los índices están estrictamente vinculados a los operadores:
- ¿Puede PostgreSQL indexar columnas de matrices?
- Comportamiento de PostgreSQL en presencia de dos tipos diferentes de índices en la misma columna
Pero para int2[] @> int2[]
, Postgres no puede decidir cuál es el mejor operador. Ambos parecen igualmente aplicables. Dado que el operador predeterminado se proporciona en el pg_catalog
schema y el operador intraray se proporciona en el public
esquema (de forma predeterminada, o donde haya instalado la extensión), puede ayudar a resolver el enigma calificando al operador con el OPERATOR()
construir. Relacionado:
- Compara matrices para la igualdad, ignorando el orden de los elementos
El mensaje de error que recibe es un poco engañoso. Pero si miras de cerca, hay una HINT
línea agregada que sugiere (¡tada!) en la dirección correcta:
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.
Puede investigar los candidatos a operadores existentes para @>
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 = '@>';
Otra solución alternativa sería establecer temporalmente (!) una ruta de búsqueda diferente, de modo que solo se encuentre el operador deseado. En la misma transacción:
SET LOCAL search_path = pg_catalog;
SELECT ...
Pero luego debe calificar con esquema todas las tablas en la consulta.
Acerca del contexto de transmisión:
- Generar series de fechas - usando el tipo de fecha como entrada
podrías cambiar el castcontext
de int2
-> int4
. Pero lo desaconsejo fuertemente. Demasiados posibles efectos secundarios:
- ¿Hay alguna forma de convertir el tipo de datos postgresql 9.3 para que pueda afectar solo a un lado?