Solução
Muito provavelmente, a solução é qualificar o operador pelo esquema:
SELECT *
FROM test
WHERE tagged OPERATOR([email protected]>) '{11}'::int2[]
ORDER BY id
LIMIT 100;
Por quê?
É um problema de resolução do operador (em combinação com resolução de tipo e contexto de conversão).
No Postgres padrão, existe apenas um único operador candidato
anyarray @> anyarray
, esse é o que você quer. Sua configuração funcionaria bem se você não tivesse instalado o módulo adicional intarray (minha suposição), que fornece outro operador para
integer[] @> integer[]
. Portanto, outra solução seria usar
integer[]
em vez disso e ter um índice GIN com o gin__int_ops
classe de operador. Ou tente o (padrão para intarray) gist__int_ops
índice. Qualquer um pode ser mais rápido, mas ambos não permitem valores NULL.Ou você pode renomear o
intarray
operador @>
para desambiguar. (Eu não faria isso. Problemas de atualização e portabilidade ocorrem.) Para expressões envolvendo pelo menos um operando do tipo
integer[]
, o Postgres sabe qual operador escolher:o operador intarray. Mas então o índice não é aplicável , porque o operador intarray opera apenas em integer
(int4
) não int2
. E os índices são estritamente vinculados aos operadores:- O PostgreSQL pode indexar colunas de array?
- Comportamento do PostgreSQL na presença de dois tipos diferentes de índices na mesma coluna
Mas para
int2[] @> int2[]
, o Postgres não consegue decidir o melhor operador. Ambos parecem igualmente aplicáveis. Como o operador padrão é fornecido no pg_catalog
esquema e o operador intarray é fornecido no public
esquema (por padrão - ou onde quer que você instalou a extensão), você pode ajudar a resolver o enigma qualificando o operador pelo esquema com o OPERATOR()
construir. Relacionado:- Compare arrays para igualdade, ignorando a ordem dos elementos
A mensagem de erro que você recebe é um pouco enganosa. Mas se você olhar de perto, há uma
HINT
linha adicionada que sugere (tada!) na direção certa: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.
Você pode investigar candidatos a operadores existentes para
@>
com:SELECT o.oid, *, oprleft::regtype, oprright::regtype, n.nspname
FROM pg_operator o
JOIN pg_namespace n ON n.oid = o.oprnamespace
WHERE oprname = '@>';
Outra solução alternativa seria definir temporariamente(!) um search_path diferente, para que apenas o operador desejado seja encontrado. Na mesma transação:
SET LOCAL search_path = pg_catalog;
SELECT ...
Mas então você precisa qualificar pelo esquema todas as tabelas na consulta.
Sobre o contexto do elenco:
- Gerar séries de datas - usando o tipo de data como entrada
Você poderia altere o
castcontext
de int2
-> int4
. Mas eu aconselho fortemente contra isso. Muitos efeitos colaterais possíveis:- Existe alguma maneira de converter o tipo de dados postgresql 9.3 para que ele possa afetar apenas um lado