7.3. Funções

Os tipos dos argumentos das chamadas de função são resolvidos de acordo com as seguintes etapas.

Determinação do tipo em argumento de função

  1. Selecionar no catálogo do sistema pg_proc as funções a ser consideradas. Se um nome não qualificado de função for utilizado, as funções consideradas são aquelas com o mesmo nome e número de argumentos visíveis no caminho de procura corrente (veja a Seção 2.8.3). Se um nome qualificado de função for fornecido, somente as funções no esquema especificado são consideradas.

    1. Se no caminho de procura forem encontradas várias funções com argumentos do mesmo tipo, somente a que aparece primeiro no caminho é considerada. Mas as funções com argumentos de tipos diferentes são consideradas com a mesma precedência, não importando a posição no caminho de procura.

  2. Verificar se alguma função aceita os mesmos tipos de dado dos argumentos de entrada. Caso exista (só pode haver uma correspondência exata no conjunto de operadores examinados), esta é usada. Os casos envolvendo o tipo unknown nunca encontram correspondência nesta etapa.

  3. Se nenhuma correspondência exata for encontrada, verificar se a chamada de função é parecida com uma requisição trivial de transformação de tipo. Isto acontece se a chamada da função possui apenas um argumento, e o nome da função é o mesmo nome (interno) de algum tipo de dado. Além disso, o argumento da função deve ser um literal de tipo desconhecido ou um tipo binariamente compatível com o tipo de dado nomeado. Quando estas condições são encontradas, o argumento da função é transformado no tipo de dado nomeado sem chamada de função explícita.

  4. Procurar pela melhor correspondência.

    1. Rejeitar as funções candidatas para as quais os tipos da entrada não correspondem e não podem ser forçados (utilizando uma função implícita de conversão) a corresponder. Pressupõe-se que os literais do tipo unknown podem ser convertidos em qualquer outro tipo para esta finalidade. Se apenas uma função candidata permanecer, então esta é usada; senão continuar na próxima etapa.

    2. Examinar todas as funções candidatas, e manter aquelas com mais correspondências exatas com os tipos da entrada. Manter todas as candidatas se nenhuma possuir alguma correspondência exata. Se apenas uma função candidata permanecer, então esta é usada; senão continuar na próxima etapa.

    3. Examinar todas as funções candidatas, e manter aquelas com mais correspondências exatas ou correspondências compatíveis binariamente com os tipos da entrada. Manter todas as candidatas se nenhuma possuir correspondências exatas ou binariamente compatíveis. Se apenas uma função candidata permanecer, então esta é usada; senão continuar na próxima etapa.

    4. Examinar todas as funções candidatas, e manter aquelas que aceitam os tipos preferidos em mais posições onde a conversão de tipo será necessária. Manter todas as candidatas se nenhuma aceitar os tipos preferidos. Se apenas uma função candidata permanecer, então esta é usada; senão continuar na próxima etapa.

    5. Se algum dos argumentos de entrada for do tipo "unknown", verificar as categorias de tipo aceitas nesta posição do argumento pelas candidatas remanescentes. Em cada posição, selecionar a categoria string se qualquer uma das candidatas aceitar esta categoria (isto faz a cadeia de caracteres parecer apropriada porque todo literal de tipo desconhecido se parece com uma cadeia de caracteres). Senão, se todas as candidatas remanescentes aceitam a mesma categoria de tipo, selecionar esta categoria; senão falha porque a escolha correta não pode ser deduzida sem mais informações. Também observa se alguma das candidatas aceita um tipo de dado preferido dentro da categoria selecionada. Agora rejeita as funções candidatas que não aceitam a categoria de tipo selecionada; além disso, se alguma função candidata aceitar o tipo preferido em uma dada posição do argumento, rejeitar as candidatas que aceitam tipos não preferidos para este argumento.

    6. Se apenas uma função candidata permanecer, este é usada; Se nenhuma candidata, ou mais de uma candidata, permanecer, então falha.

Exemplos

Exemplo 7-4. Determinação do tipo em argumento de função de fatorial

Existe apenas uma função int4fac definida no catálogo pg_proc. Portanto, a consulta abaixo converte automaticamente o argumento do tipo int2 em int4:

tgl=> SELECT int4fac(int2 '4');
 int4fac
---------
      24
(1 row)

sendo na verdade transformada pelo analisador em

tgl=> SELECT int4fac(int4(int2 '4'));
 int4fac
---------
      24
(1 row)

Exemplo 7-5. Determinação do tipo em função de cadeia de caracteres

Existem duas funções substr declaradas em pg_proc. Entretanto, apenas uma recebe dois argumentos, dos tipos text e int4.

Se for chamada com uma constante cadeia de caracteres de um tipo não especificado, o tipo é convertido diretamente no tipo da única função candidata:

tgl=> SELECT substr('1234', 3);
 substr
--------
     34
(1 row)

Se a cadeia de caracteres for declarada como do tipo varchar, podendo ser o caso se for proveniente de uma tabela, então o analisador tentará torná-la text:

tgl=> SELECT substr(varchar '1234', 3);
 substr
--------
     34
(1 row)

que é transformada pelo analisador se tornando

tgl=> SELECT substr(text(varchar '1234'), 3);
 substr
--------
     34
(1 row)

Nota: Na verdade, o analisador está ciente que os tipos text e varchar são binariamente compatíveis, significando que uma pode ser passada para a função que aceita a outra sem realizar nenhuma conversão física. Portanto, nenhuma chamada para conversão explícita de tipo é na verdade inserida neste caso.

e, se a função for chamada com o tipo int4, o analisador tenta convertê-lo para o tipo text:

tgl=> SELECT substr(1234, 3);
 substr
--------
     34
(1 row)

o que na verdade executa como

tgl=> SELECT substr(text(1234), 3);
 substr
--------
     34
(1 row)

tendo sucesso porque existe a função de conversão text(int4) no catálogo do sistema.