10.2. Operadores

PostgreSQL 14.5: Operadores

O operador específico a ser usado na chamada de operador é determinado pelo procedimento mostrado abaixo. Deve ser observado que este procedimento é afetado indiretamente pela precedência dos operadores envolvidos. Consulte a Seção 4.1.6 para obter informações adicionais.

Resolução do tipo em operando

  1. Selecionar no catálogo do sistema pg_operator os operadores a serem considerados. Se for utilizado um nome de operador não qualificado (o caso usual), os operadores a serem considerados são aqueles com nome e número de argumentos corretos, visíveis no caminho de procura corrente (consulte a Seção 5.8.3). Se for utilizado um nome de operador qualificado, somente serão considerados os operadores no esquema especificado.

    1. Se forem encontrados no caminho de procura vários operadores com argumentos do mesmo tipo, somente é considerado aquele que aparece primeiro no caminho. Porém, os operadores com argumentos de tipos diferentes são considerados em pé de igualdade, não importando a posição no caminho de procura.

  2. Verificar se algum operador aceita exatamente os mesmos tipos de dado dos argumentos da entrada. Caso exista (só pode haver uma correspondência exata no conjunto de operadores considerados), este é usado.

    1. Se um dos argumentos da chamada do operador binário for do tipo unknown (desconhecido), então assumir que seja do mesmo tipo do outro argumento nesta verificação. Outros casos envolvendo o tipo unknown nunca encontram correspondência nesta etapa.

  3. Procurar pela melhor correspondência.

    1. Desconsiderar os operadores candidatos para os quais os tipos da entrada não correspondem, e não podem ser convertidos (utilizando uma conversão implícita) para corresponder. Para esta finalidade é assumido que os literais do tipo unknown podem ser convertidos em qualquer tipo. Se permanecer apenas um operador candidato, então este é usado; senão continuar na próxima etapa.

    2. Examinar todos os operadores candidatos, e manter aqueles com mais correspondências exatas com os tipos da entrada (Os domínios são considerados idênticos aos seus tipos base para esta finalidade). Manter todos os candidatos se nenhum possuir alguma correspondência exata. Se apenas um candidato permanecer, este é usado; senão continuar na próxima etapa.

    3. Examinar todos os operadores candidatos, e manter aqueles que aceitam os tipos preferidos (da categoria de tipo do tipo de dado da entrada) em mais posições onde a conversão de tipo será necessária. Manter todos os candidatos se nenhum aceitar os tipos preferidos. Se permanecer apenas um operador candidato, este será usado; senão continuar na próxima etapa.

    4. Se algum dos argumentos de entrada for do tipo "unknown", verificar as categorias de tipo aceitas nesta posição do argumento pelos candidatos remanescentes. Em cada posição, selecionar a categoria string se qualquer um dos candidatos aceitar esta categoria (este favorecimento em relação à cadeia de caracteres é apropriado, porque um literal de tipo desconhecido se parece com uma cadeia de caracteres). Senão, se todos os candidatos remanescentes aceitarem a mesma categoria de tipo, selecionar esta categoria; senão falhar, porque a escolha correta não pode ser deduzida sem informações adicionais. Agora, rejeitar os operadores candidatos que não aceitam a categoria de tipo selecionada; além disso, se algum operador candidato aceitar o tipo preferido em uma determinada posição do argumento, rejeitar os candidatos que aceitam tipos não preferidos para este argumento.

    5. Se permanecer apenas um operador candidato, este será usado; Se não permanecer nenhum candidato, ou permanecer mais de um candidato, então falhar.

Seguem alguns exemplos.

Exemplo 10-1. Resolução do tipo em operador de exponenciação

Existe apenas um operador de exponenciação definido no catálogo, e recebe argumentos do tipo double precision. O rastreador atribui o tipo inicial integer aos os dois argumentos desta expressão de consulta:

=> SELECT 2 ^ 3 AS "exp";

 exp
-----
   8
(1 linha)

Portanto, o analisador faz uma conversão de tipo nos dois operandos e a consulta fica equivalente a

=> SELECT CAST(2 AS double precision) ^ CAST(3 AS double precision) AS "exp";

Exemplo 10-2. Resolução do tipo em operador de concatenação de cadeia de caracteres

Uma sintaxe estilo cadeia de caracteres é utilizada para trabalhar com tipos cadeias de caracteres, assim como para trabalhar com tipos de extensão complexa. Cadeias de caracteres de tipo não especificado se correspondem com praticamente todos os operadores candidatos.

Um exemplo com um argumento não especificado:

=> SELECT text 'abc' || 'def' AS "texto e desconhecido";

 texto e desconhecido
----------------------
 abcdef
(1 linha)

Neste caso o analisador procura pela existência de algum operador recebendo o tipo text nos dois argumentos. Uma vez que existe, assume que o segundo argumento deve ser interpretado como sendo do tipo text.

Concatenação de tipos não especificados:

=> SELECT 'abc' || 'def' AS "não especificado";

 não especificado
------------------
 abcdef
(1 linha)

Neste caso não existe nenhuma pista inicial do tipo a ser usado, porque não foi especificado nenhum tipo na consulta. Portanto, o analisador procura todos os operadores candidatos, e descobre que existem candidatos aceitando tanto cadeia de caracteres quanto cadeia de bits como entrada. Como a categoria cadeia de caracteres é a preferida quando está disponível, esta categoria é selecionada e, depois, é usado o tipo preferido para cadeia de caracteres, text, como o tipo específico para solucionar os literais de tipo desconhecido.

Exemplo 10-3. Resolução do tipo em operador de valor absoluto e negação

O catálogo de operadores do PostgreSQL possui várias entradas para o operador de prefixo @, todas implementando operações de valor absoluto para vários tipos de dado numéricos. Uma destas entradas é para o tipo float8, que é o tipo preferido da categoria numérica. Portanto, o PostgreSQL usa esta entrada quando na presença de uma entrada não numérica:

=> SELECT @ '-4.5' AS "abs";

 abs
-----
 4.5
(1 linha)

Aqui o sistema realiza uma conversão implícita de text para float8 antes de aplicar o operador escolhido. Pode ser verificado que foi utilizado float8, e não algum outro tipo, escrevendo-se:

=> SELECT @ '-4.5e500' AS "abs";

ERRO:  "-4.5e500" está fora da faixa para o tipo double precision

Por outro lado, o operador de prefixo ~ (negação bit-a-bit) é definido apenas para tipos de dado inteiros, e não para float8. Portanto, se tentarmos algo semelhante usando ~, resulta em:

=> SELECT ~ '20' AS "negação";

ERRO:  operador não é único: ~ "unknown"
DICA:  Não foi possível escolher um operador candidato melhor.
       Pode ser necessário adicionar uma conversão de tipo explícita.

Isto acontece porque o sistema não pode decidir qual dos vários operadores ~ possíveis deve ser o preferido. Pode ser dada uma ajuda usando uma conversão explícita:

=> SELECT ~ CAST('20' AS int8) AS "negação";

 negação
---------
     -21
(1 linha)
SourceForge.net Logo CSS válido!